Ejemplo n.º 1
0
    def removeVersion(self, version_):
        """ Removes a version (Must have state != 'active') """
        if not version_ in self.versions:
            self._log("remove-version").error(
                "removeVersion() called, version %s unknown", version_)
            raise InstallException(
                "Internal error detected in removeVersion()")

        curState = self.versions[version_][self.kTokenState]
        if curState == self.kStateActive:
            self._log("remove-version").error(
                "removeVersion() called, version %s is active", version_)
            raise InstallException(
                "Internal error detected in removeVersion()")

        #TODO(orens): think about failing here instead of warning
        subPkgsToRemove = self.getSubPkgsToRemoveOnRemoval(version_)
        if len(subPkgsToRemove) > 0:
            self._log("remove-version").warning(
                "removeVersion() called, version %s has sub-pkgs to remove: %s",
                version_, subPkgsToRemove)
        rpmsToRemove = self.getRpmsToRemoveOnRemoval(version_)
        if len(rpmsToRemove) > 0:
            self._log("remove-version").warning(
                "removeVersion() called, version %s has RPMs to remove: %s",
                version_, rpmsToRemove)
        del self.versions[version_]
        self._log("remove-version").info(
            "removeVersion() called, version %s removed", version_)
        self.save()
Ejemplo n.º 2
0
 def getPilotName(self, version_):
     """ Gets pilot name. If none, returns None """
     if not version_ in self.versions:
         self._log("get-pilot-name").error(
             "getPilotName() called, version %s unknown", version_)
         raise InstallException("Internal error detected in getPilotName()")
     return self.versions[version_].get(self.kTokenPilotName)
Ejemplo n.º 3
0
    def addVersion(self,
                   version_,
                   subPkgs=None,
                   subPkgsToRemove=None,
                   rpmsToRemove=None):
        """Adds a version with state 'on-disk' """
        curState = self.getVersionState(version_)
        if (curState == self.kStateActive) or (curState == self.kStateReady):
            self._log("add-version").error(
                "addVersion() called, version %s already known, in state %s",
                version_, curState)
            raise InstallException("Internal error detected in addVersion()")

        self.versions[version_] = {self.kTokenState: self.kStateOnDisk}
        if subPkgs != None:
            self.versions[version_][self.kTokenSubPkgs] = subPkgs
        if subPkgsToRemove != None:
            self.versions[version_][
                self.kTokenSubPkgsToRemove] = subPkgsToRemove
        if rpmsToRemove != None:
            self.versions[version_][self.kTokenRpmsToRemove] = rpmsToRemove

        self._log("add-version").info(
            "addVersion() called, version %s added (subPkgs=%s, sptr=%s, rtr=%s)",
            version_, subPkgs, subPkgsToRemove, rpmsToRemove)
        self.save()
Ejemplo n.º 4
0
 def getLeaders(self, version_):
     """ Gets leaders. """
     if not version_ in self.versions:
         self._log("get-leaders").error(
             "getLeaders() called, version %s unknown", version_)
         raise InstallException("Internal error detected in getLeaders()")
     return self.versions[version_].get(self.kTokenLeaders)
Ejemplo n.º 5
0
 def getSubPkgs(self, version_):
     """ Gets subpkgs related to this version """
     if not version_ in self.versions:
         self._log("get-subpkgs").error(
             "getSubPkgs() called, version %s unknown", version_)
         raise InstallException("Internal error detected in getSubPkgs()")
     return self.versions[version_].get(self.kTokenSubPkgs, [])
Ejemplo n.º 6
0
 def getActiveVersion(self):
     """Returns the currently active version"""
     for version_ in self.versions:
         if self.versions[version_][self.kTokenState] == self.kStateActive:
             return version_
     self._log("get-active-version").error(
         "getActiveVersion() called, no active version found")
     raise InstallException("Internal error detected in getActiveVersion()")
Ejemplo n.º 7
0
 def getRpmsToRemoveOnRemoval(self, version_):
     """ Gets RPMs to remove. If none, returns an empty list """
     if not version_ in self.versions:
         self._log("get-rpms-to-remove").error(
             "getRpmsToRemoveOnRemoval() called, version %s unknown",
             version_)
         raise InstallException(
             "Internal error detected in getRpmsToRemoveOnRemoval()")
     return self.versions[version_].get(self.kTokenRpmsToRemove, [])
