python-openstackclient 8.1.0__py3-none-any.whl → 8.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. openstackclient/api/compute_v2.py +2 -2
  2. openstackclient/api/object_store_v1.py +4 -1
  3. openstackclient/api/volume_v2.py +60 -0
  4. openstackclient/api/volume_v3.py +60 -0
  5. openstackclient/command.py +27 -0
  6. openstackclient/common/availability_zone.py +1 -1
  7. openstackclient/common/clientmanager.py +59 -21
  8. openstackclient/common/configuration.py +1 -1
  9. openstackclient/common/extension.py +1 -1
  10. openstackclient/common/limits.py +1 -1
  11. openstackclient/common/module.py +4 -2
  12. openstackclient/common/project_cleanup.py +10 -8
  13. openstackclient/common/quota.py +23 -6
  14. openstackclient/common/versions.py +1 -2
  15. openstackclient/compute/v2/agent.py +1 -1
  16. openstackclient/compute/v2/aggregate.py +6 -5
  17. openstackclient/compute/v2/console.py +5 -3
  18. openstackclient/compute/v2/console_connection.py +1 -1
  19. openstackclient/compute/v2/flavor.py +15 -2
  20. openstackclient/compute/v2/host.py +1 -1
  21. openstackclient/compute/v2/hypervisor.py +1 -1
  22. openstackclient/compute/v2/hypervisor_stats.py +1 -1
  23. openstackclient/compute/v2/keypair.py +1 -1
  24. openstackclient/compute/v2/server.py +77 -30
  25. openstackclient/compute/v2/server_backup.py +1 -1
  26. openstackclient/compute/v2/server_event.py +1 -1
  27. openstackclient/compute/v2/server_group.py +4 -2
  28. openstackclient/compute/v2/server_image.py +1 -1
  29. openstackclient/compute/v2/server_migration.py +1 -1
  30. openstackclient/compute/v2/server_volume.py +1 -1
  31. openstackclient/compute/v2/service.py +1 -1
  32. openstackclient/compute/v2/usage.py +6 -4
  33. openstackclient/identity/common.py +10 -14
  34. openstackclient/identity/v2_0/catalog.py +3 -2
  35. openstackclient/identity/v2_0/ec2creds.py +1 -1
  36. openstackclient/identity/v2_0/endpoint.py +1 -1
  37. openstackclient/identity/v2_0/project.py +17 -7
  38. openstackclient/identity/v2_0/role.py +1 -1
  39. openstackclient/identity/v2_0/role_assignment.py +3 -3
  40. openstackclient/identity/v2_0/service.py +1 -1
  41. openstackclient/identity/v2_0/token.py +1 -1
  42. openstackclient/identity/v2_0/user.py +2 -2
  43. openstackclient/identity/v3/access_rule.py +16 -4
  44. openstackclient/identity/v3/application_credential.py +116 -95
  45. openstackclient/identity/v3/catalog.py +3 -3
  46. openstackclient/identity/v3/consumer.py +1 -1
  47. openstackclient/identity/v3/credential.py +1 -1
  48. openstackclient/identity/v3/domain.py +15 -10
  49. openstackclient/identity/v3/ec2creds.py +1 -1
  50. openstackclient/identity/v3/endpoint.py +33 -12
  51. openstackclient/identity/v3/endpoint_group.py +1 -1
  52. openstackclient/identity/v3/federation_protocol.py +1 -1
  53. openstackclient/identity/v3/group.py +11 -5
  54. openstackclient/identity/v3/identity_provider.py +12 -10
  55. openstackclient/identity/v3/implied_role.py +1 -1
  56. openstackclient/identity/v3/limit.py +1 -1
  57. openstackclient/identity/v3/mapping.py +1 -1
  58. openstackclient/identity/v3/policy.py +1 -1
  59. openstackclient/identity/v3/project.py +34 -22
  60. openstackclient/identity/v3/region.py +1 -1
  61. openstackclient/identity/v3/registered_limit.py +16 -11
  62. openstackclient/identity/v3/role.py +27 -41
  63. openstackclient/identity/v3/role_assignment.py +12 -23
  64. openstackclient/identity/v3/service.py +1 -1
  65. openstackclient/identity/v3/service_provider.py +1 -1
  66. openstackclient/identity/v3/tag.py +3 -2
  67. openstackclient/identity/v3/token.py +3 -2
  68. openstackclient/identity/v3/trust.py +4 -2
  69. openstackclient/identity/v3/unscoped_saml.py +1 -1
  70. openstackclient/identity/v3/user.py +22 -13
  71. openstackclient/image/v1/image.py +35 -17
  72. openstackclient/image/v2/cache.py +11 -7
  73. openstackclient/image/v2/image.py +62 -12
  74. openstackclient/image/v2/info.py +1 -1
  75. openstackclient/image/v2/metadef_namespaces.py +1 -1
  76. openstackclient/image/v2/metadef_objects.py +9 -3
  77. openstackclient/image/v2/metadef_properties.py +11 -3
  78. openstackclient/image/v2/metadef_resource_type_association.py +1 -1
  79. openstackclient/image/v2/metadef_resource_types.py +1 -1
  80. openstackclient/image/v2/task.py +1 -1
  81. openstackclient/network/common.py +10 -9
  82. openstackclient/network/v2/address_group.py +4 -3
  83. openstackclient/network/v2/address_scope.py +8 -6
  84. openstackclient/network/v2/default_security_group_rule.py +9 -8
  85. openstackclient/network/v2/floating_ip.py +16 -9
  86. openstackclient/network/v2/floating_ip_port_forwarding.py +9 -6
  87. openstackclient/network/v2/ip_availability.py +7 -4
  88. openstackclient/network/v2/l3_conntrack_helper.py +11 -4
  89. openstackclient/network/v2/local_ip.py +13 -7
  90. openstackclient/network/v2/local_ip_association.py +7 -4
  91. openstackclient/network/v2/ndp_proxy.py +13 -6
  92. openstackclient/network/v2/network.py +33 -16
  93. openstackclient/network/v2/network_agent.py +5 -5
  94. openstackclient/network/v2/network_auto_allocated_topology.py +1 -1
  95. openstackclient/network/v2/network_flavor.py +1 -1
  96. openstackclient/network/v2/network_flavor_profile.py +1 -1
  97. openstackclient/network/v2/network_meter.py +1 -1
  98. openstackclient/network/v2/network_meter_rule.py +1 -1
  99. openstackclient/network/v2/network_qos_policy.py +7 -5
  100. openstackclient/network/v2/network_qos_rule.py +1 -1
  101. openstackclient/network/v2/network_qos_rule_type.py +1 -1
  102. openstackclient/network/v2/network_rbac.py +8 -5
  103. openstackclient/network/v2/network_segment.py +2 -2
  104. openstackclient/network/v2/network_segment_range.py +13 -6
  105. openstackclient/network/v2/network_service_provider.py +1 -1
  106. openstackclient/network/v2/network_trunk.py +65 -42
  107. openstackclient/network/v2/port.py +38 -20
  108. openstackclient/network/v2/router.py +19 -8
  109. openstackclient/network/v2/security_group.py +52 -7
  110. openstackclient/network/v2/security_group_rule.py +27 -4
  111. openstackclient/network/v2/subnet.py +17 -18
  112. openstackclient/network/v2/subnet_pool.py +11 -9
  113. openstackclient/network/v2/taas/__init__.py +0 -0
  114. openstackclient/network/v2/taas/tap_flow.py +245 -0
  115. openstackclient/network/v2/taas/tap_mirror.py +237 -0
  116. openstackclient/network/v2/taas/tap_service.py +211 -0
  117. openstackclient/object/v1/account.py +1 -1
  118. openstackclient/object/v1/container.py +1 -1
  119. openstackclient/object/v1/object.py +1 -1
  120. openstackclient/shell.py +18 -8
  121. openstackclient/tests/functional/identity/v3/test_access_rule.py +1 -1
  122. openstackclient/tests/functional/identity/v3/test_application_credential.py +7 -7
  123. openstackclient/tests/functional/identity/v3/test_catalog.py +42 -23
  124. openstackclient/tests/functional/identity/v3/test_role_assignment.py +174 -0
  125. openstackclient/tests/functional/image/v2/test_cache.py +54 -0
  126. openstackclient/tests/functional/image/v2/test_image.py +36 -14
  127. openstackclient/tests/functional/image/v2/test_metadef_resource_type.py +55 -0
  128. openstackclient/tests/functional/volume/v2/test_volume.py +1 -1
  129. openstackclient/tests/functional/volume/v3/test_volume.py +2 -2
  130. openstackclient/tests/unit/api/test_volume_v2.py +124 -0
  131. openstackclient/tests/unit/api/test_volume_v3.py +124 -0
  132. openstackclient/tests/unit/common/test_command.py +1 -1
  133. openstackclient/tests/unit/common/test_extension.py +2 -3
  134. openstackclient/tests/unit/common/test_module.py +14 -7
  135. openstackclient/tests/unit/common/test_quota.py +20 -0
  136. openstackclient/tests/unit/compute/v2/test_aggregate.py +5 -3
  137. openstackclient/tests/unit/compute/v2/test_console.py +1 -4
  138. openstackclient/tests/unit/compute/v2/test_flavor.py +160 -177
  139. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -9
  140. openstackclient/tests/unit/compute/v2/test_server.py +406 -81
  141. openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -3
  142. openstackclient/tests/unit/compute/v2/test_service.py +1 -3
  143. openstackclient/tests/unit/fakes.py +35 -134
  144. openstackclient/tests/unit/identity/test_common.py +100 -0
  145. openstackclient/tests/unit/identity/v2_0/test_project.py +4 -4
  146. openstackclient/tests/unit/identity/v3/fakes.py +10 -2
  147. openstackclient/tests/unit/identity/v3/test_application_credential.py +50 -44
  148. openstackclient/tests/unit/identity/v3/test_domain.py +3 -3
  149. openstackclient/tests/unit/identity/v3/test_endpoint.py +1 -1
  150. openstackclient/tests/unit/identity/v3/test_group.py +4 -2
  151. openstackclient/tests/unit/identity/v3/test_identity_provider.py +10 -10
  152. openstackclient/tests/unit/identity/v3/test_oauth.py +1 -1
  153. openstackclient/tests/unit/identity/v3/test_project.py +31 -54
  154. openstackclient/tests/unit/identity/v3/test_registered_limit.py +2 -2
  155. openstackclient/tests/unit/identity/v3/test_role.py +3 -90
  156. openstackclient/tests/unit/identity/v3/test_user.py +7 -51
  157. openstackclient/tests/unit/image/v1/test_image.py +47 -0
  158. openstackclient/tests/unit/image/v2/test_image.py +190 -9
  159. openstackclient/tests/unit/image/v2/test_metadef_objects.py +22 -0
  160. openstackclient/tests/unit/image/v2/test_metadef_properties.py +24 -10
  161. openstackclient/tests/unit/network/test_common.py +9 -13
  162. openstackclient/tests/unit/network/v2/fakes.py +1 -0
  163. openstackclient/tests/unit/network/v2/taas/__init__.py +0 -0
  164. openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py +276 -0
  165. openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py +288 -0
  166. openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py +271 -0
  167. openstackclient/tests/unit/network/v2/test_address_group.py +19 -22
  168. openstackclient/tests/unit/network/v2/test_address_scope.py +10 -15
  169. openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +38 -49
  170. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +21 -27
  171. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +21 -18
  172. openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -8
  173. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +6 -15
  174. openstackclient/tests/unit/network/v2/test_local_ip.py +12 -23
  175. openstackclient/tests/unit/network/v2/test_local_ip_association.py +13 -18
  176. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +13 -23
  177. openstackclient/tests/unit/network/v2/test_network.py +41 -37
  178. openstackclient/tests/unit/network/v2/test_network_agent.py +13 -20
  179. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +5 -8
  180. openstackclient/tests/unit/network/v2/test_network_flavor.py +14 -26
  181. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +14 -17
  182. openstackclient/tests/unit/network/v2/test_network_meter.py +7 -17
  183. openstackclient/tests/unit/network/v2/test_network_meter_rule.py +10 -20
  184. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +7 -13
  185. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +44 -54
  186. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +2 -7
  187. openstackclient/tests/unit/network/v2/test_network_rbac.py +21 -36
  188. openstackclient/tests/unit/network/v2/test_network_segment.py +13 -29
  189. openstackclient/tests/unit/network/v2/test_network_segment_range.py +20 -19
  190. openstackclient/tests/unit/network/v2/test_network_service_provider.py +1 -4
  191. openstackclient/tests/unit/network/v2/test_network_trunk.py +52 -47
  192. openstackclient/tests/unit/network/v2/test_port.py +113 -84
  193. openstackclient/tests/unit/network/v2/test_router.py +104 -126
  194. openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -26
  195. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +66 -18
  196. openstackclient/tests/unit/network/v2/test_subnet.py +35 -46
  197. openstackclient/tests/unit/network/v2/test_subnet_pool.py +21 -33
  198. openstackclient/tests/unit/volume/test_find_resource.py +4 -13
  199. openstackclient/tests/unit/volume/v2/test_volume.py +358 -305
  200. openstackclient/tests/unit/volume/v2/test_volume_backup.py +3 -1
  201. openstackclient/tests/unit/volume/v3/test_volume.py +443 -415
  202. openstackclient/tests/unit/volume/v3/test_volume_backup.py +9 -0
  203. openstackclient/volume/client.py +7 -17
  204. openstackclient/volume/v2/backup_record.py +1 -1
  205. openstackclient/volume/v2/consistency_group.py +1 -1
  206. openstackclient/volume/v2/consistency_group_snapshot.py +1 -1
  207. openstackclient/volume/v2/qos_specs.py +1 -1
  208. openstackclient/volume/v2/service.py +2 -2
  209. openstackclient/volume/v2/volume.py +80 -54
  210. openstackclient/volume/v2/volume_backend.py +1 -1
  211. openstackclient/volume/v2/volume_backup.py +5 -3
  212. openstackclient/volume/v2/volume_host.py +1 -2
  213. openstackclient/volume/v2/volume_snapshot.py +2 -2
  214. openstackclient/volume/v2/volume_transfer_request.py +1 -1
  215. openstackclient/volume/v2/volume_type.py +11 -6
  216. openstackclient/volume/v3/block_storage_cleanup.py +1 -1
  217. openstackclient/volume/v3/block_storage_cluster.py +1 -1
  218. openstackclient/volume/v3/block_storage_log_level.py +1 -1
  219. openstackclient/volume/v3/block_storage_manage.py +1 -1
  220. openstackclient/volume/v3/block_storage_resource_filter.py +1 -1
  221. openstackclient/volume/v3/service.py +2 -2
  222. openstackclient/volume/v3/volume.py +104 -77
  223. openstackclient/volume/v3/volume_attachment.py +6 -5
  224. openstackclient/volume/v3/volume_backup.py +18 -3
  225. openstackclient/volume/v3/volume_group.py +2 -2
  226. openstackclient/volume/v3/volume_group_snapshot.py +1 -1
  227. openstackclient/volume/v3/volume_group_type.py +1 -1
  228. openstackclient/volume/v3/volume_message.py +1 -1
  229. openstackclient/volume/v3/volume_snapshot.py +2 -2
  230. openstackclient/volume/v3/volume_transfer_request.py +1 -1
  231. openstackclient/volume/v3/volume_type.py +15 -9
  232. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/METADATA +19 -17
  233. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/RECORD +239 -224
  234. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/WHEEL +1 -1
  235. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/entry_points.txt +15 -0
  236. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/AUTHORS +15 -0
  237. python_openstackclient-8.3.0.dist-info/pbr.json +1 -0
  238. openstackclient/tests/unit/common/test_logs.py +0 -221
  239. python_openstackclient-8.1.0.dist-info/pbr.json +0 -1
  240. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/LICENSE +0 -0
  241. {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/top_level.txt +0 -0
@@ -18,16 +18,19 @@ import argparse
18
18
  import copy
19
19
  import functools
20
20
  import logging
21
+ import typing as ty
21
22
 
22
23
  from cliff import columns as cliff_columns
24
+ from openstack.block_storage.v3 import volume as _volume
23
25
  from openstack import exceptions as sdk_exceptions
24
26
  from openstack import utils as sdk_utils
25
27
  from osc_lib.cli import format_columns
26
28
  from osc_lib.cli import parseractions
27
- from osc_lib.command import command
28
29
  from osc_lib import exceptions
29
30
  from osc_lib import utils
30
31
 
32
+ from openstackclient.api import volume_v3
33
+ from openstackclient import command
31
34
  from openstackclient.common import pagination
32
35
  from openstackclient.i18n import _
33
36
  from openstackclient.identity import common as identity_common
@@ -59,7 +62,7 @@ class KeyValueHintAction(argparse.Action):
59
62
  )
