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.
- openstackclient/__init__.py +2 -6
- openstackclient/api/api.py +41 -23
- openstackclient/api/compute_v2.py +44 -25
- openstackclient/api/object_store_v1.py +75 -97
- openstackclient/api/volume_v2.py +2 -1
- openstackclient/api/volume_v3.py +2 -1
- openstackclient/common/availability_zone.py +58 -42
- openstackclient/common/clientmanager.py +56 -29
- openstackclient/common/configuration.py +10 -3
- openstackclient/common/envvars.py +2 -2
- openstackclient/common/extension.py +14 -5
- openstackclient/common/limits.py +10 -5
- openstackclient/common/module.py +14 -6
- openstackclient/common/pagination.py +8 -2
- openstackclient/common/progressbar.py +7 -6
- openstackclient/common/project_cleanup.py +13 -7
- openstackclient/common/quota.py +126 -114
- openstackclient/common/versions.py +8 -2
- openstackclient/compute/client.py +7 -3
- openstackclient/compute/v2/agent.py +17 -10
- openstackclient/compute/v2/aggregate.py +36 -22
- openstackclient/compute/v2/console.py +14 -8
- openstackclient/compute/v2/console_connection.py +11 -3
- openstackclient/compute/v2/flavor.py +39 -21
- openstackclient/compute/v2/host.py +14 -6
- openstackclient/compute/v2/hypervisor.py +14 -5
- openstackclient/compute/v2/hypervisor_stats.py +10 -2
- openstackclient/compute/v2/keypair.py +29 -14
- openstackclient/compute/v2/server.py +251 -171
- openstackclient/compute/v2/server_backup.py +10 -4
- openstackclient/compute/v2/server_event.py +21 -12
- openstackclient/compute/v2/server_group.py +21 -11
- openstackclient/compute/v2/server_image.py +19 -10
- openstackclient/compute/v2/server_migration.py +24 -10
- openstackclient/compute/v2/server_share.py +274 -0
- openstackclient/compute/v2/server_volume.py +10 -4
- openstackclient/compute/v2/service.py +14 -7
- openstackclient/compute/v2/usage.py +26 -21
- openstackclient/identity/client.py +8 -3
- openstackclient/identity/common.py +103 -41
- openstackclient/identity/v2_0/catalog.py +14 -7
- openstackclient/identity/v2_0/ec2creds.py +21 -10
- openstackclient/identity/v2_0/endpoint.py +23 -11
- openstackclient/identity/v2_0/project.py +25 -14
- openstackclient/identity/v2_0/role.py +28 -14
- openstackclient/identity/v2_0/role_assignment.py +9 -3
- openstackclient/identity/v2_0/service.py +26 -12
- openstackclient/identity/v2_0/token.py +12 -5
- openstackclient/identity/v2_0/user.py +26 -15
- openstackclient/identity/v3/access_rule.py +26 -12
- openstackclient/identity/v3/application_credential.py +59 -24
- openstackclient/identity/v3/catalog.py +14 -7
- openstackclient/identity/v3/consumer.py +22 -11
- openstackclient/identity/v3/credential.py +36 -16
- openstackclient/identity/v3/domain.py +37 -18
- openstackclient/identity/v3/ec2creds.py +25 -12
- openstackclient/identity/v3/endpoint.py +42 -20
- openstackclient/identity/v3/endpoint_group.py +28 -17
- openstackclient/identity/v3/federation_protocol.py +71 -50
- openstackclient/identity/v3/group.py +55 -32
- openstackclient/identity/v3/identity_provider.py +92 -57
- openstackclient/identity/v3/implied_role.py +21 -9
- openstackclient/identity/v3/limit.py +115 -92
- openstackclient/identity/v3/mapping.py +26 -13
- openstackclient/identity/v3/policy.py +23 -12
- openstackclient/identity/v3/project.py +211 -122
- openstackclient/identity/v3/region.py +36 -16
- openstackclient/identity/v3/registered_limit.py +116 -109
- openstackclient/identity/v3/role.py +61 -31
- openstackclient/identity/v3/role_assignment.py +23 -6
- openstackclient/identity/v3/service.py +36 -16
- openstackclient/identity/v3/service_provider.py +37 -15
- openstackclient/identity/v3/tag.py +23 -17
- openstackclient/identity/v3/token.py +30 -14
- openstackclient/identity/v3/trust.py +32 -14
- openstackclient/identity/v3/unscoped_saml.py +10 -2
- openstackclient/identity/v3/user.py +49 -26
- openstackclient/image/client.py +7 -3
- openstackclient/image/v1/image.py +33 -26
- openstackclient/image/v2/cache.py +14 -9
- openstackclient/image/v2/image.py +76 -49
- openstackclient/image/v2/info.py +7 -1
- openstackclient/image/v2/metadef_namespaces.py +109 -13
- openstackclient/image/v2/metadef_objects.py +28 -15
- openstackclient/image/v2/metadef_properties.py +24 -13
- openstackclient/image/v2/metadef_resource_type_association.py +14 -7
- openstackclient/image/v2/metadef_resource_types.py +7 -1
- openstackclient/image/v2/task.py +15 -6
- openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +7 -192
- openstackclient/network/client.py +7 -2
- openstackclient/network/common.py +16 -241
- openstackclient/network/utils.py +36 -22
- openstackclient/network/v2/address_group.py +27 -16
- openstackclient/network/v2/address_scope.py +24 -13
- openstackclient/network/v2/bgpvpn/bgpvpn.py +463 -0
- openstackclient/network/v2/bgpvpn/constants.py +30 -0
- openstackclient/network/v2/bgpvpn/network_association.py +214 -0
- openstackclient/network/v2/bgpvpn/port_association.py +490 -0
- openstackclient/network/v2/bgpvpn/router_association.py +288 -0
- openstackclient/network/v2/default_security_group_rule.py +19 -10
- openstackclient/network/v2/floating_ip.py +110 -159
- openstackclient/network/v2/floating_ip_port_forwarding.py +30 -18
- openstackclient/network/v2/fwaas/__init__.py +0 -0
- openstackclient/network/v2/fwaas/group.py +466 -0
- openstackclient/network/v2/fwaas/policy.py +518 -0
- openstackclient/network/v2/fwaas/rule.py +574 -0
- openstackclient/network/v2/ip_availability.py +13 -5
- openstackclient/network/v2/l3_conntrack_helper.py +22 -13
- openstackclient/network/v2/local_ip.py +24 -13
- openstackclient/network/v2/local_ip_association.py +14 -7
- openstackclient/network/v2/ndp_proxy.py +20 -11
- openstackclient/network/v2/network.py +129 -196
- openstackclient/network/v2/network_agent.py +46 -25
- openstackclient/network/v2/network_auto_allocated_topology.py +22 -11
- openstackclient/network/v2/network_flavor.py +27 -16
- openstackclient/network/v2/network_flavor_profile.py +23 -12
- openstackclient/network/v2/network_meter.py +21 -10
- openstackclient/network/v2/network_meter_rule.py +21 -11
- openstackclient/network/v2/network_qos_policy.py +25 -15
- openstackclient/network/v2/network_qos_rule.py +32 -17
- openstackclient/network/v2/network_qos_rule_type.py +13 -5
- openstackclient/network/v2/network_rbac.py +23 -12
- openstackclient/network/v2/network_segment.py +20 -11
- openstackclient/network/v2/network_segment_range.py +56 -29
- openstackclient/network/v2/network_service_provider.py +7 -1
- openstackclient/network/v2/network_trunk.py +38 -22
- openstackclient/network/v2/port.py +54 -29
- openstackclient/network/v2/router.py +75 -52
- openstackclient/network/v2/security_group.py +87 -157
- openstackclient/network/v2/security_group_rule.py +100 -280
- openstackclient/network/v2/subnet.py +49 -28
- openstackclient/network/v2/subnet_pool.py +30 -17
- openstackclient/network/v2/taas/tap_flow.py +22 -11
- openstackclient/network/v2/taas/tap_mirror.py +22 -11
- openstackclient/network/v2/taas/tap_service.py +23 -12
- openstackclient/object/client.py +7 -2
- openstackclient/object/v1/account.py +13 -6
- openstackclient/object/v1/container.py +25 -15
- openstackclient/object/v1/object.py +25 -15
- openstackclient/py.typed +0 -0
- openstackclient/shell.py +46 -10
- openstackclient/tests/functional/base.py +55 -20
- openstackclient/tests/functional/common/test_extension.py +4 -0
- openstackclient/tests/functional/common/test_quota.py +3 -1
- openstackclient/tests/functional/compute/v2/common.py +14 -13
- openstackclient/tests/functional/compute/v2/test_flavor.py +3 -1
- openstackclient/tests/functional/compute/v2/test_server.py +3 -0
- openstackclient/tests/functional/identity/v2/common.py +10 -6
- openstackclient/tests/functional/identity/v2/test_role.py +4 -4
- openstackclient/tests/functional/identity/v3/common.py +25 -19
- openstackclient/tests/functional/identity/v3/test_group.py +20 -20
- openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
- openstackclient/tests/functional/identity/v3/test_limit.py +47 -0
- openstackclient/tests/functional/identity/v3/test_project.py +10 -10
- openstackclient/tests/functional/identity/v3/test_role.py +18 -18
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
- openstackclient/tests/functional/identity/v3/test_user.py +8 -8
- openstackclient/tests/functional/image/base.py +1 -6
- openstackclient/tests/functional/image/v2/test_metadef_objects.py +69 -0
- openstackclient/tests/functional/network/v2/common.py +5 -2
- openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
- openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
- openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
- openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
- openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
- openstackclient/tests/functional/object/v1/common.py +4 -0
- openstackclient/tests/functional/volume/v2/common.py +4 -0
- openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
- openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
- openstackclient/tests/functional/volume/v3/common.py +4 -0
- openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +56 -138
- openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
- openstackclient/tests/unit/common/test_availability_zone.py +35 -49
- openstackclient/tests/unit/common/test_extension.py +2 -2
- openstackclient/tests/unit/common/test_module.py +12 -7
- openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
- openstackclient/tests/unit/common/test_quota.py +62 -23
- openstackclient/tests/unit/compute/v2/fakes.py +25 -0
- openstackclient/tests/unit/compute/v2/test_flavor.py +28 -2
- openstackclient/tests/unit/compute/v2/test_keypair.py +6 -6
- openstackclient/tests/unit/compute/v2/test_server.py +17 -104
- openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
- openstackclient/tests/unit/identity/v3/fakes.py +3 -0
- openstackclient/tests/unit/identity/v3/test_group.py +4 -14
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
- openstackclient/tests/unit/identity/v3/test_limit.py +197 -145
- openstackclient/tests/unit/identity/v3/test_project.py +831 -512
- openstackclient/tests/unit/identity/v3/test_protocol.py +97 -88
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +355 -220
- openstackclient/tests/unit/identity/v3/test_user.py +4 -4
- openstackclient/tests/unit/image/v2/test_image.py +16 -16
- openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
- openstackclient/tests/unit/network/test_common.py +0 -155
- openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
- openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
- openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/fwaas/test_group.py +897 -0
- openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
- openstackclient/tests/unit/network/v2/fwaas/test_rule.py +980 -0
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
- openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
- openstackclient/tests/unit/network/v2/test_address_group.py +2 -2
- openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +3 -2
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +13 -13
- openstackclient/tests/unit/network/v2/test_network_agent.py +8 -4
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
- openstackclient/tests/unit/network/v2/test_network_flavor.py +2 -2
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
- openstackclient/tests/unit/network/v2/test_network_rbac.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_segment.py +1 -1
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +7 -10
- openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
- openstackclient/tests/unit/network/v2/test_router.py +8 -9
- openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +1 -20
- openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +7 -41
- openstackclient/tests/unit/network/v2/test_subnet.py +2 -1
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +2 -1
- openstackclient/tests/unit/object/v1/fakes.py +8 -7
- openstackclient/tests/unit/object/v1/test_container.py +65 -101
- openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
- openstackclient/tests/unit/object/v1/test_object.py +44 -84
- openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
- openstackclient/tests/unit/test_hacking.py +108 -0
- openstackclient/tests/unit/volume/v2/fakes.py +1 -0
- openstackclient/tests/unit/volume/v2/test_consistency_group.py +8 -2
- openstackclient/tests/unit/volume/v2/test_volume.py +7 -6
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +1 -5
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +2 -1
- openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
- openstackclient/tests/unit/volume/v3/fakes.py +1 -0
- openstackclient/tests/unit/volume/v3/test_volume.py +94 -15
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +1 -5
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +55 -1
- openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
- openstackclient/volume/client.py +7 -3
- openstackclient/volume/v2/backup_record.py +15 -6
- openstackclient/volume/v2/consistency_group.py +37 -25
- openstackclient/volume/v2/consistency_group_snapshot.py +27 -12
- openstackclient/volume/v2/qos_specs.py +30 -19
- openstackclient/volume/v2/service.py +17 -6
- openstackclient/volume/v2/volume.py +69 -34
- openstackclient/volume/v2/volume_backend.py +19 -6
- openstackclient/volume/v2/volume_backup.py +48 -22
- openstackclient/volume/v2/volume_host.py +6 -4
- openstackclient/volume/v2/volume_snapshot.py +52 -26
- openstackclient/volume/v2/volume_transfer_request.py +33 -15
- openstackclient/volume/v2/volume_type.py +46 -27
- openstackclient/volume/v3/block_storage_cleanup.py +11 -3
- openstackclient/volume/v3/block_storage_cluster.py +19 -7
- openstackclient/volume/v3/block_storage_log_level.py +15 -6
- openstackclient/volume/v3/block_storage_manage.py +10 -4
- openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
- openstackclient/volume/v3/service.py +16 -6
- openstackclient/volume/v3/volume.py +103 -46
- openstackclient/volume/v3/volume_attachment.py +43 -21
- openstackclient/volume/v3/volume_backup.py +55 -26
- openstackclient/volume/v3/volume_group.py +23 -13
- openstackclient/volume/v3/volume_group_snapshot.py +32 -13
- openstackclient/volume/v3/volume_group_type.py +26 -13
- openstackclient/volume/v3/volume_message.py +15 -7
- openstackclient/volume/v3/volume_snapshot.py +71 -34
- openstackclient/volume/v3/volume_transfer_request.py +33 -15
- openstackclient/volume/v3/volume_type.py +45 -27
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/METADATA +6 -6
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/RECORD +279 -267
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/WHEEL +1 -1
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/entry_points.txt +53 -1
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/AUTHORS +9 -0
- python_openstackclient-10.0.0.dist-info/pbr.json +1 -0
- openstackclient/api/image_v1.py +0 -69
- openstackclient/api/image_v2.py +0 -79
- openstackclient/network/v2/floating_ip_pool.py +0 -38
- openstackclient/tests/functional/image/v1/test_image.py +0 -97
- openstackclient/tests/unit/api/test_image_v1.py +0 -96
- openstackclient/tests/unit/api/test_image_v2.py +0 -96
- openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
- openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
- openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
- python_openstackclient-8.3.0.dist-info/pbr.json +0 -1
- /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/LICENSE +0 -0
- {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/top_level.txt +0 -0
|
@@ -912,7 +912,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
912
912
|
arglist = [self.volumes[0].id]
|
|
913
913
|
verifylist = [
|
|
914
914
|
("force", False),
|
|
915
|
-
("
|
|
915
|
+
("cascade", False),
|
|
916
916
|
("volumes", [self.volumes[0].id]),
|
|
917
917
|
]
|
|
918
918
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -931,7 +931,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
931
931
|
arglist = [v.id for v in self.volumes]
|
|
932
932
|
verifylist = [
|
|
933
933
|
('force', False),
|
|
934
|
-
('
|
|
934
|
+
('cascade', False),
|
|
935
935
|
('volumes', arglist),
|
|
936
936
|
]
|
|
937
937
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -958,7 +958,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
958
958
|
]
|
|
959
959
|
verifylist = [
|
|
960
960
|
('force', False),
|
|
961
|
-
('
|
|
961
|
+
('cascade', False),
|
|
962
962
|
('volumes', [self.volumes[0].id, 'unexist_volume']),
|
|
963
963
|
]
|
|
964
964
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -989,7 +989,29 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
989
989
|
]
|
|
990
990
|
verifylist = [
|
|
991
991
|
('force', False),
|
|
992
|
-
('
|
|
992
|
+
('cascade', True),
|
|
993
|
+
('volumes', [self.volumes[0].id]),
|
|
994
|
+
]
|
|
995
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
996
|
+
|
|
997
|
+
result = self.cmd.take_action(parsed_args)
|
|
998
|
+
self.assertIsNone(result)
|
|
999
|
+
|
|
1000
|
+
self.volume_sdk_client.find_volume.assert_called_once_with(
|
|
1001
|
+
self.volumes[0].id, ignore_missing=False
|
|
1002
|
+
)
|
|
1003
|
+
self.volume_sdk_client.delete_volume.assert_called_once_with(
|
|
1004
|
+
self.volumes[0].id, cascade=True, force=False
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
def test_volume_delete_with_cascade(self):
|
|
1008
|
+
arglist = [
|
|
1009
|
+
'--cascade',
|
|
1010
|
+
self.volumes[0].id,
|
|
1011
|
+
]
|
|
1012
|
+
verifylist = [
|
|
1013
|
+
('force', False),
|
|
1014
|
+
('cascade', True),
|
|
993
1015
|
('volumes', [self.volumes[0].id]),
|
|
994
1016
|
]
|
|
995
1017
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -1011,7 +1033,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1011
1033
|
]
|
|
1012
1034
|
verifylist = [
|
|
1013
1035
|
('force', True),
|
|
1014
|
-
('
|
|
1036
|
+
('cascade', False),
|
|
1015
1037
|
('volumes', [self.volumes[0].id]),
|
|
1016
1038
|
]
|
|
1017
1039
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -1031,7 +1053,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1031
1053
|
verifylist = [
|
|
1032
1054
|
("remote", True),
|
|
1033
1055
|
("force", False),
|
|
1034
|
-
("
|
|
1056
|
+
("cascade", False),
|
|
1035
1057
|
("volumes", [self.volumes[0].id]),
|
|
1036
1058
|
]
|
|
1037
1059
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -1052,7 +1074,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1052
1074
|
verifylist = [
|
|
1053
1075
|
('remote', True),
|
|
1054
1076
|
('force', False),
|
|
1055
|
-
('
|
|
1077
|
+
('cascade', False),
|
|
1056
1078
|
('volumes', arglist[1:]),
|
|
1057
1079
|
]
|
|
1058
1080
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
@@ -1077,7 +1099,6 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1077
1099
|
verifylist = [
|
|
1078
1100
|
('remote', True),
|
|
1079
1101
|
('force', False),
|
|
1080
|
-
('purge', True),
|
|
1081
1102
|
('volumes', [self.volumes[0].id]),
|
|
1082
1103
|
]
|
|
1083
1104
|
|
|
@@ -1086,7 +1107,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1086
1107
|
exceptions.CommandError, self.cmd.take_action, parsed_args
|
|
1087
1108
|
)
|
|
1088
1109
|
self.assertIn(
|
|
1089
|
-
"The --force and --
|
|
1110
|
+
"The --force and --cascade options are not supported with the "
|
|
1090
1111
|
"--remote parameter.",
|
|
1091
1112
|
str(exc),
|
|
1092
1113
|
)
|
|
@@ -1104,7 +1125,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1104
1125
|
verifylist = [
|
|
1105
1126
|
('remote', True),
|
|
1106
1127
|
('force', True),
|
|
1107
|
-
('
|
|
1128
|
+
('cascade', False),
|
|
1108
1129
|
('volumes', [self.volumes[0].id]),
|
|
1109
1130
|
]
|
|
1110
1131
|
|
|
@@ -1113,7 +1134,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
|
|
|
1113
1134
|
exceptions.CommandError, self.cmd.take_action, parsed_args
|
|
1114
1135
|
)
|
|
1115
1136
|
self.assertIn(
|
|
1116
|
-
"The --force and --
|
|
1137
|
+
"The --force and --cascade options are not supported with the "
|
|
1117
1138
|
"--remote parameter.",
|
|
1118
1139
|
str(exc),
|
|
1119
1140
|
)
|
|
@@ -1702,9 +1723,10 @@ class TestVolumeMigrate(volume_fakes.TestVolume):
|
|
|
1702
1723
|
host="host@backend-name#pool",
|
|
1703
1724
|
force_host_copy=False,
|
|
1704
1725
|
lock_volume=False,
|
|
1726
|
+
cluster=None,
|
|
1705
1727
|
)
|
|
1706
1728
|
|
|
1707
|
-
def
|
|
1729
|
+
def test_volume_migrate_with_host(self):
|
|
1708
1730
|
arglist = [
|
|
1709
1731
|
"--force-host-copy",
|
|
1710
1732
|
"--lock-volume",
|
|
@@ -1731,9 +1753,66 @@ class TestVolumeMigrate(volume_fakes.TestVolume):
|
|
|
1731
1753
|
host="host@backend-name#pool",
|
|
1732
1754
|
force_host_copy=True,
|
|
1733
1755
|
lock_volume=True,
|
|
1756
|
+
cluster=None,
|
|
1734
1757
|
)
|
|
1735
1758
|
|
|
1736
|
-
def
|
|
1759
|
+
def test_volume_migrate_with_cluster(self):
|
|
1760
|
+
self.set_volume_api_version('3.16')
|
|
1761
|
+
arglist = [
|
|
1762
|
+
"--cluster",
|
|
1763
|
+
"cluster@backend-name#pool",
|
|
1764
|
+
self.volume.id,
|
|
1765
|
+
]
|
|
1766
|
+
verifylist = [
|
|
1767
|
+
(
|
|
1768
|
+
"cluster",
|
|
1769
|
+
"cluster@backend-name#pool",
|
|
1770
|
+
),
|
|
1771
|
+
("volume", self.volume.id),
|
|
1772
|
+
]
|
|
1773
|
+
|
|
1774
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
1775
|
+
|
|
1776
|
+
result = self.cmd.take_action(parsed_args)
|
|
1777
|
+
self.assertIsNone(result)
|
|
1778
|
+
|
|
1779
|
+
self.volume_sdk_client.find_volume.assert_called_with(
|
|
1780
|
+
self.volume.id, ignore_missing=False
|
|
1781
|
+
)
|
|
1782
|
+
self.volume_sdk_client.migrate_volume.assert_called_once_with(
|
|
1783
|
+
self.volume.id,
|
|
1784
|
+
host=None,
|
|
1785
|
+
force_host_copy=False,
|
|
1786
|
+
lock_volume=False,
|
|
1787
|
+
cluster="cluster@backend-name#pool",
|
|
1788
|
+
)
|
|
1789
|
+
|
|
1790
|
+
def test_volume_migrate_with_cluster_pre_v316(self):
|
|
1791
|
+
self.set_volume_api_version('3.15')
|
|
1792
|
+
arglist = [
|
|
1793
|
+
"--cluster",
|
|
1794
|
+
"cluster@backend-name#pool",
|
|
1795
|
+
self.volume.id,
|
|
1796
|
+
]
|
|
1797
|
+
verifylist = [
|
|
1798
|
+
(
|
|
1799
|
+
"cluster",
|
|
1800
|
+
"cluster@backend-name#pool",
|
|
1801
|
+
),
|
|
1802
|
+
("volume", self.volume.id),
|
|
1803
|
+
]
|
|
1804
|
+
|
|
1805
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
1806
|
+
|
|
1807
|
+
self.assertRaises(
|
|
1808
|
+
exceptions.CommandError,
|
|
1809
|
+
self.cmd.take_action,
|
|
1810
|
+
parsed_args,
|
|
1811
|
+
)
|
|
1812
|
+
|
|
1813
|
+
self.volume_sdk_client.migrate_volume.assert_not_called()
|
|
1814
|
+
|
|
1815
|
+
def test_volume_migrate_without_host_and_cluster(self):
|
|
1737
1816
|
arglist = [
|
|
1738
1817
|
self.volume.id,
|
|
1739
1818
|
]
|
|
@@ -1750,7 +1829,6 @@ class TestVolumeMigrate(volume_fakes.TestVolume):
|
|
|
1750
1829
|
arglist,
|
|
1751
1830
|
verifylist,
|
|
1752
1831
|
)
|
|
1753
|
-
|
|
1754
1832
|
self.volume_sdk_client.find_volume.assert_not_called()
|
|
1755
1833
|
self.volume_sdk_client.migrate_volume.assert_not_called()
|
|
1756
1834
|
|
|
@@ -1998,7 +2076,8 @@ class TestVolumeSet(volume_fakes.TestVolume):
|
|
|
1998
2076
|
result = self.cmd.take_action(parsed_args)
|
|
1999
2077
|
self.volumes_mock.retype.assert_not_called()
|
|
2000
2078
|
mock_warning.assert_called_with(
|
|
2001
|
-
"'
|
|
2079
|
+
"'%s' option will not work without '--type' option",
|
|
2080
|
+
'--retype-policy',
|
|
2002
2081
|
)
|
|
2003
2082
|
self.assertIsNone(result)
|
|
2004
2083
|
|
|
@@ -23,7 +23,7 @@ class TestVolumeAttachment(volume_fakes.TestVolume):
|
|
|
23
23
|
def setUp(self):
|
|
24
24
|
super().setUp()
|
|
25
25
|
|
|
26
|
-
self.projects_mock = self.
|
|
26
|
+
self.projects_mock = self.identity_client.projects
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class TestVolumeAttachmentCreate(TestVolumeAttachment):
|
|
@@ -319,11 +319,7 @@ class TestBackupList(volume_fakes.TestVolume):
|
|
|
319
319
|
'Incremental',
|
|
320
320
|
'Created At',
|
|
321
321
|
)
|
|
322
|
-
columns_long = columns
|
|
323
|
-
'Availability Zone',
|
|
324
|
-
'Volume',
|
|
325
|
-
'Container',
|
|
326
|
-
)
|
|
322
|
+
columns_long = (*columns, 'Availability Zone', 'Volume', 'Container')
|
|
327
323
|
|
|
328
324
|
def setUp(self):
|
|
329
325
|
super().setUp()
|
|
@@ -180,6 +180,59 @@ class TestVolumeSnapshotCreate(volume_fakes.TestVolume):
|
|
|
180
180
|
)
|
|
181
181
|
self.volume_sdk_client.create_snapshot.assert_not_called()
|
|
182
182
|
|
|
183
|
+
def test_snapshot_create_pre_v366(self):
|
|
184
|
+
self.set_volume_api_version('3.65')
|
|
185
|
+
|
|
186
|
+
arglist = ["--force", self.snapshot.name]
|
|
187
|
+
verifylist = [("force", True), ("snapshot_name", self.snapshot.name)]
|
|
188
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
189
|
+
|
|
190
|
+
self.cmd.take_action(parsed_args)
|
|
191
|
+
|
|
192
|
+
# force parameter should be passed
|
|
193
|
+
self.volume_sdk_client.create_snapshot.assert_called_with(
|
|
194
|
+
volume_id=self.snapshot.volume_id,
|
|
195
|
+
force=True,
|
|
196
|
+
name=self.snapshot.name,
|
|
197
|
+
description=None,
|
|
198
|
+
metadata=None,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def test_snapshot_create_v366_or_later(self):
|
|
202
|
+
self.set_volume_api_version('3.66')
|
|
203
|
+
|
|
204
|
+
arglist = [self.snapshot.name]
|
|
205
|
+
verifylist = [("force", False), ("snapshot_name", self.snapshot.name)]
|
|
206
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
207
|
+
|
|
208
|
+
self.cmd.take_action(parsed_args)
|
|
209
|
+
|
|
210
|
+
# force parameter should not be passed, for >=3.66
|
|
211
|
+
self.volume_sdk_client.create_snapshot.assert_called_with(
|
|
212
|
+
volume_id=self.snapshot.volume_id,
|
|
213
|
+
name=self.snapshot.name,
|
|
214
|
+
description=None,
|
|
215
|
+
metadata=None,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
def test_snapshot_create_v366_or_later_with_force(self):
|
|
219
|
+
"""--force should be ignored for microversion >= 3.66."""
|
|
220
|
+
self.set_volume_api_version('3.66')
|
|
221
|
+
|
|
222
|
+
arglist = ["--force", self.snapshot.name]
|
|
223
|
+
verifylist = [("force", True), ("snapshot_name", self.snapshot.name)]
|
|
224
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
225
|
+
|
|
226
|
+
self.cmd.take_action(parsed_args)
|
|
227
|
+
|
|
228
|
+
# passed but ignored
|
|
229
|
+
self.volume_sdk_client.create_snapshot.assert_called_with(
|
|
230
|
+
volume_id=self.snapshot.volume_id,
|
|
231
|
+
name=self.snapshot.name,
|
|
232
|
+
description=None,
|
|
233
|
+
metadata=None,
|
|
234
|
+
)
|
|
235
|
+
|
|
183
236
|
|
|
184
237
|
class TestVolumeSnapshotDelete(volume_fakes.TestVolume):
|
|
185
238
|
def setUp(self):
|
|
@@ -340,7 +393,8 @@ class TestVolumeSnapshotList(volume_fakes.TestVolume):
|
|
|
340
393
|
self.project_mock.get.return_value = self.project
|
|
341
394
|
|
|
342
395
|
self.columns = ("ID", "Name", "Description", "Status", "Size")
|
|
343
|
-
self.columns_long =
|
|
396
|
+
self.columns_long = (
|
|
397
|
+
*self.columns,
|
|
344
398
|
"Created At",
|
|
345
399
|
"Volume",
|
|
346
400
|
"Properties",
|
|
@@ -331,7 +331,7 @@ class TestTypeList(TestType):
|
|
|
331
331
|
"Name",
|
|
332
332
|
"Is Public",
|
|
333
333
|
]
|
|
334
|
-
columns_long = columns
|
|
334
|
+
columns_long = [*columns, "Description", "Properties"]
|
|
335
335
|
data_with_default_type = [(volume_types[0].id, volume_types[0].name, True)]
|
|
336
336
|
data = []
|
|
337
337
|
for t in volume_types:
|
|
@@ -509,9 +509,7 @@ class TestTypeList(TestType):
|
|
|
509
509
|
'key_size': None,
|
|
510
510
|
'control_location': 'front-end',
|
|
511
511
|
}
|
|
512
|
-
encryption_columns = self.columns
|
|
513
|
-
"Encryption",
|
|
514
|
-
]
|
|
512
|
+
encryption_columns = [*self.columns, "Encryption"]
|
|
515
513
|
encryption_data = []
|
|
516
514
|
encryption_data.append(
|
|
517
515
|
(
|
openstackclient/volume/client.py
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
# under the License.
|
|
14
14
|
#
|
|
15
15
|
|
|
16
|
+
import argparse
|
|
16
17
|
import logging
|
|
18
|
+
from typing import Any
|
|
17
19
|
|
|
18
20
|
from osc_lib import exceptions
|
|
19
21
|
from osc_lib import utils
|
|
@@ -34,7 +36,7 @@ API_VERSIONS = {
|
|
|
34
36
|
_volume_api_version = None
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def make_client(instance):
|
|
39
|
+
def make_client(instance: Any) -> Any:
|
|
38
40
|
"""Returns a volume service client."""
|
|
39
41
|
|
|
40
42
|
# Defer client imports until we actually need them
|
|
@@ -92,7 +94,9 @@ def make_client(instance):
|
|
|
92
94
|
return client
|
|
93
95
|
|
|
94
96
|
|
|
95
|
-
def build_option_parser(
|
|
97
|
+
def build_option_parser(
|
|
98
|
+
parser: argparse.ArgumentParser,
|
|
99
|
+
) -> argparse.ArgumentParser:
|
|
96
100
|
"""Hook to add global options"""
|
|
97
101
|
parser.add_argument(
|
|
98
102
|
'--os-volume-api-version',
|
|
@@ -104,7 +108,7 @@ def build_option_parser(parser):
|
|
|
104
108
|
return parser
|
|
105
109
|
|
|
106
110
|
|
|
107
|
-
def check_api_version(check_version):
|
|
111
|
+
def check_api_version(check_version: str) -> bool:
|
|
108
112
|
"""Validate version supplied by user
|
|
109
113
|
|
|
110
114
|
Returns:
|
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
"""Volume v2 Backup action implementations"""
|
|
16
16
|
|
|
17
|
+
import argparse
|
|
17
18
|
import logging
|
|
19
|
+
from collections.abc import Iterable, Sequence
|
|
20
|
+
from typing import Any
|
|
18
21
|
|
|
19
22
|
from osc_lib import utils
|
|
20
23
|
|
|
@@ -33,7 +36,7 @@ Backup information can be imported into a new service instance to be able to
|
|
|
33
36
|
restore."""
|
|
34
37
|
)
|
|
35
38
|
|
|
36
|
-
def get_parser(self, prog_name):
|
|
39
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
37
40
|
parser = super().get_parser(prog_name)
|
|
38
41
|
parser.add_argument(
|
|
39
42
|
"backup",
|
|
@@ -42,7 +45,9 @@ restore."""
|
|
|
42
45
|
)
|
|
43
46
|
return parser
|
|
44
47
|
|
|
45
|
-
def take_action(
|
|
48
|
+
def take_action(
|
|
49
|
+
self, parsed_args: argparse.Namespace
|
|
50
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
46
51
|
volume_client = self.app.client_manager.volume
|
|
47
52
|
backup = utils.find_resource(volume_client.backups, parsed_args.backup)
|
|
48
53
|
backup_data = volume_client.backups.export_record(backup.id)
|
|
@@ -53,7 +58,8 @@ restore."""
|
|
|
53
58
|
backup_data['Backup Service'] = backup_data.pop('backup_service')
|
|
54
59
|
backup_data['Metadata'] = backup_data.pop('backup_url')
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
col_headers, col_data = zip(*sorted(backup_data.items()))
|
|
62
|
+
return col_headers, col_data
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
class ImportBackupRecord(command.ShowOne):
|
|
@@ -64,7 +70,7 @@ Exported backup details contain the metadata necessary to restore to a new or
|
|
|
64
70
|
rebuilt service instance"""
|
|
65
71
|
)
|
|
66
72
|
|
|
67
|
-
def get_parser(self, prog_name):
|
|
73
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
68
74
|
parser = super().get_parser(prog_name)
|
|
69
75
|
parser.add_argument(
|
|
70
76
|
"backup_service",
|
|
@@ -78,10 +84,13 @@ rebuilt service instance"""
|
|
|
78
84
|
)
|
|
79
85
|
return parser
|
|
80
86
|
|
|
81
|
-
def take_action(
|
|
87
|
+
def take_action(
|
|
88
|
+
self, parsed_args: argparse.Namespace
|
|
89
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
82
90
|
volume_client = self.app.client_manager.volume
|
|
83
91
|
backup_data = volume_client.backups.import_record(
|
|
84
92
|
parsed_args.backup_service, parsed_args.backup_metadata
|
|
85
93
|
)
|
|
86
94
|
backup_data.pop('links', None)
|
|
87
|
-
|
|
95
|
+
col_headers, col_data = zip(*sorted(backup_data.items()))
|
|
96
|
+
return col_headers, col_data
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
import argparse
|
|
18
18
|
import logging
|
|
19
|
+
from collections.abc import Iterable, Sequence
|
|
20
|
+
from typing import Any
|
|
19
21
|
|
|
20
22
|
from osc_lib.cli import format_columns
|
|
21
23
|
from osc_lib import exceptions
|
|
@@ -28,7 +30,9 @@ from openstackclient.i18n import _
|
|
|
28
30
|
LOG = logging.getLogger(__name__)
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
def _find_volumes(
|
|
33
|
+
def _find_volumes(
|
|
34
|
+
parsed_args_volumes: list[str], volume_client: Any
|
|
35
|
+
) -> tuple[int, str]:
|
|
32
36
|
result = 0
|
|
33
37
|
uuid = ''
|
|
34
38
|
for volume in parsed_args_volumes:
|
|
@@ -38,8 +42,8 @@ def _find_volumes(parsed_args_volumes, volume_client):
|
|
|
38
42
|
except Exception as e:
|
|
39
43
|
result += 1
|
|
40
44
|
LOG.error(
|
|
41
|
-
_("Failed to find volume with name or ID '%(volume)s':%(e)s")
|
|
42
|
-
|
|
45
|
+
_("Failed to find volume with name or ID '%(volume)s':%(e)s"),
|
|
46
|
+
{'volume': volume, 'e': e},
|
|
43
47
|
)
|
|
44
48
|
|
|
45
49
|
return result, uuid
|
|
@@ -48,7 +52,7 @@ def _find_volumes(parsed_args_volumes, volume_client):
|
|
|
48
52
|
class AddVolumeToConsistencyGroup(command.Command):
|
|
49
53
|
_description = _("Add volume(s) to consistency group")
|
|
50
54
|
|
|
51
|
-
def get_parser(self, prog_name):
|
|
55
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
52
56
|
parser = super().get_parser(prog_name)
|
|
53
57
|
parser.add_argument(
|
|
54
58
|
'consistency_group',
|
|
@@ -66,15 +70,15 @@ class AddVolumeToConsistencyGroup(command.Command):
|
|
|
66
70
|
)
|
|
67
71
|
return parser
|
|
68
72
|
|
|
69
|
-
def take_action(self, parsed_args):
|
|
73
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
70
74
|
volume_client = self.app.client_manager.volume
|
|
71
75
|
result, add_uuid = _find_volumes(parsed_args.volumes, volume_client)
|
|
72
76
|
|
|
73
77
|
if result > 0:
|
|
74
78
|
total = len(parsed_args.volumes)
|
|
75
79
|
LOG.error(
|
|
76
|
-
_("%(result)s of %(total)s volumes failed to add.")
|
|
77
|
-
|
|
80
|
+
_("%(result)s of %(total)s volumes failed to add."),
|
|
81
|
+
{'result': result, 'total': total},
|
|
78
82
|
)
|
|
79
83
|
|
|
80
84
|
if add_uuid:
|
|
@@ -90,7 +94,7 @@ class AddVolumeToConsistencyGroup(command.Command):
|
|
|
90
94
|
class CreateConsistencyGroup(command.ShowOne):
|
|
91
95
|
_description = _("Create new consistency group.")
|
|
92
96
|
|
|
93
|
-
def get_parser(self, prog_name):
|
|
97
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
94
98
|
parser = super().get_parser(prog_name)
|
|
95
99
|
parser.add_argument(
|
|
96
100
|
"name",
|
|
@@ -144,7 +148,9 @@ class CreateConsistencyGroup(command.ShowOne):
|
|
|
144
148
|
)
|
|
145
149
|
return parser
|
|
146
150
|
|
|
147
|
-
def take_action(
|
|
151
|
+
def take_action(
|
|
152
|
+
self, parsed_args: argparse.Namespace
|
|
153
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
148
154
|
volume_client = self.app.client_manager.volume
|
|
149
155
|
if parsed_args.volume_type:
|
|
150
156
|
volume_type_id = utils.find_resource(
|
|
@@ -186,13 +192,14 @@ class CreateConsistencyGroup(command.ShowOne):
|
|
|
186
192
|
)
|
|
187
193
|
)
|
|
188
194
|
|
|
189
|
-
|
|
195
|
+
col_headers, col_data = zip(*sorted(consistency_group._info.items()))
|
|
196
|
+
return col_headers, col_data
|
|
190
197
|
|
|
191
198
|
|
|
192
199
|
class DeleteConsistencyGroup(command.Command):
|
|
193
200
|
_description = _("Delete consistency group(s).")
|
|
194
201
|
|
|
195
|
-
def get_parser(self, prog_name):
|
|
202
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
196
203
|
parser = super().get_parser(prog_name)
|
|
197
204
|
parser.add_argument(
|
|
198
205
|
'consistency_groups',
|
|
@@ -208,7 +215,7 @@ class DeleteConsistencyGroup(command.Command):
|
|
|
208
215
|
)
|
|
209
216
|
return parser
|
|
210
217
|
|
|
211
|
-
def take_action(self, parsed_args):
|
|
218
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
212
219
|
volume_client = self.app.client_manager.volume
|
|
213
220
|
result = 0
|
|
214
221
|
|
|
@@ -226,8 +233,8 @@ class DeleteConsistencyGroup(command.Command):
|
|
|
226
233
|
_(
|
|
227
234
|
"Failed to delete consistency group with "
|
|
228
235
|
"name or ID '%(consistency_group)s':%(e)s"
|
|
229
|
-
)
|
|
230
|
-
|
|
236
|
+
),
|
|
237
|
+
{'consistency_group': i, 'e': e},
|
|
231
238
|
)
|
|
232
239
|
|
|
233
240
|
if result > 0:
|
|
@@ -241,7 +248,7 @@ class DeleteConsistencyGroup(command.Command):
|
|
|
241
248
|
class ListConsistencyGroup(command.Lister):
|
|
242
249
|
_description = _("List consistency groups.")
|
|
243
250
|
|
|
244
|
-
def get_parser(self, prog_name):
|
|
251
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
245
252
|
parser = super().get_parser(prog_name)
|
|
246
253
|
parser.add_argument(
|
|
247
254
|
'--all-projects',
|
|
@@ -258,7 +265,9 @@ class ListConsistencyGroup(command.Lister):
|
|
|
258
265
|
)
|
|
259
266
|
return parser
|
|
260
267
|
|
|
261
|
-
def take_action(
|
|
268
|
+
def take_action(
|
|
269
|
+
self, parsed_args: argparse.Namespace
|
|
270
|
+
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
|
|
262
271
|
if parsed_args.long:
|
|
263
272
|
columns = [
|
|
264
273
|
'ID',
|
|
@@ -292,7 +301,7 @@ class ListConsistencyGroup(command.Lister):
|
|
|
292
301
|
class RemoveVolumeFromConsistencyGroup(command.Command):
|
|
293
302
|
_description = _("Remove volume(s) from consistency group")
|
|
294
303
|
|
|
295
|
-
def get_parser(self, prog_name):
|
|
304
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
296
305
|
parser = super().get_parser(prog_name)
|
|
297
306
|
parser.add_argument(
|
|
298
307
|
'consistency_group',
|
|
@@ -310,15 +319,15 @@ class RemoveVolumeFromConsistencyGroup(command.Command):
|
|
|
310
319
|
)
|
|
311
320
|
return parser
|
|
312
321
|
|
|
313
|
-
def take_action(self, parsed_args):
|
|
322
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
314
323
|
volume_client = self.app.client_manager.volume
|
|
315
324
|
result, remove_uuid = _find_volumes(parsed_args.volumes, volume_client)
|
|
316
325
|
|
|
317
326
|
if result > 0:
|
|
318
327
|
total = len(parsed_args.volumes)
|
|
319
328
|
LOG.error(
|
|
320
|
-
_("%(result)s of %(total)s volumes failed to remove.")
|
|
321
|
-
|
|
329
|
+
_("%(result)s of %(total)s volumes failed to remove."),
|
|
330
|
+
{'result': result, 'total': total},
|
|
322
331
|
)
|
|
323
332
|
|
|
324
333
|
if remove_uuid:
|
|
@@ -334,7 +343,7 @@ class RemoveVolumeFromConsistencyGroup(command.Command):
|
|
|
334
343
|
class SetConsistencyGroup(command.Command):
|
|
335
344
|
_description = _("Set consistency group properties")
|
|
336
345
|
|
|
337
|
-
def get_parser(self, prog_name):
|
|
346
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
338
347
|
parser = super().get_parser(prog_name)
|
|
339
348
|
parser.add_argument(
|
|
340
349
|
'consistency_group',
|
|
@@ -353,7 +362,7 @@ class SetConsistencyGroup(command.Command):
|
|
|
353
362
|
)
|
|
354
363
|
return parser
|
|
355
364
|
|
|
356
|
-
def take_action(self, parsed_args):
|
|
365
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
357
366
|
volume_client = self.app.client_manager.volume
|
|
358
367
|
kwargs = {}
|
|
359
368
|
if parsed_args.name:
|
|
@@ -372,7 +381,7 @@ class SetConsistencyGroup(command.Command):
|
|
|
372
381
|
class ShowConsistencyGroup(command.ShowOne):
|
|
373
382
|
_description = _("Display consistency group details.")
|
|
374
383
|
|
|
375
|
-
def get_parser(self, prog_name):
|
|
384
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
376
385
|
parser = super().get_parser(prog_name)
|
|
377
386
|
parser.add_argument(
|
|
378
387
|
"consistency_group",
|
|
@@ -381,9 +390,12 @@ class ShowConsistencyGroup(command.ShowOne):
|
|
|
381
390
|
)
|
|
382
391
|
return parser
|
|
383
392
|
|
|
384
|
-
def take_action(
|
|
393
|
+
def take_action(
|
|
394
|
+
self, parsed_args: argparse.Namespace
|
|
395
|
+
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
385
396
|
volume_client = self.app.client_manager.volume
|
|
386
397
|
consistency_group = utils.find_resource(
|
|
387
398
|
volume_client.consistencygroups, parsed_args.consistency_group
|
|
388
399
|
)
|
|
389
|
-
|
|
400
|
+
col_headers, col_data = zip(*sorted(consistency_group._info.items()))
|
|
401
|
+
return col_headers, col_data
|