summaryrefslogtreecommitdiff
path: root/openstackclient/common
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/common')
-rw-r--r--openstackclient/common/clientmanager.py19
-rw-r--r--openstackclient/common/extension.py29
-rw-r--r--openstackclient/common/quota.py226
3 files changed, 269 insertions, 5 deletions
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index 3e1a50e3..67912f0c 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -41,16 +41,19 @@ class ClientManager(clientmanager.ClientManager):
# A simple incrementing version for the plugin to know what is available
PLUGIN_INTERFACE_VERSION = "2"
+ # Let the commands set this
+ _auth_required = False
+
def __init__(
self,
cli_options=None,
api_version=None,
+ pw_func=None,
):
super(ClientManager, self).__init__(
cli_options=cli_options,
api_version=api_version,
- # TODO(dtroyer): Remove this when osc-lib 1.2 is released
- pw_func=shell.prompt_for_password,
+ pw_func=pw_func,
)
# TODO(dtroyer): For compatibility; mark this for removal when plugin
@@ -72,7 +75,10 @@ class ClientManager(clientmanager.ClientManager):
# because openstack_config is an optional argument to
# CloudConfig.__init__() and we'll die if it was not
# passed.
- if self._cli_options._openstack_config is not None:
+ if (
+ self._auth_required and
+ self._cli_options._openstack_config is not None
+ ):
self._cli_options._openstack_config._pw_callback = \
shell.prompt_for_password
try:
@@ -85,6 +91,13 @@ class ClientManager(clientmanager.ClientManager):
return super(ClientManager, self).setup_auth()
+ @property
+ def auth_ref(self):
+ if not self._auth_required:
+ return None
+ else:
+ return super(ClientManager, self).auth_ref
+
def _fallback_load_auth_plugin(self, e):
# NOTES(RuiChen): Hack to avoid auth plugins choking on data they don't
# expect, delete fake token and endpoint, then try to
diff --git a/openstackclient/common/extension.py b/openstackclient/common/extension.py
index 991f3afc..d5b72238 100644
--- a/openstackclient/common/extension.py
+++ b/openstackclient/common/extension.py
@@ -134,3 +134,32 @@ class ListExtension(command.Lister):
LOG.warning(message)
return (columns, extension_tuples)
+
+
+class ShowExtension(command.ShowOne):
+ _description = _("Show API extension")
+
+ def get_parser(self, prog_name):
+ parser = super(ShowExtension, self).get_parser(prog_name)
+ parser.add_argument(
+ 'extension',
+ metavar='<extension>',
+ help=_('Extension to display. '
+ 'Currently, only network extensions are supported. '
+ '(Name or Alias)'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ columns = ('Alias', 'Description', 'Links', 'Name',
+ 'Namespace', 'Updated')
+ ext = str(parsed_args.extension)
+ obj = client.find_extension(ext)
+ dict_tuples = (utils.get_item_properties(
+ obj,
+ columns,
+ formatters={},)
+ )
+
+ return columns, dict_tuples
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index 82fbf2bb..6ed9e370 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -16,6 +16,7 @@
"""Quota action implementations"""
import itertools
+import logging
import sys
from osc_lib.command import command
@@ -25,6 +26,8 @@ import six
from openstackclient.i18n import _
+LOG = logging.getLogger(__name__)
+
# List the quota items, map the internal argument name to the option
# name that the user sees.
@@ -78,6 +81,222 @@ NETWORK_QUOTAS = {
'l7policy': 'l7policies',
}
+NETWORK_KEYS = ['floating_ips', 'networks', 'rbac_policies', 'routers',
+ 'ports', 'security_group_rules', 'security_groups',
+ 'subnet_pools', 'subnets']
+
+
+def _xform_get_quota(data, value, keys):
+ res = []
+ res_info = {}
+ for key in keys:
+ res_info[key] = getattr(data, key, '')
+
+ res_info['id'] = value
+ res.append(res_info)
+ return res
+
+
+class ListQuota(command.Lister):
+ _description = _("List quotas for all projects "
+ "with non-default quota values")
+
+ def get_parser(self, prog_name):
+ parser = super(ListQuota, self).get_parser(prog_name)
+ option = parser.add_mutually_exclusive_group(required=True)
+ option.add_argument(
+ '--compute',
+ action='store_true',
+ default=False,
+ help=_('List compute quota'),
+ )
+ option.add_argument(
+ '--volume',
+ action='store_true',
+ default=False,
+ help=_('List volume quota'),
+ )
+ option.add_argument(
+ '--network',
+ action='store_true',
+ default=False,
+ help=_('List network quota'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ projects = self.app.client_manager.identity.projects.list()
+ result = []
+ project_ids = [getattr(p, 'id', '') for p in projects]
+
+ if parsed_args.compute:
+ compute_client = self.app.client_manager.compute
+ for p in project_ids:
+ try:
+ data = compute_client.quotas.get(p)
+ except Exception as ex:
+ if type(ex).__name__ == 'NotFound':
+ # Project not found, move on to next one
+ LOG.warning("Project %s not found: %s" % (p, ex))
+ continue
+ else:
+ raise
+
+ result_data = _xform_get_quota(
+ data,
+ p,
+ COMPUTE_QUOTAS.keys(),
+ )
+ default_data = compute_client.quotas.defaults(p)
+ result_default = _xform_get_quota(
+ default_data,
+ p,
+ COMPUTE_QUOTAS.keys(),
+ )
+ if result_default != result_data:
+ result += result_data
+
+ columns = (
+ 'id',
+ 'cores',
+ 'fixed_ips',
+ 'injected_files',
+ 'injected_file_content_bytes',
+ 'injected_file_path_bytes',
+ 'instances',
+ 'key_pairs',
+ 'metadata_items',
+ 'ram',
+ 'server_groups',
+ 'server_group_members',
+ )
+ column_headers = (
+ 'Project ID',
+ 'Cores',
+ 'Fixed IPs',
+ 'Injected Files',
+ 'Injected File Content Bytes',
+ 'Injected File Path Bytes',
+ 'Instances',
+ 'Key Pairs',
+ 'Metadata Items',
+ 'Ram',
+ 'Server Groups',
+ 'Server Group Members',
+ )
+ return (column_headers,
+ (utils.get_dict_properties(
+ s, columns,
+ ) for s in result))
+
+ if parsed_args.volume:
+ volume_client = self.app.client_manager.volume
+ for p in project_ids:
+ try:
+ data = volume_client.quotas.get(p)
+ except Exception as ex:
+ if type(ex).__name__ == 'NotFound':
+ # Project not found, move on to next one
+ LOG.warning("Project %s not found: %s" % (p, ex))
+ continue
+ else:
+ raise
+
+ result_data = _xform_get_quota(
+ data,
+ p,
+ VOLUME_QUOTAS.keys(),
+ )
+ default_data = volume_client.quotas.defaults(p)
+ result_default = _xform_get_quota(
+ default_data,
+ p,
+ VOLUME_QUOTAS.keys(),
+ )
+ if result_default != result_data:
+ result += result_data
+
+ columns = (
+ 'id',
+ 'backups',
+ 'backup_gigabytes',
+ 'gigabytes',
+ 'per_volume_gigabytes',
+ 'snapshots',
+ 'volumes',
+ )
+ column_headers = (
+ 'Project ID',
+ 'Backups',
+ 'Backup Gigabytes',
+ 'Gigabytes',
+ 'Per Volume Gigabytes',
+ 'Snapshots',
+ 'Volumes',
+ )
+ return (column_headers,
+ (utils.get_dict_properties(
+ s, columns,
+ ) for s in result))
+
+ if parsed_args.network:
+ client = self.app.client_manager.network
+ for p in project_ids:
+ try:
+ data = client.get_quota(p)
+ except Exception as ex:
+ if type(ex).__name__ == 'NotFound':
+ # Project not found, move on to next one
+ LOG.warning("Project %s not found: %s" % (p, ex))
+ continue
+ else:
+ raise
+
+ result_data = _xform_get_quota(
+ data,
+ p,
+ NETWORK_KEYS,
+ )
+ default_data = client.get_quota_default(p)
+ result_default = _xform_get_quota(
+ default_data,
+ p,
+ NETWORK_KEYS,
+ )
+ if result_default != result_data:
+ result += result_data
+
+ columns = (
+ 'id',
+ 'floating_ips',
+ 'networks',
+ 'ports',
+ 'rbac_policies',
+ 'routers',
+ 'security_groups',
+ 'security_group_rules',
+ 'subnets',
+ 'subnet_pools',
+ )
+ column_headers = (
+ 'Project ID',
+ 'Floating IPs',
+ 'Networks',
+ 'Ports',
+ 'RBAC Policies',
+ 'Routers',
+ 'Security Groups',
+ 'Security Group Rules',
+ 'Subnets',
+ 'Subnet Pools'
+ )
+ return (column_headers,
+ (utils.get_dict_properties(
+ s, columns,
+ ) for s in result))
+
+ return ((), ())
+
class SetQuota(command.Command):
_description = _("Set quotas for project or class")
@@ -126,7 +345,6 @@ class SetQuota(command.Command):
identity_client = self.app.client_manager.identity
compute_client = self.app.client_manager.compute
volume_client = self.app.client_manager.volume
- network_client = self.app.client_manager.network
compute_kwargs = {}
for k, v in COMPUTE_QUOTAS.items():
value = getattr(parsed_args, k, None)
@@ -179,7 +397,11 @@ class SetQuota(command.Command):
volume_client.quotas.update(
project,
**volume_kwargs)
- if network_kwargs:
+ if (
+ network_kwargs and
+ self.app.client_manager.is_network_endpoint_enabled()
+ ):
+ network_client = self.app.client_manager.network
network_client.update_quota(
project,
**network_kwargs)