python-openstackclient 6.6.1__py3-none-any.whl → 7.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openstackclient/api/api.py +4 -4
- 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 +24 -20
- openstackclient/common/configuration.py +1 -1
- openstackclient/common/extension.py +1 -1
- openstackclient/common/limits.py +67 -34
- openstackclient/common/module.py +3 -3
- openstackclient/common/progressbar.py +2 -2
- openstackclient/common/project_cleanup.py +5 -2
- openstackclient/common/quota.py +299 -423
- openstackclient/common/versions.py +1 -1
- openstackclient/compute/client.py +7 -116
- openstackclient/compute/v2/agent.py +75 -49
- openstackclient/compute/v2/aggregate.py +38 -32
- 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 +9 -6
- openstackclient/compute/v2/keypair.py +7 -8
- openstackclient/compute/v2/server.py +479 -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 +125 -43
- 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/releasenotes/notes/volume-backup-created-at-list-b49ec893ae1f6b0d.yaml +4 -0
- 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 +12 -4
- openstackclient/tests/functional/identity/v3/test_application_credential.py +6 -12
- 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_region.py +1 -3
- 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 +1 -3
- 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 +87 -57
- 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 +57 -34
- 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 +2850 -2453
- 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 +12 -12
- 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 +207 -230
- 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 +90 -94
- 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 +10 -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 +9 -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.1.dist-info → python_openstackclient-7.1.0.dist-info}/AUTHORS +6 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.1.0.dist-info}/METADATA +4 -4
- python_openstackclient-7.1.0.dist-info/RECORD +503 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.1.0.dist-info}/entry_points.txt +33 -27
- python_openstackclient-7.1.0.dist-info/pbr.json +1 -0
- python_openstackclient-6.6.1.dist-info/RECORD +0 -489
- python_openstackclient-6.6.1.dist-info/pbr.json +0 -1
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.1.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.1.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.1.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'
|
|
@@ -3505,14 +3587,17 @@ class RebuildServer(command.ShowOne):
|
|
|
3505
3587
|
if parsed_args.name is not None:
|
|
3506
3588
|
kwargs['name'] = parsed_args.name
|
|
3507
3589
|
|
|
3590
|
+
if parsed_args.password is not None:
|
|
3591
|
+
kwargs['admin_password'] = parsed_args.password
|
|
3592
|
+
|
|
3508
3593
|
if parsed_args.preserve_ephemeral is not None:
|
|
3509
3594
|
kwargs['preserve_ephemeral'] = parsed_args.preserve_ephemeral
|
|
3510
3595
|
|
|
3511
3596
|
if parsed_args.properties:
|
|
3512
|
-
kwargs['
|
|
3597
|
+
kwargs['metadata'] = parsed_args.properties
|
|
3513
3598
|
|
|
3514
3599
|
if parsed_args.description:
|
|
3515
|
-
if
|
|
3600
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
3516
3601
|
msg = _(
|
|
3517
3602
|
'--os-compute-api-version 2.19 or greater is required to '
|
|
3518
3603
|
'support the --description option'
|
|
@@ -3522,7 +3607,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3522
3607
|
kwargs['description'] = parsed_args.description
|
|
3523
3608
|
|
|
3524
3609
|
if parsed_args.key_name:
|
|
3525
|
-
if
|
|
3610
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3526
3611
|
msg = _(
|
|
3527
3612
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3528
3613
|
'support the --key-name option'
|
|
@@ -3531,7 +3616,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3531
3616
|
|
|
3532
3617
|
kwargs['key_name'] = parsed_args.key_name
|
|
3533
3618
|
elif parsed_args.no_key_name:
|
|
3534
|
-
if
|
|
3619
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3535
3620
|
msg = _(
|
|
3536
3621
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3537
3622
|
'support the --no-key-name option'
|
|
@@ -3540,9 +3625,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3540
3625
|
|
|
3541
3626
|
kwargs['key_name'] = None
|
|
3542
3627
|
|
|
3543
|
-
userdata = None
|
|
3544
3628
|
if parsed_args.user_data:
|
|
3545
|
-
if
|
|
3629
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3546
3630
|
msg = _(
|
|
3547
3631
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3548
3632
|
'support the --user-data option'
|
|
@@ -3550,27 +3634,29 @@ class RebuildServer(command.ShowOne):
|
|
|
3550
3634
|
raise exceptions.CommandError(msg)
|
|
3551
3635
|
|
|
3552
3636
|
try:
|
|
3553
|
-
|
|
3554
|
-
|
|
3637
|
+
with open(parsed_args.user_data, 'rb') as fh:
|
|
3638
|
+
# TODO(stephenfin): SDK should do this for us
|
|
3639
|
+
user_data = base64.b64encode(fh.read()).decode('utf-8')
|
|
3640
|
+
except OSError as e:
|
|
3555
3641
|
msg = _("Can't open '%(data)s': %(exception)s")
|
|
3556
3642
|
raise exceptions.CommandError(
|
|
3557
3643
|
msg % {'data': parsed_args.user_data, 'exception': e}
|
|
3558
3644
|
)
|
|
3559
3645
|
|
|
3560
|
-
kwargs['
|
|
3646
|
+
kwargs['user_data'] = user_data
|
|
3561
3647
|
elif parsed_args.no_user_data:
|
|
3562
|
-
if
|
|
3648
|
+
if not sdk_utils.supports_microversion(compute_client, '2.54'):
|
|
3563
3649
|
msg = _(
|
|
3564
3650
|
'--os-compute-api-version 2.54 or greater is required to '
|
|
3565
3651
|
'support the --no-user-data option'
|
|
3566
3652
|
)
|
|
3567
3653
|
raise exceptions.CommandError(msg)
|
|
3568
3654
|
|
|
3569
|
-
kwargs['
|
|
3655
|
+
kwargs['user_data'] = None
|
|
3570
3656
|
|
|
3571
3657
|
# TODO(stephenfin): Handle OS_TRUSTED_IMAGE_CERTIFICATE_IDS
|
|
3572
3658
|
if parsed_args.trusted_image_certs:
|
|
3573
|
-
if
|
|
3659
|
+
if not sdk_utils.supports_microversion(compute_client, '2.63'):
|
|
3574
3660
|
msg = _(
|
|
3575
3661
|
'--os-compute-api-version 2.63 or greater is required to '
|
|
3576
3662
|
'support the --trusted-certs option'
|
|
@@ -3580,7 +3666,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3580
3666
|
certs = parsed_args.trusted_image_certs
|
|
3581
3667
|
kwargs['trusted_image_certificates'] = certs
|
|
3582
3668
|
elif parsed_args.no_trusted_image_certs:
|
|
3583
|
-
if
|
|
3669
|
+
if not sdk_utils.supports_microversion(compute_client, '2.63'):
|
|
3584
3670
|
msg = _(
|
|
3585
3671
|
'--os-compute-api-version 2.63 or greater is required to '
|
|
3586
3672
|
'support the --no-trusted-certs option'
|
|
@@ -3590,7 +3676,7 @@ class RebuildServer(command.ShowOne):
|
|
|
3590
3676
|
kwargs['trusted_image_certificates'] = None
|
|
3591
3677
|
|
|
3592
3678
|
if parsed_args.hostname:
|
|
3593
|
-
if
|
|
3679
|
+
if not sdk_utils.supports_microversion(compute_client, '2.90'):
|
|
3594
3680
|
msg = _(
|
|
3595
3681
|
'--os-compute-api-version 2.90 or greater is required to '
|
|
3596
3682
|
'support the --hostname option'
|
|
@@ -3599,9 +3685,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3599
3685
|
|
|
3600
3686
|
kwargs['hostname'] = parsed_args.hostname
|
|
3601
3687
|
|
|
3602
|
-
v2_93 = api_versions.APIVersion('2.93')
|
|
3603
3688
|
if parsed_args.reimage_boot_volume:
|
|
3604
|
-
if compute_client.
|
|
3689
|
+
if not sdk_utils.supports_microversion(compute_client, '2.93'):
|
|
3605
3690
|
msg = _(
|
|
3606
3691
|
'--os-compute-api-version 2.93 or greater is required to '
|
|
3607
3692
|
'support the --reimage-boot-volume option'
|
|
@@ -3610,8 +3695,8 @@ class RebuildServer(command.ShowOne):
|
|
|
3610
3695
|
else:
|
|
3611
3696
|
# force user to explicitly request reimaging of volume-backed
|
|
3612
3697
|
# server
|
|
3613
|
-
if not server.image:
|
|
3614
|
-
if compute_client.
|
|
3698
|
+
if not server.image or not server.image.id:
|
|
3699
|
+
if sdk_utils.supports_microversion(compute_client, '2.93'):
|
|
3615
3700
|
msg = (
|
|
3616
3701
|
'--reimage-boot-volume is required to rebuild a '
|
|
3617
3702
|
'volume-backed server'
|
|
@@ -3643,15 +3728,11 @@ class RebuildServer(command.ShowOne):
|
|
|
3643
3728
|
msg = _("The server status is not ACTIVE, SHUTOFF or ERROR.")
|
|
3644
3729
|
raise exceptions.CommandError(msg)
|
|
3645
3730
|
|
|
3646
|
-
|
|
3647
|
-
server = server.rebuild(image, parsed_args.password, **kwargs)
|
|
3648
|
-
finally:
|
|
3649
|
-
if userdata and hasattr(userdata, 'close'):
|
|
3650
|
-
userdata.close()
|
|
3731
|
+
server = compute_client.rebuild_server(server, image, **kwargs)
|
|
3651
3732
|
|
|
3652
3733
|
if parsed_args.wait:
|
|
3653
3734
|
if utils.wait_for_status(
|
|
3654
|
-
compute_client.
|
|
3735
|
+
compute_client.get_server,
|
|
3655
3736
|
server.id,
|
|
3656
3737
|
callback=_show_progress,
|
|
3657
3738
|
success_status=success_status,
|
|
@@ -3661,10 +3742,10 @@ class RebuildServer(command.ShowOne):
|
|
|
3661
3742
|
msg = _('Error rebuilding server: %s') % server.id
|
|
3662
3743
|
raise exceptions.CommandError(msg)
|
|
3663
3744
|
|
|
3664
|
-
|
|
3745
|
+
data = _prep_server_detail(
|
|
3665
3746
|
compute_client, image_client, server, refresh=False
|
|
3666
3747
|
)
|
|
3667
|
-
return zip(*sorted(
|
|
3748
|
+
return zip(*sorted(data.items()))
|
|
3668
3749
|
|
|
3669
3750
|
|
|
3670
3751
|
class EvacuateServer(command.ShowOne):
|
|
@@ -3686,13 +3767,12 @@ host."""
|
|
|
3686
3767
|
)
|
|
3687
3768
|
|
|
3688
3769
|
def get_parser(self, prog_name):
|
|
3689
|
-
parser = super(
|
|
3770
|
+
parser = super().get_parser(prog_name)
|
|
3690
3771
|
parser.add_argument(
|
|
3691
3772
|
'server',
|
|
3692
3773
|
metavar='<server>',
|
|
3693
3774
|
help=_('Server (name or ID)'),
|
|
3694
3775
|
)
|
|
3695
|
-
|
|
3696
3776
|
parser.add_argument(
|
|
3697
3777
|
'--wait',
|
|
3698
3778
|
action='store_true',
|
|
@@ -3739,11 +3819,11 @@ host."""
|
|
|
3739
3819
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
3740
3820
|
self.app.stdout.flush()
|
|
3741
3821
|
|
|
3742
|
-
compute_client = self.app.client_manager.compute
|
|
3822
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3743
3823
|
image_client = self.app.client_manager.image
|
|
3744
3824
|
|
|
3745
3825
|
if parsed_args.host:
|
|
3746
|
-
if
|
|
3826
|
+
if not sdk_utils.supports_microversion(compute_client, '2.29'):
|
|
3747
3827
|
msg = _(
|
|
3748
3828
|
'--os-compute-api-version 2.29 or later is required '
|
|
3749
3829
|
'to specify a preferred host.'
|
|
@@ -3751,7 +3831,7 @@ host."""
|
|
|
3751
3831
|
raise exceptions.CommandError(msg)
|
|
3752
3832
|
|
|
3753
3833
|
if parsed_args.shared_storage:
|
|
3754
|
-
if compute_client
|
|
3834
|
+
if sdk_utils.supports_microversion(compute_client, '2.14'):
|
|
3755
3835
|
msg = _(
|
|
3756
3836
|
'--os-compute-api-version 2.13 or earlier is required '
|
|
3757
3837
|
'to specify shared-storage.'
|
|
@@ -3763,18 +3843,17 @@ host."""
|
|
|
3763
3843
|
'password': parsed_args.password,
|
|
3764
3844
|
}
|
|
3765
3845
|
|
|
3766
|
-
if
|
|
3846
|
+
if not sdk_utils.supports_microversion(compute_client, '2.14'):
|
|
3767
3847
|
kwargs['on_shared_storage'] = parsed_args.shared_storage
|
|
3768
3848
|
|
|
3769
|
-
server =
|
|
3770
|
-
|
|
3849
|
+
server = compute_client.find_server(
|
|
3850
|
+
parsed_args.server, ignore_missing=False
|
|
3771
3851
|
)
|
|
3772
|
-
|
|
3773
|
-
server.evacuate(**kwargs)
|
|
3852
|
+
compute_client.evacuate_server(server, **kwargs)
|
|
3774
3853
|
|
|
3775
3854
|
if parsed_args.wait:
|
|
3776
3855
|
if utils.wait_for_status(
|
|
3777
|
-
compute_client.
|
|
3856
|
+
compute_client.get_server,
|
|
3778
3857
|
server.id,
|
|
3779
3858
|
callback=_show_progress,
|
|
3780
3859
|
):
|
|
@@ -3783,17 +3862,15 @@ host."""
|
|
|
3783
3862
|
msg = _('Error evacuating server: %s') % server.id
|
|
3784
3863
|
raise exceptions.CommandError(msg)
|
|
3785
3864
|
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
)
|
|
3789
|
-
return zip(*sorted(details.items()))
|
|
3865
|
+
data = _prep_server_detail(compute_client, image_client, server)
|
|
3866
|
+
return zip(*sorted(data.items()))
|
|
3790
3867
|
|
|
3791
3868
|
|
|
3792
3869
|
class RemoveFixedIP(command.Command):
|
|
3793
3870
|
_description = _("Remove fixed IP address from server")
|
|
3794
3871
|
|
|
3795
3872
|
def get_parser(self, prog_name):
|
|
3796
|
-
parser = super(
|
|
3873
|
+
parser = super().get_parser(prog_name)
|
|
3797
3874
|
parser.add_argument(
|
|
3798
3875
|
"server",
|
|
3799
3876
|
metavar="<server>",
|
|
@@ -3807,13 +3884,14 @@ class RemoveFixedIP(command.Command):
|
|
|
3807
3884
|
return parser
|
|
3808
3885
|
|
|
3809
3886
|
def take_action(self, parsed_args):
|
|
3810
|
-
compute_client = self.app.client_manager.compute
|
|
3887
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3811
3888
|
|
|
3812
|
-
server =
|
|
3813
|
-
|
|
3889
|
+
server = compute_client.find_server(
|
|
3890
|
+
parsed_args.server, ignore_missing=False
|
|
3891
|
+
)
|
|
3892
|
+
compute_client.remove_fixed_ip_from_server(
|
|
3893
|
+
server, parsed_args.ip_address
|
|
3814
3894
|
)
|
|
3815
|
-
|
|
3816
|
-
server.remove_fixed_ip(parsed_args.ip_address)
|
|
3817
3895
|
|
|
3818
3896
|
|
|
3819
3897
|
class RemoveFloatingIP(network_common.NetworkAndComputeCommand):
|
|
@@ -3845,17 +3923,15 @@ class RemoveFloatingIP(network_common.NetworkAndComputeCommand):
|
|
|
3845
3923
|
client.update_ip(obj, **attrs)
|
|
3846
3924
|
|
|
3847
3925
|
def take_action_compute(self, client, parsed_args):
|
|
3848
|
-
client.
|
|
3849
|
-
|
|
3850
|
-
parsed_args.ip_address,
|
|
3851
|
-
)
|
|
3926
|
+
server = client.find_server(parsed_args.server, ignore_missing=False)
|
|
3927
|
+
client.remove_floating_ip_from_server(server, parsed_args.ip_address)
|
|
3852
3928
|
|
|
3853
3929
|
|
|
3854
3930
|
class RemovePort(command.Command):
|
|
3855
3931
|
_description = _("Remove port from server")
|
|
3856
3932
|
|
|
3857
3933
|
def get_parser(self, prog_name):
|
|
3858
|
-
parser = super(
|
|
3934
|
+
parser = super().get_parser(prog_name)
|
|
3859
3935
|
parser.add_argument(
|
|
3860
3936
|
"server",
|
|
3861
3937
|
metavar="<server>",
|
|
@@ -3894,7 +3970,7 @@ class RemoveNetwork(command.Command):
|
|
|
3894
3970
|
_description = _("Remove all ports of a network from server")
|
|
3895
3971
|
|
|
3896
3972
|
def get_parser(self, prog_name):
|
|
3897
|
-
parser = super(
|
|
3973
|
+
parser = super().get_parser(prog_name)
|
|
3898
3974
|
parser.add_argument(
|
|
3899
3975
|
"server",
|
|
3900
3976
|
metavar="<server>",
|
|
@@ -3934,32 +4010,38 @@ class RemoveServerSecurityGroup(command.Command):
|
|
|
3934
4010
|
_description = _("Remove security group from server")
|
|
3935
4011
|
|
|
3936
4012
|
def get_parser(self, prog_name):
|
|
3937
|
-
parser = super(
|
|
4013
|
+
parser = super().get_parser(prog_name)
|
|
3938
4014
|
parser.add_argument(
|
|
3939
4015
|
'server',
|
|
3940
4016
|
metavar='<server>',
|
|
3941
|
-
help=_('
|
|
4017
|
+
help=_('Server (name or ID)'),
|
|
3942
4018
|
)
|
|
3943
4019
|
parser.add_argument(
|
|
3944
4020
|
'group',
|
|
3945
4021
|
metavar='<group>',
|
|
3946
|
-
help=_('
|
|
4022
|
+
help=_('Security group to remove (name or ID)'),
|
|
3947
4023
|
)
|
|
3948
4024
|
return parser
|
|
3949
4025
|
|
|
3950
4026
|
def take_action(self, parsed_args):
|
|
3951
|
-
compute_client = self.app.client_manager.compute
|
|
4027
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
3952
4028
|
|
|
3953
|
-
server =
|
|
3954
|
-
|
|
3955
|
-
parsed_args.server,
|
|
4029
|
+
server = compute_client.find_server(
|
|
4030
|
+
parsed_args.server, ignore_missing=False
|
|
3956
4031
|
)
|
|
3957
|
-
|
|
3958
|
-
|
|
4032
|
+
if self.app.client_manager.is_network_endpoint_enabled():
|
|
4033
|
+
# the server handles both names and IDs for neutron SGs, so just
|
|
4034
|
+
# pass things through
|
|
4035
|
+
security_group = parsed_args.group
|
|
4036
|
+
else:
|
|
4037
|
+
# however, if using nova-network then it needs a name, not an ID
|
|
4038
|
+
security_group = compute_v2.find_security_group(
|
|
4039
|
+
compute_client, parsed_args.group
|
|
4040
|
+
)['name']
|
|
4041
|
+
compute_client.remove_security_group_from_server(
|
|
4042
|
+
server, security_group
|
|
3959
4043
|
)
|
|
3960
4044
|
|
|
3961
|
-
server.remove_security_group(security_group['id'])
|
|
3962
|
-
|
|
3963
4045
|
|
|
3964
4046
|
class RemoveServerVolume(command.Command):
|
|
3965
4047
|
_description = _(
|
|
@@ -3970,7 +4052,7 @@ volume from a server with status ``SHELVED`` or ``SHELVED_OFFLOADED``."""
|
|
|
3970
4052
|
)
|
|
3971
4053
|
|
|
3972
4054
|
def get_parser(self, prog_name):
|
|
3973
|
-
parser = super(
|
|
4055
|
+
parser = super().get_parser(prog_name)
|
|
3974
4056
|
parser.add_argument(
|
|
3975
4057
|
'server',
|
|
3976
4058
|
metavar='<server>',
|
|
@@ -4012,7 +4094,7 @@ server booted from a volume."""
|
|
|
4012
4094
|
)
|
|
4013
4095
|
|
|
4014
4096
|
def get_parser(self, prog_name):
|
|
4015
|
-
parser = super(
|
|
4097
|
+
parser = super().get_parser(prog_name)
|
|
4016
4098
|
parser.add_argument(
|
|
4017
4099
|
'server',
|
|
4018
4100
|
metavar='<server>',
|
|
@@ -4022,34 +4104,36 @@ server booted from a volume."""
|
|
|
4022
4104
|
'--image',
|
|
4023
4105
|
metavar='<image>',
|
|
4024
4106
|
help=_(
|
|
4025
|
-
'Image (name or ID) to use for the rescue mode
|
|
4026
|
-
'
|
|
4107
|
+
'Image (name or ID) to use for the rescue mode '
|
|
4108
|
+
'(defaults to the currently used one)'
|
|
4027
4109
|
),
|
|
4028
4110
|
)
|
|
4029
4111
|
parser.add_argument(
|
|
4030
4112
|
'--password',
|
|
4031
4113
|
metavar='<password>',
|
|
4032
4114
|
help=_(
|
|
4033
|
-
'Set the password on the rescued instance
|
|
4034
|
-
'
|
|
4115
|
+
'Set the password on the rescued instance '
|
|
4116
|
+
'(requires cloud support)'
|
|
4035
4117
|
),
|
|
4036
4118
|
)
|
|
4037
4119
|
return parser
|
|
4038
4120
|
|
|
4039
4121
|
def take_action(self, parsed_args):
|
|
4040
|
-
compute_client = self.app.client_manager.compute
|
|
4122
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4041
4123
|
image_client = self.app.client_manager.image
|
|
4042
4124
|
|
|
4043
|
-
|
|
4125
|
+
image_ref = None
|
|
4044
4126
|
if parsed_args.image:
|
|
4045
|
-
|
|
4127
|
+
image_ref = image_client.find_image(
|
|
4046
4128
|
parsed_args.image, ignore_missing=False
|
|
4047
|
-
)
|
|
4129
|
+
).id
|
|
4048
4130
|
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4131
|
+
server = compute_client.find_server(
|
|
4132
|
+
parsed_args.server, ignore_missing=False
|
|
4133
|
+
)
|
|
4134
|
+
compute_client.rescue_server(
|
|
4135
|
+
server, admin_pass=parsed_args.password, image_ref=image_ref
|
|
4136
|
+
)
|
|
4053
4137
|
|
|
4054
4138
|
|
|
4055
4139
|
class ResizeServer(command.Command):
|
|
@@ -4064,13 +4148,13 @@ release the new server and restart the old one."""
|
|
|
4064
4148
|
)
|
|
4065
4149
|
|
|
4066
4150
|
def get_parser(self, prog_name):
|
|
4067
|
-
parser = super(
|
|
4068
|
-
phase_group = parser.add_mutually_exclusive_group()
|
|
4151
|
+
parser = super().get_parser(prog_name)
|
|
4069
4152
|
parser.add_argument(
|
|
4070
4153
|
'server',
|
|
4071
4154
|
metavar='<server>',
|
|
4072
4155
|
help=_('Server (name or ID)'),
|
|
4073
4156
|
)
|
|
4157
|
+
phase_group = parser.add_mutually_exclusive_group()
|
|
4074
4158
|
phase_group.add_argument(
|
|
4075
4159
|
'--flavor',
|
|
4076
4160
|
metavar='<flavor>',
|
|
@@ -4107,16 +4191,11 @@ release the new server and restart the old one."""
|
|
|
4107
4191
|
self.app.stdout.write('\rProgress: %s' % progress)
|
|
4108
4192
|
self.app.stdout.flush()
|
|
4109
4193
|
|
|
4110
|
-
compute_client = self.app.client_manager.compute
|
|
4111
|
-
server =
|
|
4112
|
-
|
|
4113
|
-
parsed_args.server,
|
|
4194
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4195
|
+
server = compute_client.find_server(
|
|
4196
|
+
parsed_args.server, ignore_missing=False
|
|
4114
4197
|
)
|
|
4115
4198
|
if parsed_args.flavor:
|
|
4116
|
-
flavor = utils.find_resource(
|
|
4117
|
-
compute_client.flavors,
|
|
4118
|
-
parsed_args.flavor,
|
|
4119
|
-
)
|
|
4120
4199
|
if not server.image:
|
|
4121
4200
|
self.log.warning(
|
|
4122
4201
|
_(
|
|
@@ -4124,18 +4203,21 @@ release the new server and restart the old one."""
|
|
|
4124
4203
|
"while booting from a persistent volume."
|
|
4125
4204
|
)
|
|
4126
4205
|
)
|
|
4127
|
-
compute_client.
|
|
4206
|
+
flavor = compute_client.find_flavor(
|
|
4207
|
+
parsed_args.flavor, ignore_missing=False
|
|
4208
|
+
)
|
|
4209
|
+
compute_client.resize_server(server, flavor)
|
|
4128
4210
|
if parsed_args.wait:
|
|
4129
|
-
if utils.wait_for_status(
|
|
4130
|
-
compute_client.
|
|
4211
|
+
if not utils.wait_for_status(
|
|
4212
|
+
compute_client.get_server,
|
|
4131
4213
|
server.id,
|
|
4132
|
-
success_status=
|
|
4214
|
+
success_status=('active', 'verify_resize'),
|
|
4133
4215
|
callback=_show_progress,
|
|
4134
4216
|
):
|
|
4135
|
-
self.app.stdout.write(_('Complete\n'))
|
|
4136
|
-
else:
|
|
4137
4217
|
msg = _('Error resizing server: %s') % server.id
|
|
4138
4218
|
raise exceptions.CommandError(msg)
|
|
4219
|
+
|
|
4220
|
+
self.app.stdout.write(_('Complete\n'))
|
|
4139
4221
|
elif parsed_args.confirm:
|
|
4140
4222
|
self.log.warning(
|
|
4141
4223
|
_(
|
|
@@ -4143,7 +4225,7 @@ release the new server and restart the old one."""
|
|
|
4143
4225
|
"'openstack server resize confirm' command instead."
|
|
4144
4226
|
)
|
|
4145
4227
|
)
|
|
4146
|
-
compute_client.
|
|
4228
|
+
compute_client.confirm_server_resize(server)
|
|
4147
4229
|
elif parsed_args.revert:
|
|
4148
4230
|
self.log.warning(
|
|
4149
4231
|
_(
|
|
@@ -4151,7 +4233,7 @@ release the new server and restart the old one."""
|
|
|
4151
4233
|
"'openstack server resize revert' command instead."
|
|
4152
4234
|
)
|
|
4153
4235
|
)
|
|
4154
|
-
compute_client.
|
|
4236
|
+
compute_client.revert_server_resize(server)
|
|
4155
4237
|
|
|
4156
4238
|
|
|
4157
4239
|
class ResizeConfirm(command.Command):
|
|
@@ -4162,7 +4244,7 @@ Confirm (verify) success of resize operation and release the old server."""
|
|
|
4162
4244
|
)
|
|
4163
4245
|
|
|
4164
4246
|
def get_parser(self, prog_name):
|
|
4165
|
-
parser = super(
|
|
4247
|
+
parser = super().get_parser(prog_name)
|
|
4166
4248
|
parser.add_argument(
|
|
4167
4249
|
'server',
|
|
4168
4250
|
metavar='<server>',
|
|
@@ -4171,12 +4253,11 @@ Confirm (verify) success of resize operation and release the old server."""
|
|
|
4171
4253
|
return parser
|
|
4172
4254
|
|
|
4173
4255
|
def take_action(self, parsed_args):
|
|
4174
|
-
compute_client = self.app.client_manager.compute
|
|
4175
|
-
server =
|
|
4176
|
-
|
|
4177
|
-
parsed_args.server,
|
|
4256
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4257
|
+
server = compute_client.find_server(
|
|
4258
|
+
parsed_args.server, ignore_missing=False
|
|
4178
4259
|
)
|
|
4179
|
-
|
|
4260
|
+
compute_client.confirm_server_resize(server)
|
|
4180
4261
|
|
|
4181
4262
|
|
|
4182
4263
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
@@ -4211,7 +4292,7 @@ one."""
|
|
|
4211
4292
|
)
|
|
4212
4293
|
|
|
4213
4294
|
def get_parser(self, prog_name):
|
|
4214
|
-
parser = super(
|
|
4295
|
+
parser = super().get_parser(prog_name)
|
|
4215
4296
|
parser.add_argument(
|
|
4216
4297
|
'server',
|
|
4217
4298
|
metavar='<server>',
|
|
@@ -4220,12 +4301,11 @@ one."""
|
|
|
4220
4301
|
return parser
|
|
4221
4302
|
|
|
4222
4303
|
def take_action(self, parsed_args):
|
|
4223
|
-
compute_client = self.app.client_manager.compute
|
|
4224
|
-
server =
|
|
4225
|
-
|
|
4226
|
-
parsed_args.server,
|
|
4304
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4305
|
+
server = compute_client.find_server(
|
|
4306
|
+
parsed_args.server, ignore_missing=False
|
|
4227
4307
|
)
|
|
4228
|
-
|
|
4308
|
+
compute_client.revert_server_resize(server)
|
|
4229
4309
|
|
|
4230
4310
|
|
|
4231
4311
|
# TODO(stephenfin): Remove in OSC 7.0
|
|
@@ -4255,7 +4335,7 @@ class RestoreServer(command.Command):
|
|
|
4255
4335
|
_description = _("Restore server(s)")
|
|
4256
4336
|
|
|
4257
4337
|
def get_parser(self, prog_name):
|
|
4258
|
-
parser = super(
|
|
4338
|
+
parser = super().get_parser(prog_name)
|
|
4259
4339
|
parser.add_argument(
|
|
4260
4340
|
'server',
|
|
4261
4341
|
metavar='<server>',
|
|
@@ -4278,7 +4358,7 @@ class ResumeServer(command.Command):
|
|
|
4278
4358
|
_description = _("Resume server(s)")
|
|
4279
4359
|
|
|
4280
4360
|
def get_parser(self, prog_name):
|
|
4281
|
-
parser = super(
|
|
4361
|
+
parser = super().get_parser(prog_name)
|
|
4282
4362
|
parser.add_argument(
|
|
4283
4363
|
'server',
|
|
4284
4364
|
metavar='<server>',
|
|
@@ -4301,7 +4381,7 @@ class SetServer(command.Command):
|
|
|
4301
4381
|
_description = _("Set server properties")
|
|
4302
4382
|
|
|
4303
4383
|
def get_parser(self, prog_name):
|
|
4304
|
-
parser = super(
|
|
4384
|
+
parser = super().get_parser(prog_name)
|
|
4305
4385
|
parser.add_argument(
|
|
4306
4386
|
'server',
|
|
4307
4387
|
metavar='<server>',
|
|
@@ -4389,14 +4469,13 @@ class SetServer(command.Command):
|
|
|
4389
4469
|
return parser
|
|
4390
4470
|
|
|
4391
4471
|
def take_action(self, parsed_args):
|
|
4392
|
-
compute_client = self.app.client_manager.compute
|
|
4393
|
-
server =
|
|
4394
|
-
|
|
4395
|
-
parsed_args.server,
|
|
4472
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4473
|
+
server = compute_client.find_server(
|
|
4474
|
+
parsed_args.server, ignore_missing=False
|
|
4396
4475
|
)
|
|
4397
4476
|
|
|
4398
4477
|
if parsed_args.description:
|
|
4399
|
-
if
|
|
4478
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
4400
4479
|
msg = _(
|
|
4401
4480
|
'--os-compute-api-version 2.19 or greater is required to '
|
|
4402
4481
|
'support the --description option'
|
|
@@ -4404,7 +4483,7 @@ class SetServer(command.Command):
|
|
|
4404
4483
|
raise exceptions.CommandError(msg)
|
|
4405
4484
|
|
|
4406
4485
|
if parsed_args.tags:
|
|
4407
|
-
if
|
|
4486
|
+
if not sdk_utils.supports_microversion(compute_client, '2.26'):
|
|
4408
4487
|
msg = _(
|
|
4409
4488
|
'--os-compute-api-version 2.26 or greater is required to '
|
|
4410
4489
|
'support the --tag option'
|
|
@@ -4412,7 +4491,7 @@ class SetServer(command.Command):
|
|
|
4412
4491
|
raise exceptions.CommandError(msg)
|
|
4413
4492
|
|
|
4414
4493
|
if parsed_args.hostname:
|
|
4415
|
-
if
|
|
4494
|
+
if not sdk_utils.supports_microversion(compute_client, '2.90'):
|
|
4416
4495
|
msg = _(
|
|
4417
4496
|
'--os-compute-api-version 2.90 or greater is required to '
|
|
4418
4497
|
'support the --hostname option'
|
|
@@ -4431,30 +4510,32 @@ class SetServer(command.Command):
|
|
|
4431
4510
|
update_kwargs['hostname'] = parsed_args.hostname
|
|
4432
4511
|
|
|
4433
4512
|
if update_kwargs:
|
|
4434
|
-
|
|
4513
|
+
compute_client.update_server(server, **update_kwargs)
|
|
4435
4514
|
|
|
4436
4515
|
if parsed_args.properties:
|
|
4437
|
-
compute_client.
|
|
4516
|
+
compute_client.set_server_metadata(
|
|
4517
|
+
server, **parsed_args.properties
|
|
4518
|
+
)
|
|
4438
4519
|
|
|
4439
4520
|
if parsed_args.state:
|
|
4440
|
-
|
|
4521
|
+
compute_client.reset_server_state(server, state=parsed_args.state)
|
|
4441
4522
|
|
|
4442
4523
|
if parsed_args.root_password:
|
|
4443
4524
|
p1 = getpass.getpass(_('New password: '))
|
|
4444
4525
|
p2 = getpass.getpass(_('Retype new password: '))
|
|
4445
4526
|
if p1 == p2:
|
|
4446
|
-
|
|
4527
|
+
compute_client.change_server_password(server, p1)
|
|
4447
4528
|
else:
|
|
4448
4529
|
msg = _("Passwords do not match, password unchanged")
|
|
4449
4530
|
raise exceptions.CommandError(msg)
|
|
4450
4531
|
elif parsed_args.password:
|
|
4451
|
-
|
|
4532
|
+
compute_client.change_server_password(server, parsed_args.password)
|
|
4452
4533
|
elif parsed_args.no_password:
|
|
4453
|
-
|
|
4534
|
+
compute_client.clear_server_password(server)
|
|
4454
4535
|
|
|
4455
4536
|
if parsed_args.tags:
|
|
4456
4537
|
for tag in parsed_args.tags:
|
|
4457
|
-
|
|
4538
|
+
compute_client.add_tag_to_server(server, tag=tag)
|
|
4458
4539
|
|
|
4459
4540
|
|
|
4460
4541
|
class ShelveServer(command.Command):
|
|
@@ -4575,7 +4656,7 @@ information for the server."""
|
|
|
4575
4656
|
)
|
|
4576
4657
|
|
|
4577
4658
|
def get_parser(self, prog_name):
|
|
4578
|
-
parser = super(
|
|
4659
|
+
parser = super().get_parser(prog_name)
|
|
4579
4660
|
parser.add_argument(
|
|
4580
4661
|
'server',
|
|
4581
4662
|
metavar='<server>',
|
|
@@ -4602,12 +4683,13 @@ information for the server."""
|
|
|
4602
4683
|
|
|
4603
4684
|
def take_action(self, parsed_args):
|
|
4604
4685
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4686
|
+
image_client = self.app.client_manager.image
|
|
4605
4687
|
|
|
4606
|
-
# Find by name or ID, then get the full details of the server
|
|
4607
4688
|
server = compute_client.find_server(
|
|
4608
|
-
parsed_args.server,
|
|
4689
|
+
parsed_args.server,
|
|
4690
|
+
ignore_missing=False,
|
|
4691
|
+
details=True,
|
|
4609
4692
|
)
|
|
4610
|
-
server = compute_client.get_server(server)
|
|
4611
4693
|
|
|
4612
4694
|
if parsed_args.diagnostics:
|
|
4613
4695
|
data = compute_client.get_server_diagnostics(server)
|
|
@@ -4625,17 +4707,10 @@ information for the server."""
|
|
|
4625
4707
|
topology = server.fetch_topology(compute_client)
|
|
4626
4708
|
|
|
4627
4709
|
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,
|
|
4710
|
+
compute_client, image_client, server, refresh=False
|
|
4634
4711
|
)
|
|
4635
|
-
|
|
4636
4712
|
if topology:
|
|
4637
4713
|
data['topology'] = format_columns.DictColumn(topology)
|
|
4638
|
-
|
|
4639
4714
|
return zip(*sorted(data.items()))
|
|
4640
4715
|
|
|
4641
4716
|
|
|
@@ -4643,7 +4718,7 @@ class SshServer(command.Command):
|
|
|
4643
4718
|
_description = _("SSH to server")
|
|
4644
4719
|
|
|
4645
4720
|
def get_parser(self, prog_name):
|
|
4646
|
-
parser = super(
|
|
4721
|
+
parser = super().get_parser(prog_name)
|
|
4647
4722
|
parser.add_argument(
|
|
4648
4723
|
'server',
|
|
4649
4724
|
metavar='<server>',
|
|
@@ -4737,11 +4812,10 @@ class SshServer(command.Command):
|
|
|
4737
4812
|
return parser
|
|
4738
4813
|
|
|
4739
4814
|
def take_action(self, parsed_args):
|
|
4740
|
-
compute_client = self.app.client_manager.compute
|
|
4815
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4741
4816
|
|
|
4742
|
-
server =
|
|
4743
|
-
|
|
4744
|
-
parsed_args.server,
|
|
4817
|
+
server = compute_client.find_server(
|
|
4818
|
+
parsed_args.server, ignore_missing=False
|
|
4745
4819
|
)
|
|
4746
4820
|
|
|
4747
4821
|
# first, handle the deprecated options
|
|
@@ -4795,8 +4869,10 @@ class SshServer(command.Command):
|
|
|
4795
4869
|
)
|
|
4796
4870
|
|
|
4797
4871
|
cmd = ' '.join(['ssh', ip_address] + args)
|
|
4798
|
-
LOG.debug("ssh command: {cmd}"
|
|
4799
|
-
|
|
4872
|
+
LOG.debug(f"ssh command: {cmd}")
|
|
4873
|
+
# we intentionally pass through user-provided arguments and run this in
|
|
4874
|
+
# the user's shell
|
|
4875
|
+
os.system(cmd) # nosec: B605
|
|
4800
4876
|
|
|
4801
4877
|
|
|
4802
4878
|
class StartServer(command.Command):
|
|
@@ -4815,7 +4891,7 @@ class StartServer(command.Command):
|
|
|
4815
4891
|
action='store_true',
|
|
4816
4892
|
default=boolenv('ALL_PROJECTS'),
|
|
4817
4893
|
help=_(
|
|
4818
|
-
'Start server(s) in another project by name (admin only)'
|
|
4894
|
+
'Start server(s) in another project by name (admin only) '
|
|
4819
4895
|
'(can be specified using the ALL_PROJECTS envvar)'
|
|
4820
4896
|
),
|
|
4821
4897
|
)
|
|
@@ -4824,17 +4900,12 @@ class StartServer(command.Command):
|
|
|
4824
4900
|
def take_action(self, parsed_args):
|
|
4825
4901
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4826
4902
|
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)
|
|
4903
|
+
server_id = compute_client.find_server(
|
|
4904
|
+
server,
|
|
4905
|
+
ignore_missing=False,
|
|
4906
|
+
details=False,
|
|
4907
|
+
all_projects=parsed_args.all_projects,
|
|
4908
|
+
).id
|
|
4838
4909
|
|
|
4839
4910
|
compute_client.start_server(server_id)
|
|
4840
4911
|
|
|
@@ -4864,18 +4935,12 @@ class StopServer(command.Command):
|
|
|
4864
4935
|
def take_action(self, parsed_args):
|
|
4865
4936
|
compute_client = self.app.client_manager.sdk_connection.compute
|
|
4866
4937
|
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
|
-
|
|
4938
|
+
server_id = compute_client.find_server(
|
|
4939
|
+
server,
|
|
4940
|
+
ignore_missing=False,
|
|
4941
|
+
details=False,
|
|
4942
|
+
all_projects=parsed_args.all_projects,
|
|
4943
|
+
).id
|
|
4879
4944
|
compute_client.stop_server(server_id)
|
|
4880
4945
|
|
|
4881
4946
|
|
|
@@ -4883,7 +4948,7 @@ class SuspendServer(command.Command):
|
|
|
4883
4948
|
_description = _("Suspend server(s)")
|
|
4884
4949
|
|
|
4885
4950
|
def get_parser(self, prog_name):
|
|
4886
|
-
parser = super(
|
|
4951
|
+
parser = super().get_parser(prog_name)
|
|
4887
4952
|
parser.add_argument(
|
|
4888
4953
|
'server',
|
|
4889
4954
|
metavar='<server>',
|
|
@@ -4929,7 +4994,7 @@ class UnpauseServer(command.Command):
|
|
|
4929
4994
|
_description = _("Unpause server(s)")
|
|
4930
4995
|
|
|
4931
4996
|
def get_parser(self, prog_name):
|
|
4932
|
-
parser = super(
|
|
4997
|
+
parser = super().get_parser(prog_name)
|
|
4933
4998
|
parser.add_argument(
|
|
4934
4999
|
'server',
|
|
4935
5000
|
metavar='<server>',
|
|
@@ -4952,7 +5017,7 @@ class UnrescueServer(command.Command):
|
|
|
4952
5017
|
_description = _("Restore server from rescue mode")
|
|
4953
5018
|
|
|
4954
5019
|
def get_parser(self, prog_name):
|
|
4955
|
-
parser = super(
|
|
5020
|
+
parser = super().get_parser(prog_name)
|
|
4956
5021
|
parser.add_argument(
|
|
4957
5022
|
'server',
|
|
4958
5023
|
metavar='<server>',
|
|
@@ -4961,24 +5026,25 @@ class UnrescueServer(command.Command):
|
|
|
4961
5026
|
return parser
|
|
4962
5027
|
|
|
4963
5028
|
def take_action(self, parsed_args):
|
|
4964
|
-
compute_client = self.app.client_manager.compute
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
5029
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
5030
|
+
server = compute_client.find_server(
|
|
5031
|
+
parsed_args.server, ignore_missing=False
|
|
5032
|
+
)
|
|
5033
|
+
compute_client.unrescue_server(server)
|
|
4969
5034
|
|
|
4970
5035
|
|
|
4971
5036
|
class UnsetServer(command.Command):
|
|
4972
5037
|
_description = _("Unset server properties and tags")
|
|
4973
5038
|
|
|
4974
5039
|
def get_parser(self, prog_name):
|
|
4975
|
-
parser = super(
|
|
5040
|
+
parser = super().get_parser(prog_name)
|
|
4976
5041
|
parser.add_argument(
|
|
4977
5042
|
'server',
|
|
4978
5043
|
metavar='<server>',
|
|
4979
5044
|
help=_('Server (name or ID)'),
|
|
4980
5045
|
)
|
|
4981
|
-
parser.
|
|
5046
|
+
property_group = parser.add_mutually_exclusive_group()
|
|
5047
|
+
property_group.add_argument(
|
|
4982
5048
|
'--property',
|
|
4983
5049
|
metavar='<key>',
|
|
4984
5050
|
action='append',
|
|
@@ -4989,16 +5055,22 @@ class UnsetServer(command.Command):
|
|
|
4989
5055
|
'(repeat option to remove multiple values)'
|
|
4990
5056
|
),
|
|
4991
5057
|
)
|
|
5058
|
+
property_group.add_argument(
|
|
5059
|
+
'--all-properties',
|
|
5060
|
+
action='store_true',
|
|
5061
|
+
help=_('Remove all properties'),
|
|
5062
|
+
)
|
|
4992
5063
|
parser.add_argument(
|
|
4993
5064
|
'--description',
|
|
4994
5065
|
dest='description',
|
|
4995
5066
|
action='store_true',
|
|
4996
5067
|
help=_(
|
|
4997
|
-
'Unset server description
|
|
4998
|
-
'--os-compute-api-version 2.19 or above)'
|
|
5068
|
+
'Unset server description '
|
|
5069
|
+
'(supported by --os-compute-api-version 2.19 or above)'
|
|
4999
5070
|
),
|
|
5000
5071
|
)
|
|
5001
|
-
parser.
|
|
5072
|
+
tag_group = parser.add_mutually_exclusive_group()
|
|
5073
|
+
tag_group.add_argument(
|
|
5002
5074
|
'--tag',
|
|
5003
5075
|
metavar='<tag>',
|
|
5004
5076
|
action='append',
|
|
@@ -5010,32 +5082,40 @@ class UnsetServer(command.Command):
|
|
|
5010
5082
|
'(supported by --os-compute-api-version 2.26 or above)'
|
|
5011
5083
|
),
|
|
5012
5084
|
)
|
|
5085
|
+
tag_group.add_argument(
|
|
5086
|
+
'--all-tags',
|
|
5087
|
+
action='store_true',
|
|
5088
|
+
help=_(
|
|
5089
|
+
'Remove all tags '
|
|
5090
|
+
'(supported by --os-compute-api-version 2.26 or above)'
|
|
5091
|
+
),
|
|
5092
|
+
)
|
|
5013
5093
|
return parser
|
|
5014
5094
|
|
|
5015
5095
|
def take_action(self, parsed_args):
|
|
5016
|
-
compute_client = self.app.client_manager.compute
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
parsed_args.server,
|
|
5096
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
5097
|
+
|
|
5098
|
+
server = compute_client.find_server(
|
|
5099
|
+
parsed_args.server, ignore_missing=False
|
|
5020
5100
|
)
|
|
5021
5101
|
|
|
5022
|
-
if parsed_args.properties:
|
|
5023
|
-
compute_client.
|
|
5102
|
+
if parsed_args.properties or parsed_args.all_properties:
|
|
5103
|
+
compute_client.delete_server_metadata(
|
|
5104
|
+
server, parsed_args.properties or None
|
|
5105
|
+
)
|
|
5024
5106
|
|
|
5025
5107
|
if parsed_args.description:
|
|
5026
|
-
if
|
|
5108
|
+
if not sdk_utils.supports_microversion(compute_client, '2.19'):
|
|
5027
5109
|
msg = _(
|
|
5028
|
-
'--os-compute-api-version 2.19 or greater is '
|
|
5029
|
-
'
|
|
5110
|
+
'--os-compute-api-version 2.19 or greater is required to '
|
|
5111
|
+
'support the --description option'
|
|
5030
5112
|
)
|
|
5031
5113
|
raise exceptions.CommandError(msg)
|
|
5032
|
-
compute_client.servers.update(
|
|
5033
|
-
server,
|
|
5034
|
-
description="",
|
|
5035
|
-
)
|
|
5036
5114
|
|
|
5037
|
-
|
|
5038
|
-
|
|
5115
|
+
compute_client.update_server(server, description="")
|
|
5116
|
+
|
|
5117
|
+
if parsed_args.tags or parsed_args.all_tags:
|
|
5118
|
+
if not sdk_utils.supports_microversion(compute_client, '2.26'):
|
|
5039
5119
|
msg = _(
|
|
5040
5120
|
'--os-compute-api-version 2.26 or greater is required to '
|
|
5041
5121
|
'support the --tag option'
|
|
@@ -5043,7 +5123,10 @@ class UnsetServer(command.Command):
|
|
|
5043
5123
|
raise exceptions.CommandError(msg)
|
|
5044
5124
|
|
|
5045
5125
|
for tag in parsed_args.tags:
|
|
5046
|
-
compute_client.
|
|
5126
|
+
compute_client.remove_tag_from_server(server, tag)
|
|
5127
|
+
|
|
5128
|
+
if parsed_args.all_tags:
|
|
5129
|
+
compute_client.remove_tags_from_server(server)
|
|
5047
5130
|
|
|
5048
5131
|
|
|
5049
5132
|
class UnshelveServer(command.Command):
|