コード例 #1
0
ファイル: node.py プロジェクト: Codixis/ironic
    def power(self, node_ident, target):
        """Set the power state of the node.

        :param node_ident: the UUID or logical name of a node.
        :param target: The desired power state of the node.
        :raises: ClientSideError (HTTP 409) if a power operation is
                 already in progress.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid or if the node is in CLEANING state.

        """
        # TODO(lucasagomes): Test if it's able to transition to the
        #                    target state from the current one
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target not in [ir_states.POWER_ON,
                          ir_states.POWER_OFF,
                          ir_states.REBOOT]:
            raise exception.InvalidStateRequested(
                action=target, node=node_ident,
                state=rpc_node.power_state)

        # Don't change power state for nodes in cleaning
        elif rpc_node.provision_state == ir_states.CLEANING:
            raise exception.InvalidStateRequested(
                action=target, node=node_ident,
                state=rpc_node.provision_state)

        pecan.request.rpcapi.change_node_power_state(pecan.request.context,
                                                     rpc_node.uuid, target,
                                                     topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_ident, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #2
0
    def post(self, node):
        """Create a new node.

        :param node: a node within the request body.
        """
        if self.from_chassis:
            raise exception.OperationNotPermitted

        # NOTE(deva): get_topic_for checks if node.driver is in the hash ring
        #             and raises NoValidHost if it is not.
        #             We need to ensure that node has a UUID before it can
        #             be mapped onto the hash ring.
        if not node.uuid:
            node.uuid = utils.generate_uuid()

        try:
            pecan.request.rpcapi.get_topic_for(node)
        except exception.NoValidHost as e:
            # NOTE(deva): convert from 404 to 400 because client can see
            #             list of available drivers and shouldn't request
            #             one that doesn't exist.
            e.code = 400
            raise e

        new_node = objects.Node(context=pecan.request.context,
                                **node.as_dict())
        new_node.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('nodes', new_node.uuid)
        return Node.convert_with_links(new_node)
コード例 #3
0
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        self._check_allowed_port_fields(pdict)

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()
        if (pdict.get('portgroup_uuid') and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **pdict)
        rpc_node = objects.Node.get_by_id(context, rpc_port.node_id)

        notify_extra = {
            'node_uuid': port.node_uuid,
            'portgroup_uuid': port.portgroup_uuid
        }
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            # TODO(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. Further consideration is
            # required determine how best to support rolling upgrades from a
            # release in which ports are created by the API service to one in
            # which they are created by the conductor service, while ensuring
            # that all required validation is performed.
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
            new_port = pecan.request.rpcapi.create_port(
                context, rpc_port, topic)
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #4
0
ファイル: node.py プロジェクト: stendulker/ironic
    def power(self, node_ident, target):
        """Set the power state of the node.

        :param node_ident: the UUID or logical name of a node.
        :param target: The desired power state of the node.
        :raises: ClientSideError (HTTP 409) if a power operation is
                 already in progress.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid or if the node is in CLEANING state.

        """
        # TODO(lucasagomes): Test if it's able to transition to the
        #                    target state from the current one
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target not in [ir_states.POWER_ON,
                          ir_states.POWER_OFF,
                          ir_states.REBOOT]:
            raise exception.InvalidStateRequested(
                action=target, node=node_ident,
                state=rpc_node.power_state)

        # Don't change power state for nodes in cleaning
        elif rpc_node.provision_state == ir_states.CLEANING:
            raise exception.InvalidStateRequested(
                action=target, node=node_ident,
                state=rpc_node.provision_state)

        pecan.request.rpcapi.change_node_power_state(pecan.request.context,
                                                     rpc_node.uuid, target,
                                                     topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_ident, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #5
0
ファイル: port.py プロジェクト: Tehsmash/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        self._check_allowed_port_fields(pdict)

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()
        if (pdict.get('portgroup_uuid') and
                (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(
                    msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **pdict)
        rpc_node = objects.Node.get_by_id(context, rpc_port.node_id)

        notify_extra = {'node_uuid': port.node_uuid,
                        'portgroup_uuid': port.portgroup_uuid}
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            # TODO(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. Further consideration is
            # required determine how best to support rolling upgrades from a
            # release in which ports are created by the API service to one in
            # which they are created by the conductor service, while ensuring
            # that all required validation is performed.
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
            new_port = pecan.request.rpcapi.create_port(context, rpc_port,
                                                        topic)
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #6
0
ファイル: node.py プロジェクト: ubuntu3/ironic
    def post(self, node):
        """Create a new node.

        :param node: a node within the request body.
        """
        if self.from_chassis:
            raise exception.OperationNotPermitted

        # NOTE(deva): get_topic_for checks if node.driver is in the hash ring
        #             and raises NoValidHost if it is not.
        #             We need to ensure that node has a UUID before it can
        #             be mapped onto the hash ring.
        if not node.uuid:
            node.uuid = uuidutils.generate_uuid()

        try:
            pecan.request.rpcapi.get_topic_for(node)
        except exception.NoValidHost as e:
            # NOTE(deva): convert from 404 to 400 because client can see
            #             list of available drivers and shouldn't request
            #             one that doesn't exist.
            e.code = 400
            raise e

        error_msg = _("Cannot create node with invalid name "
                      "%(name)s") % {'name': node.name}
        self._check_name_acceptable(node.name, error_msg)
        node.provision_state = api_utils.initial_node_provision_state()

        new_node = objects.Node(pecan.request.context,
                                **node.as_dict())
        new_node.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('nodes', new_node.uuid)
        return Node.convert_with_links(new_node)
コード例 #7
0
ファイル: portgroup.py プロジェクト: windofthesky/ironic
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:portgroup:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (portgroup.name
                and not api_utils.is_valid_logical_name(portgroup.name)):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {
                              'name': portgroup.name
                          }
            raise wsme.exc.ClientSideError(error_msg,
                                           status_code=http_client.BAD_REQUEST)

        new_portgroup = objects.Portgroup(pecan.request.context,
                                          **portgroup.as_dict())
        new_portgroup.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('portgroups',
                                                 new_portgroup.uuid)
        return Portgroup.convert_with_links(new_portgroup)
コード例 #8
0
    def post(self, node):
        """Create a new node.

        :param node: a node within the request body.
        """
        if self.from_chassis:
            raise exception.OperationNotPermitted

        # NOTE(deva): get_topic_for checks if node.driver is in the hash ring
        #             and raises NoValidHost if it is not.
        #             We need to ensure that node has a UUID before it can
        #             be mapped onto the hash ring.
        if not node.uuid:
            node.uuid = uuidutils.generate_uuid()

        try:
            pecan.request.rpcapi.get_topic_for(node)
        except exception.NoValidHost as e:
            # NOTE(deva): convert from 404 to 400 because client can see
            #             list of available drivers and shouldn't request
            #             one that doesn't exist.
            e.code = http_client.BAD_REQUEST
            raise e

        error_msg = _("Cannot create node with invalid name "
                      "%(name)s") % {'name': node.name}
        self._check_name_acceptable(node.name, error_msg)
        node.provision_state = api_utils.initial_node_provision_state()

        new_node = objects.Node(pecan.request.context,
                                **node.as_dict())
        new_node.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('nodes', new_node.uuid)
        return Node.convert_with_links(new_node)
コード例 #9
0
ファイル: portgroup.py プロジェクト: bharathshetty4/ironic
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:portgroup:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (portgroup.name and
                not api_utils.is_valid_logical_name(portgroup.name)):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {'name': portgroup.name}
            raise wsme.exc.ClientSideError(
                error_msg, status_code=http_client.BAD_REQUEST)

        new_portgroup = objects.Portgroup(pecan.request.context,
                                          **portgroup.as_dict())
        new_portgroup.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('portgroups',
                                                 new_portgroup.uuid)
        return Portgroup.convert_with_links(new_portgroup)
コード例 #10
0
ファイル: port.py プロジェクト: windofthesky/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound
        """
        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if (not api_utils.allow_port_advanced_net_fields()
                and set(pdict).intersection(self.advanced_net_fields)):
            raise exception.NotAcceptable()
        if (not api_utils.allow_portgroups_subcontrollers()
                and 'portgroup_uuid' in pdict):
            raise exception.NotAcceptable()

        new_port = objects.Port(pecan.request.context, **pdict)

        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #11
0
    def power(self, node_uuid, target):
        """Set the power state of the node.

        :param node_uuid: UUID of a node.
        :param target: The desired power state of the node.
        :raises: ClientSideError (HTTP 409) if a power operation is
                 already in progress.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid.

        """
        # TODO(lucasagomes): Test if it's able to transition to the
        #                    target state from the current one
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target not in [
                ir_states.POWER_ON, ir_states.POWER_OFF, ir_states.REBOOT
        ]:
            raise exception.InvalidStateRequested(state=target, node=node_uuid)

        pecan.request.rpcapi.change_node_power_state(pecan.request.context,
                                                     node_uuid, target, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_uuid, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #12
0
ファイル: node.py プロジェクト: JoProvost/ironic
    def power(self, node_uuid, target):
        """Set the power state of the node.

        :param node_uuid: UUID of a node.
        :param target: The desired power state of the node.
        :raises: ClientSideError (HTTP 409) if a power operation is
                 already in progress.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid.

        """
        # TODO(lucasagomes): Test if it's able to transition to the
        #                    target state from the current one
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target not in [ir_states.POWER_ON,
                          ir_states.POWER_OFF,
                          ir_states.REBOOT]:
            raise exception.InvalidStateRequested(state=target, node=node_uuid)

        pecan.request.rpcapi.change_node_power_state(pecan.request.context,
                                                     node_uuid, target, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_uuid, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #13
0
    def post(self, allocation):
        """Create a new allocation.

        :param allocation: an allocation within the request body.
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:allocation:create', cdict, cdict)

        if allocation.node_uuid is not wtypes.Unset:
            msg = _("Cannot set node_uuid when creating an allocation")
            raise exception.Invalid(msg)

        if (allocation.name
                and not api_utils.is_valid_logical_name(allocation.name)):
            msg = _("Cannot create allocation with invalid name "
                    "'%(name)s'") % {
                        'name': allocation.name
                    }
            raise exception.Invalid(msg)

        if allocation.traits:
            for trait in allocation.traits:
                api_utils.validate_trait(trait)

        if allocation.candidate_nodes:
            # Convert nodes from names to UUIDs and check their validity
            try:
                converted = pecan.request.dbapi.check_node_list(
                    allocation.candidate_nodes)
            except exception.NodeNotFound as exc:
                exc.code = http_client.BAD_REQUEST
                raise
            else:
                # Make sure we keep the ordering of candidate nodes.
                allocation.candidate_nodes = [
                    converted[ident] for ident in allocation.candidate_nodes
                ]

        all_dict = allocation.as_dict()

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not all_dict.get('uuid'):
            all_dict['uuid'] = uuidutils.generate_uuid()

        new_allocation = objects.Allocation(context, **all_dict)
        topic = pecan.request.rpcapi.get_random_topic()

        notify.emit_start_notification(context, new_allocation, 'create')
        with notify.handle_error_notification(context, new_allocation,
                                              'create'):
            new_allocation = pecan.request.rpcapi.create_allocation(
                context, new_allocation, topic)
        notify.emit_end_notification(context, new_allocation, 'create')

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('allocations',
                                                 new_allocation.uuid)
        return Allocation.convert_with_links(new_allocation)
コード例 #14
0
ファイル: node.py プロジェクト: rdo-management/ironic
    def provision(self, node_uuid, target):
        """Asynchronous trigger the provisioning of the node.

        This will set the target provision state of the node, and a
        background task will begin which actually applies the state
        change. This call will return a 202 (Accepted) indicating the
        request was accepted and is in progress; the client should
        continue to GET the status of this node to observe the status
        of the requested action.

        :param node_uuid: UUID of a node.
        :param target: The desired provision state of the node.
        :raises: ClientSideError (HTTP 409) if the node is already being
                 provisioned.
        :raises: ClientSideError (HTTP 400) if the node is already in
                 the requested state.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid.
        """
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target == rpc_node.provision_state:
            msg = (_("Node %(node)s is already in the '%(state)s' state.") % {
                'node': rpc_node['uuid'],
                'state': target
            })
            raise wsme.exc.ClientSideError(msg, status_code=400)

        if target not in (ir_states.ACTIVE, ir_states.DELETED,
                          ir_states.REBUILD):
            raise exception.InvalidStateRequested(state=target, node=node_uuid)

        valid_states_if_processing = [ir_states.DEPLOYFAIL]
        if target == ir_states.DELETED:
            valid_states_if_processing.append(ir_states.DEPLOYWAIT)

        if (rpc_node.target_provision_state is not None and
                rpc_node.provision_state not in valid_states_if_processing):
            msg = (
                _('Node %s is already being provisioned or decommissioned.') %
                rpc_node.uuid)
            raise wsme.exc.ClientSideError(msg, status_code=409)  # Conflict

        # Note that there is a race condition. The node state(s) could change
        # by the time the RPC call is made and the TaskManager manager gets a
        # lock.

        if target in (ir_states.ACTIVE, ir_states.REBUILD):
            rebuild = (target == ir_states.REBUILD)
            pecan.request.rpcapi.do_node_deploy(pecan.request.context,
                                                node_uuid, rebuild, topic)
        elif target == ir_states.DELETED:
            pecan.request.rpcapi.do_node_tear_down(pecan.request.context,
                                                   node_uuid, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_uuid, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #15
0
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:portgroup:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties()
                and (portgroup.mode is not wtypes.Unset
                     or portgroup.properties is not wtypes.Unset)):
            raise exception.NotAcceptable()

        if (portgroup.name
                and not api_utils.is_valid_logical_name(portgroup.name)):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {
                              'name': portgroup.name
                          }
            raise wsme.exc.ClientSideError(error_msg,
                                           status_code=http_client.BAD_REQUEST)

        pg_dict = portgroup.as_dict()
        vif = pg_dict.get('extra', {}).get('vif_port_id')
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pg_dict.get('uuid'):
            pg_dict['uuid'] = uuidutils.generate_uuid()

        new_portgroup = objects.Portgroup(context, **pg_dict)

        notify.emit_start_notification(context,
                                       new_portgroup,
                                       'create',
                                       node_uuid=portgroup.node_uuid)
        with notify.handle_error_notification(context,
                                              new_portgroup,
                                              'create',
                                              node_uuid=portgroup.node_uuid):
            new_portgroup.create()
        notify.emit_end_notification(context,
                                     new_portgroup,
                                     'create',
                                     node_uuid=portgroup.node_uuid)

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('portgroups',
                                                 new_portgroup.uuid)
        return Portgroup.convert_with_links(new_portgroup)
コード例 #16
0
ファイル: chassis.py プロジェクト: JoProvost/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        new_chassis = pecan.request.dbapi.create_chassis(chassis.as_dict())
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #17
0
ファイル: chassis.py プロジェクト: deniscostadsc/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        new_chassis = pecan.request.dbapi.create_chassis(chassis.as_dict())
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #18
0
ファイル: port.py プロジェクト: bopopescu/OpenStack-Ocata
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if (not api_utils.allow_port_advanced_net_fields()
                and set(pdict).intersection(self.advanced_net_fields)):
            raise exception.NotAcceptable()
        if (not api_utils.allow_portgroups_subcontrollers()
                and 'portgroup_uuid' in pdict):
            raise exception.NotAcceptable()

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()
        if (pdict.get('portgroup_uuid') and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        new_port = objects.Port(context, **pdict)

        notify.emit_start_notification(context,
                                       new_port,
                                       'create',
                                       node_uuid=port.node_uuid)
        with notify.handle_error_notification(context,
                                              new_port,
                                              'create',
                                              node_uuid=port.node_uuid):
            new_port.create()
        notify.emit_end_notification(context,
                                     new_port,
                                     'create',
                                     node_uuid=port.node_uuid)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #19
0
ファイル: allocation.py プロジェクト: michaeltchapman/ironic
    def post(self, allocation):
        """Create a new allocation.

        :param allocation: an allocation within the request body.
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:allocation:create', cdict, cdict)

        if allocation.node_uuid is not wtypes.Unset:
            msg = _("Cannot set node_uuid when creating an allocation")
            raise exception.Invalid(msg)

        if (allocation.name
                and not api_utils.is_valid_logical_name(allocation.name)):
            msg = _("Cannot create allocation with invalid name "
                    "'%(name)s'") % {'name': allocation.name}
            raise exception.Invalid(msg)

        if allocation.traits:
            for trait in allocation.traits:
                api_utils.validate_trait(trait)

        if allocation.candidate_nodes:
            # Convert nodes from names to UUIDs and check their validity
            try:
                converted = pecan.request.dbapi.check_node_list(
                    allocation.candidate_nodes)
            except exception.NodeNotFound as exc:
                exc.code = http_client.BAD_REQUEST
                raise
            else:
                # Make sure we keep the ordering of candidate nodes.
                allocation.candidate_nodes = [
                    converted[ident] for ident in allocation.candidate_nodes]

        all_dict = allocation.as_dict()

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not all_dict.get('uuid'):
            all_dict['uuid'] = uuidutils.generate_uuid()

        new_allocation = objects.Allocation(context, **all_dict)
        topic = pecan.request.rpcapi.get_random_topic()

        notify.emit_start_notification(context, new_allocation, 'create')
        with notify.handle_error_notification(context, new_allocation,
                                              'create'):
            new_allocation = pecan.request.rpcapi.create_allocation(
                context, new_allocation, topic)
        notify.emit_end_notification(context, new_allocation, 'create')

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('allocations',
                                                 new_allocation.uuid)
        return Allocation.convert_with_links(new_allocation)
コード例 #20
0
ファイル: portgroup.py プロジェクト: namnx228/ironic
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        context = api.request.context
        api_utils.check_policy('baremetal:portgroup:create')

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties()
                and (portgroup.get('mode') or portgroup.get('properties'))):
            raise exception.NotAcceptable()

        if (portgroup.get('name')
                and not api_utils.is_valid_logical_name(portgroup['name'])):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {
                              'name': portgroup['name']
                          }
            raise exception.ClientSideError(
                error_msg, status_code=http_client.BAD_REQUEST)

        api_utils.handle_post_port_like_extra_vif(portgroup)

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not portgroup.get('uuid'):
            portgroup['uuid'] = uuidutils.generate_uuid()

        node = api_utils.replace_node_uuid_with_id(portgroup)

        new_portgroup = objects.Portgroup(context, **portgroup)

        notify.emit_start_notification(context,
                                       new_portgroup,
                                       'create',
                                       node_uuid=node.uuid)
        with notify.handle_error_notification(context,
                                              new_portgroup,
                                              'create',
                                              node_uuid=node.uuid):
            new_portgroup.create()
        notify.emit_end_notification(context,
                                     new_portgroup,
                                     'create',
                                     node_uuid=node.uuid)

        # Set the HTTP Location Header
        api.response.location = link.build_url('portgroups',
                                               new_portgroup.uuid)
        return convert_with_links(new_portgroup)
コード例 #21
0
ファイル: node.py プロジェクト: JoProvost/ironic
    def provision(self, node_uuid, target):
        """Asynchronous trigger the provisioning of the node.

        This will set the target provision state of the node, and a
        background task will begin which actually applies the state
        change. This call will return a 202 (Accepted) indicating the
        request was accepted and is in progress; the client should
        continue to GET the status of this node to observe the status
        of the requested action.

        :param node_uuid: UUID of a node.
        :param target: The desired provision state of the node.
        :raises: ClientSideError (HTTP 409) if the node is already being
                 provisioned.
        :raises: ClientSideError (HTTP 400) if the node is already in
                 the requested state.
        :raises: InvalidStateRequested (HTTP 400) if the requested target
                 state is not valid.
        """
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if target == rpc_node.provision_state:
            msg = (_("Node %(node)s is already in the '%(state)s' state.") %
                   {'node': rpc_node['uuid'], 'state': target})
            raise wsme.exc.ClientSideError(msg, status_code=400)

        if target in (ir_states.ACTIVE, ir_states.REBUILD):
            processing = rpc_node.target_provision_state is not None
        elif target == ir_states.DELETED:
            processing = (rpc_node.target_provision_state is not None and
                        rpc_node.provision_state != ir_states.DEPLOYWAIT)
        else:
            raise exception.InvalidStateRequested(state=target, node=node_uuid)

        if processing:
            msg = (_('Node %s is already being provisioned or decommissioned.')
                   % rpc_node.uuid)
            raise wsme.exc.ClientSideError(msg, status_code=409)  # Conflict

        # Note that there is a race condition. The node state(s) could change
        # by the time the RPC call is made and the TaskManager manager gets a
        # lock.

        if target in (ir_states.ACTIVE, ir_states.REBUILD):
            rebuild = (target == ir_states.REBUILD)
            pecan.request.rpcapi.do_node_deploy(
                    pecan.request.context, node_uuid, rebuild, topic)
        elif target == ir_states.DELETED:
            pecan.request.rpcapi.do_node_tear_down(
                    pecan.request.context, node_uuid, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_uuid, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #22
0
    def post(self, connector):
        """Create a new volume connector.

        :param connector: a volume connector within the request body.

        :returns: API-serializable volume connector object.

        :raises: OperationNotPermitted if accessed with specifying a parent
                 node.
        :raises: VolumeConnectorTypeAndIdAlreadyExists if a volume
                 connector already exists with the same type and connector_id
        :raises: VolumeConnectorAlreadyExists if a volume connector with the
                 same UUID already exists
        """
        context = api.request.context
        owner = None
        lessee = None
        raise_node_not_found = False
        node_uuid = connector.get('node_uuid')

        try:
            node = api_utils.replace_node_uuid_with_id(connector)
            owner = node.owner
            lessee = node.lessee
        except exception.NotFound:
            raise_node_not_found = True
        api_utils.check_owner_policy('node', 'baremetal:volume:create',
                                     owner, lessee=lessee, conceal_node=False)

        if raise_node_not_found:
            raise exception.InvalidInput(fieldname='node_uuid',
                                         value=node_uuid)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        # NOTE(hshiina): UUID is mandatory for notification payload
        if not connector.get('uuid'):
            connector['uuid'] = uuidutils.generate_uuid()

        new_connector = objects.VolumeConnector(context, **connector)

        notify.emit_start_notification(context, new_connector, 'create',
                                       node_uuid=node.uuid)
        with notify.handle_error_notification(context, new_connector,
                                              'create',
                                              node_uuid=node.uuid):
            new_connector.create()
        notify.emit_end_notification(context, new_connector, 'create',
                                     node_uuid=node.uuid)
        # Set the HTTP Location Header
        api.response.location = link.build_url('volume/connectors',
                                               new_connector.uuid)
        return convert_with_links(new_connector)
コード例 #23
0
ファイル: port.py プロジェクト: JoProvost/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        """
        if self.from_nodes:
            raise exception.OperationNotPermitted

        new_port = pecan.request.dbapi.create_port(port.as_dict())
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #24
0
ファイル: port.py プロジェクト: JoProvost/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        """
        if self.from_nodes:
            raise exception.OperationNotPermitted

        new_port = pecan.request.dbapi.create_port(port.as_dict())
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #25
0
ファイル: node.py プロジェクト: toby82/ironic
    def put(self, node_uuid, enabled):
        """Start and stop the node console.

        :param node_uuid: UUID of a node.
        :param enabled: Boolean value; whether to enable or disable the
                console.
        """
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)
        pecan.request.rpcapi.set_console_mode(pecan.request.context, node_uuid, enabled, topic)
        # Set the HTTP Location Header
        url_args = "/".join([node_uuid, "states", "console"])
        pecan.response.location = link.build_url("nodes", url_args)
コード例 #26
0
ファイル: node.py プロジェクト: larainema/ironic
    def put(self, node_ident, enabled):
        """Start and stop the node console.

        :param node_ident: UUID or logical name of a node.
        :param enabled: Boolean value; whether to enable or disable the
                console.
        """
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)
        pecan.request.rpcapi.set_console_mode(pecan.request.context, rpc_node.uuid, enabled, topic)
        # Set the HTTP Location Header
        url_args = "/".join([node_ident, "states", "console"])
        pecan.response.location = link.build_url("nodes", url_args)
コード例 #27
0
ファイル: portgroup.py プロジェクト: Tehsmash/ironic
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:portgroup:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties() and
                (portgroup.mode is not wtypes.Unset or
                 portgroup.properties is not wtypes.Unset)):
            raise exception.NotAcceptable()

        if (portgroup.name and
                not api_utils.is_valid_logical_name(portgroup.name)):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {'name': portgroup.name}
            raise wsme.exc.ClientSideError(
                error_msg, status_code=http_client.BAD_REQUEST)

        pg_dict = portgroup.as_dict()
        vif = pg_dict.get('extra', {}).get('vif_port_id')
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pg_dict.get('uuid'):
            pg_dict['uuid'] = uuidutils.generate_uuid()

        new_portgroup = objects.Portgroup(context, **pg_dict)

        notify.emit_start_notification(context, new_portgroup, 'create',
                                       node_uuid=portgroup.node_uuid)
        with notify.handle_error_notification(context, new_portgroup, 'create',
                                              node_uuid=portgroup.node_uuid):
            new_portgroup.create()
        notify.emit_end_notification(context, new_portgroup, 'create',
                                     node_uuid=portgroup.node_uuid)

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('portgroups',
                                                 new_portgroup.uuid)
        return Portgroup.convert_with_links(new_portgroup)
コード例 #28
0
ファイル: chassis.py プロジェクト: bharathshetty4/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:chassis:create', cdict, cdict)

        new_chassis = objects.Chassis(pecan.request.context,
                                      **chassis.as_dict())
        new_chassis.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #29
0
ファイル: chassis.py プロジェクト: mat128/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:chassis:create', cdict, cdict)

        new_chassis = objects.Chassis(pecan.request.context,
                                      **chassis.as_dict())
        new_chassis.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #30
0
    def put(self, node_uuid, enabled):
        """Start and stop the node console.

        :param node_uuid: UUID of a node.
        :param enabled: Boolean value; whether to enable or disable the
                console.
        """
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)
        pecan.request.rpcapi.set_console_mode(pecan.request.context, node_uuid,
                                              enabled, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_uuid, 'states', 'console'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #31
0
ファイル: node.py プロジェクト: Codixis/ironic
    def put(self, node_ident, enabled):
        """Start and stop the node console.

        :param node_ident: UUID or logical name of a node.
        :param enabled: Boolean value; whether to enable or disable the
                console.
        """
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)
        pecan.request.rpcapi.set_console_mode(pecan.request.context,
                                              rpc_node.uuid, enabled, topic)
        # Set the HTTP Location Header
        url_args = '/'.join([node_ident, 'states', 'console'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #32
0
    def post(self, target):
        """Create a new volume target.

        :param target: a volume target within the request body.

        :returns: API-serializable volume target object.

        :raises: OperationNotPermitted if accessed with specifying a parent
                 node.
        :raises: VolumeTargetBootIndexAlreadyExists if a volume target already
                 exists with the same node ID and boot index
        :raises: VolumeTargetAlreadyExists if a volume target with the same
                 UUID exists
        """
        context = api.request.context
        api_utils.check_policy('baremetal:volume:create')

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        # NOTE(hshiina): UUID is mandatory for notification payload
        if not target.get('uuid'):
            target['uuid'] = uuidutils.generate_uuid()

        node = api_utils.replace_node_uuid_with_id(target)

        new_target = objects.VolumeTarget(context, **target)

        notify.emit_start_notification(context,
                                       new_target,
                                       'create',
                                       node_uuid=node.uuid)
        with notify.handle_error_notification(context,
                                              new_target,
                                              'create',
                                              node_uuid=node.uuid):
            new_target.create()
        notify.emit_end_notification(context,
                                     new_target,
                                     'create',
                                     node_uuid=node.uuid)
        # Set the HTTP Location Header
        api.response.location = link.build_url('volume/targets',
                                               new_target.uuid)
        return convert_with_links(new_target)
コード例 #33
0
    def post(self, connector):
        """Create a new volume connector.

        :param connector: a volume connector within the request body.

        :returns: API-serializable volume connector object.

        :raises: OperationNotPermitted if accessed with specifying a parent
                 node.
        :raises: VolumeConnectorTypeAndIdAlreadyExists if a volume
                 connector already exists with the same type and connector_id
        :raises: VolumeConnectorAlreadyExists if a volume connector with the
                 same UUID already exists
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:volume:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        connector_dict = connector.as_dict()
        # NOTE(hshiina): UUID is mandatory for notification payload
        if not connector_dict.get('uuid'):
            connector_dict['uuid'] = uuidutils.generate_uuid()

        new_connector = objects.VolumeConnector(context, **connector_dict)

        notify.emit_start_notification(context,
                                       new_connector,
                                       'create',
                                       node_uuid=connector.node_uuid)
        with notify.handle_error_notification(context,
                                              new_connector,
                                              'create',
                                              node_uuid=connector.node_uuid):
            new_connector.create()
        notify.emit_end_notification(context,
                                     new_connector,
                                     'create',
                                     node_uuid=connector.node_uuid)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('volume/connectors',
                                                 new_connector.uuid)
        return VolumeConnector.convert_with_links(new_connector)
コード例 #34
0
ファイル: node.py プロジェクト: Codixis/ironic
    def post(self, node):
        """Create a new node.

        :param node: a node within the request body.
        """
        if self.from_chassis:
            raise exception.OperationNotPermitted

        # NOTE(deva): get_topic_for checks if node.driver is in the hash ring
        #             and raises NoValidHost if it is not.
        #             We need to ensure that node has a UUID before it can
        #             be mapped onto the hash ring.
        if not node.uuid:
            node.uuid = uuidutils.generate_uuid()

        try:
            pecan.request.rpcapi.get_topic_for(node)
        except exception.NoValidHost as e:
            # NOTE(deva): convert from 404 to 400 because client can see
            #             list of available drivers and shouldn't request
            #             one that doesn't exist.
            e.code = 400
            raise e

        # Verify that if we're creating a new node with a 'name' set
        # that it is a valid name
        if node.name:
            if not api_utils.allow_node_logical_names():
                raise exception.NotAcceptable()
            if not api_utils.is_valid_node_name(node.name):
                msg = _("Cannot create node with invalid name %(name)s")
                raise wsme.exc.ClientSideError(msg % {'name': node.name},
                                               status_code=400)

        node.provision_state = api_utils.initial_node_provision_state()

        new_node = objects.Node(pecan.request.context,
                                **node.as_dict())
        new_node.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('nodes', new_node.uuid)
        return Node.convert_with_links(new_node)
コード例 #35
0
ファイル: port.py プロジェクト: sinvalmendes/stuff
    def post(self, port):

        """Create a new port.

        :param port: a port within the request body.
        """
        if self.from_nodes:
            raise exception.OperationNotPermitted

        if not (api_utils.allow_node_name()):
            if port.node_uuid == wtypes.Unset:
                e = exception.BadRequest()
                e.code = 400
                raise e

        new_port = objects.Port(pecan.request.context, **port.as_dict())
        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url("ports", new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #36
0
ファイル: chassis.py プロジェクト: namnx228/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        context = api.request.context
        api_utils.check_policy('baremetal:chassis:create')

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not chassis.get('uuid'):
            chassis['uuid'] = uuidutils.generate_uuid()

        new_chassis = objects.Chassis(context, **chassis)
        notify.emit_start_notification(context, new_chassis, 'create')
        with notify.handle_error_notification(context, new_chassis, 'create'):
            new_chassis.create()
        notify.emit_end_notification(context, new_chassis, 'create')
        # Set the HTTP Location Header
        api.response.location = link.build_url('chassis', new_chassis.uuid)
        return convert_with_links(new_chassis)
コード例 #37
0
ファイル: port.py プロジェクト: jangseon-ryu/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if (not api_utils.allow_port_advanced_net_fields() and
                set(pdict).intersection(self.advanced_net_fields)):
            raise exception.NotAcceptable()
        if (not api_utils.allow_portgroups_subcontrollers() and
            'portgroup_uuid' in pdict):
            raise exception.NotAcceptable()

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if (pdict.get('portgroup_uuid') and
                (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(pecan.request.context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(
                    msg % pdict['portgroup_uuid'])

        new_port = objects.Port(pecan.request.context,
                                **pdict)

        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #38
0
ファイル: chassis.py プロジェクト: michaeltchapman/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:chassis:create', cdict, cdict)

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not chassis.uuid:
            chassis.uuid = uuidutils.generate_uuid()

        new_chassis = objects.Chassis(context, **chassis.as_dict())
        notify.emit_start_notification(context, new_chassis, 'create')
        with notify.handle_error_notification(context, new_chassis, 'create'):
            new_chassis.create()
        notify.emit_end_notification(context, new_chassis, 'create')
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #39
0
ファイル: chassis.py プロジェクト: younkun/ironic
    def post(self, chassis):
        """Create a new chassis.

        :param chassis: a chassis within the request body.
        """
        context = api.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:chassis:create', cdict, cdict)

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not chassis.uuid:
            chassis.uuid = uuidutils.generate_uuid()

        new_chassis = objects.Chassis(context, **chassis.as_dict())
        notify.emit_start_notification(context, new_chassis, 'create')
        with notify.handle_error_notification(context, new_chassis, 'create'):
            new_chassis.create()
        notify.emit_end_notification(context, new_chassis, 'create')
        # Set the HTTP Location Header
        api.response.location = link.build_url('chassis', new_chassis.uuid)
        return Chassis.convert_with_links(new_chassis)
コード例 #40
0
ファイル: port.py プロジェクト: bacaldwell/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable
        """
        if self.from_nodes:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if not api_utils.allow_port_advanced_net_fields():
            if set(pdict).intersection(self.advanced_net_fields):
                raise exception.NotAcceptable()

        new_port = objects.Port(pecan.request.context,
                                **pdict)

        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #41
0
ファイル: volume_connector.py プロジェクト: Tehsmash/ironic
    def post(self, connector):
        """Create a new volume connector.

        :param connector: a volume connector within the request body.

        :returns: API-serializable volume connector object.

        :raises: OperationNotPermitted if accessed with specifying a parent
                 node.
        :raises: VolumeConnectorTypeAndIdAlreadyExists if a volume
                 connector already exists with the same type and connector_id
        :raises: VolumeConnectorAlreadyExists if a volume connector with the
                 same UUID already exists
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:volume:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        connector_dict = connector.as_dict()
        # NOTE(hshiina): UUID is mandatory for notification payload
        if not connector_dict.get('uuid'):
            connector_dict['uuid'] = uuidutils.generate_uuid()

        new_connector = objects.VolumeConnector(context, **connector_dict)

        notify.emit_start_notification(context, new_connector, 'create',
                                       node_uuid=connector.node_uuid)
        with notify.handle_error_notification(context, new_connector,
                                              'create',
                                              node_uuid=connector.node_uuid):
            new_connector.create()
        notify.emit_end_notification(context, new_connector, 'create',
                                     node_uuid=connector.node_uuid)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('volume/connectors',
                                                 new_connector.uuid)
        return VolumeConnector.convert_with_links(new_connector)
コード例 #42
0
ファイル: node.py プロジェクト: kumarom/ironic
    def post(self, node):
        """Create a new node.

        :param node: a node within the request body.
        """
        if self.from_chassis:
            raise exception.OperationNotPermitted

        # NOTE(deva): get_topic_for checks if node.driver is in the hash ring
        #             and raises NoValidHost if it is not.
        #             We need to ensure that node has a UUID before it can
        #             be mapped onto the hash ring.
        if not node.uuid:
            node.uuid = uuidutils.generate_uuid()

        try:
            pecan.request.rpcapi.get_topic_for(node)
        except exception.NoValidHost as e:
            # NOTE(deva): convert from 404 to 400 because client can see
            #             list of available drivers and shouldn't request
            #             one that doesn't exist.
            e.code = 400
            raise e

        # Verify that if we're creating a new node with a 'name' set
        # that it is a valid name
        if node.name:
            if not api_utils.allow_node_logical_names():
                raise exception.NotAcceptable()
            if not api_utils.is_valid_node_name(node.name):
                msg = _("Cannot create node with invalid name %(name)s")
                raise wsme.exc.ClientSideError(msg % {'name': node.name},
                                               status_code=400)

        new_node = objects.Node(pecan.request.context,
                                **node.as_dict())
        new_node.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('nodes', new_node.uuid)
        return Node.convert_with_links(new_node)
コード例 #43
0
    def post(self, target):
        """Create a new volume target.

        :param target: a volume target within the request body.

        :returns: API-serializable volume target object.

        :raises: OperationNotPermitted if accessed with specifying a parent
                 node.
        :raises: VolumeTargetBootIndexAlreadyExists if a volume target already
                 exists with the same node ID and boot index
        :raises: VolumeTargetAlreadyExists if a volume target with the same
                 UUID exists
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:volume:create', cdict, cdict)

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        target_dict = target.as_dict()
        # NOTE(hshiina): UUID is mandatory for notification payload
        if not target_dict.get('uuid'):
            target_dict['uuid'] = uuidutils.generate_uuid()

        new_target = objects.VolumeTarget(context, **target_dict)

        notify.emit_start_notification(context, new_target, 'create',
                                       node_uuid=target.node_uuid)
        with notify.handle_error_notification(context, new_target, 'create',
                                              node_uuid=target.node_uuid):
            new_target.create()
        notify.emit_end_notification(context, new_target, 'create',
                                     node_uuid=target.node_uuid)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('volume/targets',
                                                 new_target.uuid)
        return VolumeTarget.convert_with_links(new_target)
コード例 #44
0
ファイル: deploy_template.py プロジェクト: modelsim71/ironic
    def post(self, template):
        """Create a new deploy template.

        :param template: a deploy template within the request body.
        """
        api_utils.check_policy('baremetal:deploy_template:create')

        context = api.request.context
        tdict = template.as_dict()
        # NOTE(mgoddard): UUID is mandatory for notifications payload
        if not tdict.get('uuid'):
            tdict['uuid'] = uuidutils.generate_uuid()

        new_template = objects.DeployTemplate(context, **tdict)

        notify.emit_start_notification(context, new_template, 'create')
        with notify.handle_error_notification(context, new_template, 'create'):
            new_template.create()
        # Set the HTTP Location Header
        api.response.location = link.build_url('deploy_templates',
                                               new_template.uuid)
        api_template = DeployTemplate.convert_with_links(new_template)
        notify.emit_end_notification(context, new_template, 'create')
        return api_template
コード例 #45
0
ファイル: node.py プロジェクト: stendulker/ironic
    def provision(self, node_ident, target, configdrive=None):
        """Asynchronous trigger the provisioning of the node.

        This will set the target provision state of the node, and a
        background task will begin which actually applies the state
        change. This call will return a 202 (Accepted) indicating the
        request was accepted and is in progress; the client should
        continue to GET the status of this node to observe the status
        of the requested action.

        :param node_ident: UUID or logical name of a node.
        :param target: The desired provision state of the node.
        :param configdrive: Optional. A gzipped and base64 encoded
            configdrive. Only valid when setting provision state
            to "active".
        :raises: NodeLocked (HTTP 409) if the node is currently locked.
        :raises: ClientSideError (HTTP 409) if the node is already being
                 provisioned.
        :raises: InvalidStateRequested (HTTP 400) if the requested transition
                 is not possible from the current state.
        :raises: NotAcceptable (HTTP 406) if the API version specified does
                 not allow the requested state transition.
        """
        check_allow_management_verbs(target)
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        if (target in (ir_states.ACTIVE, ir_states.REBUILD)
                and rpc_node.maintenance):
            raise exception.NodeInMaintenance(op=_('provisioning'),
                                              node=rpc_node.uuid)

        m = ir_states.machine.copy()
        m.initialize(rpc_node.provision_state)
        if not m.is_valid_event(ir_states.VERBS.get(target, target)):
            # Normally, we let the task manager recognize and deal with
            # NodeLocked exceptions. However, that isn't done until the RPC
            # calls below.
            # In order to main backward compatibility with our API HTTP
            # response codes, we have this check here to deal with cases where
            # a node is already being operated on (DEPLOYING or such) and we
            # want to continue returning 409. Without it, we'd return 400.
            if rpc_node.reservation:
                raise exception.NodeLocked(node=rpc_node.uuid,
                                           host=rpc_node.reservation)

            raise exception.InvalidStateRequested(
                action=target, node=rpc_node.uuid,
                state=rpc_node.provision_state)

        if configdrive and target != ir_states.ACTIVE:
            msg = (_('Adding a config drive is only supported when setting '
                     'provision state to %s') % ir_states.ACTIVE)
            raise wsme.exc.ClientSideError(msg, status_code=400)

        # Note that there is a race condition. The node state(s) could change
        # by the time the RPC call is made and the TaskManager manager gets a
        # lock.
        if target == ir_states.ACTIVE:
            pecan.request.rpcapi.do_node_deploy(pecan.request.context,
                                                rpc_node.uuid, False,
                                                configdrive, topic)
        elif target == ir_states.REBUILD:
            pecan.request.rpcapi.do_node_deploy(pecan.request.context,
                                                rpc_node.uuid, True,
                                                None, topic)
        elif target == ir_states.DELETED:
            pecan.request.rpcapi.do_node_tear_down(
                pecan.request.context, rpc_node.uuid, topic)
        elif target == ir_states.VERBS['inspect']:
            pecan.request.rpcapi.inspect_hardware(
                pecan.request.context, rpc_node.uuid, topic=topic)
        elif target in (
                ir_states.VERBS['manage'], ir_states.VERBS['provide']):
            pecan.request.rpcapi.do_provisioning_action(
                pecan.request.context, rpc_node.uuid, target, topic)
        else:
            msg = (_('The requested action "%(action)s" could not be '
                     'understood.') % {'action': target})
            raise exception.InvalidStateRequested(message=msg)

        # Set the HTTP Location Header
        url_args = '/'.join([node_ident, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #46
0
ファイル: port.py プロジェクト: michaeltchapman/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        self._check_allowed_port_fields(pdict)

        if (port.is_smartnic and not types.locallinkconnectiontype
                .validate_for_smart_nic(port.local_link_connection)):
            raise exception.Invalid(
                "Smart NIC port must have port_id "
                "and hostname in local_link_connection")

        create_remotely = pecan.request.rpcapi.can_send_create_port()
        if (not create_remotely and pdict.get('portgroup_uuid')):
            # NOTE(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. During a rolling upgrade,
            # the RPCAPI will reject the create_port method, so we need to
            # create the port locally. If the port is a member of a portgroup,
            # we are unable to perform the validation and must reject the
            # request.
            raise exception.NotAcceptable()

        vif = api_utils.handle_post_port_like_extra_vif(pdict)

        if (pdict.get('portgroup_uuid')
                and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(
                    msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **pdict)
        rpc_node = objects.Node.get_by_id(context, rpc_port.node_id)

        notify_extra = {'node_uuid': port.node_uuid,
                        'portgroup_uuid': port.portgroup_uuid}
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            # NOTE(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. During a rolling upgrade,
            # the RPCAPI will reject the create_port method, so we need to
            # create the port locally.
            if create_remotely:
                topic = pecan.request.rpcapi.get_topic_for(rpc_node)
                new_port = pecan.request.rpcapi.create_port(context, rpc_port,
                                                            topic)
            else:
                rpc_port.create()
                new_port = rpc_port
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #47
0
ファイル: node.py プロジェクト: Codixis/ironic
    def provision(self, node_ident, target, configdrive=None):
        """Asynchronous trigger the provisioning of the node.

        This will set the target provision state of the node, and a
        background task will begin which actually applies the state
        change. This call will return a 202 (Accepted) indicating the
        request was accepted and is in progress; the client should
        continue to GET the status of this node to observe the status
        of the requested action.

        :param node_ident: UUID or logical name of a node.
        :param target: The desired provision state of the node.
        :param configdrive: Optional. A gzipped and base64 encoded
            configdrive. Only valid when setting provision state
            to "active".
        :raises: NodeLocked (HTTP 409) if the node is currently locked.
        :raises: ClientSideError (HTTP 409) if the node is already being
                 provisioned.
        :raises: InvalidStateRequested (HTTP 400) if the requested transition
                 is not possible from the current state.
        :raises: NotAcceptable (HTTP 406) if the API version specified does
                 not allow the requested state transition.
        """
        check_allow_management_verbs(target)
        rpc_node = api_utils.get_rpc_node(node_ident)
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)

        # Normally, we let the task manager recognize and deal with
        # NodeLocked exceptions. However, that isn't done until the RPC calls
        # below. In order to main backward compatibility with our API HTTP
        # response codes, we have this check here to deal with cases where
        # a node is already being operated on (DEPLOYING or such) and we
        # want to continue returning 409. Without it, we'd return 400.
        if rpc_node.reservation:
            raise exception.NodeLocked(node=rpc_node.uuid,
                                       host=rpc_node.reservation)

        if (target in (ir_states.ACTIVE, ir_states.REBUILD)
                and rpc_node.maintenance):
            raise exception.NodeInMaintenance(op=_('provisioning'),
                                              node=rpc_node.uuid)

        m = ir_states.machine.copy()
        m.initialize(rpc_node.provision_state)
        if not m.is_valid_event(ir_states.VERBS.get(target, target)):
            raise exception.InvalidStateRequested(
                action=target, node=rpc_node.uuid,
                state=rpc_node.provision_state)

        if configdrive and target != ir_states.ACTIVE:
            msg = (_('Adding a config drive is only supported when setting '
                     'provision state to %s') % ir_states.ACTIVE)
            raise wsme.exc.ClientSideError(msg, status_code=400)

        # Note that there is a race condition. The node state(s) could change
        # by the time the RPC call is made and the TaskManager manager gets a
        # lock.
        if target == ir_states.ACTIVE:
            pecan.request.rpcapi.do_node_deploy(pecan.request.context,
                                                rpc_node.uuid, False,
                                                configdrive, topic)
        elif target == ir_states.REBUILD:
            pecan.request.rpcapi.do_node_deploy(pecan.request.context,
                                                rpc_node.uuid, True,
                                                None, topic)
        elif target == ir_states.DELETED:
            pecan.request.rpcapi.do_node_tear_down(
                pecan.request.context, rpc_node.uuid, topic)
        elif target == ir_states.VERBS['inspect']:
            pecan.request.rpcapi.inspect_hardware(
                pecan.request.context, rpc_node.uuid, topic=topic)
        elif target in (
                ir_states.VERBS['manage'], ir_states.VERBS['provide']):
            pecan.request.rpcapi.do_provisioning_action(
                pecan.request.context, rpc_node.uuid, target, topic)
        else:
            msg = (_('The requested action "%(action)s" could not be '
                     'understood.') % {'action': target})
            raise exception.InvalidStateRequested(message=msg)

        # Set the HTTP Location Header
        url_args = '/'.join([node_ident, 'states'])
        pecan.response.location = link.build_url('nodes', url_args)
コード例 #48
0
ファイル: port.py プロジェクト: ankit-kumar5/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        context = api.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        pdict = port.as_dict()
        self._check_allowed_port_fields(pdict)

        if (port.is_smartnic
                and not types.locallinkconnectiontype.validate_for_smart_nic(
                    port.local_link_connection)):
            raise exception.Invalid("Smart NIC port must have port_id "
                                    "and hostname in local_link_connection")

        create_remotely = api.request.rpcapi.can_send_create_port()
        if (not create_remotely and pdict.get('portgroup_uuid')):
            # NOTE(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. During a rolling upgrade,
            # the RPCAPI will reject the create_port method, so we need to
            # create the port locally. If the port is a member of a portgroup,
            # we are unable to perform the validation and must reject the
            # request.
            raise exception.NotAcceptable()

        vif = api_utils.handle_post_port_like_extra_vif(pdict)

        if (pdict.get('portgroup_uuid') and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **pdict)
        rpc_node = objects.Node.get_by_id(context, rpc_port.node_id)

        notify_extra = {
            'node_uuid': port.node_uuid,
            'portgroup_uuid': port.portgroup_uuid
        }
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            # NOTE(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. During a rolling upgrade,
            # the RPCAPI will reject the create_port method, so we need to
            # create the port locally.
            if create_remotely:
                topic = api.request.rpcapi.get_topic_for(rpc_node)
                new_port = api.request.rpcapi.create_port(
                    context, rpc_port, topic)
            else:
                rpc_port.create()
                new_port = rpc_port
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        api.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
コード例 #49
0
    def post(self, allocation):
        """Create a new allocation.

        :param allocation: an allocation within the request body.
        """
        context = api.request.context
        allocation = self._authorize_create_allocation(allocation)

        if (allocation.name
                and not api_utils.is_valid_logical_name(allocation.name)):
            msg = _("Cannot create allocation with invalid name "
                    "'%(name)s'") % {
                        'name': allocation.name
                    }
            raise exception.Invalid(msg)

        if allocation.traits:
            for trait in allocation.traits:
                api_utils.validate_trait(trait)

        node = None
        if allocation.node is not atypes.Unset:
            if api_utils.allow_allocation_backfill():
                try:
                    node = api_utils.get_rpc_node(allocation.node)
                except exception.NodeNotFound as exc:
                    exc.code = http_client.BAD_REQUEST
                    raise
            else:
                msg = _("Cannot set node when creating an allocation "
                        "in this API version")
                raise exception.Invalid(msg)

        if not allocation.resource_class:
            if node:
                allocation.resource_class = node.resource_class
            else:
                msg = _("The resource_class field is mandatory when not "
                        "backfilling")
                raise exception.Invalid(msg)

        if allocation.candidate_nodes:
            # Convert nodes from names to UUIDs and check their validity
            try:
                converted = api.request.dbapi.check_node_list(
                    allocation.candidate_nodes)
            except exception.NodeNotFound as exc:
                exc.code = http_client.BAD_REQUEST
                raise
            else:
                # Make sure we keep the ordering of candidate nodes.
                allocation.candidate_nodes = [
                    converted[ident] for ident in allocation.candidate_nodes
                ]

        all_dict = allocation.as_dict()

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not all_dict.get('uuid'):
            if node and node.instance_uuid:
                # When backfilling without UUID requested, assume that the
                # target instance_uuid is the desired UUID
                all_dict['uuid'] = node.instance_uuid
            else:
                all_dict['uuid'] = uuidutils.generate_uuid()

        new_allocation = objects.Allocation(context, **all_dict)
        if node:
            new_allocation.node_id = node.id
            topic = api.request.rpcapi.get_topic_for(node)
        else:
            topic = api.request.rpcapi.get_random_topic()

        notify.emit_start_notification(context, new_allocation, 'create')
        with notify.handle_error_notification(context, new_allocation,
                                              'create'):
            new_allocation = api.request.rpcapi.create_allocation(
                context, new_allocation, topic)
        notify.emit_end_notification(context, new_allocation, 'create')

        # Set the HTTP Location Header
        api.response.location = link.build_url('allocations',
                                               new_allocation.uuid)
        return Allocation.convert_with_links(new_allocation)
コード例 #50
0
ファイル: port.py プロジェクト: namnx228/ironic
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        context = api.request.context
        api_utils.check_policy('baremetal:port:create')

        # NOTE(lucasagomes): Create the node_id attribute on-the-fly
        #                    to satisfy the api -> rpc object
        #                    conversion.
        node = api_utils.replace_node_uuid_with_id(port)

        self._check_allowed_port_fields(port)

        portgroup = None
        if port.get('portgroup_uuid'):
            try:
                portgroup = objects.Portgroup.get(api.request.context,
                                                  port.pop('portgroup_uuid'))
                if portgroup.node_id != node.id:
                    raise exception.BadRequest(_('Port can not be added to a '
                                                 'portgroup belonging to a '
                                                 'different node.'))
                # NOTE(lucasagomes): Create the portgroup_id attribute
                #                    on-the-fly to satisfy the api ->
                #                    rpc object conversion.
                port['portgroup_id'] = portgroup.id
            except exception.PortgroupNotFound as e:
                # Change error code because 404 (NotFound) is inappropriate
                # response for a POST request to create a Port
                e.code = http_client.BAD_REQUEST  # BadRequest
                raise e

        if port.get('is_smartnic'):
            try:
                api_utils.LOCAL_LINK_SMART_NIC_VALIDATOR(
                    'local_link_connection',
                    port.get('local_link_connection'))
            except exception.Invalid:
                raise exception.Invalid(
                    "Smart NIC port must have port_id "
                    "and hostname in local_link_connection")

        physical_network = port.get('physical_network')
        if physical_network is not None and not physical_network:
            raise exception.Invalid('A non-empty value is required when '
                                    'setting physical_network')

        vif = api_utils.handle_post_port_like_extra_vif(port)

        if (portgroup and (port.get('pxe_enabled') or vif)):
            if not portgroup.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(
                    msg % portgroup.uuid)

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not port.get('uuid'):
            port['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **port)

        notify_extra = {
            'node_uuid': node.uuid,
            'portgroup_uuid': portgroup and portgroup.uuid or None
        }
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            topic = api.request.rpcapi.get_topic_for(node)
            new_port = api.request.rpcapi.create_port(context, rpc_port,
                                                      topic)
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        api.response.location = link.build_url('ports', new_port.uuid)
        return convert_with_links(new_port)
コード例 #51
0
ファイル: portgroup.py プロジェクト: andornotlee/ironic
    def post(self, portgroup):
        """Create a new portgroup.

        :param portgroup: a portgroup within the request body.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        raise_node_not_found = False
        node = None
        owner = None
        lessee = None
        node_uuid = portgroup.get('node_uuid')
        try:
            # The replace_node_uuid_with_id also checks access to the node
            # and will raise an exception if access is not permitted.
            node = api_utils.replace_node_uuid_with_id(portgroup)
            owner = node.owner
            lessee = node.lessee
        except exception.NotFound:
            raise_node_not_found = True

        # While the rule is for the port, the base object that controls access
        # is the node.
        api_utils.check_owner_policy('node',
                                     'baremetal:portgroup:create',
                                     owner,
                                     lessee=lessee,
                                     conceal_node=False)
        if raise_node_not_found:
            # Delayed raise of NodeNotFound because we want to check
            # the access policy first.
            raise exception.NodeNotFound(node=node_uuid,
                                         code=http_client.BAD_REQUEST)
        context = api.request.context

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties()
                and (portgroup.get('mode') or portgroup.get('properties'))):
            raise exception.NotAcceptable()

        if (portgroup.get('name')
                and not api_utils.is_valid_logical_name(portgroup['name'])):
            error_msg = _("Cannot create portgroup with invalid name "
                          "'%(name)s'") % {
                              'name': portgroup['name']
                          }
            raise exception.ClientSideError(
                error_msg, status_code=http_client.BAD_REQUEST)

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not portgroup.get('uuid'):
            portgroup['uuid'] = uuidutils.generate_uuid()

        new_portgroup = objects.Portgroup(context, **portgroup)

        notify.emit_start_notification(context,
                                       new_portgroup,
                                       'create',
                                       node_uuid=node.uuid)
        with notify.handle_error_notification(context,
                                              new_portgroup,
                                              'create',
                                              node_uuid=node.uuid):
            new_portgroup.create()
        notify.emit_end_notification(context,
                                     new_portgroup,
                                     'create',
                                     node_uuid=node.uuid)

        # Set the HTTP Location Header
        api.response.location = link.build_url('portgroups',
                                               new_portgroup.uuid)
        return convert_with_links(new_portgroup)