def _set_portgroup_uuid(self, value): if value and self._portgroup_uuid != value: if not api_utils.allow_portgroups_subcontrollers(): self._portgroup_uuid = wtypes.Unset return try: portgroup = objects.Portgroup.get(pecan.request.context, value) if portgroup.node_id != self.node_id: raise exception.BadRequest( _('Port can not be added to a ' 'portgroup belonging to a ' 'different node.')) self._portgroup_uuid = portgroup.uuid # NOTE(lucasagomes): Create the portgroup_id attribute # on-the-fly to satisfy the api -> # rpc object conversion. self.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 elif value == wtypes.Unset: self._portgroup_uuid = wtypes.Unset elif value is None and api_utils.allow_portgroups_subcontrollers(): # This is to output portgroup_uuid field if API version allows this self._portgroup_uuid = None
def _update_node_object(self, node): """Update the given node object with the changes here.""" changes = self.obj_get_changes() try: new_instance_uuid = changes.pop('uuid') except KeyError: pass else: node.instance_uuid = new_instance_uuid changes.pop('node_uuid', None) instance_info = node.instance_info for field, value in changes.items(): # NOTE(dtantsur): only instance_info fields can be updated here. try: dest = self.instance_info_mapping_rev[field] except KeyError: # NOTE(dtantsur): this should not happen because of API-level # validations, but checking just in case. raise exception.BadRequest( 'Field %s cannot be set or updated' % changes) instance_info[dest] = value node.instance_info = instance_info return node
def list(self, filters=None, marker=None, limit=30): if marker is None: index = 0 else: for index, image in enumerate(self._images): if image.id == str(marker): index += 1 break else: raise exception.BadRequest('Marker not found') return self._images[index:index + limit]
def _validate_and_remove_traits(fields): """Validate traits in fields for create or update, remove if present. :param fields: a dict of Node fields for create or update. :raises: BadRequest if fields contains a traits that are not None. """ if 'traits' in fields: # NOTE(mgoddard): Traits should be updated via the node # object's traits field, which is itself an object. We shouldn't # get here with changes to traits, as this should be handled by the # API. When services are pinned to Pike, we can get here with # traits set to None in updates, due to changes made to the object # in _convert_to_version. if fields['traits']: # NOTE(mgoddard): We shouldn't get here as this should be # handled by the API. raise exception.BadRequest() fields.pop('traits')
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)
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() # NOTE(lucasagomes): Create the node_id attribute on-the-fly # to satisfy the api -> rpc object # conversion. # NOTE(TheJulia): The get of the node *does* check if the node # can be accessed. We need to be able to get the node regardless # in order to perform the actual policy check. raise_node_not_found = False node = None owner = None lessee = None node_uuid = port.get('node_uuid') try: node = api_utils.replace_node_uuid_with_id(port) 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:port: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 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') if (portgroup and (port.get('pxe_enabled'))): 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 " "portgroup as the port's 'pxe_enabled' field 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)