python-openstackclient 8.3.0__py3-none-any.whl → 10.0.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 (292) hide show
  1. openstackclient/__init__.py +2 -6
  2. openstackclient/api/api.py +41 -23
  3. openstackclient/api/compute_v2.py +44 -25
  4. openstackclient/api/object_store_v1.py +75 -97
  5. openstackclient/api/volume_v2.py +2 -1
  6. openstackclient/api/volume_v3.py +2 -1
  7. openstackclient/common/availability_zone.py +58 -42
  8. openstackclient/common/clientmanager.py +56 -29
  9. openstackclient/common/configuration.py +10 -3
  10. openstackclient/common/envvars.py +2 -2
  11. openstackclient/common/extension.py +14 -5
  12. openstackclient/common/limits.py +10 -5
  13. openstackclient/common/module.py +14 -6
  14. openstackclient/common/pagination.py +8 -2
  15. openstackclient/common/progressbar.py +7 -6
  16. openstackclient/common/project_cleanup.py +13 -7
  17. openstackclient/common/quota.py +126 -114
  18. openstackclient/common/versions.py +8 -2
  19. openstackclient/compute/client.py +7 -3
  20. openstackclient/compute/v2/agent.py +17 -10
  21. openstackclient/compute/v2/aggregate.py +36 -22
  22. openstackclient/compute/v2/console.py +14 -8
  23. openstackclient/compute/v2/console_connection.py +11 -3
  24. openstackclient/compute/v2/flavor.py +39 -21
  25. openstackclient/compute/v2/host.py +14 -6
  26. openstackclient/compute/v2/hypervisor.py +14 -5
  27. openstackclient/compute/v2/hypervisor_stats.py +10 -2
  28. openstackclient/compute/v2/keypair.py +29 -14
  29. openstackclient/compute/v2/server.py +251 -171
  30. openstackclient/compute/v2/server_backup.py +10 -4
  31. openstackclient/compute/v2/server_event.py +21 -12
  32. openstackclient/compute/v2/server_group.py +21 -11
  33. openstackclient/compute/v2/server_image.py +19 -10
  34. openstackclient/compute/v2/server_migration.py +24 -10
  35. openstackclient/compute/v2/server_share.py +274 -0
  36. openstackclient/compute/v2/server_volume.py +10 -4
  37. openstackclient/compute/v2/service.py +14 -7
  38. openstackclient/compute/v2/usage.py +26 -21
  39. openstackclient/identity/client.py +8 -3
  40. openstackclient/identity/common.py +103 -41
  41. openstackclient/identity/v2_0/catalog.py +14 -7
  42. openstackclient/identity/v2_0/ec2creds.py +21 -10
  43. openstackclient/identity/v2_0/endpoint.py +23 -11
  44. openstackclient/identity/v2_0/project.py +25 -14
  45. openstackclient/identity/v2_0/role.py +28 -14
  46. openstackclient/identity/v2_0/role_assignment.py +9 -3
  47. openstackclient/identity/v2_0/service.py +26 -12
  48. openstackclient/identity/v2_0/token.py +12 -5
  49. openstackclient/identity/v2_0/user.py +26 -15
  50. openstackclient/identity/v3/access_rule.py +26 -12
  51. openstackclient/identity/v3/application_credential.py +59 -24
  52. openstackclient/identity/v3/catalog.py +14 -7
  53. openstackclient/identity/v3/consumer.py +22 -11
  54. openstackclient/identity/v3/credential.py +36 -16
  55. openstackclient/identity/v3/domain.py +37 -18
  56. openstackclient/identity/v3/ec2creds.py +25 -12
  57. openstackclient/identity/v3/endpoint.py +42 -20
  58. openstackclient/identity/v3/endpoint_group.py +28 -17
  59. openstackclient/identity/v3/federation_protocol.py +71 -50
  60. openstackclient/identity/v3/group.py +55 -32
  61. openstackclient/identity/v3/identity_provider.py +92 -57
  62. openstackclient/identity/v3/implied_role.py +21 -9
  63. openstackclient/identity/v3/limit.py +115 -92
  64. openstackclient/identity/v3/mapping.py +26 -13
  65. openstackclient/identity/v3/policy.py +23 -12
  66. openstackclient/identity/v3/project.py +211 -122
  67. openstackclient/identity/v3/region.py +36 -16
  68. openstackclient/identity/v3/registered_limit.py +116 -109
  69. openstackclient/identity/v3/role.py +61 -31
  70. openstackclient/identity/v3/role_assignment.py +23 -6
  71. openstackclient/identity/v3/service.py +36 -16
  72. openstackclient/identity/v3/service_provider.py +37 -15
  73. openstackclient/identity/v3/tag.py +23 -17
  74. openstackclient/identity/v3/token.py +30 -14
  75. openstackclient/identity/v3/trust.py +32 -14
  76. openstackclient/identity/v3/unscoped_saml.py +10 -2
  77. openstackclient/identity/v3/user.py +49 -26
  78. openstackclient/image/client.py +7 -3
  79. openstackclient/image/v1/image.py +33 -26
  80. openstackclient/image/v2/cache.py +14 -9
  81. openstackclient/image/v2/image.py +76 -49
  82. openstackclient/image/v2/info.py +7 -1
  83. openstackclient/image/v2/metadef_namespaces.py +109 -13
  84. openstackclient/image/v2/metadef_objects.py +28 -15
  85. openstackclient/image/v2/metadef_properties.py +24 -13
  86. openstackclient/image/v2/metadef_resource_type_association.py +14 -7
  87. openstackclient/image/v2/metadef_resource_types.py +7 -1
  88. openstackclient/image/v2/task.py +15 -6
  89. openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +7 -192
  90. openstackclient/network/client.py +7 -2
  91. openstackclient/network/common.py +16 -241
  92. openstackclient/network/utils.py +36 -22
  93. openstackclient/network/v2/address_group.py +27 -16
  94. openstackclient/network/v2/address_scope.py +24 -13
  95. openstackclient/network/v2/bgpvpn/bgpvpn.py +463 -0
  96. openstackclient/network/v2/bgpvpn/constants.py +30 -0
  97. openstackclient/network/v2/bgpvpn/network_association.py +214 -0
  98. openstackclient/network/v2/bgpvpn/port_association.py +490 -0
  99. openstackclient/network/v2/bgpvpn/router_association.py +288 -0
  100. openstackclient/network/v2/default_security_group_rule.py +19 -10
  101. openstackclient/network/v2/floating_ip.py +110 -159
  102. openstackclient/network/v2/floating_ip_port_forwarding.py +30 -18
  103. openstackclient/network/v2/fwaas/__init__.py +0 -0
  104. openstackclient/network/v2/fwaas/group.py +466 -0
  105. openstackclient/network/v2/fwaas/policy.py +518 -0
  106. openstackclient/network/v2/fwaas/rule.py +574 -0
  107. openstackclient/network/v2/ip_availability.py +13 -5
  108. openstackclient/network/v2/l3_conntrack_helper.py +22 -13
  109. openstackclient/network/v2/local_ip.py +24 -13
  110. openstackclient/network/v2/local_ip_association.py +14 -7
  111. openstackclient/network/v2/ndp_proxy.py +20 -11
  112. openstackclient/network/v2/network.py +129 -196
  113. openstackclient/network/v2/network_agent.py +46 -25
  114. openstackclient/network/v2/network_auto_allocated_topology.py +22 -11
  115. openstackclient/network/v2/network_flavor.py +27 -16
  116. openstackclient/network/v2/network_flavor_profile.py +23 -12
  117. openstackclient/network/v2/network_meter.py +21 -10
  118. openstackclient/network/v2/network_meter_rule.py +21 -11
  119. openstackclient/network/v2/network_qos_policy.py +25 -15
  120. openstackclient/network/v2/network_qos_rule.py +32 -17
  121. openstackclient/network/v2/network_qos_rule_type.py +13 -5
  122. openstackclient/network/v2/network_rbac.py +23 -12
  123. openstackclient/network/v2/network_segment.py +20 -11
  124. openstackclient/network/v2/network_segment_range.py +56 -29
  125. openstackclient/network/v2/network_service_provider.py +7 -1
  126. openstackclient/network/v2/network_trunk.py +38 -22
  127. openstackclient/network/v2/port.py +54 -29
  128. openstackclient/network/v2/router.py +75 -52
  129. openstackclient/network/v2/security_group.py +87 -157
  130. openstackclient/network/v2/security_group_rule.py +100 -280
  131. openstackclient/network/v2/subnet.py +49 -28
  132. openstackclient/network/v2/subnet_pool.py +30 -17
  133. openstackclient/network/v2/taas/tap_flow.py +22 -11
  134. openstackclient/network/v2/taas/tap_mirror.py +22 -11
  135. openstackclient/network/v2/taas/tap_service.py +23 -12
  136. openstackclient/object/client.py +7 -2
  137. openstackclient/object/v1/account.py +13 -6
  138. openstackclient/object/v1/container.py +25 -15
  139. openstackclient/object/v1/object.py +25 -15
  140. openstackclient/py.typed +0 -0
  141. openstackclient/shell.py +46 -10
  142. openstackclient/tests/functional/base.py +55 -20
  143. openstackclient/tests/functional/common/test_extension.py +4 -0
  144. openstackclient/tests/functional/common/test_quota.py +3 -1
  145. openstackclient/tests/functional/compute/v2/common.py +14 -13
  146. openstackclient/tests/functional/compute/v2/test_flavor.py +3 -1
  147. openstackclient/tests/functional/compute/v2/test_server.py +3 -0
  148. openstackclient/tests/functional/identity/v2/common.py +10 -6
  149. openstackclient/tests/functional/identity/v2/test_role.py +4 -4
  150. openstackclient/tests/functional/identity/v3/common.py +25 -19
  151. openstackclient/tests/functional/identity/v3/test_group.py +20 -20
  152. openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
  153. openstackclient/tests/functional/identity/v3/test_limit.py +47 -0
  154. openstackclient/tests/functional/identity/v3/test_project.py +10 -10
  155. openstackclient/tests/functional/identity/v3/test_role.py +18 -18
  156. openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
  157. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  158. openstackclient/tests/functional/image/base.py +1 -6
  159. openstackclient/tests/functional/image/v2/test_metadef_objects.py +69 -0
  160. openstackclient/tests/functional/network/v2/common.py +5 -2
  161. openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
  162. openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
  163. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
  164. openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
  165. openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
  166. openstackclient/tests/functional/object/v1/common.py +4 -0
  167. openstackclient/tests/functional/volume/v2/common.py +4 -0
  168. openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
  169. openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
  170. openstackclient/tests/functional/volume/v3/common.py +4 -0
  171. openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +56 -138
  172. openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
  173. openstackclient/tests/unit/common/test_availability_zone.py +35 -49
  174. openstackclient/tests/unit/common/test_extension.py +2 -2
  175. openstackclient/tests/unit/common/test_module.py +12 -7
  176. openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
  177. openstackclient/tests/unit/common/test_quota.py +62 -23
  178. openstackclient/tests/unit/compute/v2/fakes.py +25 -0
  179. openstackclient/tests/unit/compute/v2/test_flavor.py +28 -2
  180. openstackclient/tests/unit/compute/v2/test_keypair.py +6 -6
  181. openstackclient/tests/unit/compute/v2/test_server.py +17 -104
  182. openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
  183. openstackclient/tests/unit/identity/v3/fakes.py +3 -0
  184. openstackclient/tests/unit/identity/v3/test_group.py +4 -14
  185. openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
  186. openstackclient/tests/unit/identity/v3/test_limit.py +197 -145
  187. openstackclient/tests/unit/identity/v3/test_project.py +831 -512
  188. openstackclient/tests/unit/identity/v3/test_protocol.py +97 -88
  189. openstackclient/tests/unit/identity/v3/test_registered_limit.py +355 -220
  190. openstackclient/tests/unit/identity/v3/test_user.py +4 -4
  191. openstackclient/tests/unit/image/v2/test_image.py +16 -16
  192. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
  193. openstackclient/tests/unit/network/test_common.py +0 -155
  194. openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
  195. openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
  196. openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
  197. openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
  198. openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
  199. openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
  200. openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
  201. openstackclient/tests/unit/network/v2/fwaas/test_group.py +897 -0
  202. openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
  203. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +980 -0
  204. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
  205. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
  206. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
  207. openstackclient/tests/unit/network/v2/test_address_group.py +2 -2
  208. openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +3 -2
  209. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +13 -13
  210. openstackclient/tests/unit/network/v2/test_network_agent.py +8 -4
  211. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
  212. openstackclient/tests/unit/network/v2/test_network_flavor.py +2 -2
  213. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +1 -1
  214. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
  215. openstackclient/tests/unit/network/v2/test_network_rbac.py +1 -1
  216. openstackclient/tests/unit/network/v2/test_network_segment.py +1 -1
  217. openstackclient/tests/unit/network/v2/test_network_segment_range.py +7 -10
  218. openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
  219. openstackclient/tests/unit/network/v2/test_router.py +8 -9
  220. openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +1 -20
  221. openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +7 -41
  222. openstackclient/tests/unit/network/v2/test_subnet.py +2 -1
  223. openstackclient/tests/unit/network/v2/test_subnet_pool.py +2 -1
  224. openstackclient/tests/unit/object/v1/fakes.py +8 -7
  225. openstackclient/tests/unit/object/v1/test_container.py +65 -101
  226. openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
  227. openstackclient/tests/unit/object/v1/test_object.py +44 -84
  228. openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
  229. openstackclient/tests/unit/test_hacking.py +108 -0
  230. openstackclient/tests/unit/volume/v2/fakes.py +1 -0
  231. openstackclient/tests/unit/volume/v2/test_consistency_group.py +8 -2
  232. openstackclient/tests/unit/volume/v2/test_volume.py +7 -6
  233. openstackclient/tests/unit/volume/v2/test_volume_backup.py +1 -5
  234. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +2 -1
  235. openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
  236. openstackclient/tests/unit/volume/v3/fakes.py +1 -0
  237. openstackclient/tests/unit/volume/v3/test_volume.py +94 -15
  238. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
  239. openstackclient/tests/unit/volume/v3/test_volume_backup.py +1 -5
  240. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +55 -1
  241. openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
  242. openstackclient/volume/client.py +7 -3
  243. openstackclient/volume/v2/backup_record.py +15 -6
  244. openstackclient/volume/v2/consistency_group.py +37 -25
  245. openstackclient/volume/v2/consistency_group_snapshot.py +27 -12
  246. openstackclient/volume/v2/qos_specs.py +30 -19
  247. openstackclient/volume/v2/service.py +17 -6
  248. openstackclient/volume/v2/volume.py +69 -34
  249. openstackclient/volume/v2/volume_backend.py +19 -6
  250. openstackclient/volume/v2/volume_backup.py +48 -22
  251. openstackclient/volume/v2/volume_host.py +6 -4
  252. openstackclient/volume/v2/volume_snapshot.py +52 -26
  253. openstackclient/volume/v2/volume_transfer_request.py +33 -15
  254. openstackclient/volume/v2/volume_type.py +46 -27
  255. openstackclient/volume/v3/block_storage_cleanup.py +11 -3
  256. openstackclient/volume/v3/block_storage_cluster.py +19 -7
  257. openstackclient/volume/v3/block_storage_log_level.py +15 -6
  258. openstackclient/volume/v3/block_storage_manage.py +10 -4
  259. openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
  260. openstackclient/volume/v3/service.py +16 -6
  261. openstackclient/volume/v3/volume.py +103 -46
  262. openstackclient/volume/v3/volume_attachment.py +43 -21
  263. openstackclient/volume/v3/volume_backup.py +55 -26
  264. openstackclient/volume/v3/volume_group.py +23 -13
  265. openstackclient/volume/v3/volume_group_snapshot.py +32 -13
  266. openstackclient/volume/v3/volume_group_type.py +26 -13
  267. openstackclient/volume/v3/volume_message.py +15 -7
  268. openstackclient/volume/v3/volume_snapshot.py +71 -34
  269. openstackclient/volume/v3/volume_transfer_request.py +33 -15
  270. openstackclient/volume/v3/volume_type.py +45 -27
  271. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/METADATA +6 -6
  272. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/RECORD +279 -267
  273. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/WHEEL +1 -1
  274. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/entry_points.txt +53 -1
  275. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/AUTHORS +9 -0
  276. python_openstackclient-10.0.0.dist-info/pbr.json +1 -0
  277. openstackclient/api/image_v1.py +0 -69
  278. openstackclient/api/image_v2.py +0 -79
  279. openstackclient/network/v2/floating_ip_pool.py +0 -38
  280. openstackclient/tests/functional/image/v1/test_image.py +0 -97
  281. openstackclient/tests/unit/api/test_image_v1.py +0 -96
  282. openstackclient/tests/unit/api/test_image_v2.py +0 -96
  283. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
  284. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
  285. openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
  286. openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
  287. openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
  288. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
  289. python_openstackclient-8.3.0.dist-info/pbr.json +0 -1
  290. /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
  291. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/LICENSE +0 -0
  292. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/top_level.txt +0 -0
