def create(self, share_proto, size, snapshot_id=None, name=None,
               description=None, metadata=None, share_network=None,
               share_type=None, is_public=False, availability_zone=None,
               consistency_group_id=None):
        """Create a share.

        :param share_proto: text - share protocol for new share
            available values are NFS, CIFS, GlusterFS and HDFS.
        :param size: int - size in GiB
        :param snapshot_id: text - ID of the snapshot
        :param name: text - name of new share
        :param description: text - description of a share
        :param metadata: dict - optional metadata to set on share creation
        :param share_network: either instance of ShareNetwork or text with ID
        :param share_type: either instance of ShareType or text with ID
        :param is_public: bool, whether to set share as public or not.
        :param consistency_group_id: text - ID of the consistency group to
            which the share should belong
        :rtype: :class:`Share`
        """
        share_metadata = metadata if metadata is not None else dict()
        body = {
            'size': size,
            'snapshot_id': snapshot_id,
            'name': name,
            'description': description,
            'metadata': share_metadata,
            'share_proto': share_proto,
            'share_network_id': common_base.getid(share_network),
            'share_type': common_base.getid(share_type),
            'is_public': is_public,
            'availability_zone': availability_zone,
            'consistency_group_id': consistency_group_id,
        }
        return self._create('/shares', {'share': body}, 'share')
Example #2
0
    def create(self, share_network=None, name=None, description=None,
               source_cgsnapshot_id=None, share_types=None):
        """Create a Consistency Group.

        :param share_network: either the share network object or text of the
            uuid - represents the share network to use when creating a
            consistency group with multi-svm capabilities.
        :param name: text - name of the new consistency group
        :param description: text - description of the consistency group
        :param source_cgsnapshot_id: text - The uuid of the cgsnapshot from
            which this CG was created. Cannot be supplied when 'share_types'
            is provided.
        :param share_types: List of the share types that shares in the CG are
            allowed to be a part of. Cannot be supplied when
            'source_cgsnapshot_id' is provided.
        :rtype: :class:`ConsistencyGroup`
        """
        if share_types:
            share_types = [common_base.getid(share_type)
                           for share_type in share_types]

        body = {'name': name, 'description': description}

        share_network_id = None
        if share_network:
            share_network_id = common_base.getid(share_network)
        if share_network_id:
            body['share_network_id'] = share_network_id
        if source_cgsnapshot_id:
            body['source_cgsnapshot_id'] = source_cgsnapshot_id
        if share_types:
            body['share_types'] = share_types
        return self._create(RESOURCES_PATH,
                            {RESOURCE_NAME: body}, RESOURCE_NAME)
    def create(self, share_network=None, name=None, description=None,
               source_cgsnapshot_id=None, share_types=None):
        """Create a Consistency Group.

        :param share_network: either the share network object or text of the
            uuid - represents the share network to use when creating a
            consistency group with multi-svm capabilities.
        :param name: text - name of the new consistency group
        :param description: text - description of the consistency group
        :param source_cgsnapshot_id: text - The uuid of the cgsnapshot from
            which this CG was created. Cannot be supplied when 'share_types'
            is provided.
        :param share_types: List of the share types that shares in the CG are
            allowed to be a part of. Cannot be supplied when
            'source_cgsnapshot_id' is provided.
        :rtype: :class:`ConsistencyGroup`
        """
        if share_types:
            share_types = [common_base.getid(share_type)
                           for share_type in share_types]

        body = {'name': name, 'description': description}

        share_network_id = None
        if share_network:
            share_network_id = common_base.getid(share_network)
        if share_network_id:
            body['share_network_id'] = share_network_id
        if source_cgsnapshot_id:
            body['source_cgsnapshot_id'] = source_cgsnapshot_id
        if share_types:
            body['share_types'] = share_types
        return self._create(RESOURCES_PATH,
                            {RESOURCE_NAME: body}, RESOURCE_NAME)
 def get(self, share, export_location):
     """Get a share export location."""
     share_id = common_base.getid(share)
     export_location_id = common_base.getid(export_location)
     return self._get(
         "/shares/%(share_id)s/export_locations/%(export_location_id)s" % {
             "share_id": share_id,
             "export_location_id": export_location_id}, "export_location")
