Пример #1
0
 def __init__(self, testClient, logFileDir):
     self._testClient = testClient
     curTimestamp = getCurrentTimestamp()
     logFileName = "%s.%s" % (self.DEFAULT_VISTA_LOG_FILENAME, curTimestamp)
     self._logFileName = os.path.join(logFileDir, logFileName)
     self._testClient.setLogFile(self._logFileName)
     self._patchOrderGen = PatchOrderGenerator()
     self._vistaPatchInfo = VistAPackageInfoFetcher(testClient)
     self._outPatchList = []
     self._patchSet = set()
     initFileLogging(os.path.join(logFileDir, self.DEFAULT_OUTPUT_FILE_LOG))
Пример #2
0
 def runInstallation(self, vistATestClient, vistATestClient2=None, reinst=False):
     connection = vistATestClient.getConnection()
     self.__setupLogFile__(connection)
     infoFetcher = VistAPackageInfoFetcher(vistATestClient)
     installStatus = infoFetcher.getInstallationStatus(self._kidsInstallName)
     """ select KIDS installation workflow based on install status """
     if infoFetcher.isInstallCompleted(installStatus):
         logger.warn("install %s is already completed!" % self._kidsInstallName)
         if not reinst:
             return True
     # run pre-installation preparation
     self.preInstallationWork(vistATestClient)
     if infoFetcher.isInstallStarted(installStatus):
         return self.restartInstallation(vistATestClient)
     return self.normalInstallation(vistATestClient, vistATestClient2, reinst)
Пример #3
0
 def runInstallation(self, vistATestClient, vistATestClient2=None, reinst=False):
   connection = vistATestClient.getConnection()
   self.__setupLogFile__(connection)
   infoFetcher = VistAPackageInfoFetcher(vistATestClient)
   installStatus = infoFetcher.getInstallationStatus(self._kidsInstallName)
   """ select KIDS installation workflow based on install status """
   if infoFetcher.isInstallCompleted(installStatus):
     logger.warn("install %s is already completed!" %
                  self._kidsInstallName)
     if not reinst:
       return True
   # run pre-installation preparation
   self.preInstallationWork(vistATestClient)
   if infoFetcher.isInstallStarted(installStatus):
     return self.restartInstallation(vistATestClient)
   return self.normalInstallation(vistATestClient,vistATestClient2, reinst)
Пример #4
0
 def __init__(self, testClient, logFileDir):
   self._testClient = testClient
   curTimestamp = getCurrentTimestamp()
   logFileName = "%s.%s" % (self.DEFAULT_VISTA_LOG_FILENAME, curTimestamp)
   self._logFileName = os.path.join(logFileDir,
                            logFileName)
   self._testClient.setLogFile(self._logFileName)
   self._patchOrderGen = PatchOrderGenerator()
   self._vistaPatchInfo = VistAPackageInfoFetcher(testClient)
   self._outPatchList = []
   self._patchSet = set()
   initFileLogging(os.path.join(logFileDir, self.DEFAULT_OUTPUT_FILE_LOG))
Пример #5
0
class KIDSPatchSequenceApply(object):
  DEFAULT_VISTA_LOG_FILENAME = "VistAInteraction.log"
  DEFAULT_OUTPUT_FILE_LOG = "PatchAnalyzer.log"
  def __init__(self, testClient, logFileDir):
    self._testClient = testClient
    curTimestamp = getCurrentTimestamp()
    logFileName = "%s.%s" % (self.DEFAULT_VISTA_LOG_FILENAME, curTimestamp)
    self._logFileName = os.path.join(logFileDir,
                             logFileName)
    self._testClient.setLogFile(self._logFileName)
    self._kidsOrderGen = KIDSPatchOrderGenerator()
    self._vistaPatchInfo = VistAPackageInfoFetcher(testClient)
    self._outPatchList = []
    self._patchSet = set()
    initConsoleLogging()
    initFileLogging(os.path.join(logFileDir, self.DEFAULT_OUTPUT_FILE_LOG))

  """ generate the patch order sequence base on input """
  def generateKIDSPatchSequence(self, patchDir, installName=None,
                                isUpToPatch=False):
    kidsOrderGen = self._kidsOrderGen
    patchHistInfo = self._vistaPatchInfo
    patchList = []
    if isUpToPatch:
      patchList = kidsOrderGen.generatePatchOrderTopologic(patchDir)
    else:
      patchList = kidsOrderGen.generatePatchOrderTopologic(patchDir, installName)
    self._patchSet.update([x.installName for x in patchList])
    if installName and installName not in self._patchSet:
      errMsg = ("Can not find patch for install name %s" % installName)
      raise Exception(errMsg)
    for patchInfo in patchList:
      namespace = patchInfo.namespace
      self.__updatePatchInfoPackageName__(patchInfo)
      logger.info("Checking for patch info %s" % patchInfo.installName)
      logger.debug("Checking for patch info %s" % patchInfo)
      """ check to see if the patch is already installed """
      if not self.__isPatchInstalled__(patchInfo):
        if self.__isPatchReadyToInstall__(patchInfo, patchList):
          self._outPatchList.append(patchInfo)
        else:
          errorMsg = ("Can not install patch %s" % patchInfo.installName)
          logger.error(errorMsg)
          raise Exception(errorMsg)
      if isUpToPatch and installName and installName == patchInfo.installName:
        break

    logger.info("Total patches are %d" % len(self._outPatchList))
    for patchInfo in self._outPatchList:
      logger.info("%s, %s, %s" % (patchInfo.installName,
                                  patchInfo.namespace,
                                  patchInfo.kidsFilePath))

  """ Apply up to maxPatches KIDS Patches ordered by sequence number """
  def applyKIDSPatchSequenceByNumber(self, maxPatches=1):
    totalPatch = len(self._outPatchList)
    numOfPatch = 1
    if re.match("All", str(maxPatches), re.IGNORECASE):
      numOfPatch = totalPatch
    else:
      numOfPatch = int(maxPatches)
    endIndex = min(totalPatch, numOfPatch)
    self.__applyKIDSPatchUptoIndex__(endIndex)

  """ apply the KIDS Patch in sequence order up to specified install name """
  def applyKIDSPatchSequenceByInstallName(self, installName, patchOnly=False):
    if installName not in self._patchSet:
      raise Exception("Invalid install name: %s" % installName)
    if len(self._outPatchList) == 0:
      logger.info("No Patch to apply")
      return
    logger.info("Apply patches up to %s" % installName)
    self.__applyKIDSPatchUptoIndex__(len(self._outPatchList))

  @staticmethod
  def generateSha1SumForPatchInfo(patchInfo):
    if patchInfo.kidsSha1 is None:
      patchInfo.kidsSha1 = generateSha1Sum(patchInfo.kidsFilePath)
    if patchInfo.kidsInfoPath:
      patchInfo.kidsInfoSha1 = generateSha1Sum(patchInfo.kidsInfoPath)
    if patchInfo.otherKidsInfoList:
      for item in patchInfo.otherKidsInfoList:
        if item[0]:
          item[1] = generateSha1Sum(item[0])

  @staticmethod
  def indexInPatchList(installName, patchList):
    for index in range(0,len(patchList)):
      if patchList[index].installName == installName:
        return index
    return -1