@@ -15,10 +15,11 @@
15
15
  """Volume V3 Volume action implementations"""
16
16
 
17
17
  import argparse
18
+ from collections.abc import Iterable, Sequence
18
19
  import copy
19
20
  import functools
20
21
  import logging
21
- import typing as ty
22
+ from typing import Any
22
23
 
23
24
  from cliff import columns as cliff_columns
24
25
  from openstack.block_storage.v3 import volume as _volume
@@ -44,14 +45,20 @@ class KeyValueHintAction(argparse.Action):
44
45
 
45
46
  APPEND_KEYS = ('same_host', 'different_host')
46
47
 
47
- def __init__(self, *args, **kwargs):
48
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
48
49
  self._key_value_action = parseractions.KeyValueAction(*args, **kwargs)
49
50
  self._key_value_append_action = parseractions.KeyValueAppendAction(
50
51
  *args, **kwargs
51
52
  )
52
53
  super().__init__(*args, **kwargs)
53
54
 
54
- def __call__(self, parser, namespace, values, option_string=None):
55
+ def __call__(
56
+ self,
57
+ parser: argparse.ArgumentParser,
58
+ namespace: argparse.Namespace,
59
+ values: Any,
60
+ option_string: str | None = None,
61
+ ) -> None:
55
62
  if values.startswith(self.APPEND_KEYS):