60
63
 
61
64
 
62
- class AttachmentsColumn(cliff_columns.FormattableColumn):
65
+ class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
63
66
  """Formattable column for attachments column.
64
67
 
65
68
  Unlike the parent FormattableColumn class, the initializer of the
@@ -90,6 +93,52 @@ class AttachmentsColumn(cliff_columns.FormattableColumn):
90
93
  return msg
91
94
 
92
95
 
96
+ def _format_volume(volume: _volume.Volume) -> dict[str, ty.Any]:
97
+ # Some columns returned by openstacksdk should not be shown because they're
98
+ # either irrelevant or duplicates
99
+ ignored_columns = {
100
+ # computed columns
101
+ 'location',
102
+ # create-only columns
103
+ 'OS-SCH-HNT:scheduler_hints',
104
+ 'imageRef',
105
+ # removed columns
106
+ 'os-volume-replication:driver_data',
107
+ 'os-volume-replication:extended_status',
108
+ # unnecessary columns
109
+ 'links',
110
+ }
111
+ optional_columns = {
112
+ # only present if part of a consistency group
113
+ 'consistencygroup_id',
114
+ # only present if the volume is encrypted
115
+ 'encryption_key_id',
116
+ # only present if there are image properties associated
117
+ 'volume_image_metadata',
118
+ }
119
+
120
+ info = volume.to_dict(original_names=True)
121
+ data = {}
122
+ for key, value in info.items():
123
+ if key in ignored_columns:
124
+ continue
125
+
126
+ if key in optional_columns:
127
+ if info[key] is None:
128
+ continue
129
+
130
+ data[key] = value
131
+
132
+ data.update(
133
+ {
134
+ 'properties': format_columns.DictColumn(data.pop('metadata')),
135
+ 'type': data.pop('volume_type'),
136
+ }
137
+ )
138
+
139
+ return data
140
+
141
+
93
142
  class CreateVolume(command.ShowOne):
94
143
  _description = _("Create new volume")
95
144
 
@@ -272,8 +321,7 @@ class CreateVolume(command.ShowOne):
272
321
  # volume from snapshot, backup or source volume
273
322
  size = parsed_args.size
274
323
 
275
- volume_client_sdk = self.app.client_manager.sdk_connection.volume
276
- volume_client = self.app.client_manager.volume
324
+ volume_client = self.app.client_manager.sdk_connection.volume
277
325
  image_client = self.app.client_manager.image
278
326
 
279
327
  if (
@@ -285,8 +333,8 @@ class CreateVolume(command.ShowOne):
285
333
  )
286
334
  raise exceptions.CommandError(msg)
287
335
 
288
- if parsed_args.backup and not (
289
- volume_client.api_version.matches('3.47')
336
+ if parsed_args.backup and not sdk_utils.supports_microversion(
337
+ volume_client, '3.47'
290
338
  ):
291
339
  msg = _(
292
340
  "--os-volume-api-version 3.47 or greater is required "
@@ -308,9 +356,7 @@ class CreateVolume(command.ShowOne):
308
356
  )
309
357
  raise exceptions.CommandError(msg)
310
358
  if parsed_args.cluster:
311
- if not sdk_utils.supports_microversion(
312
- volume_client_sdk, '3.16'
313
- ):
359
+ if not sdk_utils.supports_microversion(volume_client, '3.16'):
314
360
  msg = _(
315
361
  "--os-volume-api-version 3.16 or greater is required "
316
362
  "to support the cluster parameter."
@@ -328,7 +374,7 @@ class CreateVolume(command.ShowOne):
328
374
  "manage a volume."
329
375
  )
330
376
  raise exceptions.CommandError(msg)
331
- volume = volume_client_sdk.manage_volume(
377
+ volume = volume_client.manage_volume(
332
378
  host=parsed_args.host,
333
379
  cluster=parsed_args.cluster,
334
380
  ref=parsed_args.remote_source,
@@ -339,35 +385,22 @@ class CreateVolume(command.ShowOne):
339
385
  metadata=parsed_args.properties,
340
386
  bootable=parsed_args.bootable,
341
387
  )
342
- data = {}
343
- for key, value in volume.to_dict().items():
344
- # FIXME(stephenfin): Stop ignoring these once we bump SDK
345
- # https://review.opendev.org/c/openstack/openstacksdk/+/945836/
346
- if key in (
347
- 'cluster_name',
348
- 'consumes_quota',
349
- 'encryption_key_id',
350
- 'service_uuid',
351
- 'shared_targets',
352
- 'volume_type_id',
353
- ):
354
- continue
355
- data[key] = value
388
+ data = _format_volume(volume)
356
389
  return zip(*sorted(data.items()))
357
390
 
358
391
  source_volume = None
359
392
  if parsed_args.source:
360
- source_volume_obj = utils.find_resource(
361
- volume_client.volumes, parsed_args.source
393
+ source_volume_obj = volume_client.find_volume(
394
+ parsed_args.source, ignore_missing=False
362
395
  )
363
396
  source_volume = source_volume_obj.id
364
397
  size = max(size or 0, source_volume_obj.size)
365
398
 
366
399
  consistency_group = None
367
400
  if parsed_args.consistency_group:
368
- consistency_group = utils.find_resource(
369
- volume_client.consistencygroups, parsed_args.consistency_group
370
- ).id
401
+ consistency_group = volume_v3.find_consistency_group(
402
+ volume_client, parsed_args.consistency_group
403
+ )['id']
371
404
 
372
405
  image = None
373
406
  if parsed_args.image:
@@ -377,8 +410,8 @@ class CreateVolume(command.ShowOne):
377
410
 
378
411
  snapshot = None
379
412
  if parsed_args.snapshot:
380
- snapshot_obj = utils.find_resource(
381
- volume_client.volume_snapshots, parsed_args.snapshot
413
+ snapshot_obj = volume_client.find_snapshot(
414
+ parsed_args.snapshot, ignore_missing=False
382
415
  )
383
416
  snapshot = snapshot_obj.id
384
417
  # Cinder requires a value for size when creating a volume
@@ -391,14 +424,14 @@ class CreateVolume(command.ShowOne):
391
424
 
392
425
  backup = None
393
426
  if parsed_args.backup:
394
- backup_obj = utils.find_resource(
395
- volume_client.backups, parsed_args.backup
427
+ backup_obj = volume_client.find_backup(
428
+ parsed_args.backup, ignore_missing=False
396
429
  )
397
430
  backup = backup_obj.id
398
431
  # As above
399
432
  size = max(size or 0, backup_obj.size)
400
433
 
401
- volume = volume_client.volumes.create(
434
+ volume = volume_client.create_volume(
402
435
  size=size,
403
436
  snapshot_id=snapshot,
404
437
  name=parsed_args.name,
@@ -406,9 +439,9 @@ class CreateVolume(command.ShowOne):
406
439
  volume_type=parsed_args.type,
407
440
  availability_zone=parsed_args.availability_zone,
408
441
  metadata=parsed_args.properties,
409
- imageRef=image,
410
- source_volid=source_volume,
411
- consistencygroup_id=consistency_group,
442
+ image_id=image,
443
+ source_volume_id=source_volume,
444
+ consistency_group_id=consistency_group,
412
445
  scheduler_hints=parsed_args.hint,
413
446
  backup_id=backup,
414
447
  )
@@ -416,14 +449,14 @@ class CreateVolume(command.ShowOne):
416
449
  if parsed_args.bootable is not None:
417
450
  try:
418
451
  if utils.wait_for_status(
419
- volume_client.volumes.get,
452
+ volume_client.get_volume,
420
453
  volume.id,
421
454
  success_status=['available'],
422
455
  error_status=['error'],
423
456
  sleep_time=1,
424
457
  ):
425
- volume_client.volumes.set_bootable(
426
- volume.id, parsed_args.bootable
458
+ volume_client.set_volume_bootable_status(
459
+ volume, parsed_args.bootable
427
460
  )
428
461
  else:
429
462
  msg = _(
@@ -436,14 +469,14 @@ class CreateVolume(command.ShowOne):
436
469
  if parsed_args.read_only is not None:
437
470
  try:
438
471
  if utils.wait_for_status(
439
- volume_client.volumes.get,
472
+ volume_client.get_volume,
440
473
  volume.id,
441
474
  success_status=['available'],
442
475
  error_status=['error'],
443
476
  sleep_time=1,
444
477
  ):
445
- volume_client.volumes.update_readonly_flag(
446
- volume.id, parsed_args.read_only
478
+ volume_client.set_volume_readonly(
479
+ volume, parsed_args.read_only
447
480
  )
448
481
  else:
449
482
  msg = _(
@@ -457,17 +490,8 @@ class CreateVolume(command.ShowOne):
457
490
  e,
458
491
  )
459
492
 
460
- # Remove key links from being displayed
461
- volume._info.update(
462
- {
463
- 'properties': format_columns.DictColumn(
464
- volume._info.pop('metadata')
465
- ),
466
- 'type': volume._info.pop('volume_type'),
467
- }
468
- )
469
- volume._info.pop("links", None)
470
- return zip(*sorted(volume._info.items()))
493
+ data = _format_volume(volume)
494
+ return zip(*sorted(data.items()))
471
495
 
472
496
 
473
497
  class DeleteVolume(command.Command):
@@ -574,6 +598,16 @@ class ListVolume(command.Lister):
574
598
  metavar='<status>',
575
599
  help=_('Filter results by status'),
576
600
  )
601
+ parser.add_argument(
602
+ '--property',
603
+ metavar='<key=value>',
604
+ action=parseractions.KeyValueAction,
605
+ dest='properties',
606
+ help=_(
607
+ 'Filter by a property on the volume list '
608
+ '(repeat option to filter by multiple properties) '
609
+ ),
610
+ )
577
611
  parser.add_argument(
578
612
  '--all-projects',
579
613
  action='store_true',
@@ -642,6 +676,7 @@ class ListVolume(command.Lister):
642
676
  'user_id': user_id,
643
677
  'name': parsed_args.name,
644
678
  'status': parsed_args.status,
679
+ 'metadata': parsed_args.properties,
645
680
  }
646
681
 
647
682
  data = volume_client.volumes.list(
@@ -726,16 +761,19 @@ class MigrateVolume(command.Command):
726
761
  "(possibly by another operation)"
727
762
  ),
728
763
  )
764
+ # TODO(stephenfin): Add --cluster argument
729
765
  return parser
730
766
 
731
767
  def take_action(self, parsed_args):
732
- volume_client = self.app.client_manager.volume
733
- volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
734
- volume_client.volumes.migrate_volume(
768
+ volume_client = self.app.client_manager.sdk_connection.volume
769
+ volume = volume_client.find_volume(
770
+ parsed_args.volume, ignore_missing=False
771
+ )
772
+ volume_client.migrate_volume(
735
773
  volume.id,
736
- parsed_args.host,
737
- parsed_args.force_host_copy,
738
- parsed_args.lock_volume,
774
+ host=parsed_args.host,
775
+ force_host_copy=parsed_args.force_host_copy,
776
+ lock_volume=parsed_args.lock_volume,
739
777
  )
740
778
 
741
779
 
@@ -1078,24 +1116,13 @@ class ShowVolume(command.ShowOne):
1078
1116
  return parser
1079
1117
 
1080
1118
  def take_action(self, parsed_args):
1081
- volume_client = self.app.client_manager.volume
1082
- volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
1119
+ volume_client = self.app.client_manager.sdk_connection.volume
1120
+ volume = volume_client.find_volume(
1121
+ parsed_args.volume, ignore_missing=False
1122
+ )
1083
1123
 
1084
- # Special mapping for columns to make the output easier to read:
1085
- # 'metadata' --> 'properties'
1086
- # 'volume_type' --> 'type'
1087
- volume._info.update(
1088
- {
1089
- 'properties': format_columns.DictColumn(
1090
- volume._info.pop('metadata')
1091
- ),
1092
- 'type': volume._info.pop('volume_type'),
1093
- },
1094
- )
1095
-
1096
- # Remove key links from being displayed
1097
- volume._info.pop("links", None)
1098
- return zip(*sorted(volume._info.items()))
1124
+ data = _format_volume(volume)
1125
+ return zip(*sorted(data.items()))
1099
1126
 
1100
1127
 
1101
1128
  class UnsetVolume(command.Command):
@@ -11,13 +11,14 @@
11
11
  # under the License.
12
12
 
13
13
  import logging
14
+ import typing as ty
14
15
 
15
16
  from openstack import utils as sdk_utils
16
17
  from osc_lib.cli import format_columns
17
- from osc_lib.command import command
18
18
  from osc_lib import exceptions
19
19
  from osc_lib import utils
20
20
 
21
+ from openstackclient import command
21
22
  from openstackclient.common import envvars
22
23
  from openstackclient.common import pagination
23
24
  from openstackclient.i18n import _
@@ -56,12 +57,12 @@ def _format_attachment(attachment):
56
57
  # VolumeAttachmentManager.create returns a dict while everything else
57
58
  # returns a VolumeAttachment object
58
59
  if isinstance(attachment, dict):
59
- data = []
60
+ data: tuple[ty.Any, ...] = ()
60
61
  for column in columns:
61
62
  if column == 'connection_info':
62
- data.append(format_columns.DictColumn(attachment[column]))
63
+ data += (format_columns.DictColumn(attachment[column]),)
63
64
  continue
64
- data.append(attachment[column])
65
+ data += (attachment[column],)
65
66
  else:
66
67
  data = utils.get_item_properties(
67
68
  attachment,
@@ -458,7 +459,7 @@ class ListVolumeAttachment(command.Lister):
458
459
  }
459
460
  # Update search option with `filters`
460
461
  # if AppendFilters.filters:
461
- # search_opts.update(shell_utils.extract_filters(AppendFilters.filters))
462
+ # search_opts.update(shell_utils.extract_filters(AppendFilters.filters)) # noqa: E501
462
463
 
463
464
  # TODO(stephenfin): Implement sorting
464
465
  attachments = volume_client.attachments(
@@ -21,17 +21,17 @@ import logging
21
21
  from cliff import columns as cliff_columns
22
22
  from openstack import utils as sdk_utils
23
23
  from osc_lib.cli import parseractions
24
- from osc_lib.command import command
25
24
  from osc_lib import exceptions
26
25
  from osc_lib import utils
27
26
 
27
+ from openstackclient import command
28
28
  from openstackclient.common import pagination
29
29
  from openstackclient.i18n import _
30
30
 
31
31
  LOG = logging.getLogger(__name__)
32
32
 
33
33
 
34
- class VolumeIdColumn(cliff_columns.FormattableColumn):
34
+ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
35
35
  """Formattable column for volume ID column.
