示例#1
0
    def delete(self):
        context = api.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:allocation:delete', cdict, cdict)

        rpc_node = api_utils.get_rpc_node_with_suffix(self.parent_node_ident)
        allocations = objects.Allocation.list(
            api.request.context, filters={'node_uuid': rpc_node.uuid})

        try:
            rpc_allocation = allocations[0]
        except IndexError:
            raise exception.AllocationNotFound(
                _("Allocation for node %s was not found") %
                self.parent_node_ident)

        notify.emit_start_notification(context,
                                       rpc_allocation,
                                       'delete',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context,
                                              rpc_allocation,
                                              'delete',
                                              node_uuid=rpc_node.uuid):
            topic = api.request.rpcapi.get_random_topic()
            api.request.rpcapi.destroy_allocation(context, rpc_allocation,
                                                  topic)
        notify.emit_end_notification(context,
                                     rpc_allocation,
                                     'delete',
                                     node_uuid=rpc_node.uuid)
示例#2
0
    def delete(self):
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:allocation:delete', cdict, cdict)

        rpc_node = api_utils.get_rpc_node_with_suffix(self.parent_node_ident)
        allocations = objects.Allocation.list(
            pecan.request.context,
            filters={'node_uuid': rpc_node.uuid})

        try:
            rpc_allocation = allocations[0]
        except IndexError:
            raise exception.AllocationNotFound(
                _("Allocation for node %s was not found") %
                self.parent_node_ident)

        notify.emit_start_notification(context, rpc_allocation, 'delete',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context, rpc_allocation,
                                              'delete',
                                              node_uuid=rpc_node.uuid):
            topic = pecan.request.rpcapi.get_random_topic()
            pecan.request.rpcapi.destroy_allocation(context, rpc_allocation,
                                                    topic)
        notify.emit_end_notification(context, rpc_allocation, 'delete',
                                     node_uuid=rpc_node.uuid)
示例#3
0
    def post(self, node_ident, callback_url, agent_version=None,
             agent_token=None):
        """Process a heartbeat from the deploy ramdisk.

        :param node_ident: the UUID or logical name of a node.
        :param callback_url: the URL to reach back to the ramdisk.
        :param agent_version: The version of the agent that is heartbeating.
            ``None`` indicates that the agent that is heartbeating is a version
            before sending agent_version was introduced so agent v3.0.0 (the
            last release before sending agent_version was introduced) will be
            assumed.
        :param agent_token: randomly generated validation token.
        :raises: NodeNotFound if node with provided UUID or name was not found.
        :raises: InvalidUuidOrName if node_ident is not valid name or UUID.
        :raises: NoValidHost if RPC topic for node could not be retrieved.
        :raises: NotFound if requested API version does not allow this
            endpoint.
        """
        if not api_utils.allow_ramdisk_endpoints():
            raise exception.NotFound()

        if agent_version and not api_utils.allow_agent_version_in_heartbeat():
            raise exception.InvalidParameterValue(
                _('Field "agent_version" not recognised'))

        cdict = api.request.context.to_policy_values()
        policy.authorize('baremetal:node:ipa_heartbeat', cdict, cdict)

        rpc_node = api_utils.get_rpc_node_with_suffix(node_ident)
        dii = rpc_node['driver_internal_info']
        agent_url = dii.get('agent_url')
        # If we have an agent_url on file, and we get something different
        # we should fail because this is unexpected behavior of the agent.
        if agent_url is not None and agent_url != callback_url:
            LOG.error('Received heartbeat for node %(node)s with '
                      'callback URL %(url)s. This is not expected, '
                      'and the heartbeat will not be processed.',
                      {'node': rpc_node.uuid, 'url': callback_url})
            raise exception.Invalid(
                _('Detected change in ramdisk provided '
                  '"callback_url"'))
        # NOTE(TheJulia): If tokens are required, lets go ahead and fail the
        # heartbeat very early on.
        token_required = CONF.require_agent_token
        if token_required and agent_token is None:
            LOG.error('Agent heartbeat received for node %(node)s '
                      'without an agent token.', {'node': node_ident})
            raise exception.InvalidParameterValue(
                _('Agent token is required for heartbeat processing.'))

        try:
            topic = api.request.rpcapi.get_topic_for(rpc_node)
        except exception.NoValidHost as e:
            e.code = http_client.BAD_REQUEST
            raise

        api.request.rpcapi.heartbeat(
            api.request.context, rpc_node.uuid, callback_url,
            agent_version, agent_token, topic=topic)
示例#4
0
    def delete(self):
        context = api.request.context

        rpc_node = api_utils.get_rpc_node_with_suffix(self.parent_node_ident)
        # Check the policy, and 404 if not authorized.
        api_utils.check_owner_policy('node',
                                     'baremetal:node:get',
                                     rpc_node.owner,
                                     lessee=rpc_node.lessee,
                                     conceal_node=self.parent_node_ident)

        # A project ID is associated, thus we should filter
        # our search using it.
        filters = {'node_uuid': rpc_node.uuid}
        allocations = objects.Allocation.list(api.request.context,
                                              filters=filters)

        try:
            rpc_allocation = allocations[0]
            allocation_owner = allocations[0]['owner']
            api_utils.check_owner_policy('allocation',
                                         'baremetal:allocation:delete',
                                         allocation_owner)
        except IndexError:
            raise exception.AllocationNotFound(
                _("Allocation for node %s was not found") %
                self.parent_node_ident)

        notify.emit_start_notification(context,
                                       rpc_allocation,
                                       'delete',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context,
                                              rpc_allocation,
                                              'delete',
                                              node_uuid=rpc_node.uuid):
            topic = api.request.rpcapi.get_random_topic()
            api.request.rpcapi.destroy_allocation(context, rpc_allocation,
                                                  topic)
        notify.emit_end_notification(context,
                                     rpc_allocation,
                                     'delete',
                                     node_uuid=rpc_node.uuid)