#---------------------------------------------------------------------------
# private implementation
#---------------------------------------------------------------------------
  """
    apply patch incrementally up to the end index in self._outPatchList
  """
  def __applyKIDSPatchUptoIndex__(self, endIndex):
    assert endIndex >= 0 and endIndex <= len(self._outPatchList)
    """ make sure taskman is running """
    taskmanUtil = VistATaskmanUtil()
    taskmanUtil.startTaskman(self._testClient)
    for index in range(0, endIndex):
      patchInfo = self._outPatchList[index]
      result = self.__applyIndividualKIDSPatch__(patchInfo)
      if not result:
        logger.error("Failed to install patch %s: KIDS %s" %
                      (patchInfo.installName, patchInfo.kidsFilePath))
        return
    """ wait until taskman is current """
    taskmanUtil.waitTaskmanToCurrent(self._testClient)

#---------------------------------------------------------------------------
# private implementation
#---------------------------------------------------------------------------
  """
    get index of a patch in self._outPatchList by install name
  """
  def __getPatchIndexByInstallName__(self, installName):
    idx = 0
    for patchInfo in self._outPatchList:
      if patchInfo.installName == installName:
        return idx
      idx += 1
    return -1
  """
    apply individual KIDS patch
  """
  def __applyIndividualKIDSPatch__(self, patchInfo):
    """ double check to see if patch is already installed """
    if self.__isPatchInstalled__(patchInfo):
      return True
    if not self.__isPatchReadyToInstall__(patchInfo):
      return False
    """ generate Sha1 Sum for patch Info """
    self.generateSha1SumForPatchInfo(patchInfo)
    """ install the KIDS patch """
    result = self.__installKIDSPatch__(patchInfo)
    if not result:
      errorMsg = ("Failed to install patch %s: KIDS %s" %
                 (patchInfo.installName, patchInfo.kidsFilePath))
      logger.error(errorMsg)
      raise Exception(errorMsg)
    else:
      # also need to reload the package patch hist
      self.__reloadPackagePatchHistory__(patchInfo)
      assert self.__isPatchInstalled__(patchInfo)
    return True
  """ get the package patch history and update package name
      for KIDS only build
  """
  def __updatePatchInfoPackageName__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    packageName = patchInfo.package
    namespace = patchInfo.namespace
    verInfo = patchInfo.version
    if namespace:
      patchHistInfo.getPackagePatchHistByNamespace(namespace, verInfo)
      if packageName:
        vistAPackageName = patchHistInfo.getPackageName(namespace)
        if vistAPackageName != packageName:
          logger.error("Different PackageName for %s, %s:%s" %
                       (patchInfo.installName, vistAPackageName, packageName))
          patchInfo.package = vistAPackageName
      else:
        packageName = patchHistInfo.getPackageName(namespace)
        patchInfo.package = packageName

  """ check to see if the patch is already installed """
  def __isPatchInstalled__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    namespace = patchInfo.namespace
    installName = patchInfo.installName
    if patchHistInfo.hasPatchInstalled(patchInfo.installName,
                                       patchInfo.namespace,
                                       patchInfo.version,
                                       patchInfo.patchNo,
                                       patchInfo.seqNo):
      logger.info("%s is already installed" % installName)
      return True
    installStatus = patchHistInfo.getInstallationStatus(installName)
    logger.debug("%s installation status is %d" %
                 (installName, installStatus))
    if patchHistInfo.isInstallCompleted(installStatus):
      logger.info("%s installed completed" % installName)
      return True
    else:
      return False

  """ update package patch history """
  def __reloadPackagePatchHistory__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    installNameList = []
    if patchInfo.isMultiBuilds:
      installNameList = patchInfo.multiBuildsList
    else:
      installNameList.append(patchInfo.installName)
    for installName in installNameList:
      (namespace,ver,patch) = extractInfoFromInstallName(installName)
      if not patchHistInfo.hasNamespace(namespace):
        patchHistInfo.createAllPackageMapping()
      if patchHistInfo.hasNamespace(namespace):
        packageName = patchHistInfo.getPackageName(namespace)
        patchHistInfo.getPackagePatchHistory(packageName, namespace, ver)

  """ create KIDS Patch Installer by patch Info and install
      the patch specified in patchInfo, return the result
      @return, True indicates on error, False indicates failure
  """
  def __installKIDSPatch__(self, patchInfo):
    installName = patchInfo.installName
    kidsPath = patchInfo.kidsFilePath
    seqNo = patchInfo.seqNo
    logFileName = self._logFileName
    multiBuildsList = patchInfo.multiBuildsList
    kidsInstaller = None
    """ handle patch stored as external link """
    if patchInfo.kidsSha1Path != None:
      kidsSha1 = patchInfo.kidsSha1
      (result, resultPath) = obtainKIDSPatchFileBySha1(kidsPath,
                                                       kidsSha1,
                                                       DEFAULT_CACHE_DIR)
      if not result:
        logger.error("Could not obtain external KIDS patch for %s" % kidsPath)
        return result
      kidsPath = resultPath # set the KIDS Path
    """ get the right KIDS installer """
    associateFiles = patchInfo.associatedInfoFiles
    associatedGlobals = patchInfo.associatedGlobalFiles
    if patchInfo.hasCustomInstaller:
      """ use python imp module to load the source """
      logger.info("using custom installer %s" % patchInfo.customInstallerPath)
      import imp
      installerModule = imp.load_source("KIDS",
                                patchInfo.customInstallerPath)
      from KIDS import CustomInstaller
      kidsInstaller = CustomInstaller(kidsPath, installName,
                                      seqNo, logFileName,
                                      multiBuildsList,
                                      files=associateFiles,
                                      globals=associatedGlobals)

    else:
      kidsInstaller = KIDSInstallerFactory.createKIDSInstaller(
                            kidsPath, installName, seqNo, logFileName,
                            multiBuildsList,
                            files=associateFiles,
                            globals=associatedGlobals)
    logger.info("Applying KIDS Patch %s" % patchInfo)
    assert kidsInstaller
    return kidsInstaller.runInstallation(self._testClient)

  """ check to see if patch is ready to be installed """
  def __isPatchReadyToInstall__(self, patchInfo, patchList = None):
    packageName = patchInfo.package
    ver = patchInfo.version
    patchHist = self._vistaPatchInfo.getPackagePatchHistByName(packageName, ver)
    if not patchHist or not patchHist.hasPatchHistory():
      logger.info("no patch hist for %s, ver: %s" % (packageName, ver))
      return True # if no such an package or hist info, just return True
    """ check patch sequence no to see if it is out of order """
    if patchInfo.seqNo:
      seqNo = patchHist.getLatestSeqNo()
      if patchInfo.seqNo < seqNo:
        logger.error("SeqNo out of order, %s less than latest one %s" %
                      (patchInfo.seqNo), seqNo)
        return False
    # check all the dependencies
    for item in patchInfo.depKIDSPatch:
      if patchList and item in self._patchSet: # we are going to install the dep patch
        logger.info("We are going to install the patch %s" % item)
        """ make sure installation is in the right order """
        itemIndex = self.indexInPatchList(item, patchList)
        patchIndex = self.indexInPatchList(patchInfo.installName, patchList)
        if itemIndex >= patchIndex:
          logger.warn("%s is out of order with %s" % (item, patchInfo))
          return False
        else:
          continue
      (namespace,ver,patch) = extractInfoFromInstallName(item)
      if self._vistaPatchInfo.hasPatchInstalled(item, namespace, ver, patch):
        logger.debug("%s is arelady installed" % item)
        continue
      installStatus = self._vistaPatchInfo.getInstallationStatus(item)
      if self._vistaPatchInfo.isInstallCompleted(installStatus):
        continue
      else:
        logger.error("dep %s is not installed for %s %s" %
                    (item, patchInfo.installName, patchInfo.kidsFilePath))
        return False
    return True