56
63
  self._key_value_append_action(
57
64
  parser, namespace, values, option_string=option_string
@@ -62,7 +69,7 @@ class KeyValueHintAction(argparse.Action):
62
69
  )
63
70
 
64
71
 
65
- class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
72
+ class AttachmentsColumn(cliff_columns.FormattableColumn[list[Any]]):
66
73
  """Formattable column for attachments column.
67
74
 
68
75
  Unlike the parent FormattableColumn class, the initializer of the
@@ -73,11 +80,13 @@ class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
73
80
  ``functools.partial(AttachmentsColumn, server_cache)``.
74
81
  """
75
82
 
76
- def __init__(self, value, server_cache=None):
83
+ def __init__(
84
+ self, value: list[Any], server_cache: dict[str, Any] | None = None
85
+ ) -> None:
77
86
  super().__init__(value)
78
87
  self._server_cache = server_cache or {}
79
88
 
80
- def human_readable(self):
89
+ def human_readable(self) -> str:
81
90
  """Return a formatted string of a volume's attached instances
82
91
 
83
92
  :rtype: a string of formatted instances
@@ -93,7 +102,7 @@ class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
93
102
  return msg
94
103
 
95
104
 
96
- def _format_volume(volume: _volume.Volume) -> dict[str, ty.Any]:
105
+ def _format_volume(volume: _volume.Volume) -> dict[str, Any]:
97
106
  # Some columns returned by openstacksdk should not be shown because they're
98
107
  # either irrelevant or duplicates
99
108
  ignored_columns = {
@@ -143,7 +152,7 @@ class CreateVolume(command.ShowOne):
143
152
  _description = _("Create new volume")
144
153
 
145
154
  @staticmethod
146
- def _check_size_arg(args):
155
+ def _check_size_arg(args: argparse.Namespace) -> None:
147
156
  """Check whether --size option is required or not.
