python-openstackclient 6.6.1__py3-none-any.whl → 7.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openstackclient/api/api.py +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 +16 -4
- openstackclient/common/configuration.py +1 -1
- openstackclient/common/extension.py +1 -1
- openstackclient/common/limits.py +66 -32
- openstackclient/common/module.py +3 -3
- openstackclient/common/progressbar.py +2 -2
- openstackclient/common/project_cleanup.py +5 -2
- openstackclient/common/quota.py +281 -410
- openstackclient/common/versions.py +1 -1
- openstackclient/compute/client.py +7 -116
- openstackclient/compute/v2/agent.py +75 -49
- openstackclient/compute/v2/aggregate.py +9 -9
- openstackclient/compute/v2/console.py +2 -2
- openstackclient/compute/v2/flavor.py +6 -6
- openstackclient/compute/v2/host.py +38 -33
- openstackclient/compute/v2/hypervisor.py +4 -3
- openstackclient/compute/v2/keypair.py +7 -8
- openstackclient/compute/v2/server.py +478 -396
- openstackclient/compute/v2/server_backup.py +1 -1
- openstackclient/compute/v2/server_group.py +4 -4
- openstackclient/compute/v2/server_image.py +1 -1
- openstackclient/compute/v2/server_migration.py +3 -4
- openstackclient/compute/v2/service.py +4 -4
- openstackclient/compute/v2/usage.py +3 -3
- openstackclient/identity/common.py +34 -0
- openstackclient/identity/v2_0/catalog.py +2 -2
- openstackclient/identity/v2_0/ec2creds.py +4 -4
- openstackclient/identity/v2_0/endpoint.py +4 -4
- openstackclient/identity/v2_0/project.py +6 -6
- openstackclient/identity/v2_0/role.py +5 -5
- openstackclient/identity/v2_0/role_assignment.py +1 -1
- openstackclient/identity/v2_0/service.py +4 -4
- openstackclient/identity/v2_0/token.py +2 -2
- openstackclient/identity/v2_0/user.py +7 -7
- openstackclient/identity/v3/access_rule.py +3 -3
- openstackclient/identity/v3/application_credential.py +127 -45
- openstackclient/identity/v3/catalog.py +2 -2
- openstackclient/identity/v3/consumer.py +4 -4
- openstackclient/identity/v3/credential.py +5 -5
- openstackclient/identity/v3/domain.py +5 -5
- openstackclient/identity/v3/ec2creds.py +4 -4
- openstackclient/identity/v3/endpoint.py +7 -7
- openstackclient/identity/v3/endpoint_group.py +8 -10
- openstackclient/identity/v3/federation_protocol.py +5 -5
- openstackclient/identity/v3/group.py +8 -8
- openstackclient/identity/v3/identity_provider.py +5 -5
- openstackclient/identity/v3/implied_role.py +3 -3
- openstackclient/identity/v3/limit.py +5 -5
- openstackclient/identity/v3/mapping.py +5 -5
- openstackclient/identity/v3/policy.py +5 -5
- openstackclient/identity/v3/project.py +5 -5
- openstackclient/identity/v3/region.py +5 -5
- openstackclient/identity/v3/registered_limit.py +5 -5
- openstackclient/identity/v3/role.py +7 -7
- openstackclient/identity/v3/role_assignment.py +92 -140
- openstackclient/identity/v3/service.py +64 -34
- openstackclient/identity/v3/service_provider.py +4 -4
- openstackclient/identity/v3/tag.py +2 -2
- openstackclient/identity/v3/token.py +5 -5
- openstackclient/identity/v3/trust.py +3 -3
- openstackclient/identity/v3/user.py +144 -80
- openstackclient/image/client.py +4 -4
- openstackclient/image/v1/image.py +8 -9
- openstackclient/image/v2/cache.py +12 -10
- openstackclient/image/v2/metadef_objects.py +44 -0
- openstackclient/image/v2/metadef_resource_type_association.py +189 -0
- openstackclient/image/v2/task.py +1 -1
- openstackclient/network/common.py +6 -5
- openstackclient/network/utils.py +2 -2
- openstackclient/network/v2/address_group.py +6 -6
- openstackclient/network/v2/address_scope.py +5 -5
- openstackclient/network/v2/default_security_group_rule.py +1 -1
- openstackclient/network/v2/floating_ip.py +8 -10
- openstackclient/network/v2/floating_ip_pool.py +6 -15
- openstackclient/network/v2/floating_ip_port_forwarding.py +5 -13
- openstackclient/network/v2/ip_availability.py +2 -2
- openstackclient/network/v2/l3_conntrack_helper.py +5 -5
- openstackclient/network/v2/network.py +8 -8
- openstackclient/network/v2/network_agent.py +8 -8
- openstackclient/network/v2/network_auto_allocated_topology.py +2 -2
- openstackclient/network/v2/network_flavor.py +6 -8
- openstackclient/network/v2/network_flavor_profile.py +4 -4
- openstackclient/network/v2/network_meter.py +3 -3
- openstackclient/network/v2/network_meter_rule.py +3 -3
- openstackclient/network/v2/network_qos_policy.py +5 -5
- openstackclient/network/v2/network_qos_rule.py +9 -9
- openstackclient/network/v2/network_qos_rule_type.py +1 -1
- openstackclient/network/v2/network_rbac.py +5 -5
- openstackclient/network/v2/network_segment.py +5 -5
- openstackclient/network/v2/network_segment_range.py +7 -7
- openstackclient/network/v2/network_trunk.py +7 -7
- openstackclient/network/v2/port.py +26 -12
- openstackclient/network/v2/router.py +403 -54
- openstackclient/network/v2/security_group.py +18 -14
- openstackclient/network/v2/security_group_rule.py +18 -15
- openstackclient/network/v2/subnet.py +15 -8
- openstackclient/network/v2/subnet_pool.py +6 -6
- openstackclient/object/v1/account.py +2 -2
- openstackclient/object/v1/container.py +7 -7
- openstackclient/object/v1/object.py +7 -7
- openstackclient/shell.py +4 -6
- openstackclient/tests/functional/base.py +1 -1
- openstackclient/tests/functional/common/test_extension.py +1 -1
- openstackclient/tests/functional/common/test_help.py +2 -2
- openstackclient/tests/functional/common/test_module.py +1 -1
- openstackclient/tests/functional/common/test_quota.py +43 -61
- openstackclient/tests/functional/compute/v2/common.py +2 -2
- openstackclient/tests/functional/compute/v2/test_flavor.py +2 -2
- openstackclient/tests/functional/compute/v2/test_keypair.py +1 -1
- openstackclient/tests/functional/compute/v2/test_server.py +5 -5
- openstackclient/tests/functional/compute/v2/test_server_event.py +1 -1
- openstackclient/tests/functional/identity/v2/common.py +3 -3
- openstackclient/tests/functional/identity/v3/common.py +14 -6
- openstackclient/tests/functional/identity/v3/test_application_credential.py +13 -19
- openstackclient/tests/functional/identity/v3/test_domain.py +1 -3
- openstackclient/tests/functional/identity/v3/test_endpoint.py +1 -1
- openstackclient/tests/functional/identity/v3/test_idp.py +1 -1
- openstackclient/tests/functional/identity/v3/test_limit.py +2 -2
- openstackclient/tests/functional/identity/v3/test_region.py +1 -3
- openstackclient/tests/functional/identity/v3/test_registered_limit.py +1 -1
- openstackclient/tests/functional/identity/v3/test_role.py +2 -2
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +210 -0
- openstackclient/tests/functional/identity/v3/test_service.py +4 -6
- openstackclient/tests/functional/identity/v3/test_service_provider.py +1 -3
- openstackclient/tests/functional/image/base.py +1 -1
- openstackclient/tests/functional/image/v2/test_image.py +1 -1
- openstackclient/tests/functional/image/v2/test_info.py +1 -1
- openstackclient/tests/functional/network/v2/common.py +4 -6
- openstackclient/tests/functional/network/v2/test_network.py +5 -3
- openstackclient/tests/functional/network/v2/test_network_agent.py +7 -5
- openstackclient/tests/functional/network/v2/test_network_qos_rule.py +4 -4
- openstackclient/tests/functional/network/v2/test_port.py +11 -7
- openstackclient/tests/functional/network/v2/test_router.py +2 -2
- openstackclient/tests/functional/object/v1/common.py +1 -1
- openstackclient/tests/functional/object/v1/test_container.py +3 -3
- openstackclient/tests/functional/object/v1/test_object.py +9 -13
- openstackclient/tests/functional/volume/base.py +1 -1
- openstackclient/tests/functional/volume/v1/test_service.py +1 -1
- openstackclient/tests/functional/volume/v1/test_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v1/test_transfer_request.py +2 -2
- openstackclient/tests/functional/volume/v1/test_volume_type.py +1 -1
- openstackclient/tests/functional/volume/v2/test_service.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_backup.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v2/test_volume_type.py +1 -1
- openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +2 -2
- openstackclient/tests/functional/volume/v3/test_volume_type.py +1 -1
- openstackclient/tests/unit/api/fakes.py +1 -1
- openstackclient/tests/unit/api/test_api.py +2 -2
- openstackclient/tests/unit/api/test_compute_v2.py +522 -707
- openstackclient/tests/unit/api/test_image_v1.py +1 -1
- openstackclient/tests/unit/api/test_image_v2.py +1 -1
- openstackclient/tests/unit/api/test_object_store_v1.py +4 -4
- openstackclient/tests/unit/common/test_limits.py +73 -35
- openstackclient/tests/unit/common/test_logs.py +2 -2
- openstackclient/tests/unit/common/test_module.py +4 -2
- openstackclient/tests/unit/common/test_project_cleanup.py +31 -6
- openstackclient/tests/unit/common/test_quota.py +490 -630
- openstackclient/tests/unit/compute/v2/fakes.py +37 -286
- openstackclient/tests/unit/compute/v2/test_agent.py +189 -147
- openstackclient/tests/unit/compute/v2/test_aggregate.py +18 -16
- openstackclient/tests/unit/compute/v2/test_console.py +4 -5
- openstackclient/tests/unit/compute/v2/test_flavor.py +59 -68
- openstackclient/tests/unit/compute/v2/test_host.py +83 -54
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +28 -31
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -2
- openstackclient/tests/unit/compute/v2/test_keypair.py +65 -50
- openstackclient/tests/unit/compute/v2/test_server.py +2895 -2459
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_event.py +14 -39
- openstackclient/tests/unit/compute/v2/test_server_group.py +28 -29
- openstackclient/tests/unit/compute/v2/test_server_migration.py +43 -68
- openstackclient/tests/unit/compute/v2/test_server_volume.py +17 -34
- openstackclient/tests/unit/compute/v2/test_service.py +34 -52
- openstackclient/tests/unit/compute/v2/test_usage.py +4 -4
- openstackclient/tests/unit/fakes.py +11 -11
- openstackclient/tests/unit/identity/v2_0/fakes.py +27 -10
- openstackclient/tests/unit/identity/v2_0/test_catalog.py +3 -3
- openstackclient/tests/unit/identity/v2_0/test_endpoint.py +7 -7
- openstackclient/tests/unit/identity/v2_0/test_project.py +8 -8
- openstackclient/tests/unit/identity/v2_0/test_role.py +10 -10
- openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +4 -4
- openstackclient/tests/unit/identity/v2_0/test_service.py +6 -6
- openstackclient/tests/unit/identity/v2_0/test_token.py +4 -4
- openstackclient/tests/unit/identity/v2_0/test_user.py +8 -8
- openstackclient/tests/unit/identity/v3/fakes.py +59 -20
- openstackclient/tests/unit/identity/v3/test_access_rule.py +5 -5
- openstackclient/tests/unit/identity/v3/test_application_credential.py +212 -235
- openstackclient/tests/unit/identity/v3/test_catalog.py +3 -3
- openstackclient/tests/unit/identity/v3/test_consumer.py +7 -8
- openstackclient/tests/unit/identity/v3/test_credential.py +9 -9
- openstackclient/tests/unit/identity/v3/test_domain.py +8 -8
- openstackclient/tests/unit/identity/v3/test_endpoint.py +13 -13
- openstackclient/tests/unit/identity/v3/test_endpoint_group.py +12 -14
- openstackclient/tests/unit/identity/v3/test_group.py +12 -12
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +8 -8
- openstackclient/tests/unit/identity/v3/test_implied_role.py +5 -5
- openstackclient/tests/unit/identity/v3/test_limit.py +7 -7
- openstackclient/tests/unit/identity/v3/test_mappings.py +7 -7
- openstackclient/tests/unit/identity/v3/test_oauth.py +5 -5
- openstackclient/tests/unit/identity/v3/test_project.py +16 -16
- openstackclient/tests/unit/identity/v3/test_protocol.py +7 -7
- openstackclient/tests/unit/identity/v3/test_region.py +7 -7
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +12 -13
- openstackclient/tests/unit/identity/v3/test_role.py +13 -13
- openstackclient/tests/unit/identity/v3/test_role_assignment.py +410 -331
- openstackclient/tests/unit/identity/v3/test_service.py +93 -97
- openstackclient/tests/unit/identity/v3/test_service_provider.py +7 -7
- openstackclient/tests/unit/identity/v3/test_token.py +4 -4
- openstackclient/tests/unit/identity/v3/test_trust.py +9 -9
- openstackclient/tests/unit/identity/v3/test_unscoped_saml.py +4 -4
- openstackclient/tests/unit/identity/v3/test_user.py +299 -327
- openstackclient/tests/unit/image/v1/test_image.py +6 -6
- openstackclient/tests/unit/image/v2/fakes.py +46 -9
- openstackclient/tests/unit/image/v2/test_cache.py +2 -2
- openstackclient/tests/unit/image/v2/test_image.py +3 -3
- openstackclient/tests/unit/image/v2/test_metadef_objects.py +62 -0
- openstackclient/tests/unit/image/v2/test_metadef_resource_type_association.py +131 -0
- openstackclient/tests/unit/integ/base.py +1 -1
- openstackclient/tests/unit/integ/cli/test_project.py +4 -4
- openstackclient/tests/unit/integ/cli/test_shell.py +7 -7
- openstackclient/tests/unit/network/test_common.py +12 -21
- openstackclient/tests/unit/network/v2/fakes.py +64 -130
- openstackclient/tests/unit/network/v2/test_address_group.py +15 -15
- openstackclient/tests/unit/network/v2/test_address_scope.py +13 -13
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +49 -27
- openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +40 -38
- openstackclient/tests/unit/network/v2/test_floating_ip_network.py +15 -15
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +4 -7
- openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +3 -5
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +11 -11
- openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -6
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +11 -21
- openstackclient/tests/unit/network/v2/test_local_ip.py +7 -7
- openstackclient/tests/unit/network/v2/test_local_ip_association.py +3 -5
- openstackclient/tests/unit/network/v2/test_ndp_proxy.py +13 -13
- openstackclient/tests/unit/network/v2/test_network.py +23 -28
- openstackclient/tests/unit/network/v2/test_network_agent.py +17 -21
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +8 -8
- openstackclient/tests/unit/network/v2/test_network_compute.py +66 -65
- openstackclient/tests/unit/network/v2/test_network_flavor.py +17 -19
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +13 -13
- openstackclient/tests/unit/network/v2/test_network_meter.py +11 -11
- openstackclient/tests/unit/network/v2/test_network_meter_rule.py +11 -11
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +11 -21
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +51 -77
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +5 -9
- openstackclient/tests/unit/network/v2/test_network_rbac.py +12 -12
- openstackclient/tests/unit/network/v2/test_network_segment.py +11 -15
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +11 -13
- openstackclient/tests/unit/network/v2/test_network_service_provider.py +3 -5
- openstackclient/tests/unit/network/v2/test_network_trunk.py +11 -11
- openstackclient/tests/unit/network/v2/test_port.py +22 -25
- openstackclient/tests/unit/network/v2/test_router.py +721 -51
- openstackclient/tests/unit/network/v2/test_security_group_compute.py +65 -49
- openstackclient/tests/unit/network/v2/test_security_group_network.py +15 -15
- openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +57 -45
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +11 -19
- openstackclient/tests/unit/network/v2/test_subnet.py +29 -25
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +15 -15
- openstackclient/tests/unit/object/v1/fakes.py +1 -1
- openstackclient/tests/unit/object/v1/test_container.py +5 -5
- openstackclient/tests/unit/object/v1/test_container_all.py +6 -6
- openstackclient/tests/unit/object/v1/test_object.py +3 -3
- openstackclient/tests/unit/object/v1/test_object_all.py +5 -5
- openstackclient/tests/unit/test_shell.py +5 -5
- openstackclient/tests/unit/utils.py +4 -1
- openstackclient/tests/unit/volume/test_find_resource.py +2 -2
- openstackclient/tests/unit/volume/v1/fakes.py +5 -6
- openstackclient/tests/unit/volume/v1/test_volume.py +5 -4
- openstackclient/tests/unit/volume/v2/fakes.py +39 -259
- openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py +5 -5
- openstackclient/tests/unit/volume/v2/test_qos_specs.py +9 -9
- openstackclient/tests/unit/volume/v2/test_volume.py +21 -87
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +7 -368
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +1 -1
- openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +0 -44
- openstackclient/tests/unit/volume/v2/test_volume_type.py +6 -87
- openstackclient/tests/unit/volume/v3/fakes.py +505 -22
- openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py +2 -3
- openstackclient/tests/unit/volume/v3/test_block_storage_cluster.py +10 -11
- openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +10 -6
- openstackclient/tests/unit/volume/v3/test_block_storage_manage.py +25 -17
- openstackclient/tests/unit/volume/v3/test_block_storage_resource_filter.py +6 -32
- openstackclient/tests/unit/volume/v3/test_service.py +271 -0
- openstackclient/tests/unit/volume/v3/test_volume.py +2177 -33
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +48 -52
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +892 -0
- openstackclient/tests/unit/volume/v3/test_volume_group.py +19 -20
- openstackclient/tests/unit/volume/v3/test_volume_group_snapshot.py +14 -34
- openstackclient/tests/unit/volume/v3/test_volume_group_type.py +13 -16
- openstackclient/tests/unit/volume/v3/test_volume_message.py +10 -11
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +161 -0
- openstackclient/tests/unit/volume/v3/test_volume_transfer_request.py +425 -0
- openstackclient/tests/unit/volume/v3/test_volume_type.py +1109 -0
- openstackclient/volume/v1/qos_specs.py +7 -7
- openstackclient/volume/v1/service.py +2 -2
- openstackclient/volume/v1/volume.py +12 -12
- openstackclient/volume/v1/volume_backup.py +7 -7
- openstackclient/volume/v1/volume_snapshot.py +8 -8
- openstackclient/volume/v1/volume_transfer_request.py +5 -5
- openstackclient/volume/v1/volume_type.py +7 -7
- openstackclient/volume/v2/backup_record.py +2 -2
- openstackclient/volume/v2/consistency_group.py +7 -9
- openstackclient/volume/v2/consistency_group_snapshot.py +4 -12
- openstackclient/volume/v2/qos_specs.py +7 -7
- openstackclient/volume/v2/service.py +2 -2
- openstackclient/volume/v2/volume.py +80 -80
- openstackclient/volume/v2/volume_backend.py +2 -2
- openstackclient/volume/v2/volume_backup.py +7 -217
- openstackclient/volume/v2/volume_host.py +2 -2
- openstackclient/volume/v2/volume_snapshot.py +8 -8
- openstackclient/volume/v2/volume_transfer_request.py +5 -37
- openstackclient/volume/v2/volume_type.py +7 -89
- openstackclient/volume/v3/service.py +56 -0
- openstackclient/volume/v3/volume.py +971 -0
- openstackclient/volume/v3/volume_attachment.py +31 -29
- openstackclient/volume/v3/volume_backup.py +670 -0
- openstackclient/volume/v3/volume_message.py +1 -1
- openstackclient/volume/v3/volume_snapshot.py +97 -0
- openstackclient/volume/v3/volume_transfer_request.py +233 -0
- openstackclient/volume/v3/volume_type.py +967 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.0.0.dist-info}/AUTHORS +4 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.0.0.dist-info}/METADATA +2 -3
- python_openstackclient-7.0.0.dist-info/RECORD +502 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.0.0.dist-info}/entry_points.txt +33 -27
- python_openstackclient-7.0.0.dist-info/pbr.json +1 -0
- python_openstackclient-6.6.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.0.0.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.0.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-6.6.1.dist-info → python_openstackclient-7.0.0.dist-info}/top_level.txt +0 -0
openstackclient/common/quota.py
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
12
12
|
# License for the specific language governing permissions and limitations
|
|
13
13
|
# under the License.
|
|
14
|
-
#
|
|
15
14
|
|
|
16
15
|
"""Quota action implementations"""
|
|
17
16
|
|
|
@@ -20,7 +19,9 @@ import itertools
|
|
|
20
19
|
import logging
|
|
21
20
|
import sys
|
|
22
21
|
|
|
22
|
+
from openstack import exceptions as sdk_exceptions
|
|
23
23
|
from osc_lib.command import command
|
|
24
|
+
from osc_lib import exceptions
|
|
24
25
|
from osc_lib import utils
|
|
25
26
|
|
|
26
27
|
from openstackclient.i18n import _
|
|
@@ -33,7 +34,6 @@ LOG = logging.getLogger(__name__)
|
|
|
33
34
|
|
|
34
35
|
COMPUTE_QUOTAS = {
|
|
35
36
|
'cores': 'cores',
|
|
36
|
-
'fixed_ips': 'fixed-ips',
|
|
37
37
|
'injected_file_content_bytes': 'injected-file-size',
|
|
38
38
|
'injected_file_path_bytes': 'injected-path-size',
|
|
39
39
|
'injected_files': 'injected-files',
|
|
@@ -41,8 +41,8 @@ COMPUTE_QUOTAS = {
|
|
|
41
41
|
'key_pairs': 'key-pairs',
|
|
42
42
|
'metadata_items': 'properties',
|
|
43
43
|
'ram': 'ram',
|
|
44
|
-
'server_groups': 'server-groups',
|
|
45
44
|
'server_group_members': 'server-group-members',
|
|
45
|
+
'server_groups': 'server-groups',
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
VOLUME_QUOTAS = {
|
|
@@ -61,6 +61,7 @@ IMPACT_VOLUME_TYPE_QUOTAS = [
|
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
NOVA_NETWORK_QUOTAS = {
|
|
64
|
+
'fixed_ips': 'fixed-ips',
|
|
64
65
|
'floating_ips': 'floating-ips',
|
|
65
66
|
'security_group_rules': 'secgroup-rules',
|
|
66
67
|
'security_groups': 'secgroups',
|
|
@@ -104,11 +105,8 @@ def _xform_get_quota(data, value, keys):
|
|
|
104
105
|
|
|
105
106
|
def get_project(app, project):
|
|
106
107
|
if project is not None:
|
|
107
|
-
identity_client = app.client_manager.identity
|
|
108
|
-
project =
|
|
109
|
-
identity_client.projects,
|
|
110
|
-
project,
|
|
111
|
-
)
|
|
108
|
+
identity_client = app.client_manager.sdk_connection.identity
|
|
109
|
+
project = identity_client.find_project(project, ignore_missing=False)
|
|
112
110
|
project_id = project.id
|
|
113
111
|
project_name = project.name
|
|
114
112
|
elif app.client_manager.auth_ref:
|
|
@@ -130,57 +128,50 @@ def get_compute_quotas(
|
|
|
130
128
|
app,
|
|
131
129
|
project_id,
|
|
132
130
|
*,
|
|
133
|
-
quota_class=False,
|
|
134
131
|
detail=False,
|
|
135
132
|
default=False,
|
|
136
133
|
):
|
|
137
134
|
try:
|
|
138
|
-
client = app.client_manager.compute
|
|
139
|
-
if
|
|
140
|
-
|
|
141
|
-
# as the nova API doesn't care what you pass in. We only pass the
|
|
142
|
-
# project in to avoid weirding people out :)
|
|
143
|
-
quota = client.quota_classes.get(project_id)
|
|
144
|
-
elif default:
|
|
145
|
-
quota = client.quotas.defaults(project_id)
|
|
135
|
+
client = app.client_manager.sdk_connection.compute
|
|
136
|
+
if default:
|
|
137
|
+
quota = client.get_quota_set_defaults(project_id)
|
|
146
138
|
else:
|
|
147
|
-
quota = client.
|
|
148
|
-
except
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
139
|
+
quota = client.get_quota_set(project_id, usage=detail)
|
|
140
|
+
except sdk_exceptions.EndpointNotFound:
|
|
141
|
+
return {}
|
|
142
|
+
data = quota.to_dict()
|
|
143
|
+
if not detail:
|
|
144
|
+
del data['usage']
|
|
145
|
+
del data['reservation']
|
|
146
|
+
return data
|
|
153
147
|
|
|
154
148
|
|
|
155
149
|
def get_volume_quotas(
|
|
156
150
|
app,
|
|
157
151
|
project_id,
|
|
158
152
|
*,
|
|
159
|
-
quota_class=False,
|
|
160
153
|
detail=False,
|
|
161
154
|
default=False,
|
|
162
155
|
):
|
|
163
156
|
try:
|
|
164
|
-
client = app.client_manager.volume
|
|
165
|
-
if
|
|
166
|
-
quota = client.
|
|
167
|
-
elif default:
|
|
168
|
-
quota = client.quotas.defaults(project_id)
|
|
169
|
-
else:
|
|
170
|
-
quota = client.quotas.get(project_id, usage=detail)
|
|
171
|
-
except Exception as e:
|
|
172
|
-
if type(e).__name__ == 'EndpointNotFound':
|
|
173
|
-
return {}
|
|
157
|
+
client = app.client_manager.sdk_connection.volume
|
|
158
|
+
if default:
|
|
159
|
+
quota = client.get_quota_set_defaults(project_id)
|
|
174
160
|
else:
|
|
175
|
-
|
|
176
|
-
|
|
161
|
+
quota = client.get_quota_set(project_id, usage=detail)
|
|
162
|
+
except sdk_exceptions.EndpointNotFound:
|
|
163
|
+
return {}
|
|
164
|
+
data = quota.to_dict()
|
|
165
|
+
if not detail:
|
|
166
|
+
del data['usage']
|
|
167
|
+
del data['reservation']
|
|
168
|
+
return data
|
|
177
169
|
|
|
178
170
|
|
|
179
171
|
def get_network_quotas(
|
|
180
172
|
app,
|
|
181
173
|
project_id,
|
|
182
174
|
*,
|
|
183
|
-
quota_class=False,
|
|
184
175
|
detail=False,
|
|
185
176
|
default=False,
|
|
186
177
|
):
|
|
@@ -207,11 +198,6 @@ def get_network_quotas(
|
|
|
207
198
|
|
|
208
199
|
return result
|
|
209
200
|
|
|
210
|
-
# neutron doesn't have the concept of quota classes and if we're using
|
|
211
|
-
# nova-network we already fetched this
|
|
212
|
-
if quota_class:
|
|
213
|
-
return {}
|
|
214
|
-
|
|
215
201
|
# we have nothing to return if we are not using neutron
|
|
216
202
|
if not app.client_manager.is_network_endpoint_enabled():
|
|
217
203
|
return {}
|
|
@@ -227,34 +213,14 @@ def get_network_quotas(
|
|
|
227
213
|
|
|
228
214
|
|
|
229
215
|
class ListQuota(command.Lister):
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
216
|
+
"""List quotas for all projects with non-default quota values.
|
|
217
|
+
|
|
218
|
+
Empty output means all projects are using default quotas, which can be
|
|
219
|
+
inspected with 'openstack quota show --default'.
|
|
220
|
+
"""
|
|
234
221
|
|
|
235
222
|
def get_parser(self, prog_name):
|
|
236
223
|
parser = super().get_parser(prog_name)
|
|
237
|
-
# TODO(stephenfin): Remove in OSC 8.0
|
|
238
|
-
parser.add_argument(
|
|
239
|
-
'--project',
|
|
240
|
-
metavar='<project>',
|
|
241
|
-
help=_(
|
|
242
|
-
"**Deprecated** List quotas for this project <project> "
|
|
243
|
-
"(name or ID). "
|
|
244
|
-
"Use 'quota show' instead."
|
|
245
|
-
),
|
|
246
|
-
)
|
|
247
|
-
# TODO(stephenfin): Remove in OSC 8.0
|
|
248
|
-
parser.add_argument(
|
|
249
|
-
'--detail',
|
|
250
|
-
dest='detail',
|
|
251
|
-
action='store_true',
|
|
252
|
-
default=False,
|
|
253
|
-
help=_(
|
|
254
|
-
"**Deprecated** Show details about quotas usage. "
|
|
255
|
-
"Use 'quota show --usage' instead."
|
|
256
|
-
),
|
|
257
|
-
)
|
|
258
224
|
option = parser.add_mutually_exclusive_group(required=True)
|
|
259
225
|
option.add_argument(
|
|
260
226
|
'--compute',
|
|
@@ -276,279 +242,197 @@ class ListQuota(command.Lister):
|
|
|
276
242
|
)
|
|
277
243
|
return parser
|
|
278
244
|
|
|
279
|
-
def
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
quotas = {}
|
|
245
|
+
def _list_quota_compute(self, parsed_args, project_ids):
|
|
246
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
247
|
+
result = []
|
|
284
248
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
249
|
+
for project_id in project_ids:
|
|
250
|
+
try:
|
|
251
|
+
project_data = compute_client.get_quota_set(project_id)
|
|
252
|
+
except (
|
|
253
|
+
sdk_exceptions.NotFoundException,
|
|
254
|
+
sdk_exceptions.ForbiddenException,
|
|
255
|
+
) as exc:
|
|
256
|
+
# Project not found, move on to next one
|
|
257
|
+
LOG.warning(f"Project {project_id} not found: {exc}")
|
|
258
|
+
continue
|
|
293
259
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
project,
|
|
299
|
-
detail=parsed_args.detail,
|
|
300
|
-
)
|
|
260
|
+
project_result = _xform_get_quota(
|
|
261
|
+
project_data,
|
|
262
|
+
project_id,
|
|
263
|
+
COMPUTE_QUOTAS.keys(),
|
|
301
264
|
)
|
|
302
265
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
detail=parsed_args.detail,
|
|
309
|
-
),
|
|
266
|
+
default_data = compute_client.get_quota_set_defaults(project_id)
|
|
267
|
+
default_result = _xform_get_quota(
|
|
268
|
+
default_data,
|
|
269
|
+
project_id,
|
|
270
|
+
COMPUTE_QUOTAS.keys(),
|
|
310
271
|
)
|
|
311
272
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# NOTE(slaweq): there is no detailed quotas info for some resources
|
|
315
|
-
# and it shouldn't be displayed here
|
|
316
|
-
if isinstance(values, dict):
|
|
317
|
-
result.append(
|
|
318
|
-
{
|
|
319
|
-
'resource': resource,
|
|
320
|
-
'in_use': values.get('in_use'),
|
|
321
|
-
'reserved': values.get('reserved'),
|
|
322
|
-
'limit': values.get('limit'),
|
|
323
|
-
}
|
|
324
|
-
)
|
|
273
|
+
if default_result != project_result:
|
|
274
|
+
result += project_result
|
|
325
275
|
|
|
326
276
|
columns = (
|
|
327
|
-
'
|
|
328
|
-
'
|
|
329
|
-
'
|
|
330
|
-
'
|
|
277
|
+
'id',
|
|
278
|
+
'cores',
|
|
279
|
+
'injected_files',
|
|
280
|
+
'injected_file_content_bytes',
|
|
281
|
+
'injected_file_path_bytes',
|
|
282
|
+
'instances',
|
|
283
|
+
'key_pairs',
|
|
284
|
+
'metadata_items',
|
|
285
|
+
'ram',
|
|
286
|
+
'server_groups',
|
|
287
|
+
'server_group_members',
|
|
331
288
|
)
|
|
332
289
|
column_headers = (
|
|
333
|
-
'
|
|
334
|
-
'
|
|
335
|
-
'
|
|
336
|
-
'
|
|
290
|
+
'Project ID',
|
|
291
|
+
'Cores',
|
|
292
|
+
'Injected Files',
|
|
293
|
+
'Injected File Content Bytes',
|
|
294
|
+
'Injected File Path Bytes',
|
|
295
|
+
'Instances',
|
|
296
|
+
'Key Pairs',
|
|
297
|
+
'Metadata Items',
|
|
298
|
+
'Ram',
|
|
299
|
+
'Server Groups',
|
|
300
|
+
'Server Group Members',
|
|
337
301
|
)
|
|
338
|
-
|
|
339
302
|
return (
|
|
340
303
|
column_headers,
|
|
341
304
|
(utils.get_dict_properties(s, columns) for s in result),
|
|
342
305
|
)
|
|
343
306
|
|
|
344
|
-
def
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
307
|
+
def _list_quota_volume(self, parsed_args, project_ids):
|
|
308
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
309
|
+
result = []
|
|
310
|
+
|
|
311
|
+
for project_id in project_ids:
|
|
312
|
+
try:
|
|
313
|
+
project_data = volume_client.get_quota_set(project_id)
|
|
314
|
+
except (
|
|
315
|
+
sdk_exceptions.NotFoundException,
|
|
316
|
+
sdk_exceptions.ForbiddenException,
|
|
317
|
+
) as exc:
|
|
318
|
+
# Project not found, move on to next one
|
|
319
|
+
LOG.warning(f"Project {project_id} not found: {exc}")
|
|
320
|
+
continue
|
|
321
|
+
|
|
322
|
+
project_result = _xform_get_quota(
|
|
323
|
+
project_data,
|
|
324
|
+
project_id,
|
|
325
|
+
VOLUME_QUOTAS.keys(),
|
|
349
326
|
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
327
|
+
|
|
328
|
+
default_data = volume_client.get_quota_set_defaults(project_id)
|
|
329
|
+
default_result = _xform_get_quota(
|
|
330
|
+
default_data,
|
|
331
|
+
project_id,
|
|
332
|
+
VOLUME_QUOTAS.keys(),
|
|
355
333
|
)
|
|
356
|
-
self.log.warning(msg)
|
|
357
334
|
|
|
335
|
+
if default_result != project_result:
|
|
336
|
+
result += project_result
|
|
337
|
+
|
|
338
|
+
columns = (
|
|
339
|
+
'id',
|
|
340
|
+
'backups',
|
|
341
|
+
'backup_gigabytes',
|
|
342
|
+
'gigabytes',
|
|
343
|
+
'per_volume_gigabytes',
|
|
344
|
+
'snapshots',
|
|
345
|
+
'volumes',
|
|
346
|
+
)
|
|
347
|
+
column_headers = (
|
|
348
|
+
'Project ID',
|
|
349
|
+
'Backups',
|
|
350
|
+
'Backup Gigabytes',
|
|
351
|
+
'Gigabytes',
|
|
352
|
+
'Per Volume Gigabytes',
|
|
353
|
+
'Snapshots',
|
|
354
|
+
'Volumes',
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return (
|
|
358
|
+
column_headers,
|
|
359
|
+
(utils.get_dict_properties(s, columns) for s in result),
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
def _list_quota_network(self, parsed_args, project_ids):
|
|
363
|
+
network_client = self.app.client_manager.network
|
|
358
364
|
result = []
|
|
359
|
-
project_ids = []
|
|
360
|
-
if parsed_args.project is None:
|
|
361
|
-
for p in self.app.client_manager.identity.projects.list():
|
|
362
|
-
project_ids.append(getattr(p, 'id', ''))
|
|
363
|
-
else:
|
|
364
|
-
identity_client = self.app.client_manager.identity
|
|
365
|
-
project = utils.find_resource(
|
|
366
|
-
identity_client.projects,
|
|
367
|
-
parsed_args.project,
|
|
368
|
-
)
|
|
369
|
-
project_ids.append(getattr(project, 'id', ''))
|
|
370
365
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
type(ex).__name__ == 'NotFound'
|
|
382
|
-
or ex.http_status >= 400
|
|
383
|
-
and ex.http_status <= 499
|
|
384
|
-
):
|
|
385
|
-
# Project not found, move on to next one
|
|
386
|
-
LOG.warning("Project %s not found: %s" % (p, ex))
|
|
387
|
-
continue
|
|
388
|
-
else:
|
|
389
|
-
raise
|
|
390
|
-
|
|
391
|
-
result_data = _xform_get_quota(
|
|
392
|
-
data,
|
|
393
|
-
p,
|
|
394
|
-
COMPUTE_QUOTAS.keys(),
|
|
395
|
-
)
|
|
396
|
-
default_data = compute_client.quotas.defaults(p)
|
|
397
|
-
result_default = _xform_get_quota(
|
|
398
|
-
default_data,
|
|
399
|
-
p,
|
|
400
|
-
COMPUTE_QUOTAS.keys(),
|
|
401
|
-
)
|
|
402
|
-
if result_default != result_data:
|
|
403
|
-
result += result_data
|
|
404
|
-
|
|
405
|
-
columns = (
|
|
406
|
-
'id',
|
|
407
|
-
'cores',
|
|
408
|
-
'fixed_ips',
|
|
409
|
-
'injected_files',
|
|
410
|
-
'injected_file_content_bytes',
|
|
411
|
-
'injected_file_path_bytes',
|
|
412
|
-
'instances',
|
|
413
|
-
'key_pairs',
|
|
414
|
-
'metadata_items',
|
|
415
|
-
'ram',
|
|
416
|
-
'server_groups',
|
|
417
|
-
'server_group_members',
|
|
418
|
-
)
|
|
419
|
-
column_headers = (
|
|
420
|
-
'Project ID',
|
|
421
|
-
'Cores',
|
|
422
|
-
'Fixed IPs',
|
|
423
|
-
'Injected Files',
|
|
424
|
-
'Injected File Content Bytes',
|
|
425
|
-
'Injected File Path Bytes',
|
|
426
|
-
'Instances',
|
|
427
|
-
'Key Pairs',
|
|
428
|
-
'Metadata Items',
|
|
429
|
-
'Ram',
|
|
430
|
-
'Server Groups',
|
|
431
|
-
'Server Group Members',
|
|
432
|
-
)
|
|
433
|
-
return (
|
|
434
|
-
column_headers,
|
|
435
|
-
(utils.get_dict_properties(s, columns) for s in result),
|
|
436
|
-
)
|
|
366
|
+
for project_id in project_ids:
|
|
367
|
+
try:
|
|
368
|
+
project_data = network_client.get_quota(project_id)
|
|
369
|
+
except (
|
|
370
|
+
sdk_exceptions.NotFoundException,
|
|
371
|
+
sdk_exceptions.ForbiddenException,
|
|
372
|
+
) as exc:
|
|
373
|
+
# Project not found, move on to next one
|
|
374
|
+
LOG.warning(f"Project {project_id} not found: {exc}")
|
|
375
|
+
continue
|
|
437
376
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
volume_client = self.app.client_manager.volume
|
|
443
|
-
for p in project_ids:
|
|
444
|
-
try:
|
|
445
|
-
data = volume_client.quotas.get(p)
|
|
446
|
-
except Exception as ex:
|
|
447
|
-
if type(ex).__name__ == 'NotFound':
|
|
448
|
-
# Project not found, move on to next one
|
|
449
|
-
LOG.warning("Project %s not found: %s" % (p, ex))
|
|
450
|
-
continue
|
|
451
|
-
else:
|
|
452
|
-
raise
|
|
453
|
-
|
|
454
|
-
result_data = _xform_get_quota(
|
|
455
|
-
data,
|
|
456
|
-
p,
|
|
457
|
-
VOLUME_QUOTAS.keys(),
|
|
458
|
-
)
|
|
459
|
-
default_data = volume_client.quotas.defaults(p)
|
|
460
|
-
result_default = _xform_get_quota(
|
|
461
|
-
default_data,
|
|
462
|
-
p,
|
|
463
|
-
VOLUME_QUOTAS.keys(),
|
|
464
|
-
)
|
|
465
|
-
if result_default != result_data:
|
|
466
|
-
result += result_data
|
|
467
|
-
|
|
468
|
-
columns = (
|
|
469
|
-
'id',
|
|
470
|
-
'backups',
|
|
471
|
-
'backup_gigabytes',
|
|
472
|
-
'gigabytes',
|
|
473
|
-
'per_volume_gigabytes',
|
|
474
|
-
'snapshots',
|
|
475
|
-
'volumes',
|
|
476
|
-
)
|
|
477
|
-
column_headers = (
|
|
478
|
-
'Project ID',
|
|
479
|
-
'Backups',
|
|
480
|
-
'Backup Gigabytes',
|
|
481
|
-
'Gigabytes',
|
|
482
|
-
'Per Volume Gigabytes',
|
|
483
|
-
'Snapshots',
|
|
484
|
-
'Volumes',
|
|
377
|
+
project_result = _xform_get_quota(
|
|
378
|
+
project_data,
|
|
379
|
+
project_id,
|
|
380
|
+
NETWORK_KEYS,
|
|
485
381
|
)
|
|
486
382
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
383
|
+
default_data = network_client.get_quota_default(project_id)
|
|
384
|
+
default_result = _xform_get_quota(
|
|
385
|
+
default_data,
|
|
386
|
+
project_id,
|
|
387
|
+
NETWORK_KEYS,
|
|
490
388
|
)
|
|
491
389
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
return self._get_detailed_quotas(parsed_args)
|
|
495
|
-
|
|
496
|
-
client = self.app.client_manager.network
|
|
497
|
-
for p in project_ids:
|
|
498
|
-
try:
|
|
499
|
-
data = client.get_quota(p)
|
|
500
|
-
except Exception as ex:
|
|
501
|
-
if type(ex).__name__ == 'NotFound':
|
|
502
|
-
# Project not found, move on to next one
|
|
503
|
-
LOG.warning("Project %s not found: %s" % (p, ex))
|
|
504
|
-
continue
|
|
505
|
-
else:
|
|
506
|
-
raise
|
|
507
|
-
|
|
508
|
-
result_data = _xform_get_quota(
|
|
509
|
-
data,
|
|
510
|
-
p,
|
|
511
|
-
NETWORK_KEYS,
|
|
512
|
-
)
|
|
513
|
-
default_data = client.get_quota_default(p)
|
|
514
|
-
result_default = _xform_get_quota(
|
|
515
|
-
default_data,
|
|
516
|
-
p,
|
|
517
|
-
NETWORK_KEYS,
|
|
518
|
-
)
|
|
519
|
-
if result_default != result_data:
|
|
520
|
-
result += result_data
|
|
521
|
-
|
|
522
|
-
columns = (
|
|
523
|
-
'id',
|
|
524
|
-
'floating_ips',
|
|
525
|
-
'networks',
|
|
526
|
-
'ports',
|
|
527
|
-
'rbac_policies',
|
|
528
|
-
'routers',
|
|
529
|
-
'security_groups',
|
|
530
|
-
'security_group_rules',
|
|
531
|
-
'subnets',
|
|
532
|
-
'subnet_pools',
|
|
533
|
-
)
|
|
534
|
-
column_headers = (
|
|
535
|
-
'Project ID',
|
|
536
|
-
'Floating IPs',
|
|
537
|
-
'Networks',
|
|
538
|
-
'Ports',
|
|
539
|
-
'RBAC Policies',
|
|
540
|
-
'Routers',
|
|
541
|
-
'Security Groups',
|
|
542
|
-
'Security Group Rules',
|
|
543
|
-
'Subnets',
|
|
544
|
-
'Subnet Pools',
|
|
545
|
-
)
|
|
390
|
+
if default_result != project_result:
|
|
391
|
+
result += project_result
|
|
546
392
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
393
|
+
columns = (
|
|
394
|
+
'id',
|
|
395
|
+
'floating_ips',
|
|
396
|
+
'networks',
|
|
397
|
+
'ports',
|
|
398
|
+
'rbac_policies',
|
|
399
|
+
'routers',
|
|
400
|
+
'security_groups',
|
|
401
|
+
'security_group_rules',
|
|
402
|
+
'subnets',
|
|
403
|
+
'subnet_pools',
|
|
404
|
+
)
|
|
405
|
+
column_headers = (
|
|
406
|
+
'Project ID',
|
|
407
|
+
'Floating IPs',
|
|
408
|
+
'Networks',
|
|
409
|
+
'Ports',
|
|
410
|
+
'RBAC Policies',
|
|
411
|
+
'Routers',
|
|
412
|
+
'Security Groups',
|
|
413
|
+
'Security Group Rules',
|
|
414
|
+
'Subnets',
|
|
415
|
+
'Subnet Pools',
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
column_headers,
|
|
420
|
+
(utils.get_dict_properties(s, columns) for s in result),
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def take_action(self, parsed_args):
|
|
424
|
+
project_ids = [
|
|
425
|
+
p.id
|
|
426
|
+
for p in self.app.client_manager.sdk_connection.identity.projects()
|
|
427
|
+
]
|
|
428
|
+
if parsed_args.compute:
|
|
429
|
+
return self._list_quota_compute(parsed_args, project_ids)
|
|
430
|
+
elif parsed_args.volume:
|
|
431
|
+
return self._list_quota_volume(parsed_args, project_ids)
|
|
432
|
+
elif parsed_args.network:
|
|
433
|
+
return self._list_quota_network(parsed_args, project_ids)
|
|
551
434
|
|
|
435
|
+
# will never get here
|
|
552
436
|
return ((), ())
|
|
553
437
|
|
|
554
438
|
|
|
@@ -590,14 +474,19 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
590
474
|
return rets
|
|
591
475
|
|
|
592
476
|
def get_parser(self, prog_name):
|
|
593
|
-
parser = super(
|
|
477
|
+
parser = super().get_parser(prog_name)
|
|
594
478
|
parser.add_argument(
|
|
595
479
|
'project',
|
|
596
480
|
metavar='<project/class>',
|
|
597
|
-
|
|
481
|
+
nargs='?',
|
|
482
|
+
help=_(
|
|
483
|
+
'Set quotas for this project or class (name or ID) '
|
|
484
|
+
'(defaults to current project)'
|
|
485
|
+
),
|
|
598
486
|
)
|
|
599
487
|
# TODO(stephenfin): Remove in OSC 8.0
|
|
600
|
-
parser.
|
|
488
|
+
type_group = parser.add_mutually_exclusive_group()
|
|
489
|
+
type_group.add_argument(
|
|
601
490
|
'--class',
|
|
602
491
|
dest='quota_class',
|
|
603
492
|
action='store_true',
|
|
@@ -609,6 +498,13 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
609
498
|
'(compute and volume only)'
|
|
610
499
|
),
|
|
611
500
|
)
|
|
501
|
+
type_group.add_argument(
|
|
502
|
+
'--default',
|
|
503
|
+
dest='default',
|
|
504
|
+
action='store_true',
|
|
505
|
+
default=False,
|
|
506
|
+
help=_('Set default quotas for <project>'),
|
|
507
|
+
)
|
|
612
508
|
for k, v, h in self._build_options_list():
|
|
613
509
|
parser.add_argument(
|
|
614
510
|
'--%s' % v,
|
|
@@ -627,22 +523,19 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
627
523
|
'--force',
|
|
628
524
|
action='store_true',
|
|
629
525
|
dest='force',
|
|
630
|
-
|
|
631
|
-
default=None,
|
|
526
|
+
default=False,
|
|
632
527
|
help=_(
|
|
633
|
-
'Force quota update (only supported by compute and network)
|
|
634
|
-
'(default for network)'
|
|
528
|
+
'Force quota update (only supported by compute and network)'
|
|
635
529
|
),
|
|
636
530
|
)
|
|
637
531
|
force_group.add_argument(
|
|
638
532
|
'--no-force',
|
|
639
533
|
action='store_false',
|
|
640
534
|
dest='force',
|
|
641
|
-
default=
|
|
535
|
+
default=False,
|
|
642
536
|
help=_(
|
|
643
537
|
'Do not force quota update '
|
|
644
|
-
'(only supported by compute and network) '
|
|
645
|
-
'(default for compute)'
|
|
538
|
+
'(only supported by compute and network) (default)'
|
|
646
539
|
),
|
|
647
540
|
)
|
|
648
541
|
# kept here for backwards compatibility/to keep the neutron folks happy
|
|
@@ -650,7 +543,7 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
650
543
|
'--check-limit',
|
|
651
544
|
action='store_false',
|
|
652
545
|
dest='force',
|
|
653
|
-
default=
|
|
546
|
+
default=False,
|
|
654
547
|
help=argparse.SUPPRESS,
|
|
655
548
|
)
|
|
656
549
|
return parser
|
|
@@ -662,20 +555,26 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
662
555
|
"never fully implemented and the compute and volume services "
|
|
663
556
|
"only support a single 'default' quota class while the "
|
|
664
557
|
"network service does not support quota classes at all. "
|
|
665
|
-
"Please use 'openstack quota
|
|
558
|
+
"Please use 'openstack quota set --default' instead."
|
|
666
559
|
)
|
|
667
560
|
self.log.warning(msg)
|
|
668
561
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
562
|
+
if (
|
|
563
|
+
parsed_args.quota_class or parsed_args.default
|
|
564
|
+
) and parsed_args.force:
|
|
565
|
+
msg = _('--force cannot be used with --class or --default')
|
|
566
|
+
raise exceptions.CommandError(msg)
|
|
567
|
+
|
|
568
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
569
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
570
|
+
|
|
672
571
|
compute_kwargs = {}
|
|
673
572
|
for k, v in COMPUTE_QUOTAS.items():
|
|
674
573
|
value = getattr(parsed_args, k, None)
|
|
675
574
|
if value is not None:
|
|
676
575
|
compute_kwargs[k] = value
|
|
677
576
|
|
|
678
|
-
if parsed_args.force is
|
|
577
|
+
if compute_kwargs and parsed_args.force is True:
|
|
679
578
|
compute_kwargs['force'] = parsed_args.force
|
|
680
579
|
|
|
681
580
|
volume_kwargs = {}
|
|
@@ -687,22 +586,6 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
687
586
|
volume_kwargs[k] = value
|
|
688
587
|
|
|
689
588
|
network_kwargs = {}
|
|
690
|
-
if parsed_args.force is True:
|
|
691
|
-
# Unlike compute, network doesn't provide a simple boolean option.
|
|
692
|
-
# Instead, it provides two options: 'force' and 'check_limit'
|
|
693
|
-
# (a.k.a. 'not force')
|
|
694
|
-
network_kwargs['force'] = True
|
|
695
|
-
elif parsed_args.force is False:
|
|
696
|
-
network_kwargs['check_limit'] = True
|
|
697
|
-
else:
|
|
698
|
-
msg = _(
|
|
699
|
-
"This command currently defaults to '--force' when modifying "
|
|
700
|
-
"network quotas. This behavior will change in a future "
|
|
701
|
-
"release. Consider explicitly providing '--force' or "
|
|
702
|
-
"'--no-force' options to avoid changes in behavior."
|
|
703
|
-
)
|
|
704
|
-
self.log.warning(msg)
|
|
705
|
-
|
|
706
589
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
707
590
|
for k, v in NETWORK_QUOTAS.items():
|
|
708
591
|
value = getattr(parsed_args, k, None)
|
|
@@ -714,15 +597,24 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
714
597
|
if value is not None:
|
|
715
598
|
compute_kwargs[k] = value
|
|
716
599
|
|
|
717
|
-
if
|
|
600
|
+
if network_kwargs:
|
|
601
|
+
if parsed_args.force is True:
|
|
602
|
+
# Unlike compute, network doesn't provide a simple boolean
|
|
603
|
+
# option. Instead, it provides two options: 'force' and
|
|
604
|
+
# 'check_limit' (a.k.a. 'not force')
|
|
605
|
+
network_kwargs['force'] = True
|
|
606
|
+
else:
|
|
607
|
+
network_kwargs['check_limit'] = True
|
|
608
|
+
|
|
609
|
+
if parsed_args.quota_class or parsed_args.default:
|
|
718
610
|
if compute_kwargs:
|
|
719
|
-
compute_client.
|
|
720
|
-
parsed_args.project,
|
|
611
|
+
compute_client.update_quota_class_set(
|
|
612
|
+
parsed_args.project or 'default',
|
|
721
613
|
**compute_kwargs,
|
|
722
614
|
)
|
|
723
615
|
if volume_kwargs:
|
|
724
|
-
volume_client.
|
|
725
|
-
parsed_args.project,
|
|
616
|
+
volume_client.update_quota_class_set(
|
|
617
|
+
parsed_args.project or 'default',
|
|
726
618
|
**volume_kwargs,
|
|
727
619
|
)
|
|
728
620
|
if network_kwargs:
|
|
@@ -730,22 +622,22 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
730
622
|
"Network quotas are ignored since quota classes are not "
|
|
731
623
|
"supported."
|
|
732
624
|
)
|
|
733
|
-
else:
|
|
734
|
-
project = utils.find_resource(
|
|
735
|
-
identity_client.projects,
|
|
736
|
-
parsed_args.project,
|
|
737
|
-
).id
|
|
738
625
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
626
|
+
return
|
|
627
|
+
|
|
628
|
+
project_info = get_project(self.app, parsed_args.project)
|
|
629
|
+
project = project_info['id']
|
|
630
|
+
|
|
631
|
+
if compute_kwargs:
|
|
632
|
+
compute_client.update_quota_set(project, **compute_kwargs)
|
|
633
|
+
if volume_kwargs:
|
|
634
|
+
volume_client.update_quota_set(project, **volume_kwargs)
|
|
635
|
+
if (
|
|
636
|
+
network_kwargs
|
|
637
|
+
and self.app.client_manager.is_network_endpoint_enabled()
|
|
638
|
+
):
|
|
639
|
+
network_client = self.app.client_manager.network
|
|
640
|
+
network_client.update_quota(project, **network_kwargs)
|
|
749
641
|
|
|
750
642
|
|
|
751
643
|
class ShowQuota(command.Lister):
|
|
@@ -760,29 +652,14 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
760
652
|
parser = super().get_parser(prog_name)
|
|
761
653
|
parser.add_argument(
|
|
762
654
|
'project',
|
|
763
|
-
metavar='<project
|
|
655
|
+
metavar='<project>',
|
|
764
656
|
nargs='?',
|
|
765
657
|
help=_(
|
|
766
|
-
'Show quotas for this project
|
|
658
|
+
'Show quotas for this project (name or ID) '
|
|
767
659
|
'(defaults to current project)'
|
|
768
660
|
),
|
|
769
661
|
)
|
|
770
662
|
type_group = parser.add_mutually_exclusive_group()
|
|
771
|
-
# TODO(stephenfin): Remove in OSC 8.0
|
|
772
|
-
type_group.add_argument(
|
|
773
|
-
'--class',
|
|
774
|
-
dest='quota_class',
|
|
775
|
-
action='store_true',
|
|
776
|
-
default=False,
|
|
777
|
-
help=_(
|
|
778
|
-
'**Deprecated** Show quotas for <class>. '
|
|
779
|
-
'Deprecated as quota classes were never fully implemented '
|
|
780
|
-
'and only the default class is supported. '
|
|
781
|
-
'Use --default instead which is also supported by the network '
|
|
782
|
-
'service. '
|
|
783
|
-
'(compute and volume only)'
|
|
784
|
-
),
|
|
785
|
-
)
|
|
786
663
|
type_group.add_argument(
|
|
787
664
|
'--default',
|
|
788
665
|
dest='default',
|
|
@@ -834,20 +711,8 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
834
711
|
return parser
|
|
835
712
|
|
|
836
713
|
def take_action(self, parsed_args):
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
if parsed_args.quota_class:
|
|
840
|
-
msg = _(
|
|
841
|
-
"The '--class' option has been deprecated. Quota classes were "
|
|
842
|
-
"never fully implemented and the compute and volume services "
|
|
843
|
-
"only support a single 'default' quota class while the "
|
|
844
|
-
"network service does not support quota classes at all. "
|
|
845
|
-
"Please use 'openstack quota show --default' instead."
|
|
846
|
-
)
|
|
847
|
-
self.log.warning(msg)
|
|
848
|
-
else:
|
|
849
|
-
project_info = get_project(self.app, parsed_args.project)
|
|
850
|
-
project = project_info['id']
|
|
714
|
+
project_info = get_project(self.app, parsed_args.project)
|
|
715
|
+
project = project_info['id']
|
|
851
716
|
|
|
852
717
|
compute_quota_info = {}
|
|
853
718
|
volume_quota_info = {}
|
|
@@ -863,7 +728,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
863
728
|
self.app,
|
|
864
729
|
project,
|
|
865
730
|
detail=parsed_args.usage,
|
|
866
|
-
quota_class=parsed_args.quota_class,
|
|
867
731
|
default=parsed_args.default,
|
|
868
732
|
)
|
|
869
733
|
if parsed_args.service in {'all', 'volume'}:
|
|
@@ -871,7 +735,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
871
735
|
self.app,
|
|
872
736
|
project,
|
|
873
737
|
detail=parsed_args.usage,
|
|
874
|
-
quota_class=parsed_args.quota_class,
|
|
875
738
|
default=parsed_args.default,
|
|
876
739
|
)
|
|
877
740
|
if parsed_args.service in {'all', 'network'}:
|
|
@@ -879,7 +742,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
879
742
|
self.app,
|
|
880
743
|
project,
|
|
881
744
|
detail=parsed_args.usage,
|
|
882
|
-
quota_class=parsed_args.quota_class,
|
|
883
745
|
default=parsed_args.default,
|
|
884
746
|
)
|
|
885
747
|
|
|
@@ -907,14 +769,24 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
907
769
|
if 'id' in info:
|
|
908
770
|
del info['id']
|
|
909
771
|
|
|
910
|
-
# Remove the
|
|
911
|
-
|
|
912
|
-
|
|
772
|
+
# Remove the sdk-derived fields
|
|
773
|
+
for field in ('location', 'name', 'force'):
|
|
774
|
+
if field in info:
|
|
775
|
+
del info[field]
|
|
913
776
|
|
|
914
777
|
if not parsed_args.usage:
|
|
915
778
|
result = [{'resource': k, 'limit': v} for k, v in info.items()]
|
|
916
779
|
else:
|
|
917
|
-
result = [
|
|
780
|
+
result = [
|
|
781
|
+
{
|
|
782
|
+
'resource': k,
|
|
783
|
+
'limit': v or 0,
|
|
784
|
+
'in_use': info['usage'].get(k, 0),
|
|
785
|
+
'reserved': info['reservation'].get(k, 0),
|
|
786
|
+
}
|
|
787
|
+
for k, v in info.items()
|
|
788
|
+
if k not in ('usage', 'reservation')
|
|
789
|
+
]
|
|
918
790
|
|
|
919
791
|
columns = (
|
|
920
792
|
'resource',
|
|
@@ -992,21 +864,20 @@ class DeleteQuota(command.Command):
|
|
|
992
864
|
return parser
|
|
993
865
|
|
|
994
866
|
def take_action(self, parsed_args):
|
|
995
|
-
identity_client = self.app.client_manager.identity
|
|
996
|
-
project =
|
|
997
|
-
|
|
998
|
-
parsed_args.project,
|
|
867
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
868
|
+
project = identity_client.find_project(
|
|
869
|
+
parsed_args.project, ignore_missing=False
|
|
999
870
|
)
|
|
1000
871
|
|
|
1001
872
|
# compute quotas
|
|
1002
873
|
if parsed_args.service in {'all', 'compute'}:
|
|
1003
|
-
compute_client = self.app.client_manager.compute
|
|
1004
|
-
compute_client.
|
|
874
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
875
|
+
compute_client.revert_quota_set(project.id)
|
|
1005
876
|
|
|
1006
877
|
# volume quotas
|
|
1007
878
|
if parsed_args.service in {'all', 'volume'}:
|
|
1008
|
-
volume_client = self.app.client_manager.volume
|
|
1009
|
-
volume_client.
|
|
879
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
880
|
+
volume_client.revert_quota_set(project.id)
|
|
1010
881
|
|
|
1011
882
|
# network quotas (but only if we're not using nova-network, otherwise
|
|
1012
883
|
# we already deleted the quotas in the compute step)
|