Ejemplo n.º 8
0
 def getPilotData(self, version_):
     """ Gets pilot data. If none, returns None """
     if not version_ in self.versions:
         self._log("get-pilot-data").error(
             "getPilotData() called, version %s unknown", version_)
         raise InstallException("Internal error detected in getPilotData()")
     data = self.versions[version_].get(self.kTokenPilotData)
     self._log("get-pilot-data").info(
         "getPilotData(version=%s) returning '%s'", version_, data)
     return data
Ejemplo n.º 9
0
 def getSwitchType(self, version_):
     """ Gets switch type. If none, returns None """
     if not version_ in self.versions:
         self._log("get-switch-type").error(
             "getSwitchType() called, version %s unknown", version_)
         raise InstallException(
             "Internal error detected in getSwitchType()")
     switchType = self.versions[version_].get(self.kTokenSwitchType)
     self._log("get-switch-type").info(
         "getSwitchType(version=%s) returning '%s'", version_, switchType)
     return switchType
Ejemplo n.º 10
0
 def getInstallDirection(self, version_):
     """ Gets install direction. If none, returns None """
     if not version_ in self.versions:
         self._log("get-install-direction").error(
             "getInstallDirection() called, version %s unknown", version_)
         raise InstallException(
             "Internal error detected in getInstallDirection()")
     installDirection = self.versions[version_].get(
         self.kTokenInstallDirection)
     self._log("get-install-direction").info(
         "getInstallDirection(version=%s) returning '%s'", version_,
         installDirection)
     return installDirection
Ejemplo n.º 11
0
 def setPilotData(self, version_, pilotData):
     """ Sets pilot data for a given version. If pilotData==None, removes the pilot data """
     if not version_ in self.versions:
         self._log("set-pilot-data").error(
             "setPilotData() called, version %s unknown", version_)
         raise InstallException("Internal error detected in setPilotData()")
     self.versions[version_][self.kTokenPilotData] = pilotData
     if pilotData is None:
         del self.versions[version_][self.kTokenPilotData]
     self._log("set-pilot-data").info(
         "setPilotData(version=%s) called, pilotData set to='%s'", version_,
         pilotData)
     self.save()
Ejemplo n.º 12
0
 def setPilotName(self, version_, pilotName):
     """ Sets pilot name for a given version. If pilotName==None, removes the pilot name"""
     if not version_ in self.versions:
         self._log("set-pilot-name").error(
             "setPilotName() called, version %s unknown", version_)
         raise InstallException("Internal error detected in setPilotName()")
     self.versions[version_][self.kTokenPilotName] = pilotName
     if pilotName is None:
         del self.versions[version_][self.kTokenPilotName]
     self._log("set-pilot-name").info(
         "setPilotName() called, version %s has pilotName=%s", version_,
         pilotName)
     self.save()
Ejemplo n.º 13
0
 def setActiveVersion(self, version_):
     """Changes ready->active and active->on-disk"""
     self._log("set-active-version").info(
         "setActiveVersion(version_=%s) called", version_)
     if version_ not in self.versions:
         self._log("set-active-version").error(
             "setActiveVersion() called, version %s not found", version_)
         raise InstallException(
             "Internal error detected in setActiveVersion()")
     if self.versions[version_][self.kTokenState] != self.kStateReady:
         self._log("set-active-version").error(
             "setActiveVersion() called, version %s not ready, it is %s",
             version_, self.versions[version_][self.kTokenState])
         raise InstallException(
             "Internal error detected in setActiveVersion()")
     curActive = self.getActiveVersion()
     self.versions[version_][self.kTokenState] = self.kStateActive
     self.versions[curActive][self.kTokenState] = self.kStateOnDisk
     self._log("set-active-version").info(
         "setActiveVersion() called, version %s is now active, prev one was %s",
         version_, curActive)
     self.save()
