summaryrefslogtreecommitdiff
path: root/src/mongo/installer/compass/install_compass.in
blob: a7b14089c4b623c6531088035d513f690dc75600 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env python2

# This script downloads the latest version of Compass and installs it on
# non-windows platforms.

import json
import os
import os.path as path
import shutil
import subprocess
import sys
import tempfile
import platform
import time
import urllib


def get_pkg_format():
    """Determine the package manager for this Linux distro."""
    with open(os.devnull, 'w') as fnull:
        try:
            subprocess.call(['apt-get', '--help'], stdout=fnull, stderr=fnull)
            return 'apt'
        except:
            pass

        try:
            subprocess.call(['dnf', '--help'], stdout=fnull, stderr=fnull)
            return 'dnf'
        except:
            pass

        try:
            subprocess.call(['yum', '--help'], stdout=fnull, stderr=fnull)
            return 'yum'
        except:
            pass

    return ''


def download_progress(count, block_size, total_size):
    """Log the download progress."""
    percent = int(count * block_size * 100 / total_size)
    sys.stdout.write("\rDownloading Compass... %d%%" % percent)
    sys.stdout.flush()


def download_pkg(link, pkg_format=''):
    """Download the package from link, logging progress. Returns the filename."""
    suf = ''
    if pkg_format == 'apt':
        suf = '.deb'
    elif pkg_format == 'yum' or pkg_format == 'dnf':
        suf = '.rpm'

    tmpf = tempfile.mkstemp(suffix=suf)
    res = urllib.urlretrieve(link, filename=tmpf[1], reporthook=download_progress)
    # Download progress doesn't end with a newline so add it here.
    print ''
    return res[0]


def install_mac(dmg):
    """Use CLI tools to mount the dmg and extract all .apps into Applications."""
    tmp = tempfile.mkdtemp()
    subprocess.check_call(['hdiutil', 'attach', '-mountpoint', tmp, dmg])
    try:
        apps = [f for f in os.listdir(tmp) if f.endswith('.app')]
        for app in apps:
            if path.isdir('/Applications/' + app):
                print 'Old version found removing...'
                shutil.rmtree('/Applications/' + app)
            print 'Copying %s to /Applications' % app
            shutil.copytree(path.join(tmp, app), '/Applications/' + app)
    # We don't really care about what errors come up here. Just log the failure
    # and use the finally to make sure we always unmount the dmg.
    except Exception as exception:
        print exception
    finally:
        subprocess.check_call(['hdiutil', 'detach', tmp])


def install_linux(pkg_format, pkg_file):
    """Use the package manager indicated by pkg_format to install pkg_file."""
    if pkg_format == 'yum':
        install = ['yum', 'localinstall', '--assumeyes', pkg_file]
    elif pkg_format == 'apt':
        # dpkg returns an error code when it fails to install dependencies
        # so just run it and let apt-get tell us if something went wrong
        subprocess.call(['dpkg', '--install', pkg_file])
        install = ['apt-get', 'install', '-f', '--yes']
    elif pkg_format == 'dnf':
        install = ['dnf', 'install', '--assumeyes', pkg_file]
    else:
        print 'No available installation methods.'
        sys.exit(1)

    subprocess.check_call(install)


def is_supported_distro():
    distro_name, version_number, extra = platform.linux_distribution()

    if (distro_name == 'Ubuntu' and
        (version_number == '14.04' or
         version_number == '16.04')):
        return True

    if (distro_name == 'Red Hat Enterprise Linux Server' and
        (float(version_number) >= 7.0)):
        return True

    return False


def download_and_install_compass():
    """Download and install compass for this platform."""
    os_type = sys.platform
    pkg_format = get_pkg_format()

    # Sometimes sys.platform gives us 'linux2' and we only want 'linux'
    if os_type.startswith('linux'):
        os_type = 'linux'
        if pkg_format == 'apt':
            os_type += '_deb'
        elif pkg_format == 'yum' or pkg_format == 'dnf':
            os_type += '_rpm'
    elif os_type == 'darwin':
        os_type = 'osx'

    if os_type.startswith('linux') and os.getuid() != 0:
        print 'You must run this script as root.'
        sys.exit(1)

    if os_type.startswith('linux') and not is_supported_distro():
        print 'You are using an unsupported Linux distribution.\n' \
        'Please visit: https://compass.mongodb.com/community-supported-os_types' \
        ' to view available community supported packages.'
        sys.exit(1)

    if platform.machine() != 'x86_64':
        print 'Sorry, MongoDB Compass is only supported on 64 bit platforms.' \
        ' If you believe you\'re seeing this message in error please open a' \
        ' ticket on the SERVER project at https://jira.mongodb.org/'

    link = 'https://compass.mongodb.com/api/v2/download/latest/@compass_type@/stable/' + os_type
    pkg = download_pkg(link, pkg_format=pkg_format)

    print 'Installing the package...'
    if os_type == 'osx':
        install_mac(pkg)
    elif os_type.startswith('linux'):
        install_linux(pkg_format, pkg)
    else:
        print 'Unrecognized os_type: %s' % os_type

    print 'Cleaning up...'
    os.remove(pkg)
    print 'Done!'


if __name__ == '__main__':
    download_and_install_compass()