python-openstackclient 7.4.0__py3-none-any.whl → 8.1.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 (264) hide show
  1. openstackclient/common/availability_zone.py +3 -6
  2. openstackclient/common/clientmanager.py +2 -1
  3. openstackclient/common/envvars.py +57 -0
  4. openstackclient/common/extension.py +3 -11
  5. openstackclient/common/limits.py +1 -1
  6. openstackclient/common/project_cleanup.py +3 -2
  7. openstackclient/common/quota.py +54 -28
  8. openstackclient/compute/client.py +7 -5
  9. openstackclient/compute/v2/agent.py +5 -5
  10. openstackclient/compute/v2/aggregate.py +17 -15
  11. openstackclient/compute/v2/console.py +10 -4
  12. openstackclient/compute/v2/console_connection.py +48 -0
  13. openstackclient/compute/v2/flavor.py +14 -18
  14. openstackclient/compute/v2/host.py +3 -3
  15. openstackclient/compute/v2/hypervisor.py +10 -4
  16. openstackclient/compute/v2/hypervisor_stats.py +1 -1
  17. openstackclient/compute/v2/keypair.py +18 -13
  18. openstackclient/compute/v2/server.py +144 -121
  19. openstackclient/compute/v2/server_backup.py +1 -1
  20. openstackclient/compute/v2/server_event.py +8 -17
  21. openstackclient/compute/v2/server_group.py +6 -6
  22. openstackclient/compute/v2/server_image.py +1 -1
  23. openstackclient/compute/v2/server_migration.py +6 -6
  24. openstackclient/compute/v2/server_volume.py +4 -4
  25. openstackclient/compute/v2/service.py +9 -13
  26. openstackclient/compute/v2/usage.py +4 -6
  27. openstackclient/identity/client.py +2 -4
  28. openstackclient/identity/common.py +95 -17
  29. openstackclient/identity/v2_0/ec2creds.py +4 -3
  30. openstackclient/identity/v2_0/endpoint.py +12 -10
  31. openstackclient/identity/v2_0/project.py +6 -6
  32. openstackclient/identity/v2_0/role.py +1 -1
  33. openstackclient/identity/v2_0/service.py +7 -7
  34. openstackclient/identity/v2_0/user.py +6 -21
  35. openstackclient/identity/v3/access_rule.py +2 -5
  36. openstackclient/identity/v3/application_credential.py +2 -2
  37. openstackclient/identity/v3/consumer.py +4 -3
  38. openstackclient/identity/v3/credential.py +6 -7
  39. openstackclient/identity/v3/domain.py +63 -44
  40. openstackclient/identity/v3/ec2creds.py +4 -3
  41. openstackclient/identity/v3/endpoint.py +104 -88
  42. openstackclient/identity/v3/endpoint_group.py +1 -1
  43. openstackclient/identity/v3/group.py +116 -72
  44. openstackclient/identity/v3/identity_provider.py +1 -2
  45. openstackclient/identity/v3/limit.py +4 -9
  46. openstackclient/identity/v3/mapping.py +4 -3
  47. openstackclient/identity/v3/policy.py +5 -8
  48. openstackclient/identity/v3/project.py +23 -6
  49. openstackclient/identity/v3/region.py +2 -5
  50. openstackclient/identity/v3/registered_limit.py +4 -8
  51. openstackclient/identity/v3/role.py +15 -16
  52. openstackclient/identity/v3/service.py +8 -8
  53. openstackclient/identity/v3/service_provider.py +3 -6
  54. openstackclient/identity/v3/tag.py +2 -2
  55. openstackclient/identity/v3/token.py +1 -2
  56. openstackclient/identity/v3/trust.py +74 -25
  57. openstackclient/identity/v3/user.py +47 -11
  58. openstackclient/image/client.py +7 -5
  59. openstackclient/image/v1/image.py +11 -15
  60. openstackclient/image/v2/cache.py +2 -4
  61. openstackclient/image/v2/image.py +41 -48
  62. openstackclient/image/v2/metadef_namespaces.py +4 -3
  63. openstackclient/image/v2/metadef_resource_type_association.py +1 -2
  64. openstackclient/image/v2/metadef_resource_types.py +1 -2
  65. openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +9 -1370
  66. openstackclient/network/client.py +4 -16
  67. openstackclient/network/common.py +16 -12
  68. openstackclient/network/utils.py +3 -3
  69. openstackclient/network/v2/address_group.py +5 -9
  70. openstackclient/network/v2/address_scope.py +2 -3
  71. openstackclient/network/v2/default_security_group_rule.py +1 -2
  72. openstackclient/network/v2/floating_ip.py +69 -47
  73. openstackclient/network/v2/floating_ip_port_forwarding.py +7 -7
  74. openstackclient/network/v2/ip_availability.py +1 -2
  75. openstackclient/network/v2/l3_conntrack_helper.py +8 -12
  76. openstackclient/network/v2/local_ip.py +24 -26
  77. openstackclient/network/v2/local_ip_association.py +4 -5
  78. openstackclient/network/v2/ndp_proxy.py +9 -10
  79. openstackclient/network/v2/network.py +12 -16
  80. openstackclient/network/v2/network_agent.py +29 -37
  81. openstackclient/network/v2/network_auto_allocated_topology.py +4 -5
  82. openstackclient/network/v2/network_flavor.py +1 -1
  83. openstackclient/network/v2/network_flavor_profile.py +5 -5
  84. openstackclient/network/v2/network_meter.py +3 -3
  85. openstackclient/network/v2/network_meter_rule.py +5 -8
  86. openstackclient/network/v2/network_qos_policy.py +4 -4
  87. openstackclient/network/v2/network_qos_rule.py +7 -16
  88. openstackclient/network/v2/network_rbac.py +4 -4
  89. openstackclient/network/v2/network_segment.py +6 -7
  90. openstackclient/network/v2/network_segment_range.py +16 -20
  91. openstackclient/network/v2/network_trunk.py +24 -16
  92. openstackclient/network/v2/port.py +28 -29
  93. openstackclient/network/v2/router.py +53 -42
  94. openstackclient/network/v2/security_group.py +13 -19
  95. openstackclient/network/v2/security_group_rule.py +10 -11
  96. openstackclient/network/v2/subnet.py +31 -30
  97. openstackclient/network/v2/subnet_pool.py +4 -4
  98. openstackclient/object/client.py +2 -3
  99. openstackclient/object/v1/container.py +2 -3
  100. openstackclient/object/v1/object.py +2 -9
  101. openstackclient/shell.py +22 -5
  102. openstackclient/tests/functional/base.py +7 -3
  103. openstackclient/tests/functional/common/test_quota.py +3 -1
  104. openstackclient/tests/functional/compute/v2/common.py +12 -6
  105. openstackclient/tests/functional/compute/v2/test_keypair.py +41 -5
  106. openstackclient/tests/functional/compute/v2/test_server.py +2 -3
  107. openstackclient/tests/functional/compute/v2/test_server_event.py +1 -1
  108. openstackclient/tests/functional/identity/v2/test_user.py +1 -1
  109. openstackclient/tests/functional/identity/v3/common.py +3 -8
  110. openstackclient/tests/functional/identity/v3/test_application_credential.py +10 -10
  111. openstackclient/tests/functional/identity/v3/test_endpoint.py +3 -3
  112. openstackclient/tests/functional/identity/v3/test_group.py +3 -3
  113. openstackclient/tests/functional/identity/v3/test_idp.py +3 -7
  114. openstackclient/tests/functional/identity/v3/test_limit.py +4 -4
  115. openstackclient/tests/functional/identity/v3/test_project.py +5 -14
  116. openstackclient/tests/functional/identity/v3/test_region.py +1 -3
  117. openstackclient/tests/functional/identity/v3/test_registered_limit.py +3 -3
  118. openstackclient/tests/functional/identity/v3/test_role.py +1 -1
  119. openstackclient/tests/functional/identity/v3/test_role_assignment.py +13 -31
  120. openstackclient/tests/functional/identity/v3/test_service_provider.py +3 -7
  121. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  122. openstackclient/tests/functional/network/v2/common.py +7 -3
  123. openstackclient/tests/functional/network/v2/test_address_group.py +4 -0
  124. openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py +15 -11
  125. openstackclient/tests/functional/network/v2/test_local_ip.py +4 -0
  126. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +2 -2
  127. openstackclient/tests/functional/network/v2/test_network_ndp_proxy.py +2 -3
  128. openstackclient/tests/functional/network/v2/test_network_rbac.py +2 -2
  129. openstackclient/tests/functional/network/v2/test_network_trunk.py +1 -1
  130. openstackclient/tests/functional/network/v2/test_port.py +17 -7
  131. openstackclient/tests/functional/network/v2/test_router.py +42 -0
  132. openstackclient/tests/functional/network/v2/test_subnet_pool.py +4 -0
  133. openstackclient/tests/unit/api/test_compute_v2.py +67 -87
  134. openstackclient/tests/unit/common/test_availability_zone.py +6 -14
  135. openstackclient/tests/unit/common/test_command.py +1 -1
  136. openstackclient/tests/unit/common/test_extension.py +5 -7
  137. openstackclient/tests/unit/common/test_limits.py +1 -1
  138. openstackclient/tests/unit/common/test_project_cleanup.py +5 -6
  139. openstackclient/tests/unit/common/test_quota.py +51 -28
  140. openstackclient/tests/unit/compute/v2/fakes.py +85 -315
  141. openstackclient/tests/unit/compute/v2/test_agent.py +16 -16
  142. openstackclient/tests/unit/compute/v2/test_aggregate.py +56 -60
  143. openstackclient/tests/unit/compute/v2/test_console.py +34 -17
  144. openstackclient/tests/unit/compute/v2/test_console_connection.py +72 -0
  145. openstackclient/tests/unit/compute/v2/test_flavor.py +72 -72
  146. openstackclient/tests/unit/compute/v2/test_host.py +8 -8
  147. openstackclient/tests/unit/compute/v2/test_hypervisor.py +22 -30
  148. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -2
  149. openstackclient/tests/unit/compute/v2/test_keypair.py +36 -29
  150. openstackclient/tests/unit/compute/v2/test_server.py +693 -606
  151. openstackclient/tests/unit/compute/v2/test_server_backup.py +36 -77
  152. openstackclient/tests/unit/compute/v2/test_server_event.py +18 -20
  153. openstackclient/tests/unit/compute/v2/test_server_group.py +25 -31
  154. openstackclient/tests/unit/compute/v2/test_server_image.py +37 -78
  155. openstackclient/tests/unit/compute/v2/test_server_migration.py +41 -41
  156. openstackclient/tests/unit/compute/v2/test_server_volume.py +12 -12
  157. openstackclient/tests/unit/compute/v2/test_service.py +39 -45
  158. openstackclient/tests/unit/compute/v2/test_usage.py +5 -5
  159. openstackclient/tests/unit/identity/v2_0/fakes.py +1 -1
  160. openstackclient/tests/unit/identity/v3/test_access_rule.py +1 -3
  161. openstackclient/tests/unit/identity/v3/test_application_credential.py +48 -26
  162. openstackclient/tests/unit/identity/v3/test_domain.py +115 -105
  163. openstackclient/tests/unit/identity/v3/test_endpoint.py +167 -172
  164. openstackclient/tests/unit/identity/v3/test_group.py +353 -202
  165. openstackclient/tests/unit/identity/v3/test_mappings.py +2 -2
  166. openstackclient/tests/unit/identity/v3/test_project.py +16 -0
  167. openstackclient/tests/unit/identity/v3/test_trust.py +5 -2
  168. openstackclient/tests/unit/identity/v3/test_user.py +102 -6
  169. openstackclient/tests/unit/image/v1/fakes.py +2 -2
  170. openstackclient/tests/unit/image/v1/test_image.py +8 -9
  171. openstackclient/tests/unit/image/v2/test_image.py +84 -46
  172. openstackclient/tests/unit/integ/cli/test_shell.py +1 -2
  173. openstackclient/tests/unit/network/test_common.py +2 -2
  174. openstackclient/tests/unit/network/v2/fakes.py +405 -485
  175. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +8 -14
  176. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +62 -54
  177. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +1 -1
  178. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +2 -2
  179. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +1 -3
  180. openstackclient/tests/unit/network/v2/test_network.py +4 -4
  181. openstackclient/tests/unit/network/v2/test_network_agent.py +15 -29
  182. openstackclient/tests/unit/network/v2/test_network_compute.py +11 -11
  183. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +16 -19
  184. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +79 -152
  185. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +4 -6
  186. openstackclient/tests/unit/network/v2/test_network_rbac.py +2 -2
  187. openstackclient/tests/unit/network/v2/test_network_trunk.py +2 -2
  188. openstackclient/tests/unit/network/v2/test_port.py +21 -22
  189. openstackclient/tests/unit/network/v2/test_router.py +130 -51
  190. openstackclient/tests/unit/network/v2/test_security_group_compute.py +11 -19
  191. openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -27
  192. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +15 -17
  193. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +33 -39
  194. openstackclient/tests/unit/object/v1/test_object_all.py +4 -3
  195. openstackclient/tests/unit/test_shell.py +16 -13
  196. openstackclient/tests/unit/volume/v2/fakes.py +1 -2
  197. openstackclient/tests/unit/volume/v2/test_service.py +57 -91
  198. openstackclient/tests/unit/volume/v2/test_volume.py +109 -106
  199. openstackclient/tests/unit/volume/v2/test_volume_backup.py +141 -148
  200. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +293 -283
  201. openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +1 -1
  202. openstackclient/tests/unit/volume/v3/fakes.py +2 -8
  203. openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +61 -71
  204. openstackclient/tests/unit/volume/v3/test_service.py +221 -141
  205. openstackclient/tests/unit/volume/v3/test_volume.py +131 -120
  206. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +4 -4
  207. openstackclient/tests/unit/volume/v3/test_volume_backup.py +198 -203
  208. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +683 -49
  209. openstackclient/tests/unit/volume/v3/test_volume_transfer_request.py +1 -1
  210. openstackclient/volume/client.py +1 -3
  211. openstackclient/volume/v2/consistency_group.py +4 -8
  212. openstackclient/volume/v2/consistency_group_snapshot.py +1 -2
  213. openstackclient/volume/v2/qos_specs.py +1 -2
  214. openstackclient/volume/v2/service.py +41 -38
  215. openstackclient/volume/v2/volume.py +71 -53
  216. openstackclient/volume/v2/volume_backup.py +15 -10
  217. openstackclient/volume/v2/volume_snapshot.py +129 -93
  218. openstackclient/volume/v2/volume_transfer_request.py +0 -3
  219. openstackclient/volume/v2/volume_type.py +10 -21
  220. openstackclient/volume/v3/block_storage_cluster.py +3 -3
  221. openstackclient/volume/v3/block_storage_log_level.py +22 -28
  222. openstackclient/volume/v3/block_storage_manage.py +1 -3
  223. openstackclient/volume/v3/service.py +105 -14
  224. openstackclient/volume/v3/volume.py +218 -58
  225. openstackclient/volume/v3/volume_attachment.py +3 -2
  226. openstackclient/volume/v3/volume_backup.py +31 -27
  227. openstackclient/volume/v3/volume_group.py +2 -1
  228. openstackclient/volume/v3/volume_group_snapshot.py +2 -1
  229. openstackclient/volume/v3/volume_snapshot.py +489 -13
  230. openstackclient/volume/v3/volume_type.py +10 -21
  231. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/AUTHORS +11 -0
  232. python_openstackclient-8.1.0.dist-info/METADATA +264 -0
  233. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/RECORD +238 -259
  234. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/WHEEL +1 -1
  235. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/entry_points.txt +7 -47
  236. python_openstackclient-8.1.0.dist-info/pbr.json +1 -0
  237. openstackclient/tests/functional/volume/v1/__init__.py +0 -0
  238. openstackclient/tests/functional/volume/v1/common.py +0 -35
  239. openstackclient/tests/functional/volume/v1/test_qos.py +0 -100
  240. openstackclient/tests/functional/volume/v1/test_service.py +0 -76
  241. openstackclient/tests/functional/volume/v1/test_snapshot.py +0 -232
  242. openstackclient/tests/functional/volume/v1/test_transfer_request.py +0 -111
  243. openstackclient/tests/functional/volume/v1/test_volume.py +0 -228
  244. openstackclient/tests/functional/volume/v1/test_volume_type.py +0 -213
  245. openstackclient/tests/unit/volume/v1/__init__.py +0 -0
  246. openstackclient/tests/unit/volume/v1/fakes.py +0 -615
  247. openstackclient/tests/unit/volume/v1/test_qos_specs.py +0 -471
  248. openstackclient/tests/unit/volume/v1/test_service.py +0 -295
  249. openstackclient/tests/unit/volume/v1/test_transfer_request.py +0 -380
  250. openstackclient/tests/unit/volume/v1/test_type.py +0 -633
  251. openstackclient/tests/unit/volume/v1/test_volume.py +0 -1447
  252. openstackclient/tests/unit/volume/v1/test_volume_backup.py +0 -435
  253. openstackclient/volume/v1/__init__.py +0 -0
  254. openstackclient/volume/v1/qos_specs.py +0 -377
  255. openstackclient/volume/v1/service.py +0 -136
  256. openstackclient/volume/v1/volume.py +0 -734
  257. openstackclient/volume/v1/volume_backup.py +0 -302
  258. openstackclient/volume/v1/volume_snapshot.py +0 -433
  259. openstackclient/volume/v1/volume_transfer_request.py +0 -200
  260. openstackclient/volume/v1/volume_type.py +0 -520
  261. python_openstackclient-7.4.0.dist-info/METADATA +0 -172
  262. python_openstackclient-7.4.0.dist-info/pbr.json +0 -1
  263. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/LICENSE +0 -0
  264. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/top_level.txt +0 -0
