python-openstackclient 6.6.0__py3-none-any.whl → 7.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/api/api.py +7 -8
- openstackclient/api/compute_v2.py +352 -638
- openstackclient/api/image_v1.py +1 -1
- openstackclient/api/object_store_v1.py +3 -4
- openstackclient/common/availability_zone.py +1 -1
- openstackclient/common/clientmanager.py +16 -4
- openstackclient/common/configuration.py +1 -1
- openstackclient/common/extension.py +1 -1
- openstackclient/common/limits.py +66 -32
- openstackclient/common/module.py +3 -3
- openstackclient/common/progressbar.py +2 -2
- openstackclient/common/project_cleanup.py +5 -2
- openstackclient/common/quota.py +281 -410
- openstackclient/common/versions.py +1 -1
- openstackclient/compute/client.py +7 -116
- openstackclient/compute/v2/agent.py +75 -49
- openstackclient/compute/v2/aggregate.py +9 -9
- openstackclient/compute/v2/console.py +2 -2
- openstackclient/compute/v2/flavor.py +6 -6
- openstackclient/compute/v2/host.py +38 -33
- openstackclient/compute/v2/hypervisor.py +4 -3
- openstackclient/compute/v2/keypair.py +7 -8
- openstackclient/compute/v2/server.py +478 -396
- openstackclient/compute/v2/server_backup.py +1 -1
- openstackclient/compute/v2/server_group.py +4 -4
- openstackclient/compute/v2/server_image.py +1 -1
- openstackclient/compute/v2/server_migration.py +3 -4
- openstackclient/compute/v2/service.py +4 -4
- openstackclient/compute/v2/usage.py +3 -3
- openstackclient/identity/common.py +34 -0
- openstackclient/identity/v2_0/catalog.py +2 -2
- openstackclient/identity/v2_0/ec2creds.py +4 -4
- openstackclient/identity/v2_0/endpoint.py +4 -4
- openstackclient/identity/v2_0/project.py +6 -6
- openstackclient/identity/v2_0/role.py +5 -5
- openstackclient/identity/v2_0/role_assignment.py +1 -1
- openstackclient/identity/v2_0/service.py +4 -4
- openstackclient/identity/v2_0/token.py +2 -2
- openstackclient/identity/v2_0/user.py +7 -7
- openstackclient/identity/v3/access_rule.py +3 -3
- openstackclient/identity/v3/application_credential.py +127 -45
- openstackclient/identity/v3/catalog.py +2 -2
- openstackclient/identity/v3/consumer.py +4 -4
- openstackclient/identity/v3/credential.py +5 -5
- openstackclient/identity/v3/domain.py +5 -5
- openstackclient/identity/v3/ec2creds.py +4 -4
- openstackclient/identity/v3/endpoint.py +7 -7
- openstackclient/identity/v3/endpoint_group.py +8 -10
- openstackclient/identity/v3/federation_protocol.py +5 -5
- openstackclient/identity/v3/group.py +8 -8
- openstackclient/identity/v3/identity_provider.py +5 -5
- openstackclient/identity/v3/implied_role.py +3 -3
- openstackclient/identity/v3/limit.py +5 -5
- openstackclient/identity/v3/mapping.py +5 -5
- openstackclient/identity/v3/policy.py +5 -5
- openstackclient/identity/v3/project.py +5 -5
- openstackclient/identity/v3/region.py +5 -5
- openstackclient/identity/v3/registered_limit.py +5 -5
- openstackclient/identity/v3/role.py +7 -7
- openstackclient/identity/v3/role_assignment.py +92 -140
- openstackclient/identity/v3/service.py +64 -34
- openstackclient/identity/v3/service_provider.py +4 -4
- openstackclient/identity/v3/tag.py +2 -2
- openstackclient/identity/v3/token.py +5 -5
- openstackclient/identity/v3/trust.py +3 -3
- openstackclient/identity/v3/user.py +144 -80
- openstackclient/image/client.py +4 -4
- openstackclient/image/v1/image.py +8 -9
- openstackclient/image/v2/cache.py +12 -10
- openstackclient/image/v2/metadef_objects.py +44 -0
- openstackclient/image/v2/metadef_resource_type_association.py +189 -0
- openstackclient/image/v2/task.py +1 -1
- openstackclient/network/common.py +6 -5
- openstackclient/network/utils.py +2 -2
- openstackclient/network/v2/address_group.py +6 -6
- openstackclient/network/v2/address_scope.py +5 -5
- openstackclient/network/v2/default_security_group_rule.py +1 -1
- openstackclient/network/v2/floating_ip.py +8 -10
- openstackclient/network/v2/floating_ip_pool.py +6 -15
- openstackclient/network/v2/floating_ip_port_forwarding.py +5 -13
- openstackclient/network/v2/ip_availability.py +2 -2
- openstackclient/network/v2/l3_conntrack_helper.py +5 -5
- openstackclient/network/v2/network.py +8 -8
- openstackclient/network/v2/network_agent.py +8 -8
- openstackclient/network/v2/network_auto_allocated_topology.py +2 -2
- openstackclient/network/v2/network_flavor.py +6 -8
- openstackclient/network/v2/network_flavor_profile.py +4 -4
- openstackclient/network/v2/network_meter.py +3 -3
- openstackclient/network/v2/network_meter_rule.py +3 -3
- openstackclient/network/v2/network_qos_policy.py +5 -5
- openstackclient/network/v2/network_qos_rule.py +9 -9
- openstackclient/network/v2/network_qos_rule_type.py +1 -1
- openstackclient/network/v2/network_rbac.py +5 -5
- openstackclient/network/v2/network_segment.py +5 -5
- openstackclient/network/v2/network_segment_range.py +7 -7
- openstackclient/network/v2/network_trunk.py +7 -7
- openstackclient/network/v2/port.py +26 -12
- openstackclient/network/v2/router.py +403 -54
- openstackclient/network/v2/security_group.py +18 -14
- openstackclient/network/v2/security_group_rule.py +18 -15
- openstackclient/network/v2/subnet.py +15 -8
- openstackclient/network/v2/subnet_pool.py +6 -6
- openstackclient/object/v1/account.py +2 -2
- openstackclient/object/v1/container.py +7 -7
- openstackclient/object/v1/object.py +7 -7
- openstackclient/shell.py +4 -6
- openstackclient/tests/functional/base.py +1 -1
- openstackclient/tests/functional/common/test_extension.py +1 -1
- openstackclient/tests/functional/common/test_help.py +2 -2
- openstackclient/tests/functional/common/test_module.py +1 -1
- openstackclient/tests/functional/common/test_quota.py +43 -61
- openstackclient/tests/functional/compute/v2/common.py +2 -2
- openstackclient/tests/functional/compute/v2/test_flavor.py +2 -2
- openstackclient/tests/functional/compute/v2/test_keypair.py +1 -1
- openstackclient/tests/functional/compute/v2/test_server.py +5 -5
- openstackclient/tests/functional/compute/v2/test_server_event.py +1 -1
- openstackclient/tests/functional/identity/v2/common.py +3 -3
- openstackclient/tests/functional/identity/v3/common.py +14 -6
- openstackclient/tests/functional/identity/v3/test_application_credential.py +13 -19
- openstackclient/tests/functional/identity/v3/test_domain.py +1 -3
- openstackclient/tests/functional/identity/v3/test_endpoint.py +1 -1
- openstackclient/tests/functional/identity/v3/test_idp.py +1 -1
- openstackclient/tests/functional/identity/v3/test_limit.py +2 -2
- openstackclient/tests/functional/identity/v3/test_region.py +1 -3
- openstackclient/tests/functional/identity/v3/test_registered_limit.py +1 -1
- openstackclient/tests/functional/identity/v3/test_role.py +2 -2
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +210 -0
- openstackclient/tests/functional/identity/v3/test_service.py +4 -6
- openstackclient/tests/functional/identity/v3/test_service_provider.py +1 -3
- openstackclient/tests/functional/image/base.py +1 -1
- openstackclient/tests/functional/image/v2/test_image.py +1 -1
- openstackclient/tests/functional/image/v2/test_info.py +1 -1
- openstackclient/tests/functional/network/v2/common.py +4 -6
- openstackclient/tests/functional/network/v2/test_network.py +5 -3
- openstackclient/tests/functional/network/v2/test_network_agent.py +7 -5
- openstackclient/tests/functional/network/v2/test_network_qos_rule.py +4 -4
- openstackclient/tests/functional/network/v2/test_port.py +11 -7
- openstackclient/tests/functional/network/v2/test_router.py +2 -2
- openstackclient/tests/functional/object/v1/common.py +1 -1
- openstackclient/tests/functional/object/v1/test_container.py +3 -3
- openstackclient/tests/functional/object/v1/test_object.py +9 -13
- openstackclient/tests/functional/volume/base.py +1 -1
- openstackclient/tests/functional/volume/v1/test_service.py +1 -1
- openstackclient/tests/functional/volume/v1/test_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v1/test_transfer_request.py +2 -2
- openstackclient/tests/functional/volume/v1/test_volume_type.py +1 -1
- openstackclient/tests/functional/volume/v2/test_service.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_backup.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_type.py +1 -1
- openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v3/test_volume_type.py +1 -1
- openstackclient/tests/unit/api/fakes.py +1 -1
- openstackclient/tests/unit/api/test_api.py +2 -2
- openstackclient/tests/unit/api/test_compute_v2.py +522 -707
- openstackclient/tests/unit/api/test_image_v1.py +1 -1
- openstackclient/tests/unit/api/test_image_v2.py +1 -1
- openstackclient/tests/unit/api/test_object_store_v1.py +4 -4
- openstackclient/tests/unit/common/test_limits.py +73 -35
- openstackclient/tests/unit/common/test_logs.py +2 -2
- openstackclient/tests/unit/common/test_module.py +4 -2
- openstackclient/tests/unit/common/test_project_cleanup.py +31 -6
- openstackclient/tests/unit/common/test_quota.py +490 -630
- openstackclient/tests/unit/compute/v2/fakes.py +37 -286
- openstackclient/tests/unit/compute/v2/test_agent.py +189 -147
- openstackclient/tests/unit/compute/v2/test_aggregate.py +18 -16
- openstackclient/tests/unit/compute/v2/test_console.py +4 -5
- openstackclient/tests/unit/compute/v2/test_flavor.py +59 -68
- openstackclient/tests/unit/compute/v2/test_host.py +83 -54
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +28 -31
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -2
- openstackclient/tests/unit/compute/v2/test_keypair.py +65 -50
- openstackclient/tests/unit/compute/v2/test_server.py +2895 -2459
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_event.py +14 -39
- openstackclient/tests/unit/compute/v2/test_server_group.py +28 -29
- openstackclient/tests/unit/compute/v2/test_server_migration.py +43 -68
- openstackclient/tests/unit/compute/v2/test_server_volume.py +17 -34
- openstackclient/tests/unit/compute/v2/test_service.py +34 -52
- openstackclient/tests/unit/compute/v2/test_usage.py +4 -4
- openstackclient/tests/unit/fakes.py +11 -11
- openstackclient/tests/unit/identity/v2_0/fakes.py +27 -10
- openstackclient/tests/unit/identity/v2_0/test_catalog.py +3 -3
- openstackclient/tests/unit/identity/v2_0/test_endpoint.py +7 -7
- openstackclient/tests/unit/identity/v2_0/test_project.py +8 -8
- openstackclient/tests/unit/identity/v2_0/test_role.py +10 -10
- openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +4 -4
- openstackclient/tests/unit/identity/v2_0/test_service.py +6 -6
- openstackclient/tests/unit/identity/v2_0/test_token.py +4 -4
- openstackclient/tests/unit/identity/v2_0/test_user.py +8 -8
- openstackclient/tests/unit/identity/v3/fakes.py +59 -20
- openstackclient/tests/unit/identity/v3/test_access_rule.py +5 -5
- openstackclient/tests/unit/identity/v3/test_application_credential.py +212 -235
- openstackclient/tests/unit/identity/v3/test_catalog.py +3 -3
- openstackclient/tests/unit/identity/v3/test_consumer.py +7 -8
- openstackclient/tests/unit/identity/v3/test_credential.py +9 -9
- openstackclient/tests/unit/identity/v3/test_domain.py +8 -8
- openstackclient/tests/unit/identity/v3/test_endpoint.py +13 -13
- openstackclient/tests/unit/identity/v3/test_endpoint_group.py +12 -14
- openstackclient/tests/unit/identity/v3/test_group.py +12 -12
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +8 -8
- openstackclient/tests/unit/identity/v3/test_implied_role.py +5 -5
- openstackclient/tests/unit/identity/v3/test_limit.py +7 -7
- openstackclient/tests/unit/identity/v3/test_mappings.py +7 -7
- openstackclient/tests/unit/identity/v3/test_oauth.py +5 -5
- openstackclient/tests/unit/identity/v3/test_project.py +16 -16
- openstackclient/tests/unit/identity/v3/test_protocol.py +7 -7
- openstackclient/tests/unit/identity/v3/test_region.py +7 -7
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +12 -13
- openstackclient/tests/unit/identity/v3/test_role.py +13 -13
- openstackclient/tests/unit/identity/v3/test_role_assignment.py +410 -331
- openstackclient/tests/unit/identity/v3/test_service.py +93 -97
- openstackclient/tests/unit/identity/v3/test_service_provider.py +7 -7
- openstackclient/tests/unit/identity/v3/test_token.py +4 -4
- openstackclient/tests/unit/identity/v3/test_trust.py +9 -9
- openstackclient/tests/unit/identity/v3/test_unscoped_saml.py +4 -4
- openstackclient/tests/unit/identity/v3/test_user.py +299 -327
- openstackclient/tests/unit/image/v1/test_image.py +6 -6
- openstackclient/tests/unit/image/v2/fakes.py +46 -9
- openstackclient/tests/unit/image/v2/test_cache.py +2 -2
- openstackclient/tests/unit/image/v2/test_image.py +3 -3
- openstackclient/tests/unit/image/v2/test_metadef_objects.py +62 -0
- openstackclient/tests/unit/image/v2/test_metadef_resource_type_association.py +131 -0
- openstackclient/tests/unit/integ/base.py +1 -1
- openstackclient/tests/unit/integ/cli/test_project.py +4 -4
- openstackclient/tests/unit/integ/cli/test_shell.py +7 -7
- openstackclient/tests/unit/network/test_common.py +12 -21
- openstackclient/tests/unit/network/v2/fakes.py +64 -130
- openstackclient/tests/unit/network/v2/test_address_group.py +15 -15
- openstackclient/tests/unit/network/v2/test_address_scope.py +13 -13
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +49 -27
- openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +40 -38
- openstackclient/tests/unit/network/v2/test_floating_ip_network.py +15 -15
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +4 -7
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +3 -5
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +11 -11
- openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -6
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +11 -21
- openstackclient/tests/unit/network/v2/test_local_ip.py +7 -7
- openstackclient/tests/unit/network/v2/test_local_ip_association.py +3 -5
- openstackclient/tests/unit/network/v2/test_ndp_proxy.py +13 -13
- openstackclient/tests/unit/network/v2/test_network.py +23 -28
- openstackclient/tests/unit/network/v2/test_network_agent.py +17 -21
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +8 -8
- openstackclient/tests/unit/network/v2/test_network_compute.py +66 -65
- openstackclient/tests/unit/network/v2/test_network_flavor.py +17 -19
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +13 -13
- openstackclient/tests/unit/network/v2/test_network_meter.py +11 -11
- openstackclient/tests/unit/network/v2/test_network_meter_rule.py +11 -11
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +11 -21
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +51 -77
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +5 -9
- openstackclient/tests/unit/network/v2/test_network_rbac.py +12 -12
- openstackclient/tests/unit/network/v2/test_network_segment.py +11 -15
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +11 -13
- openstackclient/tests/unit/network/v2/test_network_service_provider.py +3 -5
- openstackclient/tests/unit/network/v2/test_network_trunk.py +11 -11
- openstackclient/tests/unit/network/v2/test_port.py +22 -25
- openstackclient/tests/unit/network/v2/test_router.py +721 -51
- openstackclient/tests/unit/network/v2/test_security_group_compute.py +65 -49
- openstackclient/tests/unit/network/v2/test_security_group_network.py +15 -15
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +57 -45
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +11 -19
- openstackclient/tests/unit/network/v2/test_subnet.py +29 -25
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +15 -15
- openstackclient/tests/unit/object/v1/fakes.py +1 -1
- openstackclient/tests/unit/object/v1/test_container.py +5 -5
- openstackclient/tests/unit/object/v1/test_container_all.py +6 -6
- openstackclient/tests/unit/object/v1/test_object.py +3 -3
- openstackclient/tests/unit/object/v1/test_object_all.py +5 -5
- openstackclient/tests/unit/test_shell.py +5 -5
- openstackclient/tests/unit/utils.py +4 -1
- openstackclient/tests/unit/volume/test_find_resource.py +2 -2
- openstackclient/tests/unit/volume/v1/fakes.py +5 -6
- openstackclient/tests/unit/volume/v1/test_volume.py +5 -4
- openstackclient/tests/unit/volume/v2/fakes.py +39 -259
- openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py +5 -5
- openstackclient/tests/unit/volume/v2/test_qos_specs.py +9 -9
- openstackclient/tests/unit/volume/v2/test_volume.py +21 -87
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +7 -368
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +1 -1
- openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +0 -44
- openstackclient/tests/unit/volume/v2/test_volume_type.py +6 -87
- openstackclient/tests/unit/volume/v3/fakes.py +505 -22
- openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py +2 -3
- openstackclient/tests/unit/volume/v3/test_block_storage_cluster.py +10 -11
- openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +10 -6
- openstackclient/tests/unit/volume/v3/test_block_storage_manage.py +25 -17
- openstackclient/tests/unit/volume/v3/test_block_storage_resource_filter.py +6 -32
- openstackclient/tests/unit/volume/v3/test_service.py +271 -0
- openstackclient/tests/unit/volume/v3/test_volume.py +2177 -33
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +48 -52
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +892 -0
- openstackclient/tests/unit/volume/v3/test_volume_group.py +19 -20
- openstackclient/tests/unit/volume/v3/test_volume_group_snapshot.py +14 -34
- openstackclient/tests/unit/volume/v3/test_volume_group_type.py +13 -16
- openstackclient/tests/unit/volume/v3/test_volume_message.py +10 -11
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +161 -0
- openstackclient/tests/unit/volume/v3/test_volume_transfer_request.py +425 -0
- openstackclient/tests/unit/volume/v3/test_volume_type.py +1109 -0
- openstackclient/volume/v1/qos_specs.py +7 -7
- openstackclient/volume/v1/service.py +2 -2
- openstackclient/volume/v1/volume.py +12 -12
- openstackclient/volume/v1/volume_backup.py +7 -7
- openstackclient/volume/v1/volume_snapshot.py +8 -8
- openstackclient/volume/v1/volume_transfer_request.py +5 -5
- openstackclient/volume/v1/volume_type.py +7 -7
- openstackclient/volume/v2/backup_record.py +2 -2
- openstackclient/volume/v2/consistency_group.py +7 -9
- openstackclient/volume/v2/consistency_group_snapshot.py +4 -12
- openstackclient/volume/v2/qos_specs.py +7 -7
- openstackclient/volume/v2/service.py +2 -2
- openstackclient/volume/v2/volume.py +80 -80
- openstackclient/volume/v2/volume_backend.py +2 -2
- openstackclient/volume/v2/volume_backup.py +7 -217
- openstackclient/volume/v2/volume_host.py +2 -2
- openstackclient/volume/v2/volume_snapshot.py +8 -8
- openstackclient/volume/v2/volume_transfer_request.py +5 -37
- openstackclient/volume/v2/volume_type.py +7 -89
- openstackclient/volume/v3/service.py +56 -0
- openstackclient/volume/v3/volume.py +971 -0
- openstackclient/volume/v3/volume_attachment.py +31 -29
- openstackclient/volume/v3/volume_backup.py +670 -0
- openstackclient/volume/v3/volume_message.py +1 -1
- openstackclient/volume/v3/volume_snapshot.py +97 -0
- openstackclient/volume/v3/volume_transfer_request.py +233 -0
- openstackclient/volume/v3/volume_type.py +967 -0
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/AUTHORS +4 -0
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/METADATA +3 -3
- python_openstackclient-7.0.0.dist-info/RECORD +502 -0
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/entry_points.txt +33 -27
- python_openstackclient-7.0.0.dist-info/pbr.json +1 -0
- python_openstackclient-6.6.0.dist-info/RECORD +0 -489
- python_openstackclient-6.6.0.dist-info/pbr.json +0 -1
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-6.6.0.dist-info → python_openstackclient-7.0.0.dist-info}/top_level.txt +0 -0
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"""Compute v2 Server action implementations"""
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
|
+
import base64
|
|
19
20
|
import getpass
|
|
20
|
-
import io
|
|
21
21
|
import json
|
|
22
22
|
import logging
|
|
23
23
|
import os
|
|
24
|
+
import typing as ty
|
|
24
25
|
|
|
25
26
|
from cliff import columns as cliff_columns
|
|
26
27
|
import iso8601
|
|
27
|
-
from novaclient import api_versions
|
|
28
28
|
from openstack import exceptions as sdk_exceptions
|
|
29
29
|
from openstack import utils as sdk_utils
|
|
30
30
|
from osc_lib.cli import format_columns
|
|
@@ -33,6 +33,7 @@ from osc_lib.command import command
|
|
|
33
33
|
from osc_lib import exceptions
|
|
34
34
|
from osc_lib import utils
|
|
35
35
|
|
|
36
|
+
from openstackclient.api import compute_v2
|
|
36
37
|
from openstackclient.common import pagination
|
|
37
38
|
from openstackclient.i18n import _
|
|
38
39
|
from openstackclient.identity import common as identity_common
|
|
@@ -81,7 +82,7 @@ class AddressesColumn(cliff_columns.FormattableColumn):
|
|
|
81
82
|
def machine_readable(self):
|
|
82
83
|
return {
|
|
83
84
|
k: [i['addr'] for i in v if 'addr' in i]
|
|
84
|
-
for k, v in self._value.items()
|
|
85
|
+
for k, v in (self._value.items() if self._value else [])
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
|
|
@@ -128,23 +129,26 @@ def _get_ip_address(addresses, address_type, ip_address_family):
|
|
|
128
129
|
)
|
|
129
130
|
|
|
130
131
|
|
|
131
|
-
def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
132
|
+
def _prep_server_detail(compute_client, image_client, server, *, refresh=True):
|
|
132
133
|
"""Prepare the detailed server dict for printing
|
|
133
134
|
|
|
134
135
|
:param compute_client: a compute client instance
|
|
135
136
|
:param image_client: an image client instance
|
|
136
137
|
:param server: a Server resource
|
|
137
138
|
:param refresh: Flag indicating if ``server`` is already the latest version
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
or if it needs to be refreshed, for example when showing the latest
|
|
140
|
+
details of a server after creating it.
|
|
140
141
|
:rtype: a dict of server details
|
|
141
142
|
"""
|
|
142
|
-
# Note: Some callers of this routine pass a novaclient server, and others
|
|
143
|
-
# pass an SDK server. Column names may be different across those cases.
|
|
144
143
|
info = server.to_dict()
|
|
144
|
+
|
|
145
145
|
if refresh:
|
|
146
|
-
server =
|
|
147
|
-
|
|
146
|
+
server = compute_client.get_server(info['id'])
|
|
147
|
+
# we only update if the field is not empty, to avoid overwriting
|
|
148
|
+
# existing values
|
|
149
|
+
info.update(
|
|
150
|
+
**{x: y for x, y in server.to_dict().items() if x not in info or y}
|
|
151
|
+
)
|
|
148
152
|
|
|
149
153
|
# Some commands using this routine were originally implemented with the
|
|
150
154
|
# nova python wrappers, and were later migrated to use the SDK. Map the
|
|
@@ -159,7 +163,6 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
159
163
|
'compute_host': 'OS-EXT-SRV-ATTR:host',
|
|
160
164
|
'created_at': 'created',
|
|
161
165
|
'disk_config': 'OS-DCF:diskConfig',
|
|
162
|
-
'flavor_id': 'flavorRef',
|
|
163
166
|
'has_config_drive': 'config_drive',
|
|
164
167
|
'host_id': 'hostId',
|
|
165
168
|
'fault': 'fault',
|
|
@@ -180,6 +183,7 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
180
183
|
'updated_at': 'updated',
|
|
181
184
|
'user_data': 'OS-EXT-SRV-ATTR:user_data',
|
|
182
185
|
'vm_state': 'OS-EXT-STS:vm_state',
|
|
186
|
+
'pinned_availability_zone': 'pinned_availability_zone',
|
|
183
187
|
}
|
|
184
188
|
# Some columns returned by openstacksdk should not be shown because they're
|
|
185
189
|
# either irrelevant or duplicates
|
|
@@ -193,9 +197,13 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
193
197
|
'public_v6',
|
|
194
198
|
# create-only columns
|
|
195
199
|
'block_device_mapping',
|
|
200
|
+
'flavor_id',
|
|
201
|
+
'host',
|
|
196
202
|
'image_id',
|
|
197
203
|
'max_count',
|
|
198
204
|
'min_count',
|
|
205
|
+
'networks',
|
|
206
|
+
'personality',
|
|
199
207
|
'scheduler_hints',
|
|
200
208
|
# aliases
|
|
201
209
|
'volumes',
|
|
@@ -205,11 +213,12 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
205
213
|
# Some columns are only present in certain responses and should not be
|
|
206
214
|
# shown otherwise.
|
|
207
215
|
optional_columns = {
|
|
208
|
-
|
|
209
|
-
'
|
|
210
|
-
|
|
211
|
-
'
|
|
212
|
-
|
|
216
|
+
# only in create responses if '[api] enable_instance_password' is set
|
|
217
|
+
'admin_password',
|
|
218
|
+
# only present in errored servers
|
|
219
|
+
'fault',
|
|
220
|
+
# only present in create, detail responses
|
|
221
|
+
'security_groups',
|
|
213
222
|
}
|
|
214
223
|
|
|
215
224
|
data = {}
|
|
@@ -232,7 +241,7 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
232
241
|
image_id = image_info.get('id', '')
|
|
233
242
|
try:
|
|
234
243
|
image = image_client.get_image(image_id)
|
|
235
|
-
info['image'] = "
|
|
244
|
+
info['image'] = f"{image.name} ({image_id})"
|
|
236
245
|
except Exception:
|
|
237
246
|
info['image'] = image_id
|
|
238
247
|
else:
|
|
@@ -249,8 +258,10 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
249
258
|
if flavor_info.get('original_name') is None: # microversion < 2.47
|
|
250
259
|
flavor_id = flavor_info.get('id', '')
|
|
251
260
|
try:
|
|
252
|
-
flavor =
|
|
253
|
-
|
|
261
|
+
flavor = compute_client.find_flavor(
|
|
262
|
+
flavor_id, ignore_missing=False
|
|
263
|
+
)
|
|
264
|
+
info['flavor'] = f"{flavor.name} ({flavor_id})"
|
|
254
265
|
except Exception:
|
|
255
266
|
info['flavor'] = flavor_id
|
|
256
267
|
else: # microversion >= 2.47
|
|
@@ -283,7 +294,9 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|
|
283
294
|
)
|
|
284
295
|
|
|
285
296
|
if 'tags' in info:
|
|
286
|
-
info.update(
|
|
297
|
+
info.update(
|
|
298
|
+
{'tags': format_columns.ListColumn(info.pop('tags') or [])}
|
|
299
|
+
)
|
|
287
300
|
|
|
288
301
|
# Map 'networks' to 'addresses', if present. Note that the 'networks' key
|
|
289
302
|
# is used for create responses, otherwise it's 'addresses'. We know it'll
|
|
@@ -357,7 +370,7 @@ class AddFixedIP(command.ShowOne):
|
|
|
357
370
|
_description = _("Add fixed IP address to server")
|
|
358
371
|
|
|
359
372
|
def get_parser(self, prog_name):
|
|
360
|
-
parser = super(
|
|
373
|
+
parser = super().get_parser(prog_name)
|
|
361
374
|
parser.add_argument(
|
|
362
375
|
"server",
|
|
363
376
|
metavar="<server>",
|
|
@@ -480,16 +493,16 @@ class AddFloatingIP(network_common.NetworkAndComputeCommand):
|
|
|
480
493
|
return parser
|
|
481
494
|
|
|
482
495
|
def take_action_network(self, client, parsed_args):
|
|
483
|
-
compute_client = self.app.client_manager.compute
|
|
496
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
484
497
|
|
|
485
498
|
attrs = {}
|
|
486
499
|
obj = client.find_ip(
|
|
487
500
|
parsed_args.ip_address,
|
|
488
501
|
ignore_missing=False,
|
|
489
502
|
)
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
parsed_args.server,
|
|
503
|
+
|
|
504
|
+
server = compute_client.find_server(
|
|
505
|
+
parsed_args.server, ignore_missing=False
|
|
493
506
|
)
|
|
494
507
|
ports = list(client.ports(device_id=server.id))
|
|
495
508
|
if not ports:
|
|
@@ -539,8 +552,9 @@ class AddFloatingIP(network_common.NetworkAndComputeCommand):
|
|
|
539
552
|
raise error
|
|
540
553
|
|
|
541
554
|
def take_action_compute(self, client, parsed_args):
|
|
542
|
-
client.
|
|
543
|
-
|
|
555
|
+
server = client.find_server(parsed_args.server, ignore_missing=False)
|
|
556
|
+
client.add_floating_ip_to_server(
|
|
557
|
+
server,
|
|
544
558
|
parsed_args.ip_address,
|
|
545
559
|
fixed_address=parsed_args.fixed_ip_address,
|
|
546
560
|
)
|
|
@@ -550,7 +564,7 @@ class AddPort(command.Command):
|
|
|
550
564
|
_description = _("Add port to server")
|
|
551
565
|
|
|
552
566
|
def get_parser(self, prog_name):
|
|
553
|
-
parser = super(
|
|
567
|
+
parser = super().get_parser(prog_name)
|
|
554
568
|
parser.add_argument(
|
|
555
569
|
"server",
|
|
556
570
|
metavar="<server>",
|
|
@@ -604,7 +618,7 @@ class AddNetwork(command.Command):
|
|
|
604
618
|
_description = _("Add network to server")
|
|
605
619
|
|
|
606
620
|
def get_parser(self, prog_name):
|
|
607
|
-
parser = super(
|
|
621
|
+
parser = super().get_parser(prog_name)
|
|
608
622
|
parser.add_argument(
|
|
609
623
|
"server",
|
|
610
624
|
metavar="<server>",
|
|
@@ -659,7 +673,7 @@ class AddServerSecurityGroup(command.Command):
|
|
|
659
673
|
_description = _("Add security group to server")
|
|
660
674
|
|
|
661
675
|
def get_parser(self, prog_name):
|
|
662
|
-
parser = super(
|
|
676
|
+
parser = super().get_parser(prog_name)
|
|
663
677
|
parser.add_argument(
|
|
664
678
|
'server',
|
|
665
679
|
metavar='<server>',
|
|
@@ -673,17 +687,21 @@ class AddServerSecurityGroup(command.Command):
|
|
|
673
687
|
return parser
|
|
674
688
|
|
|
675
689
|
def take_action(self, parsed_args):
|
|
676
|
-
compute_client = self.app.client_manager.compute
|
|
690
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
677
691
|
|
|
678
|
-
server =
|
|
679
|
-
|
|
680
|
-
parsed_args.server,
|
|
681
|
-
)
|
|
682
|
-
security_group = compute_client.api.security_group_find(
|
|
683
|
-
parsed_args.group,
|
|
692
|
+
server = compute_client.find_server(
|
|
693
|
+
parsed_args.server, ignore_missing=False
|
|
684
694
|
)
|
|
685
|
-
|
|
686
|
-
|
|
695
|
+
if self.app.client_manager.is_network_endpoint_enabled():
|
|
696
|
+
# the server handles both names and IDs for neutron SGs, so just
|
|
697
|
+
# pass things through
|
|
698
|
+
security_group = parsed_args.group
|
|
699
|
+
else:
|
|
700
|
+
# however, if using nova-network then it needs a name, not an ID
|
|
701
|
+
security_group = compute_v2.find_security_group(
|
|
702
|
+
compute_client, parsed_args.group
|
|
703
|
+
)['name']
|
|
704
|
+
compute_client.add_security_group_to_server(server, security_group)
|
|
687
705
|
|
|
688
706
|
|
|
689
707
|
class AddServerVolume(command.ShowOne):
|
|
@@ -695,7 +713,7 @@ with status ``SHELVED`` or ``SHELVED_OFFLOADED``."""
|
|
|
695
713
|
)
|
|
696
714
|
|
|
697
715
|
def get_parser(self, prog_name):
|
|
698
|
-
parser = super(
|
|
716
|
+
parser = super().get_parser(prog_name)
|
|
699
717
|
parser.add_argument(
|
|
700
718
|
'server',
|
|
701
719
|
metavar='<server>',
|
|
@@ -914,10 +932,17 @@ class NICAction(argparse.Action):
|
|
|
914
932
|
|
|
915
933
|
if info['net-id'] and info['port-id']:
|
|
916
934
|
msg = _(
|
|
917
|
-
|
|
918
|
-
|
|
935
|
+
"Invalid argument %s; either 'network' or 'port' should be "
|
|
936
|
+
"specified but not both"
|
|
919
937
|
)
|
|
920
|
-
raise argparse.
|
|
938
|
+
raise argparse.ArgumentError(self, msg % values)
|
|
939
|
+
|
|
940
|
+
if info['v4-fixed-ip'] and info['v6-fixed-ip']:
|
|
941
|
+
msg = _(
|
|
942
|
+
"Invalid argument %s; either 'v4-fixed-ip' or 'v6-fixed-ip' "
|
|
943
|
+
"should be specified but not both"
|
|
944
|
+
)
|
|
945
|
+
raise argparse.ArgumentError(self, msg % values)
|
|
921
946
|
|
|
922
947
|
getattr(namespace, self.dest).append(info)
|
|
923
948
|
|
|
@@ -1049,7 +1074,7 @@ class CreateServer(command.ShowOne):
|
|
|
1049
1074
|
_description = _("Create a new server")
|
|
1050
1075
|
|
|
1051
1076
|
def get_parser(self, prog_name):
|
|
1052
|
-
parser = super(
|
|
1077
|
+
parser = super().get_parser(prog_name)
|
|
1053
1078
|
parser.add_argument(
|
|
1054
1079
|
'server_name',
|
|
1055
1080
|
metavar='<server-name>',
|
|
@@ -1148,7 +1173,7 @@ class CreateServer(command.ShowOne):
|
|
|
1148
1173
|
)
|
|
1149
1174
|
parser.add_argument(
|
|
1150
1175
|
'--block-device',
|
|
1151
|
-
metavar='',
|
|
1176
|
+
metavar='<block-device>',
|
|
1152
1177
|
action=BDMAction,
|
|
1153
1178
|
dest='block_devices',
|
|
1154
1179
|
default=[],
|
|
@@ -1482,7 +1507,7 @@ class CreateServer(command.ShowOne):
|
|
|
1482
1507
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
1483
1508
|
self.app.stdout.flush()
|
|
1484
1509
|
|
|
1485
|
-
compute_client = self.app.client_manager.compute
|
|
1510
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
1486
1511
|
volume_client = self.app.client_manager.volume
|
|
1487
1512
|
image_client = self.app.client_manager.image
|
|
1488
1513
|
|
|
@@ -1518,7 +1543,7 @@ class CreateServer(command.ShowOne):
|
|
|
1518
1543
|
img_dict_items.extend(list(img.properties.items()))
|
|
1519
1544
|
for key, value in img_dict_items:
|
|
1520
1545
|
try:
|
|
1521
|
-
|
|
1546
|
+
{key, value}
|
|
1522
1547
|
except TypeError:
|
|
1523
1548
|
if key != 'properties':
|
|
1524
1549
|
LOG.debug(
|
|
@@ -1577,12 +1602,12 @@ class CreateServer(command.ShowOne):
|
|
|
1577
1602
|
parsed_args.snapshot,
|
|
1578
1603
|
).id
|
|
1579
1604
|
|
|
1580
|
-
flavor =
|
|
1581
|
-
|
|
1605
|
+
flavor = compute_client.find_flavor(
|
|
1606
|
+
parsed_args.flavor, ignore_missing=False
|
|
1582
1607
|
)
|
|
1583
1608
|
|
|
1584
1609
|
if parsed_args.file:
|
|
1585
|
-
if compute_client
|
|
1610
|
+
if sdk_utils.supports_microversion(compute_client, '2.57'):
|
|
1586
1611
|
msg = _(
|
|
1587
1612
|
'Personality files are deprecated and are not supported '
|
|
1588
1613
|
'for --os-compute-api-version greater than 2.56; use '
|
|
@@ -1594,8 +1619,8 @@ class CreateServer(command.ShowOne):
|
|
|
1594
1619
|
for f in parsed_args.file:
|
|
1595
1620
|
dst, src = f.split('=', 1)
|
|
1596
1621
|
try:
|
|
1597
|
-
files[dst] =
|
|
1598
|
-
except
|
|
1622
|
+
files[dst] = open(src, 'rb')
|
|
1623
|
+
except OSError as e:
|
|
1599
1624
|
msg = _("Can't open '%(source)s': %(exception)s")
|
|
1600
1625
|
raise exceptions.CommandError(
|
|
1601
1626
|
msg % {'source': src, 'exception': e}
|
|
@@ -1613,18 +1638,20 @@ class CreateServer(command.ShowOne):
|
|
|
1613
1638
|
msg = _("max instances should be > 0")
|
|
1614
1639
|
raise exceptions.CommandError(msg)
|
|
1615
1640
|
|
|
1616
|
-
|
|
1641
|
+
user_data = None
|
|
1617
1642
|
if parsed_args.user_data:
|
|
1618
1643
|
try:
|
|
1619
|
-
|
|
1620
|
-
|
|
1644
|
+
with open(parsed_args.user_data, 'rb') as fh:
|
|
1645
|
+
# TODO(stephenfin): SDK should do this for us
|
|
1646
|
+
user_data = base64.b64encode(fh.read()).decode('utf-8')
|
|
1647
|
+
except OSError as e:
|
|
1621
1648
|
msg = _("Can't open '%(data)s': %(exception)s")
|
|
1622
1649
|
raise exceptions.CommandError(
|
|
1623
1650
|
msg % {'data': parsed_args.user_data, 'exception': e}
|
|
1624
1651
|
)
|
|
1625
1652
|
|
|
1626
1653
|
if parsed_args.description:
|
|
1627
|
-
if
|
|
1654
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
1628
1655
|
msg = _(
|
|
1629
1656
|
'--os-compute-api-version 2.19 or greater is '
|
|
1630
1657
|
'required to support the --description option'
|
|
@@ -1632,26 +1659,7 @@ class CreateServer(command.ShowOne):
|
|
|
1632
1659
|
raise exceptions.CommandError(msg)
|
|
1633
1660
|
|
|
1634
1661
|
block_device_mapping_v2 = []
|
|
1635
|
-
if
|
|
1636
|
-
block_device_mapping_v2 = [
|
|
1637
|
-
{
|
|
1638
|
-
'uuid': volume,
|
|
1639
|
-
'boot_index': 0,
|
|
1640
|
-
'source_type': 'volume',
|
|
1641
|
-
'destination_type': 'volume',
|
|
1642
|
-
}
|
|
1643
|
-
]
|
|
1644
|
-
elif snapshot:
|
|
1645
|
-
block_device_mapping_v2 = [
|
|
1646
|
-
{
|
|
1647
|
-
'uuid': snapshot,
|
|
1648
|
-
'boot_index': 0,
|
|
1649
|
-
'source_type': 'snapshot',
|
|
1650
|
-
'destination_type': 'volume',
|
|
1651
|
-
'delete_on_termination': False,
|
|
1652
|
-
}
|
|
1653
|
-
]
|
|
1654
|
-
elif parsed_args.boot_from_volume:
|
|
1662
|
+
if parsed_args.boot_from_volume:
|
|
1655
1663
|
# Tell nova to create a root volume from the image provided.
|
|
1656
1664
|
if not image:
|
|
1657
1665
|
msg = _(
|
|
@@ -1670,6 +1678,35 @@ class CreateServer(command.ShowOne):
|
|
|
1670
1678
|
]
|
|
1671
1679
|
# If booting from volume we do not pass an image to compute.
|
|
1672
1680
|
image = None
|
|
1681
|
+
elif image:
|
|
1682
|
+
block_device_mapping_v2 = [
|
|
1683
|
+
{
|
|
1684
|
+
'uuid': image.id,
|
|
1685
|
+
'boot_index': 0,
|
|
1686
|
+
'source_type': 'image',
|
|
1687
|
+
'destination_type': 'local',
|
|
1688
|
+
'delete_on_termination': True,
|
|
1689
|
+
}
|
|
1690
|
+
]
|
|
1691
|
+
elif volume:
|
|
1692
|
+
block_device_mapping_v2 = [
|
|
1693
|
+
{
|
|
1694
|
+
'uuid': volume,
|
|
1695
|
+
'boot_index': 0,
|
|
1696
|
+
'source_type': 'volume',
|
|
1697
|
+
'destination_type': 'volume',
|
|
1698
|
+
}
|
|
1699
|
+
]
|
|
1700
|
+
elif snapshot:
|
|
1701
|
+
block_device_mapping_v2 = [
|
|
1702
|
+
{
|
|
1703
|
+
'uuid': snapshot,
|
|
1704
|
+
'boot_index': 0,
|
|
1705
|
+
'source_type': 'snapshot',
|
|
1706
|
+
'destination_type': 'volume',
|
|
1707
|
+
'delete_on_termination': False,
|
|
1708
|
+
}
|
|
1709
|
+
]
|
|
1673
1710
|
|
|
1674
1711
|
if parsed_args.swap:
|
|
1675
1712
|
block_device_mapping_v2.append(
|
|
@@ -1745,7 +1782,7 @@ class CreateServer(command.ShowOne):
|
|
|
1745
1782
|
raise exceptions.CommandError(msg)
|
|
1746
1783
|
|
|
1747
1784
|
if 'tag' in mapping and (
|
|
1748
|
-
|
|
1785
|
+
not sdk_utils.supports_microversion(compute_client, '2.42')
|
|
1749
1786
|
):
|
|
1750
1787
|
msg = _(
|
|
1751
1788
|
'--os-compute-api-version 2.42 or greater is '
|
|
@@ -1754,7 +1791,7 @@ class CreateServer(command.ShowOne):
|
|
|
1754
1791
|
raise exceptions.CommandError(msg)
|
|
1755
1792
|
|
|
1756
1793
|
if 'volume_type' in mapping and (
|
|
1757
|
-
|
|
1794
|
+
not sdk_utils.supports_microversion(compute_client, '2.67')
|
|
1758
1795
|
):
|
|
1759
1796
|
msg = _(
|
|
1760
1797
|
'--os-compute-api-version 2.67 or greater is '
|
|
@@ -1810,7 +1847,7 @@ class CreateServer(command.ShowOne):
|
|
|
1810
1847
|
|
|
1811
1848
|
block_device_mapping_v2.append(mapping)
|
|
1812
1849
|
|
|
1813
|
-
if not
|
|
1850
|
+
if not any(
|
|
1814
1851
|
[bdm.get('boot_index') == 0 for bdm in block_device_mapping_v2]
|
|
1815
1852
|
):
|
|
1816
1853
|
msg = _(
|
|
@@ -1819,10 +1856,12 @@ class CreateServer(command.ShowOne):
|
|
|
1819
1856
|
)
|
|
1820
1857
|
raise exceptions.CommandError(msg)
|
|
1821
1858
|
|
|
1822
|
-
|
|
1859
|
+
# Default to empty list if nothing was specified and let nova
|
|
1860
|
+
# decide the default behavior.
|
|
1861
|
+
networks: ty.Union[str, ty.List[ty.Dict[str, str]], None] = []
|
|
1823
1862
|
|
|
1824
|
-
if 'auto' in nics or 'none' in nics:
|
|
1825
|
-
if len(nics) > 1:
|
|
1863
|
+
if 'auto' in parsed_args.nics or 'none' in parsed_args.nics:
|
|
1864
|
+
if len(parsed_args.nics) > 1:
|
|
1826
1865
|
msg = _(
|
|
1827
1866
|
'Specifying a --nic of auto or none cannot '
|
|
1828
1867
|
'be used with any other --nic, --network '
|
|
@@ -1830,7 +1869,7 @@ class CreateServer(command.ShowOne):
|
|
|
1830
1869
|
)
|
|
1831
1870
|
raise exceptions.CommandError(msg)
|
|
1832
1871
|
|
|
1833
|
-
if
|
|
1872
|
+
if not sdk_utils.supports_microversion(compute_client, '2.37'):
|
|
1834
1873
|
msg = _(
|
|
1835
1874
|
'--os-compute-api-version 2.37 or greater is '
|
|
1836
1875
|
'required to support explicit auto-allocation of a '
|
|
@@ -1838,12 +1877,12 @@ class CreateServer(command.ShowOne):
|
|
|
1838
1877
|
)
|
|
1839
1878
|
raise exceptions.CommandError(msg)
|
|
1840
1879
|
|
|
1841
|
-
|
|
1880
|
+
networks = parsed_args.nics[0]
|
|
1842
1881
|
else:
|
|
1843
|
-
for nic in nics:
|
|
1882
|
+
for nic in parsed_args.nics:
|
|
1844
1883
|
if 'tag' in nic:
|
|
1845
|
-
if
|
|
1846
|
-
'2.43'
|
|
1884
|
+
if not sdk_utils.supports_microversion(
|
|
1885
|
+
compute_client, '2.43'
|
|
1847
1886
|
):
|
|
1848
1887
|
msg = _(
|
|
1849
1888
|
'--os-compute-api-version 2.43 or greater is '
|
|
@@ -1869,9 +1908,11 @@ class CreateServer(command.ShowOne):
|
|
|
1869
1908
|
nic['port-id'] = port.id
|
|
1870
1909
|
else:
|
|
1871
1910
|
if nic['net-id']:
|
|
1872
|
-
|
|
1911
|
+
net = compute_v2.find_network(
|
|
1912
|
+
compute_client,
|
|
1873
1913
|
nic['net-id'],
|
|
1874
|
-
)
|
|
1914
|
+
)
|
|
1915
|
+
nic['net-id'] = net['id']
|
|
1875
1916
|
|
|
1876
1917
|
if nic['port-id']:
|
|
1877
1918
|
msg = _(
|
|
@@ -1880,18 +1921,35 @@ class CreateServer(command.ShowOne):
|
|
|
1880
1921
|
)
|
|
1881
1922
|
raise exceptions.CommandError(msg)
|
|
1882
1923
|
|
|
1883
|
-
|
|
1924
|
+
# convert from the novaclient-derived "NIC" view to the actual
|
|
1925
|
+
# "network" view
|
|
1926
|
+
network = {}
|
|
1927
|
+
|
|
1928
|
+
if nic['net-id']:
|
|
1929
|
+
network['uuid'] = nic['net-id']
|
|
1930
|
+
|
|
1931
|
+
if nic['port-id']:
|
|
1932
|
+
network['port'] = nic['port-id']
|
|
1933
|
+
|
|
1934
|
+
if nic['v4-fixed-ip']:
|
|
1935
|
+
network['fixed'] = nic['v4-fixed-ip']
|
|
1936
|
+
elif nic['v6-fixed-ip']:
|
|
1937
|
+
network['fixed'] = nic['v6-fixed-ip']
|
|
1938
|
+
|
|
1939
|
+
if nic.get('tag'): # tags are optional
|
|
1940
|
+
network['tag'] = nic['tag']
|
|
1941
|
+
|
|
1942
|
+
networks.append(network)
|
|
1943
|
+
|
|
1944
|
+
if not parsed_args.nics and sdk_utils.supports_microversion(
|
|
1945
|
+
compute_client, '2.37'
|
|
1946
|
+
):
|
|
1884
1947
|
# Compute API version >= 2.37 requires a value, so default to
|
|
1885
1948
|
# 'auto' to maintain legacy behavior if a nic wasn't specified.
|
|
1886
|
-
|
|
1887
|
-
nics = 'auto'
|
|
1888
|
-
else:
|
|
1889
|
-
# Default to empty list if nothing was specified and let nova
|
|
1890
|
-
# decide the default behavior.
|
|
1891
|
-
nics = []
|
|
1949
|
+
networks = 'auto'
|
|
1892
1950
|
|
|
1893
1951
|
# Check security group exist and convert ID to name
|
|
1894
|
-
|
|
1952
|
+
security_groups = []
|
|
1895
1953
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
1896
1954
|
network_client = self.app.client_manager.network
|
|
1897
1955
|
for each_sg in parsed_args.security_group:
|
|
@@ -1900,12 +1958,12 @@ class CreateServer(command.ShowOne):
|
|
|
1900
1958
|
)
|
|
1901
1959
|
# Use security group ID to avoid multiple security group have
|
|
1902
1960
|
# same name in neutron networking backend
|
|
1903
|
-
|
|
1961
|
+
security_groups.append({'name': sg.id})
|
|
1904
1962
|
else:
|
|
1905
1963
|
# Handle nova-network case
|
|
1906
1964
|
for each_sg in parsed_args.security_group:
|
|
1907
|
-
sg =
|
|
1908
|
-
|
|
1965
|
+
sg = compute_v2.find_security_group(compute_client, each_sg)
|
|
1966
|
+
security_groups.append({'name': sg['name']})
|
|
1909
1967
|
|
|
1910
1968
|
hints = {}
|
|
1911
1969
|
for key, values in parsed_args.hints.items():
|
|
@@ -1916,9 +1974,8 @@ class CreateServer(command.ShowOne):
|
|
|
1916
1974
|
hints[key] = values
|
|
1917
1975
|
|
|
1918
1976
|
if parsed_args.server_group:
|
|
1919
|
-
server_group_obj =
|
|
1920
|
-
|
|
1921
|
-
parsed_args.server_group,
|
|
1977
|
+
server_group_obj = compute_client.find_server_group(
|
|
1978
|
+
parsed_args.server_group, ignore_missing=False
|
|
1922
1979
|
)
|
|
1923
1980
|
hints['group'] = server_group_obj.id
|
|
1924
1981
|
|
|
@@ -1940,69 +1997,89 @@ class CreateServer(command.ShowOne):
|
|
|
1940
1997
|
else:
|
|
1941
1998
|
config_drive = parsed_args.config_drive
|
|
1942
1999
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
max_count=parsed_args.max,
|
|
1951
|
-
security_groups=security_group_names,
|
|
1952
|
-
userdata=userdata,
|
|
1953
|
-
key_name=parsed_args.key_name,
|
|
1954
|
-
availability_zone=parsed_args.availability_zone,
|
|
1955
|
-
admin_pass=parsed_args.password,
|
|
1956
|
-
block_device_mapping_v2=block_device_mapping_v2,
|
|
1957
|
-
nics=nics,
|
|
1958
|
-
scheduler_hints=hints,
|
|
1959
|
-
config_drive=config_drive,
|
|
1960
|
-
)
|
|
2000
|
+
kwargs = {
|
|
2001
|
+
'name': parsed_args.server_name,
|
|
2002
|
+
'image_id': image.id if image else '',
|
|
2003
|
+
'flavor_id': flavor.id,
|
|
2004
|
+
'min_count': parsed_args.min,
|
|
2005
|
+
'max_count': parsed_args.max,
|
|
2006
|
+
}
|
|
1961
2007
|
|
|
1962
2008
|
if parsed_args.description:
|
|
1963
|
-
|
|
2009
|
+
kwargs['description'] = parsed_args.description
|
|
2010
|
+
|
|
2011
|
+
if parsed_args.availability_zone:
|
|
2012
|
+
kwargs['availability_zone'] = parsed_args.availability_zone
|
|
2013
|
+
|
|
2014
|
+
if parsed_args.password:
|
|
2015
|
+
kwargs['admin_password'] = parsed_args.password
|
|
2016
|
+
|
|
2017
|
+
if parsed_args.properties:
|
|
2018
|
+
kwargs['metadata'] = parsed_args.properties
|
|
2019
|
+
|
|
2020
|
+
if parsed_args.key_name:
|
|
2021
|
+
kwargs['key_name'] = parsed_args.key_name
|
|
2022
|
+
|
|
2023
|
+
if user_data:
|
|
2024
|
+
kwargs['user_data'] = user_data
|
|
2025
|
+
|
|
2026
|
+
if files:
|
|
2027
|
+
kwargs['personality'] = files
|
|
2028
|
+
|
|
2029
|
+
if security_groups:
|
|
2030
|
+
kwargs['security_groups'] = security_groups
|
|
2031
|
+
|
|
2032
|
+
if block_device_mapping_v2:
|
|
2033
|
+
kwargs['block_device_mapping'] = block_device_mapping_v2
|
|
2034
|
+
|
|
2035
|
+
if hints:
|
|
2036
|
+
kwargs['scheduler_hints'] = hints
|
|
2037
|
+
|
|
2038
|
+
if networks is not None:
|
|
2039
|
+
kwargs['networks'] = networks
|
|
2040
|
+
|
|
2041
|
+
if config_drive is not None:
|
|
2042
|
+
kwargs['config_drive'] = config_drive
|
|
1964
2043
|
|
|
1965
2044
|
if parsed_args.tags:
|
|
1966
|
-
if
|
|
2045
|
+
if not sdk_utils.supports_microversion(compute_client, '2.52'):
|
|
1967
2046
|
msg = _(
|
|
1968
2047
|
'--os-compute-api-version 2.52 or greater is required to '
|
|
1969
2048
|
'support the --tag option'
|
|
1970
2049
|
)
|
|
1971
2050
|
raise exceptions.CommandError(msg)
|
|
1972
2051
|
|
|
1973
|
-
|
|
2052
|
+
kwargs['tags'] = parsed_args.tags
|
|
1974
2053
|
|
|
1975
2054
|
if parsed_args.host:
|
|
1976
|
-
if
|
|
2055
|
+
if not sdk_utils.supports_microversion(compute_client, '2.74'):
|
|
1977
2056
|
msg = _(
|
|
1978
2057
|
'--os-compute-api-version 2.74 or greater is required to '
|
|
1979
2058
|
'support the --host option'
|
|
1980
2059
|
)
|
|
1981
2060
|
raise exceptions.CommandError(msg)
|
|
1982
2061
|
|
|
1983
|
-
|
|
2062
|
+
kwargs['host'] = parsed_args.host
|
|
1984
2063
|
|
|
1985
2064
|
if parsed_args.hypervisor_hostname:
|
|
1986
|
-
if
|
|
2065
|
+
if not sdk_utils.supports_microversion(compute_client, '2.74'):
|
|
1987
2066
|
msg = _(
|
|
1988
2067
|
'--os-compute-api-version 2.74 or greater is required to '
|
|
1989
2068
|
'support the --hypervisor-hostname option'
|
|
1990
2069
|
)
|
|
1991
2070
|
raise exceptions.CommandError(msg)
|
|
1992
2071
|
|
|
1993
|
-
|
|
1994
|
-
'hypervisor_hostname'
|
|
1995
|
-
] = parsed_args.hypervisor_hostname
|
|
2072
|
+
kwargs['hypervisor_hostname'] = parsed_args.hypervisor_hostname
|
|
1996
2073
|
|
|
1997
2074
|
if parsed_args.hostname:
|
|
1998
|
-
if
|
|
2075
|
+
if not sdk_utils.supports_microversion(compute_client, '2.90'):
|
|
1999
2076
|
msg = _(
|
|
2000
2077
|
'--os-compute-api-version 2.90 or greater is required to '
|
|
2001
2078
|
'support the --hostname option'
|
|
2002
2079
|
)
|
|
2003
2080
|
raise exceptions.CommandError(msg)
|
|
2004
2081
|
|
|
2005
|
-
|
|
2082
|
+
kwargs['hostname'] = parsed_args.hostname
|
|
2006
2083
|
|
|
2007
2084
|
# TODO(stephenfin): Handle OS_TRUSTED_IMAGE_CERTIFICATE_IDS
|
|
2008
2085
|
if parsed_args.trusted_image_certs:
|
|
@@ -2012,7 +2089,7 @@ class CreateServer(command.ShowOne):
|
|
|
2012
2089
|
'servers booted directly from images'
|
|
2013
2090
|
)
|
|
2014
2091
|
raise exceptions.CommandError(msg)
|
|
2015
|
-
if
|
|
2092
|
+
if not sdk_utils.supports_microversion(compute_client, '2.63'):
|
|
2016
2093
|
msg = _(
|
|
2017
2094
|
'--os-compute-api-version 2.63 or greater is required to '
|
|
2018
2095
|
'support the --trusted-image-cert option'
|
|
@@ -2020,25 +2097,22 @@ class CreateServer(command.ShowOne):
|
|
|
2020
2097
|
raise exceptions.CommandError(msg)
|
|
2021
2098
|
|
|
2022
2099
|
certs = parsed_args.trusted_image_certs
|
|
2023
|
-
|
|
2100
|
+
kwargs['trusted_image_certificates'] = certs
|
|
2024
2101
|
|
|
2025
|
-
LOG.debug('
|
|
2026
|
-
LOG.debug('boot_kwargs: %s', boot_kwargs)
|
|
2102
|
+
LOG.debug('boot_kwargs: %s', kwargs)
|
|
2027
2103
|
|
|
2028
2104
|
# Wrap the call to catch exceptions in order to close files
|
|
2029
2105
|
try:
|
|
2030
|
-
server = compute_client.
|
|
2106
|
+
server = compute_client.create_server(**kwargs)
|
|
2031
2107
|
finally:
|
|
2032
2108
|
# Clean up open files - make sure they are not strings
|
|
2033
2109
|
for f in files:
|
|
2034
2110
|
if hasattr(f, 'close'):
|
|
2035
2111
|
f.close()
|
|
2036
|
-
if hasattr(userdata, 'close'):
|
|
2037
|
-
userdata.close()
|
|
2038
2112
|
|
|
2039
2113
|
if parsed_args.wait:
|
|
2040
2114
|
if utils.wait_for_status(
|
|
2041
|
-
compute_client.
|
|
2115
|
+
compute_client.get_server,
|
|
2042
2116
|
server.id,
|
|
2043
2117
|
callback=_show_progress,
|
|
2044
2118
|
):
|
|
@@ -2047,8 +2121,8 @@ class CreateServer(command.ShowOne):
|
|
|
2047
2121
|
msg = _('Error creating server: %s') % parsed_args.server_name
|
|
2048
2122
|
raise exceptions.CommandError(msg)
|
|
2049
2123
|
|
|
2050
|
-
|
|
2051
|
-
return zip(*sorted(
|
|
2124
|
+
data = _prep_server_detail(compute_client, image_client, server)
|
|
2125
|
+
return zip(*sorted(data.items()))
|
|
2052
2126
|
|
|
2053
2127
|
|
|
2054
2128
|
class CreateServerDump(command.Command):
|
|
@@ -2064,7 +2138,7 @@ class CreateServerDump(command.Command):
|
|
|
2064
2138
|
"""
|
|
2065
2139
|
|
|
2066
2140
|
def get_parser(self, prog_name):
|
|
2067
|
-
parser = super(
|
|
2141
|
+
parser = super().get_parser(prog_name)
|
|
2068
2142
|
parser.add_argument(
|
|
2069
2143
|
'server',
|
|
2070
2144
|
metavar='<server>',
|
|
@@ -2084,7 +2158,7 @@ class DeleteServer(command.Command):
|
|
|
2084
2158
|
_description = _("Delete server(s)")
|
|
2085
2159
|
|
|
2086
2160
|
def get_parser(self, prog_name):
|
|
2087
|
-
parser = super(
|
|
2161
|
+
parser = super().get_parser(prog_name)
|
|
2088
2162
|
parser.add_argument(
|
|
2089
2163
|
'server',
|
|
2090
2164
|
metavar='<server>',
|
|
@@ -2118,25 +2192,22 @@ class DeleteServer(command.Command):
|
|
|
2118
2192
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
2119
2193
|
self.app.stdout.flush()
|
|
2120
2194
|
|
|
2121
|
-
compute_client = self.app.client_manager.compute
|
|
2195
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
2122
2196
|
for server in parsed_args.server:
|
|
2123
|
-
server_obj =
|
|
2124
|
-
compute_client.servers,
|
|
2197
|
+
server_obj = compute_client.find_server(
|
|
2125
2198
|
server,
|
|
2126
|
-
|
|
2199
|
+
ignore_missing=False,
|
|
2200
|
+
all_projects=parsed_args.all_projects,
|
|
2127
2201
|
)
|
|
2128
2202
|
|
|
2129
|
-
|
|
2130
|
-
compute_client.servers.force_delete(server_obj.id)
|
|
2131
|
-
else:
|
|
2132
|
-
compute_client.servers.delete(server_obj.id)
|
|
2203
|
+
compute_client.delete_server(server_obj, force=parsed_args.force)
|
|
2133
2204
|
|
|
2134
2205
|
if parsed_args.wait:
|
|
2135
|
-
|
|
2136
|
-
compute_client.
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2206
|
+
try:
|
|
2207
|
+
compute_client.wait_for_delete(
|
|
2208
|
+
server_obj, callback=_show_progress
|
|
2209
|
+
)
|
|
2210
|
+
except sdk_exceptions.ResourceTimeout:
|
|
2140
2211
|
msg = _('Error deleting server: %s') % server_obj.id
|
|
2141
2212
|
raise exceptions.CommandError(msg)
|
|
2142
2213
|
|
|
@@ -2189,7 +2260,7 @@ class ListServer(command.Lister):
|
|
|
2189
2260
|
_description = _("List servers")
|
|
2190
2261
|
|
|
2191
2262
|
def get_parser(self, prog_name):
|
|
2192
|
-
parser = super(
|
|
2263
|
+
parser = super().get_parser(prog_name)
|
|
2193
2264
|
parser.add_argument(
|
|
2194
2265
|
'--reservation-id',
|
|
2195
2266
|
metavar='<reservation-id>',
|
|
@@ -2457,7 +2528,7 @@ class ListServer(command.Lister):
|
|
|
2457
2528
|
action='store_true',
|
|
2458
2529
|
default=False,
|
|
2459
2530
|
help=_(
|
|
2460
|
-
'When looking up flavor and image names, look them up'
|
|
2531
|
+
'When looking up flavor and image names, look them up '
|
|
2461
2532
|
'one by one as needed instead of all together (default). '
|
|
2462
2533
|
'Mutually exclusive with "--no-name-lookup|-n" option.'
|
|
2463
2534
|
),
|
|
@@ -2752,11 +2823,13 @@ class ListServer(command.Lister):
|
|
|
2752
2823
|
if parsed_args.long:
|
|
2753
2824
|
columns += (
|
|
2754
2825
|
'availability_zone',
|
|
2826
|
+
'pinned_availability_zone',
|
|
2755
2827
|
'hypervisor_hostname',
|
|
2756
2828
|
'metadata',
|
|
2757
2829
|
)
|
|
2758
2830
|
column_headers += (
|
|
2759
2831
|
'Availability Zone',
|
|
2832
|
+
'Pinned Availability Zone',
|
|
2760
2833
|
'Host',
|
|
2761
2834
|
'Properties',
|
|
2762
2835
|
)
|
|
@@ -2791,6 +2864,12 @@ class ListServer(command.Lister):
|
|
|
2791
2864
|
if c in ('Availability Zone', "availability_zone"):
|
|
2792
2865
|
columns += ('availability_zone',)
|
|
2793
2866
|
column_headers += ('Availability Zone',)
|
|
2867
|
+
if c in (
|
|
2868
|
+
'pinned_availability_zone',
|
|
2869
|
+
"Pinned Availability Zone",
|
|
2870
|
+
):
|
|
2871
|
+
columns += ('Pinned Availability Zone',)
|
|
2872
|
+
column_headers += ('Pinned Availability Zone',)
|
|
2794
2873
|
if c in ('Host', "host"):
|
|
2795
2874
|
columns += ('hypervisor_hostname',)
|
|
2796
2875
|
column_headers += ('Host',)
|
|
@@ -2834,11 +2913,12 @@ class ListServer(command.Lister):
|
|
|
2834
2913
|
# there are infra failures
|
|
2835
2914
|
if parsed_args.name_lookup_one_by_one or image_id:
|
|
2836
2915
|
for image_id in image_ids:
|
|
2837
|
-
# "Image Name" is not crucial, so we swallow any exceptions
|
|
2838
2916
|
try:
|
|
2839
2917
|
images[image_id] = image_client.get_image(image_id)
|
|
2840
2918
|
except Exception:
|
|
2841
|
-
|
|
2919
|
+
# retrieving image names is not crucial, so we swallow
|
|
2920
|
+
# any exceptions
|
|
2921
|
+
pass # nosec: B110
|
|
2842
2922
|
else:
|
|
2843
2923
|
try:
|
|
2844
2924
|
# some deployments can have *loads* of images so we only
|
|
@@ -2857,33 +2937,37 @@ class ListServer(command.Lister):
|
|
|
2857
2937
|
for i in images_list:
|
|
2858
2938
|
images[i.id] = i
|
|
2859
2939
|
except Exception:
|
|
2860
|
-
|
|
2940
|
+
# retrieving image names is not crucial, so we swallow any
|
|
2941
|
+
# exceptions
|
|
2942
|
+
pass # nosec: B110
|
|
2861
2943
|
|
|
2862
2944
|
# create a dict that maps flavor_id to flavor object, which is used
|
|
2863
2945
|
# to display the "Flavor Name" column. Note that 'flavor.id' is not
|
|
2864
2946
|
# present on microversion 2.47 or later and 'flavor' won't be
|
|
2865
2947
|
# present if there are infra failures
|
|
2866
2948
|
if parsed_args.name_lookup_one_by_one or flavor_id:
|
|
2867
|
-
for f_id in
|
|
2949
|
+
for f_id in {
|
|
2868
2950
|
s.flavor['id']
|
|
2869
2951
|
for s in data
|
|
2870
2952
|
if s.flavor and s.flavor.get('id')
|
|
2871
|
-
|
|
2872
|
-
# "Flavor Name" is not crucial, so we swallow any
|
|
2873
|
-
# exceptions
|
|
2953
|
+
}:
|
|
2874
2954
|
try:
|
|
2875
2955
|
flavors[f_id] = compute_client.find_flavor(
|
|
2876
2956
|
f_id, ignore_missing=False
|
|
2877
2957
|
)
|
|
2878
2958
|
except Exception:
|
|
2879
|
-
|
|
2959
|
+
# retrieving flavor names is not crucial, so we swallow
|
|
2960
|
+
# any exceptions
|
|
2961
|
+
pass # nosec: B110
|
|
2880
2962
|
else:
|
|
2881
2963
|
try:
|
|
2882
2964
|
flavors_list = compute_client.flavors(is_public=None)
|
|
2883
2965
|
for i in flavors_list:
|
|
2884
2966
|
flavors[i.id] = i
|
|
2885
2967
|
except Exception:
|
|
2886
|
-
|
|
2968
|
+
# retrieving flavor names is not crucial, so we swallow any
|
|
2969
|
+
# exceptions
|
|
2970
|
+
pass # nosec: B110
|
|
2887
2971
|
|
|
2888
2972
|
# Populate image_name, image_id, flavor_name and flavor_id attributes
|
|
2889
2973
|
# of server objects so that we can display those columns.
|
|
@@ -2974,7 +3058,7 @@ A non-admin user will not be able to execute actions."""
|
|
|
2974
3058
|
)
|
|
2975
3059
|
|
|
2976
3060
|
def get_parser(self, prog_name):
|
|
2977
|
-
parser = super(
|
|
3061
|
+
parser = super().get_parser(prog_name)
|
|
2978
3062
|
parser.add_argument(
|
|
2979
3063
|
'server',
|
|
2980
3064
|
metavar='<server>',
|
|
@@ -3038,7 +3122,7 @@ revert to release the new server and restart the old one."""
|
|
|
3038
3122
|
)
|
|
3039
3123
|
|
|
3040
3124
|
def get_parser(self, prog_name):
|
|
3041
|
-
parser = super(
|
|
3125
|
+
parser = super().get_parser(prog_name)
|
|
3042
3126
|
parser.add_argument(
|
|
3043
3127
|
'server',
|
|
3044
3128
|
metavar='<server>',
|
|
@@ -3117,11 +3201,10 @@ revert to release the new server and restart the old one."""
|
|
|
3117
3201
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
3118
3202
|
self.app.stdout.flush()
|
|
3119
3203
|
|
|
3120
|
-
compute_client = self.app.client_manager.compute
|
|
3204
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3121
3205
|
|
|
3122
|
-
server =
|
|
3123
|
-
|
|
3124
|
-
parsed_args.server,
|
|
3206
|
+
server = compute_client.find_server(
|
|
3207
|
+
parsed_args.server, ignore_missing=False
|
|
3125
3208
|
)
|
|
3126
3209
|
|
|
3127
3210
|
if parsed_args.live_migration:
|
|
@@ -3129,9 +3212,7 @@ revert to release the new server and restart the old one."""
|
|
|
3129
3212
|
|
|
3130
3213
|
block_migration = parsed_args.block_migration
|
|
3131
3214
|
if block_migration is None:
|
|
3132
|
-
if compute_client
|
|
3133
|
-
'2.25'
|
|
3134
|
-
):
|
|
3215
|
+
if not sdk_utils.supports_microversion(compute_client, '2.25'):
|
|
3135
3216
|
block_migration = False
|
|
3136
3217
|
else:
|
|
3137
3218
|
block_migration = 'auto'
|
|
@@ -3144,10 +3225,8 @@ revert to release the new server and restart the old one."""
|
|
|
3144
3225
|
# want to support, so if the user is using --live-migration
|
|
3145
3226
|
# and --host, we want to enforce that they are using version
|
|
3146
3227
|
# 2.30 or greater.
|
|
3147
|
-
if (
|
|
3148
|
-
|
|
3149
|
-
and compute_client.api_version
|
|
3150
|
-
< api_versions.APIVersion('2.30')
|
|
3228
|
+
if parsed_args.host and not sdk_utils.supports_microversion(
|
|
3229
|
+
compute_client, '2.30'
|
|
3151
3230
|
):
|
|
3152
3231
|
raise exceptions.CommandError(
|
|
3153
3232
|
'--os-compute-api-version 2.30 or greater is required '
|
|
@@ -3157,13 +3236,13 @@ revert to release the new server and restart the old one."""
|
|
|
3157
3236
|
# The host parameter is required in the API even if None.
|
|
3158
3237
|
kwargs['host'] = parsed_args.host
|
|
3159
3238
|
|
|
3160
|
-
if
|
|
3161
|
-
kwargs['
|
|
3239
|
+
if not sdk_utils.supports_microversion(compute_client, '2.25'):
|
|
3240
|
+
kwargs['disk_overcommit'] = parsed_args.disk_overcommit
|
|
3162
3241
|
# We can't use an argparse default value because then we can't
|
|
3163
3242
|
# distinguish between explicit 'False' and unset for the below
|
|
3164
3243
|
# case (microversion >= 2.25)
|
|
3165
|
-
if kwargs['
|
|
3166
|
-
kwargs['
|
|
3244
|
+
if kwargs['disk_overcommit'] is None:
|
|
3245
|
+
kwargs['disk_overcommit'] = False
|
|
3167
3246
|
elif parsed_args.disk_overcommit is not None:
|
|
3168
3247
|
# TODO(stephenfin): Raise an error here in OSC 7.0
|
|
3169
3248
|
msg = _(
|
|
@@ -3174,7 +3253,7 @@ revert to release the new server and restart the old one."""
|
|
|
3174
3253
|
)
|
|
3175
3254
|
self.log.warning(msg)
|
|
3176
3255
|
|
|
3177
|
-
|
|
3256
|
+
compute_client.live_migrate_server(server, **kwargs)
|
|
3178
3257
|
else: # cold migration
|
|
3179
3258
|
if parsed_args.block_migration or parsed_args.disk_overcommit:
|
|
3180
3259
|
raise exceptions.CommandError(
|
|
@@ -3183,9 +3262,7 @@ revert to release the new server and restart the old one."""
|
|
|
3183
3262
|
"specified"
|
|
3184
3263
|
)
|
|
3185
3264
|
if parsed_args.host:
|
|
3186
|
-
if compute_client
|
|
3187
|
-
'2.56'
|
|
3188
|
-
):
|
|
3265
|
+
if not sdk_utils.supports_microversion(compute_client, '2.56'):
|
|
3189
3266
|
msg = _(
|
|
3190
3267
|
'--os-compute-api-version 2.56 or greater is '
|
|
3191
3268
|
'required to use --host without --live-migration.'
|
|
@@ -3193,16 +3270,21 @@ revert to release the new server and restart the old one."""
|
|
|
3193
3270
|
raise exceptions.CommandError(msg)
|
|
3194
3271
|
|
|
3195
3272
|
kwargs = {'host': parsed_args.host} if parsed_args.host else {}
|
|
3196
|
-
|
|
3273
|
+
compute_client.migrate_server(server, **kwargs)
|
|
3197
3274
|
|
|
3198
3275
|
if parsed_args.wait:
|
|
3199
3276
|
if utils.wait_for_status(
|
|
3200
|
-
compute_client.
|
|
3277
|
+
compute_client.get_server,
|
|
3201
3278
|
server.id,
|
|
3202
|
-
success_status=
|
|
3279
|
+
success_status=('active', 'verify_resize'),
|
|
3203
3280
|
callback=_show_progress,
|
|
3204
3281
|
):
|
|
3205
|
-
self.app.stdout.write(
|
|
3282
|
+
self.app.stdout.write(
|
|
3283
|
+
_(
|
|
3284
|
+
'Complete, check success/failure by '
|
|
3285
|
+
'openstack server migration/event list/show\n'
|
|
3286
|
+
)
|
|
3287
|
+
)
|
|
3206
3288
|
else:
|
|
3207
3289
|
msg = _('Error migrating server: %s') % server.id
|
|
3208
3290
|
raise exceptions.CommandError(msg)
|
|
@@ -3212,7 +3294,7 @@ class PauseServer(command.Command):
|
|
|
3212
3294
|
_description = _("Pause server(s)")
|
|
3213
3295
|
|
|
3214
3296
|
def get_parser(self, prog_name):
|
|
3215
|
-
parser = super(
|
|
3297
|
+
parser = super().get_parser(prog_name)
|
|
3216
3298
|
parser.add_argument(
|
|
3217
3299
|
'server',
|
|
3218
3300
|
metavar='<server>',
|
|
@@ -3295,7 +3377,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3295
3377
|
_description = _("Rebuild server")
|
|
3296
3378
|
|
|
3297
3379
|
def get_parser(self, prog_name):
|
|
3298
|
-
parser = super(
|
|
3380
|
+
parser = super().get_parser(prog_name)
|
|
3299
3381
|
parser.add_argument(
|
|
3300
3382
|
'server',
|
|
3301
3383
|
metavar='<server>',
|
|
@@ -3476,11 +3558,11 @@ class RebuildServer(command.ShowOne):
|
|
|
3476
3558
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
3477
3559
|
self.app.stdout.flush()
|
|
3478
3560
|
|
|
3479
|
-
compute_client = self.app.client_manager.compute
|
|
3561
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3480
3562
|
image_client = self.app.client_manager.image
|
|
3481
3563
|
|
|
3482
|
-
server =
|
|
3483
|
-
|
|
3564
|
+
server = compute_client.find_server(
|
|
3565
|
+
parsed_args.server, ignore_missing=False
|
|
3484
3566
|
)
|
|
3485
3567
|
|
|
3486
3568
|
# If parsed_args.image is not set and if the instance is image backed,
|
|
@@ -3492,7 +3574,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3492
3574
|
parsed_args.image, ignore_missing=False
|
|
3493
3575
|
)
|
|
3494
3576
|
else:
|
|
3495
|
-
if not server.image:
|
|
3577
|
+
if not server.image or not server.image.id:
|
|
3496
3578
|
msg = _(
|
|
3497
3579
|
'The --image option is required when rebuilding a '
|
|
3498
3580
|
'volume-backed server'
|
|
@@ -3509,10 +3591,10 @@ class RebuildServer(command.ShowOne):
|
|
|
3509
3591
|
kwargs['preserve_ephemeral'] = parsed_args.preserve_ephemeral
|
|
3510
3592
|
|
|
3511
3593
|
if parsed_args.properties:
|
|
3512
|
-
kwargs['
|
|
3594
|
+
kwargs['metadata'] = parsed_args.properties
|
|
3513
3595
|
|
|
3514
3596
|
if parsed_args.description:
|
|
3515
|
-
if
|
|
3597
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
3516
3598
|
msg = _(
|
|
3517
3599
|
'--os-compute-api-version 2.19 or greater is required to '
|
|
3518
3600
|
'support the --description option'
|
|
@@ -3522,7 +3604,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3522
3604
|
kwargs['description'] = parsed_args.description
|
|
3523
3605
|
|
|
3524
3606
|
if parsed_args.key_name:
|
|
3525
|
-
if
|
|
3607
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3526
3608
|
msg = _(
|
|
3527
3609
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3528
3610
|
'support the --key-name option'
|
|
@@ -3531,7 +3613,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3531
3613
|
|
|
3532
3614
|
kwargs['key_name'] = parsed_args.key_name
|
|
3533
3615
|
elif parsed_args.no_key_name:
|
|
3534
|
-
if
|
|
3616
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3535
3617
|
msg = _(
|
|
3536
3618
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3537
3619
|
'support the --no-key-name option'
|
|
@@ -3540,9 +3622,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3540
3622
|
|
|
3541
3623
|
kwargs['key_name'] = None
|
|
3542
3624
|
|
|
3543
|
-
userdata = None
|
|
3544
3625
|
if parsed_args.user_data:
|
|
3545
|
-
if
|
|
3626
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3546
3627
|
msg = _(
|
|
3547
3628
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3548
3629
|
'support the --user-data option'
|
|
@@ -3550,27 +3631,29 @@ class RebuildServer(command.ShowOne):
|
|
|
3550
3631
|
raise exceptions.CommandError(msg)
|
|
3551
3632
|
|
|
3552
3633
|
try:
|
|
3553
|
-
|
|
3554
|
-
|
|
3634
|
+
with open(parsed_args.user_data, 'rb') as fh:
|
|
3635
|
+
# TODO(stephenfin): SDK should do this for us
|
|
3636
|
+
user_data = base64.b64encode(fh.read()).decode('utf-8')
|
|
3637
|
+
except OSError as e:
|
|
3555
3638
|
msg = _("Can't open '%(data)s': %(exception)s")
|
|
3556
3639
|
raise exceptions.CommandError(
|
|
3557
3640
|
msg % {'data': parsed_args.user_data, 'exception': e}
|
|
3558
3641
|
)
|
|
3559
3642
|
|
|
3560
|
-
kwargs['
|
|
3643
|
+
kwargs['user_data'] = user_data
|
|
3561
3644
|
elif parsed_args.no_user_data:
|
|
3562
|
-
if
|
|
3645
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3563
3646
|
msg = _(
|
|
3564
3647
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3565
3648
|
'support the --no-user-data option'
|
|
3566
3649
|
)
|
|
3567
3650
|
raise exceptions.CommandError(msg)
|
|
3568
3651
|
|
|
3569
|
-
kwargs['
|
|
3652
|
+
kwargs['user_data'] = None
|
|
3570
3653
|
|
|
3571
3654
|
# TODO(stephenfin): Handle OS_TRUSTED_IMAGE_CERTIFICATE_IDS
|
|
3572
3655
|
if parsed_args.trusted_image_certs:
|
|
3573
|
-
if
|
|
3656
|
+
if not sdk_utils.supports_microversion(compute_client, '2.63'):
|
|
3574
3657
|
msg = _(
|
|
3575
3658
|
'--os-compute-api-version 2.63 or greater is required to '
|
|
3576
3659
|
'support the --trusted-certs option'
|
|
@@ -3580,7 +3663,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3580
3663
|
certs = parsed_args.trusted_image_certs
|
|
3581
3664
|
kwargs['trusted_image_certificates'] = certs
|
|
3582
3665
|
elif parsed_args.no_trusted_image_certs:
|
|
3583
|
-
if
|
|
3666
|
+
if not sdk_utils.supports_microversion(compute_client, '2.63'):
|
|
3584
3667
|
msg = _(
|
|
3585
3668
|
'--os-compute-api-version 2.63 or greater is required to '
|
|
3586
3669
|
'support the --no-trusted-certs option'
|
|
@@ -3590,7 +3673,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3590
3673
|
kwargs['trusted_image_certificates'] = None
|
|
3591
3674
|
|
|
3592
3675
|
if parsed_args.hostname:
|
|
3593
|
-
if
|
|
3676
|
+
if not sdk_utils.supports_microversion(compute_client, '2.90'):
|
|
3594
3677
|
msg = _(
|
|
3595
3678
|
'--os-compute-api-version 2.90 or greater is required to '
|
|
3596
3679
|
'support the --hostname option'
|
|
@@ -3599,9 +3682,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3599
3682
|
|
|
3600
3683
|
kwargs['hostname'] = parsed_args.hostname
|
|
3601
3684
|
|
|
3602
|
-
v2_93 = api_versions.APIVersion('2.93')
|
|
3603
3685
|
if parsed_args.reimage_boot_volume:
|
|
3604
|
-
if compute_client.
|
|
3686
|
+
if not sdk_utils.supports_microversion(compute_client, '2.93'):
|
|
3605
3687
|
msg = _(
|
|
3606
3688
|
'--os-compute-api-version 2.93 or greater is required to '
|
|
3607
3689
|
'support the --reimage-boot-volume option'
|
|
@@ -3610,8 +3692,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3610
3692
|
else:
|
|
3611
3693
|
# force user to explicitly request reimaging of volume-backed
|
|
3612
3694
|
# server
|
|
3613
|
-
if not server.image:
|
|
3614
|
-
if compute_client.
|
|
3695
|
+
if not server.image or not server.image.id:
|
|
3696
|
+
if sdk_utils.supports_microversion(compute_client, '2.93'):
|
|
3615
3697
|
msg = (
|
|
3616
3698
|
'--reimage-boot-volume is required to rebuild a '
|
|
3617
3699
|
'volume-backed server'
|
|
@@ -3643,15 +3725,13 @@ class RebuildServer(command.ShowOne):
|
|
|
3643
3725
|
msg = _("The server status is not ACTIVE, SHUTOFF or ERROR.")
|
|
3644
3726
|
raise exceptions.CommandError(msg)
|
|
3645
3727
|
|
|
3646
|
-
|
|
3647
|
-
server
|
|
3648
|
-
|
|
3649
|
-
if userdata and hasattr(userdata, 'close'):
|
|
3650
|
-
userdata.close()
|
|
3728
|
+
server = compute_client.rebuild_server(
|
|
3729
|
+
server, image, admin_password=parsed_args.password, **kwargs
|
|
3730
|
+
)
|
|
3651
3731
|
|
|
3652
3732
|
if parsed_args.wait:
|
|
3653
3733
|
if utils.wait_for_status(
|
|
3654
|
-
compute_client.
|
|
3734
|
+
compute_client.get_server,
|
|
3655
3735
|
server.id,
|
|
3656
3736
|
callback=_show_progress,
|
|
3657
3737
|
success_status=success_status,
|
|
@@ -3661,10 +3741,10 @@ class RebuildServer(command.ShowOne):
|
|
|
3661
3741
|
msg = _('Error rebuilding server: %s') % server.id
|
|
3662
3742
|
raise exceptions.CommandError(msg)
|
|
3663
3743
|
|
|
3664
|
-
|
|
3744
|
+
data = _prep_server_detail(
|
|
3665
3745
|
compute_client, image_client, server, refresh=False
|
|
3666
3746
|
)
|
|
3667
|
-
return zip(*sorted(
|
|
3747
|
+
return zip(*sorted(data.items()))
|
|
3668
3748
|
|
|
3669
3749
|
|
|
3670
3750
|
class EvacuateServer(command.ShowOne):
|
|
@@ -3686,13 +3766,12 @@ host."""
|
|
|
3686
3766
|
)
|
|
3687
3767
|
|
|
3688
3768
|
def get_parser(self, prog_name):
|
|
3689
|
-
parser = super(
|
|
3769
|
+
parser = super().get_parser(prog_name)
|
|
3690
3770
|
parser.add_argument(
|
|
3691
3771
|
'server',
|
|
3692
3772
|
metavar='<server>',
|
|
3693
3773
|
help=_('Server (name or ID)'),
|
|
3694
3774
|
)
|
|
3695
|
-
|
|
3696
3775
|
parser.add_argument(
|
|
3697
3776
|
'--wait',
|
|
3698
3777
|
action='store_true',
|
|
@@ -3739,11 +3818,11 @@ host."""
|
|
|
3739
3818
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
3740
3819
|
self.app.stdout.flush()
|
|
3741
3820
|
|
|
3742
|
-
compute_client = self.app.client_manager.compute
|
|
3821
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3743
3822
|
image_client = self.app.client_manager.image
|
|
3744
3823
|
|
|
3745
3824
|
if parsed_args.host:
|
|
3746
|
-
if
|
|
3825
|
+
if not sdk_utils.supports_microversion(compute_client, '2.29'):
|
|
3747
3826
|
msg = _(
|
|
3748
3827
|
'--os-compute-api-version 2.29 or later is required '
|
|
3749
3828
|
'to specify a preferred host.'
|
|
@@ -3751,7 +3830,7 @@ host."""
|
|
|
3751
3830
|
raise exceptions.CommandError(msg)
|
|
3752
3831
|
|
|
3753
3832
|
if parsed_args.shared_storage:
|
|
3754
|
-
if compute_client
|
|
3833
|
+
if sdk_utils.supports_microversion(compute_client, '2.14'):
|
|
3755
3834
|
msg = _(
|
|
3756
3835
|
'--os-compute-api-version 2.13 or earlier is required '
|
|
3757
3836
|
'to specify shared-storage.'
|
|
@@ -3763,18 +3842,17 @@ host."""
|
|
|
3763
3842
|
'password': parsed_args.password,
|
|
3764
3843
|
}
|
|
3765
3844
|
|
|
3766
|
-
if
|
|
3845
|
+
if not sdk_utils.supports_microversion(compute_client, '2.14'):
|
|
3767
3846
|
kwargs['on_shared_storage'] = parsed_args.shared_storage
|
|
3768
3847
|
|
|
3769
|
-
server =
|
|
3770
|
-
|
|
3848
|
+
server = compute_client.find_server(
|
|
3849
|
+
parsed_args.server, ignore_missing=False
|
|
3771
3850
|
)
|
|
3772
|
-
|
|
3773
|
-
server.evacuate(**kwargs)
|
|
3851
|
+
compute_client.evacuate_server(server, **kwargs)
|
|
3774
3852
|
|
|
3775
3853
|
if parsed_args.wait:
|
|
3776
3854
|
if utils.wait_for_status(
|
|
3777
|
-
compute_client.
|
|
3855
|
+
compute_client.get_server,
|
|
3778
3856
|
server.id,
|
|
3779
3857
|
callback=_show_progress,
|
|
3780
3858
|
):
|
|
@@ -3783,17 +3861,15 @@ host."""
|
|
|
3783
3861
|
msg = _('Error evacuating server: %s') % server.id
|
|
3784
3862
|
raise exceptions.CommandError(msg)
|
|
3785
3863
|
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
)
|
|
3789
|
-
return zip(*sorted(details.items()))
|
|
3864
|
+
data = _prep_server_detail(compute_client, image_client, server)
|
|
3865
|
+
return zip(*sorted(data.items()))
|
|
3790
3866
|
|
|
3791
3867
|
|
|
3792
3868
|
class RemoveFixedIP(command.Command):
|
|
3793
3869
|
_description = _("Remove fixed IP address from server")
|
|
3794
3870
|
|
|
3795
3871
|
def get_parser(self, prog_name):
|
|
3796
|
-
parser = super(
|
|
3872
|
+
parser = super().get_parser(prog_name)
|
|
3797
3873
|
parser.add_argument(
|
|
3798
3874
|
"server",
|
|
3799
3875
|
metavar="<server>",
|
|
@@ -3807,13 +3883,14 @@ class RemoveFixedIP(command.Command):
|
|
|
3807
3883
|
return parser
|
|
3808
3884
|
|
|
3809
3885
|
def take_action(self, parsed_args):
|
|
3810
|
-
compute_client = self.app.client_manager.compute
|
|
3886
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3811
3887
|
|
|
3812
|
-
server =
|
|
3813
|
-
|
|
3888
|
+
server = compute_client.find_server(
|
|
3889
|
+
parsed_args.server, ignore_missing=False
|
|
3890
|
+
)
|
|
3891
|
+
compute_client.remove_fixed_ip_from_server(
|
|
3892
|
+
server, parsed_args.ip_address
|
|
3814
3893
|
)
|
|
3815
|
-
|
|
3816
|
-
server.remove_fixed_ip(parsed_args.ip_address)
|
|
3817
3894
|
|
|
3818
3895
|
|
|
3819
3896
|
class RemoveFloatingIP(network_common.NetworkAndComputeCommand):
|
|
@@ -3845,17 +3922,15 @@ class RemoveFloatingIP(network_common.NetworkAndComputeCommand):
|
|
|
3845
3922
|
client.update_ip(obj, **attrs)
|
|
3846
3923
|
|
|
3847
3924
|
def take_action_compute(self, client, parsed_args):
|
|
3848
|
-
client.
|
|
3849
|
-
|
|
3850
|
-
parsed_args.ip_address,
|
|
3851
|
-
)
|
|
3925
|
+
server = client.find_server(parsed_args.server, ignore_missing=False)
|
|
3926
|
+
client.remove_floating_ip_from_server(server, parsed_args.ip_address)
|
|
3852
3927
|
|
|
3853
3928
|
|
|
3854
3929
|
class RemovePort(command.Command):
|
|
3855
3930
|
_description = _("Remove port from server")
|
|
3856
3931
|
|
|
3857
3932
|
def get_parser(self, prog_name):
|
|
3858
|
-
parser = super(
|
|
3933
|
+
parser = super().get_parser(prog_name)
|
|
3859
3934
|
parser.add_argument(
|
|
3860
3935
|
"server",
|
|
3861
3936
|
metavar="<server>",
|
|
@@ -3894,7 +3969,7 @@ class RemoveNetwork(command.Command):
|
|
|
3894
3969
|
_description = _("Remove all ports of a network from server")
|
|
3895
3970
|
|
|
3896
3971
|
def get_parser(self, prog_name):
|
|
3897
|
-
parser = super(
|
|
3972
|
+
parser = super().get_parser(prog_name)
|
|
3898
3973
|
parser.add_argument(
|
|
3899
3974
|
"server",
|
|
3900
3975
|
metavar="<server>",
|
|
@@ -3934,32 +4009,38 @@ class RemoveServerSecurityGroup(command.Command):
|
|
|
3934
4009
|
_description = _("Remove security group from server")
|
|
3935
4010
|
|
|
3936
4011
|
def get_parser(self, prog_name):
|
|
3937
|
-
parser = super(
|
|
4012
|
+
parser = super().get_parser(prog_name)
|
|
3938
4013
|
parser.add_argument(
|
|
3939
4014
|
'server',
|
|
3940
4015
|
metavar='<server>',
|
|
3941
|
-
help=_('
|
|
4016
|
+
help=_('Server (name or ID)'),
|
|
3942
4017
|
)
|
|
3943
4018
|
parser.add_argument(
|
|
3944
4019
|
'group',
|
|
3945
4020
|
metavar='<group>',
|
|
3946
|
-
help=_('
|
|
4021
|
+
help=_('Security group to remove (name or ID)'),
|
|
3947
4022
|
)
|
|
3948
4023
|
return parser
|
|
3949
4024
|
|
|
3950
4025
|
def take_action(self, parsed_args):
|
|
3951
|
-
compute_client = self.app.client_manager.compute
|
|
4026
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3952
4027
|
|
|
3953
|
-
server =
|
|
3954
|
-
|
|
3955
|
-
parsed_args.server,
|
|
4028
|
+
server = compute_client.find_server(
|
|
4029
|
+
parsed_args.server, ignore_missing=False
|
|
3956
4030
|
)
|
|
3957
|
-
|
|
3958
|
-
|
|
4031
|
+
if self.app.client_manager.is_network_endpoint_enabled():
|
|
4032
|
+
# the server handles both names and IDs for neutron SGs, so just
|
|
4033
|
+
# pass things through
|
|
4034
|
+
security_group = parsed_args.group
|
|
4035
|
+
else:
|
|
4036
|
+
# however, if using nova-network then it needs a name, not an ID
|
|
4037
|
+
security_group = compute_v2.find_security_group(
|
|
4038
|
+
compute_client, parsed_args.group
|
|
4039
|
+
)['name']
|
|
4040
|
+
compute_client.remove_security_group_from_server(
|
|
4041
|
+
server, security_group
|
|
3959
4042
|
)
|
|
3960
4043
|
|
|
3961
|
-
server.remove_security_group(security_group['id'])
|
|
3962
|
-
|
|
3963
4044
|
|
|
3964
4045
|
class RemoveServerVolume(command.Command):
|
|
3965
4046
|
_description = _(
|
|
@@ -3970,7 +4051,7 @@ volume from a server with status ``SHELVED`` or ``SHELVED_OFFLOADED``."""
|
|
|
3970
4051
|
)
|
|
3971
4052
|
|
|
3972
4053
|
def get_parser(self, prog_name):
|
|
3973
|
-
parser = super(
|
|
4054
|
+
parser = super().get_parser(prog_name)
|
|
3974
4055
|
parser.add_argument(
|
|
3975
4056
|
'server',
|
|
3976
4057
|
metavar='<server>',
|
|
@@ -4012,7 +4093,7 @@ server booted from a volume."""
|
|
|
4012
4093
|
)
|
|
4013
4094
|
|
|
4014
4095
|
def get_parser(self, prog_name):
|
|
4015
|
-
parser = super(
|
|
4096
|
+
parser = super().get_parser(prog_name)
|
|
4016
4097
|
parser.add_argument(
|
|
4017
4098
|
'server',
|
|
4018
4099
|
metavar='<server>',
|
|
@@ -4022,34 +4103,36 @@ server booted from a volume."""
|
|
|
4022
4103
|
'--image',
|
|
4023
4104
|
metavar='<image>',
|
|
4024
4105
|
help=_(
|
|
4025
|
-
'Image (name or ID) to use for the rescue mode
|
|
4026
|
-
'
|
|
4106
|
+
'Image (name or ID) to use for the rescue mode '
|
|
4107
|
+
'(defaults to the currently used one)'
|
|
4027
4108
|
),
|
|
4028
4109
|
)
|
|
4029
4110
|
parser.add_argument(
|
|
4030
4111
|
'--password',
|
|
4031
4112
|
metavar='<password>',
|
|
4032
4113
|
help=_(
|
|
4033
|
-
'Set the password on the rescued instance
|
|
4034
|
-
'
|
|
4114
|
+
'Set the password on the rescued instance '
|
|
4115
|
+
'(requires cloud support)'
|
|
4035
4116
|
),
|
|
4036
4117
|
)
|
|
4037
4118
|
return parser
|
|
4038
4119
|
|
|
4039
4120
|
def take_action(self, parsed_args):
|
|
4040
|
-
compute_client = self.app.client_manager.compute
|
|
4121
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4041
4122
|
image_client = self.app.client_manager.image
|
|
4042
4123
|
|
|
4043
|
-
|
|
4124
|
+
image_ref = None
|
|
4044
4125
|
if parsed_args.image:
|
|
4045
|
-
|
|
4126
|
+
image_ref = image_client.find_image(
|
|
4046
4127
|
parsed_args.image, ignore_missing=False
|
|
4047
|
-
)
|
|
4128
|
+
).id
|
|
4048
4129
|
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4130
|
+
server = compute_client.find_server(
|
|
4131
|
+
parsed_args.server, ignore_missing=False
|
|
4132
|
+
)
|
|
4133
|
+
compute_client.rescue_server(
|
|
4134
|
+
server, admin_pass=parsed_args.password, image_ref=image_ref
|
|
4135
|
+
)
|
|
4053
4136
|
|
|
4054
4137
|
|
|
4055
4138
|
class ResizeServer(command.Command):
|
|
@@ -4064,13 +4147,13 @@ release the new server and restart the old one."""
|
|
|
4064
4147
|
)
|
|
4065
4148
|
|
|
4066
4149
|
def get_parser(self, prog_name):
|
|
4067
|
-
parser = super(
|
|
4068
|
-
phase_group = parser.add_mutually_exclusive_group()
|
|
4150
|
+
parser = super().get_parser(prog_name)
|
|
4069
4151
|
parser.add_argument(
|
|
4070
4152
|
'server',
|
|
4071
4153
|
metavar='<server>',
|
|
4072
4154
|
help=_('Server (name or ID)'),
|
|
4073
4155
|
)
|
|
4156
|
+
phase_group = parser.add_mutually_exclusive_group()
|
|
4074
4157
|
phase_group.add_argument(
|
|
4075
4158
|
'--flavor',
|
|
4076
4159
|
metavar='<flavor>',
|
|
@@ -4107,16 +4190,11 @@ release the new server and restart the old one."""
|
|
|
4107
4190
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
4108
4191
|
self.app.stdout.flush()
|
|
4109
4192
|
|
|
4110
|
-
compute_client = self.app.client_manager.compute
|
|
4111
|
-
server =
|
|
4112
|
-
|
|
4113
|
-
parsed_args.server,
|
|
4193
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4194
|
+
server = compute_client.find_server(
|
|
4195
|
+
parsed_args.server, ignore_missing=False
|
|
4114
4196
|
)
|
|
4115
4197
|
if parsed_args.flavor:
|
|
4116
|
-
flavor = utils.find_resource(
|
|
4117
|
-
compute_client.flavors,
|
|
4118
|
-
parsed_args.flavor,
|
|
4119
|
-
)
|
|
4120
4198
|
if not server.image:
|
|
4121
4199
|
self.log.warning(
|
|
4122
4200
|
_(
|
|
@@ -4124,18 +4202,21 @@ release the new server and restart the old one."""
|
|
|
4124
4202
|
"while booting from a persistent volume."
|
|
4125
4203
|
)
|
|
4126
4204
|
)
|
|
4127
|
-
compute_client.
|
|
4205
|
+
flavor = compute_client.find_flavor(
|
|
4206
|
+
parsed_args.flavor, ignore_missing=False
|
|
4207
|
+
)
|
|
4208
|
+
compute_client.resize_server(server, flavor)
|
|
4128
4209
|
if parsed_args.wait:
|
|
4129
|
-
if utils.wait_for_status(
|
|
4130
|
-
compute_client.
|
|
4210
|
+
if not utils.wait_for_status(
|
|
4211
|
+
compute_client.get_server,
|
|
4131
4212
|
server.id,
|
|
4132
|
-
success_status=
|
|
4213
|
+
success_status=('active', 'verify_resize'),
|
|
4133
4214
|
callback=_show_progress,
|
|
4134
4215
|
):
|
|
4135
|
-
self.app.stdout.write(_('Complete\n'))
|
|
4136
|
-
else:
|
|
4137
4216
|
msg = _('Error resizing server: %s') % server.id
|
|
4138
4217
|
raise exceptions.CommandError(msg)
|
|
4218
|
+
|
|
4219
|
+
self.app.stdout.write(_('Complete\n'))
|
|
4139
4220
|
elif parsed_args.confirm:
|
|
4140
4221
|
self.log.warning(
|
|
4141
4222
|
_(
|
|
@@ -4143,7 +4224,7 @@ release the new server and restart the old one."""
|
|
|
4143
4224
|
"'openstack server resize confirm' command instead."
|
|
4144
4225
|
)
|
|
4145
4226
|
)
|
|
4146
|
-
compute_client.
|
|
4227
|
+
compute_client.confirm_server_resize(server)
|
|
4147
4228
|
elif parsed_args.revert:
|
|
4148
4229
|
self.log.warning(
|
|
4149
4230
|
_(
|
|
@@ -4151,7 +4232,7 @@ release the new server and restart the old one."""
|
|
|
4151
4232
|
"'openstack server resize revert' command instead."
|
|
4152
4233
|
)
|
|
4153
4234
|
)
|
|
4154
|
-
compute_client.
|
|
4235
|
+
compute_client.revert_server_resize(server)
|
|
4155
4236
|
|
|
4156
4237
|
|
|
4157
4238
|
class ResizeConfirm(command.Command):
|
|
@@ -4162,7 +4243,7 @@ Confirm (verify) success of resize operation and release the old server."""
|
|
|
4162
4243
|
)
|
|
4163
4244
|
|
|
4164
4245
|
def get_parser(self, prog_name):
|
|
4165
|
-
parser = super(
|
|
4246
|
+
parser = super().get_parser(prog_name)
|
|
4166
4247
|
parser.add_argument(
|
|
4167
4248
|
'server',
|
|
4168
4249
|
metavar='<server>',
|
|
@@ -4171,12 +4252,11 @@ Confirm (verify) success of resize operation and release the old server."""
|
|
|
4171
4252
|
return parser
|
|
4172
4253
|
|
|
4173
4254
|
def take_action(self, parsed_args):
|
|
4174
|
-
compute_client = self.app.client_manager.compute
|
|
4175
|
-
server =
|
|
4176
|
-
|
|
4177
|
-
parsed_args.server,
|
|
4255
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4256
|
+
server = compute_client.find_server(
|
|
4257
|
+
parsed_args.server, ignore_missing=False
|
|
4178
4258
|
)
|
|
4179
|
-
|
|
4259
|
+
compute_client.confirm_server_resize(server)
|
|
4180
4260
|
|
|
4181
4261
|
|
|
4182
4262
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
@@ -4211,7 +4291,7 @@ one."""
|
|
|
4211
4291
|
)
|
|
4212
4292
|
|
|
4213
4293
|
def get_parser(self, prog_name):
|
|
4214
|
-
parser = super(
|
|
4294
|
+
parser = super().get_parser(prog_name)
|
|
4215
4295
|
parser.add_argument(
|
|
4216
4296
|
'server',
|
|
4217
4297
|
metavar='<server>',
|
|
@@ -4220,12 +4300,11 @@ one."""
|
|
|
4220
4300
|
return parser
|
|
4221
4301
|
|
|
4222
4302
|
def take_action(self, parsed_args):
|
|
4223
|
-
compute_client = self.app.client_manager.compute
|
|
4224
|
-
server =
|
|
4225
|
-
|
|
4226
|
-
parsed_args.server,
|
|
4303
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4304
|
+
server = compute_client.find_server(
|
|
4305
|
+
parsed_args.server, ignore_missing=False
|
|
4227
4306
|
)
|
|
4228
|
-
|
|
4307
|
+
compute_client.revert_server_resize(server)
|
|
4229
4308
|
|
|
4230
4309
|
|
|
4231
4310
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
@@ -4255,7 +4334,7 @@ class RestoreServer(command.Command):
|
|
|
4255
4334
|
_description = _("Restore server(s)")
|
|
4256
4335
|
|
|
4257
4336
|
def get_parser(self, prog_name):
|
|
4258
|
-
parser = super(
|
|
4337
|
+
parser = super().get_parser(prog_name)
|
|
4259
4338
|
parser.add_argument(
|
|
4260
4339
|
'server',
|
|
4261
4340
|
metavar='<server>',
|
|
@@ -4278,7 +4357,7 @@ class ResumeServer(command.Command):
|
|
|
4278
4357
|
_description = _("Resume server(s)")
|
|
4279
4358
|
|
|
4280
4359
|
def get_parser(self, prog_name):
|
|
4281
|
-
parser = super(
|
|
4360
|
+
parser = super().get_parser(prog_name)
|
|
4282
4361
|
parser.add_argument(
|
|
4283
4362
|
'server',
|
|
4284
4363
|
metavar='<server>',
|
|
@@ -4301,7 +4380,7 @@ class SetServer(command.Command):
|
|
|
4301
4380
|
_description = _("Set server properties")
|
|
4302
4381
|
|
|
4303
4382
|
def get_parser(self, prog_name):
|
|
4304
|
-
parser = super(
|
|
4383
|
+
parser = super().get_parser(prog_name)
|
|
4305
4384
|
parser.add_argument(
|
|
4306
4385
|
'server',
|
|
4307
4386
|
metavar='<server>',
|
|
@@ -4389,14 +4468,13 @@ class SetServer(command.Command):
|
|
|
4389
4468
|
return parser
|
|
4390
4469
|
|
|
4391
4470
|
def take_action(self, parsed_args):
|
|
4392
|
-
compute_client = self.app.client_manager.compute
|
|
4393
|
-
server =
|
|
4394
|
-
|
|
4395
|
-
parsed_args.server,
|
|
4471
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4472
|
+
server = compute_client.find_server(
|
|
4473
|
+
parsed_args.server, ignore_missing=False
|
|
4396
4474
|
)
|
|
4397
4475
|
|
|
4398
4476
|
if parsed_args.description:
|
|
4399
|
-
if
|
|
4477
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
4400
4478
|
msg = _(
|
|
4401
4479
|
'--os-compute-api-version 2.19 or greater is required to '
|
|
4402
4480
|
'support the --description option'
|
|
@@ -4404,7 +4482,7 @@ class SetServer(command.Command):
|
|
|
4404
4482
|
raise exceptions.CommandError(msg)
|
|
4405
4483
|
|
|
4406
4484
|
if parsed_args.tags:
|
|
4407
|
-
if
|
|
4485
|
+
if not sdk_utils.supports_microversion(compute_client, '2.26'):
|
|
4408
4486
|
msg = _(
|
|
4409
4487
|
'--os-compute-api-version 2.26 or greater is required to '
|
|
4410
4488
|
'support the --tag option'
|
|
@@ -4412,7 +4490,7 @@ class SetServer(command.Command):
|
|
|
4412
4490
|
raise exceptions.CommandError(msg)
|
|
4413
4491
|
|
|
4414
4492
|
if parsed_args.hostname:
|
|
4415
|
-
if
|
|
4493
|
+
if not sdk_utils.supports_microversion(compute_client, '2.90'):
|
|
4416
4494
|
msg = _(
|
|
4417
4495
|
'--os-compute-api-version 2.90 or greater is required to '
|
|
4418
4496
|
'support the --hostname option'
|
|
@@ -4431,30 +4509,32 @@ class SetServer(command.Command):
|
|
|
4431
4509
|
update_kwargs['hostname'] = parsed_args.hostname
|
|
4432
4510
|
|
|
4433
4511
|
if update_kwargs:
|
|
4434
|
-
|
|
4512
|
+
compute_client.update_server(server, **update_kwargs)
|
|
4435
4513
|
|
|
4436
4514
|
if parsed_args.properties:
|
|
4437
|
-
compute_client.
|
|
4515
|
+
compute_client.set_server_metadata(
|
|
4516
|
+
server, **parsed_args.properties
|
|
4517
|
+
)
|
|
4438
4518
|
|
|
4439
4519
|
if parsed_args.state:
|
|
4440
|
-
|
|
4520
|
+
compute_client.reset_server_state(server, state=parsed_args.state)
|
|
4441
4521
|
|
|
4442
4522
|
if parsed_args.root_password:
|
|
4443
4523
|
p1 = getpass.getpass(_('New password: '))
|
|
4444
4524
|
p2 = getpass.getpass(_('Retype new password: '))
|
|
4445
4525
|
if p1 == p2:
|
|
4446
|
-
|
|
4526
|
+
compute_client.change_server_password(server, p1)
|
|
4447
4527
|
else:
|
|
4448
4528
|
msg = _("Passwords do not match, password unchanged")
|
|
4449
4529
|
raise exceptions.CommandError(msg)
|
|
4450
4530
|
elif parsed_args.password:
|
|
4451
|
-
|
|
4531
|
+
compute_client.change_server_password(server, parsed_args.password)
|
|
4452
4532
|
elif parsed_args.no_password:
|
|
4453
|
-
|
|
4533
|
+
compute_client.clear_server_password(server)
|
|
4454
4534
|
|
|
4455
4535
|
if parsed_args.tags:
|
|
4456
4536
|
for tag in parsed_args.tags:
|
|
4457
|
-
|
|
4537
|
+
compute_client.add_tag_to_server(server, tag=tag)
|
|
4458
4538
|
|
|
4459
4539
|
|
|
4460
4540
|
class ShelveServer(command.Command):
|
|
@@ -4575,7 +4655,7 @@ information for the server."""
|
|
|
4575
4655
|
)
|
|
4576
4656
|
|
|
4577
4657
|
def get_parser(self, prog_name):
|
|
4578
|
-
parser = super(
|
|
4658
|
+
parser = super().get_parser(prog_name)
|
|
4579
4659
|
parser.add_argument(
|
|
4580
4660
|
'server',
|
|
4581
4661
|
metavar='<server>',
|
|
@@ -4602,12 +4682,13 @@ information for the server."""
|
|
|
4602
4682
|
|
|
4603
4683
|
def take_action(self, parsed_args):
|
|
4604
4684
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4685
|
+
image_client = self.app.client_manager.image
|
|
4605
4686
|
|
|
4606
|
-
# Find by name or ID, then get the full details of the server
|
|
4607
4687
|
server = compute_client.find_server(
|
|
4608
|
-
parsed_args.server,
|
|
4688
|
+
parsed_args.server,
|
|
4689
|
+
ignore_missing=False,
|
|
4690
|
+
details=True,
|
|
4609
4691
|
)
|
|
4610
|
-
server = compute_client.get_server(server)
|
|
4611
4692
|
|
|
4612
4693
|
if parsed_args.diagnostics:
|
|
4613
4694
|
data = compute_client.get_server_diagnostics(server)
|
|
@@ -4625,17 +4706,10 @@ information for the server."""
|
|
|
4625
4706
|
topology = server.fetch_topology(compute_client)
|
|
4626
4707
|
|
|
4627
4708
|
data = _prep_server_detail(
|
|
4628
|
-
|
|
4629
|
-
# all callers of _prep_server_detail() are using the SDK.
|
|
4630
|
-
self.app.client_manager.compute,
|
|
4631
|
-
self.app.client_manager.image,
|
|
4632
|
-
server,
|
|
4633
|
-
refresh=False,
|
|
4709
|
+
compute_client, image_client, server, refresh=False
|
|
4634
4710
|
)
|
|
4635
|
-
|
|
4636
4711
|
if topology:
|
|
4637
4712
|
data['topology'] = format_columns.DictColumn(topology)
|
|
4638
|
-
|
|
4639
4713
|
return zip(*sorted(data.items()))
|
|
4640
4714
|
|
|
4641
4715
|
|
|
@@ -4643,7 +4717,7 @@ class SshServer(command.Command):
|
|
|
4643
4717
|
_description = _("SSH to server")
|
|
4644
4718
|
|
|
4645
4719
|
def get_parser(self, prog_name):
|
|
4646
|
-
parser = super(
|
|
4720
|
+
parser = super().get_parser(prog_name)
|
|
4647
4721
|
parser.add_argument(
|
|
4648
4722
|
'server',
|
|
4649
4723
|
metavar='<server>',
|
|
@@ -4737,11 +4811,10 @@ class SshServer(command.Command):
|
|
|
4737
4811
|
return parser
|
|
4738
4812
|
|
|
4739
4813
|
def take_action(self, parsed_args):
|
|
4740
|
-
compute_client = self.app.client_manager.compute
|
|
4814
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4741
4815
|
|
|
4742
|
-
server =
|
|
4743
|
-
|
|
4744
|
-
parsed_args.server,
|
|
4816
|
+
server = compute_client.find_server(
|
|
4817
|
+
parsed_args.server, ignore_missing=False
|
|
4745
4818
|
)
|
|
4746
4819
|
|
|
4747
4820
|
# first, handle the deprecated options
|
|
@@ -4795,8 +4868,10 @@ class SshServer(command.Command):
|
|
|
4795
4868
|
)
|
|
4796
4869
|
|
|
4797
4870
|
cmd = ' '.join(['ssh', ip_address] + args)
|
|
4798
|
-
LOG.debug("ssh command: {cmd}"
|
|
4799
|
-
|
|
4871
|
+
LOG.debug(f"ssh command: {cmd}")
|
|
4872
|
+
# we intentionally pass through user-provided arguments and run this in
|
|
4873
|
+
# the user's shell
|
|
4874
|
+
os.system(cmd) # nosec: B605
|
|
4800
4875
|
|
|
4801
4876
|
|
|
4802
4877
|
class StartServer(command.Command):
|
|
@@ -4815,7 +4890,7 @@ class StartServer(command.Command):
|
|
|
4815
4890
|
action='store_true',
|
|
4816
4891
|
default=boolenv('ALL_PROJECTS'),
|
|
4817
4892
|
help=_(
|
|
4818
|
-
'Start server(s) in another project by name (admin only)'
|
|
4893
|
+
'Start server(s) in another project by name (admin only) '
|
|
4819
4894
|
'(can be specified using the ALL_PROJECTS envvar)'
|
|
4820
4895
|
),
|
|
4821
4896
|
)
|
|
@@ -4824,17 +4899,12 @@ class StartServer(command.Command):
|
|
|
4824
4899
|
def take_action(self, parsed_args):
|
|
4825
4900
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4826
4901
|
for server in parsed_args.server:
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
).id
|
|
4834
|
-
except sdk_exceptions.HttpException as exc:
|
|
4835
|
-
if exc.status_code == 403:
|
|
4836
|
-
msg = _("Policy doesn't allow passing all-projects")
|
|
4837
|
-
raise exceptions.Forbidden(msg)
|
|
4902
|
+
server_id = compute_client.find_server(
|
|
4903
|
+
server,
|
|
4904
|
+
ignore_missing=False,
|
|
4905
|
+
details=False,
|
|
4906
|
+
all_projects=parsed_args.all_projects,
|
|
4907
|
+
).id
|
|
4838
4908
|
|
|
4839
4909
|
compute_client.start_server(server_id)
|
|
4840
4910
|
|
|
@@ -4864,18 +4934,12 @@ class StopServer(command.Command):
|
|
|
4864
4934
|
def take_action(self, parsed_args):
|
|
4865
4935
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4866
4936
|
for server in parsed_args.server:
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
).id
|
|
4874
|
-
except sdk_exceptions.HttpException as exc:
|
|
4875
|
-
if exc.status_code == 403:
|
|
4876
|
-
msg = _("Policy doesn't allow passing all-projects")
|
|
4877
|
-
raise exceptions.Forbidden(msg)
|
|
4878
|
-
|
|
4937
|
+
server_id = compute_client.find_server(
|
|
4938
|
+
server,
|
|
4939
|
+
ignore_missing=False,
|
|
4940
|
+
details=False,
|
|
4941
|
+
all_projects=parsed_args.all_projects,
|
|
4942
|
+
).id
|
|
4879
4943
|
compute_client.stop_server(server_id)
|
|
4880
4944
|
|
|
4881
4945
|
|
|
@@ -4883,7 +4947,7 @@ class SuspendServer(command.Command):
|
|
|
4883
4947
|
_description = _("Suspend server(s)")
|
|
4884
4948
|
|
|
4885
4949
|
def get_parser(self, prog_name):
|
|
4886
|
-
parser = super(
|
|
4950
|
+
parser = super().get_parser(prog_name)
|
|
4887
4951
|
parser.add_argument(
|
|
4888
4952
|
'server',
|
|
4889
4953
|
metavar='<server>',
|
|
@@ -4929,7 +4993,7 @@ class UnpauseServer(command.Command):
|
|
|
4929
4993
|
_description = _("Unpause server(s)")
|
|
4930
4994
|
|
|
4931
4995
|
def get_parser(self, prog_name):
|
|
4932
|
-
parser = super(
|
|
4996
|
+
parser = super().get_parser(prog_name)
|
|
4933
4997
|
parser.add_argument(
|
|
4934
4998
|
'server',
|
|
4935
4999
|
metavar='<server>',
|
|
@@ -4952,7 +5016,7 @@ class UnrescueServer(command.Command):
|
|
|
4952
5016
|
_description = _("Restore server from rescue mode")
|
|
4953
5017
|
|
|
4954
5018
|
def get_parser(self, prog_name):
|
|
4955
|
-
parser = super(
|
|
5019
|
+
parser = super().get_parser(prog_name)
|
|
4956
5020
|
parser.add_argument(
|
|
4957
5021
|
'server',
|
|
4958
5022
|
metavar='<server>',
|
|
@@ -4961,24 +5025,25 @@ class UnrescueServer(command.Command):
|
|
|
4961
5025
|
return parser
|
|
4962
5026
|
|
|
4963
5027
|
def take_action(self, parsed_args):
|
|
4964
|
-
compute_client = self.app.client_manager.compute
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
5028
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
5029
|
+
server = compute_client.find_server(
|
|
5030
|
+
parsed_args.server, ignore_missing=False
|
|
5031
|
+
)
|
|
5032
|
+
compute_client.unrescue_server(server)
|
|
4969
5033
|
|
|
4970
5034
|
|
|
4971
5035
|
class UnsetServer(command.Command):
|
|
4972
5036
|
_description = _("Unset server properties and tags")
|
|
4973
5037
|
|
|
4974
5038
|
def get_parser(self, prog_name):
|
|
4975
|
-
parser = super(
|
|
5039
|
+
parser = super().get_parser(prog_name)
|
|
4976
5040
|
parser.add_argument(
|
|
4977
5041
|
'server',
|
|
4978
5042
|
metavar='<server>',
|
|
4979
5043
|
help=_('Server (name or ID)'),
|
|
4980
5044
|
)
|
|
4981
|
-
parser.
|
|
5045
|
+
property_group = parser.add_mutually_exclusive_group()
|
|
5046
|
+
property_group.add_argument(
|
|
4982
5047
|
'--property',
|
|
4983
5048
|
metavar='<key>',
|
|
4984
5049
|
action='append',
|
|
@@ -4989,16 +5054,22 @@ class UnsetServer(command.Command):
|
|
|
4989
5054
|
'(repeat option to remove multiple values)'
|
|
4990
5055
|
),
|
|
4991
5056
|
)
|
|
5057
|
+
property_group.add_argument(
|
|
5058
|
+
'--all-properties',
|
|
5059
|
+
action='store_true',
|
|
5060
|
+
help=_('Remove all properties'),
|
|
5061
|
+
)
|
|
4992
5062
|
parser.add_argument(
|
|
4993
5063
|
'--description',
|
|
4994
5064
|
dest='description',
|
|
4995
5065
|
action='store_true',
|
|
4996
5066
|
help=_(
|
|
4997
|
-
'Unset server description
|
|
4998
|
-
'--os-compute-api-version 2.19 or above)'
|
|
5067
|
+
'Unset server description '
|
|
5068
|
+
'(supported by --os-compute-api-version 2.19 or above)'
|
|
4999
5069
|
),
|
|
5000
5070
|
)
|
|
5001
|
-
parser.
|
|
5071
|
+
tag_group = parser.add_mutually_exclusive_group()
|
|
5072
|
+
tag_group.add_argument(
|
|
5002
5073
|
'--tag',
|
|
5003
5074
|
metavar='<tag>',
|
|
5004
5075
|
action='append',
|
|
@@ -5010,32 +5081,40 @@ class UnsetServer(command.Command):
|
|
|
5010
5081
|
'(supported by --os-compute-api-version 2.26 or above)'
|
|
5011
5082
|
),
|
|
5012
5083
|
)
|
|
5084
|
+
tag_group.add_argument(
|
|
5085
|
+
'--all-tags',
|
|
5086
|
+
action='store_true',
|
|
5087
|
+
help=_(
|
|
5088
|
+
'Remove all tags '
|
|
5089
|
+
'(supported by --os-compute-api-version 2.26 or above)'
|
|
5090
|
+
),
|
|
5091
|
+
)
|
|
5013
5092
|
return parser
|
|
5014
5093
|
|
|
5015
5094
|
def take_action(self, parsed_args):
|
|
5016
|
-
compute_client = self.app.client_manager.compute
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
parsed_args.server,
|
|
5095
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
5096
|
+
|
|
5097
|
+
server = compute_client.find_server(
|
|
5098
|
+
parsed_args.server, ignore_missing=False
|
|
5020
5099
|
)
|
|
5021
5100
|
|
|
5022
|
-
if parsed_args.properties:
|
|
5023
|
-
compute_client.
|
|
5101
|
+
if parsed_args.properties or parsed_args.all_properties:
|
|
5102
|
+
compute_client.delete_server_metadata(
|
|
5103
|
+
server, parsed_args.properties or None
|
|
5104
|
+
)
|
|
5024
5105
|
|
|
5025
5106
|
if parsed_args.description:
|
|
5026
|
-
if
|
|
5107
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
5027
5108
|
msg = _(
|
|
5028
|
-
'--os-compute-api-version 2.19 or greater is '
|
|
5029
|
-
'
|
|
5109
|
+
'--os-compute-api-version 2.19 or greater is required to '
|
|
5110
|
+
'support the --description option'
|
|
5030
5111
|
)
|
|
5031
5112
|
raise exceptions.CommandError(msg)
|
|
5032
|
-
compute_client.servers.update(
|
|
5033
|
-
server,
|
|
5034
|
-
description="",
|
|
5035
|
-
)
|
|
5036
5113
|
|
|
5037
|
-
|
|
5038
|
-
|
|
5114
|
+
compute_client.update_server(server, description="")
|
|
5115
|
+
|
|
5116
|
+
if parsed_args.tags or parsed_args.all_tags:
|
|
5117
|
+
if not sdk_utils.supports_microversion(compute_client, '2.26'):
|
|
5039
5118
|
msg = _(
|
|
5040
5119
|
'--os-compute-api-version 2.26 or greater is required to '
|
|
5041
5120
|
'support the --tag option'
|
|
@@ -5043,7 +5122,10 @@ class UnsetServer(command.Command):
|
|
|
5043
5122
|
raise exceptions.CommandError(msg)
|
|
5044
5123
|
|
|
5045
5124
|
for tag in parsed_args.tags:
|
|
5046
|
-
compute_client.
|
|
5125
|
+
compute_client.remove_tag_from_server(server, tag)
|
|
5126
|
+
|
|
5127
|
+
if parsed_args.all_tags:
|
|
5128
|
+
compute_client.remove_tags_from_server(server)
|
|
5047
5129
|
|
|
5048
5130
|
|
|
5049
5131
|
class UnshelveServer(command.Command):
|