Esempio n. 1
0
    def set_power_state(self, session, target):
        """Run an action modifying this node's power state.

        This call is asynchronous, it will return success as soon as the Bare
        Metal service acknowledges the request.

        :param session: The session to use for making this request.
        :type session: :class:`~keystoneauth1.adapter.Adapter`
        :param target: Target power state, e.g. "rebooting", "power on".
            See the Bare Metal service documentation for available actions.
        """
        session = self._get_session(session)

        if target.startswith("soft "):
            version = '1.27'
        else:
            version = None

        version = utils.pick_microversion(session, version)

        # TODO(dtantsur): server timeout support
        body = {'target': target}

        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'states', 'power')
        response = session.put(
            request.url, json=body,
            headers=request.headers, microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to set power state for bare metal node {node} "
               "to {target}".format(node=self.id, target=target))
        exceptions.raise_from_response(response, error_message=msg)
Esempio n. 2
0
    def set_traits(self, session, traits):
        """Set traits for a node.

        Removes any existing traits and adds the traits passed in to this
        method.

        :param session: The session to use for making this request.
        :param traits: list of traits to add to the node.
        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
        """
        session = self._get_session(session)
        version = utils.pick_microversion(session, '1.37')
        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'traits')

        body = {'traits': traits}

        response = session.put(
            request.url, json=body,
            headers=request.headers, microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to set traits for node {node}"
               .format(node=self.id))
        exceptions.raise_from_response(response, error_message=msg)

        self.traits = traits
Esempio n. 3
0
    def remove_trait(self, session, trait, ignore_missing=True):
        """Remove a trait from a node.

        :param session: The session to use for making this request.
        :param trait: The trait to remove from the node.
        :param bool ignore_missing: When set to ``False``
            :class:`~openstack.exceptions.ResourceNotFound` will be
            raised when the trait does not exist.
            Otherwise, ``False`` is returned.
        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
        """
        session = self._get_session(session)
        version = utils.pick_microversion(session, '1.37')
        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'traits', trait)

        response = session.delete(
            request.url, headers=request.headers, microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        if ignore_missing or response.status_code == 400:
            session.log.debug(
                'Trait %(trait)s was already removed from node %(node)s',
                {'trait': trait, 'node': self.id})
            return False

        msg = ("Failed to remove trait {trait} from bare metal node {node}"
               .format(node=self.id, trait=trait))
        exceptions.raise_from_response(response, error_message=msg)

        self.traits = list(set(self.traits) - {trait})

        return True
Esempio n. 4
0
    def set_power_state(self, session, target):
        """Run an action modifying this node's power state.

        This call is asynchronous, it will return success as soon as the Bare
        Metal service acknowledges the request.

        :param session: The session to use for making this request.
        :type session: :class:`~keystoneauth1.adapter.Adapter`
        :param target: Target power state, e.g. "rebooting", "power on".
            See the Bare Metal service documentation for available actions.
        """
        session = self._get_session(session)

        if target.startswith("soft "):
            version = '1.27'
        else:
            version = None

        version = utils.pick_microversion(session, version)

        # TODO(dtantsur): server timeout support
        body = {'target': target}

        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'states', 'power')
        response = session.put(
            request.url,
            json=body,
            headers=request.headers,
            microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to set power state for bare metal node {node} "
               "to {target}".format(node=self.id, target=target))
        exceptions.raise_from_response(response, error_message=msg)
Esempio n. 5
0
    def patch(self,
              session,
              patch=None,
              prepend_key=True,
              has_body=True,
              retry_on_conflict=None,
              base_path=None,
              reset_interfaces=None):

        if reset_interfaces is not None:
            # The id cannot be dirty for an commit
            self._body._dirty.discard("id")

            # Only try to update if we actually have anything to commit.
            if not patch and not self.requires_commit:
                return self

            if not self.allow_patch:
                raise exceptions.MethodNotSupported(self, "patch")

            session = self._get_session(session)
            microversion = utils.pick_microversion(session, '1.45')
            params = [('reset_interfaces', reset_interfaces)]

            request = self._prepare_request(requires_id=True,
                                            prepend_key=prepend_key,
                                            base_path=base_path,
                                            patch=True,
                                            params=params)

            if patch:
                request.body += self._convert_patch(patch)

            return self._commit(session,
                                request,
                                'PATCH',
                                microversion,
                                has_body=has_body,
                                retry_on_conflict=retry_on_conflict)

        else:
            return super(Node, self).patch(session,
                                           patch=patch,
                                           retry_on_conflict=retry_on_conflict)
Esempio n. 6
0
    def add_trait(self, session, trait):
        """Add a trait to a node.

        :param session: The session to use for making this request.
        :param trait: The trait to add to the node.
        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
        """
        session = self._get_session(session)
        version = utils.pick_microversion(session, '1.37')
        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'traits', trait)
        response = session.put(
            request.url, json=None,
            headers=request.headers, microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to add trait {trait} for node {node}"
               .format(trait=trait, node=self.id))
        exceptions.raise_from_response(response, error_message=msg)

        self.traits = list(set(self.traits or ()) | {trait})