@@ -31,7 +31,6 @@ from osc_lib import utils
31
31
  from openstackclient.common import pagination
32
32
  from openstackclient.i18n import _
33
33
  from openstackclient.identity import common as identity_common
34
- from openstackclient.volume.v2 import volume as volume_v2
35
34
 
36
35
 
37
36
  LOG = logging.getLogger(__name__)
@@ -91,7 +90,7 @@ class AttachmentsColumn(cliff_columns.FormattableColumn):
91
90
  return msg
92
91
 
93
92
 
94
- class CreateVolume(volume_v2.CreateVolume):
93
+ class CreateVolume(command.ShowOne):
95
94
  _description = _("Create new volume")
96
95
 
97
96
  @staticmethod
@@ -117,8 +116,48 @@ class CreateVolume(volume_v2.CreateVolume):
117
116
  raise exceptions.CommandError(msg)
118
117
 
119
118
  def get_parser(self, prog_name):
120
- parser, source_group = self._get_parser(prog_name)
121
-
119
+ parser = super().get_parser(prog_name)
120
+ parser.add_argument(
121
+ "name",
122
+ metavar="<name>",
123
+ nargs="?",
124
+ help=_("Volume name"),
125
+ )
126
+ parser.add_argument(
127
+ "--size",
128
+ metavar="<size>",
129
+ type=int,
130
+ help=_(
131
+ "Volume size in GB (required unless --snapshot or "
132
+ "--source specified)"
133
+ ),
134
+ )
135
+ parser.add_argument(
136
+ "--type",
137
+ metavar="<volume-type>",
138
+ help=_("Set the type of volume"),
139
+ )
140
+ source_group = parser.add_mutually_exclusive_group()
141
+ source_group.add_argument(
142
+ "--image",
143
+ metavar="<image>",
144
+ help=_("Use <image> as source of volume (name or ID)"),
145
+ )
146
+ source_group.add_argument(
147
+ "--snapshot",
148
+ metavar="<snapshot>",
149
+ help=_("Use <snapshot> as source of volume (name or ID)"),
150
+ )
151
+ source_group.add_argument(
152
+ "--source",
153
+ metavar="<volume>",
154
+ help=_("Volume to clone (name or ID)"),
155
+ )
156
+ source_group.add_argument(
157
+ "--source-replicated",
158
+ metavar="<replicated-volume>",
159
+ help=argparse.SUPPRESS,
160
+ )
122
161
  source_group.add_argument(
123
162
  "--backup",
124
163
  metavar="<backup>",
@@ -138,6 +177,72 @@ class CreateVolume(volume_v2.CreateVolume):
138
177
  "--remote-source source-id=test_id')"
139
178
  ),
