def add_uuid_filter(query, value): if utils.is_int_like(value): return query.filter_by(id=value) elif uuidutils.is_uuid_like(value): return query.filter_by(uuid=value) else: raise exception.InvalidUUID(uuid=value)
def get_node_by_instance(self, instance): if not utils.is_uuid_like(instance): raise exception.InvalidUUID(uuid=instance) query = (model_query(models.Node).filter_by(instance_uuid=instance)) try: result = query.one() except NoResultFound: raise exception.InstanceNotFound(instance=instance) return result
def get_node_by_instance(self, instance): if not uuidutils.is_uuid_like(instance): raise exception.InvalidUUID(uuid=instance) query = _get_node_query_with_tags() query = query.filter_by(instance_uuid=instance) try: result = query.one() except NoResultFound: raise exception.InstanceNotFound(instance=instance) return result
def validate(value): if not uuidutils.is_uuid_like(value): raise exception.InvalidUUID(uuid=value) return value
def patch(self, connector_uuid, patch): """Update an existing volume connector. :param connector_uuid: UUID of a volume connector. :param patch: a json PATCH document to apply to this volume connector. :returns: API-serializable volume connector object. :raises: OperationNotPermitted if accessed with specifying a parent node. :raises: PatchError if a given patch can not be applied. :raises: VolumeConnectorNotFound if no volume connector exists with the specified UUID. :raises: InvalidParameterValue if the volume connector's UUID is being changed :raises: NodeLocked if node is locked by another conductor :raises: NodeNotFound if the node associated with the connector does not exist :raises: VolumeConnectorTypeAndIdAlreadyExists if another connector already exists with the same values for type and connector_id fields :raises: InvalidUUID if invalid node UUID is passed in the patch. :raises: InvalidStateRequested If a node associated with the volume connector is not powered off. """ context = pecan.request.context cdict = context.to_policy_values() policy.authorize('baremetal:volume:update', cdict, cdict) if self.parent_node_ident: raise exception.OperationNotPermitted() values = api_utils.get_patch_values(patch, '/node_uuid') for value in values: if not uuidutils.is_uuid_like(value): message = _("Expected a UUID for node_uuid, but received " "%(uuid)s.") % { 'uuid': six.text_type(value) } raise exception.InvalidUUID(message=message) rpc_connector = objects.VolumeConnector.get_by_uuid( context, connector_uuid) try: connector_dict = rpc_connector.as_dict() # NOTE(smoriya): # 1) Remove node_id because it's an internal value and # not present in the API object # 2) Add node_uuid connector_dict['node_uuid'] = connector_dict.pop('node_id', None) connector = VolumeConnector( **api_utils.apply_jsonpatch(connector_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed. for field in objects.VolumeConnector.fields: try: patch_val = getattr(connector, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_connector[field] != patch_val: rpc_connector[field] = patch_val rpc_node = objects.Node.get_by_id(context, rpc_connector.node_id) notify.emit_start_notification(context, rpc_connector, 'update', node_uuid=rpc_node.uuid) with notify.handle_error_notification(context, rpc_connector, 'update', node_uuid=rpc_node.uuid): topic = pecan.request.rpcapi.get_topic_for(rpc_node) new_connector = pecan.request.rpcapi.update_volume_connector( context, rpc_connector, topic) api_connector = VolumeConnector.convert_with_links(new_connector) notify.emit_end_notification(context, new_connector, 'update', node_uuid=rpc_node.uuid) return api_connector
def patch(self, target_uuid, patch): """Update an existing volume target. :param target_uuid: UUID of a volume target. :param patch: a json PATCH document to apply to this volume target. :returns: API-serializable volume target object. :raises: OperationNotPermitted if accessed with specifying a parent node. :raises: PatchError if a given patch can not be applied. :raises: InvalidParameterValue if the volume target's UUID is being changed :raises: NodeLocked if the node is already locked :raises: NodeNotFound if the node associated with the volume target does not exist :raises: VolumeTargetNotFound if the volume target cannot be found :raises: VolumeTargetBootIndexAlreadyExists if a volume target already exists with the same node ID and boot index values :raises: InvalidUUID if invalid node UUID is passed in the patch. :raises: InvalidStateRequested If a node associated with the volume target is not powered off. """ context = api.request.context api_utils.check_policy('baremetal:volume:update') if self.parent_node_ident: raise exception.OperationNotPermitted() api_utils.patch_validate_allowed_fields(patch, PATCH_ALLOWED_FIELDS) values = api_utils.get_patch_values(patch, '/node_uuid') for value in values: if not uuidutils.is_uuid_like(value): message = _("Expected a UUID for node_uuid, but received " "%(uuid)s.") % { 'uuid': str(value) } raise exception.InvalidUUID(message=message) rpc_target = objects.VolumeTarget.get_by_uuid(context, target_uuid) target_dict = rpc_target.as_dict() # NOTE(smoriya): # 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(target_dict) target_dict = api_utils.apply_jsonpatch(target_dict, patch) try: if target_dict['node_uuid'] != rpc_node.uuid: rpc_node = objects.Node.get(api.request.context, target_dict['node_uuid']) except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a PATCH request to change a volume target e.code = http_client.BAD_REQUEST # BadRequest raise api_utils.patched_validate_with_schema(target_dict, TARGET_SCHEMA, TARGET_VALIDATOR) api_utils.patch_update_changed_fields( target_dict, rpc_target, fields=objects.VolumeTarget.fields, schema=TARGET_SCHEMA, id_map={'node_id': rpc_node.id}) notify.emit_start_notification(context, rpc_target, 'update', node_uuid=rpc_node.uuid) with notify.handle_error_notification(context, rpc_target, 'update', node_uuid=rpc_node.uuid): topic = api.request.rpcapi.get_topic_for(rpc_node) new_target = api.request.rpcapi.update_volume_target( context, rpc_target, topic) api_target = convert_with_links(new_target) notify.emit_end_notification(context, new_target, 'update', node_uuid=rpc_node.uuid) return api_target
def patch(self, target_uuid, patch): """Update an existing volume target. :param target_uuid: UUID of a volume target. :param patch: a json PATCH document to apply to this volume target. :returns: API-serializable volume target object. :raises: OperationNotPermitted if accessed with specifying a parent node. :raises: PatchError if a given patch can not be applied. :raises: InvalidParameterValue if the volume target's UUID is being changed :raises: NodeLocked if the node is already locked :raises: NodeNotFound if the node associated with the volume target does not exist :raises: VolumeTargetNotFound if the volume target cannot be found :raises: VolumeTargetBootIndexAlreadyExists if a volume target already exists with the same node ID and boot index values :raises: InvalidUUID if invalid node UUID is passed in the patch. :raises: InvalidStateRequested If a node associated with the volume target is not powered off. """ context = api.request.context cdict = context.to_policy_values() policy.authorize('baremetal:volume:update', cdict, cdict) if self.parent_node_ident: raise exception.OperationNotPermitted() values = api_utils.get_patch_values(patch, '/node_uuid') for value in values: if not uuidutils.is_uuid_like(value): message = _("Expected a UUID for node_uuid, but received " "%(uuid)s.") % {'uuid': str(value)} raise exception.InvalidUUID(message=message) rpc_target = objects.VolumeTarget.get_by_uuid(context, target_uuid) target_dict = rpc_target.as_dict() # NOTE(smoriya): # 1) Remove node_id because it's an internal value and # not present in the API object # 2) Add node_uuid target_dict['node_uuid'] = target_dict.pop('node_id', None) target = VolumeTarget( **api_utils.apply_jsonpatch(target_dict, patch)) # Update only the fields that have changed. for field in objects.VolumeTarget.fields: try: patch_val = getattr(target, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == atypes.Unset: patch_val = None if rpc_target[field] != patch_val: rpc_target[field] = patch_val rpc_node = objects.Node.get_by_id(context, rpc_target.node_id) notify.emit_start_notification(context, rpc_target, 'update', node_uuid=rpc_node.uuid) with notify.handle_error_notification(context, rpc_target, 'update', node_uuid=rpc_node.uuid): topic = api.request.rpcapi.get_topic_for(rpc_node) new_target = api.request.rpcapi.update_volume_target( context, rpc_target, topic) api_target = VolumeTarget.convert_with_links(new_target) notify.emit_end_notification(context, new_target, 'update', node_uuid=rpc_node.uuid) return api_target
def patch(self, connector_uuid, patch): """Update an existing volume connector. :param connector_uuid: UUID of a volume connector. :param patch: a json PATCH document to apply to this volume connector. :returns: API-serializable volume connector object. :raises: OperationNotPermitted if accessed with specifying a parent node. :raises: PatchError if a given patch can not be applied. :raises: VolumeConnectorNotFound if no volume connector exists with the specified UUID. :raises: InvalidParameterValue if the volume connector's UUID is being changed :raises: NodeLocked if node is locked by another conductor :raises: NodeNotFound if the node associated with the connector does not exist :raises: VolumeConnectorTypeAndIdAlreadyExists if another connector already exists with the same values for type and connector_id fields :raises: InvalidUUID if invalid node UUID is passed in the patch. :raises: InvalidStateRequested If a node associated with the volume connector is not powered off. """ context = api.request.context rpc_connector, rpc_node = api_utils.check_volume_policy_and_retrieve( 'baremetal:volume:update', connector_uuid, target=False) if self.parent_node_ident: raise exception.OperationNotPermitted() api_utils.patch_validate_allowed_fields(patch, PATCH_ALLOWED_FIELDS) for value in api_utils.get_patch_values(patch, '/node_uuid'): if not uuidutils.is_uuid_like(value): message = _("Expected a UUID for node_uuid, but received " "%(uuid)s.") % {'uuid': str(value)} raise exception.InvalidUUID(message=message) connector_dict = rpc_connector.as_dict() # NOTE(smoriya): # 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(connector_dict) connector_dict = api_utils.apply_jsonpatch(connector_dict, patch) try: if connector_dict['node_uuid'] != rpc_node.uuid: rpc_node = objects.Node.get( api.request.context, connector_dict['node_uuid']) except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a PATCH request to change a Port e.code = http_client.BAD_REQUEST # BadRequest raise api_utils.patched_validate_with_schema( connector_dict, CONNECTOR_SCHEMA, CONNECTOR_VALIDATOR) api_utils.patch_update_changed_fields( connector_dict, rpc_connector, fields=objects.VolumeConnector.fields, schema=CONNECTOR_SCHEMA, id_map={'node_id': rpc_node.id} ) notify.emit_start_notification(context, rpc_connector, 'update', node_uuid=rpc_node.uuid) with notify.handle_error_notification(context, rpc_connector, 'update', node_uuid=rpc_node.uuid): topic = api.request.rpcapi.get_topic_for(rpc_node) new_connector = api.request.rpcapi.update_volume_connector( context, rpc_connector, topic) api_connector = convert_with_links(new_connector) notify.emit_end_notification(context, new_connector, 'update', node_uuid=rpc_node.uuid) return api_connector