示例#5
0
    def post(self, node_ident, callback_url, agent_version=None):
        """Process a heartbeat from the deploy ramdisk.

        :param node_ident: the UUID or logical name of a node.
        :param callback_url: the URL to reach back to the ramdisk.
        :param agent_version: The version of the agent that is heartbeating.
            ``None`` indicates that the agent that is heartbeating is a version
            before sending agent_version was introduced so agent v3.0.0 (the
            last release before sending agent_version was introduced) will be
            assumed.
        :raises: NodeNotFound if node with provided UUID or name was not found.
        :raises: InvalidUuidOrName if node_ident is not valid name or UUID.
        :raises: NoValidHost if RPC topic for node could not be retrieved.
        :raises: NotFound if requested API version does not allow this
            endpoint.
        """
        if not api_utils.allow_ramdisk_endpoints():
            raise exception.NotFound()

        if agent_version and not api_utils.allow_agent_version_in_heartbeat():
            raise exception.InvalidParameterValue(
                _('Field "agent_version" not recognised'))

        cdict = pecan.request.context.to_policy_values()
        policy.authorize('baremetal:node:ipa_heartbeat', cdict, cdict)

        rpc_node = api_utils.get_rpc_node_with_suffix(node_ident)

        try:
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
        except exception.NoValidHost as e:
            e.code = http_client.BAD_REQUEST
            raise

        pecan.request.rpcapi.heartbeat(pecan.request.context,
                                       rpc_node.uuid,
                                       callback_url,
                                       agent_version,
                                       topic=topic)
示例#6
0
    def post(self,
             node_ident,
             callback_url,
             agent_version=None,
             agent_token=None,
             agent_verify_ca=None,
             agent_status=None,
             agent_status_message=None):
        """Process a heartbeat from the deploy ramdisk.

        :param node_ident: the UUID or logical name of a node.
        :param callback_url: the URL to reach back to the ramdisk.
        :param agent_version: The version of the agent that is heartbeating.
            ``None`` indicates that the agent that is heartbeating is a version
            before sending agent_version was introduced so agent v3.0.0 (the
            last release before sending agent_version was introduced) will be
            assumed.
        :param agent_token: randomly generated validation token.
        :param agent_verify_ca: TLS certificate to use to connect to the agent.
        :param agent_status: Current status of the heartbeating agent. Used by
            anaconda ramdisk to send status back to Ironic. The valid states
            are 'start', 'end', 'error'
        :param agent_status_message: Optional status message describing current
            agent_status
        :raises: NodeNotFound if node with provided UUID or name was not found.
        :raises: InvalidUuidOrName if node_ident is not valid name or UUID.
        :raises: NoValidHost if RPC topic for node could not be retrieved.
        :raises: NotFound if requested API version does not allow this
            endpoint.
        """
        if not api_utils.allow_ramdisk_endpoints():
            raise exception.NotFound()

        if agent_version and not api_utils.allow_agent_version_in_heartbeat():
            raise exception.InvalidParameterValue(
                _('Field "agent_version" not recognised'))

        if ((agent_status or agent_status_message)
                and not api_utils.allow_status_in_heartbeat()):
            raise exception.InvalidParameterValue(
                _('Fields "agent_status" and "agent_status_message" '
                  'not recognised.'))

        api_utils.check_policy('baremetal:node:ipa_heartbeat')

        if (agent_verify_ca is not None
                and not api_utils.allow_verify_ca_in_heartbeat()):
            raise exception.InvalidParameterValue(
                _('Field "agent_verify_ca" not recognised in this version'))

        rpc_node = api_utils.get_rpc_node_with_suffix(node_ident)
        dii = rpc_node['driver_internal_info']
        agent_url = dii.get('agent_url')
        # If we have an agent_url on file, and we get something different
        # we should fail because this is unexpected behavior of the agent.
        if agent_url is not None and agent_url != callback_url:
            LOG.error(
                'Received heartbeat for node %(node)s with '
                'callback URL %(url)s. This is not expected, '
                'and the heartbeat will not be processed.', {
                    'node': rpc_node.uuid,
                    'url': callback_url
                })
            raise exception.Invalid(
                _('Detected change in ramdisk provided '
                  '"callback_url"'))
        # NOTE(TheJulia): If tokens are required, lets go ahead and fail the
        # heartbeat very early on.
        if agent_token is None:
            LOG.error(
                'Agent heartbeat received for node %(node)s '
                'without an agent token.', {'node': node_ident})
            raise exception.InvalidParameterValue(
                _('Agent token is required for heartbeat processing.'))

        if agent_status is not None and agent_status not in AGENT_VALID_STATES:
            valid_states = ','.join(AGENT_VALID_STATES)
            LOG.error(
                'Agent heartbeat received for node %(node)s '
                'has an invalid agent status: %(agent_status)s. '
                'Valid states are %(valid_states)s ', {
                    'node': node_ident,
                    'agent_status': agent_status,
                    'valid_states': valid_states
                })
            msg = (_('Agent status is invalid. Valid states are %s.') %
                   valid_states)
            raise exception.InvalidParameterValue(msg)

        try:
            topic = api.request.rpcapi.get_topic_for(rpc_node)
        except exception.NoValidHost as e:
            e.code = http_client.BAD_REQUEST
            raise

        api.request.rpcapi.heartbeat(api.request.context,
                                     rpc_node.uuid,
                                     callback_url,
                                     agent_version,
                                     agent_token,
                                     agent_verify_ca,
                                     agent_status,
                                     agent_status_message,
                                     topic=topic)