Add 'all_projects' support to proxy layers
A number of compute and block storage APIs support this parameter. Plumb them through. This turns out to be a bigger change than expected as it highlights a number of gaps in our documentation. Change-Id: Id4049193ab2e6c173208692ed46fc5f9491da3dc Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
0c54b0993e
commit
6fee18fcd1
@ -37,7 +37,13 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
"""
|
||||
return self._get(_snapshot.Snapshot, snapshot)
|
||||
|
||||
def find_snapshot(self, name_or_id, ignore_missing=True):
|
||||
def find_snapshot(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single snapshot
|
||||
|
||||
:param snapshot: The name or ID a snapshot
|
||||
@ -45,6 +51,9 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the snapshot does not exist. When set to ``True``, None will
|
||||
be returned when attempting to find a nonexistent resource.
|
||||
:param bool all_projects: When set to ``True``, search for snapshot by
|
||||
name across all projects. Note that this will likely result in
|
||||
a higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v2.snapshot.Snapshot` or
|
||||
None.
|
||||
@ -53,13 +62,17 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_snapshot.Snapshot,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**query,
|
||||
)
|
||||
|
||||
def snapshots(self, details=True, **query):
|
||||
def snapshots(self, *, details=True, all_projects=False, **query):
|
||||
"""Retrieve a generator of snapshots
|
||||
|
||||
:param bool details: When set to ``False``
|
||||
@ -67,17 +80,20 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
objects will be returned. The default, ``True``, will cause
|
||||
:class:`~openstack.block_storage.v2.snapshot.SnapshotDetail`
|
||||
objects to be returned.
|
||||
:param bool all_projects: When set to ``True``, list snapshots from all
|
||||
projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the snapshots being returned. Available parameters include:
|
||||
|
||||
* name: Name of the snapshot as a string.
|
||||
* all_projects: Whether return the snapshots in all projects.
|
||||
* volume_id: volume id of a snapshot.
|
||||
* status: Value of the status of the snapshot so that you can
|
||||
filter on "available" for example.
|
||||
|
||||
:returns: A generator of snapshot objects.
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
base_path = '/snapshots/detail' if details else None
|
||||
return self._list(_snapshot.Snapshot, base_path=base_path, **query)
|
||||
|
||||
@ -221,37 +237,59 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
"""
|
||||
return self._get(_volume.Volume, volume)
|
||||
|
||||
def find_volume(self, name_or_id, ignore_missing=True):
|
||||
def find_volume(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single volume
|
||||
|
||||
:param snapshot: The name or ID a volume
|
||||
:param volume: The name or ID a volume
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the volume does not exist.
|
||||
:param bool all_projects: When set to ``True``, search for volume by
|
||||
name across all projects. Note that this will likely result in
|
||||
a higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v2.volume.Volume`
|
||||
:returns: One :class:`~openstack.block_storage.v2.volume.Volume` or
|
||||
None.
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_volume.Volume, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_volume.Volume,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**query,
|
||||
)
|
||||
|
||||
def volumes(self, details=True, **query):
|
||||
def volumes(self, *, details=True, all_projects=False, **query):
|
||||
"""Retrieve a generator of volumes
|
||||
|
||||
:param bool details: When set to ``False`` no extended attributes
|
||||
will be returned. The default, ``True``, will cause objects with
|
||||
additional attributes to be returned.
|
||||
:param bool all_projects: When set to ``True``, list volumes from all
|
||||
projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the volumes being returned. Available parameters include:
|
||||
|
||||
* name: Name of the volume as a string.
|
||||
* all_projects: Whether return the volumes in all projects
|
||||
* status: Value of the status of the volume so that you can filter
|
||||
on "available" for example.
|
||||
|
||||
:returns: A generator of volume objects.
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
base_path = '/volumes/detail' if details else None
|
||||
return self._list(_volume.Volume, base_path=base_path, **query)
|
||||
|
||||
|
@ -62,33 +62,53 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
"""
|
||||
return self._get(_snapshot.Snapshot, snapshot)
|
||||
|
||||
def find_snapshot(self, name_or_id, ignore_missing=True):
|
||||
def find_snapshot(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single snapshot
|
||||
|
||||
:param snapshot: The name or ID a snapshot
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the snapshot does not exist.
|
||||
when the snapshot does not exist. When set to ``True``, None will
|
||||
be returned when attempting to find a nonexistent resource.
|
||||
:param bool all_projects: When set to ``True``, search for snapshot by
|
||||
name across all projects. Note that this will likely result in
|
||||
a higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v3.snapshot.Snapshot`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_snapshot.Snapshot, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_snapshot.Snapshot,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**query,
|
||||
)
|
||||
|
||||
def snapshots(self, details=True, **query):
|
||||
def snapshots(self, *, details=True, all_projects=False, **query):
|
||||
"""Retrieve a generator of snapshots
|
||||
|
||||
:param bool details: When set to ``False`` :class:
|
||||
`~openstack.block_storage.v3.snapshot.Snapshot`
|
||||
objects will be returned. The default, ``True``, will cause
|
||||
more attributes to be returned.
|
||||
:param bool all_projects: When set to ``True``, list snapshots from all
|
||||
projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the snapshots being returned. Available parameters include:
|
||||
|
||||
* name: Name of the snapshot as a string.
|
||||
* all_projects: Whether return the snapshots in all projects.
|
||||
* project_id: Filter the snapshots by project.
|
||||
* volume_id: volume id of a snapshot.
|
||||
* status: Value of the status of the snapshot so that you can
|
||||
@ -96,6 +116,8 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
|
||||
:returns: A generator of snapshot objects.
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
base_path = '/snapshots/detail' if details else None
|
||||
return self._list(_snapshot.Snapshot, base_path=base_path, **query)
|
||||
|
||||
@ -237,14 +259,19 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:param snapshot: The name or ID a volume type
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the type does not exist.
|
||||
when the volume type does not exist.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v3.type.Type`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_type.Type, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_type.Type,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def types(self, **query):
|
||||
"""Retrieve a generator of volume types
|
||||
@ -469,38 +496,59 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
"""
|
||||
return self._get(_volume.Volume, volume)
|
||||
|
||||
def find_volume(self, name_or_id, ignore_missing=True):
|
||||
def find_volume(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single volume
|
||||
|
||||
:param snapshot: The name or ID a volume
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the volume does not exist.
|
||||
:param bool all_projects: When set to ``True``, search for volume by
|
||||
name across all projects. Note that this will likely result in
|
||||
a higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v3.volume.Volume`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_volume.Volume, name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
list_base_path='/volumes/detail')
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_volume.Volume,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
list_base_path='/volumes/detail',
|
||||
**query,
|
||||
)
|
||||
|
||||
def volumes(self, details=True, **query):
|
||||
def volumes(self, *, details=True, all_projects=False, **query):
|
||||
"""Retrieve a generator of volumes
|
||||
|
||||
:param bool details: When set to ``False`` no extended attributes
|
||||
will be returned. The default, ``True``, will cause objects with
|
||||
additional attributes to be returned.
|
||||
:param bool all_projects: When set to ``True``, list volumes from all
|
||||
projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the volumes being returned. Available parameters include:
|
||||
|
||||
* name: Name of the volume as a string.
|
||||
* all_projects: Whether return the volumes in all projects
|
||||
* status: Value of the status of the volume so that you can filter
|
||||
on "available" for example.
|
||||
|
||||
:returns: A generator of volume objects.
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
base_path = '/volumes/detail' if details else None
|
||||
return self._list(_volume.Volume, base_path=base_path, **query)
|
||||
|
||||
@ -872,7 +920,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
return self._list(_stats.Pools, **query)
|
||||
|
||||
# ====== BACKUPS ======
|
||||
def backups(self, details=True, **query):
|
||||
def backups(self, *, details=True, **query):
|
||||
"""Retrieve a generator of backups
|
||||
|
||||
:param bool details: When set to ``False``
|
||||
@ -921,9 +969,14 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:returns: One :class:`~openstack.block_storage.v3.backup.Backup`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_backup.Backup, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_backup.Backup,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def create_backup(self, **attrs):
|
||||
"""Create a new Backup from attributes with native API
|
||||
@ -1032,11 +1085,16 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:returns: One :class:`~openstack.block_storage.v3.group.Group`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(
|
||||
_group.Group, name_or_id, ignore_missing=ignore_missing)
|
||||
_group.Group,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def groups(self, details=True, **query):
|
||||
def groups(self, *, details=True, **query):
|
||||
"""Retrieve a generator of groups
|
||||
|
||||
:param bool details: When set to ``False``, no additional details will
|
||||
@ -1155,12 +1213,16 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:returns: One :class:`~openstack.block_storage.v3.group_snapshot`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(
|
||||
_group_snapshot.GroupSnapshot, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
_group_snapshot.GroupSnapshot,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def group_snapshots(self, details=True, **query):
|
||||
def group_snapshots(self, *, details=True, **query):
|
||||
"""Retrieve a generator of group snapshots
|
||||
|
||||
:param bool details: When ``True``, returns
|
||||
@ -1245,9 +1307,14 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
:class:`~openstack.block_storage.v3.group_type.GroupType`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(
|
||||
_group_type.GroupType, name_or_id, ignore_missing=ignore_missing)
|
||||
_group_type.GroupType,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def group_types(self, **query):
|
||||
"""Retrive a generator of group types
|
||||
|
@ -78,11 +78,19 @@ class Proxy(proxy.Proxy):
|
||||
raised when the resource does not exist.
|
||||
When set to ``True``, None will be returned when
|
||||
attempting to find a nonexistent resource.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.extension.Extension` or
|
||||
None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(extension.Extension, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
extension.Extension,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def extensions(self):
|
||||
"""Retrieve a generator of extensions
|
||||
@ -94,8 +102,15 @@ class Proxy(proxy.Proxy):
|
||||
|
||||
# ========== Flavors ==========
|
||||
|
||||
def find_flavor(self, name_or_id, ignore_missing=True,
|
||||
get_extra_specs=False, **query):
|
||||
# TODO(stephenfin): Drop 'query' parameter or apply it consistently
|
||||
def find_flavor(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
get_extra_specs=False,
|
||||
**query,
|
||||
):
|
||||
"""Find a single flavor
|
||||
|
||||
:param name_or_id: The name or ID of a flavor.
|
||||
@ -106,14 +121,21 @@ class Proxy(proxy.Proxy):
|
||||
:param bool get_extra_specs: When set to ``True`` and extra_specs not
|
||||
present in the response will invoke additional API call to fetch
|
||||
extra_specs.
|
||||
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the flavors being returned.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.flavor.Flavor` or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
flavor = self._find(
|
||||
_flavor.Flavor, name_or_id, ignore_missing=ignore_missing, **query)
|
||||
_flavor.Flavor,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**query,
|
||||
)
|
||||
if flavor and get_extra_specs and not flavor.extra_specs:
|
||||
flavor = flavor.fetch_extra_specs(self)
|
||||
return flavor
|
||||
@ -325,11 +347,19 @@ class Proxy(proxy.Proxy):
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.aggregate.Aggregate`
|
||||
or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_aggregate.Aggregate, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_aggregate.Aggregate,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def create_aggregate(self, **attrs):
|
||||
"""Create a new host aggregate from attributes
|
||||
@ -463,15 +493,23 @@ class Proxy(proxy.Proxy):
|
||||
raised when the resource does not exist.
|
||||
When set to ``True``, None will be returned when
|
||||
attempting to find a nonexistent resource.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.image.Image` or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
warnings.warn(
|
||||
'This API is a proxy to the image service and has been '
|
||||
'deprecated; use the image service proxy API instead',
|
||||
DeprecationWarning,
|
||||
)
|
||||
return self._find(_image.Image, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_image.Image,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def get_image(self, image):
|
||||
"""Get a single image
|
||||
@ -615,7 +653,7 @@ class Proxy(proxy.Proxy):
|
||||
attrs = {'user_id': user_id} if user_id else {}
|
||||
return self._get(_keypair.Keypair, keypair, **attrs)
|
||||
|
||||
def find_keypair(self, name_or_id, ignore_missing=True, user_id=None):
|
||||
def find_keypair(self, name_or_id, ignore_missing=True, *, user_id=None):
|
||||
"""Find a single keypair
|
||||
|
||||
:param name_or_id: The name or ID of a keypair.
|
||||
@ -626,11 +664,18 @@ class Proxy(proxy.Proxy):
|
||||
:param str user_id: Optional user_id owning the keypair
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.keypair.Keypair` or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
attrs = {'user_id': user_id} if user_id else {}
|
||||
return self._find(_keypair.Keypair, name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**attrs)
|
||||
return self._find(
|
||||
_keypair.Keypair,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
def keypairs(self, **query):
|
||||
"""Return a generator of keypairs
|
||||
@ -690,20 +735,40 @@ class Proxy(proxy.Proxy):
|
||||
else:
|
||||
self._delete(_server.Server, server, ignore_missing=ignore_missing)
|
||||
|
||||
def find_server(self, name_or_id, ignore_missing=True):
|
||||
def find_server(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single server
|
||||
|
||||
:param name_or_id: The name or ID of a server.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be
|
||||
raised when the resource does not exist.
|
||||
When set to ``True``, None will be returned when
|
||||
attempting to find a nonexistent resource.
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
:param bool all_projects: When set to ``True``, search for server
|
||||
by name across all projects. Note that this will likely result in a
|
||||
higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.server.Server` or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_server.Server, name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
list_base_path='/servers/detail')
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_server.Server,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
list_base_path='/servers/detail',
|
||||
**query,
|
||||
)
|
||||
|
||||
def get_server(self, server):
|
||||
"""Get a single server
|
||||
@ -723,6 +788,8 @@ class Proxy(proxy.Proxy):
|
||||
:param bool details: When set to ``False``
|
||||
instances with only basic data will be returned. The default,
|
||||
``True``, will cause instances with full data to be returned.
|
||||
:param bool all_projects: When set to ``True``, lists servers from all
|
||||
projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the servers being returned. Available parameters can be seen
|
||||
under https://docs.openstack.org/api-ref/compute/#list-servers
|
||||
@ -1374,21 +1441,40 @@ class Proxy(proxy.Proxy):
|
||||
self._delete(_server_group.ServerGroup, server_group,
|
||||
ignore_missing=ignore_missing)
|
||||
|
||||
def find_server_group(self, name_or_id, ignore_missing=True):
|
||||
def find_server_group(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
):
|
||||
"""Find a single server group
|
||||
|
||||
:param name_or_id: The name or ID of a server group.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be
|
||||
raised when the resource does not exist.
|
||||
When set to ``True``, None will be returned when
|
||||
attempting to find a nonexistent resource.
|
||||
:returns:
|
||||
One :class:`~openstack.compute.v2.server_group.ServerGroup` object
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
:param bool all_projects: When set to ``True``, search for server
|
||||
groups by name across all projects. Note that this will likely
|
||||
result in a higher chance of duplicates. Admin-only by default.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.server_group.ServerGroup`
|
||||
or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_server_group.ServerGroup, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
query = {}
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._find(
|
||||
_server_group.ServerGroup,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
**query,
|
||||
)
|
||||
|
||||
def get_server_group(self, server_group):
|
||||
"""Get a single server group
|
||||
@ -1404,21 +1490,25 @@ class Proxy(proxy.Proxy):
|
||||
"""
|
||||
return self._get(_server_group.ServerGroup, server_group)
|
||||
|
||||
def server_groups(self, **query):
|
||||
def server_groups(self, *, all_projects=False, **query):
|
||||
"""Return a generator of server groups
|
||||
|
||||
:param bool all_projects: When set to ``True``, lists servers groups
|
||||
from all projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the resources being returned.
|
||||
|
||||
:returns: A generator of ServerGroup objects
|
||||
:rtype: :class:`~openstack.compute.v2.server_group.ServerGroup`
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._list(_server_group.ServerGroup, **query)
|
||||
|
||||
# ========== Hypervisors ==========
|
||||
|
||||
def hypervisors(self, details=False, **query):
|
||||
"""Return a generator of hypervisor
|
||||
"""Return a generator of hypervisors
|
||||
|
||||
:param bool details: When set to the default, ``False``,
|
||||
:class:`~openstack.compute.v2.hypervisor.Hypervisor`
|
||||
@ -1438,20 +1528,36 @@ class Proxy(proxy.Proxy):
|
||||
pattern=query.pop('hypervisor_hostname_pattern'))
|
||||
return self._list(_hypervisor.Hypervisor, base_path=base_path, **query)
|
||||
|
||||
def find_hypervisor(self, name_or_id, ignore_missing=True, details=True):
|
||||
"""Find a hypervisor from name or id to get the corresponding info
|
||||
def find_hypervisor(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
details=True,
|
||||
):
|
||||
"""Find a single hypervisor
|
||||
|
||||
:param name_or_id: The name or id of a hypervisor
|
||||
:param name_or_id: The name or ID of a hypervisor
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
|
||||
:returns:
|
||||
One: class:`~openstack.compute.v2.hypervisor.Hypervisor` object
|
||||
:returns: One: class:`~openstack.compute.v2.hypervisor.Hypervisor`
|
||||
or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
|
||||
list_base_path = '/os-hypervisors/detail' if details else None
|
||||
return self._find(_hypervisor.Hypervisor, name_or_id,
|
||||
list_base_path=list_base_path,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_hypervisor.Hypervisor,
|
||||
name_or_id,
|
||||
list_base_path=list_base_path,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def get_hypervisor(self, hypervisor):
|
||||
"""Get a single hypervisor
|
||||
@ -1580,9 +1686,11 @@ class Proxy(proxy.Proxy):
|
||||
attempting to find a nonexistent resource.
|
||||
:param dict query: Additional attributes like 'host'
|
||||
|
||||
:returns:
|
||||
One: class:`~openstack.compute.v2.hypervisor.Hypervisor` object
|
||||
or None
|
||||
:returns: One: class:`~openstack.compute.v2.service.Service` or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(
|
||||
_service.Service,
|
||||
|
@ -2192,6 +2192,7 @@ class Resource(dict):
|
||||
list_base_path=None,
|
||||
*,
|
||||
microversion=None,
|
||||
all_projects=None,
|
||||
**params,
|
||||
):
|
||||
"""Find a resource by its name or id.
|
||||
@ -2220,10 +2221,13 @@ class Resource(dict):
|
||||
is found and ignore_missing is ``False``.
|
||||
"""
|
||||
session = cls._get_session(session)
|
||||
|
||||
# Try to short-circuit by looking directly for a matching ID.
|
||||
try:
|
||||
match = cls.existing(
|
||||
id=name_or_id, connection=session._get_connection(), **params
|
||||
id=name_or_id,
|
||||
connection=session._get_connection(),
|
||||
**params,
|
||||
)
|
||||
return match.fetch(session, microversion=microversion, **params)
|
||||
except (exceptions.NotFoundException, exceptions.BadRequestException):
|
||||
@ -2234,6 +2238,12 @@ class Resource(dict):
|
||||
if list_base_path:
|
||||
params['base_path'] = list_base_path
|
||||
|
||||
# all_projects is a special case that is used by multiple services. We
|
||||
# handle it here since it doesn't make sense to pass it to the .fetch
|
||||
# call above
|
||||
if all_projects is not None:
|
||||
params['all_projects'] = all_projects
|
||||
|
||||
if (
|
||||
'name' in cls._query_mapping._mapping.keys()
|
||||
and 'name' not in params
|
||||
@ -2248,6 +2258,7 @@ class Resource(dict):
|
||||
|
||||
if ignore_missing:
|
||||
return None
|
||||
|
||||
raise exceptions.ResourceNotFound(
|
||||
"No %s found for %s" % (cls.__name__, name_or_id)
|
||||
)
|
||||
|
@ -23,8 +23,9 @@ from openstack.tests.unit import test_proxy_base
|
||||
|
||||
|
||||
class TestVolumeProxy(test_proxy_base.TestProxyBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVolumeProxy, self).setUp()
|
||||
super().setUp()
|
||||
self.proxy = _proxy.Proxy(self.session)
|
||||
|
||||
|
||||
@ -34,18 +35,31 @@ class TestVolume(TestVolumeProxy):
|
||||
self.verify_get(self.proxy.get_volume, volume.Volume)
|
||||
|
||||
def test_volume_find(self):
|
||||
self.verify_find(self.proxy.find_volume, volume.Volume)
|
||||
self.verify_find(
|
||||
self.proxy.find_volume,
|
||||
volume.Volume,
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={'all_projects': True},
|
||||
)
|
||||
|
||||
def test_volumes_detailed(self):
|
||||
self.verify_list(self.proxy.volumes, volume.Volume,
|
||||
method_kwargs={"details": True, "query": 1},
|
||||
expected_kwargs={"query": 1,
|
||||
"base_path": "/volumes/detail"})
|
||||
self.verify_list(
|
||||
self.proxy.volumes,
|
||||
volume.Volume,
|
||||
method_kwargs={"details": True, "all_projects": True},
|
||||
expected_kwargs={
|
||||
"base_path": "/volumes/detail",
|
||||
"all_projects": True,
|
||||
}
|
||||
)
|
||||
|
||||
def test_volumes_not_detailed(self):
|
||||
self.verify_list(self.proxy.volumes, volume.Volume,
|
||||
method_kwargs={"details": False, "query": 1},
|
||||
expected_kwargs={"query": 1})
|
||||
self.verify_list(
|
||||
self.proxy.volumes,
|
||||
volume.Volume,
|
||||
method_kwargs={"details": False, "all_projects": True},
|
||||
expected_kwargs={"all_projects": True},
|
||||
)
|
||||
|
||||
def test_volume_create_attrs(self):
|
||||
self.verify_create(self.proxy.create_volume, volume.Volume)
|
||||
@ -197,6 +211,7 @@ class TestVolumeActions(TestVolumeProxy):
|
||||
|
||||
|
||||
class TestBackup(TestVolumeProxy):
|
||||
|
||||
def test_backups_detailed(self):
|
||||
self.verify_list(
|
||||
self.proxy.backups,
|
||||
@ -257,21 +272,33 @@ class TestBackup(TestVolumeProxy):
|
||||
|
||||
|
||||
class TestSnapshot(TestVolumeProxy):
|
||||
|
||||
def test_snapshot_get(self):
|
||||
self.verify_get(self.proxy.get_snapshot, snapshot.Snapshot)
|
||||
|
||||
def test_snapshot_find(self):
|
||||
self.verify_find(self.proxy.find_snapshot, snapshot.Snapshot)
|
||||
self.verify_find(
|
||||
self.proxy.find_snapshot,
|
||||
snapshot.Snapshot,
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={'all_projects': True},
|
||||
)
|
||||
|
||||
def test_snapshots_detailed(self):
|
||||
self.verify_list(self.proxy.snapshots, snapshot.SnapshotDetail,
|
||||
method_kwargs={"details": True, "query": 1},
|
||||
expected_kwargs={"query": 1})
|
||||
self.verify_list(
|
||||
self.proxy.snapshots,
|
||||
snapshot.SnapshotDetail,
|
||||
method_kwargs={"details": True, "all_projects": True},
|
||||
expected_kwargs={"all_projects": True},
|
||||
)
|
||||
|
||||
def test_snapshots_not_detailed(self):
|
||||
self.verify_list(self.proxy.snapshots, snapshot.Snapshot,
|
||||
method_kwargs={"details": False, "query": 1},
|
||||
expected_kwargs={"query": 1})
|
||||
self.verify_list(
|
||||
self.proxy.snapshots,
|
||||
snapshot.Snapshot,
|
||||
method_kwargs={"details": False, "all_projects": True},
|
||||
expected_kwargs={"all_projects": 1},
|
||||
)
|
||||
|
||||
def test_snapshot_create_attrs(self):
|
||||
self.verify_create(self.proxy.create_snapshot, snapshot.Snapshot)
|
||||
@ -325,6 +352,7 @@ class TestSnapshot(TestVolumeProxy):
|
||||
|
||||
|
||||
class TestType(TestVolumeProxy):
|
||||
|
||||
def test_type_get(self):
|
||||
self.verify_get(self.proxy.get_type, type.Type)
|
||||
|
||||
@ -363,6 +391,7 @@ class TestType(TestVolumeProxy):
|
||||
|
||||
|
||||
class TestQuota(TestVolumeProxy):
|
||||
|
||||
def test_get(self):
|
||||
self._verify(
|
||||
'openstack.resource.Resource.fetch',
|
||||
|
@ -41,9 +41,15 @@ class TestVolume(TestVolumeProxy):
|
||||
self.verify_get(self.proxy.get_volume, volume.Volume)
|
||||
|
||||
def test_volume_find(self):
|
||||
self.verify_find(self.proxy.find_volume, volume.Volume,
|
||||
expected_kwargs=dict(
|
||||
list_base_path='/volumes/detail'))
|
||||
self.verify_find(
|
||||
self.proxy.find_volume,
|
||||
volume.Volume,
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={
|
||||
"list_base_path": "/volumes/detail",
|
||||
"all_projects": True,
|
||||
},
|
||||
)
|
||||
|
||||
def test_volumes_detailed(self):
|
||||
self.verify_list(
|
||||
@ -612,7 +618,12 @@ class TestSnapshot(TestVolumeProxy):
|
||||
self.verify_get(self.proxy.get_snapshot, snapshot.Snapshot)
|
||||
|
||||
def test_snapshot_find(self):
|
||||
self.verify_find(self.proxy.find_snapshot, snapshot.Snapshot)
|
||||
self.verify_find(
|
||||
self.proxy.find_snapshot,
|
||||
snapshot.Snapshot,
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={'all_projects': True},
|
||||
)
|
||||
|
||||
def test_snapshots_detailed(self):
|
||||
self.verify_list(
|
||||
|
@ -80,7 +80,8 @@ class TestFlavor(TestComputeProxy):
|
||||
self._verify(
|
||||
'openstack.proxy.Proxy._find',
|
||||
self.proxy.find_flavor,
|
||||
method_args=['res', True, True],
|
||||
method_args=['res', True],
|
||||
method_kwargs={'get_extra_specs': True},
|
||||
expected_result=res,
|
||||
expected_args=[flavor.Flavor, 'res'],
|
||||
expected_kwargs={'ignore_missing': True}
|
||||
@ -851,7 +852,11 @@ class TestCompute(TestComputeProxy):
|
||||
self.verify_find(
|
||||
self.proxy.find_server,
|
||||
server.Server,
|
||||
expected_kwargs={'list_base_path': '/servers/detail'},
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={
|
||||
'list_base_path': '/servers/detail',
|
||||
'all_projects': True,
|
||||
},
|
||||
)
|
||||
|
||||
def test_server_get(self):
|
||||
@ -1209,8 +1214,12 @@ class TestCompute(TestComputeProxy):
|
||||
server_group.ServerGroup, True)
|
||||
|
||||
def test_server_group_find(self):
|
||||
self.verify_find(self.proxy.find_server_group,
|
||||
server_group.ServerGroup)
|
||||
self.verify_find(
|
||||
self.proxy.find_server_group,
|
||||
server_group.ServerGroup,
|
||||
method_kwargs={'all_projects': True},
|
||||
expected_kwargs={'all_projects': True},
|
||||
)
|
||||
|
||||
def test_server_group_get(self):
|
||||
self.verify_get(self.proxy.get_server_group,
|
||||
|
@ -85,5 +85,8 @@ class TestCronTriggerProxy(test_proxy_base.TestProxyBase):
|
||||
cron_trigger.CronTrigger, True)
|
||||
|
||||
def test_cron_trigger_find(self):
|
||||
self.verify_find(self.proxy.find_cron_trigger,
|
||||
cron_trigger.CronTrigger)
|
||||
self.verify_find(
|
||||
self.proxy.find_cron_trigger,
|
||||
cron_trigger.CronTrigger,
|
||||
expected_kwargs={'all_projects': False},
|
||||
)
|
||||
|
@ -196,9 +196,11 @@ class Proxy(proxy.Proxy):
|
||||
"""
|
||||
return self._get(_cron_trigger.CronTrigger, cron_trigger)
|
||||
|
||||
def cron_triggers(self, **query):
|
||||
def cron_triggers(self, *, all_projects=False, **query):
|
||||
"""Retrieve a generator of cron triggers
|
||||
|
||||
:param bool all_projects: When set to ``True``, list cron triggers from
|
||||
all projects. Admin-only by default.
|
||||
:param kwargs query: Optional query parameters to be sent to
|
||||
restrict the cron triggers to be returned. Available parameters
|
||||
include:
|
||||
@ -212,6 +214,8 @@ class Proxy(proxy.Proxy):
|
||||
|
||||
:returns: A generator of CronTrigger instances.
|
||||
"""
|
||||
if all_projects:
|
||||
query['all_projects'] = True
|
||||
return self._list(_cron_trigger.CronTrigger, **query)
|
||||
|
||||
def delete_cron_trigger(self, value, ignore_missing=True):
|
||||
@ -231,17 +235,39 @@ class Proxy(proxy.Proxy):
|
||||
return self._delete(_cron_trigger.CronTrigger, value,
|
||||
ignore_missing=ignore_missing)
|
||||
|
||||
def find_cron_trigger(self, name_or_id, ignore_missing=True):
|
||||
# TODO(stephenfin): Drop 'query' parameter or apply it consistently
|
||||
def find_cron_trigger(
|
||||
self,
|
||||
name_or_id,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
all_projects=False,
|
||||
**query,
|
||||
):
|
||||
"""Find a single cron trigger
|
||||
|
||||
:param name_or_id: The name or ID of a cron trigger.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be
|
||||
raised when the resource does not exist.
|
||||
When set to ``True``, None will be returned when
|
||||
attempting to find a nonexistent resource.
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
:param bool all_projects: When set to ``True``, search for cron
|
||||
triggers by name across all projects. Note that this will likely
|
||||
result in a higher chance of duplicates.
|
||||
:param kwargs query: Optional query parameters to be sent to limit
|
||||
the cron triggers being returned.
|
||||
|
||||
:returns: One :class:`~openstack.compute.v2.cron_trigger.CronTrigger`
|
||||
or None
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
:raises: :class:`~openstack.exceptions.DuplicateResource` when multiple
|
||||
resources are found.
|
||||
"""
|
||||
return self._find(_cron_trigger.CronTrigger, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
return self._find(
|
||||
_cron_trigger.CronTrigger,
|
||||
name_or_id,
|
||||
ignore_missing=ignore_missing,
|
||||
all_projects=all_projects,
|
||||
**query,
|
||||
)
|
||||
|
@ -0,0 +1,33 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A number of APIs support passing an admin-only ``all_projects`` filter when
|
||||
listing certain resources, allowing you to retrieve resources from all
|
||||
projects rather than just the current projects. This filter is now
|
||||
explicitly supported at the proxy layer for services and resources that
|
||||
support it. These are:
|
||||
|
||||
* Block storage (v2)
|
||||
|
||||
* ``find_snapshot``
|
||||
* ``snapshots``
|
||||
* ``find_volume``
|
||||
* ``volumes``
|
||||
|
||||
* Block storage (v3)
|
||||
|
||||
* ``find_snapshot``
|
||||
* ``snapshots``
|
||||
* ``find_volume``
|
||||
* ``volumes``
|
||||
|
||||
* Compute (v2)
|
||||
|
||||
* ``find_server``
|
||||
* ``find_server_group``
|
||||
* ``server_groups``
|
||||
|
||||
* Workflow (v2)
|
||||
|
||||
* ``find_cron_triggers``
|
||||
* ``cron_triggers``
|
Loading…
Reference in New Issue
Block a user