def wait_for_provision_state(baremetal_client,
                             node_uuid,
                             provision_state,
                             loops=10,
                             sleep=1):
    """Wait for a given Provisioning state in Ironic

    Updating the provisioning state is an async operation, we
    need to wait for it to be completed.

    :param baremetal_client: Instance of Ironic client
    :type  baremetal_client: ironicclient.v1.client.Client

    :param node_uuid: The Ironic node UUID
    :type  node_uuid: str

    :param provision_state: The provisioning state name to wait for
    :type  provision_state: str

    :param loops: How many times to loop
    :type loops: int

    :param sleep: How long to sleep between loops
    :type sleep: int

    :raises exceptions.StateTransitionFailed: if node.last_error is set
    """

    for _l in range(0, loops):

        node = baremetal_client.node.get(node_uuid)

        if node is None:
            # The node can't be found in ironic, so we don't need to wait for
            # the provision state
            return
        if node.provision_state == provision_state:
            return

        # node.last_error should be None after any successful operation
        if node.last_error:
            raise exceptions.StateTransitionFailed(
                _("Error transitioning node %(uuid)s to provision state "
                  "%(state)s: %(error)s. Now in state %(actual)s.") % {
                      'uuid': node_uuid,
                      'state': provision_state,
                      'error': node.last_error,
                      'actual': node.provision_state
                  })

        time.sleep(sleep)

    raise exceptions.Timeout(
        _("Node %(uuid)s did not reach provision state %(state)s. "
          "Now in state %(actual)s.") % {
              'uuid': node_uuid,
              'state': provision_state,
              'actual': node.provision_state
          })
    def _wait_for_drac_config_jobs(self, nodes):
        for node in nodes:
            print("Waiting for DRAC config jobs to finish on node {0}".format(
                node.uuid))

            for _r in range(self.loops):
                resp = self.bm_client.node.vendor_passthru(
                    node.uuid, 'list_unfinished_jobs', http_method='GET')
                if not resp.unfinished_jobs:
                    break

                time.sleep(self.sleep_time)
            else:
                msg = ("Timed out waiting for DRAC config jobs on node {0}".
                       format(node.uuid))
                raise exceptions.Timeout(msg)
Exemple #3
0
    def take_action(self, parsed_args):

        self.log.debug("take_action(%s)" % parsed_args)

        queue_name = str(uuid.uuid4())
        bm_client = self.app.client_manager.baremetal

        for node in bm_client.node.list(maintenance=False):
            # NOTE(bnemec): Ironic won't let us update the node while the
            # power_state is transitioning.
            # Make sure we have the current node state, and not a cached one
            # from the list call above, which may have happened minutes ago.
            node_detail = bm_client.node.get(node.uuid)
            if node_detail.power_state is None:
                self.log.warning(
                    'Node %s power state is in transition. '
                    'Waiting up to %d seconds for it to '
                    'complete.', node_detail.uuid,
                    self.loops * self.sleep_time)
                for _r in range(self.loops):
                    time.sleep(self.sleep_time)
                    node_detail = bm_client.node.get(node.uuid)
                    if node_detail.power_state is not None:
                        break
                else:
                    msg = ('Timed out waiting for node %s power state.' %
                           node.uuid)
                    raise exceptions.Timeout(msg)

            baremetal.configure(
                self.app.client_manager,
                node_uuids=[node.uuid],
                queue_name=queue_name,
                kernel_name=parsed_args.deploy_kernel,
                ramdisk_name=parsed_args.deploy_ramdisk,
                root_device=parsed_args.root_device,
                root_device_minimum_size=parsed_args.root_device_minimum_size,
                overwrite_root_device_hints=(
                    parsed_args.overwrite_root_device_hints))
    def take_action(self, parsed_args):

        self.log.debug("take_action(%s)" % parsed_args)
        bm_client = self.app.client_manager.baremetal

        image_client = self.app.client_manager.image

        try:
            kernel_id = osc_utils.find_resource(image_client.images,
                                                parsed_args.deploy_kernel).id
        except AttributeError:
            self.log.error("Please make sure that an image named \"%s\" exists"
                           " in Glance and is the only image with this name." %
                           parsed_args.deploy_ramdisk)
            return

        try:
            ramdisk_id = osc_utils.find_resource(image_client.images,
                                                 parsed_args.deploy_ramdisk).id
        except AttributeError:
            self.log.error("Please make sure that an image named \"%s\" exists"
                           " in Glance and is the only image with this name." %
                           parsed_args.deploy_ramdisk)
            return

        self.log.debug("Using kernel ID: {0} and ramdisk ID: {1}".format(
            kernel_id, ramdisk_id))

        for node in bm_client.node.list(maintenance=False):
            # NOTE(bnemec): Ironic won't let us update the node while the
            # power_state is transitioning.
            # Make sure we have the current node state, and not a cached one
            # from the list call above, which may have happened minutes ago.
            node_detail = bm_client.node.get(node.uuid)
            if node_detail.power_state is None:
                self.log.warning(
                    'Node %s power state is in transition. '
                    'Waiting up to %d seconds for it to '
                    'complete.', node_detail.uuid,
                    self.loops * self.sleep_time)
                for _r in range(self.loops):
                    time.sleep(self.sleep_time)
                    node_detail = bm_client.node.get(node.uuid)
                    if node_detail.power_state is not None:
                        break
                else:
                    msg = ('Timed out waiting for node %s power state.' %
                           node.uuid)
                    raise exceptions.Timeout(msg)

            # Get the full node info
            capabilities = node_detail.properties.get('capabilities', None)

            # Only update capabilities to add boot_option if it doesn't exist.
            if capabilities:
                if 'boot_option' not in capabilities:
                    capabilities = "boot_option:local,%s" % capabilities
            else:
                capabilities = "boot_option:local"

            self.log.debug("Configuring boot for Node {0}".format(node.uuid))

            bm_client.node.update(node.uuid, [
                {
                    'op': 'add',
                    'path': '/properties/capabilities',
                    'value': capabilities,
                },
                {
                    'op': 'add',
                    'path': '/driver_info/deploy_ramdisk',
                    'value': ramdisk_id,
                },
                {
                    'op': 'add',
                    'path': '/driver_info/deploy_kernel',
                    'value': kernel_id,
                },
            ])

            self._apply_root_device_strategy(
                node_detail, parsed_args.root_device,
                parsed_args.root_device_minimum_size,
                parsed_args.overwrite_root_device_hints)