140
179
  )
180
+ parser.add_argument(
181
+ "--description",
182
+ metavar="<description>",
183
+ help=_("Volume description"),
184
+ )
185
+ parser.add_argument(
186
+ "--availability-zone",
187
+ metavar="<availability-zone>",
188
+ help=_("Create volume in <availability-zone>"),
189
+ )
190
+ parser.add_argument(
191
+ "--consistency-group",
192
+ metavar="consistency-group>",
193
+ help=_("Consistency group where the new volume belongs to"),
194
+ )
195
+ parser.add_argument(
196
+ "--property",
197
+ metavar="<key=value>",
198
+ action=parseractions.KeyValueAction,
199
+ dest="properties",
200
+ help=_(
201
+ "Set a property to this volume "
202
+ "(repeat option to set multiple properties)"
203
+ ),
204
+ )
205
+ parser.add_argument(
206
+ "--hint",
207
+ metavar="<key=value>",
208
+ action=KeyValueHintAction,
209
+ help=_(
210
+ "Arbitrary scheduler hint key-value pairs to help creating "
211
+ "a volume. Repeat the option to set multiple hints. "
212
+ "'same_host' and 'different_host' get values appended when "
213
+ "repeated, all other keys take the last given value"
214
+ ),
215
+ )
216
+ bootable_group = parser.add_mutually_exclusive_group()
217
+ bootable_group.add_argument(
218
+ "--bootable",
219
+ action="store_true",
220
+ dest="bootable",
221
+ default=None,
222
+ help=_("Mark volume as bootable"),
223
+ )
224
+ bootable_group.add_argument(
225
+ "--non-bootable",
226
+ action="store_false",
227
+ dest="bootable",
228
+ default=None,
229
+ help=_("Mark volume as non-bootable (default)"),
230
+ )
231
+ readonly_group = parser.add_mutually_exclusive_group()
232
+ readonly_group.add_argument(
233
+ "--read-only",
234
+ action="store_true",
235
+ dest="read_only",
236
+ default=None,
237
+ help=_("Set volume to read-only access mode"),
238
+ )
239
+ readonly_group.add_argument(
240
+ "--read-write",
241
+ action="store_false",
242
+ dest="read_only",
243
+ default=None,
244
+ help=_("Set volume to read-write access mode (default)"),
245
+ )
141
246
  parser.add_argument(
142
247
  "--host",
143
248
  metavar="<host>",
@@ -160,7 +265,7 @@ class CreateVolume(volume_v2.CreateVolume):
160
265
  return parser
161
266
 
162
267
  def take_action(self, parsed_args):
163
- CreateVolume._check_size_arg(parsed_args)
268
+ self._check_size_arg(parsed_args)
164
269
  # size is validated in the above call to
165
270
  # _check_size_arg where we check that size
166
271
  # should be passed if we are not creating a
@@ -194,8 +299,7 @@ class CreateVolume(volume_v2.CreateVolume):
194
299
  parsed_args.size
195
300
  or parsed_args.consistency_group
196
301
  or parsed_args.hint
197
- or parsed_args.read_only
198
- or parsed_args.read_write
302
+ or parsed_args.read_only is not None
199
303
  ):