Ejemplo n.º 14
0
 def setSwitchType(self, version_, switchType):
     """ Sets switch type for a given version. If switchType==None, removes the information """
     if not version_ in self.versions:
         self._log("set-switch-type").error(
             "setSwitchType() called, version %s unknown", version_)
         raise InstallException(
             "Internal error detected in setSwitchType()")
     self.versions[version_][self.kTokenSwitchType] = switchType
     if switchType is None:
         del self.versions[version_][self.kTokenSwitchType]
     self._log("set-switch-type").info(
         "setSwitchType(version=%s) called, switchType set to='%s'",
         version_, switchType)
     self.save()
Ejemplo n.º 15
0
 def setInstallDirection(self, version_, installDirection):
     """ Sets install direction for a given version (upgrade or downgrade). If installDirection==None, removes the information """
     if not version_ in self.versions:
         self._log("set-install-direction").error(
             "setInstallDirection() called, version %s unknown", version_)
         raise InstallException(
             "Internal error detected in setInstallDirection()")
     self.versions[version_][self.kTokenInstallDirection] = installDirection
     if installDirection is None:
         del self.versions[version_][self.kTokenInstallDirection]
     self._log("set-install-direction").info(
         "setInstallDirection(version=%s) called, installDirection set to='%s'",
         version_, installDirection)
     self.save()
Ejemplo n.º 16
0
 def setLeaders(self, version_, leaders):
     """ 
     Sets leaders for a given version. 
     leaders is a dict with 'prepare' and 'switch' entries, mapping them to a full package name of the leader
     """
     if not version_ in self.versions:
         self._log("set-leaders").error(
             "setLeaders() called, version %s unknown", version_)
         raise InstallException("Internal error detected in setLeaders()")
     self.versions[version_][self.kTokenLeaders] = leaders
     self._log("set-leaders").info(
         "setLeaders() called, version %s has leaders=%s", version_,
         leaders)
     self.save()
Ejemplo n.º 17
0
    def setReadyVersion(self, version_):
        """Changes on-disk->ready"""
        self._log("set-active-version").info(
            "setReadyVersion(version_=%s) called", version_)
        if version_ not in self.versions:
            self._log("set-ready-version").error(
                "setReadyVersion() called, version %s not found", version_)
            raise InstallException(
                "Internal error detected in setReadyVersion()")

        curReady = self.getReadyVersion()
        if curReady == version_:
            self._log("set-ready-version").info(
                "setReadyVersion(%s) called, version is already ready, nothing to do ",
                version_)
            return

        if curReady != None:
            self._log("set-ready-version").error(
                "setReadyVersion(%s) called, found a different ready version %s",
                version_, curReady)
            raise InstallException(
                "Internal error detected in setReadyVersion()")

        curState = self.versions[version_][self.kTokenState]
        if curState != self.kStateOnDisk:
            self._log("set-ready-version").error(
                "setReadyVersion() called, version %s not on disk, it is '%s'",
                version_, curState)
            raise InstallException(
                "Internal error detected in setReadyVersion()")

        self.versions[version_][self.kTokenState] = self.kStateReady
        self._log("set-active-version").info(
            "setReadyVersion() called, version %s is now ready", version_)
        self.save()
Ejemplo n.º 18
0
 def setRpmsToRemoveOnRemoval(self, version_, rpmsToRemove):
     """ Sets RPMs to remove for a given version. Prev RPMs to remove are forgotten """
     if not version_ in self.versions:
         self._log("set-rpms-to-remove").error(
             "setRpmsToRemoveOnRemoval() called, version %s unknown",
             version_)
         raise InstallException(
             "Internal error detected in setRpmsToRemoveOnRemoval()")
     self.versions[version_][self.kTokenRpmsToRemove] = rpmsToRemove
     if (rpmsToRemove is None) or (len(rpmsToRemove) == 0):
         del self.versions[version_][self.kTokenRpmsToRemove]
     self._log("set-rpms-to-remove").info(
         "setRpmsToRemoveOnRemoval() called, version %s has rpmsToRemove=%s",
         version_, rpmsToRemove)
     self.save()
