Skip to content

Commit cb69d09

Browse files
committed
Add list method and query support for cinder volume and snapshot
This patch do those things: 1. Add list method for volume and snapshot in _proxy.py 2. Change the Volume(block_store/v2/volume.Volume)'s base class to resource2 to support QueryParameters. 3. Change the Snapshot(block_store/v2/snapshot.Snapshot)'s base class to resource2 to support QueryParameters. 4. Change the type(block_store/v2/type/type.Type)'s base class to resource2. 5. Add query support for volume and snapshot with parameters: all_tenants, name, status, volume_id(snapshot only). Change-Id: I60f537ea8fd67283fd84addb334bdd932f537635
1 parent b2a0d5c commit cb69d09

File tree

8 files changed

+165
-66
lines changed

8 files changed

+165
-66
lines changed

openstack/block_store/v2/_proxy.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
from openstack.block_store.v2 import snapshot as _snapshot
1414
from openstack.block_store.v2 import type as _type
1515
from openstack.block_store.v2 import volume as _volume
16-
from openstack import proxy
16+
from openstack import proxy2
1717

1818

19-
class Proxy(proxy.BaseProxy):
19+
class Proxy(proxy2.BaseProxy):
2020

2121
def get_snapshot(self, snapshot):
2222
"""Get a single snapshot
@@ -31,6 +31,28 @@ def get_snapshot(self, snapshot):
3131
"""
3232
return self._get(_snapshot.Snapshot, snapshot)
3333

34+
def snapshots(self, details=True, **query):
35+
"""Retrieve a generator of snapshots
36+
37+
:param bool details: When set to ``False``
38+
:class:`~openstack.block_store.v2.snapshot.Snapshot`
39+
objects will be returned. The default, ``True``, will cause
40+
:class:`~openstack.block_store.v2.snapshot.SnapshotDetail`
41+
objects to be returned.
42+
:param kwargs \*\*query: Optional query parameters to be sent to limit
43+
the snapshots being returned. Available parameters include:
44+
45+
* name: Name of the snapshot as a string.
46+
* all_tenants: Whether return the snapshots of all tenants.
47+
* volume_id: volume id of a snapshot.
48+
* status: Value of the status of the snapshot so that you can
49+
filter on "available" for example.
50+
51+
:returns: A generator of snapshot objects.
52+
"""
53+
snapshot = _snapshot.SnapshotDetail if details else _snapshot.Snapshot
54+
return self._list(snapshot, paginated=True, **query)
55+
3456
def create_snapshot(self, **attrs):
3557
"""Create a new snapshot from attributes
3658
@@ -72,6 +94,13 @@ def get_type(self, type):
7294
"""
7395
return self._get(_type.Type, type)
7496

97+
def types(self):
98+
"""Retrieve a generator of volume types
99+
100+
:returns: A generator of volume type objects.
101+
"""
102+
return self._list(_type.Type, paginated=False)
103+
75104
def create_type(self, **attrs):
76105
"""Create a new type from attributes
77106
@@ -111,6 +140,27 @@ def get_volume(self, volume):
111140
"""
112141
return self._get(_volume.Volume, volume)
113142