200
304
  msg = _(
201
305
  "The --size, --consistency-group, --hint, --read-only "
@@ -232,10 +336,24 @@ class CreateVolume(volume_v2.CreateVolume):
232
336
  description=parsed_args.description,
233
337
  volume_type=parsed_args.type,
234
338
  availability_zone=parsed_args.availability_zone,
235
- metadata=parsed_args.property,
339
+ metadata=parsed_args.properties,
236
340
  bootable=parsed_args.bootable,
237
341
  )
238
- return zip(*sorted(volume.items()))
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
356
+ return zip(*sorted(data.items()))
239
357
 
240
358
  source_volume = None
241
359
  if parsed_args.source:
@@ -287,7 +405,7 @@ class CreateVolume(volume_v2.CreateVolume):
287
405
  description=parsed_args.description,
288
406
  volume_type=parsed_args.type,
289
407
  availability_zone=parsed_args.availability_zone,
290
- metadata=parsed_args.property,
408
+ metadata=parsed_args.properties,
291
409
  imageRef=image,
292
410
  source_volid=source_volume,
293
411
  consistencygroup_id=consistency_group,
@@ -295,7 +413,7 @@ class CreateVolume(volume_v2.CreateVolume):
295
413
  backup_id=backup,
296
414
  )
297
415
 