Ejemplo n.º 19
0
 def addSubPkgs(self, version_, subPkgsToAdd):
     """ Adds subpkgs to a version """
     if not version_ in self.versions:
         self._log("add-subpkgs").error(
             "addSubPkgs() called, version %s unknown", version_)
         raise InstallException("Internal error detected in addSubPkgs()")
     # Version must have some sub packages already
     subPkgs = self.versions[version_][self.kTokenSubPkgs]
     for sb in subPkgsToAdd:
         if not sb in subPkgs:
             subPkgs.append(sb)
     self._log("add-subpkgs").info(
         "addSubPkgs(version=%s) called, sub-pkgs now are set to='%s'",
         version_, subPkgs)
     self.save()
Ejemplo n.º 20
0
    def setVersionStateOnDisk(self, version_):
        """Changes version state to on-disk"""
        if version_ not in self.versions:
            self._log("set-version-state-ondisk").error(
                "setVersionStateOnDisk() called, version %s not found",
                version_)
            raise InstallException(
                "Internal error detected in setVersionStateOnDisk()")

        curState = self.versions[version_][self.kTokenState]
        self._log("set-version-state-ondisk").info(
            "setVersionStateOnDisk() called, version %s current state is '%s'",
            version_, curState)
        if curState == self.kStateOnDisk:
            return

        self.versions[version_][self.kTokenState] = self.kStateOnDisk
        self._log("set-version-state-ondisk").info(
            "setVersionStateOnDisk() called, version %s is now on-disk",
            version_)
        self.save()
Ejemplo n.º 21
0
    def raiseException(self, msg):
        """Raises an exception to abort current pilot operation with an error"""

        self._log("raise-exception").info("raiseException() called,  msg = %s",
                                          msg)
        raise InstallException(msg)
