def register_subtask(self, subtask): """Register a task as a subtask to this task. :param subtask: objects.Task instance """ if self.status in [hd_fields.TaskStatus.Terminating]: raise errors.OrchestratorError("Cannot add subtask for parent" " marked for termination") if self.statemgr.add_subtask(self.task_id, subtask.task_id): self.add_status_msg(msg="Started subtask %s for action %s" % (str(subtask.get_id()), subtask.action), error=False, ctx=str(self.get_id()), ctx_type='task') self.subtask_id_list.append(subtask.task_id) subtask.parent_task_id = self.task_id subtask.save() else: raise errors.OrchestratorError("Error adding subtask.")
def save(self): """Save this task's current state to the database.""" chk_task = self.statemgr.get_task(self.get_id()) if chk_task in [ hd_fields.TaskStatus.Terminating, hd_fields.TaskStatus.Terminated ]: self.set_status(chk_task.status) self.updated = datetime.utcnow() if not self.statemgr.put_task(self): raise errors.OrchestratorError("Error saving task.")
def _load_site_design(self): """Load the site design from this action's task. The design_ref in the task can be resolved to a set of design documents that reflect the site design to be operated on. Load this design for use by this action. """ design_status, site_design = self.orchestrator.get_effective_site( self.task.design_ref) if design_status is None or design_status.status == hd_fields.ActionResult.Failure: raise errors.OrchestratorError("Site design failed load.") return site_design
def execute_task(self, task_id): if self.state_manager is None: raise errors.OrchestratorError("Cannot execute task without" \ " initialized state manager") task = self.state_manager.get_task(task_id) if task is None: raise errors.OrchestratorError("Task %s not found." % (task_id)) design_id = task.design_id task_site = task.site # Just for testing now, need to implement with enabled_drivers # logic if task.action == hd_fields.OrchestratorAction.Noop: self.task_field_update(task_id, status=hd_fields.TaskStatus.Running) driver_task = self.create_task(tasks.DriverTask, design_id=0, action=hd_fields.OrchestratorAction.Noop, parent_task_id=task.get_id()) driver = drivers.ProviderDriver(state_manager=self.state_manager, orchestrator=self) driver.execute_task(driver_task.get_id()) driver_task = self.state_manager.get_task(driver_task.get_id()) self.task_field_update(task_id, status=driver_task.get_status()) return elif task.action == hd_fields.OrchestratorAction.ValidateDesign: self.task_field_update(task_id, status=hd_fields.TaskStatus.Running) try: site_design = self.get_effective_site(design_id) self.task_field_update(task_id, result=hd_fields.ActionResult.Success) except: self.task_field_update(task_id, result=hd_fields.ActionResult.Failure) self.task_field_update(task_id, status=hd_fields.TaskStatus.Complete) return elif task.action == hd_fields.OrchestratorAction.VerifySite: self.task_field_update(task_id, status=hd_fields.TaskStatus.Running) node_driver = self.enabled_drivers['node'] if node_driver is not None: node_driver_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, action=hd_fields.OrchestratorAction.ValidateNodeServices) node_driver.execute_task(node_driver_task.get_id()) node_driver_task = self.state_manager.get_task(node_driver_task.get_id()) self.task_field_update(task_id, status=hd_fields.TaskStatus.Complete, result=node_driver_task.get_result()) return elif task.action == hd_fields.OrchestratorAction.PrepareSite: driver = self.enabled_drivers['node'] if driver is None: self.task_field_update(task_id, status=hd_fields.TaskStatus.Errored, result=hd_fields.ActionResult.Failure) return task_scope = { 'site': task.site } driver_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, task_scope=task_scope, action=hd_fields.OrchestratorAction.CreateNetworkTemplate) self.logger.info("Starting node driver task %s to create network templates" % (driver_task.get_id())) driver.execute_task(driver_task.get_id()) driver_task = self.state_manager.get_task(driver_task.get_id()) self.logger.info("Node driver task %s complete" % (driver_task.get_id())) self.task_field_update(task_id, status=hd_fields.TaskStatus.Complete, result=driver_task.get_result()) return elif task.action == hd_fields.OrchestratorAction.VerifyNode: self.task_field_update(task_id, status=hd_fields.TaskStatus.Running) oob_driver = self.enabled_drivers['oob'] if oob_driver is None: self.task_field_update(task_id, status=hd_fields.TaskStatus.Errored, result=hd_fields.ActionResult.Failure, result_detail={'detail': 'Error: No oob driver configured', 'retry': False}) return site_design = self.get_effective_site(design_id) node_filter = task.node_filter target_nodes = self.process_node_filter(node_filter, site_design) target_names = [x.get_name() for x in target_nodes] task_scope = {'site' : task_site, 'node_names' : target_names} oob_driver_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, action=hd_fields.OrchestratorAction.InterrogateOob, task_scope=task_scope) oob_driver.execute_task(oob_driver_task.get_id()) oob_driver_task = self.state_manager.get_task(oob_driver_task.get_id()) self.task_field_update(task_id, status=hd_fields.TaskStatus.Complete, result=oob_driver_task.get_result()) return elif task.action == hd_fields.OrchestratorAction.PrepareNode: failed = worked = False self.task_field_update(task_id, status=hd_fields.TaskStatus.Running) oob_driver = self.enabled_drivers['oob'] if oob_driver is None: self.task_field_update(task_id, status=hd_fields.TaskStatus.Errored, result=hd_fields.ActionResult.Failure, result_detail={'detail': 'Error: No oob driver configured', 'retry': False}) return node_driver = self.enabled_drivers['node'] if node_driver is None: self.task_field_update(task_id, status=hd_fields.TaskStatus.Errored, result=hd_fields.ActionResult.Failure, result_detail={'detail': 'Error: No node driver configured', 'retry': False}) return site_design = self.get_effective_site(design_id) node_filter = task.node_filter target_nodes = self.process_node_filter(node_filter, site_design) target_names = [x.get_name() for x in target_nodes] task_scope = {'site' : task_site, 'node_names' : target_names} setboot_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, action=hd_fields.OrchestratorAction.SetNodeBoot, task_scope=task_scope) self.logger.info("Starting OOB driver task %s to set PXE boot" % (setboot_task.get_id())) oob_driver.execute_task(setboot_task.get_id()) self.logger.info("OOB driver task %s complete" % (setboot_task.get_id())) setboot_task = self.state_manager.get_task(setboot_task.get_id()) if setboot_task.get_result() == hd_fields.ActionResult.Success: worked = True elif setboot_task.get_result() == hd_fields.ActionResult.PartialSuccess: worked = failed = True elif setboot_task.get_result() == hd_fields.ActionResult.Failure: failed = True cycle_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, action=hd_fields.OrchestratorAction.PowerCycleNode, task_scope=task_scope) self.logger.info("Starting OOB driver task %s to power cycle nodes" % (cycle_task.get_id())) oob_driver.execute_task(cycle_task.get_id()) self.logger.info("OOB driver task %s complete" % (cycle_task.get_id())) cycle_task = self.state_manager.get_task(cycle_task.get_id()) if cycle_task.get_result() == hd_fields.ActionResult.Success: worked = True elif cycle_task.get_result() == hd_fields.ActionResult.PartialSuccess: worked = failed = True elif cycle_task.get_result() == hd_fields.ActionResult.Failure: failed = True # IdentifyNode success will take some time after PowerCycleNode finishes # Retry the operation a few times if it fails before considering it a final failure # Each attempt is a new task which might make the final task tree a bit confusing node_identify_attempts = 0 while True: node_identify_task = self.create_task(tasks.DriverTask, parent_task_id=task.get_id(), design_id=design_id, action=hd_fields.OrchestratorAction.IdentifyNode, task_scope=task_scope) self.logger.info("Starting node driver task %s to identify node - attempt %s" % (node_identify_task.get_id(), node_identify_attempts+1)) node_driver.execute_task(node_identify_task.get_id()) node_identify_attempts = node_identify_attempts + 1 node_identify_task = self.state_manager.get_task(node_identify_task.get_id()) if node_identify_task.get_result() == hd_fields.ActionResult.Success: worked = True break elif node_identify_task.get_result() in [hd_fields.ActionResult.PartialSuccess, hd_fields.ActionResult.Failure]: # TODO This threshold should be a configurable default and tunable by task API if node_identify_attempts > 2: failed = True break time.sleep(5 * 60) final_result = None if worked and failed: final_result = hd_fields.ActionResult.PartialSuccess elif worked: final_result = hd_fields.ActionResult.Success else: final_result = hd_fields.ActionResult.Failure self.task_field_update(task_id, status=hd_fields.TaskStatus.Complete, result=final_result) return else: raise errors.OrchestratorError("Action %s not supported" % (task.action))
def register_subtask(self, subtask_id): if self.terminate: raise errors.OrchestratorError("Cannot add subtask for parent" \ " marked for termination") self.subtasks.append(subtask_id)
def render_route_domains(self, site_design): """Update site_design with static routes for route domains. site_design will be updated in place with explicit static routes for all routedomain members :param site_design: a populated instance of objects.SiteDesign """ self.logger.info("Rendering routes for network route domains.") if 'networks' in site_design: if site_design.networks is not None: routedomains = dict() for n in site_design.networks: if 'routedomain' in n: if n.routedomain is not None: if n.routedomain not in routedomains: self.logger.debug( "Adding routedomain %s to render " "map." % n.routedomain) routedomains[n.routedomain] = list() routedomains[n.routedomain].append(n) else: msg = "Invalid network model: {}. Cannot find "\ "routedomain field in network: {}.".format( n.name, n.url) raise errors.OrchestratorError(msg) for rd, nl in routedomains.items(): rd_cidrs = [n.cidr for n in nl] self.logger.debug("Target CIDRs for routedomain " "%s: %s" % (rd, ','.join(rd_cidrs))) for n in site_design.networks: gw = None metric = None if 'routes' in n and n.routes is not None: for r in n.routes: if 'routedomain' in r and r.get( 'routedomain', None) == rd: gw = r.get('gateway') metric = r.get('metric') self.logger.debug( "Use gateway %s for routedomain %s " "on network %s." % (gw, rd, n.get_name())) break if gw is not None and metric is not None: for cidr in rd_cidrs: if cidr != n.cidr: n.routes.append( dict(subnet=cidr, gateway=gw, metric=metric)) else: msg = "Invalid network model: {}. Cannot find " \ "routes field in network with routedomain: " \ "{}.".format(n.name, n.url) self.logger.error(msg) else: msg = "Invalid site_design model. Cannot find networks field in " \ "site_design." self.logger.error(msg)