Ejemplo n.º 1
0
    def _validate_arq_patch(self, patch):
        """Validate a single patch for an ARQ.

        :param patch: a JSON PATCH document.
            The patch must be of the form [{..}], as specified in the
            value field of arq_uuid in patch() method below.
        :returns: dict of valid fields
        """
        valid_fields = {
            'hostname': None,
            'device_rp_uuid': None,
            'instance_uuid': None
        }
        if ((not all(p['op'] == 'add' for p in patch))
                and (not all(p['op'] == 'remove' for p in patch))):
            raise exception.PatchError(reason='Every op must be add or remove')

        for p in patch:
            path = p['path'].lstrip('/')
            if path not in valid_fields.keys():
                reason = 'Invalid path in patch {}'.format(p['path'])
                raise exception.PatchError(reason=reason)
            if p['op'] == 'add':
                valid_fields[path] = p['value']
        not_found = [
            field for field, value in valid_fields.items() if value is None
        ]
        if patch[0]['op'] == 'add' and len(not_found) > 0:
            msg = ','.join(not_found)
            reason = _('Fields absent in patch {}').format(msg)
            raise exception.PatchError(reason=reason)

        return valid_fields
Ejemplo n.º 2
0
    def patch(self, uuid, patch):
        """Update a deployable.
        :param uuid: UUID of a deployable.
        :param patch: a json PATCH document to apply to this deployable.
        """
        context = pecan.request.context
        obj_dep = objects.Deployable.get(context, uuid)

        try:
            api_dep = Deployable(
                **api_utils.apply_jsonpatch(obj_dep.as_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.Deployable.fields:
            try:
                patch_val = getattr(api_dep, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if obj_dep[field] != patch_val:
                obj_dep[field] = patch_val

        new_dep = pecan.request.conductor_api.deployable_update(
            context, obj_dep)
        return Deployable.convert_with_links(new_dep)
Ejemplo n.º 3
0
    def patch(self, uuid, patch):
        """Update an accelerator.

        :param uuid: UUID of an accelerator.
        :param patch: a json PATCH document to apply to this accelerator.
        """
        obj_acc = self._resource or self._get_resource(uuid)
        try:
            api_acc = Accelerator(
                **api_utils.apply_jsonpatch(obj_acc.as_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.Accelerator.fields:
            try:
                patch_val = getattr(api_acc, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if obj_acc[field] != patch_val:
                obj_acc[field] = patch_val

        context = pecan.request.context
        new_acc = pecan.request.conductor_api.accelerator_update(
            context, obj_acc)
        return Accelerator.convert_with_links(new_acc)
Ejemplo n.º 4
0
    def put(self, uuid, patch):
        """Update an port's property.
        : param uuid: UUID of a port.
        : param patch: a json PATCH document to apply to this port.
        """
        obj_port = self._resource or self._get_resource(uuid)
        try:
            api_port = Port(
                **api_utils.apply_jsonpatch(obj_port.as_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.Port.fields:
            try:
                patch_val = getattr(api_port, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue

            if patch_val == wtypes.Unset:
                patch_val = None
            if obj_port[field] != patch_val:
                obj_port[field] = patch_val

        context = pecan.request.context
        new_port = pecan.request.conductor_api.port_update(context, obj_port)
        return Port.convert_with_links(new_port)
Ejemplo n.º 5
0
    def _validate_arq_patch(self, patch):
        """Validate a single patch for an ARQ.

        :param patch: a JSON PATCH document.
            The patch must be of the form [{..}], as specified in the
            value field of arq_uuid in patch() method below.
        :returns: dict of valid fields
        """
        valid_fields = {
            'hostname': None,
            'device_rp_uuid': None,
            'instance_uuid': None
        }
        if utils.allow_project_id():
            valid_fields['project_id'] = None
        if ((not all(p['op'] == 'add' for p in patch))
                and (not all(p['op'] == 'remove' for p in patch))):
            raise exception.PatchError(reason='Every op must be add or remove')

        for p in patch:
            path = p['path'].lstrip('/')
            if path == 'project_id' and not utils.allow_project_id():
                raise exception.NotAcceptable(
                    _("Request not acceptable. The minimal required API "
                      "version should be %(base)s.%(opr)s") % {
                          'base': versions.BASE_VERSION,
                          'opr': versions.MINOR_1_PROJECT_ID
                      })
            if path not in valid_fields.keys():
                reason = 'Invalid path in patch {}'.format(p['path'])
                raise exception.PatchError(reason=reason)
            if p['op'] == 'add':
                valid_fields[path] = p['value']
        not_found = [
            field for field, value in valid_fields.items() if value is None
        ]
        if patch[0]['op'] == 'add' and len(not_found) > 0:
            msg = ','.join(not_found)
            reason = _('Fields absent in patch {}').format(msg)
            raise exception.PatchError(reason=reason)

        return valid_fields
Ejemplo n.º 6
0
 def _check_if_already_bound(context, valid_fields):
     patch_fields = list(valid_fields.values())[0]
     instance_uuid = patch_fields['instance_uuid']
     extarqs = objects.ExtARQ.list(context)
     extarqs_for_instance = [
         extarq for extarq in extarqs
         if extarq.arq['instance_uuid'] == instance_uuid
     ]
     if extarqs_for_instance:  # duplicate binding request
         msg = _('Instance {} already has accelerator requests. '
                 'Cannot bind additional ARQs.')
         reason = msg.format(instance_uuid)
         raise exception.PatchError(reason=reason)
Ejemplo n.º 7
0
    def patch(self, uuid, patch):
        """Update a deployable.

        Usage: curl -X PATCH {ip}:{port}/v1/accelerators/deployables/
        {deployable_uuid} -d '[{"path":"/instance_uuid","value":
        {instance_uuid}, "op":"replace"}]'  -H "Content-type:
        application/json"

        :param uuid: UUID of a deployable.
        :param patch: a json PATCH document to apply to this deployable.
        """
        context = pecan.request.context
        reservations = None

        obj_dep = objects.Deployable.get(context, uuid)
        try:
            # TODO(xinran): need more discussion on quota's granularity.
            # Now we count by board.
            for p in patch:
                if p["path"] == "/instance_uuid" and p["op"] == "replace":
                    if not p["value"]:
                        obj_dep["assignable"] = True
                        reserve_opts = {obj_dep["board"]: -1}
                    else:
                        obj_dep["assignable"] = False
                        reserve_opts = {obj_dep["board"]: 1}
                    reservations = QUOTAS.reserve(context, reserve_opts)
            api_dep = Deployable(
                **api_utils.apply_jsonpatch(obj_dep.as_dict(), patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            QUOTAS.rollback(context, reservations, project_id=None)
            raise exception.PatchError(patch=patch, reason=e)

        QUOTAS.commit(context, reservations)

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

        new_dep = pecan.request.conductor_api.deployable_update(
            context, obj_dep)
        return Deployable.convert_with_links(new_dep)