Ejemplo n.º 22
0
    def _doPrepare(self):
        self._log("prepare").info("prepare() called")
        # Do not allow running this command after 'switch'
        self.raiseIfPendingRestart()

        fileArg = self._options.file
        if fileArg == None:
            self._log("missing-file").error("file option is missing")
            a.infra.process.processFatal("Missing file option")

        self._log("prepare").info("prepare got file: '%s'", fileArg)
        fileNormalized = self._normalizeFile(
            fileArg, normalize=not self._options.keepFileName)
        self._log("prepare").info("prepare normalized file: '%s'",
                                  fileNormalized)

        if not os.path.exists(fileNormalized):
            self._log("prepare").info("prepare: file '%s' does not exist",
                                      fileNormalized)
            printError("File does not exist")
            return 1

        print("This may take some time, please wait")

        readyVersionAndBuild = self._installManager.getReadyVersion()
        self._log("prepare").info("Ready version+build is '%s'",
                                  readyVersionAndBuild)
        if readyVersionAndBuild != None:
            self._log("prepare").info("Canceling ready")
            self._installManager.cancel(readyVersionAndBuild[0],
                                        readyVersionAndBuild[1])
            self._log("prepare").info("Calling removeVersionAndSubPkgs()")
            self._installManager.removeVersionAndSubPkgs(
                readyVersionAndBuild[0], readyVersionAndBuild[1])

        self._log("prepare").info("Calling removeUnneededVersionsFromDisk()")
        self._installManager.removeUnneededVersionsFromDisk()

        if self._installSameVersion:
            # Patch: If --install-same-version is specified, we do the following things to allow it:
            # 1. Check that indeed prepared version is the same as the active version
            # 2. Rename the current version from 'v-b' to 'v-99999999'. This is done by changing the state file.
            # 3. Create a fake pilot for the fake build (ln -s pilot-qb-2.6.0.0-21037 /opt/qb/rpms/pilot-qb-2.6.0.0-99999)

            # Make sure that indeed we are installing the same version
            (newVersion,
             newBuild) = self._installManager.isPackageValid(fileNormalized)
            (activeVersion,
             activeBuild) = self._installManager.getActiveVersionAndBuild()

            if (newVersion != activeVersion) or (newBuild != activeBuild):
                msg="prepare(): --install-same-version used, but current version = %s-%s != package file version = %s-%s" \
                    % (activeVersion, activeBuild, newVersion, newBuild)
                self._log("prepare").error(msg)
                raise InstallException(msg)

            # Change name of active version
            fakeVersionAndBuild = self._installManager.combineVersion(
                activeVersion, a.sys.install.install_manager.kFakeBuildNumber)
            self._log("prepare").info("Changing active version name to %s",
                                      fakeVersionAndBuild)
            self._installManager.getStateManager(
            ).patchChangeNameOfActiveVersion(fakeVersionAndBuild)

            # Create fake pilot for fake build
            newVersionAndBuild = self._installManager.combineVersion(
                activeVersion, activeBuild)
            existingPilotName = self._installManager.calcPilotName(
                newVersionAndBuild)
            fakePilotName = self._installManager.calcPilotName(
                fakeVersionAndBuild)
            fakePilotDirName = os.path.join(self._rpmsDir, fakePilotName)
            self._log("prepare").info("Creating symlink  %s -> %s",
                                      fakePilotDirName, existingPilotName)
            if os.path.lexists(fakePilotDirName):
                os.remove(fakePilotDirName)
            os.symlink(existingPilotName, fakePilotDirName)

        self._log("prepare").info("Calling addSubPkgs(%s)", fileNormalized)
        (version_, build) = self._installManager.addSubPkgs(fileNormalized)

        self._log("prepare").info("setting pilot hints to '%s'",
                                  self._pilotHints)
        self._installManager.setPilotHints(self._pilotHints)

        self._log("prepare").info(
            "Calling prepare(%s, %s, usePilotVersion=%s)", version_, build,
            self._options.usePilotVersion)
        try:
            self._installManager.prepare(
                version_, build, usePilotVersion=self._options.usePilotVersion)
        except:
            exc = sys.exc_info()
            self._log("prepare").error(
                "prepare() caused exception: %s, %s, tb=%s", exc[0], exc[1],
                traceback.format_tb(exc[2]))
            if os.path.exists(self._debugFlagFileDontCleanOnError):
                self._log("prepare").info(
                    "prepare() failed, %s exists, not removing sub-packages",
                    self._debugFlagFileDontCleanOnError)
                removeSubPackages = False
            else:
                removeSubPackages = True
            self._log("prepare").info(
                "prepare() failed, calling removeVersionAndSubPkgs(%s, %s)",
                version_, build)
            self._installManager.removeVersionAndSubPkgs(
                version_, build, removeSubPackages=removeSubPackages)
            self._log("prepare").info("removeVersionAndSubPkgs() done")
            raise
        self._log("prepare").info("prepare() done")
        return 0
Ejemplo n.º 23
0
 def raiseIfPendingRestart(self):
     if self._installManager.isPendingRestart():
         raise InstallException(
             "'switch' command was executed, further install commands cannot be executed until system restarts"
         )