Пример #6
0
class PatchSequenceApply(object):
  DEFAULT_VISTA_LOG_FILENAME = "VistAInteraction.log"
  DEFAULT_OUTPUT_FILE_LOG = "PatchAnalyzer.log"
  def __init__(self, testClient, logFileDir, testClient2=None):
    self._testClient = testClient
    self._testClient2 = testClient2
    curTimestamp = getCurrentTimestamp()
    logFileName = "%s.%s" % (self.DEFAULT_VISTA_LOG_FILENAME, curTimestamp)
    self._logFileName = os.path.join(logFileDir,
                             logFileName)
    self._testClient.setLogFile(self._logFileName)
    self._patchOrderGen = PatchOrderGenerator()
    self._vistaPatchInfo = VistAPackageInfoFetcher(testClient)
    self._outPatchList = []
    self._patchSet = set()
    initFileLogging(os.path.join(logFileDir, self.DEFAULT_OUTPUT_FILE_LOG))

  """ generate the patch order sequence base on input """
  def generatePatchSequence(self, patchDir, installName=None,
                                isUpToPatch=False):
    patchOrderGen = self._patchOrderGen
    patchHistInfo = self._vistaPatchInfo
    patchList = []
    if isUpToPatch:
      patchList = patchOrderGen.generatePatchOrderTopologic(patchDir)
    else:
      patchList = patchOrderGen.generatePatchOrderTopologic(patchDir, installName)
    self._patchSet.update([x.installName for x in patchList])
    if installName and installName not in self._patchSet:
      errMsg = ("Can not find patch for install name %s" % installName)
      raise Exception(errMsg)
    dependencyIssues = {}
    for patchInfo in patchList:
      namespace = patchInfo.namespace
      self.__updatePatchInfoPackageName__(patchInfo)
      logger.info("Checking for patch info %s" % patchInfo.installName)
      logger.debug("Checking for patch info %s" % patchInfo)
      """ check to see if the patch is already installed """
      if not self.__isPatchInstalled__(patchInfo):
        if self.__isPatchReadyToInstall__(patchInfo, patchList):
          self._outPatchList.append(patchInfo)
        else:
          dependencyIssues[patchInfo.installName] = patchInfo.depKIDSBuild
          continue #raise Exception(errorMsg)
      if isUpToPatch and installName and installName == patchInfo.installName:
        break
    if len(dependencyIssues):
        for obj in dependencyIssues:
            logger.error("Problems found with dependencies of %s in: %s" % (obj, dependencyIssues[obj]))
        raise Exception("Dependency Errors Found")
    logger.info("Total patches are %d" % len(self._outPatchList))
    for patchInfo in self._outPatchList:
      logger.info("%s, %s, %s" % (patchInfo.installName,
                                  patchInfo.namespace,
                                  patchInfo.kidsFilePath))
    return self._outPatchList

  """ Apply up to maxPatches Patches ordered by sequence number """
  def applyPatchSequenceByNumber(self, maxPatches=1):
    totalPatch = len(self._outPatchList)
    numOfPatch = 1
    if re.match("All", str(maxPatches), re.IGNORECASE):
      numOfPatch = totalPatch
    else:
      numOfPatch = int(maxPatches)
    endIndex = min(totalPatch, numOfPatch)
    return self.__applyPatchUptoIndex__(endIndex)

  def applyPatchSequenceByInstallName(self, installName, patchOnly=False):
    """ apply the Patch in sequence order up to specified install name
        if patchOnly is set to True, will only apply that patch
    """
    if installName not in self._patchSet:
      raise Exception("Invalid install name: %s" % installName)
    if len(self._outPatchList) == 0:
      logger.info("No Patch to apply")
      return 0
    logger.info("Apply patches up to %s" % installName)
    patchIndex = self.__getPatchIndexByInstallName__(installName)
    endIndex = patchIndex + 1
    startIndex = 0
    if patchOnly:
      startIndex = patchIndex
    return self.__applyPatchUptoIndex__(endIndex, startIndex)

  @staticmethod
  def generateSha1SumForPatchInfo(patchInfo):
    if patchInfo.kidsSha1 is None:
      patchInfo.kidsSha1 = generateSha1Sum(patchInfo.kidsFilePath)
    if patchInfo.kidsInfoPath:
      patchInfo.kidsInfoSha1 = generateSha1Sum(patchInfo.kidsInfoPath)
    if patchInfo.otherKidsInfoList:
      for item in patchInfo.otherKidsInfoList:
        if item[0]:
          item[1] = generateSha1Sum(item[0])

  @staticmethod
  def indexInPatchList(installName, patchList):
    for index in range(0,len(patchList)):
      if patchList[index].installName == installName:
        return index
    return -1

