class IAReqNodeEvac(IARequestBase): """A node evacuation request. """ # pylint: disable=E1101 MODE = constants.IALLOCATOR_MODE_NODE_EVAC REQ_PARAMS = [ ("instances", _STRING_LIST), ("evac_mode", ht.TEvacMode), ("ignore_soft_errors", ht.TMaybe(ht.TBool)), ] REQ_RESULT = _NEVAC_RESULT def GetRequest(self, cfg): """Get data for node-evacuate requests. """ return { "instances": self.instances, "evac_mode": self.evac_mode, } def GetExtraParams(self): """Get extra iallocator command line options for node-evacuate requests. """ if self.ignore_soft_errors: return {"ignore-soft-errors": None} else: return {}
def testOr(self): fn = ht.TMaybe(ht.TAnd(ht.TString, ht.TIsLength(5))) self.assertTrue(fn("12345")) self.assertTrue(fn(None)) self.assertFalse(fn(1)) self.assertFalse(fn("")) self.assertFalse(fn("abc"))
def BuildJobDepCheck(relative): """Builds check for job dependencies (L{DEPEND_ATTR}). @type relative: bool @param relative: Whether to accept relative job IDs (negative) @rtype: callable """ if relative: job_id = ht.TOr(ht.TJobId, ht.TRelativeJobId) else: job_id = ht.TJobId job_dep = \ ht.TAnd(ht.TOr(ht.TListOf(ht.TAny), ht.TTuple), ht.TIsLength(2), ht.TItems([job_id, ht.TListOf(ht.TElemOf(constants.JOBS_FINALIZED))])) return ht.TMaybe(ht.TListOf(job_dep))
class IAReqInstanceAlloc(IARequestBase): """An instance allocation request. """ # pylint: disable=E1101 MODE = constants.IALLOCATOR_MODE_ALLOC REQ_PARAMS = [ _INST_NAME, ("memory", ht.TNonNegativeInt), ("spindle_use", ht.TNonNegativeInt), ("disks", ht.TListOf(ht.TDict)), ("disk_template", ht.TString), ("group_name", ht.TMaybe(ht.TNonEmptyString)), ("os", ht.TString), ("tags", _STRING_LIST), ("nics", ht.TListOf(ht.TDict)), ("vcpus", ht.TInt), ("hypervisor", ht.TString), ("node_whitelist", ht.TMaybeListOf(ht.TNonEmptyString)), ] REQ_RESULT = ht.TList def RequiredNodes(self): """Calculates the required nodes based on the disk_template. """ if self.disk_template in constants.DTS_INT_MIRROR: return 2 else: return 1 def GetRequest(self, cfg): """Requests a new instance. The checks for the completeness of the opcode must have already been done. """ for d in self.disks: d[constants.IDISK_TYPE] = self.disk_template disk_space = gmi.ComputeDiskSize(self.disks) return { "name": self.name, "disk_template": self.disk_template, "group_name": self.group_name, "tags": self.tags, "os": self.os, "vcpus": self.vcpus, "memory": self.memory, "spindle_use": self.spindle_use, "disks": self.disks, "disk_space_total": disk_space, "nics": self.nics, "required_nodes": self.RequiredNodes(), "hypervisor": self.hypervisor, } def ValidateResult(self, ia, result): """Validates an single instance allocation request. """ IARequestBase.ValidateResult(self, ia, result) if ia.success and len(result) != self.RequiredNodes(): raise errors.ResultValidationError( "iallocator returned invalid number" " of nodes (%s), required %s" % (len(result), self.RequiredNodes()))