예제 #1
0
def copyApp(fromdir, to, appDir=None):
    "Private: Copy application files to the other blades"

    logdir = os.getenv("ASP_LOGDIR")
    if logdir:
        logFileName = logdir + os.sep + 'appdeploy.log'
    else:
        logFileName = 'appdeploy.log'

    try:
        fout = file(logFileName, 'w+')
    except:  # lack of debug logging should not be fatal
        fout = None

    exp = pexpect.spawn('bash')
    exp.delaybeforesend = 0  # to make sessions a lot faster
    i = exp.expect([pexpect.TIMEOUT, '[$#>]'], timeout=10)
    if i == 0:  # timeout
        raise DeployError("Could not start bash session")
    exp.setwinsize(200, 1024)

    exp.logfile = fout
    exp.sendline("export PS1='_expectpromptlocal_'")
    pshell = psh.Psh(exp, '_expectpromptlocal_')

    # the "to" argument can be a string containing the node name, slot number or IP address, OR it can be an AmfNodeEntity
    if type(to) is type(""):
        node = clusterinfo.ci.nodes[to]
    else:
        node = to

    try:
        fout2 = file(logFileName + "1", 'w+')
    except:
        fout2 = None

    retries = 0
    while retries < 4:
        retries += 1
        tgtexp = pxssh.pxssh()

        tgtexp.logfile = fout2
        log.info("Connecting to %s user %s pw %s" %
                 (node.localIp, node.localUser, node.localPasswd))
        try:
            result = tgtexp.login(node.localIp,
                                  node.localUser,
                                  node.localPasswd,
                                  login_timeout=30)
            retries = 10000
        except pxssh.ExceptionPxssh, e:  # Could not synchronize with original prompt
            if retries > 3:
                raise DeployError("Cannot connect to %s exception: %s" %
                                  (node.localIp, str(e)))
def copyApp(fromdir,to,appDir=None):
  "Private: Copy application files to the other blades"

  logdir = os.getenv("ASP_LOGDIR")
  if logdir:
    logFileName = logdir + os.sep + 'appdeploy.log'
  else:
    logFileName = 'appdeploy.log'

  try:
    fout = file(logFileName, 'w+')
  except:  # lack of debug logging should not be fatal
    fout = None

  exp = pexpect.spawn('bash')
  exp.delaybeforesend = 0 # to make sessions a lot faster
  i = exp.expect([pexpect.TIMEOUT, '[$#>]'], timeout=10)
  if i==0: # timeout
        raise DeployError("Could not start bash session")
  exp.setwinsize(200, 1024)

  exp.logfile = fout
  exp.sendline("export PS1='_expectpromptlocal_'")  
  pshell = psh.Psh(exp, '_expectpromptlocal_')

  # the "to" argument can be a string containing the node name, slot number or IP address, OR it can be an AmfNodeEntity
  if type(to) is type(""):
    node = clusterinfo.ci.nodes[to]
  else:
    node = to

  try:
    fout2 = file(logFileName + "1", 'w+')
  except:
    fout2 = None

  retries = 0
  while retries<4:
    retries += 1
    tgtexp = pxssh.pxssh()
      
    tgtexp.logfile = fout2
    log.info("Connecting to %s user %s pw %s" % (node.localIp, node.localUser, node.localPasswd))
    try:
      result = tgtexp.login(node.localIp, node.localUser, node.localPasswd, login_timeout=30)
      retries = 10000
    except pxssh.ExceptionPxssh,e: # Could not synchronize with original prompt
      if retries>3: raise DeployError("Cannot connect to %s exception: %s" % (node.localIp,str(e)))
    def ReloadApps(self):
        """Reload the entire DB from archive files in the AppArchiveDir"""
        self.apps = {}  # Clear the old objects

        # Find all .tgz files in the app dir and process them
        for base, dirs, files in os.walk(self.appdir):

            # Blow away all the temporary directories
            for d in dirs:
                os.removedirs(base + os.sep + d)

            for f in files:
                (noext, ext) = os.path.splitext(f)
                if ext == ".tgz" or ext == ".tar.gz":
                    try:
                        self.NewAppFile(base + os.sep + f)
                    except Error, e:  # Bad file
                        log.info("Bad archive [%s] error: [%s]" % (base + os.sep + f, str(e)))
                        os.remove(base + os.sep + f)
                    except xml2dict.BadConfigFile, e:
                        log.info("Bad archive [%s] error: [%s]" % (base + os.sep + f, str(e)))
