예제 #1
0
    def delete(self, portgroup_ident):
        """Delete a portgroup.

        :param portgroup_ident: UUID or logical name of a portgroup.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

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

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        rpc_portgroup = api_utils.get_rpc_portgroup_with_suffix(
            portgroup_ident)
        rpc_node = objects.Node.get_by_id(pecan.request.context,
                                          rpc_portgroup.node_id)

        notify.emit_start_notification(context,
                                       rpc_portgroup,
                                       'delete',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context,
                                              rpc_portgroup,
                                              'delete',
                                              node_uuid=rpc_node.uuid):
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
            pecan.request.rpcapi.destroy_portgroup(context, rpc_portgroup,
                                                   topic)
        notify.emit_end_notification(context,
                                     rpc_portgroup,
                                     'delete',
                                     node_uuid=rpc_node.uuid)
예제 #2
0
    def get_one(self, portgroup_ident, fields=None):
        """Retrieve information about the given portgroup.

        :param portgroup_ident: UUID or logical name of a portgroup.
        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

        api_utils.check_policy('baremetal:portgroup:get')

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        api_utils.check_allowed_portgroup_fields(fields)

        rpc_portgroup = api_utils.get_rpc_portgroup_with_suffix(
            portgroup_ident)
        return convert_with_links(rpc_portgroup, fields=fields)