36
36
 
37
37
  Unlike the parent FormattableColumn class, the initializer of the
@@ -236,6 +236,11 @@ class ListVolumeBackup(command.Lister):
236
236
 
237
237
  def get_parser(self, prog_name):
238
238
  parser = super().get_parser(prog_name)
239
+ parser.add_argument(
240
+ '--project',
241
+ metavar='<project>',
242
+ help=_('Filter results by project (name or ID) (admin only)'),
243
+ )
239
244
  parser.add_argument(
240
245
  "--long",
241
246
  action="store_true",
@@ -296,6 +301,7 @@ class ListVolumeBackup(command.Lister):
296
301
 
297
302
  def take_action(self, parsed_args):
298
303
  volume_client = self.app.client_manager.sdk_connection.volume
304
+ identity_client = self.app.client_manager.sdk_connection.identity
299
305
 
300
306
  columns: tuple[str, ...] = (
301
307
  'id',
@@ -332,6 +338,14 @@ class ListVolumeBackup(command.Lister):
332
338
  VolumeIdColumn, volume_cache=volume_cache
333
339
  )
334
340
 
341
+ all_tenants = parsed_args.all_projects
342
+ project_id = None
343
+ if parsed_args.project:
344
+ all_tenants = True
345
+ project_id = identity_client.find_project(
346
+ parsed_args.project, ignore_missing=False
347
+ ).id
348
+
335
349
  filter_volume_id = None
336
350
  if parsed_args.volume:
337
351
  try:
@@ -360,9 +374,10 @@ class ListVolumeBackup(command.Lister):
360
374
  name=parsed_args.name,
361
375
  status=parsed_args.status,
362
376
  volume_id=filter_volume_id,
363
- all_tenants=parsed_args.all_projects,
377
+ all_tenants=all_tenants,
364
378
  marker=marker_backup_id,
365
379
  limit=parsed_args.limit,
380
+ project_id=project_id,
366
381
  )