298
- if parsed_args.bootable or parsed_args.non_bootable:
416
+ if parsed_args.bootable is not None:
299
417
  try:
300
418
  if utils.wait_for_status(
301
419
  volume_client.volumes.get,
@@ -309,13 +427,13 @@ class CreateVolume(volume_v2.CreateVolume):
309
427
  )
310
428
  else:
311
429
  msg = _(
312
- "Volume status is not available for setting boot "
313
- "state"
430
+ "Volume status is not available for setting boot state"
314
431
  )
315
432
  raise exceptions.CommandError(msg)
316
433
  except Exception as e:
317
434
  LOG.error(_("Failed to set volume bootable property: %s"), e)
318
- if parsed_args.read_only or parsed_args.read_write:
435
+
436
+ if parsed_args.read_only is not None:
319
437
  try:
320
438
  if utils.wait_for_status(
321
439
  volume_client.volumes.get,
@@ -335,10 +453,7 @@ class CreateVolume(volume_v2.CreateVolume):
335
453
  raise exceptions.CommandError(msg)
336
454
  except Exception as e:
337
455
  LOG.error(
338
- _(
339
- "Failed to set volume read-only access "
340
- "mode flag: %s"
341
- ),
456
+ _("Failed to set volume read-only access mode flag: %s"),
342
457
  e,
343
458
  )
344
459
 
@@ -355,11 +470,33 @@ class CreateVolume(volume_v2.CreateVolume):
355
470
  return zip(*sorted(volume._info.items()))
356
471
 
357
472
 
358
- class DeleteVolume(volume_v2.DeleteVolume):
473
+ class DeleteVolume(command.Command):
359
474
  _description = _("Delete volume(s)")
360
475
 
361
476
  def get_parser(self, prog_name):
362
477
  parser = super().get_parser(prog_name)
478
+ parser.add_argument(
479
+ "volumes",
480
+ metavar="<volume>",
481
+ nargs="+",
482
+ help=_("Volume(s) to delete (name or ID)"),
483
+ )
484
+ group = parser.add_mutually_exclusive_group()
485
+ group.add_argument(
486
+ "--force",
487
+ action="store_true",
488
+ help=_(
489
+ "Attempt forced removal of volume(s), regardless of state "
490
+ "(defaults to False)"
491
+ ),
492
+ )
493
+ group.add_argument(
494
+ "--purge",
495
+ action="store_true",
496
+ help=_(
497
+ "Remove any snapshots along with volume(s) (defaults to False)"
498
+ ),
499
+ )
363
500
  parser.add_argument(
364
501
  '--remote',
365
502
  action='store_true',
@@ -368,8 +505,7 @@ class DeleteVolume(volume_v2.DeleteVolume):
368
505
  return parser
369
506
 
370
507
  def take_action(self, parsed_args):
371
- volume_client = self.app.client_manager.volume
372
- volume_client_sdk = self.app.client_manager.sdk_connection.volume
508
+ volume_client = self.app.client_manager.sdk_connection.volume
373
509
  result = 0
374
510
 
375
511
  if parsed_args.remote and (parsed_args.force or parsed_args.purge):
@@ -379,16 +515,18 @@ class DeleteVolume(volume_v2.DeleteVolume):
379
515
  )
380
516
  raise exceptions.CommandError(msg)
381
517
 
382
- for i in parsed_args.volumes:
518
+ for volume in parsed_args.volumes:
383
519
  try:
384
- volume_obj = utils.find_resource(volume_client.volumes, i)
520
+ volume_obj = volume_client.find_volume(
521
+ volume, ignore_missing=False
522
+ )
385
523
  if parsed_args.remote:
386
- volume_client_sdk.unmanage_volume(volume_obj.id)
387
- elif parsed_args.force:
388
- volume_client.volumes.force_delete(volume_obj.id)
524
+ volume_client.unmanage_volume(volume_obj.id)
389
525
  else:
390
- volume_client.volumes.delete(
391
- volume_obj.id, cascade=parsed_args.purge
526
+ volume_client.delete_volume(
527
+ volume_obj.id,
528
+ force=parsed_args.force,
529
+ cascade=parsed_args.purge,
392
530
  )
393
531
  except Exception as e:
394
532
  result += 1
@@ -397,12 +535,12 @@ class DeleteVolume(volume_v2.DeleteVolume):
397
535
  "Failed to delete volume with "
398
536
  "name or ID '%(volume)s': %(e)s"
399
537
  ),
400
- {'volume': i, 'e': e},
538
+ {'volume': volume, 'e': e},
401
539
  )
