python-openstackclient 10.0.0__py3-none-any.whl → 10.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 (203) hide show
  1. openstackclient/common/availability_zone.py +1 -1
  2. openstackclient/common/module.py +21 -27
  3. openstackclient/common/pagination.py +42 -4
  4. openstackclient/common/project_cleanup.py +1 -2
  5. openstackclient/common/quota.py +9 -5
  6. openstackclient/compute/v2/flavor.py +3 -1
  7. openstackclient/compute/v2/hypervisor.py +2 -0
  8. openstackclient/compute/v2/keypair.py +6 -2
  9. openstackclient/compute/v2/server.py +21 -12
  10. openstackclient/compute/v2/server_event.py +8 -1
  11. openstackclient/compute/v2/server_group.py +2 -0
  12. openstackclient/compute/v2/server_migration.py +3 -0
  13. openstackclient/compute/v2/server_volume.py +3 -1
  14. openstackclient/compute/v2/service.py +3 -1
  15. openstackclient/compute/v2/usage.py +2 -2
  16. openstackclient/identity/common.py +5 -1
  17. openstackclient/identity/v3/access_rule.py +6 -0
  18. openstackclient/identity/v3/application_credential.py +10 -3
  19. openstackclient/identity/v3/credential.py +4 -2
  20. openstackclient/identity/v3/domain.py +4 -2
  21. openstackclient/identity/v3/endpoint.py +57 -45
  22. openstackclient/identity/v3/federation_protocol.py +7 -5
  23. openstackclient/identity/v3/group.py +11 -10
  24. openstackclient/identity/v3/identity_provider.py +4 -1
  25. openstackclient/identity/v3/limit.py +5 -2
  26. openstackclient/identity/v3/mapping.py +36 -19
  27. openstackclient/identity/v3/project.py +18 -5
  28. openstackclient/identity/v3/region.py +4 -2
  29. openstackclient/identity/v3/registered_limit.py +3 -2
  30. openstackclient/identity/v3/role.py +2 -1
  31. openstackclient/identity/v3/role_assignment.py +3 -2
  32. openstackclient/identity/v3/service.py +4 -2
  33. openstackclient/identity/v3/service_provider.py +4 -2
  34. openstackclient/identity/v3/trust.py +8 -5
  35. openstackclient/identity/v3/user.py +38 -11
  36. openstackclient/image/v2/cache.py +2 -2
  37. openstackclient/image/v2/image.py +15 -9
  38. openstackclient/image/v2/metadef_namespaces.py +11 -10
  39. openstackclient/image/v2/metadef_objects.py +5 -5
  40. openstackclient/image/v2/metadef_properties.py +7 -4
  41. openstackclient/image/v2/task.py +11 -22
  42. openstackclient/network/utils.py +0 -41
  43. openstackclient/network/v2/address_group.py +13 -1
  44. openstackclient/network/v2/address_scope.py +13 -8
  45. openstackclient/network/v2/bgpvpn/bgpvpn.py +33 -19
  46. openstackclient/network/v2/bgpvpn/network_association.py +25 -13
  47. openstackclient/network/v2/bgpvpn/port_association.py +35 -21
  48. openstackclient/network/v2/bgpvpn/router_association.py +27 -14
  49. openstackclient/network/v2/default_security_group_rule.py +14 -6
  50. openstackclient/network/v2/floating_ip.py +12 -4
  51. openstackclient/network/v2/floating_ip_port_forwarding.py +12 -2
  52. openstackclient/network/v2/fwaas/group.py +34 -1
  53. openstackclient/network/v2/fwaas/rule.py +39 -3
  54. openstackclient/network/v2/ip_availability.py +13 -4
  55. openstackclient/network/v2/l3_conntrack_helper.py +14 -1
  56. openstackclient/network/v2/local_ip.py +4 -1
  57. openstackclient/network/v2/local_ip_association.py +4 -1
  58. openstackclient/network/v2/ndp_proxy.py +4 -1
  59. openstackclient/network/v2/network.py +87 -20
  60. openstackclient/network/v2/network_agent.py +32 -10
  61. openstackclient/network/v2/network_auto_allocated_topology.py +6 -5
  62. openstackclient/network/v2/network_flavor.py +19 -6
  63. openstackclient/network/v2/network_flavor_profile.py +20 -6
  64. openstackclient/network/v2/network_meter.py +19 -6
  65. openstackclient/network/v2/network_meter_rule.py +20 -2
  66. openstackclient/network/v2/network_qos_policy.py +15 -7
  67. openstackclient/network/v2/network_qos_rule.py +16 -1
  68. openstackclient/network/v2/network_qos_rule_type.py +16 -5
  69. openstackclient/network/v2/network_rbac.py +12 -5
  70. openstackclient/network/v2/network_segment.py +13 -1
  71. openstackclient/network/v2/network_segment_range.py +15 -3
  72. openstackclient/network/v2/network_trunk.py +4 -1
  73. openstackclient/network/v2/port.py +88 -12
  74. openstackclient/network/v2/router.py +27 -16
  75. openstackclient/network/v2/security_group.py +18 -49
  76. openstackclient/network/v2/security_group_rule.py +18 -5
  77. openstackclient/network/v2/subnet.py +15 -7
  78. openstackclient/network/v2/subnet_pool.py +13 -8
  79. openstackclient/network/v2/taas/tap_flow.py +13 -3
  80. openstackclient/network/v2/taas/tap_mirror.py +7 -4
  81. openstackclient/network/v2/taas/tap_service.py +4 -1
  82. openstackclient/object/v1/container.py +3 -1
  83. openstackclient/object/v1/object.py +3 -1
  84. openstackclient/tests/functional/identity/v3/common.py +34 -0
  85. openstackclient/tests/functional/identity/v3/test_application_credential.py +1 -1
  86. openstackclient/tests/functional/identity/v3/test_mapping.py +81 -0
  87. openstackclient/tests/functional/volume/v3/test_volume_group.py +163 -0
  88. openstackclient/tests/unit/common/test_limits.py +1 -1
  89. openstackclient/tests/unit/common/test_module.py +77 -44
  90. openstackclient/tests/unit/common/test_quota.py +9 -0
  91. openstackclient/tests/unit/compute/v2/fakes.py +1 -57
  92. openstackclient/tests/unit/compute/v2/test_agent.py +4 -4
  93. openstackclient/tests/unit/compute/v2/test_aggregate.py +1 -1
  94. openstackclient/tests/unit/compute/v2/test_console.py +2 -2
  95. openstackclient/tests/unit/compute/v2/test_console_connection.py +1 -1
  96. openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
  97. openstackclient/tests/unit/compute/v2/test_host.py +3 -3
  98. openstackclient/tests/unit/compute/v2/test_hypervisor.py +2 -2
  99. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -1
  100. openstackclient/tests/unit/compute/v2/test_keypair.py +1 -1
  101. openstackclient/tests/unit/compute/v2/test_server.py +15 -15
  102. openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
  103. openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
  104. openstackclient/tests/unit/compute/v2/test_server_group.py +1 -1
  105. openstackclient/tests/unit/compute/v2/test_server_image.py +1 -1
  106. openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
  107. openstackclient/tests/unit/compute/v2/test_server_share.py +4 -4
  108. openstackclient/tests/unit/compute/v2/test_server_volume.py +2 -2
  109. openstackclient/tests/unit/compute/v2/test_service.py +3 -3
  110. openstackclient/tests/unit/compute/v2/test_usage.py +1 -1
  111. openstackclient/tests/unit/identity/v2_0/fakes.py +3 -7
  112. openstackclient/tests/unit/identity/v2_0/test_endpoint.py +1 -1
  113. openstackclient/tests/unit/identity/v2_0/test_project.py +1 -1
  114. openstackclient/tests/unit/identity/v2_0/test_role.py +1 -1
  115. openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +1 -1
  116. openstackclient/tests/unit/identity/v2_0/test_service.py +1 -1
  117. openstackclient/tests/unit/identity/v2_0/test_token.py +2 -2
  118. openstackclient/tests/unit/identity/v2_0/test_user.py +1 -1
  119. openstackclient/tests/unit/identity/v3/fakes.py +5 -38
  120. openstackclient/tests/unit/identity/v3/test_access_rule.py +3 -3
  121. openstackclient/tests/unit/identity/v3/test_application_credential.py +4 -4
  122. openstackclient/tests/unit/identity/v3/test_credential.py +5 -5
  123. openstackclient/tests/unit/identity/v3/test_domain.py +5 -5
  124. openstackclient/tests/unit/identity/v3/test_endpoint.py +6 -6
  125. openstackclient/tests/unit/identity/v3/test_endpoint_group.py +1 -1
  126. openstackclient/tests/unit/identity/v3/test_group.py +8 -8
  127. openstackclient/tests/unit/identity/v3/test_implied_role.py +1 -1
  128. openstackclient/tests/unit/identity/v3/test_limit.py +5 -5
  129. openstackclient/tests/unit/identity/v3/test_mappings.py +163 -79
  130. openstackclient/tests/unit/identity/v3/test_project.py +28 -5
  131. openstackclient/tests/unit/identity/v3/test_protocol.py +3 -3
  132. openstackclient/tests/unit/identity/v3/test_region.py +5 -5
  133. openstackclient/tests/unit/identity/v3/test_registered_limit.py +5 -5
  134. openstackclient/tests/unit/identity/v3/test_role.py +8 -8
  135. openstackclient/tests/unit/identity/v3/test_role_assignment.py +1 -1
  136. openstackclient/tests/unit/identity/v3/test_service.py +5 -5
  137. openstackclient/tests/unit/identity/v3/test_token.py +2 -2
  138. openstackclient/tests/unit/identity/v3/test_trust.py +4 -4
  139. openstackclient/tests/unit/identity/v3/test_user.py +73 -6
  140. openstackclient/tests/unit/network/v2/fakes.py +5 -77
  141. openstackclient/tests/unit/network/v2/fwaas/test_group.py +28 -2
  142. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +28 -3
  143. openstackclient/tests/unit/network/v2/test_address_group.py +24 -0
  144. openstackclient/tests/unit/network/v2/test_address_scope.py +24 -0
  145. openstackclient/tests/unit/network/v2/test_floating_ip.py +24 -0
  146. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +24 -0
  147. openstackclient/tests/unit/network/v2/test_ip_availability.py +25 -0
  148. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +29 -3
  149. openstackclient/tests/unit/network/v2/test_network.py +74 -12
  150. openstackclient/tests/unit/network/v2/test_network_agent.py +50 -1
  151. openstackclient/tests/unit/network/v2/test_network_flavor.py +24 -0
  152. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +24 -0
  153. openstackclient/tests/unit/network/v2/test_network_meter.py +24 -0
  154. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +24 -0
  155. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +24 -0
  156. openstackclient/tests/unit/network/v2/test_network_rbac.py +24 -0
  157. openstackclient/tests/unit/network/v2/test_network_segment.py +24 -0
  158. openstackclient/tests/unit/network/v2/test_network_segment_range.py +24 -0
  159. openstackclient/tests/unit/network/v2/test_port.py +166 -0
  160. openstackclient/tests/unit/network/v2/test_router.py +28 -7
  161. openstackclient/tests/unit/network/v2/test_security_group.py +22 -0
  162. openstackclient/tests/unit/network/v2/test_security_group_rule.py +25 -0
  163. openstackclient/tests/unit/network/v2/test_subnet.py +28 -4
  164. openstackclient/tests/unit/network/v2/test_subnet_pool.py +24 -0
  165. openstackclient/tests/unit/volume/v2/fakes.py +20 -140
  166. openstackclient/tests/unit/volume/v2/test_volume_backup.py +5 -9
  167. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +6 -0
  168. openstackclient/tests/unit/volume/v3/fakes.py +204 -100
  169. openstackclient/tests/unit/volume/v3/test_backup_record.py +114 -0
  170. openstackclient/tests/unit/volume/v3/test_consistency_group.py +720 -0
  171. openstackclient/tests/unit/volume/v3/test_consistency_group_snapshot.py +354 -0
  172. openstackclient/tests/unit/volume/v3/test_qos_specs.py +455 -0
  173. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +2 -0
  174. openstackclient/tests/unit/volume/v3/test_volume_backend.py +158 -0
  175. openstackclient/tests/unit/volume/v3/test_volume_backup.py +5 -9
  176. openstackclient/tests/unit/volume/v3/test_volume_group_type.py +65 -0
  177. openstackclient/tests/unit/volume/v3/test_volume_host.py +115 -0
  178. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +6 -0
  179. openstackclient/volume/v2/volume.py +4 -2
  180. openstackclient/volume/v2/volume_backup.py +2 -3
  181. openstackclient/volume/v2/volume_snapshot.py +3 -4
  182. openstackclient/volume/v3/backup_record.py +94 -0
  183. openstackclient/volume/v3/consistency_group.py +400 -0
  184. openstackclient/volume/v3/consistency_group_snapshot.py +225 -0
  185. openstackclient/volume/v3/qos_specs.py +389 -0
  186. openstackclient/volume/v3/volume.py +4 -2
  187. openstackclient/volume/v3/volume_attachment.py +5 -1
  188. openstackclient/volume/v3/volume_backend.py +130 -0
  189. openstackclient/volume/v3/volume_backup.py +2 -3
  190. openstackclient/volume/v3/volume_group_snapshot.py +4 -6
  191. openstackclient/volume/v3/volume_group_type.py +1 -1
  192. openstackclient/volume/v3/volume_host.py +74 -0
  193. openstackclient/volume/v3/volume_message.py +3 -1
  194. openstackclient/volume/v3/volume_snapshot.py +2 -1
  195. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/METADATA +3 -4
  196. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/RECORD +202 -188
  197. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/entry_points.txt +24 -24
  198. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/AUTHORS +5 -0
  199. python_openstackclient-10.1.0.dist-info/pbr.json +1 -0
  200. python_openstackclient-10.0.0.dist-info/pbr.json +0 -1
  201. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/WHEEL +0 -0
  202. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/LICENSE +0 -0
  203. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/top_level.txt +0 -0