def createModel(fromdir,cfg,tgtblades,specifiedNodes):
  ci = clusterinfo.ci

  notes = []
  errors = []
  # Create the SAF AMF entities corresponding to this application
  for (appname,appcfg) in cfg.items():

    integration = appcfg.get("GuiIntegration",None)
    if integration:
      install = integration.install
      exec install in globals(), {}

    basename = appcfg.get("deployPrefix",appname) # Deploy preferentially with the deployment prefix, but use the app name if there isn't one
    nameIndex = 0
    for existingSg in ci.sgList:
      if basename + "SGi" in existingSg.name:
        i = int(existingSg.name.replace(basename + "SGi",""))
        if i >= nameIndex: nameIndex = i+1
    if nameIndex:
      notes.append("Name %s exists, so appending the numeral %d." % (basename,nameIndex))
 
    compNames = appcfg.programNames.values()
    nodes = []

    ninst = 1
    if appcfg.modifiers.has_key('instancesPerNode'):
      ninst = int(appcfg.modifiers.instancesPerNode)
      tgtblades = tgtblades * ninst
      
    if specifiedNodes:
      numNodes = len(tgtblades) # We deploy to where the user selected
    else:
      numNodes = min(appcfg.totalNodes*ninst,len(tgtblades)) # If no blades chosen, we just deploy the recommended instance(s)

    if appcfg.redundancyModel in ["2N", "2n", "2"]:
      log.info("%s uses 2N redundancy model" % basename)
      appcfg.rModel = "2N"
      appcfg.activePerSg = 1
      appcfg.standbyPerSg = 1
      nodesPerSg = 2
    elif appcfg.redundancyModel.lower() == "custom":
      appcfg.rModel = "custom"
      nodesPerSg = appcfg.totalNodes
      appcfg.setdefault("activePerSg", nodesPerSg)
      appcfg.setdefault("standbyPerSg", 0)      
    else:
      log.info("%s uses N+M redundancy model" % basename)
      regexp = r'\s*(?P<active>\d+)\s*\+\s*(?P<standby>\d+)\s*'
      m = re.match(regexp, appcfg.redundancyModel)
      d = m.groupdict()

      appcfg.rModel = "M+N"
# This configures the SG exactly as suggested in the appcfg.xml
#      appcfg.activePerSg = int(d['active'])
#      appcfg.standbyPerSg = int(d['standby'])
#      nodesPerSg = appcfg.activePerSg + appcfg.standbyPerSg

      try:  # If the # active is not a number then that's ok (see below)
        active = int(d['active'])
      except:
        active = None

      standby = int(d['standby'])

      if numNodes<3 and standby>0:  # If there's 1 or 2 nodes, use 1+1
        appcfg.activePerSg  = 1
        appcfg.standbyPerSg = 1
      elif active is None: # (N+1) Keep the specified # of standby and let active grow.
        appcfg.standbyPerSg = standby
        appcfg.activePerSg  = max(1,numNodes-standby) # But at least 1 active of course
      else:  # (3+1) Make sure there's at least 1 standby, otherwise keep the ratio intact
        sbratio = float(standby)/(float(active)+float(standby))
        nstandby = int(numNodes*sbratio)
        if nstandby < 1: nstandby = 1
        appcfg.standbyPerSg = nstandby
        appcfg.activePerSg  = max(1,numNodes-standby) # But at least 1 active of course

    # Assign each node to an SG.
    if 0:  # This logic generates multiple SGs if more nodes are passed than numNodes
      nodeCnt = 0
      while nodeCnt < numNodes:
        sgNodes = []     
        for perSg in range(0,nodesPerSg):
          if nodeCnt >= numNodes: break
          sgNodes.append(tgtblades[nodeCnt])
          nodeCnt +=1
        nodes.append(sgNodes) # Make a list of sgs which is therefore a list of lists of nodes
    else: # Instead, I'm just going to create a bigger SG
        nodes.append(tgtblades[0:numNodes])

    log.debug("Nodes: %s" % str([[x.name for x in y] for y in nodes]))
    entities = aspAmfCreate.CreateApp(compNames,nodes,appcfg,appcfg.get('work', None),basename, {},nameIndex)

    return (entities,(errors,notes))
    def ConnectToServiceGroups(self, cinfo=None):
        """ Iterate through the clusterinfo service groups and connect them up to apps and appfiles
    """

        if cinfo is None:
            cinfo = ci

        # Clear out the old connections
        for e in self.entities.values():
            e.sg = []

        log.info("Connecting App Database to existing Service Groups")
        for sg in cinfo.sgList:
            if sg.associatedData:
                log.info("Service Group %s, data: %s" % (sg.name, sg.associatedData))
                try:
                    [appName, appVer] = sg.associatedData.split()
                except ValueError:  # The data isn't in the right format, so it is probably not for me
                    log.info(
                        "Improperly formatted entity associated data [%s].  Expecting 'appName version'."
                        % (sg.associatedData)
                    )
                    continue
                    # appName = None # skip the rest of the logic for this SG

                app = self.entities.get(appName, None)
                if app:
                    log.info("App %s found" % (app.name))
                    app.sg.append(sg)
                    appFile = app.version.get(appVer, None)
                    sg.app = app
                    if appFile:
                        log.info("AppFile %s found" % (appFile.name))
                        appFile.sg.append(sg)
                        sg.appVer = appFile
            else:
                log.info("Service Group %s, no app data" % (sg.name))