402
540
 
403
541
  if result > 0:
404
542
  total = len(parsed_args.volumes)
405
- msg = _("%(result)s of %(total)s volumes failed " "to delete.") % {
543
+ msg = _("%(result)s of %(total)s volumes failed to delete.") % {
406
544
  'result': result,
407
545
  'total': total,
408
546
  }
@@ -523,7 +661,7 @@ class ListVolume(command.Lister):
523
661
  server_cache = {}
524
662
  if do_server_list:
525
663
  try:
526
- compute_client = self.app.client_manager.sdk_connection.compute
664
+ compute_client = self.app.client_manager.compute
527
665
  for s in compute_client.servers():
528
666
  server_cache[s.id] = s
529
667
  except sdk_exceptions.SDKException: # noqa: S110
@@ -642,6 +780,7 @@ class SetVolume(command.Command):
642
780
  '--property',
643
781
  metavar='<key=value>',
644
782
  action=parseractions.KeyValueAction,
783
+ dest='properties',
645
784
  help=_(
646
785
  'Set a property on this volume '
647
786
  '(repeat option to set multiple properties)'
@@ -651,6 +790,7 @@ class SetVolume(command.Command):
651
790
  '--image-property',
652
791
  metavar='<key=value>',
653
792
  action=parseractions.KeyValueAction,
793
+ dest='image_properties',
654
794
  help=_(
655
795
  'Set an image property on this volume '
656
796
  '(repeat option to set multiple image properties)'
@@ -727,22 +867,30 @@ class SetVolume(command.Command):
727
867
  bootable_group.add_argument(
728
868
  "--bootable",
729
869
  action="store_true",
870
+ dest="bootable",
871
+ default=None,
730
872
  help=_("Mark volume as bootable"),
731
873
  )
732
874
  bootable_group.add_argument(
733
875
  "--non-bootable",
734
- action="store_true",
876
+ action="store_false",
877
+ dest="bootable",
878
+ default=None,
735
879
  help=_("Mark volume as non-bootable"),
736
880
  )
737
881
  readonly_group = parser.add_mutually_exclusive_group()
738
882
  readonly_group.add_argument(
739
883
  "--read-only",
740
884
  action="store_true",
885
+ dest="read_only",
886
+ default=None,
741
887
  help=_("Set volume to read-only access mode"),
742
888
  )
743
889
  readonly_group.add_argument(
744
890
  "--read-write",
745
- action="store_true",
891
+ action="store_false",
892
+ dest="read_only",
893
+ default=None,
746
894
  help=_("Set volume to read-write access mode"),
747
895
  )
748
896
  return parser
@@ -768,18 +916,24 @@ class SetVolume(command.Command):
768
916
  _("New size must be greater than %s GB") % volume.size
769
917
  )
770
918
  raise exceptions.CommandError(msg)
771
- if (
772
- volume.status != 'available'
773
- and not volume_client.api_version.matches('3.42')
774
- ):
919
+ if volume.status not in ('available', 'in-use'):
775
920
  msg = (
776
921
  _(
777
922
  "Volume is in %s state, it must be available "
778
- "before size can be extended"
923
+ "or in-use before size can be extended."
779
924
  )
780
925
  % volume.status
781
926
  )
782
927
  raise exceptions.CommandError(msg)
928
+ if (
929
+ volume.status == 'in-use'
930
+ and not volume_client.api_version.matches('3.42')
931
+ ):
932
+ msg = _(
933
+ "--os-volume-api-version 3.42 or greater is "
934
+ "required to extend in-use volumes."
935
+ )
936
+ raise exceptions.CommandError(msg)
783
937
  volume_client.volumes.extend(volume.id, parsed_args.size)
784
938
  except Exception as e:
785
939
  LOG.error(_("Failed to set volume size: %s"), e)
@@ -794,28 +948,31 @@ class SetVolume(command.Command):
794
948
  LOG.error(_("Failed to clean volume properties: %s"), e)
795
949
  result += 1
796
950
 
797
- if parsed_args.property:
951
+ if parsed_args.properties:
798
952
  try:
799
953
  volume_client.volumes.set_metadata(
800
- volume.id, parsed_args.property
954
+ volume.id, parsed_args.properties
801
955
  )
802
956
  except Exception as e:
803
- LOG.error(_("Failed to set volume property: %s"), e)
957
+ LOG.error(_("Failed to set volume properties: %s"), e)
804
958
  result += 1
805
- if parsed_args.image_property:
959
+
960
+ if parsed_args.image_properties:
806
961
  try:
807
962
  volume_client.volumes.set_image_metadata(
808
- volume.id, parsed_args.image_property
963
+ volume.id, parsed_args.image_properties
809
964
  )
810
965
  except Exception as e:
811
- LOG.error(_("Failed to set image property: %s"), e)
966
+ LOG.error(_("Failed to set image properties: %s"), e)
812
967
  result += 1
968
+
813
969
  if parsed_args.state:
814
970
  try:
815
971
  volume_client.volumes.reset_state(volume.id, parsed_args.state)
816
972
  except Exception as e:
817
973
  LOG.error(_("Failed to set volume state: %s"), e)
818
974
  result += 1
975
+
819
976
  if parsed_args.attached:
820
977
  try:
821
978
  volume_client.volumes.reset_state(
@@ -824,6 +981,7 @@ class SetVolume(command.Command):
824
981
  except Exception as e:
825
982
  LOG.error(_("Failed to set volume attach-status: %s"), e)
826
983
  result += 1
984
+
827
985
  if parsed_args.detached:
828
986
  try:
829
987
  volume_client.volumes.reset_state(
@@ -832,7 +990,8 @@ class SetVolume(command.Command):
832
990
  except Exception as e:
833
991
  LOG.error(_("Failed to set volume attach-status: %s"), e)
834
992
  result += 1
835
- if parsed_args.bootable or parsed_args.non_bootable:
993
+
994
+ if parsed_args.bootable is not None:
836
995
  try:
837
996
  volume_client.volumes.set_bootable(
838
997
  volume.id, parsed_args.bootable
@@ -840,20 +999,19 @@ class SetVolume(command.Command):
840
999
  except Exception as e:
841
1000
  LOG.error(_("Failed to set volume bootable property: %s"), e)
842
1001
  result += 1
843
- if parsed_args.read_only or parsed_args.read_write:
1002
+
1003
+ if parsed_args.read_only is not None:
844
1004
  try:
845
1005
  volume_client.volumes.update_readonly_flag(
846
1006
  volume.id, parsed_args.read_only
847
1007
  )
848
1008
  except Exception as e:
849
1009
  LOG.error(
850
- _(
851
- "Failed to set volume read-only access "
852
- "mode flag: %s"
853
- ),
1010
+ _("Failed to set volume read-only access mode flag: %s"),
854
1011
  e,
855
1012
  )
856
1013
  result += 1
1014
+
857
1015
  policy = parsed_args.migration_policy or parsed_args.retype_policy
858
1016
  if parsed_args.type:
859
1017
  # get the migration policy
@@ -903,7 +1061,7 @@ class SetVolume(command.Command):
903
1061
 
904
1062
  if result > 0:
905
1063
  raise exceptions.CommandError(
906
- _("One or more of the " "set operations failed")
1064
+ _("One or more of the set operations failed")
907
1065
  )
908
1066
 
909
1067
 
@@ -954,6 +1112,7 @@ class UnsetVolume(command.Command):
954
1112
  '--property',
955
1113
  metavar='<key>',
956
1114
  action='append',
1115
+ dest='properties',
957
1116
  help=_(
958
1117
  'Remove a property from volume '
959
1118
  '(repeat option to remove multiple properties)'
@@ -963,6 +1122,7 @@ class UnsetVolume(command.Command):
963
1122
  '--image-property',
964
1123
  metavar='<key>',
965
1124
  action='append',
1125
+ dest='image_properties',
966
1126
  help=_(
967
1127
  'Remove an image property from volume '
968
1128
  '(repeat option to remove multiple image properties)'
@@ -975,27 +1135,27 @@ class UnsetVolume(command.Command):
975
1135
  volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
976
1136
 
977
1137
  result = 0
978
- if parsed_args.property:
1138
+ if parsed_args.properties:
979
1139
  try:
980
1140
  volume_client.volumes.delete_metadata(
981
- volume.id, parsed_args.property
1141
+ volume.id, parsed_args.properties
982
1142
  )
983
1143
  except Exception as e:
984
- LOG.error(_("Failed to unset volume property: %s"), e)
1144
+ LOG.error(_("Failed to unset volume properties: %s"), e)
985
1145
  result += 1
986
1146
 
987
- if parsed_args.image_property:
1147
+ if parsed_args.image_properties:
988
1148
  try:
989
1149
  volume_client.volumes.delete_image_metadata(
990
- volume.id, parsed_args.image_property
1150
+ volume.id, parsed_args.image_properties
991
1151
  )
992
1152
  except Exception as e:
993
- LOG.error(_("Failed to unset image property: %s"), e)
1153
+ LOG.error(_("Failed to unset image properties: %s"), e)
994
1154
  result += 1
995
1155
 
996
1156
  if result > 0:
997
1157
  raise exceptions.CommandError(
998
- _("One or more of the " "unset operations failed")
1158
+ _("One or more of the unset operations failed")
999
1159
  )
1000
1160
 
1001
1161
 
@@ -18,6 +18,7 @@ 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.common import envvars
21
22
  from openstackclient.common import pagination
22
23
  from openstackclient.i18n import _
23
24
  from openstackclient.identity import common as identity_common
@@ -171,7 +172,7 @@ class CreateVolumeAttachment(command.ShowOne):
171
172
 
172
173
  def take_action(self, parsed_args):
173
174
  volume_client = self.app.client_manager.sdk_connection.volume
174
- compute_client = self.app.client_manager.sdk_connection.compute
175
+ compute_client = self.app.client_manager.compute
175
176
 
176
177
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
177
178
  msg = _(
@@ -399,7 +400,7 @@ class ListVolumeAttachment(command.Lister):
399
400
  '--all-projects',
400
401
  dest='all_projects',
401
402
  action='store_true',
402
- default=utils.env('ALL_PROJECTS', default=False),
403
+ default=envvars.boolenv('ALL_PROJECTS'),
403
404
  help=_('Shows details for all projects (admin only).'),
404
405
  )
405
406
  parser.add_argument(