Example #5
0
 def get(self, share, export_location):
     """Get a share export location."""
     share_id = common_base.getid(share)
     export_location_id = common_base.getid(export_location)
     return self._get(
         "/shares/%(share_id)s/export_locations/%(export_location_id)s" % {
             "share_id": share_id,
             "export_location_id": export_location_id
         }, "export_location")
    def unmanage(self, share):
        """Unmanage a share.

        :param share: either share object or text with its ID.
        """
        return self.api.client.post(
            "/os-share-unmanage/%s/unmanage" % common_base.getid(share))
    def get_metadata(self, share):
        """Get metadata of a share.

        :param share: either share object or text with its ID.
        """
        return self._get("/shares/%s/metadata" % common_base.getid(share),
                         "metadata")
Example #8
0
    def unmanage(self, share):
        """Unmanage a share.

        :param share: either share object or text with its ID.
        """
        return self.api.client.post("/os-share-unmanage/%s/unmanage" %
                                    common_base.getid(share))
    def update(self, share_network, neutron_net_id=None,
               neutron_subnet_id=None, nova_net_id=None,
               name=None, description=None):
        """Updates a share network.

        :param share_network: share network to update.
        :rtype: :class:`ShareNetwork`
        """
        values = {}
        if neutron_net_id is not None:
            values['neutron_net_id'] = neutron_net_id
        if neutron_subnet_id is not None:
            values['neutron_subnet_id'] = neutron_subnet_id
        if nova_net_id is not None:
            values['nova_net_id'] = nova_net_id
        if name is not None:
            values['name'] = name
        if description is not None:
            values['description'] = description

        for k, v in six.iteritems(values):
            if v == '':
                values[k] = None

        if not values:
            msg = "Must specify fields to be updated"
            raise exceptions.CommandError(msg)

        body = {RESOURCE_NAME: values}
        return self._update(RESOURCE_PATH % common_base.getid(share_network),
                            body,
                            RESOURCE_NAME)
Example #10
0
    def get_metadata(self, share):
        """Get metadata of a share.

        :param share: either share object or text with its ID.
        """
        return self._get("/shares/%s/metadata" % common_base.getid(share),
                         "metadata")
    def list(self, share_type):
        if share_type.is_public:
            return None

        return self._list(
            '/types/%s/os-share-type-access' % common_base.getid(share_type),
            'share_type_access')
Example #12
0
    def update(self, share_network, neutron_net_id=None,
               neutron_subnet_id=None, nova_net_id=None,
               name=None, description=None):
        """Updates a share network.

        :param share_network: share network to update.
        :rtype: :class:`ShareNetwork`
        """
        values = {}
        if neutron_net_id:
            values['neutron_net_id'] = neutron_net_id
        if neutron_subnet_id:
            values['neutron_subnet_id'] = neutron_subnet_id
        if nova_net_id:
            values['nova_net_id'] = nova_net_id
        if name:
            values['name'] = name
        if description:
            values['description'] = description

        if not values:
            msg = "Must specify fields to be updated"
            raise exceptions.CommandError(msg)

        body = {RESOURCE_NAME: values}
        return self._update(RESOURCE_PATH % common_base.getid(share_network),
                            body,
                            RESOURCE_NAME)
    def get(self, share):
        """Get a share.

        :param share: either share object or text with its ID.
        :rtype: :class:`Share`
        """
        share_id = common_base.getid(share)
        return self._get("/shares/%s" % share_id, "share")
Example #14
0
    def get(self, share):
        """Get a share.

        :param share: either share object or text with its ID.
        :rtype: :class:`Share`
        """
        share_id = common_base.getid(share)
        return self._get("/shares/%s" % share_id, "share")
    def get(self, share_network):
        """Get a share network.

        :param policy: share network to get.
        :rtype: :class:`NetworkInfo`
        """
        return self._get(RESOURCE_PATH % common_base.getid(share_network),
                         RESOURCE_NAME)
Example #16
0
    def remove_security_service(self, share_network, security_service):
        """Dissociate security service from a share network.

        :param share_network: share network name, id or ShareNetwork instance
        :param security_service: name, id or SecurityService instance
        :rtype: :class:`ShareNetwork`
        """
        body = {
            'remove_security_service': {
                'security_service_id': common_base.getid(security_service),
            },
        }
        return self._create(
            RESOURCE_PATH % common_base.getid(share_network) + '/action',
            body,
            RESOURCE_NAME,
        )
    def get(self, replica):
        """Get a share replica.

        :param replica: either replica object or its UUID.
        :rtype: :class:`ShareReplica`
        """
        replica_id = common_base.getid(replica)
        return self._get(RESOURCE_PATH % replica_id, RESOURCE_NAME)