#---------------------------------------------------------------------------
# private implementation
#---------------------------------------------------------------------------
  """
    apply patch incrementally up to the end index in self._outPatchList
  """
  def __applyPatchUptoIndex__(self, endIndex, startIndex=0):
    assert endIndex >= 0 and endIndex <= len(self._outPatchList)
    assert startIndex >=0 and startIndex <= endIndex
    """ make sure taskman is running """
    taskmanUtil = VistATaskmanUtil()
    taskmanUtil.startTaskman(self._testClient)
    result = 0
    for index in range(startIndex, endIndex):
      patchInfo = self._outPatchList[index]
      result = self.__applyIndividualPatch__(patchInfo)
      if result < 0:
        logger.error("Failed to install patch %s: KIDS %s" %
                      (patchInfo.installName, patchInfo.kidsFilePath))
        return result
    """ wait until taskman is current """
    taskmanUtil.waitTaskmanToCurrent(self._testClient)
    return result

#---------------------------------------------------------------------------
# private implementation
#---------------------------------------------------------------------------
  """
    get index of a patch in self._outPatchList by install name
  """
  def __getPatchIndexByInstallName__(self, installName):
    idx = 0
    for patchInfo in self._outPatchList:
      if patchInfo.installName == installName:
        return idx
      idx += 1
    return -1
  """
    apply individual patch
    @return:
      throw exception for installation error.
      0 if patch is already installed.
      -1 if patch is not ready to install
      1 if patch installed sucessfully
  """
  def __applyIndividualPatch__(self, patchInfo):
    """ double check to see if patch is already installed """
    if self.__isPatchInstalled__(patchInfo):
      return 0
    if not self.__isPatchReadyToInstall__(patchInfo):
      return -1
    """ generate Sha1 Sum for patch Info """
    self.generateSha1SumForPatchInfo(patchInfo)
    """ install the Patch """
    result = self.__installPatch__(patchInfo)
    if not result:
      errorMsg = ("Failed to install patch %s: KIDS %s" %
                 (patchInfo.installName, patchInfo.kidsFilePath))
      logger.error(errorMsg)
      raise Exception(errorMsg)
    else:
      # also need to reload the package patch hist
      self.__reloadPackagePatchHistory__(patchInfo)
      """ special logic to handle release code """
      installed = False
      namespace,ver,patch = extractInfoFromInstallName(patchInfo.installName)
      if not patch:
        if namespace and ver:
          updVer = getPackageLatestVersionByNamespace(namespace,
                                                      self._testClient)
          if updVer and updVer == ver:
            installed = True
      if not installed:
        assert self.__isPatchInstalled__(patchInfo)
    return 1
  """ get the package patch history and update package name
      for KIDS only build
  """
  def __updatePatchInfoPackageName__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    packageName = patchInfo.package
    namespace = patchInfo.namespace
    verInfo = patchInfo.version
    if namespace:
      patchHistInfo.getPackagePatchHistByNamespace(namespace, verInfo)
      if packageName:
        vistAPackageName = patchHistInfo.getPackageName(namespace)
        if vistAPackageName != packageName:
          logger.error("Different PackageName for %s, %s:%s" %
                       (patchInfo.installName, vistAPackageName, packageName))
          patchInfo.package = vistAPackageName
      else:
        packageName = patchHistInfo.getPackageName(namespace)
        patchInfo.package = packageName

  """ check to see if the patch is already installed """
  def __isPatchInstalled__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    namespace = patchInfo.namespace
    installName = patchInfo.installName
    if patchHistInfo.hasPatchInstalled(patchInfo.installName,
                                       patchInfo.namespace,
                                       patchInfo.version,
                                       patchInfo.patchNo,
                                       patchInfo.seqNo):
      logger.info("%s is already installed" % installName)
      return True
    installStatus = patchHistInfo.getInstallationStatus(installName)
    logger.debug("%s installation status is %d" %
                 (installName, installStatus))
    if patchHistInfo.isInstallCompleted(installStatus):
      logger.info("%s installed completed" % installName)
      return True
    else:
      return False

  """ update package patch history """
  def __reloadPackagePatchHistory__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    patchHistInfo.createAllPackageMapping()
    installNameList = []
    if patchInfo.isMultiBuilds:
      installNameList = patchInfo.multiBuildsList
    else:
      installNameList.append(patchInfo.installName)
    for installName in installNameList:
      (namespace,ver,patch) = extractInfoFromInstallName(installName)
      if not patchHistInfo.hasNamespace(namespace):
        ns = patchHistInfo.getPackageNamespaceByName(namespace)
        if not ns:
          patchHistInfo.createAllPackageMapping()
        else:
          namespace = ns
      if patchHistInfo.hasNamespace(namespace):
        packageName = patchHistInfo.getPackageName(namespace)
        patchHistInfo.getPackagePatchHistory(packageName, namespace, ver)

  """ create Patch Installer by patch Info and install
      the patch specified in patchInfo, return the result
      @return, True indicates on error, False indicates failure
  """
  def __installPatch__(self, patchInfo):
    installName = patchInfo.installName
    kidsPath = patchInfo.kidsFilePath
    seqNo = patchInfo.seqNo
    logFileName = self._logFileName
    multiBuildsList = patchInfo.multiBuildsList
    kidsInstaller = None
    """ handle patch stored as external link """
    if patchInfo.kidsSha1Path != None:
      kidsSha1 = patchInfo.kidsSha1
      (result, resultPath) = obtainKIDSBuildFileBySha1(kidsPath,
                                                       kidsSha1,
                                                       DEFAULT_CACHE_DIR)
      if not result:
        logger.error("Could not obtain external Patch for %s" % kidsPath)
        return result
      kidsPath = resultPath # set the KIDS Path
    """ get the right KIDS installer """
    associateFiles = patchInfo.associatedInfoFiles
    associatedGlobals = patchInfo.associatedGlobalFiles
    if patchInfo.hasCustomInstaller:
      """ use python imp module to load the source """
      logger.info("using custom installer %s" % patchInfo.customInstallerPath)
      import imp
      installerModule = imp.load_source("KIDS",
                                patchInfo.customInstallerPath)
      from KIDS import CustomInstaller
      kidsInstaller = CustomInstaller(kidsPath, installName,
                                      seqNo, logFileName,
                                      multiBuildsList,
                                      files=associateFiles,
                                      globals=associatedGlobals,
                                      duz = self._duz)

    else:
      kidsInstaller = KIDSInstallerFactory.createKIDSInstaller(
                            kidsPath, installName, seqNo, logFileName,
                            multiBuildsList,
                            files=associateFiles,
                            globals=associatedGlobals,
                            duz = self._duz)
    logger.info("Applying Patch %s" % patchInfo)
    assert kidsInstaller
    return kidsInstaller.runInstallation(self._testClient, self._testClient2)

  """ check to see if patch is ready to be installed """
  def __isPatchReadyToInstall__(self, patchInfo, patchList = None):
    packageName = patchInfo.package
    ver = patchInfo.version
    patchHist = self._vistaPatchInfo.getPackagePatchHistByName(packageName, ver)
    if not patchHist or not patchHist.hasPatchHistory():
      logger.info("no patch hist for %s, ver: %s" % (packageName, ver))
      return True # if no such an package or hist info, just return True
    """ check patch sequence no to see if it is out of order """
    if patchInfo.seqNo:
      seqNo = patchHist.getLatestSeqNo()
      if patchInfo.seqNo < seqNo:
        logger.error("SeqNo out of order, %s less than latest one %s" % (patchInfo.seqNo, seqNo))
        return False
    # check all the dependencies
    for item in patchInfo.depKIDSBuild:
      if patchList and item in self._patchSet: # we are going to install the dep patch
        logger.info("We are going to install the patch %s" % item)
        """ make sure installation is in the right order """
        itemIndex = self.indexInPatchList(item, patchList)
        patchIndex = self.indexInPatchList(patchInfo.installName, patchList)
        if itemIndex >= patchIndex:
          logger.warn("%s is out of order with %s" % (item, patchInfo))
          return False
        else:
          continue
      (namespace,ver,patch) = extractInfoFromInstallName(item)
      if self._vistaPatchInfo.hasPatchInstalled(item, namespace, ver, patch):
        logger.debug("%s is arelady installed" % item)
        continue
      installStatus = self._vistaPatchInfo.getInstallationStatus(item)
      if self._vistaPatchInfo.isInstallCompleted(installStatus):
        continue
      elif item in patchInfo.optionalDepSet:
        logger.warn("Patch specified in KIDS info file %s is not installed for %s" %
                    (item, patchInfo.installName))
        continue
      else:
        logger.error("dep %s is not installed for %s %s" %
                    (item, patchInfo.installName, patchInfo.kidsFilePath))
        patchInfo.depKIDSBuild.remove(item)
        patchInfo.depKIDSBuild.add(item+" <---")
        return False
    return True
 def _autoRecover(self):
   """
     private method to recover the right cache.dat based on the patch
     installed in the running VistA instance.
   """
   from GitUtils import getCommitInfo
   mExtractConfig = self._config['M_Extract']
   mRepo = mExtractConfig['M_repo']
   mRepoBranch = mExtractConfig.get('M_repo_branch', None)
   if not mRepoBranch:
     mRepoBranch = 'master' # default is the master branch
   commitInfo = getCommitInfo(mRepo, mRepoBranch)
   if not commitInfo:
     logger.error("Can not read commit info from %s branch %s" % (mRepo,
                                                            mRepoBranch))
     return -1
   logger.debug(commitInfo)
   """ convert datetime to VistA T- format """
   from datetime import datetime
   commitDate = datetime.fromtimestamp(int(commitInfo['%ct']))
   timeDiff =  datetime.now() - commitDate
   days = timeDiff.days + 30 # extra 30 days
   logger.debug("Totol dates to query is %s" % days)
   installNames = None
   idx = commitInfo['%s'].find('Install: ')
   if idx >= 0:
     installNames = commitInfo['%s'][len('Install: '):].split(', ')
   logger.info("installNames is %s" % installNames)
   if installNames is None:
     logger.error("Can not find patch installed after")
     return -1
   """ check to see what and when is the last patch installed """
   testClient = self._createTestClient()
   """ make sure cache instance is up and running """
   startCache(self._instance, self._useSudo)
   with testClient:
     patchInfoFetch = VistAPackageInfoFetcher(testClient)
     output = patchInfoFetch.getAllPatchInstalledAfterByTime("T-%s" % days)
   if not output: # must be an error or something, skip backup
     logger.error("Can not get patch installation information from VistA")
     return -1
   logger.debug(output)
   """ logic to check if we need to recover from cache backup data """
   found = False
   for idx in xrange(0,len(output)):
     if output[idx][0] == installNames[-1]:
       found = True
       break
   if found and idx == len(output) - 1:
     """ last patch is the same as last in the commit """
     logger.info("No need to recover.")
     return 0
   if not found or idx < len(output) - 1:
     """ check to see if cache.dat exist in the backup dir"""
     backupConfig = self._config.get('Backup')
     backupDir = backupConfig['backup_dir']
     if not os.path.exists(backupDir):
       logger.error("%s does not exist" % backupDir)
       return -4
     cacheDir = backupConfig['cache_dat_dir']
     origDir = os.path.join(cacheDir, "CACHE.DAT")
     """ identify the exists of backup file in the right format """
     commitHash = commitInfo['%H']
     cacheBackupFile = os.path.join(backupDir,
                                    getCacheBackupNameByHash(commitHash))
     if not os.path.exists(cacheBackupFile):
       logger.error("backup file %s does not exist" % cacheBackupFile)
       return -5
     logger.info("Need to restore from backup data %s" % cacheBackupFile)
     restoreCacheData(self._instance, cacheBackupFile,
                      cacheDir, self._useSudo)
     startCache(self._instance, self._useSudo)
     return 0
   return -1