148
157
 
149
158
  Require size parameter in case if any of the following is not
@@ -164,7 +173,7 @@ class CreateVolume(command.ShowOne):
164
173
  )
165
174
  raise exceptions.CommandError(msg)
166
175
 
167
- def get_parser(self, prog_name):
176
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
168
177
  parser = super().get_parser(prog_name)
169
178
  parser.add_argument(
170
179
  "name",
@@ -313,7 +322,9 @@ class CreateVolume(command.ShowOne):
313
322
  )
314
323
  return parser
315
324
 
316
- def take_action(self, parsed_args):
325
+ def take_action(
326
+ self, parsed_args: argparse.Namespace
327
+ ) -> tuple[Sequence[str], Iterable[Any]]:
317
328
  self._check_size_arg(parsed_args)
318
329
  # size is validated in the above call to
319
330
  # _check_size_arg where we check that size
@@ -321,7 +332,9 @@ class CreateVolume(command.ShowOne):
321
332
  # volume from snapshot, backup or source volume
322
333
  size = parsed_args.size
323
334
 
324
- volume_client = self.app.client_manager.sdk_connection.volume
335
+ volume_client = sdk_utils.ensure_service_version(
336
+ self.app.client_manager.sdk_connection.volume, '3'
337
+ )
325
338
  image_client = self.app.client_manager.image