Example #18
0
    def get(self, share_network):
        """Get a share network.

        :param policy: share network to get.
        :rtype: :class:`NetworkInfo`
        """
        return self._get(RESOURCE_PATH % common_base.getid(share_network),
                         RESOURCE_NAME)
    def get(self, share_type="default"):
        """Get a specific share type.

        :param share_type: The ID of the :class:`ShareType` to get.
        :rtype: :class:`ShareType`
        """
        return self._get("/types/%s" % common_base.getid(share_type),
                         "share_type")
    def get(self, volume_type):
        """Get a specific volume type.

        :param volume_type: The ID of the :class:`VolumeType` to get.
        :rtype: :class:`VolumeType`
        """
        return self._get("/types/%s" % common_base.getid(volume_type),
                         "volume_type")
    def get_keys(self):
        """Get extra specs from a volume type.

        :param vol_type: The :class:`VolumeType` to get extra specs from
        """
        _resp, body = self.manager.api.client.get(
            "/types/%s/extra_specs" % common_base.getid(self))
        return body["extra_specs"]
    def get(self, share_type="default"):
        """Get a specific share type.

        :param share_type: The ID of the :class:`ShareType` to get.
        :rtype: :class:`ShareType`
        """
        return self._get("/types/%s" % common_base.getid(share_type),
                         "share_type")
    def get(self, instance):
        """Get a share instance.

        :param instance: either share object or text with its ID.
        :rtype: :class:`ShareInstance`
        """
        share_id = common_base.getid(instance)
        return self._get("/share_instances/%s" % share_id, "share_instance")
    def remove_security_service(self, share_network, security_service):
        """Dissociate security service from a share network.

        :param share_network: share network name, id or ShareNetwork instance
        :param security_service: name, id or SecurityService instance
        :rtype: :class:`ShareNetwork`
        """
        body = {
            'remove_security_service': {
                'security_service_id': common_base.getid(security_service),
            },
        }
        return self._create(
            RESOURCE_PATH % common_base.getid(share_network) + '/action',
            body,
            RESOURCE_NAME,
        )
Example #25
0
    def list_instances(self, share):
        """List instances of the specified share.

        :param share: either share object or text with its ID.
        """
        return self._list('/shares/%s/instances' % common_base.getid(share),
                          'share_instances',
                          obj_class=share_instances.ShareInstance)
    def get(self, snapshot):
        """Get a snapshot.

        :param snapshot: The :class:`ShareSnapshot` instance or string with ID
            of snapshot to delete.
        :rtype: :class:`ShareSnapshot`
        """
        snapshot_id = common_base.getid(snapshot)
        return self._get('/snapshots/%s' % snapshot_id, 'snapshot')
    def get(self, snapshot):
        """Get a snapshot.

        :param snapshot: The :class:`ShareSnapshot` instance or string with ID
            of snapshot to delete.
        :rtype: :class:`ShareSnapshot`
        """
        snapshot_id = common_base.getid(snapshot)
        return self._get('/snapshots/%s' % snapshot_id, 'snapshot')
Example #28
0
    def set_metadata(self, share, metadata):
        """Set or update metadata for share.

        :param share: either share object or text with its ID.
        :param metadata: A list of keys to be set.
        """
        body = {'metadata': metadata}
        return self._create("/shares/%s/metadata" % common_base.getid(share),
                            body, "metadata")
Example #29
0
    def update_all_metadata(self, share, metadata):
        """Update all metadata of a share.

        :param share: either share object or text with its ID.
        :param metadata: A list of keys to be updated.
        """
        body = {'metadata': metadata}
        return self._update("/shares/%s/metadata" % common_base.getid(share),
                            body)
    def _do_list(self, share_type, action_name="share_type_access"):
        if share_type.is_public:
            return None

        return self._list(
            "/types/%(st_id)s/%(action_name)s" % {
                "st_id": common_base.getid(share_type),
                "action_name": action_name},
            "share_type_access")
    def update_all_metadata(self, share, metadata):
        """Update all metadata of a share.

        :param share: either share object or text with its ID.
        :param metadata: A list of keys to be updated.
        """
        body = {'metadata': metadata}
        return self._update("/shares/%s/metadata" % common_base.getid(share),
                            body)