Ejemplo n.º 24
0
    def add(self, r2pmFile=None, httpRepo=None, packageName=None):
        """
        Adds sub-packages, either from a r2pm file or from an http repo.
        To install from file:
        r2pmFile : file name

        To install from an http repo:
        httpRepo : repo address
        packageName : Name of package containing the sub-packages

        Returns a tuple (subPkgs, subPkgstoRemove).
        subPkgs: list of sub-pkgs included in this version. 
        subPkgstoRemove: list of new sub-pkgs (Replaced sub-pkgs are not included in that list). These sub-pkgs
        will be removed if 'prepare' operation is canceled
        """

        self._log("add-called").info(
            "add() called, r2pmFile=%s, httpRepo=%s, packageName=%s", r2pmFile,
            httpRepo, packageName)

        # Check that our input makes sense
        if (r2pmFile == None) == (httpRepo == None):
            msg = "add(): bad parameters, must use either r2pmFile or httpRepo"
            self._log("add-called-bad").error(msg)
            raise InstallException(msg)

        if r2pmFile != None:
            self._raiseIfNotAbsPath(r2pmFile, "r2pmFile")
        else:
            if packageName == None:
                msg = "add(): bad parameters, httpRepo must come with packageName"
                self._log("add-called-bad").error(msg)
                raise InstallException(msg)

        # Clean the temp dir and create it
        if not self.useFakeChrootMode:
            # In ut fakechroot mode we do not remove this, because this dir has chroot soft links
            self._cleanTempDir()
        self.utils.runCommandRaiseIfFail("mkdir -p " + self.subPkgTempDir)

        # Import RPM public keys
        # In unit tests, it is impossible to get keys from outside of the chroot. Instead, the test does rpm --import
        # in this chroot for us.
        if not self.useFakeChrootMode:
            rpm = Rpm(self._log)
            rpm.setRoot(self.subPkgTempDir)
            for keyFile in os.listdir(self.rpmKeysDir):
                rpm.doImport(os.path.join(self.rpmKeysDir, keyFile))

        # Check space - must have at least 4GB free
        availableSize = self.utils.getAvailableSize(self.subPkgTempDir)
        if availableSize < 4e9:
            raise InstallException(
                "Internal error: Not enough space on system disk")

        # Read all existing sub-pkgs
        oldInfoDict = self._readInfoFiles(self.infoDir)
        self._log("add-sub-pkg").info("add(): Found old sub-pkgs %s",
                                      oldInfoDict)
        oldSubPkgs = oldInfoDict.keys()

        # Create temp dir for yum (for config file and such)
        if not self.useFakeChrootMode:
            yumTempDir = os.path.join(self.subPkgTempDir, "tmp")
        else:
            yumTempDir = "/tmp"

        # Extract r2pm into temp dir
        try:
            if r2pmFile != None:
                # Install from file
                removeFile = False
                if not self.useFakeChrootMode:
                    r2pmNameToYum = r2pmFile
                    # In CentOS6.2, package files must end with '.rpm'
                    if not r2pmNameToYum.endswith('.rpm'):
                        r2pmNameToYum = os.path.join(self.subPkgTempDir,
                                                     'package.rpm')
                        self._log("add-sub-pkg-copy").info(
                            "add(): Copying %s to %s to have a file name that ends with .rpm",
                            r2pmFile, r2pmNameToYum)
                        self.utils.runCommandRaiseIfFail(
                            "cp -f %s %s" % (r2pmFile, r2pmNameToYum))
                        removeFile = True

                else:
                    self.utils.runCommandRaiseIfFail("cp " + r2pmFile + " " +
                                                     self.subPkgTempDir)
                    r2pmNameToYum = "/" + os.path.basename(r2pmFile)
                yum = Yum(self._log, yumTempDir)
                yum.setRoot(self.subPkgTempDir,
                            useFakeChrootMode=self.useFakeChrootMode)
                yum.doLocalInstall(r2pmNameToYum)
                if removeFile:
                    self._log("add-sub-pkg-remove").info(
                        "add(): Removing file that was copied")
                    self.utils.runCommandRaiseIfFail("rm -f %s" %
                                                     r2pmNameToYum)
            else:
                # Install from http repo
                yum = Yum(self._log, yumTempDir)
                yum.setRoot(self.subPkgTempDir,
                            useFakeChrootMode=self.useFakeChrootMode)
                yum.addHttpRepo("network", httpRepo)
                yum.doInstall(packageName)

            # Now, move/replace new sub-pkgs into subPkgDir.
            # We do this according to a very specific sequence, so that in case we abort in the middle (power failure or whatever),
            # A call to TBD() will restore things the way they were before this operation
            # Todo(orens): TBD -> Real function
            # Sequence is:
            # 1. Copy all existing sub-packages to self.subPkgTempDir, except for those found there already (i.e. new copy
            #    is better tahn old copy)
            # 2. Rename self.subPkgDir with a '.tmp' suffix
            # 3. Rename self.subPkgTempDir to become self.subPkgDir
            # 4. Remove self.subPkgDir + '.tmp'

            # System is always stable, excelt for the split-second between 2 and 3.

            # Read list of new sub-packages
            newInfoDict = self._readInfoFiles(
                os.path.join(self.subPkgTempDir, "info"))
            self._log("add-sub-pkg").info("add(): Found new sub-pkgs %s",
                                          newInfoDict)
            newSubPkgs = newInfoDict.keys()

            # Sanity-check the new info: Make sure new sub-pkgs have all the data we need in their .info files
            for subPkg in newSubPkgs:
                info = newInfoDict[subPkg]
                if not 'dir' in info:
                    self._log("add-bad-info-dir").error(
                        "add(): sub-pkg %s info does not have 'dir'", subPkg)
                    return None
                infoDirPath = os.path.join(self.subPkgTempDir, info['dir'])
                if not os.path.isdir(infoDirPath):
                    self._log("add-missing-dir").error(
                        "add(): sub-pkg %s info has 'dir'->%s, does not exist",
                        subPkg, infoDirPath)
                    return None
                if not 'name' in info:
                    self._log("add-bad-info-name").error(
                        "add(): sub-pkg %s info does not have 'name'", subPkg)
                    return None
                if info['name'] != subPkg:
                    self._log("add-bad-name").error(
                        "add(): sub-pkg %s info has 'name'=%s, should be identical",
                        subPkg, info['name'])
                    return None

            # Step 1: Copy all old sub-packages, which are not found in the new dir, to the new dir
            for subPkg in oldSubPkgs:
                if subPkg not in newSubPkgs:
                    oldInfoFile = self._getInfoFileName(self.subPkgDir, subPkg)
                    newInfoFile = self._getInfoFileName(
                        self.subPkgTempDir, subPkg)
                    oldSubPkgDir = os.path.join(self.subPkgDir,
                                                oldInfoDict[subPkg]['dir'])
                    newSubPkgDir = os.path.join(self.subPkgTempDir,
                                                oldInfoDict[subPkg]['dir'])
                    if os.path.exists(newSubPkgDir):
                        self._log("add-bad-name").error(
                            "add(): old sub-pkg %s not found in new sub-packages, but %s exists",
                            subPkg, newSubPkgDir)
                        return None
                    self.utils.runCommandRaiseIfFail(
                        "cp -vpf %s %s" % (oldInfoFile, newInfoFile))
                    self.utils.runCommandRaiseIfFail(
                        "cp -vrpf %s %s" % (oldSubPkgDir, newSubPkgDir))

            # Steps 2-4: Copy all old sub-packages, which are not found in the new dir, to the new dir
            tmpOldName = self.subPkgDir + '.tmp'
            self.utils.runCommandRaiseIfFail("mv -vf %s %s" %
                                             (self.subPkgDir, tmpOldName))
            self.utils.runCommandRaiseIfFail(
                "mv -vf %s %s" % (self.subPkgTempDir, self.subPkgDir))
            self.utils.runCommandRaiseIfFail("rm -vrf %s" % (tmpOldName))

        finally:
            # Remove the install-temp directory, no sense in leaving it here
            self._cleanTempDir()

        # oldInfoDict.keys() holds the list of subPkgs before the install. Let's find out what was added.
        newInfoDict = self._readInfoFiles(self.infoDir)

        # Sorting makes it easy on unit tests :-)
        addedSubPkgs = sorted(
            list(set(newInfoDict.keys()) - set(oldInfoDict.keys())))
        return (sorted(newSubPkgs), addedSubPkgs)
