Exemplo n.º 1
0
    def _restore(self, filename):
        ipath = path.normpath(path.join(self.installpath, filename))
        bpath = path.normpath(path.join(self.backuppath, filename))

        idir = path.dirname(ipath)
        if not path.isdir(idir):
            os.makedirs(idir)

        try:
            if path.isfile(ipath):
                log.debug("Removing file {0} before restoring old version".format(filename))
                os.remove(ipath)

            log.debug("Restoring file {0} by moving from backup directory".format(filename))
            shutil.move(bpath, ipath)

        except:
            log.debug("Restore failed for {0}".format(filename))
Exemplo n.º 2
0
    def _backup(self, filename, move=True):
        ipath = path.normpath(path.join(self.installpath, filename))
        bpath = path.normpath(path.join(self.backuppath, filename))

        if not path.isfile(ipath):
            return

        bdir = path.dirname(bpath)
        if not path.isdir(bdir):
            os.makedirs(bdir)

        try:
            if move:
                log.debug("Backing up file {0} by moving to backup directory".format(filename))
                shutil.move(ipath, bpath)
            else:
                log.debug("Backing up file {0} by copying to backup directory".format(filename))
                shutil.copy(ipath, bpath)

        except:
            log.debug("Backup failed for {0}".format(filename))
Exemplo n.º 3
0
    def apply(self, installpath, backuppath=None):
        """
        Apply the manifest against the given installation path.
        """

        self.installpath = installpath
        manifest = self.manifest

        # fetch and verify package
        if "package-uri" in manifest:
            packageuri = URI(manifest["package-uri"])
            packagename = path.basename(packageuri["path"])
            packagepath = path.join(tempfile.gettempdir(), packagename)

            packageformat = None
            if "package-format" in manifest:
                packageformat = manifest["package-format"]

            # download package file
            log.info("Fetching update package from {0}".format(packageuri.uri))
            packageuri.fetch(packagepath)
            packageuri.close()

            # integrity check
            if "package-sha1" in manifest:
                packagesha1 = sha1(packagepath)
                if not packagesha1 == manifest["package-sha1"]:
                    raise Exception("Package integrity check failed")

            self.package = Package(packagepath, packageformat)

        # create spot for backup files
        if backuppath is None:
            self.backuppath = tempfile.mkdtemp(prefix="update_")
        else:
            self.backuppath = backuppath

        if not path.isdir(self.backuppath):
            log.debug("Backup path {0} does not exist; creating".format(self.backuppath))
            os.mkdir(self.backuppath)

        # start applying actions
        try:
            for info in manifest.actions:
                self._action(info)

        # handle update errors by rolling back
        except Exception as err:
            log.exception("Exception eaten; beginning rollback")

            for root, dirs, files in os.walk(self.backuppath):
                relpath = path.relpath(root, self.backuppath)

                if relpath == ".":
                    relpath = ""

                for filename in files:
                    filepath = path.join(relpath, filename)

                    log.info("Rolling back file %s" % (filepath))

                    self._restore(filepath)

            log.info("Rollback completed; raising exception")
            raise

        # clean up
        finally:
            self.cleanup = False
            shutil.rmtree(self.backuppath, onerror=self._onerror)

            self.package.close()
            os.remove(packagepath)

            if self.cleanup:
                return self.backuppath
Exemplo n.º 4
0
    def fetch(self, target=None):
        parse = self.parse

        # local file
        if parse.scheme == "file":
            self.handle = File(parse.path, "r", format=self.format)

            if target:
                self.handle.decompress(target)
                self.handle.close()
                self.handle = File(target, "r")

        # package file
        elif parse.scheme == "package":
            if self.package is None:
                raise Exception("No package specified")

            filename = parse.path.lstrip("/")
            self.handle = self.package.open(filename, "r", format=self.format)

            if target:
                self.handle.decompress(target)
                self.handle.close()
                self.handle = File(target, "r")

        # remote http resource
        elif parse.scheme in ("http", "https"):
            failure = True
            tries = 0

            while failure:
                failure = False

                try:
                    if target:
                        target = path.normpath(target)
                        log.info("Downloading {0} to file {1}".format(self.uri, target))
                        downloadpath, headers = urllib.urlretrieve(self.uri)
                        self.handle = File(downloadpath, "r", format=self.format)
                        self.handle.decompress(target)
                        self.handle.close()
                        self.handle = File(target, "r")
                    else:
                        self.handle = urllib2.urlopen(self.uri)

                except:
                    failure = True
                    if tries < 3:
                        log.info("Problem retrieving URI, retry in 3 seconds...")
                        log.debug(traceback.format_exception(sys.exc_type,
                                                             sys.exc_value,
                                                             sys.exc_traceback))
                        time.sleep(3)

                    else:
                        log.info("Failed retrieving URI")
                        raise

                finally:
                    tries += 1

            return self.handle

        else:
            raise Exception("Unsupported URI scheme {0}".format(parse.scheme))

        return self.handle