Esempio n. 7
0
    def set_provision_state(self,
                            session,
                            target,
                            config_drive=None,
                            clean_steps=None,
                            rescue_password=None,
                            wait=False,
                            timeout=None):
        """Run an action modifying this node's provision state.

        This call is asynchronous, it will return success as soon as the Bare
        Metal service acknowledges the request.

        :param session: The session to use for making this request.
        :type session: :class:`~keystoneauth1.adapter.Adapter`
        :param target: Provisioning action, e.g. ``active``, ``provide``.
            See the Bare Metal service documentation for available actions.
        :param config_drive: Config drive to pass to the node, only valid
            for ``active` and ``rebuild`` targets. You can use functions from
            :mod:`openstack.baremetal.configdrive` to build it.
        :param clean_steps: Clean steps to execute, only valid for ``clean``
            target.
        :param rescue_password: Password for the rescue operation, only valid
            for ``rescue`` target.
        :param wait: Whether to wait for the target state to be reached.
        :param timeout: Timeout (in seconds) to wait for the target state to be
            reached. If ``None``, wait without timeout.

        :return: This :class:`Node` instance.
        :raises: ValueError if ``config_drive``, ``clean_steps`` or
            ``rescue_password`` are provided with an invalid ``target``.
        """
        session = self._get_session(session)

        if target in _common.PROVISIONING_VERSIONS:
            version = '1.%d' % _common.PROVISIONING_VERSIONS[target]
        else:
            if config_drive and target == 'rebuild':
                version = '1.35'
            else:
                version = None
        version = utils.pick_microversion(session, version)

        body = {'target': target}
        if config_drive:
            if target not in ('active', 'rebuild'):
                raise ValueError('Config drive can only be provided with '
                                 '"active" and "rebuild" targets')
            # Not a typo - ironic accepts "configdrive" (without underscore)
            body['configdrive'] = config_drive

        if clean_steps is not None:
            if target != 'clean':
                raise ValueError('Clean steps can only be provided with '
                                 '"clean" target')
            body['clean_steps'] = clean_steps

        if rescue_password is not None:
            if target != 'rescue':
                raise ValueError('Rescue password can only be provided with '
                                 '"rescue" target')
            body['rescue_password'] = rescue_password

        if wait:
            try:
                expected_state = _common.EXPECTED_STATES[target]
            except KeyError:
                raise ValueError('For target %s the expected state is not '
                                 'known, cannot wait for it' % target)

        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'states', 'provision')
        response = session.put(
            request.url,
            json=body,
            headers=request.headers,
            microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to set provision state for bare metal node {node} "
               "to {target}".format(node=self.id, target=target))
        exceptions.raise_from_response(response, error_message=msg)

        if wait:
            return self.wait_for_provision_state(session,
                                                 expected_state,
                                                 timeout=timeout)
        else:
            return self.fetch(session)
Esempio n. 8
0
    def set_provision_state(self, session, target, config_drive=None,
                            clean_steps=None, rescue_password=None,
                            wait=False, timeout=None):
        """Run an action modifying this node's provision state.

        This call is asynchronous, it will return success as soon as the Bare
        Metal service acknowledges the request.

        :param session: The session to use for making this request.
        :type session: :class:`~keystoneauth1.adapter.Adapter`
        :param target: Provisioning action, e.g. ``active``, ``provide``.
            See the Bare Metal service documentation for available actions.
        :param config_drive: Config drive to pass to the node, only valid
            for ``active` and ``rebuild`` targets. You can use functions from
            :mod:`openstack.baremetal.configdrive` to build it.
        :param clean_steps: Clean steps to execute, only valid for ``clean``
            target.
        :param rescue_password: Password for the rescue operation, only valid
            for ``rescue`` target.
        :param wait: Whether to wait for the target state to be reached.
        :param timeout: Timeout (in seconds) to wait for the target state to be
            reached. If ``None``, wait without timeout.

        :return: This :class:`Node` instance.
        :raises: ValueError if ``config_drive``, ``clean_steps`` or
            ``rescue_password`` are provided with an invalid ``target``.
        """
        session = self._get_session(session)

        version = None
        if target in _common.PROVISIONING_VERSIONS:
            version = '1.%d' % _common.PROVISIONING_VERSIONS[target]

        if config_drive:
            # Some config drive actions require a higher version.
            if isinstance(config_drive, dict):
                version = '1.56'
            elif target == 'rebuild':
                version = '1.35'

        version = utils.pick_microversion(session, version)

        body = {'target': target}
        if config_drive:
            if target not in ('active', 'rebuild'):
                raise ValueError('Config drive can only be provided with '
                                 '"active" and "rebuild" targets')
            # Not a typo - ironic accepts "configdrive" (without underscore)
            body['configdrive'] = config_drive

        if clean_steps is not None:
            if target != 'clean':
                raise ValueError('Clean steps can only be provided with '
                                 '"clean" target')
            body['clean_steps'] = clean_steps

        if rescue_password is not None:
            if target != 'rescue':
                raise ValueError('Rescue password can only be provided with '
                                 '"rescue" target')
            body['rescue_password'] = rescue_password

        if wait:
            try:
                expected_state = _common.EXPECTED_STATES[target]
            except KeyError:
                raise ValueError('For target %s the expected state is not '
                                 'known, cannot wait for it' % target)

        request = self._prepare_request(requires_id=True)
        request.url = utils.urljoin(request.url, 'states', 'provision')
        response = session.put(
            request.url, json=body,
            headers=request.headers, microversion=version,
            retriable_status_codes=_common.RETRIABLE_STATUS_CODES)

        msg = ("Failed to set provision state for bare metal node {node} "
               "to {target}".format(node=self.id, target=target))
        exceptions.raise_from_response(response, error_message=msg)

        if wait:
            return self.wait_for_provision_state(session,
                                                 expected_state,
                                                 timeout=timeout)
        else:
            return self.fetch(session)