2013-01-21 17:55:25 +01:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import tempfile
|
|
|
|
import urllib2
|
|
|
|
import subprocess
|
|
|
|
import tarfile
|
|
|
|
import shutil
|
|
|
|
import errno
|
2013-03-05 16:39:10 +01:00
|
|
|
# To ensure it exists on the system
|
|
|
|
import gzip
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# Useful script for installing multiple versions of MongoDB on a machine
|
|
|
|
# Only really tested/works on Linux.
|
|
|
|
#
|
|
|
|
|
|
|
|
class MultiVersionDownloader :
|
|
|
|
|
|
|
|
def __init__(self, install_dir, link_dir, platform):
|
|
|
|
self.install_dir = install_dir
|
|
|
|
self.link_dir = link_dir
|
|
|
|
match = re.compile("(.*)\/(.*)").match(platform)
|
|
|
|
self.platform = match.group(1)
|
|
|
|
self.arch = match.group(2)
|
2013-03-05 16:39:10 +01:00
|
|
|
self.links = self.download_links()
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
def download_links(self):
|
|
|
|
href = "http://dl.mongodb.org/dl/%s/%s" \
|
|
|
|
% (self.platform.lower(), self.arch)
|
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
html = urllib2.urlopen(href).read()
|
2013-01-21 17:55:25 +01:00
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
links = {}
|
2013-01-21 17:55:25 +01:00
|
|
|
for line in html.split():
|
2013-03-05 16:39:10 +01:00
|
|
|
match = re.compile("http:\/\/downloads\.mongodb\.org\/%s/mongodb-%s-%s-([^\"]*)\.tgz" \
|
|
|
|
% (self.platform.lower(), self.platform.lower(), self.arch)).search(line)
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
if match == None: continue
|
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
link = match.group(0)
|
|
|
|
version = match.group(1)
|
|
|
|
links[version] = link
|
2013-01-21 17:55:25 +01:00
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
return links
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
def download_version(self, version):
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
try:
|
|
|
|
os.makedirs(self.install_dir)
|
|
|
|
except OSError as exc:
|
|
|
|
if exc.errno == errno.EEXIST and os.path.isdir(self.install_dir):
|
|
|
|
pass
|
|
|
|
else: raise
|
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
urls = []
|
|
|
|
for link_version, link_url in self.links.iteritems():
|
|
|
|
if link_version.startswith(version):
|
2013-01-21 17:55:25 +01:00
|
|
|
# If we have a "-" in our version, exact match only
|
|
|
|
if version.find("-") >= 0:
|
|
|
|
if link_version != version: continue
|
|
|
|
elif link_version.find("-") >= 0:
|
|
|
|
continue
|
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
urls.append((link_version, link_url))
|
|
|
|
|
|
|
|
if len(urls) == 0:
|
|
|
|
raise Exception("Cannot find a link for version %s, versions %s found." \
|
|
|
|
% (version, self.links))
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
urls.sort()
|
|
|
|
full_version = urls[-1][0]
|
2013-03-05 16:39:10 +01:00
|
|
|
url = urls[-1][1]
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
temp_dir = tempfile.mkdtemp()
|
2013-03-05 16:39:10 +01:00
|
|
|
temp_file = tempfile.mktemp(suffix=".tgz")
|
|
|
|
|
|
|
|
data = urllib2.urlopen(url)
|
|
|
|
|
|
|
|
print "Downloading data for version %s (%s)..." % (version, full_version)
|
|
|
|
|
|
|
|
with open(temp_file, 'wb') as f:
|
|
|
|
f.write(data.read())
|
|
|
|
print "Uncompressing data for version %s (%s)..." % (version, full_version)
|
|
|
|
|
|
|
|
# Can't use cool with syntax b/c of python 2.6
|
|
|
|
tf = tarfile.open(temp_file, 'r:gz')
|
|
|
|
|
|
|
|
try:
|
|
|
|
tf.extractall(path=temp_dir)
|
|
|
|
except:
|
|
|
|
tf.close()
|
|
|
|
raise
|
|
|
|
|
|
|
|
tf.close()
|
|
|
|
|
|
|
|
extract_dir = os.listdir(temp_dir)[0]
|
|
|
|
temp_install_dir = os.path.join(temp_dir, extract_dir)
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
shutil.move(temp_install_dir, self.install_dir)
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
shutil.rmtree(temp_dir)
|
|
|
|
os.remove(temp_file)
|
|
|
|
|
2013-03-05 16:39:10 +01:00
|
|
|
self.symlink_version(version, os.path.abspath(os.path.join(self.install_dir, extract_dir)))
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
def symlink_version(self, version, installed_dir):
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.makedirs(self.link_dir)
|
|
|
|
except OSError as exc:
|
|
|
|
if exc.errno == errno.EEXIST and os.path.isdir(self.link_dir):
|
|
|
|
pass
|
|
|
|
else: raise
|
2013-03-05 16:39:10 +01:00
|
|
|
|
|
|
|
for executable in os.listdir(os.path.join(installed_dir, "bin")):
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
link_name = "%s-%s" % (executable, version)
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
os.symlink(os.path.join(installed_dir, "bin", executable),\
|
|
|
|
os.path.join(self.link_dir, link_name))
|
|
|
|
|
|
|
|
|
|
|
|
CL_HELP_MESSAGE = \
|
|
|
|
"""
|
|
|
|
Downloads and installs particular mongodb versions into an install directory and symlinks the binaries with versions to
|
|
|
|
another directory.
|
|
|
|
|
|
|
|
Usage: install_multiversion_mongodb.sh INSTALL_DIR LINK_DIR PLATFORM_AND_ARCH VERSION1 [VERSION2 VERSION3 ...]
|
|
|
|
|
|
|
|
Ex: install_multiversion_mongodb.sh ./install ./link "Linux/x86_64" "2.0.6" "2.0.3-rc0" "2.0" "2.2" "2.3"
|
|
|
|
|
|
|
|
If "rc" is included in the version name, we'll use the exact rc, otherwise we'll pull the highest non-rc
|
|
|
|
version compatible with the version specified.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def parse_cl_args(args):
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
def raise_exception(msg):
|
|
|
|
print CL_HELP_MESSAGE
|
|
|
|
raise Exception(msg)
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
if len(args) == 0: raise_exception("Missing INSTALL_DIR")
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
install_dir = args[0]
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
args = args[1:]
|
|
|
|
if len(args) == 0: raise_exception("Missing LINK_DIR")
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
link_dir = args[0]
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
args = args[1:]
|
|
|
|
if len(args) == 0: raise_exception("Missing PLATFORM_AND_ARCH")
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
platform = args[0]
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
args = args[1:]
|
|
|
|
if re.compile(".*\/.*").match(platform) == None:
|
|
|
|
raise_exception("PLATFORM_AND_ARCH isn't of the correct format")
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
if len(args) == 0: raise_exception("Missing VERSION1")
|
|
|
|
|
|
|
|
versions = args
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
return (MultiVersionDownloader(install_dir, link_dir, platform), versions)
|
|
|
|
|
|
|
|
def main():
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
downloader, versions = parse_cl_args(sys.argv[1:])
|
2013-03-05 16:39:10 +01:00
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
for version in versions:
|
|
|
|
downloader.download_version(version)
|
2013-03-05 16:39:10 +01:00
|
|
|
|
|
|
|
|
2013-01-21 17:55:25 +01:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|
2013-03-05 16:39:10 +01:00
|
|
|
|