Beispiel #1
0
 def wrapper(func, *args, **kwargs):
     baymodel_ident = args[1]
     patch = args[2]
     baymodel = api_utils.get_rpc_resource('BayModel', baymodel_ident)
     try:
         baymodel_dict = api_utils.apply_jsonpatch(baymodel.as_dict(),
                                                   patch)
     except api_utils.JSONPATCH_EXCEPTIONS as e:
         raise exception.PatchError(patch=patch, reason=e)
     baymodel = objects.BayModel(pecan.request.context, **baymodel_dict)
     _enforce_network_driver_types(baymodel)
     return func(*args, **kwargs)
Beispiel #2
0
 def wrapper(func, *args, **kwargs):
     cluster_template_ident = args[1]
     patch = args[2]
     cluster_template = api_utils.get_resource('ClusterTemplate',
                                               cluster_template_ident)
     try:
         cluster_template_dict = api_utils.apply_jsonpatch(
             cluster_template.as_dict(), patch)
     except api_utils.JSONPATCH_EXCEPTIONS as e:
         raise exception.PatchError(patch=patch, reason=e)
     _enforce_volume_driver_types(cluster_template_dict)
     return func(*args, **kwargs)
Beispiel #3
0
    def patch(self, cluster_template_ident, patch):
        """Update an existing ClusterTemplate.

        :param cluster_template_ident: UUID or logic name of a
        ClusterTemplate.
        :param patch: a json PATCH document to apply to this
        ClusterTemplate.
        """
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context,
                           'clustertemplate:update_all_projects',
                           action='clustertemplate:update_all_projects')
            context.all_tenants = True
        cluster_template = api_utils.get_resource('ClusterTemplate',
                                                  cluster_template_ident)
        policy.enforce(context,
                       'clustertemplate:update',
                       cluster_template.as_dict(),
                       action='clustertemplate:update')
        try:
            cluster_template_dict = cluster_template.as_dict()
            new_cluster_template = ClusterTemplate(
                **api_utils.apply_jsonpatch(cluster_template_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        new_cluster_template_dict = new_cluster_template.as_dict()
        attr_validator.validate_os_resources(context,
                                             new_cluster_template_dict)
        # check permissions when updating ClusterTemplate public or hidden flag
        if (cluster_template.public != new_cluster_template.public
                or cluster_template.hidden != new_cluster_template.hidden):
            if not policy.enforce(
                    context, "clustertemplate:publish", None, do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

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

        cluster_template.save()
        return ClusterTemplate.convert_with_links(cluster_template)
Beispiel #4
0
 def wrapper(func, *args, **kwargs):
     cluster_template_ident = args[1]
     patch = args[2]
     cluster_template = api_utils.get_resource('ClusterTemplate',
                                               cluster_template_ident)
     try:
         cluster_template_dict = api_utils.apply_jsonpatch(
             cluster_template.as_dict(), patch)
     except api_utils.JSONPATCH_EXCEPTIONS as e:
         raise exception.PatchError(patch=patch, reason=e)
     cluster_template = objects.ClusterTemplate(pecan.request.context,
                                                **cluster_template_dict)
     _enforce_network_driver_types(cluster_template)
     return func(*args, **kwargs)
Beispiel #5
0
    def _patch(self, cluster_ident, patch):
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context,
                           "cluster:update_all_projects",
                           action="cluster:update_all_projects")
            context.all_tenants = True

        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:update',
                       cluster.as_dict(),
                       action='cluster:update')
        policy.enforce(context,
                       "cluster:update_health_status",
                       action="cluster:update_health_status")
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(
                **api_utils.apply_jsonpatch(cluster_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a
        # property so we won't be able to store it in the object. So
        # instead of object_what_changed compare the new and the old
        # clusters.
        delta = set()
        for field in new_cluster.fields:
            if getattr(cluster, field) != getattr(new_cluster, field):
                delta.add(field)

        validation.validate_cluster_properties(delta)

        # NOTE(brtknr): cluster.node_count is the size of the whole cluster
        # which includes non-default nodegroups. However cluster_update expects
        # node_count to be the size of the default_ng_worker therefore return
        # this value unless the patch object says otherwise.
        node_count = cluster.default_ng_worker.node_count
        for p in patch:
            if p['path'] == '/node_count':
                node_count = p.get('value') or new_cluster.node_count

        return (cluster, node_count, new_cluster.health_status,
                new_cluster.health_status_reason)
Beispiel #6
0
    def patch(self, pod_ident, bay_ident, patch):
        """Update an existing pod.

        :param pod_ident: UUID or logical name of a pod.
        :param bay_ident: UUID or logical name of the Bay.
        :param patch: a json PATCH document to apply to this pod.
        """
        pod_dict = {}
        pod_dict['manifest'] = None
        pod_dict['manifest_url'] = None
        try:
            pod = Pod(**api_utils.apply_jsonpatch(pod_dict, patch))
            if pod.manifest or pod.manifest_url:
                pod.parse_manifest()
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        rpc_pod = pecan.request.rpcapi.pod_update(pod_ident, bay_ident,
                                                  pod.manifest)
        return Pod.convert_with_links(rpc_pod)
Beispiel #7
0
    def patch(self, service_ident, bay_ident, patch):
        """Update an existing service.

        :param service_ident: UUID or logical name of a service.
        :param bay_ident: UUID or logical name of the Bay.
        :param patch: a json PATCH document to apply to this service.
        """
        service_dict = {}
        service_dict['manifest'] = None
        service_dict['manifest_url'] = None
        try:
            service = Service(**api_utils.apply_jsonpatch(service_dict, patch))
            if service.manifest or service.manifest_url:
                service.parse_manifest()
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        rpc_service = pecan.request.rpcapi.service_update(
            service_ident, bay_ident, service.manifest)
        return Service.convert_with_links(rpc_service)
Beispiel #8
0
    def patch(self, baymodel_ident, patch):
        """Update an existing Baymodel.

        :param baymodel_ident: UUID or logic name of a Baymodel.
        :param patch: a json PATCH document to apply to this Baymodel.
        """
        context = pecan.request.context
        baymodel = api_utils.get_resource('ClusterTemplate', baymodel_ident)
        policy.enforce(context,
                       'baymodel:update',
                       baymodel.as_dict(),
                       action='baymodel:update')
        try:
            baymodel_dict = baymodel.as_dict()
            new_baymodel = BayModel(
                **api_utils.apply_jsonpatch(baymodel_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        new_baymodel_dict = new_baymodel.as_dict()
        attr_validator.validate_os_resources(context, new_baymodel_dict)
        # check permissions when updating baymodel public flag
        if baymodel.public != new_baymodel.public:
            if not policy.enforce(
                    context, "baymodel:publish", None, do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

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

        baymodel.save()
        return BayModel.convert_with_links(baymodel)
Beispiel #9
0
def apply_jsonpatch(doc, patch):
    for p in patch:
        if p['op'] == 'add' and p['path'].count('/') == 1:
            attr = p['path'].lstrip('/')
            if attr not in doc:
                msg = _("Adding a new attribute %s to the root of "
                        "the resource is not allowed.") % p['path']
                raise wsme.exc.ClientSideError(msg)
            if doc[attr] is not None:
                msg = _("The attribute %s has existed, please use "
                        "'replace' operation instead.") % p['path']
                raise wsme.exc.ClientSideError(msg)

        if p['op'] == 'replace' and p['path'] == '/labels':
            try:
                val = p['value']
                dict_val = val if type(val) == dict else ast.literal_eval(val)
                p['value'] = dict_val
            except (SyntaxError, ValueError, AssertionError) as e:
                raise exception.PatchError(patch=patch, reason=e)
    return jsonpatch.apply_patch(doc, patch)
    def patch(self, rc_ident, bay_ident, patch):
        """Update an existing rc.

        :param rc_ident: UUID or logical name of a ReplicationController.
        :param bay_ident: UUID or logical name of the Bay.
        :param patch: a json PATCH document to apply to this rc.
        """
        rc_dict = {}
        rc_dict['manifest'] = None
        rc_dict['manifest_url'] = None
        try:
            rc = ReplicationController(
                **api_utils.apply_jsonpatch(rc_dict, patch))
            if rc.manifest or rc.manifest_url:
                rc.parse_manifest()
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        rpc_rc = pecan.request.rpcapi.rc_update(rc_ident, bay_ident,
                                                rc.manifest)
        return ReplicationController.convert_with_links(rpc_rc)
    def patch(self, rc_uuid, patch):
        """Update an existing rc.

        :param rc_uuid: UUID of a ReplicationController.
        :param patch: a json PATCH document to apply to this rc.
        """
        if self.from_rcs:
            raise exception.OperationNotPermitted

        rpc_rc = objects.ReplicationController.get_by_uuid(
                                    pecan.request.context, rc_uuid)
        try:
            rc_dict = rpc_rc.as_dict()
            rc = ReplicationController(**api_utils.apply_jsonpatch(rc_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.ReplicationController.fields:
            # ignore manifest_url as it was used for create rc
            if field == 'manifest_url':
                continue
            # ignore manifest as it was used for create rc
            if field == 'manifest':
                continue
            try:
                patch_val = getattr(rc, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_rc[field] != patch_val:
                rpc_rc[field] = patch_val

        rpc_rc.save()
        return ReplicationController.convert_with_links(rpc_rc)
    def patch(self, rc_ident, bay_ident, patch):
        """Update an existing rc.

        :param rc_ident: UUID or logical name of a ReplicationController.
        :param bay_ident: UUID or logical name of the Bay.
        :param patch: a json PATCH document to apply to this rc.
        """
        rpc_rc = api_utils.get_rpc_resource('ReplicationController', rc_ident)
        # Init manifest and manifest_url field because we don't store them
        # in database.
        rpc_rc['manifest'] = None
        rpc_rc['manifest_url'] = None
        try:
            rc_dict = rpc_rc.as_dict()
            rc = ReplicationController(**api_utils.apply_jsonpatch(rc_dict,
                                                                   patch))
            if rc.manifest or rc.manifest_url:
                rc.parse_manifest()
        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.ReplicationController.fields:
            try:
                patch_val = getattr(rc, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_rc[field] != patch_val:
                rpc_rc[field] = patch_val

        if rc.manifest or rc.manifest_url:
            pecan.request.rpcapi.rc_update(rpc_rc)
        else:
            rpc_rc.save()
        return ReplicationController.convert_with_links(rpc_rc)
Beispiel #13
0
    def patch(self, pod_ident, bay_ident, patch):
        """Update an existing pod.

        :param pod_ident: UUID or logical name of a pod.
        :param bay_ident: UUID or logical name of the Bay.
        :param patch: a json PATCH document to apply to this pod.
        """
        rpc_pod = api_utils.get_rpc_resource('Pod', pod_ident)
        # Init manifest and manifest_url field because we don't store them
        # in database.
        rpc_pod['manifest'] = None
        rpc_pod['manifest_url'] = None
        try:
            pod_dict = rpc_pod.as_dict()
            pod = Pod(**api_utils.apply_jsonpatch(pod_dict, patch))
            if pod.manifest or pod.manifest_url:
                pod.parse_manifest()
        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.Pod.fields:
            try:
                patch_val = getattr(pod, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_pod[field] != patch_val:
                rpc_pod[field] = patch_val

        if pod.manifest or pod.manifest_url:
            pecan.request.rpcapi.pod_update(rpc_pod)
        else:
            rpc_pod.save()
        return Pod.convert_with_links(rpc_pod)
Beispiel #14
0
    def patch(self, cluster_ident, patch):
        """Update an existing bay.

        :param cluster_ident: UUID or logical name of a bay.
        :param patch: a json PATCH document to apply to this bay.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Bay', cluster_ident)
        policy.enforce(context,
                       'cluster:update',
                       cluster,
                       action='cluster:update')
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(
                **api_utils.apply_jsonpatch(cluster_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.Bay.fields:
            try:
                patch_val = getattr(new_cluster, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if cluster[field] != patch_val:
                cluster[field] = patch_val

        delta = cluster.obj_what_changed()

        validate_bay_properties(delta)

        pecan.request.rpcapi.bay_update_async(cluster)
        return ClusterID(cluster.uuid)
Beispiel #15
0
    def patch(self, service_ident, patch):
        """Update an existing service.

        :param service_ident: UUID or logical name of a service.
        :param patch: a json PATCH document to apply to this service.
        """
        rpc_service = api_utils.get_rpc_resource('Service', service_ident)
        # Init manifest and manifest_url field because we don't store them
        # in database.
        rpc_service['manifest'] = None
        rpc_service['manifest_url'] = None
        try:
            service_dict = rpc_service.as_dict()
            service = Service(**api_utils.apply_jsonpatch(service_dict, patch))
            if service.manifest or service.manifest_url:
                service.parse_manifest()
        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.Service.fields:
            try:
                patch_val = getattr(service, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_service[field] != patch_val:
                rpc_service[field] = patch_val

        if service.manifest or service.manifest_url:
            pecan.request.rpcapi.service_update(rpc_service)
        else:
            rpc_service.save()
        return Service.convert_with_links(rpc_service)
Beispiel #16
0
    def patch(self, service_uuid, patch):
        """Update an existing service.

        :param service_uuid: UUID of a service.
        :param patch: a json PATCH document to apply to this service.
        """
        if self.from_services:
            raise exception.OperationNotPermitted

        rpc_service = objects.Service.get_by_uuid(pecan.request.context,
                                                  service_uuid)
        try:
            service_dict = rpc_service.as_dict()
            service = Service(**api_utils.apply_jsonpatch(service_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.Service.fields:
            # ignore manifest_url as it was used for create service
            if field == 'manifest_url':
                continue
            if field == 'manifest':
                continue
            try:
                patch_val = getattr(service, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if rpc_service[field] != patch_val:
                rpc_service[field] = patch_val

        rpc_service.save()
        return Service.convert_with_links(rpc_service)
Beispiel #17
0
 def test_PatchError(self):
     self.assertRaises(exception.PatchError,
                       lambda: self.raise_(exception.PatchError()))