예제 #6
0
def createModel(fromdir, cfg, tgtblades, specifiedNodes):
    ci = clusterinfo.ci

    notes = []
    errors = []
    # Create the SAF AMF entities corresponding to this application
    for (appname, appcfg) in cfg.items():

        integration = appcfg.get("GuiIntegration", None)
        if integration:
            install = integration.install
            exec install in globals(), {}

        basename = appcfg.get(
            "deployPrefix", appname
        )  # Deploy preferentially with the deployment prefix, but use the app name if there isn't one
        nameIndex = 0
        for existingSg in ci.sgList:
            if basename + "SGi" in existingSg.name:
                i = int(existingSg.name.replace(basename + "SGi", ""))
                if i >= nameIndex: nameIndex = i + 1
        if nameIndex:
            notes.append("Name %s exists, so appending the numeral %d." %
                         (basename, nameIndex))

        compNames = appcfg.programNames.values()
        nodes = []

        ninst = 1
        if appcfg.modifiers.has_key('instancesPerNode'):
            ninst = int(appcfg.modifiers.instancesPerNode)
            tgtblades = tgtblades * ninst

        if specifiedNodes:
            numNodes = len(tgtblades)  # We deploy to where the user selected
        else:
            numNodes = min(
                appcfg.totalNodes * ninst, len(tgtblades)
            )  # If no blades chosen, we just deploy the recommended instance(s)

        if appcfg.redundancyModel in ["2N", "2n", "2"]:
            log.info("%s uses 2N redundancy model" % basename)
            appcfg.rModel = "2N"
            appcfg.activePerSg = 1
            appcfg.standbyPerSg = 1
            nodesPerSg = 2
        elif appcfg.redundancyModel.lower() == "custom":
            appcfg.rModel = "custom"
            nodesPerSg = appcfg.totalNodes
            appcfg.setdefault("activePerSg", nodesPerSg)
            appcfg.setdefault("standbyPerSg", 0)
        else:
            log.info("%s uses N+M redundancy model" % basename)
            regexp = r'\s*(?P<active>\d+)\s*\+\s*(?P<standby>\d+)\s*'
            m = re.match(regexp, appcfg.redundancyModel)
            d = m.groupdict()

            appcfg.rModel = "M+N"
            # This configures the SG exactly as suggested in the appcfg.xml
            #      appcfg.activePerSg = int(d['active'])
            #      appcfg.standbyPerSg = int(d['standby'])
            #      nodesPerSg = appcfg.activePerSg + appcfg.standbyPerSg

            try:  # If the # active is not a number then that's ok (see below)
                active = int(d['active'])
            except:
                active = None

            standby = int(d['standby'])

            if numNodes < 3 and standby > 0:  # If there's 1 or 2 nodes, use 1+1
                appcfg.activePerSg = 1
                appcfg.standbyPerSg = 1
            elif active is None:  # (N+1) Keep the specified # of standby and let active grow.
                appcfg.standbyPerSg = standby
                appcfg.activePerSg = max(
                    1, numNodes - standby)  # But at least 1 active of course
            else:  # (3+1) Make sure there's at least 1 standby, otherwise keep the ratio intact
                sbratio = float(standby) / (float(active) + float(standby))
                nstandby = int(numNodes * sbratio)
                if nstandby < 1: nstandby = 1
                appcfg.standbyPerSg = nstandby
                appcfg.activePerSg = max(
                    1, numNodes - standby)  # But at least 1 active of course

        # Assign each node to an SG.
        if 0:  # This logic generates multiple SGs if more nodes are passed than numNodes
            nodeCnt = 0
            while nodeCnt < numNodes:
                sgNodes = []
                for perSg in range(0, nodesPerSg):
                    if nodeCnt >= numNodes: break
                    sgNodes.append(tgtblades[nodeCnt])
                    nodeCnt += 1
                nodes.append(
                    sgNodes
                )  # Make a list of sgs which is therefore a list of lists of nodes
        else:  # Instead, I'm just going to create a bigger SG
            nodes.append(tgtblades[0:numNodes])

        log.debug("Nodes: %s" % str([[x.name for x in y] for y in nodes]))
        entities = aspAmfCreate.CreateApp(compNames, nodes, appcfg,
                                          appcfg.get('work', None), basename,
                                          {}, nameIndex)

        return (entities, (errors, notes))