326
339
 
327
340
  if (
@@ -386,7 +399,8 @@ class CreateVolume(command.ShowOne):
386
399
  bootable=parsed_args.bootable,
387
400
  )
388
401
  data = _format_volume(volume)
389
- return zip(*sorted(data.items()))
402
+ col_headers, col_data = zip(*sorted(data.items()))
403
+ return col_headers, col_data
390
404
 
391
405
  source_volume = None
392
406
  if parsed_args.source:
@@ -491,13 +505,14 @@ class CreateVolume(command.ShowOne):
491
505
  )
492
506
 
493
507
  data = _format_volume(volume)
494
- return zip(*sorted(data.items()))
508
+ col_headers, col_data = zip(*sorted(data.items()))
509
+ return col_headers, col_data
495
510
 
496
511
 
497
512
  class DeleteVolume(command.Command):
498
513
  _description = _("Delete volume(s)")
499
514
 
500
- def get_parser(self, prog_name):
515
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
501
516
  parser = super().get_parser(prog_name)
502
517
  parser.add_argument(
503
518
  "volumes",
@@ -515,12 +530,19 @@ class DeleteVolume(command.Command):
515
530
  ),
516
531
  )
517
532
  group.add_argument(
518
- "--purge",
533
+ "--cascade",
519
534
  action="store_true",
520
535
  help=_(
521
536
  "Remove any snapshots along with volume(s) (defaults to False)"
522
537
  ),
523
538
  )
539
+ group.add_argument(
540
+ # now called "cascade", accept old arg for compatibility
541
+ "--purge",
542
+ action="store_true",
543
+ help=argparse.SUPPRESS,
544
+ dest='cascade',
545
+ )
524
546
  parser.add_argument(
525
547
  '--remote',
526
548
  action='store_true',
@@ -528,13 +550,15 @@ class DeleteVolume(command.Command):
528
550
  )
529
551
  return parser
530
552
 
531
- def take_action(self, parsed_args):
532
- volume_client = self.app.client_manager.sdk_connection.volume
553
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
554
+ volume_client = sdk_utils.ensure_service_version(
555
+ self.app.client_manager.sdk_connection.volume, '3'
556
+ )
533
557
  result = 0
534
558
 
535
- if parsed_args.remote and (parsed_args.force or parsed_args.purge):
559
+ if parsed_args.remote and (parsed_args.force or parsed_args.cascade):
536
560
  msg = _(
537
- "The --force and --purge options are not "
561
+ "The --force and --cascade options are not "
538
562
  "supported with the --remote parameter."
539
563
  )
540
564
  raise exceptions.CommandError(msg)
@@ -550,7 +574,7 @@ class DeleteVolume(command.Command):
550
574
  volume_client.delete_volume(
551
575
  volume_obj.id,
552
576
  force=parsed_args.force,
553
- cascade=parsed_args.purge,
577
+ cascade=parsed_args.cascade,
554
578
  )
555
579
  except Exception as e:
556
580
  result += 1
@@ -574,7 +598,7 @@ class DeleteVolume(command.Command):
574
598
  class ListVolume(command.Lister):
575
599
  _description = _("List volumes")
576
600
 
577
- def get_parser(self, prog_name):
601
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
578
602
  parser = super().get_parser(prog_name)