Example #32
0
    def get(self, cg_snapshot):
        """Get a consistency group snapshot.

        :param cg_snapshot: either cg snapshot object or text with
            its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        consistency_group_id = common_base.getid(cg_snapshot)
        return self._get(RESOURCE_PATH % consistency_group_id, RESOURCE_NAME)
    def set_metadata(self, share, metadata):
        """Set or update metadata for share.

        :param share: either share object or text with its ID.
        :param metadata: A list of keys to be set.
        """
        body = {'metadata': metadata}
        return self._create("/shares/%s/metadata" % common_base.getid(share),
                            body, "metadata")
    def _do_list(self, share_type, action_name="share_type_access"):
        if share_type.is_public:
            return None

        return self._list(
            "/types/%(st_id)s/%(action_name)s" % {
                "st_id": common_base.getid(share_type),
                "action_name": action_name
            }, "share_type_access")
    def list_instances(self, share):
        """List instances of the specified share.

        :param share: either share object or text with its ID.
        """
        return self._list(
            '/shares/%s/instances' % common_base.getid(share),
            'share_instances',
            obj_class=share_instances.ShareInstance
        )
Example #36
0
    def get(self, consistency_group):
        """Get a consistency group.

        :param consistency_group: either consistency group object or text with
            its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        consistency_group_id = common_base.getid(consistency_group)
        return self._get(RESOURCE_PATH % consistency_group_id,
                         RESOURCE_NAME)
    def get(self, cg_snapshot):
        """Get a consistency group snapshot.

        :param cg_snapshot: either cg snapshot object or text with
            its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        consistency_group_id = common_base.getid(cg_snapshot)
        return self._get(RESOURCE_PATH % consistency_group_id,
                         RESOURCE_NAME)
    def get(self, security_service):
        """Get a security service info.

        :param security_service: security service to get.
        :rtype: :class:`SecurityService`
        """
        return self._get(
            RESOURCE_PATH % common_base.getid(security_service),
            RESOURCE_NAME,
        )
    def delete_metadata(self, share, keys):
        """Delete specified keys from shares metadata.

        :param share: either share object or text with its ID.
        :param keys: A list of keys to be removed.
        """
        share_id = common_base.getid(share)
        for key in keys:
            self._delete("/shares/%(share_id)s/metadata/%(key)s" % {
                'share_id': share_id, 'key': key})
    def get(self, consistency_group):
        """Get a consistency group.

        :param consistency_group: either consistency group object or text with
            its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        consistency_group_id = common_base.getid(consistency_group)
        return self._get(RESOURCE_PATH % consistency_group_id,
                         RESOURCE_NAME)
Example #41
0
    def get(self, security_service):
        """Get a security service info.

        :param security_service: security service to get.
        :rtype: :class:`SecurityService`
        """
        return self._get(
            RESOURCE_PATH % common_base.getid(security_service),
            RESOURCE_NAME,
        )
Example #42
0
    def create(self,
               share_proto,
               size,
               snapshot_id=None,
               name=None,
               description=None,
               metadata=None,
               share_network=None,
               share_type=None,
               is_public=False,
               availability_zone=None,
               consistency_group_id=None):
        """Create a share.

        :param share_proto: text - share protocol for new share
            available values are NFS, CIFS, GlusterFS and HDFS.
        :param size: int - size in GiB
        :param snapshot_id: text - ID of the snapshot
        :param name: text - name of new share
        :param description: text - description of a share
        :param metadata: dict - optional metadata to set on share creation
        :param share_network: either instance of ShareNetwork or text with ID
        :param share_type: either instance of ShareType or text with ID
        :param is_public: bool, whether to set share as public or not.
        :param consistency_group_id: text - ID of the consistency group to
            which the share should belong
        :rtype: :class:`Share`
        """
        share_metadata = metadata if metadata is not None else dict()
        body = {
            'size': size,
            'snapshot_id': snapshot_id,
            'name': name,
            'description': description,
            'metadata': share_metadata,
            'share_proto': share_proto,
            'share_network_id': common_base.getid(share_network),
            'share_type': common_base.getid(share_type),
            'is_public': is_public,
            'availability_zone': availability_zone,
            'consistency_group_id': consistency_group_id,
        }
        return self._create('/shares', {'share': body}, 'share')
