Example #1
0
    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.")
Example #2
0
    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.")
Example #3
0
    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
Example #4
0
    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))
Example #5
0
 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)
Example #6
0
    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)