@@ -459,3 +459,68 @@ class TestVolumeGroupTypeList(TestVolumeGroupType):
459
459
  self.assertIn(
460
460
  '--os-volume-api-version 3.11 or greater is required', str(exc)
461
461
  )
462
+
463
+
464
+ class TestVolumeGroupTypeShow(TestVolumeGroupType):
465
+ fake_volume_group_type = volume_fakes.create_one_volume_group_type()
466
+
467
+ columns = (
468
+ 'ID',
469
+ 'Name',
470
+ 'Description',
471
+ 'Is Public',
472
+ 'Properties',
473
+ )
474
+ data = (
475
+ fake_volume_group_type.id,
476
+ fake_volume_group_type.name,
477
+ fake_volume_group_type.description,
478
+ fake_volume_group_type.is_public,
479
+ format_columns.DictColumn(fake_volume_group_type.group_specs),
480
+ )
481
+
482
+ def setUp(self):
483
+ super().setUp()
484
+
485
+ self.volume_group_types_mock.get.return_value = (
486
+ self.fake_volume_group_type
487
+ )
488
+
489
+ self.cmd = volume_group_type.ShowVolumeGroupType(self.app, None)
490
+
491
+ def test_volume_group_type_show(self):
492
+ self.set_volume_api_version('3.11')
493
+
494
+ arglist = [
495
+ self.fake_volume_group_type.id,
496
+ ]
497
+ verifylist = [
498
+ ('group_type', self.fake_volume_group_type.id),
499
+ ]
500
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
501
+
502
+ columns, data = self.cmd.take_action(parsed_args)
503
+
504
+ self.volume_group_types_mock.get.assert_called_once_with(
505
+ self.fake_volume_group_type.id,
506
+ )
507
+ self.assertEqual(self.columns, columns)
508
+ self.assertCountEqual(self.data, data)
509
+
510
+ def test_volume_group_type_show_pre_v311(self):
511
+ self.set_volume_api_version('3.10')
512
+
513
+ arglist = [
514
+ self.fake_volume_group_type.id,
515
+ ]
516
+ verifylist = [
517
+ ('group_type', self.fake_volume_group_type.id),
518
+ ]
519
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
520
+
521
+ exc = self.assertRaises(
522
+ exceptions.CommandError, self.cmd.take_action, parsed_args
523
+ )
524
+ self.assertIn(
525
+ '--os-volume-api-version 3.11 or greater is required', str(exc)
526
+ )
@@ -0,0 +1,115 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+ # not use this file except in compliance with the License. You may obtain
4
+ # a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+ # License for the specific language governing permissions and limitations
12
+ # under the License.
13
+
14
+ from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
15
+ from openstackclient.volume.v3 import volume_host
16
+
17
+
18
+ class TestVolumeHost(volume_fakes.TestVolume):
19
+ def setUp(self):
20
+ super().setUp()
21
+
22
+ self.host_mock = self.volume_client.services
23
+ self.host_mock.reset_mock()
24
+
25
+
26
+ class TestVolumeHostSet(TestVolumeHost):
27
+ service = volume_fakes.create_one_service()
28
+
29
+ def setUp(self):
30
+ super().setUp()
31
+
32
+ self.host_mock.freeze_host.return_value = None
33
+ self.host_mock.thaw_host.return_value = None
34
+
35
+ # Get the command object to mock
36
+ self.cmd = volume_host.SetVolumeHost(self.app, None)
37
+
38
+ def test_volume_host_set_nothing(self):
39
+ arglist = [
40
+ self.service.host,
41
+ ]
42
+ verifylist = [
43
+ ('host', self.service.host),
44
+ ]
45
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
46
+ result = self.cmd.take_action(parsed_args)
47
+
48
+ self.host_mock.freeze_host.assert_not_called()
49
+ self.host_mock.thaw_host.assert_not_called()
50
+ self.assertIsNone(result)
51
+
52
+ def test_volume_host_set_enable(self):
53
+ arglist = [
54
+ '--enable',
55
+ self.service.host,
56
+ ]
57
+ verifylist = [
58
+ ('enable', True),
59
+ ('host', self.service.host),
60
+ ]
61
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
62
+
63
+ result = self.cmd.take_action(parsed_args)
64
+
65
+ self.host_mock.thaw_host.assert_called_with(self.service.host)
66
+ self.host_mock.freeze_host.assert_not_called()
67
+ self.assertIsNone(result)
68
+
69
+ def test_volume_host_set_disable(self):
70
+ arglist = [
71
+ '--disable',
72
+ self.service.host,
73
+ ]
74
+ verifylist = [
75
+ ('disable', True),
76
+ ('host', self.service.host),
77
+ ]
78
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
79
+
80
+ result = self.cmd.take_action(parsed_args)
81
+
82
+ self.host_mock.freeze_host.assert_called_with(self.service.host)
83
+ self.host_mock.thaw_host.assert_not_called()
84
+ self.assertIsNone(result)
85
+
86
+
87
+ class TestVolumeHostFailover(TestVolumeHost):
88
+ service = volume_fakes.create_one_service()
89
+
90
+ def setUp(self):
91
+ super().setUp()
92
+
93
+ self.host_mock.failover_host.return_value = None
94
+
95
+ # Get the command object to mock
96
+ self.cmd = volume_host.FailoverVolumeHost(self.app, None)
97
+
98
+ def test_volume_host_failover(self):
99
+ arglist = [
100
+ '--volume-backend',
101
+ 'backend_test',
102
+ self.service.host,
103
+ ]
104
+ verifylist = [
105
+ ('volume_backend', 'backend_test'),
106
+ ('host', self.service.host),
107
+ ]
108
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
109
+
110
+ result = self.cmd.take_action(parsed_args)
111
+
112
+ self.host_mock.failover_host.assert_called_with(
113
+ self.service.host, 'backend_test'
114
+ )
115
+ self.assertIsNone(result)
@@ -439,6 +439,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
439
439
  self.volume_sdk_client.snapshots.assert_called_once_with(
440
440
  limit=None,
441
441
  marker=None,
442
+ max_items=None,
442
443
  all_projects=False,
443
444
  name=None,
444
445
  status=None,
@@ -472,6 +473,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
472
473
  self.volume_sdk_client.snapshots.assert_called_once_with(
473
474
  limit=2,
474
475
  marker=self.snapshots[0].id,
476
+ max_items=None,
475
477
  all_projects=True,
476
478
  project_id=self.project.id,
477
479
  name=None,
@@ -493,6 +495,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
493
495
  self.volume_sdk_client.snapshots.assert_called_once_with(
494
496
  limit=None,
495
497
  marker=None,
498
+ max_items=None,
496
499
  all_projects=True,
497
500
  name=None,
498
501
  status=None,
@@ -519,6 +522,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
519
522
  self.volume_sdk_client.snapshots.assert_called_once_with(
520
523
  limit=None,
521
524
  marker=None,
525
+ max_items=None,
522
526
  all_projects=False,
523
527
  name=self.snapshots[0].name,
524
528
  status=None,
@@ -545,6 +549,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
545
549
  self.volume_sdk_client.snapshots.assert_called_once_with(
546
550
  limit=None,
547
551
  marker=None,
552
+ max_items=None,
548
553
  all_projects=False,
549
554
  name=None,
550
555
  status='available',
@@ -571,6 +576,7 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
571
576
  self.volume_sdk_client.snapshots.assert_called_once_with(
572
577
  limit=None,
573
578
  marker=None,
579
+ max_items=None,
574
580
  all_projects=False,
575
581
  name=None,
576
582
  status=None,
@@ -102,7 +102,7 @@ class AttachmentsColumn(cliff_columns.FormattableColumn[list[Any]]):
102
102
  return msg
103
103
 
104
104
 
105
- def _format_volume(volume: _volume.Volume) -> dict[str, Any]:
105
+ def _format_volume(volume: _volume.Volume) -> dict[str, object]:
106
106
  # Some columns returned by openstacksdk should not be shown because they're
107
107
  # either irrelevant or duplicates
108
108
  ignored_columns = {
@@ -494,7 +494,9 @@ class ListVolume(command.Lister):
494
494
  default=False,
495
495
  help=_('List additional fields in output'),
496
496
  )
497
- pagination.add_marker_pagination_option_to_parser(parser)
497
+ pagination.add_marker_pagination_option_to_parser(
498
+ parser, include_max_items=False
499
+ )
498
500
  return parser
499
501
 
500
502
  def take_action(
@@ -322,6 +322,7 @@ class ListVolumeBackup(command.Lister):
322
322
  all_tenants=parsed_args.all_projects,
323
323
  marker=marker_backup_id,
324
324
  limit=parsed_args.limit,
325
+ max_items=parsed_args.max_items,
325
326
  )
326
327
 
327
328
  return (
@@ -404,9 +405,7 @@ class RestoreVolumeBackup(command.ShowOne):
404
405
  raise exceptions.CommandError(msg % parsed_args.volume)
405
406
 
406
407
  restore = volume_client.restore_backup(
407
- backup.id,
408
- volume_id=volume_id,
409
- name=volume_name,
408
+ backup.id, volume=volume_id, name=volume_name
410
409
  )
411
410
 
412
411
  data = utils.get_dict_properties(restore, columns)
@@ -66,7 +66,7 @@ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
66
66
  return volume
67
67
 
68
68
 
69
- def _format_snapshot(snapshot: _snapshot.Snapshot) -> dict[str, Any]:
69
+ def _format_snapshot(snapshot: _snapshot.Snapshot) -> dict[str, object]:
70
70
  # Some columns returned by openstacksdk should not be shown because they're
71
71
  # either irrelevant or duplicates
72
72
  ignored_columns = {
@@ -231,11 +231,9 @@ class DeleteVolumeSnapshot(command.Command):
231
231
  snapshot_id = volume_client.find_snapshot(
232
232
  snapshot, ignore_missing=False
233
233
  ).id
234
- # FIXME(stephenfin): This parameter is missing from sdk
235
- # https://review.opendev.org/c/openstack/openstacksdk/+/984529
236
234
  volume_client.delete_snapshot(
237
235
  snapshot_id,
238
- force=parsed_args.force, # type: ignore
236
+ force=parsed_args.force,
239
237
  )
240
238
  except Exception as e:
241
239
  result += 1
@@ -378,6 +376,7 @@ class ListVolumeSnapshot(command.Lister):
378
376
  data = volume_client.snapshots(
379
377
  marker=parsed_args.marker,
380
378
  limit=parsed_args.limit,
379
+ max_items=parsed_args.max_items,
381
380
  all_projects=all_projects,
382
381
  project_id=project_id,
383
382
  name=parsed_args.name,
@@ -0,0 +1,94 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+ # not use this file except in compliance with the License. You may obtain
4
+ # a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+ # License for the specific language governing permissions and limitations
12
+ # under the License.
13
+
14
+ """Volume v3 Backup action implementations"""
15
+
16
+ import argparse
17
+ import logging
18
+ from collections.abc import Iterable, Sequence
19
+ from typing import Any
20
+
21
+ from osc_lib import utils
22
+
23
+ from openstackclient import command
24
+ from openstackclient.i18n import _
25
+
26
+ LOG = logging.getLogger(__name__)
27
+
28
+
29
+ class ExportBackupRecord(command.ShowOne):
30
+ _description = _(
31
+ """Export volume backup details.
32
+
33
+ Backup information can be imported into a new service instance to be able to
34
+ restore."""
35
+ )
36
+
37
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
38
+ parser = super().get_parser(prog_name)
39
+ parser.add_argument(
40
+ "backup",
41
+ metavar="<backup>",
42
+ help=_("Backup to export (name or ID)"),
43
+ )
44
+ return parser
45
+
46
+ def take_action(
47
+ self, parsed_args: argparse.Namespace
48
+ ) -> tuple[Sequence[str], Iterable[Any]]:
49
+ volume_client = self.app.client_manager.volume
50
+ backup = utils.find_resource(volume_client.backups, parsed_args.backup)
51
+ backup_data = volume_client.backups.export_record(backup.id)
52
+
53
+ # We only want to show "friendly" display names, but also want to keep
54
+ # json structure compatibility with cinderclient
55
+ if parsed_args.formatter == 'table':
56
+ backup_data['Backup Service'] = backup_data.pop('backup_service')
57
+ backup_data['Metadata'] = backup_data.pop('backup_url')
58
+
59
+ col_headers, col_data = zip(*sorted(backup_data.items()))
60
+ return col_headers, col_data
61
+
62
+
63
+ class ImportBackupRecord(command.ShowOne):
64
+ _description = _(
65
+ """Import volume backup details.
66
+
67
+ Exported backup details contain the metadata necessary to restore to a new or
68
+ rebuilt service instance"""
69
+ )
70
+
71
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
72
+ parser = super().get_parser(prog_name)
73
+ parser.add_argument(
74
+ "backup_service",
75
+ metavar="<backup_service>",
76
+ help=_("Backup service containing the backup."),
77
+ )
78
+ parser.add_argument(
79
+ "backup_metadata",
80
+ metavar="<backup_metadata>",
81
+ help=_("Encoded backup metadata from export."),
82
+ )
83
+ return parser
84
+
85
+ def take_action(
86
+ self, parsed_args: argparse.Namespace
87
+ ) -> tuple[Sequence[str], Iterable[Any]]:
88
+ volume_client = self.app.client_manager.volume
89
+ backup_data = volume_client.backups.import_record(
90
+ parsed_args.backup_service, parsed_args.backup_metadata
91
+ )
92
+ backup_data.pop('links', None)
93
+ col_headers, col_data = zip(*sorted(backup_data.items()))
94
+ return col_headers, col_data