Example #43
0
    def delete(self, share, consistency_group_id=None):
        """Delete a share.

        :param share: either share object or text with its ID.
        :param consistency_group_id: text - ID of the consistency group to
            which the share belongs to.
        """
        url = "/shares/%s" % common_base.getid(share)
        if consistency_group_id:
            url += "?consistency_group_id=%s" % consistency_group_id
        self._delete(url)
    def get(self, access_group):
        """Get an access_group.

        :param access_group: The :class:`AccessGroup` instance or string with ID
               of access_group to delete.
        :rtype: :class:`AccessGroup`
        """
        access_group_id = common_base.getid(access_group)
        print"NMH access_groups.py MANAGER file 1111111333333333",access_group_id
        return self._get(RESOURCE_PATH % access_group_id,
                         RESOURCE_NAME)
    def get(self, access_group_entry):
        """Get an access_group_entry.

        :param access_group_entry: The :class:`AccessGroupEntry` instance or string with ID
               of access_group_entry.
        :rtype: :class:`AccessGroupEntry`
        """
        access_group_entry_id = common_base.getid(access_group_entry)
        print"NMH access_groups_entries.py MANAGER file 111111133333 access_group_entry_id is",access_group_entry_id
        return self._get(RESOURCE_PATH % access_group_entry_id,
                         RESOURCE_NAME)
    def delete(self, share, consistency_group_id=None):
        """Delete a share.

        :param share: either share object or text with its ID.
        :param consistency_group_id: text - ID of the consistency group to
            which the share belongs to.
        """
        url = "/shares/%s" % common_base.getid(share)
        if consistency_group_id:
            url += "?consistency_group_id=%s" % consistency_group_id
        self._delete(url)
    def _action(self, action, share, info=None, **kwargs):
        """Perform a share 'action'.

        :param action: text with action name.
        :param share: either share object or text with its ID.
        :param info: dict with data for specified 'action'.
        :param kwargs: dict with data to be provided for action hooks.
        """
        body = {action: info}
        self.run_hooks('modify_body_for_action', body, **kwargs)
        url = '/shares/%s/action' % common_base.getid(share)
        return self.api.client.post(url, body=body)
Example #48
0
    def _action(self, action, share, info=None, **kwargs):
        """Perform a share 'action'.

        :param action: text with action name.
        :param share: either share object or text with its ID.
        :param info: dict with data for specified 'action'.
        :param kwargs: dict with data to be provided for action hooks.
        """
        body = {action: info}
        self.run_hooks('modify_body_for_action', body, **kwargs)
        url = '/shares/%s/action' % common_base.getid(share)
        return self.api.client.post(url, body=body)
Example #49
0
    def delete_metadata(self, share, keys):
        """Delete specified keys from shares metadata.

        :param share: either share object or text with its ID.
        :param keys: A list of keys to be removed.
        """
        share_id = common_base.getid(share)
        for key in keys:
            self._delete("/shares/%(share_id)s/metadata/%(key)s" % {
                'share_id': share_id,
                'key': key
            })
    def _do_delete(self, replica, force=False):
        """Delete a share replica.

        :param replica: either share replica object or its UUID.
        """
        replica_id = common_base.getid(replica)
        url = RESOURCE_PATH % replica_id

        if force:
            self._do_force_delete(replica_id)
        else:
            self._delete(url)
    def create(self, share, availability_zone=None, share_network=None):
        """Create a replica for a share.

        :param share: The share to create the replica of. Can be the share
        object or its UUID.
        :param availability_zone: The 'availability_zone' object or its UUID.
        :param share_network: either share network object or its UUID.
        """

        share_id = common_base.getid(share)
        body = {'share_id': share_id}

        if availability_zone:
            body['availability_zone'] = common_base.getid(availability_zone)

        if share_network:
            body['share_network'] = common_base.getid(share_network)

        return self._create(RESOURCES_PATH,
                            {RESOURCE_NAME: body},
                            RESOURCE_NAME)
    def set_keys(self, metadata):
        """Set extra specs on a share type.

        :param type : The :class:`ShareType` to set extra spec on
        :param metadata: A dict of key/value pairs to be set
        """
        body = {'extra_specs': metadata}
        return self.manager._create(
            "/types/%s/extra_specs" % common_base.getid(self),
            body,
            "extra_specs",
            return_raw=True,
        )
