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
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,67 +555,75 @@ 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
|
+
|
|
672
568
|
compute_kwargs = {}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
if value is not None:
|
|
676
|
-
compute_kwargs[k] = value
|
|
569
|
+
volume_kwargs = {}
|
|
570
|
+
network_kwargs = {}
|
|
677
571
|
|
|
678
|
-
if
|
|
679
|
-
|
|
572
|
+
if self.app.client_manager.is_compute_endpoint_enabled():
|
|
573
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
680
574
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
if parsed_args.volume_type and k in IMPACT_VOLUME_TYPE_QUOTAS:
|
|
686
|
-
k = k + '_%s' % parsed_args.volume_type
|
|
687
|
-
volume_kwargs[k] = value
|
|
575
|
+
for k, v in COMPUTE_QUOTAS.items():
|
|
576
|
+
value = getattr(parsed_args, k, None)
|
|
577
|
+
if value is not None:
|
|
578
|
+
compute_kwargs[k] = value
|
|
688
579
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
self.log.warning(msg)
|
|
580
|
+
if compute_kwargs and parsed_args.force is True:
|
|
581
|
+
compute_kwargs['force'] = parsed_args.force
|
|
582
|
+
|
|
583
|
+
if self.app.client_manager.is_volume_endpoint_enabled():
|
|
584
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
585
|
+
|
|
586
|
+
for k, v in VOLUME_QUOTAS.items():
|
|
587
|
+
value = getattr(parsed_args, k, None)
|
|
588
|
+
if value is not None:
|
|
589
|
+
if (
|
|
590
|
+
parsed_args.volume_type
|
|
591
|
+
and k in IMPACT_VOLUME_TYPE_QUOTAS
|
|
592
|
+
):
|
|
593
|
+
k = k + '_%s' % parsed_args.volume_type
|
|
594
|
+
volume_kwargs[k] = value
|
|
705
595
|
|
|
706
596
|
if self.app.client_manager.is_network_endpoint_enabled():
|
|
597
|
+
network_client = self.app.client_manager.network
|
|
598
|
+
|
|
707
599
|
for k, v in NETWORK_QUOTAS.items():
|
|
708
600
|
value = getattr(parsed_args, k, None)
|
|
709
601
|
if value is not None:
|
|
710
602
|
network_kwargs[k] = value
|
|
711
|
-
|
|
603
|
+
elif self.app.client_manager.is_compute_endpoint_enabled():
|
|
712
604
|
for k, v in NOVA_NETWORK_QUOTAS.items():
|
|
713
605
|
value = getattr(parsed_args, k, None)
|
|
714
606
|
if value is not None:
|
|
715
607
|
compute_kwargs[k] = value
|
|
716
608
|
|
|
717
|
-
if
|
|
609
|
+
if network_kwargs:
|
|
610
|
+
if parsed_args.force is True:
|
|
611
|
+
# Unlike compute, network doesn't provide a simple boolean
|
|
612
|
+
# option. Instead, it provides two options: 'force' and
|
|
613
|
+
# 'check_limit' (a.k.a. 'not force')
|
|
614
|
+
network_kwargs['force'] = True
|
|
615
|
+
else:
|
|
616
|
+
network_kwargs['check_limit'] = True
|
|
617
|
+
|
|
618
|
+
if parsed_args.quota_class or parsed_args.default:
|
|
718
619
|
if compute_kwargs:
|
|
719
|
-
compute_client.
|
|
720
|
-
parsed_args.project,
|
|
620
|
+
compute_client.update_quota_class_set(
|
|
621
|
+
parsed_args.project or 'default',
|
|
721
622
|
**compute_kwargs,
|
|
722
623
|
)
|
|
723
624
|
if volume_kwargs:
|
|
724
|
-
volume_client.
|
|
725
|
-
parsed_args.project,
|
|
625
|
+
volume_client.update_quota_class_set(
|
|
626
|
+
parsed_args.project or 'default',
|
|
726
627
|
**volume_kwargs,
|
|
727
628
|
)
|
|
728
629
|
if network_kwargs:
|
|
@@ -730,22 +631,18 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|
|
730
631
|
"Network quotas are ignored since quota classes are not "
|
|
731
632
|
"supported."
|
|
732
633
|
)
|
|
733
|
-
else:
|
|
734
|
-
project = utils.find_resource(
|
|
735
|
-
identity_client.projects,
|
|
736
|
-
parsed_args.project,
|
|
737
|
-
).id
|
|
738
634
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
635
|
+
return
|
|
636
|
+
|
|
637
|
+
project_info = get_project(self.app, parsed_args.project)
|
|
638
|
+
project = project_info['id']
|
|
639
|
+
|
|
640
|
+
if compute_kwargs:
|
|
641
|
+
compute_client.update_quota_set(project, **compute_kwargs)
|
|
642
|
+
if volume_kwargs:
|
|
643
|
+
volume_client.update_quota_set(project, **volume_kwargs)
|
|
644
|
+
if network_kwargs:
|
|
645
|
+
network_client.update_quota(project, **network_kwargs)
|
|
749
646
|
|
|
750
647
|
|
|
751
648
|
class ShowQuota(command.Lister):
|
|
@@ -760,29 +657,14 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
760
657
|
parser = super().get_parser(prog_name)
|
|
761
658
|
parser.add_argument(
|
|
762
659
|
'project',
|
|
763
|
-
metavar='<project
|
|
660
|
+
metavar='<project>',
|
|
764
661
|
nargs='?',
|
|
765
662
|
help=_(
|
|
766
|
-
'Show quotas for this project
|
|
663
|
+
'Show quotas for this project (name or ID) '
|
|
767
664
|
'(defaults to current project)'
|
|
768
665
|
),
|
|
769
666
|
)
|
|
770
667
|
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
668
|
type_group.add_argument(
|
|
787
669
|
'--default',
|
|
788
670
|
dest='default',
|
|
@@ -834,20 +716,8 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
834
716
|
return parser
|
|
835
717
|
|
|
836
718
|
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']
|
|
719
|
+
project_info = get_project(self.app, parsed_args.project)
|
|
720
|
+
project = project_info['id']
|
|
851
721
|
|
|
852
722
|
compute_quota_info = {}
|
|
853
723
|
volume_quota_info = {}
|
|
@@ -863,7 +733,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
863
733
|
self.app,
|
|
864
734
|
project,
|
|
865
735
|
detail=parsed_args.usage,
|
|
866
|
-
quota_class=parsed_args.quota_class,
|
|
867
736
|
default=parsed_args.default,
|
|
868
737
|
)
|
|
869
738
|
if parsed_args.service in {'all', 'volume'}:
|
|
@@ -871,7 +740,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
871
740
|
self.app,
|
|
872
741
|
project,
|
|
873
742
|
detail=parsed_args.usage,
|
|
874
|
-
quota_class=parsed_args.quota_class,
|
|
875
743
|
default=parsed_args.default,
|
|
876
744
|
)
|
|
877
745
|
if parsed_args.service in {'all', 'network'}:
|
|
@@ -879,7 +747,6 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
879
747
|
self.app,
|
|
880
748
|
project,
|
|
881
749
|
detail=parsed_args.usage,
|
|
882
|
-
quota_class=parsed_args.quota_class,
|
|
883
750
|
default=parsed_args.default,
|
|
884
751
|
)
|
|
885
752
|
|
|
@@ -907,14 +774,24 @@ and ``server-group-members`` output for a given quota class."""
|
|
|
907
774
|
if 'id' in info:
|
|
908
775
|
del info['id']
|
|
909
776
|
|
|
910
|
-
# Remove the
|
|
911
|
-
|
|
912
|
-
|
|
777
|
+
# Remove the sdk-derived fields
|
|
778
|
+
for field in ('location', 'name', 'force'):
|
|
779
|
+
if field in info:
|
|
780
|
+
del info[field]
|
|
913
781
|
|
|
914
782
|
if not parsed_args.usage:
|
|
915
783
|
result = [{'resource': k, 'limit': v} for k, v in info.items()]
|
|
916
784
|
else:
|
|
917
|
-
result = [
|
|
785
|
+
result = [
|
|
786
|
+
{
|
|
787
|
+
'resource': k,
|
|
788
|
+
'limit': v or 0,
|
|
789
|
+
'in_use': info['usage'].get(k, 0),
|
|
790
|
+
'reserved': info['reservation'].get(k, 0),
|
|
791
|
+
}
|
|
792
|
+
for k, v in info.items()
|
|
793
|
+
if k not in ('usage', 'reservation')
|
|
794
|
+
]
|
|
918
795
|
|
|
919
796
|
columns = (
|
|
920
797
|
'resource',
|
|
@@ -992,21 +869,20 @@ class DeleteQuota(command.Command):
|
|
|
992
869
|
return parser
|
|
993
870
|
|
|
994
871
|
def take_action(self, parsed_args):
|
|
995
|
-
identity_client = self.app.client_manager.identity
|
|
996
|
-
project =
|
|
997
|
-
|
|
998
|
-
parsed_args.project,
|
|
872
|
+
identity_client = self.app.client_manager.sdk_connection.identity
|
|
873
|
+
project = identity_client.find_project(
|
|
874
|
+
parsed_args.project, ignore_missing=False
|
|
999
875
|
)
|
|
1000
876
|
|
|
1001
877
|
# compute quotas
|
|
1002
878
|
if parsed_args.service in {'all', 'compute'}:
|
|
1003
|
-
compute_client = self.app.client_manager.compute
|
|
1004
|
-
compute_client.
|
|
879
|
+
compute_client = self.app.client_manager.sdk_connection.compute
|
|
880
|
+
compute_client.revert_quota_set(project.id)
|
|
1005
881
|
|
|
1006
882
|
# volume quotas
|
|
1007
883
|
if parsed_args.service in {'all', 'volume'}:
|
|
1008
|
-
volume_client = self.app.client_manager.volume
|
|
1009
|
-
volume_client.
|
|
884
|
+
volume_client = self.app.client_manager.sdk_connection.volume
|
|
885
|
+
volume_client.revert_quota_set(project.id)
|
|
1010
886
|
|
|
1011
887
|
# network quotas (but only if we're not using nova-network, otherwise
|
|
1012
888
|
# we already deleted the quotas in the compute step)
|