summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/clientmanager.py16
-rw-r--r--openstackclient/common/utils.py14
-rw-r--r--openstackclient/compute/client.py7
-rw-r--r--openstackclient/identity/client.py6
-rw-r--r--openstackclient/image/v1/image.py18
-rw-r--r--openstackclient/shell.py63
-rw-r--r--openstackclient/tests/test_shell.py182
-rw-r--r--openstackclient/volume/client.py5
8 files changed, 288 insertions, 23 deletions
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index a0224064..b6dab253 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -42,16 +42,26 @@ class ClientManager(object):
"""Manages access to API clients, including authentication."""
identity = ClientCache(identity_client.make_client)
- def __init__(self, token=None, url=None, auth_url=None, project_name=None,
- project_id=None, username=None, password=None,
- region_name=None, verify=True, api_version=None):
+ def __init__(self, token=None, url=None, auth_url=None,
+ domain_id=None, domain_name=None,
+ project_name=None, project_id=None,
+ username=None, password=None,
+ user_domain_id=None, user_domain_name=None,
+ project_domain_id=None, project_domain_name=None,
+ region_name=None, api_version=None, verify=True):
self._token = token
self._url = url
self._auth_url = auth_url
+ self._domain_id = domain_id
+ self._domain_name = domain_name
self._project_name = project_name
self._project_id = project_id
self._username = username
self._password = password
+ self._user_domain_id = user_domain_id
+ self._user_domain_name = user_domain_name
+ self._project_domain_id = project_domain_id
+ self._project_domain_name = project_domain_name
self._region_name = region_name
self._api_version = api_version
self._service_catalog = None
diff --git a/openstackclient/common/utils.py b/openstackclient/common/utils.py
index 91a20895..94ea2225 100644
--- a/openstackclient/common/utils.py
+++ b/openstackclient/common/utils.py
@@ -15,6 +15,7 @@
"""Common client utilities"""
+import logging
import os
import six
import sys
@@ -215,3 +216,16 @@ def wait_for_status(status_f,
callback(progress)
time.sleep(sleep_time)
return retval
+
+
+def get_effective_log_level():
+ """Returns the lowest logging level considered by logging handlers
+
+ Retrieve an return the smallest log level set among the root
+ logger's handlers (in case of multiple handlers).
+ """
+ root_log = logging.getLogger()
+ min_log_lvl = logging.CRITICAL
+ for handler in root_log.handlers:
+ min_log_lvl = min(min_log_lvl, handler.level)
+ return min_log_lvl
diff --git a/openstackclient/compute/client.py b/openstackclient/compute/client.py
index 4ccb2f6d..765a48db 100644
--- a/openstackclient/compute/client.py
+++ b/openstackclient/compute/client.py
@@ -35,6 +35,10 @@ def make_client(instance):
instance._api_version[API_NAME],
API_VERSIONS)
LOG.debug('instantiating compute client: %s' % compute_client)
+
+ # Set client http_log_debug to True if verbosity level is high enough
+ http_log_debug = utils.get_effective_log_level() <= logging.DEBUG
+
client = compute_client(
username=instance._username,
api_key=instance._password,
@@ -49,7 +53,8 @@ def make_client(instance):
extensions=[],
service_type=API_NAME,
# FIXME(dhellmann): what is service_name?
- service_name='')
+ service_name='',
+ http_log_debug=http_log_debug)
# Populate the Nova client to skip another auth query to Identity
if instance._url:
diff --git a/openstackclient/identity/client.py b/openstackclient/identity/client.py
index 305d4cc4..b19388cc 100644
--- a/openstackclient/identity/client.py
+++ b/openstackclient/identity/client.py
@@ -46,6 +46,12 @@ def make_client(instance):
client = identity_client(
username=instance._username,
password=instance._password,
+ user_domain_id=instance._user_domain_id,
+ user_domain_name=instance._user_domain_name,
+ project_domain_id=instance._project_domain_id,
+ project_domain_name=instance._project_domain_name,
+ domain_id=instance._domain_id,
+ domain_name=instance._domain_name,
tenant_name=instance._project_name,
tenant_id=instance._project_id,
auth_url=instance._auth_url,
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index 05006d69..026b583c 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -48,9 +48,9 @@ class CreateImage(show.ShowOne):
help="Name of image",
)
parser.add_argument(
- "--disk_format",
+ "--disk-format",
default="raw",
- metavar="<disk_format>",
+ metavar="<disk-format>",
help="Disk format of image",
)
parser.add_argument(
@@ -66,7 +66,7 @@ class CreateImage(show.ShowOne):
parser.add_argument(
"--container-format",
default="bare",
- metavar="<container_format>",
+ metavar="<container-format>",
help="Container format of image",
)
parser.add_argument(
@@ -82,17 +82,17 @@ class CreateImage(show.ShowOne):
)
parser.add_argument(
"--min-disk",
- metavar="<disk_gb>",
+ metavar="<disk-gb>",
help="Minimum size of disk needed to boot image in gigabytes",
)
parser.add_argument(
"--min-ram",
- metavar="<disk_ram>",
+ metavar="<disk-ram>",
help="Minimum amount of ram needed to boot image in megabytes",
)
parser.add_argument(
"--location",
- metavar="<image_url>",
+ metavar="<image-url>",
help="URL where the data for this image already resides",
)
parser.add_argument(
@@ -107,7 +107,7 @@ class CreateImage(show.ShowOne):
)
parser.add_argument(
"--copy-from",
- metavar="<image_url>",
+ metavar="<image-url>",
help="Similar to --location, but this indicates that the image"
" should immediately be copied from the data store",
)
@@ -301,12 +301,12 @@ class SetImage(show.ShowOne):
)
parser.add_argument(
"--min-disk",
- metavar="<disk_gb>",
+ metavar="<disk-gb>",
help="Minimum size of disk needed to boot image in gigabytes",
)
parser.add_argument(
"--min-ram",
- metavar="<disk_ram>",
+ metavar="<disk-ram>",
help="Minimum amount of ram needed to boot image in megabytes",
)
parser.add_argument(
diff --git a/openstackclient/shell.py b/openstackclient/shell.py
index 73766a6e..76cc3c6a 100644
--- a/openstackclient/shell.py
+++ b/openstackclient/shell.py
@@ -144,10 +144,25 @@ class OpenStackShell(app.App):
default=env('OS_AUTH_URL'),
help='Authentication URL (Env: OS_AUTH_URL)')
parser.add_argument(
+ '--os-domain-name',
+ metavar='<auth-domain-name>',
+ default=env('OS_DOMAIN_NAME'),
+ help='Domain name of the requested domain-level'
+ 'authorization scope (Env: OS_DOMAIN_NAME)',
+ )
+ parser.add_argument(
+ '--os-domain-id',
+ metavar='<auth-domain-id>',
+ default=env('OS_DOMAIN_ID'),
+ help='Domain ID of the requested domain-level'
+ 'authorization scope (Env: OS_DOMAIN_ID)',
+ )
+ parser.add_argument(
'--os-project-name',
metavar='<auth-project-name>',
default=env('OS_PROJECT_NAME', default=env('OS_TENANT_NAME')),
- help='Authentication project name (Env: OS_PROJECT_NAME)',
+ help='Project name of the requested project-level'
+ 'authorization scope (Env: OS_PROJECT_NAME)',
)
parser.add_argument(
'--os-tenant-name',
@@ -159,7 +174,8 @@ class OpenStackShell(app.App):
'--os-project-id',
metavar='<auth-project-id>',
default=env('OS_PROJECT_ID', default=env('OS_TENANT_ID')),
- help='Authentication project ID (Env: OS_PROJECT_ID)',
+ help='Project ID of the requested project-level'
+ 'authorization scope (Env: OS_PROJECT_ID)',
)
parser.add_argument(
'--os-tenant-id',
@@ -178,6 +194,30 @@ class OpenStackShell(app.App):
default=utils.env('OS_PASSWORD'),
help='Authentication password (Env: OS_PASSWORD)')
parser.add_argument(
+ '--os-user-domain-name',
+ metavar='<auth-user-domain-name>',
+ default=utils.env('OS_USER_DOMAIN_NAME'),
+ help='Domain name of the user (Env: OS_USER_DOMAIN_NAME)')
+ parser.add_argument(
+ '--os-user-domain-id',
+ metavar='<auth-user-domain-id>',
+ default=utils.env('OS_USER_DOMAIN_ID'),
+ help='Domain ID of the user (Env: OS_USER_DOMAIN_ID)')
+ parser.add_argument(
+ '--os-project-domain-name',
+ metavar='<auth-project-domain-name>',
+ default=utils.env('OS_PROJECT_DOMAIN_NAME'),
+ help='Domain name of the project which is the requested '
+ 'project-level authorization scope '
+ '(Env: OS_PROJECT_DOMAIN_NAME)')
+ parser.add_argument(
+ '--os-project-domain-id',
+ metavar='<auth-project-domain-id>',
+ default=utils.env('OS_PROJECT_DOMAIN_ID'),
+ help='Domain ID of the project which is the requested '
+ 'project-level authorization scope '
+ '(Env: OS_PROJECT_DOMAIN_ID)')
+ parser.add_argument(
'--os-region-name',
metavar='<auth-region-name>',
default=env('OS_REGION_NAME'),
@@ -284,11 +324,16 @@ class OpenStackShell(app.App):
" either --os-password, or env[OS_PASSWORD], "
" or prompted response")
- if not (self.options.os_project_id
- or self.options.os_project_name):
+ if not ((self.options.os_project_id
+ or self.options.os_project_name) or
+ (self.options.os_domain_id
+ or self.options.os_domain_name)):
raise exc.CommandError(
- "You must provide a project id via"
- " either --os-project-id or via env[OS_PROJECT_ID]")
+ "You must provide authentication scope as a project "
+ "or a domain via --os-project-id or env[OS_PROJECT_ID], "
+ "--os-project-name or env[OS_PROJECT_NAME], "
+ "--os-domain-id or env[OS_DOMAIN_ID], or"
+ "--os-domain-name or env[OS_DOMAIN_NAME].")
if not self.options.os_auth_url:
raise exc.CommandError(
@@ -299,8 +344,14 @@ class OpenStackShell(app.App):
token=self.options.os_token,
url=self.options.os_url,
auth_url=self.options.os_auth_url,
+ domain_id=self.options.os_domain_id,
+ domain_name=self.options.os_domain_name,
project_name=self.options.os_project_name,
project_id=self.options.os_project_id,
+ user_domain_id=self.options.os_user_domain_id,
+ user_domain_name=self.options.os_user_domain_name,
+ project_domain_id=self.options.os_project_domain_id,
+ project_domain_name=self.options.os_project_domain_name,
username=self.options.os_username,
password=self.options.os_password,
region_name=self.options.os_region_name,
diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py
index be9c5d49..9253f701 100644
--- a/openstackclient/tests/test_shell.py
+++ b/openstackclient/tests/test_shell.py
@@ -20,13 +20,19 @@ from openstackclient import shell
from openstackclient.tests import utils
-DEFAULT_USERNAME = "username"
-DEFAULT_PASSWORD = "password"
+DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/"
DEFAULT_PROJECT_ID = "xxxx-yyyy-zzzz"
DEFAULT_PROJECT_NAME = "project"
-DEFAULT_TOKEN = "token"
+DEFAULT_DOMAIN_ID = "aaaa-bbbb-cccc"
+DEFAULT_DOMAIN_NAME = "domain"
+DEFAULT_USER_DOMAIN_ID = "aaaa-bbbb-cccc"
+DEFAULT_USER_DOMAIN_NAME = "domain"
+DEFAULT_PROJECT_DOMAIN_ID = "aaaa-bbbb-cccc"
+DEFAULT_PROJECT_DOMAIN_NAME = "domain"
+DEFAULT_USERNAME = "username"
+DEFAULT_PASSWORD = "password"
DEFAULT_REGION_NAME = "ZZ9_Plural_Z_Alpha"
-DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/"
+DEFAULT_TOKEN = "token"
DEFAULT_SERVICE_URL = "http://127.0.0.1:8771/v3.0/"
DEFAULT_COMPUTE_API_VERSION = "2"
@@ -78,6 +84,18 @@ class TestShell(utils.TestCase):
default_args["project_id"])
self.assertEqual(_shell.options.os_project_name,
default_args["project_name"])
+ self.assertEqual(_shell.options.os_domain_id,
+ default_args["domain_id"])
+ self.assertEqual(_shell.options.os_domain_name,
+ default_args["domain_name"])
+ self.assertEqual(_shell.options.os_user_domain_id,
+ default_args["user_domain_id"])
+ self.assertEqual(_shell.options.os_user_domain_name,
+ default_args["user_domain_name"])
+ self.assertEqual(_shell.options.os_project_domain_id,
+ default_args["project_domain_id"])
+ self.assertEqual(_shell.options.os_project_domain_name,
+ default_args["project_domain_name"])
self.assertEqual(_shell.options.os_username,
default_args["username"])
self.assertEqual(_shell.options.os_password,
@@ -151,6 +169,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": DEFAULT_AUTH_URL,
"project_id": "",
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": "",
"region_name": ""
@@ -163,6 +187,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": DEFAULT_PROJECT_ID,
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": "",
"region_name": ""
@@ -175,6 +205,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": "",
"project_name": DEFAULT_PROJECT_NAME,
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": "",
"region_name": ""
@@ -187,6 +223,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": DEFAULT_PROJECT_ID,
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": "",
"region_name": ""
@@ -199,6 +241,120 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": "",
"project_name": DEFAULT_PROJECT_NAME,
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_domain_id_flow(self):
+ flag = "--os-domain-id " + DEFAULT_DOMAIN_ID
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": DEFAULT_DOMAIN_ID,
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_domain_name_flow(self):
+ flag = "--os-domain-name " + DEFAULT_DOMAIN_NAME
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": DEFAULT_DOMAIN_NAME,
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_user_domain_id_flow(self):
+ flag = "--os-user-domain-id " + DEFAULT_USER_DOMAIN_ID
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": DEFAULT_USER_DOMAIN_ID,
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_user_domain_name_flow(self):
+ flag = "--os-user-domain-name " + DEFAULT_USER_DOMAIN_NAME
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": DEFAULT_USER_DOMAIN_NAME,
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_project_domain_id_flow(self):
+ flag = "--os-project-domain-id " + DEFAULT_PROJECT_DOMAIN_ID
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": DEFAULT_PROJECT_DOMAIN_ID,
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": ""
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_project_domain_name_flow(self):
+ flag = "--os-project-domain-name " + DEFAULT_PROJECT_DOMAIN_NAME
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": DEFAULT_PROJECT_DOMAIN_NAME,
"username": "",
"password": "",
"region_name": ""
@@ -211,6 +367,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": "",
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": DEFAULT_USERNAME,
"password": "",
"region_name": ""
@@ -223,6 +385,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": "",
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": DEFAULT_PASSWORD,
"region_name": ""
@@ -235,6 +403,12 @@ class TestShellPasswordAuth(TestShell):
"auth_url": "",
"project_id": "",
"project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
"username": "",
"password": "",
"region_name": DEFAULT_REGION_NAME
diff --git a/openstackclient/volume/client.py b/openstackclient/volume/client.py
index e04e8cd7..a53203f1 100644
--- a/openstackclient/volume/client.py
+++ b/openstackclient/volume/client.py
@@ -37,6 +37,10 @@ def make_client(instance):
)
LOG.debug('instantiating volume client')
+
+ # Set client http_log_debug to True if verbosity level is high enough
+ http_log_debug = utils.get_effective_log_level() <= logging.DEBUG
+
client = volume_client(
username=instance._username,
api_key=instance._password,
@@ -44,6 +48,7 @@ def make_client(instance):
auth_url=instance._auth_url,
cacert=instance._cacert,
insecure=instance._insecure,
+ http_log_debug=http_log_debug
)
return client