Example #53
0
    def update(self, share, **kwargs):
        """Updates a share.

        :param share: either share object or text with its ID.
        :rtype: :class:`Share`
        """
        if not kwargs:
            return

        body = {
            'share': kwargs,
        }
        share_id = common_base.getid(share)
        return self._update("/shares/%s" % share_id, body)
Example #54
0
    def update(self, cg_snapshot, **kwargs):
        """Updates a consistency group snapshot.

        :param cg_snapshot: either consistency group snapshot object or text
            with its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        if not kwargs:
            return

        body = {RESOURCE_NAME: kwargs}
        cg_snapshot_id = common_base.getid(cg_snapshot)
        return self._update(RESOURCE_PATH % cg_snapshot_id, body,
                            RESOURCE_NAME)
Example #55
0
    def update(self, consistency_group, **kwargs):
        """Updates a consistency group.

        :param consistency_group: either consistency group object or text
            with its ID.
        :rtype: :class:`ConsistencyGroup`
        """
        if not kwargs:
            return

        body = {RESOURCE_NAME: kwargs}
        consistency_group_id = common_base.getid(consistency_group)
        return self._update(RESOURCE_PATH % consistency_group_id,
                            body,
                            RESOURCE_NAME)
    def update(self, snapshot, **kwargs):
        """Update a snapshot.

        :param snapshot: The :class:`ShareSnapshot` instance or string with ID
            of snapshot to delete.
        :rtype: :class:`ShareSnapshot`
        """
        if not kwargs:
            return

        body = {
            'snapshot': kwargs,
        }
        snapshot_id = common_base.getid(snapshot)
        return self._update("/snapshots/%s" % snapshot_id, body)
Example #57
0
    def _do_delete(self, cg_snapshot, force=False, action_name='force_delete'):
        """Delete a consistency group snapshot.

        :param cg_snapshot: either a cg snapshot object or text wit its ID.
        """
        cg_id = common_base.getid(cg_snapshot)
        body = None

        if force:
            body = {action_name: None}

        if body:
            self.api.client.post(RESOURCE_PATH_ACTION % cg_id, body=body)
        else:
            self._delete(RESOURCE_PATH % cg_id)
    def unset_keys(self, keys):
        """Unset extra specs on a share type.

        :param type_id: The :class:`ShareType` to unset extra spec on
        :param keys: A list of keys to be unset
        """

        # NOTE(jdg): This wasn't actually doing all of the keys before
        # the return in the loop resulted in ony ONE key being unset.
        # since on success the return was NONE, we'll only interrupt the loop
        # and return if there's an error
        resp = None
        for k in keys:
            resp = self.manager._delete(
                "/types/%s/extra_specs/%s" % (common_base.getid(self), k))
            if resp is not None:
                return resp
Example #59
0
    def update(self, security_service, dns_ip=None, server=None, domain=None,
               password=None, user=None, name=None, description=None):
        """Updates a security service.

        :param security_service: security service to update.
        :param dns_ip: dns ip address used inside tenant's network
        :param server: security service server ip address or hostname
        :param domain: security service domain
        :param user: security identifier used by tenant
        :param password: password used by user
        :param name: security service name
        :param description: security service description
        :rtype: :class:`SecurityService`
        """

        values = {}
        if dns_ip is not None:
            values['dns_ip'] = dns_ip
        if server is not None:
            values['server'] = server
        if domain is not None:
            values['domain'] = domain
        if user is not None:
            values['user'] = user
        if password is not None:
            values['password'] = password
        if name is not None:
            values['name'] = name
        if description is not None:
            values['description'] = description

        for k, v in six.iteritems(values):
            if v == '':
                values[k] = None

        if not values:
            msg = "Must specify fields to be updated"
            raise exceptions.CommandError(msg)

        body = {RESOURCE_NAME: values}

        return self._update(
            RESOURCE_PATH % common_base.getid(security_service),
            body,
            RESOURCE_NAME,
        )