367
382
 
368
383
  return (
@@ -13,10 +13,10 @@
13
13
  import argparse
14
14
 
15
15
  from cinderclient import api_versions
16
- from osc_lib.command import command
17
16
  from osc_lib import exceptions
18
17
  from osc_lib import utils
19
18
 
19
+ from openstackclient import command
20
20
  from openstackclient.common import envvars
21
21
  from openstackclient.i18n import _
22
22
 
@@ -552,7 +552,7 @@ class ShowVolumeGroup(command.ShowOne):
552
552
  parsed_args.group,
553
553
  )
554
554
 
555
- group = volume_client.groups.show(group.id, **kwargs)
555
+ group = volume_client.groups.get(group.id, **kwargs)
556
556
 
557
557
  if parsed_args.show_replication_targets:
558
558
  replication_targets = (
@@ -13,10 +13,10 @@
13
13
  import logging
14
14
 
15
15
  from openstack import utils as sdk_utils
16
- from osc_lib.command import command
17
16
  from osc_lib import exceptions
18
17
  from osc_lib import utils
19
18
 
19
+ from openstackclient import command
20
20
  from openstackclient.common import envvars
21
21
  from openstackclient.i18n import _
22
22
 
@@ -15,10 +15,10 @@ import logging
15
15
  from cinderclient import api_versions
16
16
  from osc_lib.cli import format_columns
17
17
  from osc_lib.cli import parseractions
18
- from osc_lib.command import command
19
18
  from osc_lib import exceptions
20
19
  from osc_lib import utils
21
20
 
21
+ from openstackclient import command
22
22
  from openstackclient.i18n import _
23
23
 
24
24
  LOG = logging.getLogger(__name__)
@@ -17,10 +17,10 @@
17
17
  import logging as LOG
18
18
 
19
19
  from cinderclient import api_versions
20
- from osc_lib.command import command
21
20
  from osc_lib import exceptions
22
21
  from osc_lib import utils
23
22
 
23
+ from openstackclient import command
24
24
  from openstackclient.common import pagination
25
25
  from openstackclient.i18n import _
26
26
  from openstackclient.identity import common as identity_common
@@ -22,10 +22,10 @@ from cliff import columns as cliff_columns
22
22
  from openstack.block_storage.v3 import snapshot as _snapshot
23
23
  from osc_lib.cli import format_columns
24
24
  from osc_lib.cli import parseractions
25
- from osc_lib.command import command
26
25
  from osc_lib import exceptions
27
26
  from osc_lib import utils
28
27
 
28
+ from openstackclient import command
29
29
  from openstackclient.common import pagination
30
30
  from openstackclient.i18n import _
31
31
  from openstackclient.identity import common as identity_common
@@ -33,7 +33,7 @@ from openstackclient.identity import common as identity_common
33
33
  LOG = logging.getLogger(__name__)
34
34
 
35
35
 
36
- class VolumeIdColumn(cliff_columns.FormattableColumn):
36
+ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
37
37
  """Formattable column for volume ID column.
38
38
 
39
39
  Unlike the parent FormattableColumn class, the initializer of the
@@ -17,10 +17,10 @@
17
17
  import logging
18
18
 
19
19
  from cinderclient import api_versions
20
- from osc_lib.command import command
21
20
  from osc_lib import exceptions
22
21
  from osc_lib import utils
23
22
 
23
+ from openstackclient import command
24
24
  from openstackclient.i18n import _
25
25
 
26
26
 
@@ -10,21 +10,21 @@
10
10
  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
11
  # License for the specific language governing permissions and limitations
12
12
  # under the License.
13
- #
14
13
 
15
14
  """Volume v3 Type action implementations"""
16
15
 
17
16
  import functools
18
17
  import logging
18
+ import typing as ty
19
19
 
20
20
  from cinderclient import api_versions
21
21
  from cliff import columns as cliff_columns
22
22
  from osc_lib.cli import format_columns
23
23
  from osc_lib.cli import parseractions
24
- from osc_lib.command import command
25
24
  from osc_lib import exceptions
26
25
  from osc_lib import utils
27
26
 
27
+ from openstackclient import command
28
28
  from openstackclient.i18n import _
29
29
  from openstackclient.identity import common as identity_common
30
30
 
@@ -32,7 +32,7 @@ from openstackclient.identity import common as identity_common
32
32
  LOG = logging.getLogger(__name__)
33
33
 
34
34
 
35
- class EncryptionInfoColumn(cliff_columns.FormattableColumn):
35
+ class EncryptionInfoColumn(cliff_columns.FormattableColumn[ty.Any]):
36
36
  """Formattable column for encryption info column.
37
37
 
38
38
  Unlike the parent FormattableColumn class, the initializer of the
@@ -172,7 +172,8 @@ class CreateVolumeType(command.ShowOne):
172
172
  default=False,
173
173
  help=_(
174
174
  "Enabled replication for this volume type "
175
- "(this is an alias for '--property replication_enabled=<is> True') "
175
+ "(this is an alias for "
176
+ "'--property replication_enabled=<is> True') "
176
177
  "(requires driver support)"
177
178
  ),
178
179
  )