Пример #8
0
 def _autoRecover(self):
     """
   private method to recover the right cache.dat based on the patch
   installed in the running VistA instance.
 """
     from GitUtils import getCommitInfo
     mExtractConfig = self._config['M_Extract']
     mRepo = mExtractConfig['M_repo']
     mRepoBranch = mExtractConfig.get('M_repo_branch', None)
     if not mRepoBranch:
         mRepoBranch = 'master'  # default is the master branch
     commitInfo = getCommitInfo(mRepo, mRepoBranch)
     if not commitInfo:
         logger.error("Can not read commit info from %s branch %s" %
                      (mRepo, mRepoBranch))
         return -1
     logger.debug(commitInfo)
     """ convert datetime to VistA T- format """
     from datetime import datetime
     commitDate = datetime.fromtimestamp(int(commitInfo['%ct']))
     timeDiff = datetime.now() - commitDate
     days = timeDiff.days + 30  # extra 30 days
     logger.debug("Totol dates to query is %s" % days)
     installNames = None
     idx = commitInfo['%s'].find('Install: ')
     if idx >= 0:
         installNames = commitInfo['%s'][len('Install: '):].split(', ')
     logger.info("installNames is %s" % installNames)
     if installNames is None:
         logger.error("Can not find patch installed after")
         return -1
     """ check to see what and when is the last patch installed """
     testClient = self._createTestClient()
     """ make sure cache instance is up and running """
     startCache(self._instance, self._useSudo)
     with testClient:
         patchInfoFetch = VistAPackageInfoFetcher(testClient)
         output = patchInfoFetch.getAllPatchInstalledAfterByTime("T-%s" %
                                                                 days)
     if not output:  # must be an error or something, skip backup
         logger.error(
             "Can not get patch installation information from VistA")
         return -1
     logger.debug(output)
     """ logic to check if we need to recover from cache backup data """
     found = False
     for idx in xrange(0, len(output)):
         if output[idx][0] == installNames[-1]:
             found = True
             break
     if found and idx == len(output) - 1:
         """ last patch is the same as last in the commit """
         logger.info("No need to recover.")
         return 0
     if not found or idx < len(output) - 1:
         """ check to see if cache.dat exist in the backup dir"""
         backupConfig = self._config.get('Backup')
         backupDir = backupConfig['backup_dir']
         if not os.path.exists(backupDir):
             logger.error("%s does not exist" % backupDir)
             return -4
         cacheDir = backupConfig['cache_dat_dir']
         origDir = os.path.join(cacheDir, "CACHE.DAT")
         """ identify the exists of backup file in the right format """
         commitHash = commitInfo['%H']
         cacheBackupFile = os.path.join(
             backupDir, getCacheBackupNameByHash(commitHash))
         if not os.path.exists(cacheBackupFile):
             logger.error("backup file %s does not exist" % cacheBackupFile)
             return -5
         logger.info("Need to restore from backup data %s" %
                     cacheBackupFile)
         restoreCacheData(self._instance, cacheBackupFile, cacheDir,
                          self._useSudo)
         startCache(self._instance, self._useSudo)
         return 0
     return -1