579
603
  parser.add_argument(
580
604
  '--project',
@@ -623,7 +647,9 @@ class ListVolume(command.Lister):
623
647
  pagination.add_marker_pagination_option_to_parser(parser)
624
648
  return parser
625
649
 
626
- def take_action(self, parsed_args):
650
+ def take_action(
651
+ self, parsed_args: argparse.Namespace
652
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
627
653
  volume_client = self.app.client_manager.volume
628
654
  identity_client = self.app.client_manager.identity
629
655
 
@@ -699,7 +725,7 @@ class ListVolume(command.Lister):
699
725
  compute_client = self.app.client_manager.compute
700
726
  for s in compute_client.servers():
701
727
  server_cache[s.id] = s
702
- except sdk_exceptions.SDKException: # noqa: S110
728
+ except sdk_exceptions.SDKException:
703
729
  # Just forget it if there's any trouble
704
730
  pass
705
731
  AttachmentsColumnWithCache = functools.partial(
@@ -729,21 +755,29 @@ class ListVolume(command.Lister):
729
755
  class MigrateVolume(command.Command):
730
756
  _description = _("Migrate volume to a new host")
731
757
 
732
- def get_parser(self, prog_name):
758
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
733
759
  parser = super().get_parser(prog_name)
734
760
  parser.add_argument(
735
761
  'volume',
736
762
  metavar="<volume>",
737
763
  help=_("Volume to migrate (name or ID)"),
738
764
  )
739
- parser.add_argument(
765
+ destination_group = parser.add_mutually_exclusive_group(required=True)
766
+ destination_group.add_argument(
740
767
  '--host',
741
768
  metavar="<host>",
742
- required=True,
743
769
  help=_(
744
770
  "Destination host (takes the form: host@backend-name#pool)"
745
771
  ),
746
772
  )
773
+ destination_group.add_argument(
774
+ '--cluster',
775
+ metavar="<cluster>",
776
+ help=_(
777
+ "Destination cluster to migrate the volume to "
778
+ "(requires --os-volume-api-version 3.16 or higher)"
779
+ ),
780
+ )
747
781
  parser.add_argument(
748
782
  '--force-host-copy',
749
783
  action="store_true",
@@ -761,26 +795,38 @@ class MigrateVolume(command.Command):
761
795
  "(possibly by another operation)"
762
796
  ),
763
797
  )
764
- # TODO(stephenfin): Add --cluster argument
765
798
  return parser
766
799
 
767
- def take_action(self, parsed_args):
768
- volume_client = self.app.client_manager.sdk_connection.volume
800
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
801
+ volume_client = sdk_utils.ensure_service_version(
802
+ self.app.client_manager.sdk_connection.volume, '3'
803
+ )
769
804
  volume = volume_client.find_volume(
770
805
  parsed_args.volume, ignore_missing=False
771
806
  )
807
+
808
+ if parsed_args.cluster and not sdk_utils.supports_microversion(
809
+ volume_client, '3.16'
810
+ ):
811
+ msg = _(
812
+ "--os-volume-api-version 3.16 or greater is required to "
813
+ "support the volume migration with cluster"
814
+ )
815
+ raise exceptions.CommandError(msg)
816
+
772
817
  volume_client.migrate_volume(
773
818
  volume.id,
774
819
  host=parsed_args.host,
775
820
  force_host_copy=parsed_args.force_host_copy,
776
821
  lock_volume=parsed_args.lock_volume,
822
+ cluster=parsed_args.cluster,
777
823
  )
778
824
 
779
825
 
780
826
  class SetVolume(command.Command):
781
827
  _description = _("Set volume properties")
782
828
 
783
- def get_parser(self, prog_name):
829
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
784
830
  parser = super().get_parser(prog_name)
785
831
  parser.add_argument(
786
832
  'volume',
@@ -933,7 +979,7 @@ class SetVolume(command.Command):
933
979
  )
934
980
  return parser
935
981
 
936
- def take_action(self, parsed_args):
982
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
937
983
  volume_client = self.app.client_manager.volume
938
984
  volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
939
985
 
@@ -1071,12 +1117,12 @@ class SetVolume(command.Command):
1071
1117
  elif policy:
1072
1118
  # If the "--migration-policy" is specified without "--type"
1073
1119
  LOG.warning(
1074
- _("'%s' option will not work without '--type' option")
1075
- % (
1120
+ _("'%s' option will not work without '--type' option"),
1121
+ (
1076
1122
  '--migration-policy'
1077
1123
  if parsed_args.migration_policy
1078
1124
  else '--retype-policy'
1079
- )
1125
+ ),
1080
1126
  )
1081
1127
 
1082
1128
  kwargs = {}
@@ -1106,7 +1152,7 @@ class SetVolume(command.Command):
1106
1152
  class ShowVolume(command.ShowOne):
1107
1153
  _description = _("Display volume details")
1108
1154
 
1109
- def get_parser(self, prog_name):
1155
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
1110
1156
  parser = super().get_parser(prog_name)
1111
1157
  parser.add_argument(
1112
1158
  'volume',
@@ -1115,20 +1161,25 @@ class ShowVolume(command.ShowOne):
1115
1161
  )
1116
1162
  return parser
1117
1163
 
1118
- def take_action(self, parsed_args):
1119
- volume_client = self.app.client_manager.sdk_connection.volume
1164
+ def take_action(
1165
+ self, parsed_args: argparse.Namespace
1166
+ ) -> tuple[Sequence[str], Iterable[Any]]:
1167
+ volume_client = sdk_utils.ensure_service_version(
1168
+ self.app.client_manager.sdk_connection.volume, '3'
1169
+ )
1120
1170
  volume = volume_client.find_volume(
1121
1171
  parsed_args.volume, ignore_missing=False
1122
1172
  )
1123
1173
 
1124
1174
  data = _format_volume(volume)
1125
- return zip(*sorted(data.items()))
1175
+ col_headers, col_data = zip(*sorted(data.items()))
1176
+ return col_headers, col_data
1126
1177
 
1127
1178
 
1128
1179
  class UnsetVolume(command.Command):
1129
1180
  _description = _("Unset volume properties")
1130
1181
 
1131
- def get_parser(self, prog_name):
1182
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
1132
1183
  parser = super().get_parser(prog_name)
1133
1184
  parser.add_argument(
1134
1185
  'volume',
@@ -1157,7 +1208,7 @@ class UnsetVolume(command.Command):
1157
1208
  )
1158
1209
  return parser
1159
1210
 
1160
- def take_action(self, parsed_args):
1211
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
1161
1212
  volume_client = self.app.client_manager.volume
1162
1213
  volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
1163
1214
 
@@ -1189,7 +1240,7 @@ class UnsetVolume(command.Command):
1189
1240
  class VolumeSummary(command.ShowOne):
1190
1241
  _description = _("Show a summary of all volumes in this deployment.")
1191
1242
 
1192
- def get_parser(self, prog_name):
1243
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
1193
1244
  parser = super().get_parser(prog_name)
1194
1245
  parser.add_argument(
1195
1246
  '--all-projects',
@@ -1199,8 +1250,12 @@ class VolumeSummary(command.ShowOne):
1199
1250
  )
1200
1251
  return parser
1201
1252
 
1202
- def take_action(self, parsed_args):
1203
- volume_client = self.app.client_manager.sdk_connection.volume
1253
+ def take_action(
1254
+ self, parsed_args: argparse.Namespace
1255
+ ) -> tuple[Sequence[str], Iterable[Any]]:
1256
+ volume_client = sdk_utils.ensure_service_version(
1257
+ self.app.client_manager.sdk_connection.volume, '3'
1258
+ )
1204
1259
 
1205
1260
  if not sdk_utils.supports_microversion(volume_client, '3.12'):
1206
1261
  msg = _(
@@ -1239,7 +1294,7 @@ class VolumeSummary(command.ShowOne):
1239
1294
  class VolumeRevertToSnapshot(command.Command):
1240
1295
  _description = _("Revert a volume to a snapshot.")
1241
1296
 
1242
- def get_parser(self, prog_name):
1297
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
1243
1298
  parser = super().get_parser(prog_name)
1244
1299
  parser.add_argument(
1245
1300
  'snapshot',
@@ -1251,8 +1306,10 @@ class VolumeRevertToSnapshot(command.Command):
1251
1306
  )
1252
1307
  return parser
1253
1308
 
1254
- def take_action(self, parsed_args):
1255
- volume_client = self.app.client_manager.sdk_connection.volume
1309
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
1310
+ volume_client = sdk_utils.ensure_service_version(
1311
+ self.app.client_manager.sdk_connection.volume, '3'
1312
+ )
1256
1313
 
1257
1314
  if not sdk_utils.supports_microversion(volume_client, '3.40'):
1258
1315
  msg = _(
@@ -10,8 +10,10 @@
10
10
  # License for the specific language governing permissions and limitations
11
11
  # under the License.
12
12
 
13
+ import argparse
14
+ from collections.abc import Iterable, Sequence
13
15
  import logging
14
- import typing as ty
16
+ from typing import Any
15
17
 
16
18
  from openstack import utils as sdk_utils
17
19
  from osc_lib.cli import format_columns
@@ -32,7 +34,7 @@ _FILTER_DEPRECATED = _(
32
34
  )
33
35
 
34
36
 
35
- def _format_attachment(attachment):
37
+ def _format_attachment(attachment: Any) -> tuple[tuple[str, ...], Any]:
36
38
  columns = (
37
39
  'id',
38
40
  'volume_id',
@@ -57,7 +59,7 @@ def _format_attachment(attachment):
57
59
  # VolumeAttachmentManager.create returns a dict while everything else
58
60
  # returns a VolumeAttachment object
59
61
  if isinstance(attachment, dict):
60
- data: tuple[ty.Any, ...] = ()
62
+ data: tuple[Any, ...] = ()
61
63
  for column in columns:
62
64
  if column == 'connection_info':
63
65
  data += (format_columns.DictColumn(attachment[column]),)
@@ -88,7 +90,7 @@ class CreateVolumeAttachment(command.ShowOne):
88
90
  add volume' command should be preferred.
89
91
  """
90
92
 
91
- def get_parser(self, prog_name):
93
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
92
94
  parser = super().get_parser(prog_name)
93
95
  parser.add_argument(
94
96
  'volume',
@@ -171,8 +173,12 @@ class CreateVolumeAttachment(command.ShowOne):
171
173
  )
172
174
  return parser
173
175
 
174
- def take_action(self, parsed_args):
175
- volume_client = self.app.client_manager.sdk_connection.volume
176
+ def take_action(
177
+ self, parsed_args: argparse.Namespace
178
+ ) -> tuple[Sequence[str], Iterable[Any]]:
179
+ volume_client = sdk_utils.ensure_service_version(
180
+ self.app.client_manager.sdk_connection.volume, '3'
181
+ )
176
182
  compute_client = self.app.client_manager.compute
177
183
 
178
184
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
@@ -249,7 +255,7 @@ class DeleteVolumeAttachment(command.Command):
249
255
  remove' command should be preferred.
250
256
  """
251
257
 
252
- def get_parser(self, prog_name):
258
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
253
259
  parser = super().get_parser(prog_name)
254
260
  parser.add_argument(
255
261
  'attachment',
@@ -258,8 +264,10 @@ class DeleteVolumeAttachment(command.Command):
258
264
  )
259
265
  return parser
260
266
 
261
- def take_action(self, parsed_args):
262
- volume_client = self.app.client_manager.sdk_connection.volume
267
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
268
+ volume_client = sdk_utils.ensure_service_version(
269
+ self.app.client_manager.sdk_connection.volume, '3'
270
+ )
263
271
 
264
272
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
265
273
  msg = _(
@@ -280,7 +288,7 @@ class SetVolumeAttachment(command.ShowOne):
280
288
  connected to.
281
289
  """
282
290
 
283
- def get_parser(self, prog_name):
291
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
284
292
  parser = super().get_parser(prog_name)
285
293
  parser.add_argument(
286
294
  'attachment',
@@ -332,8 +340,12 @@ class SetVolumeAttachment(command.ShowOne):
332
340
  )
333
341
  return parser
334
342
 
335
- def take_action(self, parsed_args):
336
- volume_client = self.app.client_manager.sdk_connection.volume
343
+ def take_action(
344
+ self, parsed_args: argparse.Namespace
345
+ ) -> tuple[Sequence[str], Iterable[Any]]:
346
+ volume_client = sdk_utils.ensure_service_version(
347
+ self.app.client_manager.sdk_connection.volume, '3'
348
+ )
337
349
 
338
350
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
339
351
  msg = _(
@@ -363,7 +375,7 @@ class SetVolumeAttachment(command.ShowOne):
363
375
  class CompleteVolumeAttachment(command.Command):
364
376
  """Complete an attachment for a volume."""
365
377
 
366
- def get_parser(self, prog_name):
378
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
367
379
  parser = super().get_parser(prog_name)
368
380
  parser.add_argument(
369
381
  'attachment',
@@ -372,8 +384,10 @@ class CompleteVolumeAttachment(command.Command):
372
384
  )
373
385
  return parser
374
386
 
375
- def take_action(self, parsed_args):
376
- volume_client = self.app.client_manager.sdk_connection.volume
387
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
388
+ volume_client = sdk_utils.ensure_service_version(
389
+ self.app.client_manager.sdk_connection.volume, '3'
390
+ )
377
391
 
378
392
  if not sdk_utils.supports_microversion(volume_client, '3.44'):
379
393
  msg = _(
@@ -388,7 +402,7 @@ class CompleteVolumeAttachment(command.Command):
388
402
  class ListVolumeAttachment(command.Lister):
389
403
  """Lists all volume attachments."""
390
404
 
391
- def get_parser(self, prog_name):
405
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
392
406
  parser = super().get_parser(prog_name)
393
407
  parser.add_argument(
394
408
  '--project',
@@ -432,8 +446,12 @@ class ListVolumeAttachment(command.Lister):
432
446
  # )
433
447
  return parser
434
448
 
435
- def take_action(self, parsed_args):
436
- volume_client = self.app.client_manager.sdk_connection.volume
449
+ def take_action(
450
+ self, parsed_args: argparse.Namespace
451
+ ) -> tuple[tuple[str, ...], Iterable[tuple[Any, ...]]]:
452
+ volume_client = sdk_utils.ensure_service_version(
453
+ self.app.client_manager.sdk_connection.volume, '3'
454
+ )
437
455
  identity_client = self.app.client_manager.identity
438
456
 
439
457
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
@@ -490,7 +508,7 @@ class ListVolumeAttachment(command.Lister):
490
508
  class ShowVolumeAttachment(command.ShowOne):
491
509
  """Show detailed information for a volume attachment."""
492
510
 
493
- def get_parser(self, prog_name):
511
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
494
512
  parser = super().get_parser(prog_name)
495
513
  parser.add_argument(
496
514
  'attachment',
@@ -499,8 +517,12 @@ class ShowVolumeAttachment(command.ShowOne):
499
517
  )
500
518
  return parser
501
519
 
502
- def take_action(self, parsed_args):
503
- volume_client = self.app.client_manager.sdk_connection.volume
520
+ def take_action(
521
+ self, parsed_args: argparse.Namespace
522
+ ) -> tuple[Sequence[str], Iterable[Any]]:
523
+ volume_client = sdk_utils.ensure_service_version(
524
+ self.app.client_manager.sdk_connection.volume, '3'
525
+ )
504
526
 
505
527
  if not sdk_utils.supports_microversion(volume_client, '3.27'):
506
528
  msg = _(