@@ -182,7 +183,8 @@ class CreateVolumeType(command.ShowOne):
182
183
  dest='availability_zones',
183
184
  help=_(
184
185
  "Set an availability zone for this volume type "
185
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
186
+ "(this is an alias for "
187
+ "'--property RESKEY:availability_zones:<az>') "
186
188
  "(repeat option to set multiple availability zones)"
187
189
  ),
188
190
  )
@@ -447,7 +449,8 @@ class ListVolumeType(command.Lister):
447
449
  default=False,
448
450
  help=_(
449
451
  "List only volume types with replication enabled "
450
- "(this is an alias for '--property replication_enabled=<is> True') "
452
+ "(this is an alias for "
453
+ "'--property replication_enabled=<is> True') "
451
454
  "(supported by --os-volume-api-version 3.52 or above)"
452
455
  ),
453
456
  )
@@ -457,7 +460,8 @@ class ListVolumeType(command.Lister):
457
460
  dest='availability_zones',
458
461
  help=_(
459
462
  "List only volume types with this availability configured "
460
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
463
+ "(this is an alias for "
464
+ "'--property RESKEY:availability_zones:<az>') "
461
465
  "(repeat option to filter on multiple availability zones)"
462
466
  ),
463
467
  )
@@ -616,7 +620,8 @@ class SetVolumeType(command.Command):
616
620
  default=False,
617
621
  help=_(
618
622
  "Enabled replication for this volume type "
619
- "(this is an alias for '--property replication_enabled=<is> True') "
623
+ "(this is an alias for "
624
+ "'--property replication_enabled=<is> True') "
620
625
  "(requires driver support)"
621
626
  ),
622
627
  )
@@ -626,7 +631,8 @@ class SetVolumeType(command.Command):
626
631
  dest='availability_zones',
627
632
  help=_(
628
633
  "Set an availability zone for this volume type "
629
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
634
+ "(this is an alias for "
635
+ "'--property RESKEY:availability_zones:<az>') "
630
636
  "(repeat option to set multiple availability zones)"
631
637
  ),
632
638
  )