Пример #9
0
class KIDSPatchSequenceApply(object):
  DEFAULT_VISTA_LOG_FILENAME = "VistAInteraction.log"
  DEFAULT_OUTPUT_FILE_LOG = "PatchAnalyzer.log"
  def __init__(self, testClient, logFileDir):
    self._testClient = testClient
    curTimestamp = getCurrentTimestamp()
    logFileName = "%s.%s" % (self.DEFAULT_VISTA_LOG_FILENAME, curTimestamp)
    self._logFileName = os.path.join(logFileDir,
                             logFileName)
    self._testClient.setLogFile(self._logFileName)
    self._kidsOrderGen = KIDSPatchOrderGenerator()
    self._vistaPatchInfo = VistAPackageInfoFetcher(testClient)
    self._outPatchList = []
    self._patchSet = set()
    initConsoleLogging()
    initFileLogging(os.path.join(logFileDir, self.DEFAULT_OUTPUT_FILE_LOG))

  """ generate the patch order sequence base on input """
  def generateKIDSPatchSequence(self, patchDir, patchesCSV=None):
    kidsOrderGen = self._kidsOrderGen
    patchHistInfo = self._vistaPatchInfo
    patchList = []
    if patchesCSV and os.path.exists(patchCSVFile):
      patchList = kidsOrderGen.generatePatchOrderByCSV(patchDir, patchCSVFile)
    else:
      patchList = kidsOrderGen.generatePatchOrderTopologic(patchDir)
    self._patchSet.update([x.installName for x in patchList])
    for patchInfo in patchList:
      namespace = patchInfo.namespace
      self.__updatePatchInfoPackageName__(patchInfo)
      logger.info("Checking for patch info %s" % patchInfo.installName)
      logger.debug("Checking for patch info %s" % patchInfo)
      """ check to see if the patch is already installed """
      if self.__isPatchInstalled__(patchInfo):
        continue
      if self.__isPatchReadyToInstall__(patchInfo, patchList):
        self._outPatchList.append(patchInfo)
      else:
        logger.error("Can not install patch %s" % patchInfo.installName)
        break
    logger.info("Total patches are %d" % len(self._outPatchList))
    for patchInfo in self._outPatchList:
      logger.info("%s, %s, %s" % (patchInfo.installName,
                                  patchInfo.namespace,
                                  patchInfo.kidsFilePath))

  """ apply the KIDS Patch in order """
  def applyKIDSPatchSequence(self, numOfPatches = 1, restart = True):
    totalPatch = len(self._outPatchList)
    numOfPatch = 1
    if re.match("All", str(numOfPatches), re.IGNORECASE):
      numOfPatch = totalPatch
    else:
      numOfPatch = int(numOfPatches)
    restartCache = False
    taskmanUtil = VistATaskmanUtil()
    """ make sure taskman is running """
    taskmanUtil.startTaskman(self._testClient)
    for index in range(0,min(totalPatch, numOfPatch)):
      patchInfo = self._outPatchList[index]
      """ double check to see if patch is already installed """
      if self.__isPatchInstalled__(patchInfo):
        continue
      if not self.__isPatchReadyToInstall__(patchInfo):
        break
      """ generate Sha1 Sum for patch Info """
      self.generateSha1SumForPatchInfo(patchInfo)
      """ install the KIDS patch """
      result = self.__installKIDSPatch__(patchInfo)
      if not result:
        logger.error("Failed to install patch %s: KIDS %s" %
                      (patchInfo.installName, patchInfo.kidsFilePath))
        return
      else:
        # also need to reload the package patch hist
        self.__reloadPackagePatchHistory__(patchInfo)
        assert self.__isPatchInstalled__(patchInfo)
        restartCache = True
    taskmanUtil.waitTaskmanToCurrent(self._testClient)
    """ restart Cache if needed """
    if restart and restartCache and self._testClient.isCache():
      self.__restartCache__()

  @staticmethod
  def generateSha1SumForPatchInfo(patchInfo):
    if patchInfo.kidsSha1 is None:
      patchInfo.kidsSha1 = generateSha1Sum(patchInfo.kidsFilePath)
    if patchInfo.kidsInfoPath:
      patchInfo.kidsInfoSha1 = generateSha1Sum(patchInfo.kidsInfoPath)
    if patchInfo.otherKidsInfoList:
      for item in patchInfo.otherKidsInfoList:
        if item[0]:
          item[1] = generateSha1Sum(item[0])

  @staticmethod
  def indexInPatchList(installName, patchList):
    for index in range(0,len(patchList)):
      if patchList[index].installName == installName:
        return index
    return -1

