aboutsummaryrefslogtreecommitdiff
path: root/ur_upgrade.py
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2014-08-05 19:48:41 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2014-08-05 19:48:41 -0400
commitee857ff7ba4ccd32694859bf15c0a99bf77dce30 (patch)
treeb45dd9a344a4166e8799dbfa62bd0b1a06ad61e3 /ur_upgrade.py
downloadur_upgrade-ee857ff7ba4ccd32694859bf15c0a99bf77dce30.tar.gz
Initial commit
Diffstat (limited to 'ur_upgrade.py')
-rwxr-xr-xur_upgrade.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/ur_upgrade.py b/ur_upgrade.py
new file mode 100755
index 0000000..eada7ea
--- /dev/null
+++ b/ur_upgrade.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+from __future__ import division
+import os
+import shutil
+import sys
+import stat
+import subprocess
+import tempfile
+import urllib2
+import signal
+import tarfile
+from collections import namedtuple
+
+def which(cmd, mode=os.F_OK | os.X_OK, path=None):
+ """Given a command, mode, and a PATH string, return the path which
+ conforms to the given mode on the PATH, or None if there is no such
+ file.
+
+ `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
+ of os.environ.get("PATH"), or can be overridden with a custom search
+ path.
+
+ """
+ # Check that a given file can be accessed with the correct mode.
+ # Additionally check that `file` is not a directory, as on Windows
+ # directories pass the os.access check.
+ def _access_check(fn, mode):
+ return (os.path.exists(fn) and os.access(fn, mode)
+ and not os.path.isdir(fn))
+
+ # If we're given a path with a directory part, look it up directly rather
+ # than referring to PATH directories. This includes checking relative to the
+ # current directory, e.g. ./script
+ if os.path.dirname(cmd):
+ if _access_check(cmd, mode):
+ return cmd
+ return None
+
+ if path is None:
+ path = os.environ.get("PATH", os.defpath)
+ if not path:
+ return None
+ path = path.split(os.pathsep)
+
+ if sys.platform == "win32":
+ # The current directory takes precedence on Windows.
+ if not os.curdir in path:
+ path.insert(0, os.curdir)
+
+ # PATHEXT is necessary to check on Windows.
+ pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
+ # See if the given file matches any of the expected path extensions.
+ # This will allow us to short circuit when given "python.exe".
+ # If it does match, only test that one, otherwise we have to try
+ # others.
+ if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
+ files = [cmd]
+ else:
+ files = [cmd + ext for ext in pathext]
+ else:
+ # On other platforms you don't have things like PATHEXT to tell you
+ # what file suffixes are executable, so just pass on cmd as-is.
+ files = [cmd]
+
+ seen = set()
+ for di in path:
+ normdir = os.path.normcase(di)
+ if not normdir in seen:
+ seen.add(normdir)
+ for thefile in files:
+ name = os.path.join(di, thefile)
+ if _access_check(name, mode):
+ return name
+ return None
+
+class Ureka(object):
+ def __init__(self, basepath):
+ self.path = basepath
+ self.path_data = os.path.abspath(os.path.join(self.path, 'misc'))
+ self._files = ['os', 'bits', 'version', 'name']
+ if os.path.exists(self.path_data):
+ self.info = self._info()
+ else:
+ self.info = {}
+
+
+ def _info(self):
+ data = []
+ for key in self._files:
+ path = os.path.join(self.path_data, key)
+ item = open(path, 'r').readline().strip()
+ data.append(item)
+
+
+ ureka_info = namedtuple('ureka_info', self._files)
+ return ureka_info._make(data)
+
+ def __getitem__(self, key):
+ info = self.info._asdict()
+ if key not in info:
+ return None
+ return info[key]
+
+ def __iter__(self):
+ for item in self.info._asdict().iteritems():
+ yield item
+
+UPGRADE_TEMP = tempfile.mkdtemp(prefix="upgrade")
+ORIGINAL = os.path.abspath('/home/jhunk/Ureka')
+
+def cleanup():
+ print('cleaning up')
+
+if __name__ == "__main__":
+
+
+ signal.signal(signal.SIGINT, cleanup)
+ #signal.signal(signal.SIGKILL, cleanup)
+ signal.signal(signal.SIGTERM, cleanup)
+
+ if not which('rsync'):
+ print('rsync not found in PATH. Please install it.')
+ exit(1)
+
+ u = Ureka(ORIGINAL)
+ INSTALL_PATH = os.path.join(UPGRADE_TEMP, '1.4.1')
+ UREKA_TARBALL = "Ureka_{}_{}_{}.tar.gz".format(u['os'], u['bits'], '1.4.1')
+ ''' http://ssb.stsci.edu/ureka/1.0/Ureka_linux-rhe5_64_1.4.1.tar.gz '''
+
+ #url = "http://ssb.stsci.edu/ureka/{}/Ureka_{}_{}_{}.tar.gz".format('1.4.1', u['os'], u['bits'], '1.4.1')
+ url = "http://localhost/ureka/{}/{}".format('1.4.1', UREKA_TARBALL)
+
+ print("Downloading update... {}".format(url))
+ req_data = urllib2.urlopen(url)
+ remote_size = float(req_data.headers['content-length'])
+ total = 0
+ with open(os.path.join(UPGRADE_TEMP, UREKA_TARBALL), 'wb') as installer:
+ for chunk in iter(lambda: req_data.read(16*1024), ''):
+ print("\r{:.2f}% [{:.2f}/{:.2f} MB]".format((total / remote_size * 100), (total / 1024 ** 2), (remote_size / 1024 ** 2))),
+ total += float(len(chunk))
+ installer.write(chunk)
+ print("")
+
+ os.mkdir(INSTALL_PATH)
+ tarball = tarfile.open(os.path.join(UPGRADE_TEMP, UREKA_TARBALL), 'r')
+ print("Preparing to unpack...")
+ files_total = 74690 #len(tarball.getmembers())
+ print("Unpacking update...")
+ for index, member in enumerate(tarball, start=0):
+ print("\r{:.2f}% [{}/{}]".format((index / files_total * 100), index, files_total)),
+ tarball.extract(member, path=INSTALL_PATH)
+ print("")
+
+ open(os.path.join(INSTALL_PATH, 'Ureka', 'misc', 'name'), 'w+').write(u['name'] + os.linesep)
+ n = Ureka(os.path.join(INSTALL_PATH, 'Ureka'))
+
+ print("Updating distribution from {} to {}...".format(u['version'], n['version']))
+ proc = subprocess.Popen('rsync -a -u {} {}'.format(n.path, os.path.dirname(u.path)).split())
+ proc.wait()
+
+ # Regenerate Ureka object
+ u = Ureka(ORIGINAL)
+
+ print("Normalizing...")
+ proc = subprocess.Popen('{}/bin/ur-setup-real -sh'.format(u.path).split())
+ proc = subprocess.Popen('ur_normalize'.split())
+
+
+
+ shutil.rmtree(UPGRADE_TEMP)
+