Ejemplo n.º 25
0
    def load(self):
        """
        Loads state from file. If file does not exist or invalid, raises InstallException
        """

        self._log("load-called").info("load() called, reading state from %s",
                                      self._stateFile)

        if not os.path.exists(self._stateFile):
            self._log("load-no-file").error(
                "load() called, no file '%s' found", self._stateFile)
            raise InstallException("State file not found: %s" %
                                   self._stateFile)

        dict_ = a.infra.format.json.readFromFile(self._log, self._stateFile)
        if not self.kTokenVersions in dict_:
            self._log("load-invalid-text").error("load() could not find '%s'",
                                                 self.kTokenVersions)
            raise InstallException("State file is invalid: %s " %
                                   self._stateFile)
        versions = dict_[self.kTokenVersions]

        # Parse versions into newVersions
        newVersions = {}
        numActive = 0
        numReady = 0
        for version_ in versions:
            versionInfo = versions[version_]

            # state is checked thorrowly
            if not self.kTokenState in versionInfo:
                self._log("load-invalid-version").error(
                    "load() could not find state for version '%s'", version_)
                raise InstallException("State file is invalid: %s " %
                                       self._stateFile)
            state = versionInfo[self.kTokenState]
            if (state != self.kStateActive) and (
                    state != self.kStateReady) and (state !=
                                                    self.kStateOnDisk):
                self._log("load-invalid-state").error(
                    "load() got invalid state '%s' for version '%s'", state,
                    version_)
                raise InstallException("State file is invalid: %s " %
                                       self._stateFile)

            newVersions[version_] = {self.kTokenState: state}
            newVersionInfo = newVersions[version_]
            if state == self.kStateActive:
                numActive += 1
            if state == self.kStateReady:
                numReady += 1

            # Other data is simple copied
            if self.kTokenPilotName in versionInfo:
                newVersionInfo[self.kTokenPilotName] = versionInfo[
                    self.kTokenPilotName]
            if self.kTokenPilotData in versionInfo:
                newVersionInfo[self.kTokenPilotData] = versionInfo[
                    self.kTokenPilotData]
            if self.kTokenSwitchType in versionInfo:
                newVersionInfo[self.kTokenSwitchType] = versionInfo[
                    self.kTokenSwitchType]
            if self.kTokenInstallDirection in versionInfo:
                newVersionInfo[self.kTokenInstallDirection] = versionInfo[
                    self.kTokenInstallDirection]

            if self.kTokenSubPkgsToRemove in versionInfo:
                newVersionInfo[self.kTokenSubPkgsToRemove] = versionInfo[
                    self.kTokenSubPkgsToRemove]
            if self.kTokenRpmsToRemove in versionInfo:
                newVersionInfo[self.kTokenRpmsToRemove] = versionInfo[
                    self.kTokenRpmsToRemove]

            if self.kTokenSubPkgs in versionInfo:
                newVersionInfo[self.kTokenSubPkgs] = versionInfo[
                    self.kTokenSubPkgs]
            else:
                # 2.1.0.0 does not maintain the 'sub-packages' info. Hence, we 'guess' it :-)
                newVersionInfo[self.kTokenSubPkgs] = ['qb-' + version_]

            if self.kTokenLeaders in versionInfo:
                newVersionInfo[self.kTokenLeaders] = versionInfo[
                    self.kTokenLeaders]
            else:
                # 2.1.0.0 does not maintain the 'leaders' info. Hence, we 'guess' it :-)
                newVersionInfo[self.kTokenLeaders] = {
                    'prepare': 'qb-leader-prepare-' + version_,
                    'switch': 'qb-leader-switch-' + version_
                }

        if (numActive != 1) or (numReady > 1):
            self._log("load-invalid-states").error(
                "load() found %s active versions, %s ready versions, impossible",
                numActive, numReady)
            raise InstallException("State file is invalid: %s " %
                                   self._stateFile)

        # Check 'versionToActivateOnStartup'
        newVersionToActivate = None
        if self.kTokenActivateOnStartup in dict_:
            newVersionToActivate = dict_[self.kTokenActivateOnStartup]
            if not newVersionToActivate in newVersions:
                self._log("load-invalid-vta").error(
                    "load() found invalid version to activate = '%s', not in list",
                    newVersionToActivate)
                raise InstallException("State file is invalid: %s" %
                                       self._stateFile)
            vtaState = newVersions[newVersionToActivate][self.kTokenState]
            if vtaState != self.kStateReady:
                self._log("load-invalid-vta").error(
                    "load() found invalid version to activate = '%s', has state '%s', not ready",
                    newVersionToActivate, vtaState)
                raise InstallException("State file is invalid: %s" %
                                       self._stateFile)

        # Check 'locked'
        newLocked = False
        if self.kTokenLocked in dict_:
            newLocked = True

        # Now that we are sure that the state we got is valid, we rememebr it
        self.versions = newVersions
        self.versionToActivateOnStartup = newVersionToActivate
        self._locked = newLocked
        self._log("load-got-state").info(
            "load() got a new state: versions='%s', versionToActivateOnStartup='%s', locked=%s",
            self.versions, self.versionToActivateOnStartup, self._locked)