143+
def volumes(self, details=True, **query):
144+
"""Retrieve a generator of volumes
145+
146+
:param bool details: When set to ``False``
147+
:class:`~openstack.block_store.v2.volume.Volume` objects
148+
will be returned. The default, ``True``, will cause
149+
:class:`~openstack.block_store.v2.volume.VolumeDetail`
150+
objects to be returned.
151+
:param kwargs \*\*query: Optional query parameters to be sent to limit
152+
the volumes being returned. Available parameters include:
153+
154+
* name: Name of the volume as a string.
155+
* all_tenants: Whether return the volumes of all tenants
156+
* status: Value of the status of the volume so that you can filter
157+
on "available" for example.
158+
159+
:returns: A generator of volume objects.
160+
"""
161+
volume = _volume.VolumeDetail if details else _volume.Volume
162+
return self._list(volume, paginated=True, **query)
163+
114164
def create_volume(self, **attrs):
115165
"""Create a new volume from attributes
116166

openstack/block_store/v2/snapshot.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,54 @@
1212

1313
from openstack.block_store import block_store_service
1414
from openstack import format
15-
from openstack import resource
15+
from openstack import resource2
1616

1717

18-
class Snapshot(resource.Resource):
18+
class Snapshot(resource2.Resource):
1919
resource_key = "snapshot"
2020
resources_key = "snapshots"
2121
base_path = "/snapshots"
2222
service = block_store_service.BlockStoreService()
2323

24+
_query_mapping = resource2.QueryParameters('all_tenants', 'name', 'status',
25+
'volume_id')
26+
2427
# capabilities
25-
allow_retrieve = True
28+
allow_get = True
2629
allow_create = True
2730
allow_delete = True
2831
allow_update = True
32+
allow_list = True
2933

3034
# Properties
3135
#: A ID representing this snapshot.
32-
id = resource.prop("id")
36+
id = resource2.Body("id")
3337
#: Name of the snapshot. Default is None.
34-
name = resource.prop("name")
38+
name = resource2.Body("name")
3539

3640
#: The current status of this snapshot. Potential values are creating,
3741
#: available, deleting, error, and error_deleting.
38-
status = resource.prop("status")
42+
status = resource2.Body("status")
3943
#: Description of snapshot. Default is None.
40-
description = resource.prop("description")
44+
description = resource2.Body("description")
4145
#: The timestamp of this snapshot creation.
42-
created_at = resource.prop("created_at")
46+
created_at = resource2.Body("created_at")
4347
#: Metadata associated with this snapshot.
44-
metadata = resource.prop("metadata", type=dict)
48+
metadata = resource2.Body("metadata", type=dict)
4549
#: The ID of the volume this snapshot was taken of.
46-
volume_id = resource.prop("volume_id")
50+
volume_id = resource2.Body("volume_id")
4751
#: The size of the volume, in GBs.
48-
size = resource.prop("size", type=int)
52+
size = resource2.Body("size", type=int)
4953
#: Indicate whether to create snapshot, even if the volume is attached.
5054
#: Default is ``False``. *Type: bool*
51-
is_forced = resource.prop("force", type=format.BoolStr)
55+
is_forced = resource2.Body("force", type=format.BoolStr)
5256

5357

5458
class SnapshotDetail(Snapshot):
5559

5660
base_path = "/snapshots/detail"
5761

5862
#: The percentage of completeness the snapshot is currently at.
59-
progress = resource.prop("os-extended-snapshot-attributes:progress")
63+
progress = resource2.Body("os-extended-snapshot-attributes:progress")
6064
#: The project ID this snapshot is associated with.
61-
project_id = resource.prop("os-extended-snapshot-attributes:project_id")
65+
project_id = resource2.Body("os-extended-snapshot-attributes:project_id")

openstack/block_store/v2/type.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,25 @@
1111
# under the License.
1212

1313
from openstack.block_store import block_store_service
14-
from openstack import resource
14+
from openstack import resource2
1515

1616

17-
class Type(resource.Resource):
17+
class Type(resource2.Resource):
1818
resource_key = "volume_type"
1919
resources_key = "volume_types"
2020
base_path = "/types"
2121
service = block_store_service.BlockStoreService()
2222

2323
# capabilities
24-
allow_retrieve = True
24+
allow_get = True
2525
allow_create = True
2626
allow_delete = True
27+
allow_list = True
2728

2829
# Properties
2930
#: A ID representing this type.
30-
id = resource.prop("id")
31+
id = resource2.Body("id")
3132
#: Name of the type.
32-
name = resource.prop("name")
33+
name = resource2.Body("name")
3334
#: A dict of extra specifications. "capabilities" is a usual key.
34-
extra_specs = resource.prop("extra_specs", type=dict)
35+
extra_specs = resource2.Body("extra_specs", type=dict)

openstack/block_store/v2/volume.py

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,88 +12,91 @@
1212

1313
from openstack.block_store import block_store_service
1414
from openstack import format
15-
from openstack import resource
15+
from openstack import resource2
1616

1717

18-
class Volume(resource.Resource):
18+
class Volume(resource2.Resource):
1919
resource_key = "volume"
2020
resources_key = "volumes"
2121
base_path = "/volumes"
2222
service = block_store_service.BlockStoreService()
2323

24+
_query_mapping = resource2.QueryParameters('all_tenants', 'name', 'status')
25+
2426
# capabilities
25-
allow_retrieve = True
27+
allow_get = True
2628
allow_create = True
2729
allow_delete = True
2830
allow_update = True
31+
allow_list = True
2932

3033
# Properties
3134
#: A ID representing this volume.
32-
id = resource.prop("id")
35+
id = resource2.Body("id")
3336
#: The name of this volume.
34-
name = resource.prop("name")
37+
name = resource2.Body("name")
3538
#: A list of links associated with this volume. *Type: list*
36-
links = resource.prop("links", type=list)
39+
links = resource2.Body("links", type=list)
3740

3841
#: The availability zone.
39-
availability_zone = resource.prop("availability_zone")
42+
availability_zone = resource2.Body("availability_zone")
4043
#: To create a volume from an existing volume, specify the ID of
4144
#: the existing volume. If specified, the volume is created with
4245
#: same size of the source volume.
43-
source_volume_id = resource.prop("source_volid")
46+
source_volume_id = resource2.Body("source_volid")
4447
#: The volume description.
45-
description = resource.prop("description")
48+
description = resource2.Body("description")
4649
#: To create a volume from an existing snapshot, specify the ID of
4750
#: the existing volume snapshot. If specified, the volume is created
4851
#: in same availability zone and with same size of the snapshot.
49-
snapshot_id = resource.prop("snapshot_id")
52+
snapshot_id = resource2.Body("snapshot_id")
5053
#: The size of the volume, in GBs. *Type: int*
51-
size = resource.prop("size", type=int)
54+
size = resource2.Body("size", type=int)
5255
#: The ID of the image from which you want to create the volume.
5356
#: Required to create a bootable volume.
54-
image_id = resource.prop("imageRef")
57+
image_id = resource2.Body("imageRef")
5558
#: The name of the associated volume type.
56-
volume_type = resource.prop("volume_type")
59+
volume_type = resource2.Body("volume_type")
5760
#: Enables or disables the bootable attribute. You can boot an
5861
#: instance from a bootable volume. *Type: bool*
59-
is_bootable = resource.prop("bootable", type=format.BoolStr)
62+
is_bootable = resource2.Body("bootable", type=format.BoolStr)
6063
#: One or more metadata key and value pairs to associate with the volume.
61-
metadata = resource.prop("metadata")
64+
metadata = resource2.Body("metadata")
6265

6366
#: One of the following values: creating, available, attaching, in-use
6467
#: deleting, error, error_deleting, backing-up, restoring-backup,
6568
#: error_restoring. For details on these statuses, see the
6669
#: Block Storage API documentation.
67-
status = resource.prop("status")
70+
status = resource2.Body("status")
6871
#: TODO(briancurtin): This is currently undocumented in the API.
69-
attachments = resource.prop("attachments")
72+
attachments = resource2.Body("attachments")
7073
#: The timestamp of this volume creation.
71-
created_at = resource.prop("created_at")
74+
created_at = resource2.Body("created_at")
7275

7376

7477
class VolumeDetail(Volume):
7578

7679
base_path = "/volumes/detail"
7780

7881
#: The volume's current back-end.
79-
host = resource.prop("os-vol-host-attr:host")
82+
host = resource2.Body("os-vol-host-attr:host")
8083
#: The project ID associated with current back-end.
81-
project_id = resource.prop("os-vol-tenant-attr:tenant_id")
84+
project_id = resource2.Body("os-vol-tenant-attr:tenant_id")
8285
#: The status of this volume's migration (None means that a migration
8386
#: is not currently in progress).
84-
migration_status = resource.prop("os-vol-mig-status-attr:migstat")
87+
migration_status = resource2.Body("os-vol-mig-status-attr:migstat")
8588
#: The volume ID that this volume's name on the back-end is based on.
86-
migration_id = resource.prop("os-vol-mig-status-attr:name_id")
89+
migration_id = resource2.Body("os-vol-mig-status-attr:name_id")
8790
#: Status of replication on this volume.
88-
replication_status = resource.prop("replication_status")
91+
replication_status = resource2.Body("replication_status")
8992
#: Extended replication status on this volume.
90-
extended_replication_status = resource.prop(
93+
extended_replication_status = resource2.Body(
9194
"os-volume-replication:extended_status")
9295
#: ID of the consistency group.
93-
consistency_group_id = resource.prop("consistencygroup_id")
96+
consistency_group_id = resource2.Body("consistencygroup_id")
9497
#: Data set by the replication driver
95-
replication_driver_data = resource.prop(
98+
replication_driver_data = resource2.Body(
9699
"os-volume-replication:driver_data")
97100
#: ``True`` if this volume is encrypted, ``False`` if not.
98101
#: *Type: bool*
99-
is_encrypted = resource.prop("encrypted", type=format.BoolStr)
102+
is_encrypted = resource2.Body("encrypted", type=format.BoolStr)

openstack/tests/unit/block_store/v2/test_proxy.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,29 @@
1414
from openstack.block_store.v2 import snapshot
1515
from openstack.block_store.v2 import type
1616
from openstack.block_store.v2 import volume
17-
from openstack.tests.unit import test_proxy_base
17+
from openstack.tests.unit import test_proxy_base2
1818

1919

20-
class TestVolumeProxy(test_proxy_base.TestProxyBase):
20+
class TestVolumeProxy(test_proxy_base2.TestProxyBase):
2121
def setUp(self):
2222
super(TestVolumeProxy, self).setUp()
2323
self.proxy = _proxy.Proxy(self.session)
2424

2525
def test_snapshot_get(self):
2626
self.verify_get(self.proxy.get_snapshot, snapshot.Snapshot)
2727

28+
def test_snapshots_detailed(self):
29+
self.verify_list(self.proxy.snapshots, snapshot.SnapshotDetail,
30+
paginated=True,
31+
method_kwargs={"details": True, "query": 1},
32+
expected_kwargs={"query": 1})
33+
34+
def test_snapshots_not_detailed(self):
35+
self.verify_list(self.proxy.snapshots, snapshot.Snapshot,
36+
paginated=True,
37+
method_kwargs={"details": False, "query": 1},
38+
expected_kwargs={"query": 1})
39+
2840
def test_snapshot_create_attrs(self):
2941
self.verify_create(self.proxy.create_snapshot, snapshot.Snapshot)
3042

@@ -39,6 +51,9 @@ def test_snapshot_delete_ignore(self):
3951
def test_type_get(self):
4052
self.verify_get(self.proxy.get_type, type.Type)
4153

54+
def test_types(self):
55+
self.verify_list(self.proxy.types, type.Type, paginated=False)
56+
4257
def test_type_create_attrs(self):
4358
self.verify_create(self.proxy.create_type, type.Type)
4459

@@ -51,6 +66,18 @@ def test_type_delete_ignore(self):
5166
def test_volume_get(self):
5267
self.verify_get(self.proxy.get_volume, volume.Volume)
5368

69+
def test_volumes_detailed(self):
70+
self.verify_list(self.proxy.volumes, volume.VolumeDetail,
71+
paginated=True,
72+
method_kwargs={"details": True, "query": 1},
73+
expected_kwargs={"query": 1})
74+
75+
def test_volumes_not_detailed(self):
76+
self.verify_list(self.proxy.volumes, volume.Volume,
77+
paginated=True,
78+
method_kwargs={"details": False, "query": 1},
79+
expected_kwargs={"query": 1})
80+
5481
def test_volume_create_attrs(self):
5582
self.verify_create(self.proxy.create_volume, volume.Volume)
5683

0 commit comments

Comments
 (0)