#---------------------------------------------------------------------------
# private implementation
#---------------------------------------------------------------------------
  """ get the package patch history and update package name
      for KIDS only build
  """
  def __updatePatchInfoPackageName__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    packageName = patchInfo.package
    namespace = patchInfo.namespace
    verInfo = patchInfo.version
    if namespace:
      patchHistInfo.getPackagePatchHistByNamespace(namespace, verInfo)
      if packageName:
        vistAPackageName = patchHistInfo.getPackageName(namespace)
        if vistAPackageName != packageName:
          logger.error("Different PackageName for %s, %s:%s" %
                       (patchInfo.installName, vistAPackageName, packageName))
          patchInfo.package = vistAPackageName
      else:
        packageName = patchHistInfo.getPackageName(namespace)
        patchInfo.package = packageName

  """ check to see if the patch is already installed """
  def __isPatchInstalled__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    namespace = patchInfo.namespace
    installName = patchInfo.installName
    if patchHistInfo.hasPatchInstalled(patchInfo.installName,
                                       patchInfo.namespace,
                                       patchInfo.version,
                                       patchInfo.patchNo,
                                       patchInfo.seqNo):
      logger.info("%s is already installed" % installName)
      return True
    installStatus = patchHistInfo.getInstallationStatus(installName)
    logger.debug("%s installation status is %d" %
                 (installName, installStatus))
    if patchHistInfo.isInstallCompleted(installStatus):
      logger.info("%s installed completed" % installName)
      return True
    else:
      return False

  """ update package patch history """
  def __reloadPackagePatchHistory__(self, patchInfo):
    patchHistInfo = self._vistaPatchInfo
    installNameList = []
    if patchInfo.isMultiBuilds:
      installNameList = patchInfo.multiBuildsList
    else:
      installNameList.append(patchInfo.installName)
    for installName in installNameList:
      (namespace,ver,patch) = extractInfoFromInstallName(installName)
      if not patchHistInfo.hasNamespace(namespace):
        patchHistInfo.createAllPackageMapping()
      assert patchHistInfo.hasNamespace(namespace)
      packageName = patchHistInfo.getPackageName(namespace)
      patchHistInfo.getPackagePatchHistory(packageName, namespace, ver)

  """ create KIDS Patch Installer by patch Info and install
      the patch specified in patchInfo, return the result
      @return, True indicates on error, False indicates failure
  """
  def __installKIDSPatch__(self, patchInfo):
    installName = patchInfo.installName
    kidsPath = patchInfo.kidsFilePath
    seqNo = patchInfo.seqNo
    logFileName = self._logFileName
    multiBuildsList = patchInfo.multiBuildsList
    kidsInstaller = None
    """ handle patch stored as external link """
    if patchInfo.kidsSha1Path != None:
      kidsSha1 = patchInfo.kidsSha1
      (result, resultPath) = obtainKIDSPatchFileBySha1(kidsPath,
                                                       kidsSha1,
                                                       DEFAULT_CACHE_DIR)
      if not result:
        logger.error("Could not obtain external KIDS patch for %s" % kidsPath)
        return result
      kidsPath = resultPath # set the KIDS Path
    """ get the right KIDS installer """
    associateFiles = patchInfo.associatedInfoFiles
    associatedGlobals = patchInfo.associatedGlobalFiles
    if patchInfo.hasCustomInstaller:
      """ use python imp module to load the source """
      logger.info("using custom installer %s" % patchInfo.customInstallerPath)
      import imp
      installerModule = imp.load_source("KIDS",
                                patchInfo.customInstallerPath)
      from KIDS import CustomInstaller
      kidsInstaller = CustomInstaller(kidsPath, installName,
                                      seqNo, logFileName,
                                      multiBuildsList,
                                      files=associateFiles,
                                      globals=associatedGlobals)

    else:
      kidsInstaller = KIDSInstallerFactory.createKIDSInstaller(
                            kidsPath, installName, seqNo, logFileName,
                            multiBuildsList,
                            files=associateFiles,
                            globals=associatedGlobals)
    logger.info("Applying KIDS Patch %s" % patchInfo)
    assert kidsInstaller
    return kidsInstaller.runInstallation(self._testClient)

  """ restart the cache instance """
  def __restartCache__(self):
    self._testClient.getConnection().terminate()
    logger.info("Wait for 5 seconds")
    time.sleep(5)
    logger.info("Restart CACHE instance")
    instanceName = self._testClient.getInstanceName()
    result = stopCache(instanceName, True)
    if not result:
      result = forceDownCache(instanceName)
      if result:
        startCache(instanceName)
      else:
        logger.error("Can not stop cache instance %s" % instanceName)

  """ check to see if patch is ready to be installed """
  def __isPatchReadyToInstall__(self, patchInfo, patchList = None):
    packageName = patchInfo.package
    ver = patchInfo.version
    patchHist = self._vistaPatchInfo.getPackagePatchHistByName(packageName, ver)
    if not patchHist or not patchHist.hasPatchHistory():
      logger.info("no patch hist for %s, ver: %s" % (packageName, ver))
      return True # if no such an package or hist info, just return True
    """ check patch sequence no to see if it is out of order """
    if patchInfo.seqNo:
      seqNo = patchHist.getLatestSeqNo()
      if patchInfo.seqNo < seqNo:
        logger.error("SeqNo out of order, %s less than latest one %s" %
                      (patchInfo.seqNo), seqNo)
        return False
    # check all the dependencies
    for item in patchInfo.depKIDSPatch:
      if patchList and item in self._patchSet: # we are going to install the dep patch
        logger.info("We are going to install the patch %s" % item)
        """ make sure installation is in the right order """
        itemIndex = self.indexInPatchList(item, patchList)
        patchIndex = self.indexInPatchList(patchInfo.installName, patchList)
        if itemIndex >= patchIndex:
          logger.warn("%s is out of order with %s" % (item, patchInfo))
          return False
        else:
          continue
      (namespace,ver,patch) = extractInfoFromInstallName(item)
      if self._vistaPatchInfo.hasPatchInstalled(item, namespace, ver, patch):
        logger.debug("%s is arelady installed" % item)
        continue
      else:
        logger.error("dep %s is not installed for %s %s" %
                    (item, patchInfo.installName, patchInfo.kidsFilePath))
        return False
    return True