예제 #3
0
    def patch(self, portgroup_ident, patch):
        """Update an existing portgroup.

        :param portgroup_ident: UUID or logical name of a portgroup.
        :param patch: a json PATCH document to apply to this portgroup.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

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

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties()
                and (api_utils.is_path_updated(patch, '/mode')
                     or api_utils.is_path_updated(patch, '/properties'))):
            raise exception.NotAcceptable()

        rpc_portgroup = api_utils.get_rpc_portgroup_with_suffix(
            portgroup_ident)

        names = api_utils.get_patch_values(patch, '/name')
        for name in names:
            if (name and not api_utils.is_valid_logical_name(name)):
                error_msg = _("Portgroup %(portgroup)s: Cannot change name to"
                              " invalid name '%(name)s'") % {
                                  'portgroup': portgroup_ident,
                                  'name': name
                              }
                raise wsme.exc.ClientSideError(
                    error_msg, status_code=http_client.BAD_REQUEST)

        try:
            portgroup_dict = rpc_portgroup.as_dict()
            # NOTE:
            # 1) Remove node_id because it's an internal value and
            #    not present in the API object
            # 2) Add node_uuid
            portgroup_dict['node_uuid'] = portgroup_dict.pop('node_id', None)
            portgroup = Portgroup(
                **api_utils.apply_jsonpatch(portgroup_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        api_utils.handle_patch_port_like_extra_vif(rpc_portgroup, portgroup,
                                                   patch)

        # Update only the fields that have changed
        for field in objects.Portgroup.fields:
            try:
                patch_val = getattr(portgroup, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_portgroup[field] != patch_val:
                rpc_portgroup[field] = patch_val

        rpc_node = objects.Node.get_by_id(context, rpc_portgroup.node_id)
        if (rpc_node.provision_state == ir_states.INSPECTING
                and api_utils.allow_inspect_wait_state()):
            msg = _('Cannot update portgroup "%(portgroup)s" on node '
                    '"%(node)s" while it is in state "%(state)s".') % {
                        'portgroup': rpc_portgroup.uuid,
                        'node': rpc_node.uuid,
                        'state': ir_states.INSPECTING
                    }
            raise wsme.exc.ClientSideError(msg,
                                           status_code=http_client.CONFLICT)

        notify.emit_start_notification(context,
                                       rpc_portgroup,
                                       'update',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context,
                                              rpc_portgroup,
                                              'update',
                                              node_uuid=rpc_node.uuid):
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
            new_portgroup = pecan.request.rpcapi.update_portgroup(
                context, rpc_portgroup, topic)

        api_portgroup = Portgroup.convert_with_links(new_portgroup)
        notify.emit_end_notification(context,
                                     new_portgroup,
                                     'update',
                                     node_uuid=api_portgroup.node_uuid)

        return api_portgroup
예제 #4
0
    def patch(self, portgroup_ident, patch):
        """Update an existing portgroup.

        :param portgroup_ident: UUID or logical name of a portgroup.
        :param patch: a json PATCH document to apply to this portgroup.
        """
        if not api_utils.allow_portgroups():
            raise exception.NotFound()

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

        if self.parent_node_ident:
            raise exception.OperationNotPermitted()

        if (not api_utils.allow_portgroup_mode_properties()
                and (api_utils.is_path_updated(patch, '/mode')
                     or api_utils.is_path_updated(patch, '/properties'))):
            raise exception.NotAcceptable()

        api_utils.patch_validate_allowed_fields(patch, PATCH_ALLOWED_FIELDS)

        rpc_portgroup = api_utils.get_rpc_portgroup_with_suffix(
            portgroup_ident)

        names = api_utils.get_patch_values(patch, '/name')
        for name in names:
            if (name and not api_utils.is_valid_logical_name(name)):
                error_msg = _("Portgroup %(portgroup)s: Cannot change name to"
                              " invalid name '%(name)s'") % {
                                  'portgroup': portgroup_ident,
                                  'name': name
                              }
                raise exception.ClientSideError(
                    error_msg, status_code=http_client.BAD_REQUEST)

        portgroup_dict = rpc_portgroup.as_dict()

        # NOTE:
        # 1) Remove node_id because it's an internal value and
        #    not present in the API object
        # 2) Add node_uuid
        rpc_node = api_utils.replace_node_id_with_uuid(portgroup_dict)

        portgroup_dict = api_utils.apply_jsonpatch(portgroup_dict, patch)

        if 'mode' not in portgroup_dict:
            msg = _("'mode' is a mandatory attribute and can not be removed")
            raise exception.ClientSideError(msg)

        try:
            if portgroup_dict['node_uuid'] != rpc_node.uuid:
                rpc_node = objects.Node.get(api.request.context,
                                            portgroup_dict['node_uuid'])

        except exception.NodeNotFound as e:
            # Change error code because 404 (NotFound) is inappropriate
            # response for a POST request to patch a Portgroup
            e.code = http_client.BAD_REQUEST  # BadRequest
            raise

        api_utils.handle_patch_port_like_extra_vif(
            rpc_portgroup, portgroup_dict.get('internal_info'), patch)

        api_utils.patched_validate_with_schema(portgroup_dict,
                                               PORTGROUP_PATCH_SCHEMA,
                                               PORTGROUP_PATCH_VALIDATOR)

        api_utils.patch_update_changed_fields(portgroup_dict,
                                              rpc_portgroup,
                                              fields=objects.Portgroup.fields,
                                              schema=PORTGROUP_PATCH_SCHEMA,
                                              id_map={'node_id': rpc_node.id})

        if (rpc_node.provision_state == ir_states.INSPECTING
                and api_utils.allow_inspect_wait_state()):
            msg = _('Cannot update portgroup "%(portgroup)s" on node '
                    '"%(node)s" while it is in state "%(state)s".') % {
                        'portgroup': rpc_portgroup.uuid,
                        'node': rpc_node.uuid,
                        'state': ir_states.INSPECTING
                    }
            raise exception.ClientSideError(msg,
                                            status_code=http_client.CONFLICT)

        notify.emit_start_notification(context,
                                       rpc_portgroup,
                                       'update',
                                       node_uuid=rpc_node.uuid)
        with notify.handle_error_notification(context,
                                              rpc_portgroup,
                                              'update',
                                              node_uuid=rpc_node.uuid):
            topic = api.request.rpcapi.get_topic_for(rpc_node)
            new_portgroup = api.request.rpcapi.update_portgroup(
                context, rpc_portgroup, topic)

        api_portgroup = convert_with_links(new_portgroup)
        notify.emit_end_notification(context,
                                     new_portgroup,
                                     'update',
                                     node_uuid=rpc_node.uuid)

        return api_portgroup