diff --git a/README.rst b/README.rst index e08bc1ce8..84dc4e38c 100644 --- a/README.rst +++ b/README.rst @@ -15,8 +15,7 @@ This is a client for the OpenStack `Bare Metal API `_. It provides: * a Python API: the ``ironicclient`` module, and -* two command-line interfaces: ``openstack baremetal`` and ``ironic`` - (deprecated, please use ``openstack baremetal``). +* a command-line interfaces: ``openstack baremetal`` Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. @@ -83,47 +82,3 @@ For more information about the ``openstack baremetal`` command and the subcommands available, run:: $ openstack help baremetal - -``ironic`` CLI (deprecated) ---------------------------- - -This is deprecated and will be removed in the S* release. Please use the -``openstack baremetal`` CLI instead. - -This package will install the ``ironic`` command line interface that you -can use to interact with the ``ironic`` API. - -In order to use the ``ironic`` CLI you'll need to provide your OpenStack -tenant, username, password and authentication endpoint. You can do this with -the ``--os-tenant-name``, ``--os-username``, ``--os-password`` and -``--os-auth-url`` parameters, though it may be easier to set them -as environment variables:: - - $ export OS_PROJECT_NAME=project - $ export OS_USERNAME=user - $ export OS_PASSWORD=pass - $ export OS_AUTH_URL=http://auth.example.com:5000/v2.0 - -To use a specific Ironic API endpoint:: - - $ export IRONIC_URL=http://ironic.example.com:6385 - -An example of creating a basic node with the ``ipmi`` driver:: - - $ ironic node-create -d ipmi - -An example of creating a port on a node:: - - $ ironic port-create -a AA:BB:CC:DD:EE:FF -n nodeUUID - -An example of updating driver properties for a node:: - - $ ironic node-update nodeUUID add driver_info/ipmi_address= - $ ironic node-update nodeUUID add driver_info/ipmi_username= - $ ironic node-update nodeUUID add driver_info/ipmi_password= - - -For more information about the ``ironic`` command and the subcommands -available, run:: - - $ ironic help diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index b4f306fae..ac8ad0798 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -5,4 +5,3 @@ python-ironicclient User Documentation .. toctree:: osc_plugin_cli - ironic_client diff --git a/doc/source/cli/ironic_client.rst b/doc/source/cli/ironic_client.rst deleted file mode 100644 index 7ee6b5e54..000000000 --- a/doc/source/cli/ironic_client.rst +++ /dev/null @@ -1,100 +0,0 @@ -======================================= -``ironic`` Command-Line Interface (CLI) -======================================= - -.. program:: ironic -.. highlight:: bash - -SYNOPSIS -======== - -:program:`ironic` [options] [command-options] - -:program:`ironic help` - -:program:`ironic help` - - -DESCRIPTION -=========== - -.. WARNING:: - - The :program:`ironic` command-line interface is deprecated; no new features - will be added. This CLI will be removed in the S* release. The `openstack - baremetal `_ command-line interface should be used instead. - -The :program:`ironic` command-line interface (CLI) interacts with the -OpenStack Bare Metal Service (Ironic). - -In order to use the CLI, you must provide your OpenStack username, password, -project (historically called tenant), and auth endpoint. You can use -configuration options ``--os-username``, ``--os-password``, -``--os-tenant-id`` (or ``--os-tenant-name``), -and ``--os-auth-url``, or set the corresponding -environment variables:: - - $ export OS_USERNAME=user - $ export OS_PASSWORD=password - $ export OS_PROJECT_ID=b363706f891f48019483f8bd6503c54b # or OS_PROJECT_NAME - $ export OS_PROJECT_NAME=project # or OS_PROJECT_ID - $ export OS_AUTH_URL=http://auth.example.com:5000/v2.0 - -The command-line tool will attempt to reauthenticate using the provided -credentials for every request. You can override this behavior by manually -supplying an auth token using ``--ironic-url`` and -``--os-auth-token``, or by setting the corresponding environment -variables:: - - $ export IRONIC_URL=http://ironic.example.org:6385/ - $ export OS_AUTH_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155 - -Since Keystone can return multiple regions in the Service Catalog, you can -specify the one you want with ``--os-region-name`` or set the following -environment variable. (It defaults to the first in the list returned.) -:: - - export OS_REGION_NAME=region - -Ironic CLI supports bash completion. The command-line tool can automatically -fill partially typed commands. To use this feature, source the below file -(available at -https://opendev.org/openstack/python-ironicclient/src/branch/master/tools/ironic.bash_completion) -to your terminal and then bash completion should work:: - - $ . ironic.bash_completion - -To avoid doing this every time, add this to your ``.bashrc`` or copy the -ironic.bash_completion file to the default bash completion scripts directory -on your linux distribution. - -OPTIONS -======= - -To get a list of available (sub)commands and options, run:: - - $ ironic help - -To get usage and options of a command, run:: - - $ ironic help - - -EXAMPLES -======== - -Get information about the node-create command:: - - $ ironic help node-create - -Get a list of available drivers:: - - $ ironic driver-list - -Enroll a node with the ``ipmi`` driver, specifying the IPMI address:: - - $ ironic node-create -d ipmi -i ipmi_address=1.2.3.4 - -Get a list of nodes:: - - $ ironic node-list diff --git a/doc/source/index.rst b/doc/source/index.rst index cc14818ea..67dc6ee8a 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -5,8 +5,7 @@ Python Bindings to the OpenStack Ironic API This is a client for the OpenStack `Ironic`_ API. It provides: * a Python API: the ``ironicclient`` module, and -* two command-line interfaces: ``openstack baremetal`` and ``ironic`` - (deprecated, please use ``openstack baremetal`` instead). +* command-line interface: ``openstack baremetal`` Contents ======== diff --git a/doc/source/user/create_command.rst b/doc/source/user/create_command.rst index ed5fe3d33..5396dada4 100644 --- a/doc/source/user/create_command.rst +++ b/doc/source/user/create_command.rst @@ -3,7 +3,7 @@ Creating the Bare Metal service resources from file =================================================== It is possible to create a set of resources using their descriptions in JSON -or YAML format. It can be done in one of three ways: +or YAML format. It can be done in one of two ways: 1. Using OpenStackClient bare metal plugin CLI's command ``openstack baremetal create``:: @@ -17,25 +17,7 @@ or YAML format. It can be done in one of three ways: File (.yaml or .json) containing descriptions of the resources to create. Can be specified multiple times. -2. Using ironic CLI's ``ironic create`` command (deprecated, please use - ``openstack baremetal create`` instead):: - - $ ironic help create - The "ironic" CLI is deprecated and will be removed in the S* release. - Please use the "openstack baremetal" CLI instead. - usage: ironic create [ ...] - - Create baremetal resources (chassis, nodes, port groups and ports). The - resources may be described in one or more JSON or YAML files. If any file - cannot be validated, no resources are created. An attempt is made to - create all the resources; those that could not be created are skipped - (with a corresponding error message). - - Positional arguments: - File (.yaml or .json) containing descriptions of the resources - to create. Can be specified multiple times. - -3. Programmatically using the Python API: +2. Programmatically using the Python API: .. autofunction:: ironicclient.v1.create_resources.create_resources :noindex: diff --git a/ironicclient/common/cliutils.py b/ironicclient/common/cliutils.py deleted file mode 100644 index c5fb9cfaa..000000000 --- a/ironicclient/common/cliutils.py +++ /dev/null @@ -1,296 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# W0603: Using the global statement -# W0621: Redefining name %s from outer scope -# pylint: disable=W0603,W0621 - -from __future__ import print_function - -import getpass -import inspect -import json -import os -import sys -import textwrap - -from oslo_utils import encodeutils -from oslo_utils import strutils -import prettytable -import six -from six import moves - -from ironicclient.common.i18n import _ - - -class MissingArgs(Exception): - """Supplied arguments are not sufficient for calling a function.""" - def __init__(self, missing): - self.missing = missing - msg = _("Missing arguments: %s") % ", ".join(missing) - super(MissingArgs, self).__init__(msg) - - -def validate_args(fn, *args, **kwargs): - """Check that the supplied args are sufficient for calling a function. - - >>> validate_args(lambda a: None) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): a - >>> validate_args(lambda a, b, c, d: None, 0, c=1) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): b, d - - :param fn: the function to check - :param args: the positional arguments supplied - :param kwargs: the keyword arguments supplied - """ - argspec = inspect.getargspec(fn) - - num_defaults = len(argspec.defaults or []) - required_args = argspec.args[:len(argspec.args) - num_defaults] - - def isbound(method): - return getattr(method, '__self__', None) is not None - - if isbound(fn): - required_args.pop(0) - - missing = [arg for arg in required_args if arg not in kwargs] - missing = missing[len(args):] - if missing: - raise MissingArgs(missing) - - -def arg(*args, **kwargs): - """Decorator for CLI args. - - Example: - - >>> @arg("name", help="Name of the new entity") - ... def entity_create(args): - ... pass - """ - def _decorator(func): - add_arg(func, *args, **kwargs) - return func - return _decorator - - -def env(*args, **kwargs): - """Returns the first environment variable set. - - If all are empty, defaults to '' or keyword arg `default`. - """ - for arg in args: - value = os.environ.get(arg) - if value: - return value - return kwargs.get('default', '') - - -def add_arg(func, *args, **kwargs): - """Bind CLI arguments to a shell.py `do_foo` function.""" - - if not hasattr(func, 'arguments'): - func.arguments = [] - - # NOTE(sirp): avoid dups that can occur when the module is shared across - # tests. - if (args, kwargs) not in func.arguments: - # Because of the semantics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.arguments.insert(0, (args, kwargs)) - - -def unauthenticated(func): - """Adds 'unauthenticated' attribute to decorated function. - - Usage: - - >>> @unauthenticated - ... def mymethod(f): - ... pass - """ - func.unauthenticated = True - return func - - -def isunauthenticated(func): - """Checks if the function does not require authentication. - - Mark such functions with the `@unauthenticated` decorator. - - :returns: bool - """ - return getattr(func, 'unauthenticated', False) - - -def print_list(objs, fields, formatters=None, sortby_index=0, - mixed_case_fields=None, field_labels=None, json_flag=False): - """Print a list of objects or dict as a table, one row per object or dict. - - :param objs: iterable of :class:`Resource` - :param fields: attributes that correspond to columns, in order - :param formatters: `dict` of callables for field formatting - :param sortby_index: index of the field for sorting table rows - :param mixed_case_fields: fields corresponding to object attributes that - have mixed case names (e.g., 'serverId') - :param field_labels: Labels to use in the heading of the table, default to - fields. - :param json_flag: print the list as JSON instead of table - """ - def _get_name_and_data(field): - if field in formatters: - # The value of the field has to be modified. - # For example, it can be used to add extra fields. - return (field, formatters[field](o)) - - field_name = field.replace(' ', '_') - if field not in mixed_case_fields: - field_name = field.lower() - if isinstance(o, dict): - data = o.get(field_name, '') - else: - data = getattr(o, field_name, '') - return (field_name, data) - - formatters = formatters or {} - mixed_case_fields = mixed_case_fields or [] - field_labels = field_labels or fields - if len(field_labels) != len(fields): - raise ValueError(_("Field labels list %(labels)s has different number " - "of elements than fields list %(fields)s"), - {'labels': field_labels, 'fields': fields}) - - if sortby_index is None: - kwargs = {} - else: - kwargs = {'sortby': field_labels[sortby_index]} - pt = prettytable.PrettyTable(field_labels) - pt.align = 'l' - - json_array = [] - - for o in objs: - row = [] - for field in fields: - row.append(_get_name_and_data(field)) - if json_flag: - json_array.append(dict(row)) - else: - pt.add_row([r[1] for r in row]) - - if json_flag: - print(json.dumps(json_array, indent=4, separators=(',', ': '))) - elif six.PY3: - print(encodeutils.safe_encode(pt.get_string(**kwargs)).decode()) - else: - print(encodeutils.safe_encode(pt.get_string(**kwargs))) - - -def print_dict(dct, dict_property="Property", wrap=0, dict_value='Value', - json_flag=False): - """Print a `dict` as a table of two columns. - - :param dct: `dict` to print - :param dict_property: name of the first column - :param wrap: wrapping for the second column - :param dict_value: header label for the value (second) column - :param json_flag: print `dict` as JSON instead of table - """ - if json_flag: - print(json.dumps(dct, indent=4, separators=(',', ': '))) - return - pt = prettytable.PrettyTable([dict_property, dict_value]) - pt.align = 'l' - for k, v in sorted(dct.items()): - # convert dict to str to check length - if isinstance(v, dict): - v = six.text_type(v) - if wrap > 0: - v = textwrap.fill(six.text_type(v), wrap) - elif wrap < 0: - raise ValueError(_("wrap argument should be a non-negative " - "integer")) - # if value has a newline, add in multiple rows - # e.g. fault with stacktrace - if v and isinstance(v, six.string_types) and r'\n' in v: - lines = v.strip().split(r'\n') - col1 = k - for line in lines: - pt.add_row([col1, line]) - col1 = '' - else: - pt.add_row([k, v]) - - if six.PY3: - print(encodeutils.safe_encode(pt.get_string()).decode()) - else: - print(encodeutils.safe_encode(pt.get_string())) - - -def get_password(max_password_prompts=3): - """Read password from TTY.""" - verify = strutils.bool_from_string(env("OS_VERIFY_PASSWORD")) - pw = None - if hasattr(sys.stdin, "isatty") and sys.stdin.isatty(): - # Check for Ctrl-D - try: - for __ in moves.range(max_password_prompts): - pw1 = getpass.getpass("OS Password: ") - if verify: - pw2 = getpass.getpass("Please verify: ") - else: - pw2 = pw1 - if pw1 == pw2 and pw1: - pw = pw1 - break - except EOFError: - pass - return pw - - -def service_type(stype): - """Adds 'service_type' attribute to decorated function. - - Usage: - - .. code-block:: python - - @service_type('volume') - def mymethod(f): - ... - """ - def inner(f): - f.service_type = stype - return f - return inner - - -def get_service_type(f): - """Retrieves service type from function.""" - return getattr(f, 'service_type', None) - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def exit(msg=''): - if msg: - print(msg, file=sys.stderr) - sys.exit(1) diff --git a/ironicclient/shell.py b/ironicclient/shell.py deleted file mode 100644 index 03f813ac6..000000000 --- a/ironicclient/shell.py +++ /dev/null @@ -1,496 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Bare Metal Provisioning API. -""" - -from __future__ import print_function - -import argparse -import getpass -import logging -import os -import pkgutil -import re -import sys - -from keystoneauth1.loading import session as kasession -from oslo_utils import encodeutils -from oslo_utils import importutils -import six - -import ironicclient -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import http -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient import exc - - -LAST_KNOWN_API_VERSION = http.LAST_KNOWN_API_VERSION -LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION) - - -class IronicShell(object): - - def get_base_parser(self): - parser = argparse.ArgumentParser( - prog='ironic', - description=__doc__.strip(), - epilog=_('See "ironic help COMMAND" ' - 'for help on a specific command.'), - add_help=False, - formatter_class=HelpFormatter, - ) - - # Register global Keystone args first so their defaults are respected. - # See https://bugs.launchpad.net/python-ironicclient/+bug/1463581 - kasession.register_argparse_arguments(parser) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS, - ) - - parser.add_argument('--version', - action='version', - version=ironicclient.__version__) - - parser.add_argument('--debug', - default=bool(cliutils.env('IRONICCLIENT_DEBUG')), - action='store_true', - help=_('Defaults to env[IRONICCLIENT_DEBUG]')) - - parser.add_argument('--json', - default=False, - action='store_true', - help=_('Print JSON response without formatting.')) - - parser.add_argument('-v', '--verbose', - default=False, action="store_true", - help=_('Print more verbose output')) - - # for backward compatibility only - parser.add_argument('--cert-file', - dest='os_cert', - help=_('DEPRECATED! Use --os-cert.')) - - # for backward compatibility only - parser.add_argument('--key-file', - dest='os_key', - help=_('DEPRECATED! Use --os-key.')) - - # for backward compatibility only - parser.add_argument('--ca-file', - dest='os_cacert', - help=_('DEPRECATED! Use --os-cacert.')) - - parser.add_argument('--os-username', - dest='username', - default=cliutils.env('OS_USERNAME'), - help=_('Defaults to env[OS_USERNAME]')) - - parser.add_argument('--os_username', - dest='username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - dest='password', - default=cliutils.env('OS_PASSWORD'), - help=_('Defaults to env[OS_PASSWORD]')) - - parser.add_argument('--os_password', - dest='password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - dest='tenant_id', - default=cliutils.env('OS_TENANT_ID'), - help=_('Defaults to env[OS_TENANT_ID]')) - - parser.add_argument('--os_tenant_id', - dest='tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - dest='tenant_name', - default=cliutils.env('OS_TENANT_NAME'), - help=_('Defaults to env[OS_TENANT_NAME]')) - - parser.add_argument('--os_tenant_name', - dest='tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - dest='auth_url', - default=cliutils.env('OS_AUTH_URL'), - help=_('Defaults to env[OS_AUTH_URL]')) - - parser.add_argument('--os_auth_url', - dest='auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - dest='region_name', - default=cliutils.env('OS_REGION_NAME'), - help=_('Defaults to env[OS_REGION_NAME]')) - - parser.add_argument('--os_region_name', - dest='region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-token', - dest='token', - default=cliutils.env('OS_AUTH_TOKEN'), - help=_('Defaults to env[OS_AUTH_TOKEN]')) - - parser.add_argument('--os_auth_token', - dest='token', - help=argparse.SUPPRESS) - - parser.add_argument('--ironic-url', - dest='endpoint', - default=cliutils.env('IRONIC_URL'), - help=_('Defaults to env[IRONIC_URL]')) - - parser.add_argument('--ironic_url', - dest='endpoint', - help=argparse.SUPPRESS) - - parser.add_argument('--ironic-api-version', - default=cliutils.env('IRONIC_API_VERSION', - default="latest"), - help=_('Accepts 1.x (where "x" is microversion), ' - '1 or "latest". Defaults to ' - 'env[IRONIC_API_VERSION] or "latest".')) - - parser.add_argument('--ironic_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-service-type', - dest='service_type', - default=cliutils.env('OS_SERVICE_TYPE'), - help=_('Defaults to env[OS_SERVICE_TYPE] or ' - '"baremetal"')) - - parser.add_argument('--os_service_type', - dest='service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint', - dest='endpoint', - default=cliutils.env('OS_SERVICE_ENDPOINT'), - help=_('Specify an endpoint to use instead of ' - 'retrieving one from the service catalog ' - '(via authentication). ' - 'Defaults to env[OS_SERVICE_ENDPOINT].')) - - parser.add_argument('--os_endpoint', - dest='endpoint', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint-type', - dest='interface', - default=cliutils.env('OS_ENDPOINT_TYPE'), - help=_('Defaults to env[OS_ENDPOINT_TYPE] or ' - '"publicURL"')) - - parser.add_argument('--os_endpoint_type', - dest='interface', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-domain-id', - dest='user_domain_id', - default=cliutils.env('OS_USER_DOMAIN_ID'), - help=_('Defaults to env[OS_USER_DOMAIN_ID].')) - - parser.add_argument('--os-user-domain-name', - dest='user_domain_name', - default=cliutils.env('OS_USER_DOMAIN_NAME'), - help=_('Defaults to env[OS_USER_DOMAIN_NAME].')) - - parser.add_argument('--os-project-id', - dest='project_id', - default=cliutils.env('OS_PROJECT_ID'), - help=_('Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].')) - - parser.add_argument('--os-project-name', - dest='project_name', - default=cliutils.env('OS_PROJECT_NAME'), - help=_('Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].')) - - parser.add_argument('--os-project-domain-id', - dest='project_domain_id', - default=cliutils.env('OS_PROJECT_DOMAIN_ID'), - help=_('Defaults to env[OS_PROJECT_DOMAIN_ID].')) - - parser.add_argument('--os-project-domain-name', - dest='project_domain_name', - default=cliutils.env('OS_PROJECT_DOMAIN_NAME'), - help=_('Defaults to env[OS_PROJECT_DOMAIN_NAME].')) - - msg = _('Maximum number of retries in case of conflict error ' - '(HTTP 409). Defaults to env[IRONIC_MAX_RETRIES] or %d. ' - 'Use 0 to disable retrying.') % http.DEFAULT_MAX_RETRIES - parser.add_argument('--max-retries', type=int, help=msg, - default=cliutils.env( - 'IRONIC_MAX_RETRIES', - default=str(http.DEFAULT_MAX_RETRIES))) - - msg = _('Amount of time (in seconds) between retries ' - 'in case of conflict error (HTTP 409). ' - 'Defaults to env[IRONIC_RETRY_INTERVAL] ' - 'or %d.') % http.DEFAULT_RETRY_INTERVAL - parser.add_argument('--retry-interval', type=int, help=msg, - default=cliutils.env( - 'IRONIC_RETRY_INTERVAL', - default=str(http.DEFAULT_RETRY_INTERVAL))) - - return parser - - def get_available_major_versions(self): - matcher = re.compile(r"^v[0-9]+$") - submodules = pkgutil.iter_modules([os.path.dirname(__file__)]) - available_versions = [name[1:] for loader, name, ispkg in submodules - if matcher.search(name)] - - return available_versions - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='', - dest='subparser_name') - try: - submodule = importutils.import_versioned_module('ironicclient', - version, 'shell') - except ImportError as e: - msg = _("Invalid client version '%(version)s'. " - "Major part must be one of: '%(major)s'") % { - "version": version, - "major": ", ".join(self.get_available_major_versions())} - raise exceptions.UnsupportedVersion( - _('%(message)s, error was: %(error)s') % - {'message': msg, 'error': e}) - submodule.enhance_parser(parser, subparsers, self.subcommands) - utils.define_commands_from_module(subparsers, self, self.subcommands) - return parser - - def _setup_debugging(self, debug): - if debug: - logging.basicConfig( - format="%(levelname)s (%(module)s:%(lineno)d) %(message)s", - level=logging.DEBUG) - else: - logging.basicConfig( - format="%(levelname)s %(message)s", - level=logging.CRITICAL) - - def do_bash_completion(self): - """Prints all of the commands and options for bash-completion.""" - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in sc._optionals._option_string_actions.keys(): - options.add(option) - - commands.remove('bash-completion') - print(' '.join(commands | options)) - - def _check_version(self, api_version): - """Validate the supplied API (micro)version. - - :param api_version: API version as a string ("1", "1.x" or "latest") - :returns: tuple (major version, version string) - """ - if api_version in ('1', 'latest'): - return (1, LATEST_VERSION) - else: - try: - versions = tuple(int(i) for i in api_version.split('.')) - except ValueError: - versions = () - - if not versions or len(versions) > 2: - msg = _("The requested API version %(ver)s is an unexpected " - "format. Acceptable formats are 'X', 'X.Y', or the " - "literal string 'latest'." - ) % {'ver': api_version} - raise exc.CommandError(msg) - - if versions == (1, 0): - os_ironic_api_version = None - else: - os_ironic_api_version = api_version - - api_major_version = versions[0] - return (api_major_version, os_ironic_api_version) - - def main(self, argv): - # TODO(rloo): delete the ironic CLI in the S* cycle. - print('The "ironic" CLI is deprecated and will be removed in the ' - 'S* release. Please use the "openstack baremetal" CLI instead.', - file=sys.stderr) - # Parse args once to find version - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self._setup_debugging(options.debug) - - # build available subcommands based on version - (api_major_version, os_ironic_api_version) = ( - self._check_version(options.ironic_api_version)) - - subcommand_parser = self.get_subcommand_parser(api_major_version) - self.parser = subcommand_parser - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if options.help or not argv: - self.do_help(options) - return 0 - - # Parse args again and call whatever callback was selected - args = subcommand_parser.parse_args(argv) - - # Short-circuit and deal with these commands right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion() - return 0 - - # Assume password auth if it does not seem like none, admin_token or - # token auth - if not args.endpoint and not (args.token and args.auth_url): - if not args.username: - raise exc.CommandError(_("You must provide a username via " - "either --os-username or via " - "env[OS_USERNAME]")) - - if not args.password: - # No password, If we've got a tty, try prompting for it - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - args.password = getpass.getpass( - 'OpenStack Password: ') - except EOFError: - pass - # No password because we didn't have a tty or the - # user Ctl-D when prompted. - if not args.password: - raise exc.CommandError(_("You must provide a password via " - "either --os-password, " - "env[OS_PASSWORD], " - "or prompted response")) - - if not (args.tenant_id or args.tenant_name or - args.project_id or args.project_name): - raise exc.CommandError( - _("You must provide a project name or" - " project id via --os-project-name, --os-project-id," - " env[OS_PROJECT_ID] or env[OS_PROJECT_NAME].")) - - if not args.auth_url: - raise exc.CommandError(_("You must provide an auth url via " - "either --os-auth-url or via " - "env[OS_AUTH_URL]")) - - if args.max_retries < 0: - raise exc.CommandError(_("You must provide value >= 0 for " - "--max-retries")) - if args.retry_interval < 1: - raise exc.CommandError(_("You must provide value >= 1 for " - "--retry-interval")) - client_args = ( - 'token', 'endpoint', 'username', 'password', 'auth_url', - 'project_id', 'project_name', 'tenant_id', 'tenant_name', - 'region_name', 'user_domain_id', 'user_domain_name', - 'project_domain_id', 'project_domain_name', 'service_type', - 'interface', 'max_retries', 'retry_interval', 'timeout', 'insecure' - ) - kwargs = {} - for key in client_args: - value = getattr(args, key) - # NOTE(vdrok): check for both None and ''. If the default value - # for option is set using cliutils.env function, default empty - # value is ''. If the default is not set explicitly, it is None. - if value not in (None, ''): - kwargs[key] = value - # NOTE(vdrok): this is to workaround the fact that these options are - # named differently in keystoneauth, depending on whether they are - # provided through CLI or loaded from conf options, here we unify them. - for cli_ssl_opt, conf_ssl_opt in [ - ('os_cacert', 'cafile'), ('os_cert', 'certfile'), - ('os_key', 'keyfile')]: - value = getattr(args, cli_ssl_opt) - if value not in (None, ''): - kwargs[conf_ssl_opt] = value - kwargs['os_ironic_api_version'] = os_ironic_api_version - client = ironicclient.client.get_client(api_major_version, **kwargs) - if options.ironic_api_version in ('1', 'latest'): - # Allow negotiating a lower version, if the latest version - # supported by the client is higher than the latest version - # supported by the server. - client.http_client.api_version_select_state = 'default' - - try: - args.func(client, args) - except exc.Unauthorized: - raise exc.CommandError(_("Invalid OpenStack Identity credentials")) - except exc.CommandError as e: - subcommand_parser = self.subcommands[args.subparser_name] - subcommand_parser.error(e) - - @cliutils.arg('command', metavar='', nargs='?', - help=_('Display help for ')) - def do_help(self, args): - """Display help about this program or one of its subcommands.""" - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError(_("'%s' is not a valid subcommand") % - args.command) - else: - self.parser.print_help() - - -class HelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - super(HelpFormatter, self).start_section(heading.capitalize()) - - -def main(): - try: - IronicShell().main(sys.argv[1:]) - except KeyboardInterrupt: - print(_("... terminating ironic client"), file=sys.stderr) - return 130 - except Exception as e: - print(encodeutils.safe_encode(six.text_type(e)), file=sys.stderr) - return 1 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/ironicclient/tests/functional/test_chassis.py b/ironicclient/tests/functional/test_chassis.py deleted file mode 100644 index 67cab2677..000000000 --- a/ironicclient/tests/functional/test_chassis.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright (c) 2016 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from ironicclient.tests.functional import base - - -class ChassisSanityTestIronicClient(base.FunctionalTestBase): - """Sanity tests for testing actions with Chassis. - - Smoke test for the Ironic CLI commands which checks basic actions with - chassis command like create, show, update, delete etc. - """ - def setUp(self): - super(ChassisSanityTestIronicClient, self).setUp() - self.chassis = self.create_chassis() - - def test_chassis_create(self): - """Test steps: - - 1) create chassis - 2) check that chassis has been successfully created - """ - chassis_list_uuid = self.get_chassis_uuids_from_chassis_list() - self.assertIn(self.chassis['uuid'], chassis_list_uuid) - - def test_chassis_delete(self): - """Test steps: - - 1) create chassis - 2) check that chassis has been successfully created - 3) delete chassis - 4) check that chassis has been successfully deleted - """ - self.delete_chassis(self.chassis['uuid']) - chassis_list_uuid = self.get_chassis_uuids_from_chassis_list() - - self.assertNotIn(self.chassis['uuid'], chassis_list_uuid) - - def test_chassis_show(self): - """Test steps: - - 1) create chassis - 2) check that chassis-show returns the same chassis UUID - 3) chassis-create - """ - chassis_show = self.show_chassis(self.chassis['uuid']) - self.assertEqual(self.chassis['uuid'], chassis_show['uuid']) - - def test_chassis_show_field(self): - """Test steps: - - 1) create chassis - 2) show chassis with fields uuid - 3) check that fields is exist - """ - fields = ['uuid'] - chassis_show = self.show_chassis(self.chassis['uuid'], - params='--fields {0}' - .format(*fields)) - self.assertTableHeaders(fields, chassis_show.keys()) - - def test_chassis_update(self): - """Test steps: - - 1) create chassis - 2) update chassis - 3) check that chassis has been successfully updated - """ - updated_chassis = self.update_chassis( - self.chassis['uuid'], 'add', 'description=test-chassis') - self.assertEqual('test-chassis', updated_chassis['description']) - self.assertNotEqual(self.chassis['description'], - updated_chassis['description']) - - def test_chassis_node_list(self): - """Test steps: - - 1) create chassis in setUp() - 2) create 3 nodes - 3) update 2 nodes to be included in chassis - 4) check if 2 nodes are added to chassis - 5) check if 1 nodes isn't added to chassis - """ - node1 = self.create_node() - node2 = self.create_node() - - # This node is created to show that it won't be present - # in the chassis-node-list output - - node3 = self.create_node() - updated_node1 = self.update_node(node1['uuid'], - 'add chassis_uuid={0}' - .format(self.chassis['uuid'])) - updated_node2 = self.update_node(node2['uuid'], - 'add chassis_uuid={0}' - .format(self.chassis['uuid'])) - nodes = [updated_node1['uuid'], updated_node2['uuid']] - nodes.sort() - nodes_uuids = self.get_nodes_uuids_from_chassis_node_list( - self.chassis['uuid']) - nodes_uuids.sort() - self.assertEqual(nodes, nodes_uuids) - self.assertNotIn(node3['uuid'], nodes_uuids) - - -class ChassisNegativeTestsIronicClient(base.FunctionalTestBase): - """Negative tests for testing actions with Chassis. - - Negative tests for the Ironic CLI commands which checks actions with - chassis command like show, update, delete either using with arguments - or without arguments. - """ - - def test_chassis_delete_without_arguments(self): - """Test step: - - 1) check that chassis-delete command without arguments - triggers an exception - """ - ex_text = r'chassis-delete: error:' - - six.assertRaisesRegex(self, exceptions.CommandFailed, - ex_text, - self.delete_chassis, '') - - def test_chassis_delete_with_incorrect_chassis_uuid(self): - """Test step: - - 1) check that deleting non-exist chassis triggers an exception - triggers an exception - """ - uuid = data_utils.rand_uuid() - ex_text = (r"Chassis {0} " - r"could not be found. \(HTTP 404\)".format(uuid)) - - six.assertRaisesRegex(self, exceptions.CommandFailed, - ex_text, - self.delete_chassis, - '{0}'.format(uuid)) - - def test_chassis_show_without_arguments(self): - """Test step: - - 1) check that chassis-show command without arguments - triggers an exception - """ - ex_text = r'chassis-show: error:' - - six.assertRaisesRegex(self, exceptions.CommandFailed, - ex_text, - self.show_chassis, '') - - def test_chassis_show_with_incorrect_chassis_uuid(self): - """Test step: - - 1) check that chassis-show command with incorrect chassis - uuid triggers an exception - """ - uuid = data_utils.rand_uuid() - ex_text = (r"Chassis {0} " - r"could not be found. \(HTTP 404\)".format(uuid)) - - six.assertRaisesRegex(self, exceptions.CommandFailed, - ex_text, - self.show_chassis, - '{0}'.format(uuid)) - - def test_chassis_update_without_arguments(self): - """Test steps: - - 1) create chassis - 2) check that chassis-update command without arguments - triggers an exception - """ - ex_text = r'chassis-update: error:' - - six.assertRaisesRegex(self, exceptions.CommandFailed, - ex_text, - self.update_chassis, - chassis_id='', - operation='') - - def test_chassis_update_with_incorrect_chassis_uuid(self): - """Test steps: - - 1) create chassis - 2) check that chassis-update command with incorrect arguments - triggers an exception - """ - uuid = data_utils.rand_uuid() - ex_text = r'chassis-update: error:' - - six.assertRaisesRegex(self, - exceptions.CommandFailed, - ex_text, - self.update_chassis, - chassis_id='{0}'.format(uuid), - operation='') diff --git a/ironicclient/tests/functional/test_chassis_create.py b/ironicclient/tests/functional/test_chassis_create.py deleted file mode 100644 index 9ac70394e..000000000 --- a/ironicclient/tests/functional/test_chassis_create.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (c) 2016 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from ironicclient.tests.functional import base - - -class NegativeChassisCreateTestsIronicClient(base.FunctionalTestBase): - """Negative tests for testing chassis-create command. - - Negative tests for the Ironic CLI commands which check actions with - chassis-create command like create chassis without arguments or with - incorrect arguments and check that correct error message raised. - """ - - error_msg = r'ironic chassis-create: error:' - expected_msg = r'expected one argument' - - def test_description_no_value(self): - """Test steps: - - 1) create chassis using -d argument without the value - 2) create chassis using --description argument without the value - 3) check that command using -d argument triggers an exception - 4) check that command with --description arg triggers an exception - """ - ex_text = (r'{0} argument -d/--description: {1}' - .format(self.error_msg, self.expected_msg)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '-d') - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '--description') - - def test_metadata_extra_no_value(self): - """Test steps: - - 1) create chassis using -e argument without the value - 2) create chassis using --extra argument without the value - 3) check that command using -e argument triggers an exception - 4) check that command with --extra argument triggers an exception - """ - ex_text = (r'{0} argument -e/--extra: {1}' - .format(self.error_msg, self.expected_msg)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '-e') - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '--extra') - - def test_specific_uuid_no_value(self): - """Test steps: - - 1) create chassis using -u argument without the value - 2) create chassis using --uuid argument without the value - 3) check that command using -u argument triggers an exception - 4) check that command with --uuid argument triggers an exception - """ - ex_text = (r'{0} argument -u/--uuid: {1}' - .format(self.error_msg, self.expected_msg)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '-u') - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, '--uuid') - - def test_invalid_description(self): - """Test steps: - - 1) create chassis with invalid description using -d argument - 2) create chassis with invalid description using --description arg - 3) check that command using -d argument triggers an exception - 4) check that command using --uuid argument triggers an exception - """ - description = '--' - ex_text = (r'{0} argument -d/--description: {1}' - .format(self.error_msg, self.expected_msg)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='-d {0}'.format(description)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='--description {0}'.format(description)) - - def test_invalid_metadata_extra(self): - """Test steps: - - 1) create chassis with invalid metadata using -e argument - 2) create chassis with invalid metadata using --extra argument - 3) check that command using -e argument triggers an exception - 4) check that command using --extra argument triggers an exception - """ - extra = "HelloWorld" - ex_text = (r'{0} Attributes must be a list of PATH=VALUE' - .format(self.error_msg)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='-e {0}'.format(extra)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='--extra {0}'.format(extra)) - - def test_invalid_specific_uuid(self): - """Test steps: - - 1) create chassis with invalid specific uuid using -u argument - 2) create chassis with invalid specific uuid using --uuid argument - 3) check that command using -u argument triggers an exception - 4) check that command using --uuid argument triggers an exception - """ - invalid_uuid = data_utils.rand_uuid()[:-1] - ex_text = r'Expected a UUID but received {0}'.format(invalid_uuid) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='-u {0}'.format(invalid_uuid)) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.create_chassis, - params='--uuid {0}'.format(invalid_uuid)) diff --git a/ironicclient/tests/functional/test_driver.py b/ironicclient/tests/functional/test_driver.py deleted file mode 100644 index 7d9ad66a6..000000000 --- a/ironicclient/tests/functional/test_driver.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class DriverSanityTestIronicClient(base.FunctionalTestBase): - """Sanity tests for testing actions with driver. - - Smoke test for the Ironic CLI commands which checks basic actions with - driver command like driver-show, driver-properties. - """ - - def test_driver_show(self): - """Test steps: - - 1) get drivers names - 2) check that each driver exists in driver-show output - """ - drivers_names = self.get_drivers_names() - for driver in drivers_names: - driver_show = self.show_driver(driver) - self.assertEqual(driver, driver_show['name']) - - def test_driver_properties(self): - """Test steps: - - 1) get drivers names - 2) check that each driver has some properties - """ - drivers_names = self.get_drivers_names() - for driver in drivers_names: - driver_properties = self.properties_driver(driver) - self.assertNotEqual([], [x['Property'] for x in driver_properties]) - - def test_driver_list(self): - """Test steps: - - 1) get list of drivers - 2) check that list of drivers is not empty - """ - driver = 'fake-hardware' - available_drivers = self.get_drivers_names() - self.assertGreater(len(available_drivers), 0) - self.assertIn(driver, available_drivers) diff --git a/ironicclient/tests/functional/test_help_msg.py b/ironicclient/tests/functional/test_help_msg.py deleted file mode 100644 index 39bde4193..000000000 --- a/ironicclient/tests/functional/test_help_msg.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class IronicClientHelp(base.FunctionalTestBase): - """Test for python-ironicclient help messages.""" - - def test_ironic_help(self): - """Check Ironic client main help message contents.""" - caption = ("Command-line interface to the " - "OpenStack Bare Metal Provisioning API.") - subcommands = { - 'bash-completion', - 'chassis-create', - 'chassis-delete', - 'chassis-list', - 'chassis-node-list', - 'chassis-show', - 'chassis-update', - 'driver-list', - 'driver-properties', - 'driver-show', - 'driver-vendor-passthru', - 'help', - 'node-create', - 'node-delete', - 'node-get-boot-device', - 'node-get-console', - 'node-get-supported-boot-devices', - 'node-list', - 'node-port-list', - 'node-set-boot-device', - 'node-set-console-mode', - 'node-set-maintenance', - 'node-set-power-state', - 'node-set-provision-state', - 'node-show', - 'node-show-states', - 'node-update', - 'node-validate', - 'node-vendor-passthru', - 'node-vif-attach', - 'node-vif-detach', - 'node-vif-list', - 'port-create', - 'port-delete', - 'port-list', - 'port-show', - 'port-update' - } - - output = self._ironic('help', flags='', params='') - - self.assertIn(caption, output) - for string in subcommands: - self.assertIn(string, output) diff --git a/ironicclient/tests/functional/test_json_response.py b/ironicclient/tests/functional/test_json_response.py deleted file mode 100644 index 358826862..000000000 --- a/ironicclient/tests/functional/test_json_response.py +++ /dev/null @@ -1,289 +0,0 @@ -# Copyright (c) 2016 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -import jsonschema -from tempest.lib.common.utils import data_utils - -from ironicclient.tests.functional import base - - -def _validate_json(json_response, schema): - """Verify JSON is valid. - - :param json_response: JSON response from CLI - :type json_response: string - :param schema: expected schema of response - :type json_response: dictionary - """ - json_response = json.loads(json_response) - jsonschema.validate(json_response, schema) - - -class TestNodeJsonResponse(base.FunctionalTestBase): - """Test JSON responses for node commands.""" - - node_schema = { - "type": "object", - "properties": { - "target_power_state": {"type": ["string", "null"]}, - "extra": {"type": "object"}, - "last_error": {"type": ["string", "null"]}, - "updated_at": {"type": ["string", "null"]}, - "maintenance_reason": {"type": ["string", "null"]}, - "provision_state": {"type": "string"}, - "clean_step": {"type": "object"}, - "deploy_step": {"type": "object"}, - "uuid": {"type": "string"}, - "console_enabled": {"type": "boolean"}, - "target_provision_state": {"type": ["string", "null"]}, - "raid_config": {"type": "object"}, - "provision_updated_at": {"type": ["string", "null"]}, - "maintenance": {"type": "boolean"}, - "target_raid_config": {"type": "object"}, - "inspection_started_at": {"type": ["string", "null"]}, - "inspection_finished_at": {"type": ["string", "null"]}, - "power_state": {"type": ["string", "null"]}, - "driver": {"type": "string"}, - "reservation": {"type": ["string", "null"]}, - "properties": {"type": "object"}, - "instance_uuid": {"type": ["string", "null"]}, - "name": {"type": ["string", "null"]}, - "driver_info": {"type": "object"}, - "created_at": {"type": "string"}, - "driver_internal_info": {"type": "object"}, - "chassis_uuid": {"type": ["string", "null"]}, - "instance_info": {"type": "object"} - }, - "patternProperties": { - ".*_interface$": {"type": ["string", "null"]} - }, - "additionalProperties": True - } - - def setUp(self): - super(TestNodeJsonResponse, self).setUp() - self.node = self.create_node() - - def test_node_list_json(self): - """Test JSON response for nodes list.""" - schema = { - "type": "array", - "items": { - "type": "object", - "properties": { - "instance_uuid": {"type": ["string", "null"]}, - "maintenance": {"type": "boolean"}, - "name": {"type": ["string", "null"]}, - "power_state": {"type": ["string", "null"]}, - "provision_state": {"type": "string"}, - "uuid": {"type": "string"}}} - } - response = self.ironic('node-list', flags='--json', - params='', parse=False) - _validate_json(response, schema) - - def test_node_show_json(self): - """Test JSON response for node show.""" - response = self.ironic('node-show', flags='--json', params='{0}' - .format(self.node['uuid']), parse=False) - _validate_json(response, self.node_schema) - - def test_node_validate_json(self): - """Test JSON response for node validation.""" - schema = { - "type": "array", - "items": { - "type": "object", - "properties": { - "interface": {"type": ["string", "null"]}, - "result": {"type": ["boolean", "null"]}, - "reason": {"type": ["string", "null"]}}} - } - response = self.ironic('node-validate', flags='--json', - params='{0}'.format(self.node['uuid']), - parse=False) - _validate_json(response, schema) - - def test_node_show_states_json(self): - """Test JSON response for node show states.""" - schema = { - "type": "object", - "properties": { - "target_power_state": {"type": ["string", "null"]}, - "target_provision_state": {"type": ["string", "null"]}, - "last_error": {"type": ["string", "null"]}, - "console_enabled": {"type": "boolean"}, - "provision_updated_at": {"type": ["string", "null"]}, - "power_state": {"type": ["string", "null"]}, - "provision_state": {"type": "string"} - } - } - response = self.ironic('node-show-states', flags='--json', - params='{0}'.format(self.node['uuid']), - parse=False) - _validate_json(response, schema) - - def test_node_create_json(self): - """Test JSON response for node creation.""" - schema = { - "type": "object", - "properties": { - "uuid": {"type": "string"}, - "driver_info": {"type": "object"}, - "extra": {"type": "object"}, - "driver": {"type": "string"}, - "chassis_uuid": {"type": ["string", "null"]}, - "properties": {"type": "object"}, - "name": {"type": ["string", "null"]}, - } - } - node_name = 'nodejson' - response = self.ironic( - 'node-create', flags='--json', - params='-d fake-hardware -n {0}'.format(node_name), - parse=False) - self.addCleanup(self.delete_node, node_name) - _validate_json(response, schema) - - def test_node_update_json(self): - """Test JSON response for node update.""" - node_name = data_utils.rand_name('test') - response = self.ironic('node-update', flags='--json', - params='{0} add name={1}' - .format(self.node['uuid'], node_name), - parse=False) - _validate_json(response, self.node_schema) - - -class TestDriverJsonResponse(base.FunctionalTestBase): - """Test JSON responses for driver commands.""" - - def test_driver_list_json(self): - """Test JSON response for drivers list.""" - schema = { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "hosts": {"type": "string"}, - }} - } - response = self.ironic('driver-list', flags='--json', parse=False) - _validate_json(response, schema) - - def test_driver_show_json(self): - """Test JSON response for driver show.""" - schema = { - "type": "object", - "properties": { - "name": {"type": "string"}, - "hosts": { - "type": "array", - "items": {"type": "string"}} - } - } - drivers_names = self.get_drivers_names() - for driver in drivers_names: - response = self.ironic('driver-show', flags='--json', - params='{0}'.format(driver), parse=False) - _validate_json(response, schema) - - def test_driver_properties_json(self): - """Test JSON response for driver properties.""" - schema = { - "type": "object", - "additionalProperties": {"type": "string"} - } - drivers_names = self.get_drivers_names() - for driver in drivers_names: - response = self.ironic('driver-properties', flags='--json', - params='{0}'.format(driver), parse=False) - _validate_json(response, schema) - - -class TestChassisJsonResponse(base.FunctionalTestBase): - """Test JSON responses for chassis commands.""" - - chassis_schema = { - "type": "object", - "properties": { - "uuid": {"type": "string"}, - "updated_at": {"type": ["string", "null"]}, - "created_at": {"type": "string"}, - "description": {"type": ["string", "null"]}, - "extra": {"type": "object"}} - } - - def setUp(self): - super(TestChassisJsonResponse, self).setUp() - self.chassis = self.create_chassis() - - def test_chassis_list_json(self): - """Test JSON response for chassis list.""" - schema = { - "type": "array", - "items": { - "type": "object", - "properties": { - "uuid": {"type": "string"}, - "description": {"type": ["string", "null"]}} - } - } - response = self.ironic('chassis-list', flags='--json', parse=False) - _validate_json(response, schema) - - def test_chassis_show_json(self): - """Test JSON response for chassis show.""" - response = self.ironic('chassis-show', flags='--json', - params='{0}'.format(self.chassis['uuid']), - parse=False) - _validate_json(response, self.chassis_schema) - - def test_chassis_create_json(self): - """Test JSON response for chassis create.""" - response = self.ironic('chassis-create', flags='--json', parse=False) - _validate_json(response, self.chassis_schema) - - def test_chassis_update_json(self): - """Test JSON response for chassis update.""" - response = self.ironic( - 'chassis-update', flags='--json', params='{0} {1} {2}'.format( - self.chassis['uuid'], 'add', 'description=test-chassis'), - parse=False) - _validate_json(response, self.chassis_schema) - - def test_chassis_node_list_json(self): - """Test JSON response for chassis-node-list command.""" - schema = { - "type": "array", - "items": { - "type": "object", - "properties": { - "instance_uuid": {"type": ["string", "null"]}, - "maintenance": {"type": "boolean"}, - "name": {"type": ["string", "null"]}, - "power_state": {"type": ["string", "null"]}, - "provision_state": {"type": "string"}, - "uuid": {"type": "string"}}} - } - self.node = self.create_node() - self.update_node(self.node['uuid'], 'add chassis_uuid={0}' - .format(self.chassis['uuid'])) - response = self.ironic('chassis-node-list', flags='--json', - params='{0}'.format(self.chassis['uuid']), - parse=False) - _validate_json(response, schema) diff --git a/ironicclient/tests/functional/test_node.py b/ironicclient/tests/functional/test_node.py deleted file mode 100644 index 546622552..000000000 --- a/ironicclient/tests/functional/test_node.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib.common.utils import data_utils - -from ironicclient.tests.functional import base -import ironicclient.tests.functional.utils as utils - - -class NodeSanityTestIronicClient(base.FunctionalTestBase): - """Sanity tests for testing actions with Node. - - Smoke test for the Ironic CLI commands which checks basic actions with - node command like create, delete etc. - """ - - def setUp(self): - super(NodeSanityTestIronicClient, self).setUp() - self.node = self.create_node() - - def test_node_create(self): - """Test steps: - - 1) create node - 2) check that node has been successfully created - """ - self.assertIn(self.node['uuid'], self.get_nodes_uuids_from_node_list()) - - def test_node_show(self): - """Test steps: - - 1) create node - 2) check that created node UUID equals to the one present - in node-show output - """ - node_show = self.show_node(self.node['uuid']) - self.assertEqual(self.node['uuid'], node_show['uuid']) - - def test_node_show_field(self): - """Test steps: - - 1) create node - 2) show node with fields instance_uuid, driver, name, uuid - 3) check that only fields instance_uuid, driver, name, - uuid are the output fields - """ - fields = ['instance_uuid', 'driver', 'name', 'uuid'] - node_show = self.show_node(self.node['uuid'], - params='--fields %s' % ' '.join(fields)) - self.assertTableHeaders(fields, node_show.keys()) - - def test_node_delete(self): - """Test steps: - - 1) create node - 2) check that it was created - 3) delete node - 4) check that node has been successfully deleted - """ - self.assertIn(self.node['uuid'], self.get_nodes_uuids_from_node_list()) - self.delete_node(self.node['uuid']) - self.assertNotIn(self.node['uuid'], - self.get_nodes_uuids_from_node_list()) - - def test_node_update(self): - """Test steps: - - 1) create node - 2) update node name - 3) check that node name has been successfully updated - """ - node_name = data_utils.rand_name(prefix='test') - updated_node = self.update_node(self.node['uuid'], - 'add name={0}'.format(node_name)) - self.assertEqual(node_name, updated_node['name']) - - def test_node_set_console_mode(self): - """Test steps: - - 1) create node - 2) check that console_enabled is False - 3) set node console mode to True - 4) check that node console mode has been successfully updated - """ - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('False', node_show['console_enabled']) - - self.ironic('node-set-console-mode', - params='{0} true'.format(self.node['uuid'])) - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('True', node_show['console_enabled']) - - def test_node_get_console(self): - """Test steps: - - 1) create node - 2) check console mode using node-show - 3) get console mode using node-get-console - 4) check that node-get-console value equals node-show value - """ - node_show = self.show_node(self.node['uuid']) - node_get = self.ironic('node-get-console', params=self.node['uuid']) - node_get = utils.get_dict_from_output(node_get) - - self.assertEqual(node_show['console_enabled'], - node_get['console_enabled']) - - def test_node_set_maintenance(self): - """Test steps: - - 1) create node - 2) check that maintenance is False - 3) put node to maintenance - 4) check that node is in maintenance - 5) check that maintenance reason has been successfully updated - """ - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('False', node_show['maintenance']) - - self.set_node_maintenance( - self.node['uuid'], - "true --reason 'Testing node-set power state command'") - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('True', node_show['maintenance']) - self.assertEqual('Testing node-set power state command', - node_show['maintenance_reason']) - - def test_node_set_power_state(self): - """Test steps: - - 1) create node - 2) check that power state is None - 3) set power state to 'off' - 4) check that power state has been changed successfully - """ - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('None', node_show['power_state']) - - self.set_node_power_state(self.node['uuid'], "off") - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('power off', node_show['power_state']) - - def test_node_set_provision_state(self): - """Test steps: - - 1) create node - 2) check that provision state is 'enroll' - 3) set new provision state to the node - 4) check that provision state has been updated successfully - """ - node_show = self.show_node(self.node['uuid']) - - self.assertEqual('enroll', node_show['provision_state']) - - for verb, target in [('manage', 'manageable'), - ('provide', 'available'), - ('active', 'active'), - ('deleted', 'available')]: - self.set_node_provision_state(self.node['uuid'], verb) - node_show = self.show_node(self.node['uuid']) - self.assertEqual(target, node_show['provision_state']) - - def test_node_validate(self): - """Test steps: - - 1) create node - 2) validate node - """ - node_validate = self.validate_node(self.node['uuid']) - self.assertNodeValidate(node_validate) - - def test_show_node_states(self): - """Test steps: - - 1) create node - 2) check that states returned by node-show and node-show-states - are the same - """ - node_show = self.show_node(self.node['uuid']) - show_node_states = self.show_node_states(self.node['uuid']) - self.assertNodeStates(node_show, show_node_states) - - def test_node_list(self): - """Test steps: - - 1) create node in setup and one more node explicitly - 2) check that both nodes are in list - """ - other_node = self.create_node() - node_list = self.list_nodes() - uuids = [x['UUID'] for x in node_list] - names = [x['Name'] for x in node_list] - self.assertIn(self.node['uuid'], uuids) - self.assertIn(other_node['uuid'], uuids) - self.assertIn(self.node['name'], names) - self.assertIn(other_node['name'], names) diff --git a/ironicclient/tests/functional/test_node_set_power_state.py b/ironicclient/tests/functional/test_node_set_power_state.py deleted file mode 100644 index 634548fa3..000000000 --- a/ironicclient/tests/functional/test_node_set_power_state.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class NodeSetPowerStateTestIronicClient(base.FunctionalTestBase): - """Tests for testing node-set-power-state command. - - Tests for the Ironic CLI node-set-power-state command that checks that - node can be set to 'on', 'off' or 'reboot' power states - """ - - def setUp(self): - super(NodeSetPowerStateTestIronicClient, self).setUp() - self.node = self.create_node() - node_power_state = self.show_node_states(self.node['uuid']) - self.assertEqual('None', node_power_state['power_state']) - - def test_node_set_power_state_on(self): - """Test steps: - - 1) create node - 2) set node power state to 'on' - 3) check node power state has been set to 'on' - """ - self.set_node_power_state(self.node['uuid'], 'on') - node_state = self.show_node_states(self.node['uuid']) - self.assertEqual('power on', node_state['power_state']) - - def test_node_set_power_state_off(self): - """Test steps: - - 1) create node - 2) set node power state to 'off' - 3) check node power state has been set to 'off' - """ - self.set_node_power_state(self.node['uuid'], 'off') - node_state = self.show_node_states(self.node['uuid']) - self.assertEqual('power off', node_state['power_state']) - - def test_node_set_power_state_reboot_node_off(self): - """Test steps: - - 1) create node - 2) set node power state to 'off' - 3) check node power state has been set to 'off' - 4) set node power state to 'reboot' - 5) check node power state has been set to 'on' - """ - self.set_node_power_state(self.node['uuid'], 'off') - node_state = self.show_node_states(self.node['uuid']) - - self.assertEqual('power off', node_state['power_state']) - - self.set_node_power_state(self.node['uuid'], 'reboot') - node_state = self.show_node_states(self.node['uuid']) - - self.assertEqual('power on', node_state['power_state']) - - def test_node_set_power_state_reboot_node_on(self): - """Test steps: - - 1) create node - 2) set node power state to 'on' - 3) check node power state has been set to 'on' - 4) set node power state to 'reboot' - 5) check node power state has been set to 'on' - """ - self.set_node_power_state(self.node['uuid'], 'on') - node_state = self.show_node_states(self.node['uuid']) - - self.assertEqual('power on', node_state['power_state']) - - self.set_node_power_state(self.node['uuid'], 'reboot') - node_state = self.show_node_states(self.node['uuid']) - - self.assertEqual('power on', node_state['power_state']) diff --git a/ironicclient/tests/functional/test_port.py b/ironicclient/tests/functional/test_port.py deleted file mode 100644 index 095f731e3..000000000 --- a/ironicclient/tests/functional/test_port.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright (c) 2016 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class PortSanityTestIronicClient(base.FunctionalTestBase): - """Sanity tests for testing actions with port. - - Smoke test for the Ironic CLI commands which checks basic actions with - port command like create, show, update, delete etc. - """ - - def setUp(self): - super(PortSanityTestIronicClient, self).setUp() - self.node = self.create_node() - self.port = self.create_port(self.node['uuid']) - - def test_port_create(self): - """Test steps: - - 1) create node in setUp() - 2) create port in setUp() - 3) check that port has been successfully created - """ - port_list_uuid = self.get_uuids_from_port_list() - self.assertIn(self.port['uuid'], port_list_uuid) - - def test_port_delete(self): - """Test steps: - - 1) create node in setUp() - 2) create port in setUp() - 3) check that port has been successfully created - 4) delete port - 5) check that port has been successfully deleted - """ - port_list_uuid = self.get_uuids_from_port_list() - self.assertIn(self.port['uuid'], port_list_uuid) - - self.delete_port(self.port['uuid']) - - port_list_uuid = self.get_uuids_from_port_list() - self.assertNotIn(self.port['uuid'], port_list_uuid) - - def test_port_show(self): - """Test steps: - - 1) create node in setUp() - 2) create port in setUp() - 3) check that port-show returns the same port UUID as port-create - """ - port_show = self.show_port(self.port['uuid']) - self.assertEqual(self.port['uuid'], port_show['uuid']) - - def test_port_show_field(self): - """Test steps: - - 1) create node in setUp() - 2) create port in setUp() - 3) show port with fields uuid, address, node_uuid - 4) check that only fields uuid, address, - node_uuid are the output fields - """ - fields = ['uuid', 'address', 'node_uuid'] - port_show = self.show_port(self.port['uuid'], - params='--fields {0} {1} {2}' - .format(*fields)) - self.assertTableHeaders(fields, port_show.keys()) - - def test_port_update(self): - """Test steps: - - 1) create node in setUp() - 2) create port in setUp() - 3) create node to replace - 4) update port replacing node - 5) check that port has been successfully updated - """ - node_to_replace = self.create_node() - updated_port = self.update_port(self.port['uuid'], - 'replace', - params='node_uuid={0}' - .format(node_to_replace['uuid'])) - - self.assertEqual(node_to_replace['uuid'], updated_port['node_uuid']) - self.assertNotEqual(self.port['node_uuid'], updated_port['node_uuid']) - - def test_port_list(self): - """Test steps: - - 1) create node and port in setUp() - 2) create one more node and port explicitly - 3) check that port-list contains UUIDs of created ports - 4) check that port-list contains Addresses of created ports - """ - other_node = self.create_node() - other_port = self.create_port(other_node['uuid']) - - port_list = self.list_ports() - uuids = {x['UUID'] for x in port_list} - self.assertTrue({self.port['uuid'], - other_port['uuid']}.issubset(uuids)) - addresses = {x['Address'] for x in port_list} - self.assertTrue({self.port['address'], - other_port['address']}.issubset(addresses)) - - def test_port_create_with_portgroup_uuid(self): - """Test steps: - - 1) Create node in setUp(). - 2) Create a port group. - 3) Create a port with specified port group UUID. - 4) Check port properties for portgroup_uuid. - """ - flag = '--ironic-api-version 1.25' - port_group = self.create_portgroup(self.node['uuid']) - port = self.create_port( - self.node['uuid'], - flags=flag, - params='--portgroup {0}'.format(port_group['uuid'])) - - self.assertEqual(port_group['uuid'], port['portgroup_uuid']) diff --git a/ironicclient/tests/functional/test_portgroup.py b/ironicclient/tests/functional/test_portgroup.py deleted file mode 100644 index 7d3f9ea4f..000000000 --- a/ironicclient/tests/functional/test_portgroup.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright (c) 2016 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class PortGroupSanityTest(base.FunctionalTestBase): - """Sanity tests for testing actions with port groups. - - Smoke test for the Ironic CLI port group subcommands: - create, show, update, delete, list, port-list. - """ - def setUp(self): - super(PortGroupSanityTest, self).setUp() - self.node = self.create_node() - self.port_group = self.create_portgroup(self.node['uuid']) - - def test_portgroup_create(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Check that port group has been successfully created. - """ - portgroup_list_uuid = self.get_portgroup_uuids_from_portgroup_list() - self.assertIn(self.port_group['uuid'], portgroup_list_uuid) - - def test_portgroup_delete(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Delete port group. - 3) Check that port group has been successfully deleted. - """ - self.delete_portgroup(self.port_group['uuid']) - portgroup_list_uuid = self.get_portgroup_uuids_from_portgroup_list() - self.assertNotIn(self.port_group['uuid'], portgroup_list_uuid) - - def test_portgroup_show(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Check that portgroup-show returns the same UUID as portgroup-create. - """ - portgroup_show = self.show_portgroup(self.port_group['uuid']) - self.assertEqual(self.port_group['uuid'], portgroup_show['uuid']) - self.assertEqual(self.port_group['name'], portgroup_show['name']) - - def test_portgroup_list(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Create one more node and port group. - 3) Check that portgroup-list contains UUIDs - of all created port groups. - """ - other_node = self.create_node() - other_portgroup = self.create_portgroup(other_node['uuid']) - - uuids = {x['UUID'] for x in self.list_portgroups()} - - self.assertTrue({self.port_group['uuid'], - other_portgroup['uuid']}.issubset(uuids)) - - def test_portgroup_update(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Create node to replace. - 3) Set new node to maintenance. - 4) Update port group by replacing node. - 5) Check that port group has been successfully updated. - """ - node_to_replace = self.create_node() - self.set_node_maintenance(node_to_replace['uuid'], True) - updated_portgroup = self.update_portgroup( - self.port_group['uuid'], 'replace', params='node_uuid={0}' - .format(node_to_replace['uuid']) - ) - self.assertEqual(node_to_replace['uuid'], - updated_portgroup['node_uuid']) - self.assertNotEqual(self.port_group['node_uuid'], - updated_portgroup['node_uuid']) - - def test_portgroup_port_list(self): - """Test steps: - - 1) Create node and port group in setUp(). - 2) Create a port. - 3) Set node to maintenance. - 4) Attach port to the port group. - 5) List the ports associated with a port group. - 6) Check port UUID in list. - 7) Check port address in list. - """ - port = self.create_port(self.node['uuid']) - self.set_node_maintenance(self.node['uuid'], True) - self.update_port(port['uuid'], 'replace', - flags='--ironic-api-version 1.25', - params='portgroup_uuid={0}' - .format(self.port_group['uuid'])) - pg_port_list = self.portgroup_port_list(self.port_group['uuid']) - self.assertIn(port['uuid'], [x['UUID'] for x in pg_port_list]) - self.assertIn(port['address'], [x['Address'] for x in pg_port_list]) diff --git a/ironicclient/tests/functional/test_table_structure.py b/ironicclient/tests/functional/test_table_structure.py deleted file mode 100644 index a617cef16..000000000 --- a/ironicclient/tests/functional/test_table_structure.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.functional import base - - -class TableStructureIronicCLITests(base.FunctionalTestBase): - """Basic, read-only table structure tests for Ironic CLI commands. - - Basic smoke tests for the Ironic CLI commands to check table structure - which do not require creating or modifying Ironic objects. - """ - - def test_chassis_list_table_structure(self): - """Test steps: - - 1) get chassis-list - 2) check table structure - """ - chassis_list_header = self.get_table_headers('chassis-list') - self.assertTableHeaders(['Description', 'UUID'], chassis_list_header) - - def test_node_list_table_structure(self): - """Test steps: - - 1) get node-list - 2) check table structure - """ - node_list_header = self.get_table_headers('node-list') - self.assertTableHeaders(['UUID', 'Name', 'Instance UUID', - 'Power State', 'Provisioning State', - 'Maintenance'], node_list_header) - - def test_port_list_table_structure(self): - """Test steps: - - 1) get port-list - 2) check table structure - """ - port_list_header = self.get_table_headers('port-list') - self.assertTableHeaders(['UUID', 'Address'], port_list_header) - - def test_driver_list_table_structure(self): - """Test steps: - - 1) get driver-list - 2) check table structure - """ - driver_list_header = self.get_table_headers('driver-list') - self.assertTableHeaders(['Supported driver(s)', 'Active host(s)'], - driver_list_header) diff --git a/ironicclient/tests/unit/common/test_cliutils.py b/ironicclient/tests/unit/common/test_cliutils.py deleted file mode 100644 index 5984b5f73..000000000 --- a/ironicclient/tests/unit/common/test_cliutils.py +++ /dev/null @@ -1,740 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import sys - -import fixtures -import mock -from oslotest import base as test_base -import six - -from ironicclient.common import cliutils - - -class ValidateArgsTest(test_base.BaseTestCase): - - def test_lambda_no_args(self): - cliutils.validate_args(lambda: None) - - def _test_lambda_with_args(self, *args, **kwargs): - cliutils.validate_args(lambda x, y: None, *args, **kwargs) - - def test_lambda_positional_args(self): - self._test_lambda_with_args(1, 2) - - def test_lambda_kwargs(self): - self._test_lambda_with_args(x=1, y=2) - - def test_lambda_mixed_kwargs(self): - self._test_lambda_with_args(1, y=2) - - def test_lambda_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_args) - - def test_lambda_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_args, 1) - - def test_lambda_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_args, y=2) - - def _test_lambda_with_default(self, *args, **kwargs): - cliutils.validate_args(lambda x, y, z=3: None, *args, **kwargs) - - def test_lambda_positional_args_with_default(self): - self._test_lambda_with_default(1, 2) - - def test_lambda_kwargs_with_default(self): - self._test_lambda_with_default(x=1, y=2) - - def test_lambda_mixed_kwargs_with_default(self): - self._test_lambda_with_default(1, y=2) - - def test_lambda_positional_args_all_with_default(self): - self._test_lambda_with_default(1, 2, 3) - - def test_lambda_kwargs_all_with_default(self): - self._test_lambda_with_default(x=1, y=2, z=3) - - def test_lambda_mixed_kwargs_all_with_default(self): - self._test_lambda_with_default(1, y=2, z=3) - - def test_lambda_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_default) - - def test_lambda_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_default, 1) - - def test_lambda_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_default, y=2) - - def test_lambda_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_lambda_with_default, y=2, z=3) - - def test_function_no_args(self): - def func(): - pass - cliutils.validate_args(func) - - def _test_function_with_args(self, *args, **kwargs): - def func(x, y): - pass - cliutils.validate_args(func, *args, **kwargs) - - def test_function_positional_args(self): - self._test_function_with_args(1, 2) - - def test_function_kwargs(self): - self._test_function_with_args(x=1, y=2) - - def test_function_mixed_kwargs(self): - self._test_function_with_args(1, y=2) - - def test_function_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_args) - - def test_function_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_args, 1) - - def test_function_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_args, y=2) - - def _test_function_with_default(self, *args, **kwargs): - def func(x, y, z=3): - pass - cliutils.validate_args(func, *args, **kwargs) - - def test_function_positional_args_with_default(self): - self._test_function_with_default(1, 2) - - def test_function_kwargs_with_default(self): - self._test_function_with_default(x=1, y=2) - - def test_function_mixed_kwargs_with_default(self): - self._test_function_with_default(1, y=2) - - def test_function_positional_args_all_with_default(self): - self._test_function_with_default(1, 2, 3) - - def test_function_kwargs_all_with_default(self): - self._test_function_with_default(x=1, y=2, z=3) - - def test_function_mixed_kwargs_all_with_default(self): - self._test_function_with_default(1, y=2, z=3) - - def test_function_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_default) - - def test_function_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_default, 1) - - def test_function_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_default, y=2) - - def test_function_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_function_with_default, y=2, z=3) - - def test_bound_method_no_args(self): - class Foo(object): - def bar(self): - pass - cliutils.validate_args(Foo().bar) - - def _test_bound_method_with_args(self, *args, **kwargs): - class Foo(object): - def bar(self, x, y): - pass - cliutils.validate_args(Foo().bar, *args, **kwargs) - - def test_bound_method_positional_args(self): - self._test_bound_method_with_args(1, 2) - - def test_bound_method_kwargs(self): - self._test_bound_method_with_args(x=1, y=2) - - def test_bound_method_mixed_kwargs(self): - self._test_bound_method_with_args(1, y=2) - - def test_bound_method_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_args) - - def test_bound_method_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_args, 1) - - def test_bound_method_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_args, y=2) - - def _test_bound_method_with_default(self, *args, **kwargs): - class Foo(object): - def bar(self, x, y, z=3): - pass - cliutils.validate_args(Foo().bar, *args, **kwargs) - - def test_bound_method_positional_args_with_default(self): - self._test_bound_method_with_default(1, 2) - - def test_bound_method_kwargs_with_default(self): - self._test_bound_method_with_default(x=1, y=2) - - def test_bound_method_mixed_kwargs_with_default(self): - self._test_bound_method_with_default(1, y=2) - - def test_bound_method_positional_args_all_with_default(self): - self._test_bound_method_with_default(1, 2, 3) - - def test_bound_method_kwargs_all_with_default(self): - self._test_bound_method_with_default(x=1, y=2, z=3) - - def test_bound_method_mixed_kwargs_all_with_default(self): - self._test_bound_method_with_default(1, y=2, z=3) - - def test_bound_method_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_default) - - def test_bound_method_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_default, 1) - - def test_bound_method_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_default, y=2) - - def test_bound_method_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_bound_method_with_default, y=2, z=3) - - def test_unbound_method_no_args(self): - class Foo(object): - def bar(self): - pass - cliutils.validate_args(Foo.bar, Foo()) - - def _test_unbound_method_with_args(self, *args, **kwargs): - class Foo(object): - def bar(self, x, y): - pass - cliutils.validate_args(Foo.bar, Foo(), *args, **kwargs) - - def test_unbound_method_positional_args(self): - self._test_unbound_method_with_args(1, 2) - - def test_unbound_method_kwargs(self): - self._test_unbound_method_with_args(x=1, y=2) - - def test_unbound_method_mixed_kwargs(self): - self._test_unbound_method_with_args(1, y=2) - - def test_unbound_method_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_args) - - def test_unbound_method_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_args, 1) - - def test_unbound_method_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_args, y=2) - - def _test_unbound_method_with_default(self, *args, **kwargs): - class Foo(object): - def bar(self, x, y, z=3): - pass - cliutils.validate_args(Foo.bar, Foo(), *args, **kwargs) - - def test_unbound_method_positional_args_with_default(self): - self._test_unbound_method_with_default(1, 2) - - def test_unbound_method_kwargs_with_default(self): - self._test_unbound_method_with_default(x=1, y=2) - - def test_unbound_method_mixed_kwargs_with_default(self): - self._test_unbound_method_with_default(1, y=2) - - def test_unbound_method_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_default) - - def test_unbound_method_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_default, 1) - - def test_unbound_method_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_default, y=2) - - def test_unbound_method_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_unbound_method_with_default, y=2, z=3) - - def test_class_method_no_args(self): - class Foo(object): - @classmethod - def bar(cls): - pass - cliutils.validate_args(Foo.bar) - - def _test_class_method_with_args(self, *args, **kwargs): - class Foo(object): - @classmethod - def bar(cls, x, y): - pass - cliutils.validate_args(Foo.bar, *args, **kwargs) - - def test_class_method_positional_args(self): - self._test_class_method_with_args(1, 2) - - def test_class_method_kwargs(self): - self._test_class_method_with_args(x=1, y=2) - - def test_class_method_mixed_kwargs(self): - self._test_class_method_with_args(1, y=2) - - def test_class_method_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_args) - - def test_class_method_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_args, 1) - - def test_class_method_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_args, y=2) - - def _test_class_method_with_default(self, *args, **kwargs): - class Foo(object): - @classmethod - def bar(cls, x, y, z=3): - pass - cliutils.validate_args(Foo.bar, *args, **kwargs) - - def test_class_method_positional_args_with_default(self): - self._test_class_method_with_default(1, 2) - - def test_class_method_kwargs_with_default(self): - self._test_class_method_with_default(x=1, y=2) - - def test_class_method_mixed_kwargs_with_default(self): - self._test_class_method_with_default(1, y=2) - - def test_class_method_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_default) - - def test_class_method_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_default, 1) - - def test_class_method_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_default, y=2) - - def test_class_method_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_class_method_with_default, y=2, z=3) - - def test_static_method_no_args(self): - class Foo(object): - @staticmethod - def bar(): - pass - cliutils.validate_args(Foo.bar) - - def _test_static_method_with_args(self, *args, **kwargs): - class Foo(object): - @staticmethod - def bar(x, y): - pass - cliutils.validate_args(Foo.bar, *args, **kwargs) - - def test_static_method_positional_args(self): - self._test_static_method_with_args(1, 2) - - def test_static_method_kwargs(self): - self._test_static_method_with_args(x=1, y=2) - - def test_static_method_mixed_kwargs(self): - self._test_static_method_with_args(1, y=2) - - def test_static_method_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_args) - - def test_static_method_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_args, 1) - - def test_static_method_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_args, y=2) - - def _test_static_method_with_default(self, *args, **kwargs): - class Foo(object): - @staticmethod - def bar(x, y, z=3): - pass - cliutils.validate_args(Foo.bar, *args, **kwargs) - - def test_static_method_positional_args_with_default(self): - self._test_static_method_with_default(1, 2) - - def test_static_method_kwargs_with_default(self): - self._test_static_method_with_default(x=1, y=2) - - def test_static_method_mixed_kwargs_with_default(self): - self._test_static_method_with_default(1, y=2) - - def test_static_method_with_default_missing_args1(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_default) - - def test_static_method_with_default_missing_args2(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_default, 1) - - def test_static_method_with_default_missing_args3(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_default, y=2) - - def test_static_method_with_default_missing_args4(self): - self.assertRaises(cliutils.MissingArgs, - self._test_static_method_with_default, y=2, z=3) - - -class _FakeResult(object): - def __init__(self, name, value): - self.name = name - self.value = value - - -class PrintResultTestCase(test_base.BaseTestCase): - - def setUp(self): - super(PrintResultTestCase, self).setUp() - self.mock_add_row = mock.MagicMock() - self.useFixture(fixtures.MonkeyPatch( - "prettytable.PrettyTable.add_row", - self.mock_add_row)) - self.mock_get_string = mock.MagicMock(return_value="") - self.useFixture(fixtures.MonkeyPatch( - "prettytable.PrettyTable.get_string", - self.mock_get_string)) - self.mock_init = mock.MagicMock(return_value=None) - self.useFixture(fixtures.MonkeyPatch( - "prettytable.PrettyTable.__init__", - self.mock_init)) - # NOTE(dtantsur): won't work with mocked __init__ - self.useFixture(fixtures.MonkeyPatch( - "prettytable.PrettyTable.align", - mock.MagicMock())) - - def test_print_list_sort_by_str(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 2), - _FakeResult("k2", 3)] - - cliutils.print_list(objs, ["Name", "Value"], sortby_index=0) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k3", 2]), - mock.call(["k2", 3])]) - self.mock_get_string.assert_called_with(sortby="Name") - self.mock_init.assert_called_once_with(["Name", "Value"]) - - def test_print_list_sort_by_integer(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k2", 3), - _FakeResult("k3", 2)] - - cliutils.print_list(objs, ["Name", "Value"], sortby_index=1) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k2", 3]), - mock.call(["k3", 2])]) - self.mock_get_string.assert_called_with(sortby="Value") - self.mock_init.assert_called_once_with(["Name", "Value"]) - - def test_print_list_sort_by_none(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - - cliutils.print_list(objs, ["Name", "Value"], sortby_index=None) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k3", 3]), - mock.call(["k2", 2])]) - self.mock_get_string.assert_called_with() - self.mock_init.assert_called_once_with(["Name", "Value"]) - - def test_print_list_dict(self): - objs = [{'name': 'k1', 'value': 1}, - {'name': 'k2', 'value': 2}] - cliutils.print_list(objs, ["Name", "Value"], sortby_index=None) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k2", 2])]) - self.mock_get_string.assert_called_with() - self.mock_init.assert_called_once_with(["Name", "Value"]) - - def test_print_dict(self): - cliutils.print_dict({"K": "k", "Key": "Value"}) - cliutils.print_dict({"K": "k", "Key": "Long\\nValue"}) - self.mock_add_row.assert_has_calls([ - mock.call(["K", "k"]), - mock.call(["Key", "Value"]), - mock.call(["K", "k"]), - mock.call(["Key", "Long"]), - mock.call(["", "Value"])], - any_order=True) - - def test_print_list_field_labels(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - field_labels = ["Another Name", "Another Value"] - - cliutils.print_list(objs, ["Name", "Value"], sortby_index=None, - field_labels=field_labels) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k3", 3]), - mock.call(["k2", 2])]) - self.mock_init.assert_called_once_with(field_labels) - - def test_print_list_field_labels_sort(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - field_labels = ["Another Name", "Another Value"] - - cliutils.print_list(objs, ["Name", "Value"], sortby_index=0, - field_labels=field_labels) - - self.assertEqual(self.mock_add_row.call_args_list, - [mock.call(["k1", 1]), - mock.call(["k3", 3]), - mock.call(["k2", 2])]) - self.mock_init.assert_called_once_with(field_labels) - self.mock_get_string.assert_called_with(sortby="Another Name") - - def test_print_list_field_labels_too_many(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - field_labels = ["Another Name", "Another Value", "Redundant"] - - self.assertRaises(ValueError, cliutils.print_list, - objs, ["Name", "Value"], sortby_index=None, - field_labels=field_labels) - - -class PrintResultStringTestCase(test_base.BaseTestCase): - - def test_print_list_string(self): - objs = [_FakeResult("k1", 1)] - field_labels = ["Another Name", "Another Value"] - - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_list(objs, ["Name", "Value"], sortby_index=0, - field_labels=field_labels) - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - expected = '''\ -+--------------+---------------+ -| Another Name | Another Value | -+--------------+---------------+ -| k1 | 1 | -+--------------+---------------+ -''' - self.assertEqual(expected, out) - - def test_print_list_string_json(self): - objs = [_FakeResult("k1", 1)] - field_labels = ["Another Name", "Another Value"] - - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_list(objs, ["Name", "Value"], sortby_index=0, - field_labels=field_labels, json_flag=True) - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - expected = [{"name": "k1", "value": 1}] - self.assertEqual(expected, json.loads(out)) - - def test_print_dict_string(self): - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_dict({"K": "k", "Key": "Value"}) - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - expected = '''\ -+----------+-------+ -| Property | Value | -+----------+-------+ -| K | k | -| Key | Value | -+----------+-------+ -''' - self.assertEqual(expected, out) - - def test_print_dict_string_json(self): - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_dict({"K": "k", "Key": "Value"}, json_flag=True) - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - expected = {"K": "k", "Key": "Value"} - self.assertEqual(expected, json.loads(out)) - - def test_print_dict_string_custom_headers(self): - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_dict({"K": "k", "Key": "Value"}, dict_property='Foo', - dict_value='Bar') - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - expected = '''\ -+-----+-------+ -| Foo | Bar | -+-----+-------+ -| K | k | -| Key | Value | -+-----+-------+ -''' - self.assertEqual(expected, out) - - def test_print_dict_string_sorted(self): - orig = sys.stdout - sys.stdout = six.StringIO() - cliutils.print_dict({"Foo": "k", "Bar": "Value"}) - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - expected = '''\ -+----------+-------+ -| Property | Value | -+----------+-------+ -| Bar | Value | -| Foo | k | -+----------+-------+ -''' - self.assertEqual(expected, out) - - def test_print_dict_negative_wrap(self): - dct = {"K": "k", "Key": "Value"} - self.assertRaises(ValueError, cliutils.print_dict, dct, wrap=-10) - - -class DecoratorsTestCase(test_base.BaseTestCase): - - def test_arg(self): - func_args = [("--image", ), ("--flavor", )] - func_kwargs = [dict(default=None, - metavar=""), - dict(default=None, - metavar="")] - - @cliutils.arg(*func_args[1], **func_kwargs[1]) - @cliutils.arg(*func_args[0], **func_kwargs[0]) - def dummy_func(): - pass - - self.assertTrue(hasattr(dummy_func, "arguments")) - self.assertEqual(len(dummy_func.arguments), 2) - for args_kwargs in zip(func_args, func_kwargs): - self.assertIn(args_kwargs, dummy_func.arguments) - - def test_unauthenticated(self): - def dummy_func(): - pass - - self.assertFalse(cliutils.isunauthenticated(dummy_func)) - dummy_func = cliutils.unauthenticated(dummy_func) - self.assertTrue(cliutils.isunauthenticated(dummy_func)) - - -class EnvTestCase(test_base.BaseTestCase): - - def test_env(self): - env = {"alpha": "a", "beta": "b"} - self.useFixture(fixtures.MonkeyPatch("os.environ", env)) - self.assertEqual(env["beta"], cliutils.env("beta")) - self.assertEqual(env["beta"], cliutils.env("beta", "alpha")) - self.assertEqual(env["alpha"], cliutils.env("alpha", "beta")) - self.assertEqual(env["beta"], cliutils.env("gamma", "beta")) - self.assertEqual("", cliutils.env("gamma")) - self.assertEqual("c", cliutils.env("gamma", default="c")) - - -class GetPasswordTestCase(test_base.BaseTestCase): - - def setUp(self): - super(GetPasswordTestCase, self).setUp() - - class FakeFile(object): - def isatty(self): - return True - - self.useFixture(fixtures.MonkeyPatch("sys.stdin", FakeFile())) - - def test_get_password(self): - self.useFixture(fixtures.MonkeyPatch("getpass.getpass", - lambda prompt: "mellon")) - self.assertEqual("mellon", cliutils.get_password()) - - def test_get_password_verify(self): - env = {"OS_VERIFY_PASSWORD": "True"} - self.useFixture(fixtures.MonkeyPatch("os.environ", env)) - self.useFixture(fixtures.MonkeyPatch("getpass.getpass", - lambda prompt: "mellon")) - self.assertEqual("mellon", cliutils.get_password()) - - def test_get_password_verify_failure(self): - env = {"OS_VERIFY_PASSWORD": "True"} - self.useFixture(fixtures.MonkeyPatch("os.environ", env)) - self.useFixture(fixtures.MonkeyPatch("getpass.getpass", - lambda prompt: prompt)) - self.assertIsNone(cliutils.get_password()) diff --git a/ironicclient/tests/unit/test_shell.py b/ironicclient/tests/unit/test_shell.py deleted file mode 100644 index 74d0084ac..000000000 --- a/ironicclient/tests/unit/test_shell.py +++ /dev/null @@ -1,520 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import sys - -import fixtures -from keystoneauth1 import exceptions as keystone_exc -from keystoneauth1 import fixture as ks_fixture -import mock -from oslo_utils import uuidutils -import requests_mock -import six -import testtools -from testtools import matchers - -from ironicclient import client -from ironicclient.common.apiclient import exceptions -from ironicclient.common import http -from ironicclient import exc -from ironicclient import shell as ironic_shell -from ironicclient.tests.unit import utils - -BASE_URL = 'http://no.where:5000' -V2_URL = BASE_URL + '/v2.0' -V3_URL = BASE_URL + '/v3' - -FAKE_ENV = {'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_PROJECT_NAME': 'project_name', - 'OS_AUTH_URL': V2_URL} - -FAKE_ENV_WITH_SSL = FAKE_ENV.copy() -FAKE_ENV_WITH_SSL.update({ - 'OS_CACERT': 'cacert', - 'OS_CERT': 'cert', - 'OS_KEY': 'key', -}) - -FAKE_ENV_KEYSTONE_V2 = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_PROJECT_NAME': 'project_name', - 'OS_AUTH_URL': V2_URL -} - -FAKE_ENV_KEYSTONE_V3 = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_PROJECT_NAME': 'project_name', - 'OS_AUTH_URL': V3_URL, - 'OS_USER_DOMAIN_ID': 'default', - 'OS_PROJECT_DOMAIN_ID': 'default', -} - -FAKE_ENV_KEYSTONE_V2_TOKEN = { - 'OS_AUTH_TOKEN': 'admin_token', - 'OS_PROJECT_NAME': 'project_name', - 'OS_AUTH_URL': V2_URL -} - - -class ShellTest(utils.BaseTestCase): - re_options = re.DOTALL | re.MULTILINE - - # Patch os.environ to avoid required auth info. - def make_env(self, exclude=None, environ_dict=FAKE_ENV): - env = dict((k, v) for k, v in environ_dict.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - def setUp(self): - super(ShellTest, self).setUp() - - def shell(self, argstr): - with mock.patch.object(sys, 'stdout', six.StringIO()): - with mock.patch.object(sys, 'stderr', six.StringIO()): - try: - _shell = ironic_shell.IronicShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - out = sys.stdout.getvalue() - err = sys.stderr.getvalue() - return out, err - - def test_help_unknown_command(self): - self.assertRaises(exc.CommandError, self.shell, 'help foofoo') - - def test_help(self): - required = [ - '.*?^usage: ironic', - '.*?^ +bash-completion', - '.*?^See "ironic help COMMAND" ' - 'for help on a specific command', - ] - for argstr in ['--help', 'help']: - help_text = self.shell(argstr)[0] - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, - self.re_options)) - - def test_help_on_subcommand(self): - required = [ - ".*?^usage: ironic chassis-show", - ".*?^Show detailed information about a chassis", - ] - argstrings = [ - 'help chassis-show', - ] - for argstr in argstrings: - help_text = self.shell(argstr)[0] - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, self.re_options)) - - def test_required_args_on_node_create_help(self): - required = [ - ".*?^usage: ironic node-create", - ".*?^Register a new node with the Ironic service", - ".*?^Required arguments:", - ] - argstrings = [ - 'help node-create', - ] - for argstr in argstrings: - help_text = self.shell(argstr)[0] - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, self.re_options)) - - def test_required_args_on_port_create_help(self): - required = [ - ".*?^usage: ironic port-create", - ".*?^Create a new port", - ".*?^Required arguments:", - ] - argstrings = [ - 'help port-create', - ] - for argstr in argstrings: - help_text = self.shell(argstr)[0] - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, self.re_options)) - - def test_auth_param(self): - self.make_env(exclude='OS_USERNAME') - self.test_help() - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - @mock.patch('sys.stdin', side_effect=mock.MagicMock, autospec=True) - @mock.patch('getpass.getpass', return_value='password', autospec=True) - def test_password_prompted(self, mock_getpass, mock_stdin, mock_client): - self.make_env(exclude='OS_PASSWORD') - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, 'node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV['OS_AUTH_URL'], - 'username': FAKE_ENV['OS_USERNAME'], - 'password': FAKE_ENV['OS_PASSWORD'], - 'project_name': FAKE_ENV['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'timeout': 600, 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - # Make sure we are actually prompted. - mock_getpass.assert_called_with('OpenStack Password: ') - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - @mock.patch('sys.stdin', side_effect=mock.MagicMock, autospec=True) - @mock.patch('getpass.getpass', return_value='password', autospec=True) - def test_password(self, mock_getpass, mock_stdin, mock_client): - self.make_env(environ_dict=FAKE_ENV_WITH_SSL) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, 'node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV_WITH_SSL['OS_AUTH_URL'], - 'username': FAKE_ENV_WITH_SSL['OS_USERNAME'], - 'password': FAKE_ENV_WITH_SSL['OS_PASSWORD'], - 'project_name': FAKE_ENV_WITH_SSL['OS_PROJECT_NAME'], - 'cafile': FAKE_ENV_WITH_SSL['OS_CACERT'], - 'certfile': FAKE_ENV_WITH_SSL['OS_CERT'], - 'keyfile': FAKE_ENV_WITH_SSL['OS_KEY'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'timeout': 600, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - self.assertFalse(mock_getpass.called) - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - @mock.patch('getpass.getpass', return_value='password', autospec=True) - def test_token_auth(self, mock_getpass, mock_client): - self.make_env(environ_dict=FAKE_ENV_KEYSTONE_V2_TOKEN) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, 'node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_URL'], - 'token': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN'], - 'project_name': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'timeout': 600, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - self.assertFalse(mock_getpass.called) - - @mock.patch.object(client, 'get_client', autospec=True) - @mock.patch('getpass.getpass', return_value='password', autospec=True) - def test_admin_token_auth(self, mock_getpass, mock_client): - self.make_env(environ_dict={ - 'IRONIC_URL': 'http://192.168.1.1/v1', - 'OS_AUTH_TOKEN': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN']}) - expected_kwargs = { - 'endpoint': 'http://192.168.1.1/v1', - 'token': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'timeout': 600, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'insecure': False - } - self.shell('node-list') - mock_client.assert_called_once_with(1, **expected_kwargs) - self.assertFalse(mock_getpass.called) - - @mock.patch.object(client, 'get_client', autospec=True) - @mock.patch('getpass.getpass', return_value='password', autospec=True) - def test_none_auth(self, mock_getpass, mock_client): - self.make_env(environ_dict={'IRONIC_URL': 'http://192.168.1.1/v1'}) - expected_kwargs = { - 'endpoint': 'http://192.168.1.1/v1', - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'timeout': 600, 'insecure': False - } - self.shell('node-list') - mock_client.assert_called_once_with(1, **expected_kwargs) - self.assertFalse(mock_getpass.called) - - @mock.patch('sys.stdin', side_effect=mock.MagicMock, autospec=True) - @mock.patch('getpass.getpass', side_effect=EOFError, autospec=True) - def test_password_prompted_ctrlD(self, mock_getpass, mock_stdin): - self.make_env(exclude='OS_PASSWORD') - # We should get Command Error because we mock Ctl-D. - self.assertRaises(exc.CommandError, - self.shell, 'node-list') - # Make sure we are actually prompted. - mock_getpass.assert_called_with('OpenStack Password: ') - - @mock.patch('sys.stdin', autospec=True) - def test_no_password_no_tty(self, mock_stdin): - # delete the isatty attribute so that we do not get - # prompted when manually running the tests - del mock_stdin.isatty - required = ('You must provide a password' - ' via either --os-password, env[OS_PASSWORD],' - ' or prompted response',) - self.make_env(exclude='OS_PASSWORD') - try: - self.shell('node-list') - except exc.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - def test_bash_completion(self): - stdout = self.shell('bash-completion')[0] - # just check we have some output - required = [ - '.*--driver_info', - '.*--chassis_uuid', - '.*help', - '.*node-create', - '.*chassis-create'] - for r in required: - self.assertThat(stdout, - matchers.MatchesRegex(r, self.re_options)) - - def test_ironic_api_version(self): - err = self.shell('--ironic-api-version 1.2 help')[1] - self.assertIn('The "ironic" CLI is deprecated', err) - - err = self.shell('--ironic-api-version latest help')[1] - self.assertIn('The "ironic" CLI is deprecated', err) - - err = self.shell('--ironic-api-version 1 help')[1] - self.assertIn('The "ironic" CLI is deprecated', err) - - def test_invalid_ironic_api_version(self): - self.assertRaises(exceptions.UnsupportedVersion, - self.shell, '--ironic-api-version 0.8 help') - self.assertRaises(exc.CommandError, - self.shell, '--ironic-api-version 1.2.1 help') - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - def test_api_version_in_env(self, mock_client): - env = dict(IRONIC_API_VERSION='1.10', **FAKE_ENV) - self.make_env(environ_dict=env) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, 'node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV['OS_AUTH_URL'], - 'username': FAKE_ENV['OS_USERNAME'], - 'password': FAKE_ENV['OS_PASSWORD'], - 'project_name': FAKE_ENV['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': '1.10', - 'timeout': 600, 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - def test_api_version_v1_in_env(self, mock_client): - env = dict(IRONIC_API_VERSION='1', **FAKE_ENV) - self.make_env(environ_dict=env) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, 'node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV['OS_AUTH_URL'], - 'username': FAKE_ENV['OS_USERNAME'], - 'password': FAKE_ENV['OS_PASSWORD'], - 'project_name': FAKE_ENV['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'timeout': 600, 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - def test_api_version_in_args(self, mock_client): - env = dict(IRONIC_API_VERSION='1.10', **FAKE_ENV) - self.make_env(environ_dict=env) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, '--ironic-api-version 1.11 node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV['OS_AUTH_URL'], - 'username': FAKE_ENV['OS_USERNAME'], - 'password': FAKE_ENV['OS_PASSWORD'], - 'project_name': FAKE_ENV['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': '1.11', - 'timeout': 600, 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - - @mock.patch.object(client, 'get_client', autospec=True, - side_effect=keystone_exc.ConnectFailure) - def test_api_version_v1_in_args(self, mock_client): - env = dict(IRONIC_API_VERSION='1.10', **FAKE_ENV) - self.make_env(environ_dict=env) - # We will get a ConnectFailure because there is no keystone. - self.assertRaises(keystone_exc.ConnectFailure, - self.shell, '--ironic-api-version 1 node-list') - expected_kwargs = { - 'auth_url': FAKE_ENV['OS_AUTH_URL'], - 'username': FAKE_ENV['OS_USERNAME'], - 'password': FAKE_ENV['OS_PASSWORD'], - 'project_name': FAKE_ENV['OS_PROJECT_NAME'], - 'max_retries': http.DEFAULT_MAX_RETRIES, - 'retry_interval': http.DEFAULT_RETRY_INTERVAL, - 'os_ironic_api_version': ironic_shell.LATEST_VERSION, - 'timeout': 600, 'insecure': False - } - mock_client.assert_called_once_with(1, **expected_kwargs) - - -class TestCase(testtools.TestCase): - - def set_fake_env(self, fake_env): - client_env = ('OS_USERNAME', 'OS_PASSWORD', 'OS_PROJECT_ID', - 'OS_PROJECT_NAME', 'OS_AUTH_URL', 'OS_REGION_NAME', - 'OS_AUTH_TOKEN', 'OS_NO_CLIENT_AUTH', 'OS_SERVICE_TYPE', - 'OS_ENDPOINT_TYPE', 'OS_CACERT', 'OS_CERT', 'OS_KEY') - - for key in client_env: - self.useFixture( - fixtures.EnvironmentVariable(key, fake_env.get(key))) - - def register_keystone_v2_token_fixture(self, request_mocker): - v2_token = ks_fixture.V2Token() - service = v2_token.add_service('baremetal') - service.add_endpoint('http://ironic.example.com', region='RegionOne') - request_mocker.post('%s/tokens' % V2_URL, - json=v2_token) - - def register_keystone_v3_token_fixture(self, request_mocker): - v3_token = ks_fixture.V3Token() - service = v3_token.add_service('baremetal') - service.add_standard_endpoints(public='http://ironic.example.com') - request_mocker.post( - '%s/auth/tokens' % V3_URL, - json=v3_token, - headers={'X-Subject-Token': uuidutils.generate_uuid()}) - - def register_keystone_auth_fixture(self, request_mocker): - self.register_keystone_v2_token_fixture(request_mocker) - self.register_keystone_v3_token_fixture(request_mocker) - - request_mocker.get(V2_URL, json=ks_fixture.V2Discovery(V2_URL)) - request_mocker.get(V3_URL, json=ks_fixture.V3Discovery(V3_URL)) - request_mocker.get(BASE_URL, json=ks_fixture.DiscoveryList(BASE_URL)) - - -class ShellTestKeystoneV2(TestCase): - def setUp(self): - super(ShellTestKeystoneV2, self).setUp() - self.set_fake_env(FAKE_ENV_KEYSTONE_V2) - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = six.StringIO() - _shell = ironic_shell.IronicShell() - _shell.main(argstr.split()) - self.subcommands = _shell.subcommands.keys() - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - return out - - @requests_mock.mock() - def test_node_list(self, request_mocker): - self.register_keystone_auth_fixture(request_mocker) - resp_dict = {"nodes": [ - {"instance_uuid": "null", - "uuid": "351a82d6-9f04-4c36-b79a-a38b9e98ff71", - "links": [{"href": "http://ironic.example.com:6385/" - "v1/nodes/foo", - "rel": "self"}, - {"href": "http://ironic.example.com:6385/" - "nodes/foo", - "rel": "bookmark"}], - "maintenance": "false", - "provision_state": "null", - "power_state": "power off"}, - {"instance_uuid": "null", - "uuid": "66fbba13-29e8-4b8a-9e80-c655096a40d3", - "links": [{"href": "http://ironic.example.com:6385/" - "v1/nodes/foo2", - "rel": "self"}, - {"href": "http://ironic.example.com:6385/" - "nodes/foo2", - "rel": "bookmark"}], - "maintenance": "false", - "provision_state": "null", - "power_state": "power off"}]} - headers = {'Content-Type': 'application/json; charset=UTF-8'} - request_mocker.get('http://ironic.example.com/v1/nodes', - headers=headers, - json=resp_dict) - - event_list_text = self.shell('node-list') - - required = [ - '351a82d6-9f04-4c36-b79a-a38b9e98ff71', - '66fbba13-29e8-4b8a-9e80-c655096a40d3', - ] - - for r in required: - self.assertRegex(event_list_text, r) - - -class ShellTestKeystoneV3(ShellTestKeystoneV2): - - def _set_fake_env(self): - self.set_fake_env(FAKE_ENV_KEYSTONE_V3) - - -class ShellParserTest(TestCase): - def test_deprecated_defaults(self): - cert_env = {} - cert_env['OS_CACERT'] = '/fake/cacert.pem' - cert_env['OS_CERT'] = '/fake/cert.pem' - cert_env['OS_KEY'] = '/fake/key.pem' - self.set_fake_env(cert_env) - parser = ironic_shell.IronicShell().get_base_parser() - options, _ = parser.parse_known_args([]) - self.assertEqual(cert_env['OS_CACERT'], options.os_cacert) - self.assertEqual(cert_env['OS_CERT'], options.os_cert) - self.assertEqual(cert_env['OS_KEY'], options.os_key) diff --git a/ironicclient/tests/unit/v1/test_chassis_shell.py b/ironicclient/tests/unit/v1/test_chassis_shell.py deleted file mode 100644 index a254ce99c..000000000 --- a/ironicclient/tests/unit/v1/test_chassis_shell.py +++ /dev/null @@ -1,391 +0,0 @@ -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from oslo_utils import uuidutils - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient.tests.unit import utils -import ironicclient.v1.chassis_shell as c_shell - - -class ChassisShellTest(utils.BaseTestCase): - def _get_client_mock_args(self, chassis=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, associated=None, maintenance=None, - provision_state=None, json=False): - args = mock.MagicMock(spec=True) - args.chassis = chassis - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.associated = associated - args.maintenance = maintenance - args.provision_state = provision_state - args.json = json - - return args - - def test_chassis_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - chassis = object() - c_shell._print_chassis_show(chassis) - exp = ['created_at', 'description', 'extra', 'updated_at', 'uuid'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_chassis_show_space_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = ' ' - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_show, - client_mock, args) - - def test_do_chassis_show_empty_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = '' - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_show, - client_mock, args) - - def test_do_chassis_show_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = 'chassis_uuid' - args.fields = [['uuid', 'description']] - args.json = False - c_shell.do_chassis_show(client_mock, args) - client_mock.chassis.get.assert_called_once_with( - 'chassis_uuid', fields=['uuid', 'description']) - - def test_do_chassis_show_invalid_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = 'chassis_uuid' - args.fields = [['foo', 'bar']] - args.json = False - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_show, - client_mock, args) - - def test_do_chassis_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(detail=False) - - def test_do_chassis_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(detail=True) - - def test_do_chassis_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='created_at', - detail=False) - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(sort_key='created_at', - detail=False) - - def test_do_chassis_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='extra', - detail=False) - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list.called) - - def test_do_chassis_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='created_at', - detail=True) - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(sort_key='created_at', - detail=True) - - def test_do_chassis_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='extra', - detail=True) - - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list.called) - - def test_do_chassis_list_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='desc', - detail=False) - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(sort_dir='desc', - detail=False) - - def test_do_chassis_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='asc', - detail=True) - - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with(sort_dir='asc', - detail=True) - - def test_do_chassis_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='abc', - detail=False) - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list.called) - - def test_do_chassis_list_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['uuid', 'description']]) - c_shell.do_chassis_list(client_mock, args) - client_mock.chassis.list.assert_called_once_with( - fields=['uuid', 'description'], detail=False) - - def test_do_chassis_list_invalid_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_list, - client_mock, args) - - def test_do_chassis_node_list(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, detail=False) - - def test_do_chassis_node_list_details(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, detail=True) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, detail=True) - - def test_do_chassis_node_list_sort_key(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_key='created_at', - detail=False) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, sort_key='created_at', detail=False) - - def test_do_chassis_node_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_key='extra', - detail=False) - - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_node_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list_nodes.called) - - def test_do_chassis_node_list_detail_sort_key(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_key='created_at', - detail=True) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, sort_key='created_at', detail=True) - - def test_do_chassis_node_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_key='extra', - detail=True) - - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_node_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list_nodes.called) - - def test_do_chassis_node_list_sort_dir(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_dir='desc', - detail=False) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, sort_dir='desc', detail=False) - - def test_do_chassis_node_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_dir='asc', - detail=True) - - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, sort_dir='asc', detail=True) - - def test_do_chassis_node_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis_mock, sort_dir='abc', - detail=False) - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_node_list, - client_mock, args) - self.assertFalse(client_mock.chassis.list_nodes.called) - - def test_do_chassis_node_list_fields(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, - fields=[['uuid', 'power_state']]) - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, fields=['uuid', 'power_state'], detail=False) - - def test_do_chassis_node_list_associated(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, - associated=True) - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, associated=True, detail=False) - - def test_do_chassis_node_list_maintenance(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, - maintenance=True) - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, maintenance=True, detail=False) - - def test_do_chassis_node_list_provision_state(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, - provision_state='wait call-back') - c_shell.do_chassis_node_list(client_mock, args) - client_mock.chassis.list_nodes.assert_called_once_with( - chassis_mock, provision_state='wait call-back', detail=False) - - def test_do_chassis_node_list_invalid_fields(self): - client_mock = mock.MagicMock() - chassis_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(chassis=chassis_mock, - fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_node_list, client_mock, args) - - def test_do_chassis_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - c_shell.do_chassis_create(client_mock, args) - client_mock.chassis.create.assert_called_once_with() - - def test_do_chassis_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = uuidutils.generate_uuid() - args.json = False - - c_shell.do_chassis_create(client_mock, args) - client_mock.chassis.create.assert_called_once_with(uuid=args.uuid) - - def test_do_chassis_create_valid_field(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.extra = ["key1=val1", "key2=val2"] - args.description = 'desc' - args.json = False - c_shell.do_chassis_create(client_mock, args) - client_mock.chassis.create.assert_called_once_with(extra={ - 'key1': 'val1', - 'key2': 'val2'}, - description='desc') - - def test_do_chassis_create_wrong_extra_field(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.extra = ["foo"] - args.description = 'desc' - args.json = False - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_create, client_mock, args) - - def test_do_chassis_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = ['chassis_uuid'] - c_shell.do_chassis_delete(client_mock, args) - client_mock.chassis.delete.assert_called_once_with('chassis_uuid') - - def test_do_chassis_delete_multiple(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = ['chassis_uuid1', 'chassis_uuid2'] - c_shell.do_chassis_delete(client_mock, args) - client_mock.chassis.delete.assert_has_calls([ - mock.call('chassis_uuid1'), mock.call('chassis_uuid2')]) - - def test_do_chassis_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = 'chassis_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - c_shell.do_chassis_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.chassis.update.assert_called_once_with('chassis_uuid', - patch) - - def test_do_chassis_update_wrong_op(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis = 'chassis_uuid' - args.op = 'foo' - args.attributes = [['arg1=val1', 'arg2=val2']] - self.assertRaises(exceptions.CommandError, - c_shell.do_chassis_update, - client_mock, args) - self.assertFalse(client_mock.chassis.update.called) diff --git a/ironicclient/tests/unit/v1/test_create_resources_shell.py b/ironicclient/tests/unit/v1/test_create_resources_shell.py deleted file mode 100644 index 87a93206f..000000000 --- a/ironicclient/tests/unit/v1/test_create_resources_shell.py +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.tests.unit import utils -from ironicclient.v1 import create_resources -from ironicclient.v1 import create_resources_shell - - -class TestCreateResourcesShell(utils.BaseTestCase): - def setUp(self): - super(TestCreateResourcesShell, self).setUp() - self.client = mock.MagicMock(autospec=True) - - @mock.patch.object(create_resources, 'create_resources', autospec=True) - def test_create_shell(self, mock_create_resources): - args = mock.MagicMock() - files = ['file1', 'file2', 'file3'] - args.resource_files = files - create_resources_shell.do_create(self.client, args) - mock_create_resources.assert_called_once_with(self.client, files) diff --git a/ironicclient/tests/unit/v1/test_driver_shell.py b/ironicclient/tests/unit/v1/test_driver_shell.py deleted file mode 100644 index f73239a9d..000000000 --- a/ironicclient/tests/unit/v1/test_driver_shell.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.common import cliutils -from ironicclient.tests.unit import utils -import ironicclient.v1.driver as v1_driver -import ironicclient.v1.driver_shell as d_shell - - -class DriverShellTest(utils.BaseTestCase): - def setUp(self): - super(DriverShellTest, self).setUp() - client_mock = mock.MagicMock() - driver_mock = mock.MagicMock(spec=v1_driver.DriverManager) - client_mock.driver = driver_mock - self.client_mock = client_mock - - def test_driver_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - driver = object() - d_shell._print_driver_show(driver) - exp = ['hosts', 'name', 'type', - 'default_bios_interface', 'default_boot_interface', - 'default_console_interface', 'default_deploy_interface', - 'default_inspect_interface', 'default_management_interface', - 'default_network_interface', 'default_power_interface', - 'default_raid_interface', 'default_rescue_interface', - 'default_storage_interface', 'default_vendor_interface', - 'enabled_bios_interfaces', 'enabled_boot_interfaces', - 'enabled_console_interfaces', 'enabled_deploy_interfaces', - 'enabled_inspect_interfaces', 'enabled_management_interfaces', - 'enabled_network_interfaces', 'enabled_power_interfaces', - 'enabled_raid_interfaces', 'enabled_rescue_interfaces', - 'enabled_storage_interfaces', 'enabled_vendor_interfaces'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_driver_vendor_passthru_with_args(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [['arg1=val1', 'arg2=val2']] - - d_shell.do_driver_vendor_passthru(client_mock, args) - client_mock.driver.vendor_passthru.assert_called_once_with( - args.driver_name, args.method, http_method=args.http_method, - args={'arg1': 'val1', 'arg2': 'val2'}) - - def test_do_driver_vendor_passthru_without_args(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [[]] - - d_shell.do_driver_vendor_passthru(client_mock, args) - client_mock.driver.vendor_passthru.assert_called_once_with( - args.driver_name, args.method, args={}, - http_method=args.http_method) - - def test_do_driver_properties(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.json = False - - d_shell.do_driver_properties(client_mock, args) - client_mock.driver.properties.assert_called_once_with("driver_name") - - @mock.patch('ironicclient.common.cliutils.print_dict', autospec=True) - def test_do_driver_properties_with_wrap_default(self, mock_print_dict): - client_mock = self.client_mock - client_mock.driver.properties.return_value = { - 'foo': 'bar', - 'baz': 'qux'} - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.wrap = 0 - args.json = False - - d_shell.do_driver_properties(client_mock, args) - mock_print_dict.assert_called_with( - {'foo': 'bar', 'baz': 'qux'}, - dict_value='Description', - json_flag=False, - wrap=0) - - @mock.patch('ironicclient.common.cliutils.print_dict', autospec=True) - def test_do_driver_properties_with_wrap(self, mock_print_dict): - client_mock = self.client_mock - client_mock.driver.properties.return_value = { - 'foo': 'bar', - 'baz': 'qux'} - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.wrap = 80 - args.json = False - - d_shell.do_driver_properties(client_mock, args) - mock_print_dict.assert_called_with( - {'foo': 'bar', 'baz': 'qux'}, - dict_value='Description', - json_flag=False, - wrap=80) - - @mock.patch('ironicclient.common.cliutils.print_dict', autospec=True) - def _test_do_driver_raid_logical_disk(self, print_dict_mock, wrap=0): - cli_mock = self.client_mock - cli_mock.driver.raid_logical_disk_properties.return_value = { - 'foo': 'bar'} - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.wrap = wrap - - d_shell.do_driver_raid_logical_disk_properties(cli_mock, args) - - cli_mock.driver.raid_logical_disk_properties.assert_called_once_with( - "driver_name") - print_dict_mock.assert_called_with( - {'foo': 'bar'}, - dict_value='Description', - wrap=wrap) - - def test_do_driver_raid_logical_disk_default_wrap(self): - self._test_do_driver_raid_logical_disk() - - def test_do_driver_raid_logical_disk_with_wrap(self): - self._test_do_driver_raid_logical_disk(wrap=80) - - def test_do_driver_show(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.driver_name = 'fake' - args.json = False - - d_shell.do_driver_show(client_mock, args) - client_mock.driver.get.assert_called_once_with('fake') - - def test_do_driver_list(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.type = None - args.detail = None - args.json = False - - d_shell.do_driver_list(client_mock, args) - client_mock.driver.list.assert_called_once_with(driver_type=None, - detail=None) - - def test_do_driver_list_with_type_and_no_detail(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.type = 'classic' - args.detail = False - args.json = False - - d_shell.do_driver_list(client_mock, args) - client_mock.driver.list.assert_called_once_with(driver_type='classic', - detail=False) - - def test_do_driver_list_with_detail(self): - client_mock = self.client_mock - args = mock.MagicMock() - args.type = None - args.detail = True - args.json = False - - d_shell.do_driver_list(client_mock, args) - client_mock.driver.list.assert_called_once_with(driver_type=None, - detail=True) - - def test_do_driver_get_vendor_passthru_methods(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver_name = 'fake' - d_shell.do_driver_get_vendor_passthru_methods(client_mock, args) - mock_method = client_mock.driver.get_vendor_passthru_methods - mock_method.assert_called_once_with('fake') diff --git a/ironicclient/tests/unit/v1/test_node_shell.py b/ironicclient/tests/unit/v1/test_node_shell.py deleted file mode 100644 index 4cab954a8..000000000 --- a/ironicclient/tests/unit/v1/test_node_shell.py +++ /dev/null @@ -1,1327 +0,0 @@ -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import tempfile - -import mock - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient import exc -from ironicclient.tests.unit import utils -import ironicclient.v1.node_shell as n_shell -import ironicclient.v1.utils as v1_utils - - -class NodeShellTest(utils.BaseTestCase): - def test_node_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - node = object() - n_shell._print_node_show(node) - exp = ['allocation_uuid', - 'automated_clean', - 'chassis_uuid', - 'clean_step', - 'created_at', - 'conductor', - 'conductor_group', - 'console_enabled', - 'deploy_step', - 'description', - 'driver', - 'driver_info', - 'driver_internal_info', - 'extra', - 'instance_info', - 'instance_uuid', - 'last_error', - 'maintenance', - 'maintenance_reason', - 'fault', - 'name', - 'bios_interface', - 'boot_interface', - 'console_interface', - 'deploy_interface', - 'inspect_interface', - 'management_interface', - 'network_interface', - 'owner', - 'power_interface', - 'raid_interface', - 'rescue_interface', - 'storage_interface', - 'vendor_interface', - 'power_state', - 'properties', - 'protected', - 'protected_reason', - 'provision_state', - 'provision_updated_at', - 'reservation', - 'resource_class', - 'target_power_state', - 'target_provision_state', - 'traits', - 'updated_at', - 'inspection_finished_at', - 'inspection_started_at', - 'uuid', - 'raid_config', - 'target_raid_config'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_node_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ['node_uuid'] - - n_shell.do_node_delete(client_mock, args) - client_mock.node.delete.assert_called_once_with('node_uuid') - - def test_do_node_delete_multiple(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ['node_uuid1', 'node_uuid2'] - - n_shell.do_node_delete(client_mock, args) - client_mock.node.delete.assert_has_calls( - [mock.call('node_uuid1'), mock.call('node_uuid2')]) - - def test_do_node_delete_multiple_with_exception(self): - client_mock = mock.MagicMock() - client_mock.node.delete.side_effect = ( - [exceptions.ClientException, None]) - args = mock.MagicMock() - args.node = ['node_uuid1', 'node_uuid2'] - - self.assertRaises(exceptions.ClientException, n_shell.do_node_delete, - client_mock, args) - client_mock.node.delete.assert_has_calls( - [mock.call('node_uuid1'), mock.call('node_uuid2')]) - - def test_do_node_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - - n_shell.do_node_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.node.update.assert_called_once_with('node_uuid', patch) - - def test_do_node_update_wrong_op(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.op = 'foo' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_update, - client_mock, args) - self.assertFalse(client_mock.node.update.called) - - def test_do_node_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with() - - def test_do_node_create_with_driver(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver = 'driver' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - driver='driver') - - def test_do_node_create_with_chassis_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis_uuid = 'chassis_uuid' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - chassis_uuid='chassis_uuid') - - def test_do_node_create_with_driver_info(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver_info = ['arg1=val1', 'arg2=val2'] - args.json = False - - n_shell.do_node_create(client_mock, args) - kwargs = {'driver_info': {'arg1': 'val1', 'arg2': 'val2'}} - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_properties(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.properties = ['arg1=val1', 'arg2=val2'] - args.json = False - - n_shell.do_node_create(client_mock, args) - kwargs = {'properties': {'arg1': 'val1', 'arg2': 'val2'}} - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_extra(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver = 'driver_name' - args.extra = ['arg1=val1', 'arg2=val2'] - args.json = False - - n_shell.do_node_create(client_mock, args) - kwargs = { - 'driver': 'driver_name', - 'extra': {'arg1': 'val1', 'arg2': 'val2'}, - } - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = 'fef99cb8-a0d1-43df-b084-17b3b42b3cbd' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with(uuid=args.uuid) - - def test_do_node_create_with_name(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.name = 'node_name' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with(name=args.name) - - def test_do_node_create_with_boot_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.boot_interface = 'boot' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - boot_interface='boot') - - def test_do_node_create_with_console_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.console_interface = 'console' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - console_interface='console') - - def test_do_node_create_with_deploy_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.deploy_interface = 'deploy' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - deploy_interface='deploy') - - def test_do_node_create_with_inspect_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.inspect_interface = 'inspect' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - inspect_interface='inspect') - - def test_do_node_create_with_management_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.management_interface = 'management' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - management_interface='management') - - def test_do_node_create_with_network_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.network_interface = 'neutron' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - network_interface='neutron') - - def test_do_node_create_with_power_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.power_interface = 'power' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - power_interface='power') - - def test_do_node_create_with_raid_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.raid_interface = 'raid' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - raid_interface='raid') - - def test_do_node_create_with_storage_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.storage_interface = 'storage' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - storage_interface='storage') - - def test_do_node_create_with_vendor_interface(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.vendor_interface = 'vendor' - args.json = False - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - vendor_interface='vendor') - - def test_do_node_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.instance_uuid = False - args.fields = None - args.json = False - - n_shell.do_node_show(client_mock, args) - client_mock.node.get.assert_called_once_with('node_uuid', fields=None) - # assert get_by_instance_uuid() wasn't called - self.assertFalse(client_mock.node.get_by_instance_uuid.called) - - def test_do_node_show_by_instance_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'instance_uuid' - args.instance_uuid = True - args.fields = None - args.json = False - - n_shell.do_node_show(client_mock, args) - client_mock.node.get_by_instance_uuid.assert_called_once_with( - 'instance_uuid', fields=None) - # assert get() wasn't called - self.assertFalse(client_mock.node.get.called) - - def test_do_node_show_by_space_node_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ' ' - args.instance_uuid = False - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_show, - client_mock, args) - - def test_do_node_show_by_space_instance_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ' ' - args.instance_uuid = True - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_show, - client_mock, args) - - def test_do_node_show_by_empty_node_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = '' - args.instance_uuid = False - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_show, - client_mock, args) - - def test_do_node_show_by_empty_instance_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = '' - args.instance_uuid = True - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_show, - client_mock, args) - - def test_do_node_show_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.instance_uuid = False - args.fields = [['uuid', 'power_state']] - args.json = False - n_shell.do_node_show(client_mock, args) - client_mock.node.get.assert_called_once_with( - 'node_uuid', fields=['uuid', 'power_state']) - - def test_do_node_show_invalid_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.instance_uuid = False - args.fields = [['foo', 'bar']] - args.json = False - self.assertRaises(exceptions.CommandError, - n_shell.do_node_show, client_mock, args) - - def test_do_node_set_maintenance_true(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'true' - args.reason = 'reason' - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', True, maint_reason='reason') - - def test_do_node_set_maintenance_false(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'false' - # NOTE(jroll) None is the default. <3 mock. - args.reason = None - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', False, maint_reason=None) - - def test_do_node_set_maintenance_bad(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'yuck' - # NOTE(jroll) None is the default. <3 mock. - args.reason = None - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_maintenance, client_mock, args) - self.assertFalse(client_mock.node.set_maintenance.called) - - def test_do_node_set_maintenance_false_with_reason_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'false' - args.reason = 'reason' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_maintenance, - client_mock, args) - - def test_do_node_set_maintenance_on(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'on' - args.reason = 'reason' - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', True, maint_reason='reason') - - def test_do_node_set_maintenance_off(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'off' - # NOTE(jroll) None is the default. <3 mock. - args.reason = None - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', False, maint_reason=None) - - def test_do_node_set_maintenance_off_with_reason_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'off' - args.reason = 'reason' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_maintenance, - client_mock, args) - - def _do_node_set_power_state_helper(self, power_state, - soft=False, timeout=None, error=False): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.power_state = power_state - args.soft = soft - args.power_timeout = timeout - - if error: - client_mock.node = mock.MagicMock() - client_mock.node.set_power_state = mock.MagicMock() - client_mock.node.set_power_state.side_effect = ValueError("fake") - self.assertRaises(exc.CommandError, - n_shell.do_node_set_power_state, - client_mock, args) - else: - n_shell.do_node_set_power_state(client_mock, args) - client_mock.node.set_power_state.assert_called_once_with( - 'node_uuid', power_state, soft, timeout=timeout) - - def test_do_node_set_power_state_on(self): - self._do_node_set_power_state_helper('on') - - def test_do_node_set_power_state_off(self): - self._do_node_set_power_state_helper('off') - - def test_do_node_set_power_state_reboot(self): - self._do_node_set_power_state_helper('reboot') - - def test_do_node_set_power_state_on_timeout(self): - self._do_node_set_power_state_helper('on', timeout=10) - - def test_do_node_set_power_state_on_timeout_fail(self): - self._do_node_set_power_state_helper('on', timeout=0, error=True) - - def test_do_node_set_power_state_off_timeout(self): - self._do_node_set_power_state_helper('off', timeout=10) - - def test_do_node_set_power_state_reboot_timeout(self): - self._do_node_set_power_state_helper('reboot', timeout=10) - - def test_do_node_set_power_state_soft_on_fail(self): - self._do_node_set_power_state_helper('on', soft=True, error=True) - - def test_do_node_set_power_state_soft_off(self): - self._do_node_set_power_state_helper('off', soft=True) - - def test_do_node_set_power_state_soft_reboot(self): - self._do_node_set_power_state_helper('reboot', soft=True) - - def test_do_node_set_power_state_soft_on_timeout_fail(self): - self._do_node_set_power_state_helper('on', soft=True, timeout=10, - error=True) - - def test_do_node_set_power_state_soft_off_timeout(self): - self._do_node_set_power_state_helper('off', soft=True, timeout=10) - - def test_do_node_set_power_state_soft_reboot_timeout(self): - self._do_node_set_power_state_helper('reboot', soft=True, timeout=10) - - def test_do_node_set_target_raid_config_file(self): - contents = '{"raid": "config"}' - - with tempfile.NamedTemporaryFile(mode='w') as f: - f.write(contents) - f.flush() - - node_manager_mock = mock.MagicMock(spec=['set_target_raid_config']) - client_mock = mock.MagicMock(spec=['node'], node=node_manager_mock) - args = mock.MagicMock() - args.node = 'node_uuid' - args.target_raid_config = f.name - - n_shell.do_node_set_target_raid_config(client_mock, args) - node_manager_mock.set_target_raid_config.assert_called_once_with( - 'node_uuid', json.loads(contents)) - - def test_do_node_set_target_raid_config_string(self): - node_manager_mock = mock.MagicMock(spec=['set_target_raid_config']) - client_mock = mock.MagicMock(spec=['node'], node=node_manager_mock) - target_raid_config_string = ( - '{"logical_disks": [{"size_gb": 100, "raid_level": "1"}]}') - expected_target_raid_config_string = json.loads( - target_raid_config_string) - - args = mock.MagicMock(node='node', - target_raid_config=target_raid_config_string) - n_shell.do_node_set_target_raid_config(client_mock, args) - - node_manager_mock.set_target_raid_config.assert_called_once_with( - 'node', expected_target_raid_config_string) - - @mock.patch.object(commonutils, 'get_from_stdin', autospec=True) - def test_set_target_raid_config_stdin(self, stdin_read_mock): - node_manager_mock = mock.MagicMock(spec=['set_target_raid_config']) - client_mock = mock.MagicMock(spec=['node'], node=node_manager_mock) - target_raid_config_string = ( - '{"logical_disks": [{"size_gb": 100, "raid_level": "1"}]}') - stdin_read_mock.return_value = target_raid_config_string - args_mock = mock.MagicMock(node='node', - target_raid_config='-') - expected_target_raid_config_string = json.loads( - target_raid_config_string) - n_shell.do_node_set_target_raid_config(client_mock, args_mock) - stdin_read_mock.assert_called_once_with('target_raid_config') - client_mock.node.set_target_raid_config.assert_called_once_with( - 'node', expected_target_raid_config_string) - - @mock.patch.object(commonutils, 'get_from_stdin', autospec=True) - def test_set_target_raid_config_stdin_exception(self, stdin_read_mock): - client_mock = mock.MagicMock() - stdin_read_mock.side_effect = exc.InvalidAttribute('bad') - args_mock = mock.MagicMock(node='node', - target_raid_config='-') - - self.assertRaises(exc.InvalidAttribute, - n_shell.do_node_set_target_raid_config, - client_mock, args_mock) - - stdin_read_mock.assert_called_once_with('target_raid_config') - self.assertFalse(client_mock.set_target_raid_config.called) - - def test_do_node_validate(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - - n_shell.do_node_validate(client_mock, args) - client_mock.node.validate.assert_called_once_with('node_uuid') - - def test_do_node_vendor_passthru_with_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [['arg1=val1', 'arg2=val2']] - - n_shell.do_node_vendor_passthru(client_mock, args) - client_mock.node.vendor_passthru.assert_called_once_with( - args.node, args.method, args={'arg1': 'val1', 'arg2': 'val2'}, - http_method=args.http_method) - - def test_do_node_vendor_passthru_without_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [[]] - - n_shell.do_node_vendor_passthru(client_mock, args) - client_mock.node.vendor_passthru.assert_called_once_with( - args.node, args.method, args={}, http_method=args.http_method) - - def test_do_node_set_provision_state_active(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'active' - args.config_drive = 'foo' - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'active', configdrive='foo', cleansteps=None) - self.assertFalse(client_mock.node.wait_for_provision_state.called) - - def test_do_node_set_provision_state_active_wait(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'active' - args.config_drive = 'foo' - args.clean_steps = None - args.wait_timeout = 0 - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'active', configdrive='foo', cleansteps=None) - client_mock.node.wait_for_provision_state.assert_called_once_with( - 'node_uuid', expected_state='active', timeout=0, - poll_interval=v1_utils._LONG_ACTION_POLL_INTERVAL) - - def test_do_node_set_provision_state_deleted(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'deleted' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'deleted', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_rebuild(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'rebuild' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'rebuild', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_not_active_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'deleted' - args.config_drive = 'foo' - args.clean_steps = None - args.wait_timeout = None - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_provision_state, - client_mock, args) - self.assertFalse(client_mock.node.set_provision_state.called) - - def test_do_node_set_provision_state_inspect(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'inspect' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'inspect', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_manage(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'manage' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'manage', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_provide(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'provide' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'provide', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_clean(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'clean' - args.config_drive = None - clean_steps = '[{"step": "upgrade", "interface": "deploy"}]' - args.clean_steps = clean_steps - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'clean', configdrive=None, - cleansteps=json.loads(clean_steps)) - - @mock.patch.object(commonutils, 'get_from_stdin', autospec=True) - def test_do_node_set_provision_state_clean_stdin(self, mock_stdin): - clean_steps = '[{"step": "upgrade", "interface": "deploy"}]' - mock_stdin.return_value = clean_steps - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'clean' - args.config_drive = None - args.clean_steps = '-' - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - mock_stdin.assert_called_once_with('clean steps') - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'clean', configdrive=None, - cleansteps=json.loads(clean_steps)) - - @mock.patch.object(commonutils, 'get_from_stdin', autospec=True) - def test_do_node_set_provision_state_clean_stdin_fails(self, mock_stdin): - mock_stdin.side_effect = exc.InvalidAttribute('bad') - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'clean' - args.config_drive = None - args.clean_steps = '-' - args.wait_timeout = None - - self.assertRaises(exc.InvalidAttribute, - n_shell.do_node_set_provision_state, - client_mock, args) - mock_stdin.assert_called_once_with('clean steps') - self.assertFalse(client_mock.node.set_provision_state.called) - - def test_do_node_set_provision_state_clean_file(self): - contents = '[{"step": "upgrade", "interface": "deploy"}]' - - with tempfile.NamedTemporaryFile(mode='w') as f: - f.write(contents) - f.flush() - - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'clean' - args.config_drive = None - args.clean_steps = f.name - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'clean', configdrive=None, - cleansteps=json.loads(contents)) - - def test_do_node_set_provision_state_clean_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'clean' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - # clean_steps isn't specified - self.assertRaisesRegex(exceptions.CommandError, - 'clean-steps.*must be specified', - n_shell.do_node_set_provision_state, - client_mock, args) - self.assertFalse(client_mock.node.set_provision_state.called) - - def test_do_node_set_provision_state_not_clean_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'deleted' - args.config_drive = None - clean_steps = '[{"step": "upgrade", "interface": "deploy"}]' - args.clean_steps = clean_steps - args.wait_timeout = None - - # clean_steps specified but not cleaning - self.assertRaisesRegex(exceptions.CommandError, - 'clean-steps.*only valid', - n_shell.do_node_set_provision_state, - client_mock, args) - self.assertFalse(client_mock.node.set_provision_state.called) - - def test_do_node_set_provision_state_abort(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'abort' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'abort', configdrive=None, cleansteps=None) - - def test_do_node_set_provision_state_adopt(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'adopt' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = 0 - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'adopt', cleansteps=None, configdrive=None) - - def test_do_node_set_provision_state_abort_no_wait(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'abort' - args.config_drive = None - args.clean_steps = None - args.wait_timeout = 0 - - self.assertRaisesRegex(exceptions.CommandError, - "not supported for provision state 'abort'", - n_shell.do_node_set_provision_state, - client_mock, args) - self.assertFalse(client_mock.node.set_provision_state.called) - self.assertFalse(client_mock.node.wait_for_provision_state.called) - - def test_do_node_set_console_mode(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.enabled = 'true' - - n_shell.do_node_set_console_mode(client_mock, args) - client_mock.node.set_console_mode.assert_called_once_with( - 'node_uuid', True) - - def test_do_node_set_console_mode_bad(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.enabled = 'yuck' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_console_mode, client_mock, args) - self.assertFalse(client_mock.node.set_console_mode.called) - - def test_do_node_set_boot_device(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.persistent = False - args.device = 'pxe' - - n_shell.do_node_set_boot_device(client_mock, args) - client_mock.node.set_boot_device.assert_called_once_with( - 'node_uuid', 'pxe', False) - - def test_do_node_set_boot_device_persistent(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.persistent = True - args.device = 'disk' - - n_shell.do_node_set_boot_device(client_mock, args) - client_mock.node.set_boot_device.assert_called_once_with( - 'node_uuid', 'disk', True) - - def test_do_node_get_boot_device(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.json = False - - n_shell.do_node_get_boot_device(client_mock, args) - client_mock.node.get_boot_device.assert_called_once_with('node_uuid') - - def test_do_node_inject_nmi(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - - n_shell.do_node_inject_nmi(client_mock, args) - client_mock.node.inject_nmi.assert_called_once_with('node_uuid') - - def test_do_node_get_supported_boot_devices(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.json = False - - n_shell.do_node_get_supported_boot_devices(client_mock, args) - client_mock.node.get_supported_boot_devices.assert_called_once_with( - 'node_uuid') - - def _get_client_mock_args(self, node=None, associated=None, - maintenance=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, provision_state=None, driver=None, - json=False, resource_class=None): - args = mock.MagicMock() - args.node = node - args.associated = associated - args.maintenance = maintenance - args.provision_state = provision_state - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.driver = driver - args.json = json - args.resource_class = resource_class - - return args - - def test_do_node_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(detail=False) - - def test_do_node_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(detail=True) - - def test_do_node_list_provision_state(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(provision_state='wait call-back', - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with( - provision_state='wait call-back', - detail=False) - - def test_do_node_list_detail_provision_state(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(provision_state='wait call-back', - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with( - provision_state='wait call-back', - detail=True) - - def test_do_node_list_driver(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(driver='fake', - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(driver='fake', - detail=False) - - def test_do_node_list_detail_driver(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(driver='fake', - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(driver='fake', - detail=True) - - def test_do_node_list_resource_class(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(resource_class='foo', - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(resource_class='foo', - detail=False) - - def test_do_node_list_detail_resource_class(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(resource_class='foo', - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(resource_class='foo', - detail=True) - - def test_do_node_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='created_at', - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(sort_key='created_at', - detail=False) - - def test_do_node_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='chassis_uuid', - detail=False) - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_list, - client_mock, args) - self.assertFalse(client_mock.node.list.called) - - def test_do_node_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='created_at', - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(sort_key='created_at', - detail=True) - - def test_do_node_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='chassis_uuid', - detail=True) - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_list, - client_mock, args) - self.assertFalse(client_mock.node.list.called) - - def test_do_node_list_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='desc', - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(sort_dir='desc', - detail=False) - - def test_do_node_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='asc', - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(sort_dir='asc', - detail=True) - - def test_do_node_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='abc', - detail=False) - self.assertRaises(exceptions.CommandError, - n_shell.do_node_list, - client_mock, args) - self.assertFalse(client_mock.node.list.called) - - def test_do_node_list_maintenance(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(maintenance=True, - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(maintenance=True, - detail=False) - - def test_do_node_list_detail_maintenance(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(maintenance=True, - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(maintenance=True, - detail=True) - - def test_do_node_list_associated(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(associated=True, - detail=False) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(associated=True, - detail=False) - - def test_do_node_list_detail_associated(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(associated=True, - detail=True) - - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with(associated=True, - detail=True) - - def test_do_node_list_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['uuid', 'provision_state']]) - n_shell.do_node_list(client_mock, args) - client_mock.node.list.assert_called_once_with( - fields=['uuid', 'provision_state'], detail=False) - - def test_do_node_list_invalid_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - n_shell.do_node_list, client_mock, args) - - def test_do_node_show_states(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.json = False - - n_shell.do_node_show_states(client_mock, args) - client_mock.node.states.assert_called_once_with('node_uuid') - - def test_do_node_port_list(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock) - - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, detail=False) - - def test_do_node_port_list_detail(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, detail=True) - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, detail=True) - - def test_do_node_port_list_sort_key(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - sort_key='created_at', - detail=False) - - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, sort_key='created_at', detail=False) - - def test_do_node_port_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - sort_key='node_uuid', - detail=False) - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_port_list, - client_mock, args) - self.assertFalse(client_mock.node.list_ports.called) - - def test_do_node_port_list_detail_sort_key(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - sort_key='created_at', - detail=True) - - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, sort_key='created_at', detail=True) - - def test_do_node_port_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - sort_key='node_uuid', - detail=True) - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_port_list, - client_mock, args) - self.assertFalse(client_mock.node.list_ports.called) - - def test_do_node_port_list_sort_dir(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, sort_dir='desc', - detail=False) - - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, sort_dir='desc', detail=False) - - def test_do_node_port_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, sort_dir='abc', - detail=False) - self.assertRaises(exceptions.CommandError, - n_shell.do_node_port_list, - client_mock, args) - self.assertFalse(client_mock.node.list_ports.called) - - def test_do_node_port_list_fields(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - fields=[['uuid', 'address']]) - n_shell.do_node_port_list(client_mock, args) - client_mock.node.list_ports.assert_called_once_with( - node_mock, fields=['uuid', 'address'], detail=False) - - def test_do_node_port_list_invalid_fields(self): - client_mock = mock.MagicMock() - node_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(node=node_mock, - fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - n_shell.do_node_port_list, client_mock, args) - - def test_do_node_get_vendor_passthru_methods(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - n_shell.do_node_get_vendor_passthru_methods(client_mock, args) - client_mock.node.get_vendor_passthru_methods.assert_called_once_with( - 'node_uuid') - - def test_do_node_vif_list(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - n_shell.do_node_vif_list(client_mock, args) - client_mock.node.vif_list.assert_called_once_with( - 'node_uuid') - - def test_do_node_vif_attach(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.vif_id = 'aaa-aaa' - n_shell.do_node_vif_attach(client_mock, args) - client_mock.node.vif_attach.assert_called_once_with( - 'node_uuid', 'aaa-aaa') - - def test_do_node_vif_attach_custom_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.vif_id = 'aaa-aaa' - args.vif_info = ['aaa=bbb', 'ccc=ddd'] - n_shell.do_node_vif_attach(client_mock, args) - client_mock.node.vif_attach.assert_called_once_with( - 'node_uuid', 'aaa-aaa', aaa='bbb', ccc='ddd') - - def test_do_node_vif_detach(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.vif_id = 'aaa-aaa' - n_shell.do_node_vif_detach(client_mock, args) - client_mock.node.vif_detach.assert_called_once_with( - 'node_uuid', 'aaa-aaa') diff --git a/ironicclient/tests/unit/v1/test_port_shell.py b/ironicclient/tests/unit/v1/test_port_shell.py deleted file mode 100644 index 862b074b7..000000000 --- a/ironicclient/tests/unit/v1/test_port_shell.py +++ /dev/null @@ -1,329 +0,0 @@ -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from oslo_utils import uuidutils - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient.tests.unit import utils -import ironicclient.v1.port_shell as p_shell - - -class PortShellTest(utils.BaseTestCase): - - def test_port_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - port = object() - p_shell._print_port_show(port) - exp = ['address', 'created_at', 'extra', 'node_uuid', - 'physical_network', 'updated_at', 'uuid', 'pxe_enabled', - 'local_link_connection', 'internal_info', 'is_smartnic', - 'portgroup_uuid'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_port_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.address = False - args.fields = None - args.json = False - - p_shell.do_port_show(client_mock, args) - client_mock.port.get.assert_called_once_with('port_uuid', fields=None) - # assert get_by_address() wasn't called - self.assertFalse(client_mock.port.get_by_address.called) - - def test_do_port_show_space_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = ' ' - args.address = False - args.json = False - self.assertRaises(exceptions.CommandError, - p_shell.do_port_show, - client_mock, args) - - def test_do_port_show_empty_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = '' - args.address = False - args.json = False - self.assertRaises(exceptions.CommandError, - p_shell.do_port_show, - client_mock, args) - - def test_do_port_show_by_address(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_address' - args.address = True - args.fields = None - args.json = False - - p_shell.do_port_show(client_mock, args) - client_mock.port.get_by_address.assert_called_once_with('port_address', - fields=None) - # assert get() wasn't called - self.assertFalse(client_mock.port.get.called) - - def test_do_port_show_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.address = False - args.fields = [['uuid', 'address']] - args.json = False - p_shell.do_port_show(client_mock, args) - client_mock.port.get.assert_called_once_with( - 'port_uuid', fields=['uuid', 'address']) - - def test_do_port_show_invalid_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.address = False - args.fields = [['foo', 'bar']] - args.json = False - self.assertRaises(exceptions.CommandError, - p_shell.do_port_show, - client_mock, args) - - def test_do_port_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - - p_shell.do_port_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.port.update.assert_called_once_with('port_uuid', patch) - - def test_do_port_update_wrong_op(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.op = 'foo' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - self.assertRaises(exceptions.CommandError, - p_shell.do_port_update, - client_mock, args) - self.assertFalse(client_mock.port.update.called) - - def _get_client_mock_args(self, address=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, json=False): - args = mock.MagicMock(spec=True) - args.address = address - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.json = json - - return args - - def test_do_port_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(detail=False) - - def test_do_port_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(detail=True) - - def test_do_port_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=False) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(sort_key='uuid', - detail=False) - - def test_do_port_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', detail=False) - - self.assertRaises(exceptions.CommandError, - p_shell.do_port_list, - client_mock, args) - self.assertFalse(client_mock.port.list.called) - - def test_do_port_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=True) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(sort_key='uuid', - detail=True) - - def test_do_port_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', - detail=True) - - self.assertRaises(exceptions.CommandError, - p_shell.do_port_list, - client_mock, args) - self.assertFalse(client_mock.port.list.called) - - def test_do_port_list_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['uuid', 'address']]) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with( - fields=['uuid', 'address'], detail=False) - - def test_do_port_list_invalid_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - p_shell.do_port_list, - client_mock, args) - - def test_do_port_list_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='desc', - detail=False) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(sort_dir='desc', - detail=False) - - def test_do_port_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='asc', - detail=True) - - p_shell.do_port_list(client_mock, args) - client_mock.port.list.assert_called_once_with(sort_dir='asc', - detail=True) - - def test_do_port_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='abc', - detail=False) - self.assertRaises(exceptions.CommandError, - p_shell.do_port_list, - client_mock, args) - self.assertFalse(client_mock.port.list.called) - - def test_do_port_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - p_shell.do_port_create(client_mock, args) - client_mock.port.create.assert_called_once_with() - - def test_do_port_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = uuidutils.generate_uuid() - args.json = False - - p_shell.do_port_create(client_mock, args) - client_mock.port.create.assert_called_once_with(uuid=args.uuid) - - def test_do_port_create_valid_fields_values(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.address = 'address' - args.node_uuid = 'uuid' - args.extra = ["key1=val1", "key2=val2"] - args.json = False - p_shell.do_port_create(client_mock, args) - client_mock.port.create.assert_called_once_with( - address='address', node_uuid='uuid', extra={'key1': 'val1', - 'key2': 'val2'}) - - def test_do_port_create_invalid_extra_fields_values(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.address = 'address' - args.node_uuid = 'uuid' - args.extra = ["foo"] - args.json = False - self.assertRaises(exceptions.CommandError, - p_shell.do_port_create, client_mock, args) - - def test_do_port_create_portgroup_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.address = 'address' - args.node_uuid = 'uuid' - args.portgroup_uuid = 'portgroup-uuid' - args.json = False - p_shell.do_port_create(client_mock, args) - client_mock.port.create.assert_called_once_with( - address='address', node_uuid='uuid', - portgroup_uuid='portgroup-uuid') - - def test_do_port_create_physical_network(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.address = 'address' - args.node_uuid = 'uuid' - args.physical_network = 'physnet1' - args.json = False - p_shell.do_port_create(client_mock, args) - client_mock.port.create.assert_called_once_with( - address='address', node_uuid='uuid', - physical_network='physnet1') - - def test_do_port_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = ['port_uuid'] - p_shell.do_port_delete(client_mock, args) - client_mock.port.delete.assert_called_once_with('port_uuid') - - def test_do_port_delete_multiple(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = ['port_uuid', 'port_uuid2'] - p_shell.do_port_delete(client_mock, args) - client_mock.port.delete.assert_has_calls( - [mock.call('port_uuid'), mock.call('port_uuid2')]) - - def test_do_port_delete_multiple_with_exception(self): - client_mock = mock.MagicMock() - client_mock.port.delete.side_effect = ( - [exceptions.ClientException, None]) - args = mock.MagicMock() - args.port = ['port_uuid', 'port_uuid2'] - - self.assertRaises(exceptions.ClientException, - p_shell.do_port_delete, client_mock, args) - client_mock.port.delete.assert_has_calls( - [mock.call('port_uuid'), mock.call('port_uuid2')]) diff --git a/ironicclient/tests/unit/v1/test_portgroup.py b/ironicclient/tests/unit/v1/test_portgroup.py index 5ac1fd8b4..8ee198e54 100644 --- a/ironicclient/tests/unit/v1/test_portgroup.py +++ b/ironicclient/tests/unit/v1/test_portgroup.py @@ -15,13 +15,10 @@ import copy -import mock import testtools -from ironicclient.common.apiclient import exceptions from ironicclient.tests.unit import utils import ironicclient.v1.portgroup -import ironicclient.v1.portgroup_shell as pg_shell PORTGROUP = {'uuid': '11111111-2222-3333-4444-555555555555', 'name': 'Portgroup-name', @@ -284,25 +281,6 @@ class PortgroupManagerTest(testtools.TestCase): self.api.responses['/v1/portgroups/%s' % PORTGROUP['uuid']]['GET']) - def test_do_portgroup_delete_multiple_with_exception(self): - client_mock = mock.MagicMock() - client_mock.portgroup.delete.side_effect = ( - [exceptions.ClientException, None]) - args = mock.MagicMock() - args.portgroup = ['pg_uuid1', 'pg_uuid2'] - - self.assertRaises(exceptions.ClientException, - pg_shell.do_portgroup_delete, - client_mock, args) - client_mock.portgroup.delete.assert_has_calls( - [mock.call('pg_uuid1'), mock.call('pg_uuid2')]) - - expected_resp = ({}, PORTGROUP,) - self.assertEqual( - expected_resp, - self.api.responses['/v1/portgroups/%s' - % PORTGROUP['uuid']]['GET']) - def test_update(self): patch = {'op': 'replace', 'value': NEW_ADDR, diff --git a/ironicclient/tests/unit/v1/test_portgroup_shell.py b/ironicclient/tests/unit/v1/test_portgroup_shell.py deleted file mode 100644 index 4a7a1a6b0..000000000 --- a/ironicclient/tests/unit/v1/test_portgroup_shell.py +++ /dev/null @@ -1,298 +0,0 @@ -# Copyright 2016 SAP Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient.tests.unit import utils -import ironicclient.v1.portgroup_shell as pg_shell - - -class PortgroupShellTest(utils.BaseTestCase): - - def test_portgroup_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - portgroup = object() - pg_shell._print_portgroup_show(portgroup) - exp = ['address', 'created_at', 'extra', 'standalone_ports_supported', - 'node_uuid', 'updated_at', 'uuid', 'name', 'internal_info', - 'mode', 'properties'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_portgroup_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = 'portgroup_uuid' - args.address = False - args.fields = None - args.json = False - - pg_shell.do_portgroup_show(client_mock, args) - client_mock.portgroup.get.assert_called_once_with('portgroup_uuid', - fields=None) - self.assertFalse(client_mock.portgroup.get_by_address.called) - - def test_do_portgroup_show_space_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = ' ' - args.address = False - args.json = False - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_show, - client_mock, args) - - def test_do_portgroup_show_empty_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = '' - args.address = False - args.json = False - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_show, - client_mock, args) - - def test_do_portgroup_show_by_address(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = 'portgroup_address' - args.address = True - args.fields = None - args.json = False - - pg_shell.do_portgroup_show(client_mock, args) - client_mock.portgroup.get_by_address.assert_called_once_with( - 'portgroup_address', fields=None) - self.assertFalse(client_mock.portgroup.get.called) - - def test_do_portgroup_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = 'portgroup_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - - pg_shell.do_portgroup_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.portgroup.update.assert_called_once_with('portgroup_uuid', - patch) - - def _get_client_mock_args(self, address=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, node=None, json=False, - portgroup=None): - args = mock.MagicMock(spec=True) - args.address = address - args.node = node - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.json = json - args.portgroup = portgroup - - return args - - def test_do_portgroup_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - pg_shell.do_portgroup_list(client_mock, args) - client_mock.portgroup.list.assert_called_once_with(detail=False) - - def test_do_portgroup_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - pg_shell.do_portgroup_list(client_mock, args) - client_mock.portgroup.list.assert_called_once_with(detail=True) - - def test_do_portgroup_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=False) - - pg_shell.do_portgroup_list(client_mock, args) - client_mock.portgroup.list.assert_called_once_with(sort_key='uuid', - detail=False) - - def test_do_portgroup_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', - detail=False) - - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list.called) - - def test_do_portgroup_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=True) - - pg_shell.do_portgroup_list(client_mock, args) - client_mock.portgroup.list.assert_called_once_with(sort_key='uuid', - detail=True) - - def test_do_portgroup_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', - detail=True) - - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list.called) - - def test_do_portgroup_port_list(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock) - - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=False) - - def test_do_portgroup_port_list_detail(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, detail=True) - - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=True) - - def test_do_portgroup_port_list_sort_key(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_key='created_at') - - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=False, sort_key='created_at') - - def test_do_portgroup_port_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_key='node_uuid') - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_port_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list_ports.called) - - def test_do_portgroup_port_list_detail_sort_key(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_key='created_at', - detail=True) - - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=True, sort_key='created_at') - - def test_do_portgroup_port_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_key='node_uuid', - detail=True) - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_port_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list_ports.called) - - def test_do_portgroup_port_list_sort_dir(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_dir='desc') - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=False, sort_dir='desc') - - def test_do_portgroup_port_list_wrong_sort_dir(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - sort_dir='abc') - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_port_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list_ports.called) - - def test_do_portgroup_port_list_fields(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - fields=[['uuid', 'address']]) - pg_shell.do_portgroup_port_list(client_mock, args) - client_mock.portgroup.list_ports.assert_called_once_with( - pg_mock, detail=False, fields=['uuid', 'address']) - - def test_do_portgroup_port_list_wrong_fields(self): - client_mock = mock.MagicMock() - pg_mock = mock.MagicMock(spec_set=[]) - args = self._get_client_mock_args(portgroup=pg_mock, - fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - pg_shell.do_portgroup_port_list, - client_mock, args) - self.assertFalse(client_mock.portgroup.list_ports.called) - - def test_do_portgroup_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - pg_shell.do_portgroup_create(client_mock, args) - client_mock.portgroup.create.assert_called_once_with() - - def test_do_portgroup_address(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.address = 'aa:bb:cc:dd:ee:ff' - args.mode = '802.3ad' - args.properties = ['xmit_hash_policy=layer3+4', 'miimon=100'] - args.json = False - pg_shell.do_portgroup_create(client_mock, args) - client_mock.portgroup.create.assert_called_once_with( - address='aa:bb:cc:dd:ee:ff', mode='802.3ad', - properties={'xmit_hash_policy': 'layer3+4', 'miimon': 100}) - - def test_do_portgroup_node_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node_uuid = 'node-uuid' - args.json = False - pg_shell.do_portgroup_create(client_mock, args) - client_mock.portgroup.create.assert_called_once_with( - node_uuid='node-uuid') - - def test_do_portgroup_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.portgroup = ['portgroup_uuid'] - pg_shell.do_portgroup_delete(client_mock, args) - client_mock.portgroup.delete.assert_called_once_with('portgroup_uuid') diff --git a/ironicclient/tests/unit/v1/test_volume_connector_shell.py b/ironicclient/tests/unit/v1/test_volume_connector_shell.py deleted file mode 100644 index 495cc7750..000000000 --- a/ironicclient/tests/unit/v1/test_volume_connector_shell.py +++ /dev/null @@ -1,284 +0,0 @@ -# Copyright 2017 Hitachi Data Systems -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from oslo_utils import uuidutils - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient.tests.unit import utils -import ironicclient.v1.volume_connector_shell as vc_shell - - -class Volume_ConnectorShellTest(utils.BaseTestCase): - - def test_volume_connector_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - volume_connector = object() - vc_shell._print_volume_connector_show(volume_connector) - exp = ['created_at', 'extra', 'node_uuid', 'type', 'updated_at', - 'uuid', 'connector_id'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_volume_connector_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = 'volume_connector_uuid' - args.fields = None - args.json = False - - vc_shell.do_volume_connector_show(client_mock, args) - client_mock.volume_connector.get.assert_called_once_with( - 'volume_connector_uuid', fields=None) - - def test_do_volume_connector_show_space_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = ' ' - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_show, - client_mock, args) - - def test_do_volume_connector_show_empty_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = '' - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_show, - client_mock, args) - - def test_do_volume_connector_show_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = 'volume_connector_uuid' - args.fields = [['uuid', 'connector_id']] - args.json = False - vc_shell.do_volume_connector_show(client_mock, args) - client_mock.volume_connector.get.assert_called_once_with( - 'volume_connector_uuid', fields=['uuid', 'connector_id']) - - def test_do_volume_connector_show_invalid_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = 'volume_connector_uuid' - args.fields = [['foo', 'bar']] - args.json = False - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_show, - client_mock, args) - - def test_do_volume_connector_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = 'volume_connector_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - - vc_shell.do_volume_connector_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.volume_connector.update.assert_called_once_with( - 'volume_connector_uuid', patch) - - def test_do_volume_connector_update_wrong_op(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = 'volume_connector_uuid' - args.op = 'foo' - args.attributes = [['arg1=val1', 'arg2=val2']] - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_update, - client_mock, args) - self.assertFalse(client_mock.volume_connector.update.called) - - def _get_client_mock_args(self, node=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, json=False): - args = mock.MagicMock(spec=True) - args.node = node - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.json = json - - return args - - def test_do_volume_connector_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with(detail=False) - - def test_do_volume_connector_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with(detail=True) - - def test_do_volume_connector_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=False) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with( - sort_key='uuid', detail=False) - - def test_do_volume_connector_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', detail=False) - - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_list, - client_mock, args) - self.assertFalse(client_mock.volume_connector.list.called) - - def test_do_volume_connector_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', - detail=True) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with( - sort_key='uuid', detail=True) - - def test_do_volume_connector_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', - detail=True) - - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_list, - client_mock, args) - self.assertFalse(client_mock.volume_connector.list.called) - - def test_do_volume_connector_list_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['uuid', 'connector_id']]) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with( - fields=['uuid', 'connector_id'], detail=False) - - def test_do_volume_connector_list_invalid_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_list, - client_mock, args) - - def test_do_volume_connector_list_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='desc', detail=False) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with( - sort_dir='desc', detail=False) - - def test_do_volume_connector_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='asc', detail=True) - - vc_shell.do_volume_connector_list(client_mock, args) - client_mock.volume_connector.list.assert_called_once_with( - sort_dir='asc', detail=True) - - def test_do_volume_connector_wrong_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='abc', detail=False) - - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_list, - client_mock, args) - self.assertFalse(client_mock.volume_connector.list.called) - - def test_do_volume_connector_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - vc_shell.do_volume_connector_create(client_mock, args) - client_mock.volume_connector.create.assert_called_once_with() - - def test_do_volume_connector_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = uuidutils.generate_uuid() - args.json = False - - vc_shell.do_volume_connector_create(client_mock, args) - client_mock.volume_connector.create.assert_called_once_with( - uuid=args.uuid) - - def test_do_volume_connector_create_valid_fields_values(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.type = 'type' - args.connector_id = 'connector_id' - args.node_uuid = 'uuid' - args.extra = ["key1=val1", "key2=val2"] - args.json = False - vc_shell.do_volume_connector_create(client_mock, args) - client_mock.volume_connector.create.assert_called_once_with( - type='type', connector_id='connector_id', node_uuid='uuid', - extra={'key1': 'val1', 'key2': 'val2'}) - - def test_do_volume_connector_create_invalid_extra_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.type = 'type' - args.connector_id = 'connector_id' - args.node_uuid = 'uuid' - args.extra = ["foo"] - args.json = False - self.assertRaises(exceptions.CommandError, - vc_shell.do_volume_connector_create, - client_mock, args) - - def test_do_volume_connector_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = ['volume_connector_uuid'] - vc_shell.do_volume_connector_delete(client_mock, args) - client_mock.volume_connector.delete.assert_called_once_with( - 'volume_connector_uuid') - - def test_do_volume_connector_delete_multi(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = ['uuid1', 'uuid2'] - vc_shell.do_volume_connector_delete(client_mock, args) - self.assertEqual([mock.call('uuid1'), mock.call('uuid2')], - client_mock.volume_connector.delete.call_args_list) - - def test_do_volume_connector_delete_multi_error(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_connector = ['uuid1', 'uuid2'] - client_mock.volume_connector.delete.side_effect = [ - exceptions.ClientException('error'), None] - self.assertRaises(exceptions.ClientException, - vc_shell.do_volume_connector_delete, - client_mock, args) - self.assertEqual([mock.call('uuid1'), mock.call('uuid2')], - client_mock.volume_connector.delete.call_args_list) diff --git a/ironicclient/tests/unit/v1/test_volume_target_shell.py b/ironicclient/tests/unit/v1/test_volume_target_shell.py deleted file mode 100644 index 15e5c4b23..000000000 --- a/ironicclient/tests/unit/v1/test_volume_target_shell.py +++ /dev/null @@ -1,288 +0,0 @@ -# Copyright 2017 Hitachi, Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from oslo_utils import uuidutils - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common import utils as commonutils -from ironicclient.tests.unit import utils -import ironicclient.v1.volume_target_shell as vt_shell - - -class Volume_TargetShellTest(utils.BaseTestCase): - - def test_volume_target_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - volume_target = object() - vt_shell._print_volume_target_show(volume_target) - exp = ['created_at', 'extra', 'node_uuid', 'volume_type', - 'updated_at', 'uuid', 'properties', 'boot_index', - 'volume_id'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_volume_target_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = 'volume_target_uuid' - args.fields = None - args.json = False - - vt_shell.do_volume_target_show(client_mock, args) - client_mock.volume_target.get.assert_called_once_with( - 'volume_target_uuid', fields=None) - - def test_do_volume_target_show_space_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = ' ' - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_show, - client_mock, args) - - def test_do_volume_target_show_empty_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = '' - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_show, - client_mock, args) - - def test_do_volume_target_show_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = 'volume_target_uuid' - args.fields = [['uuid', 'boot_index']] - args.json = False - vt_shell.do_volume_target_show(client_mock, args) - client_mock.volume_target.get.assert_called_once_with( - 'volume_target_uuid', fields=['uuid', 'boot_index']) - - def test_do_volume_target_show_invalid_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = 'volume_target_uuid' - args.fields = [['foo', 'bar']] - args.json = False - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_show, - client_mock, args) - - def test_do_volume_target_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = 'volume_target_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - args.json = False - - vt_shell.do_volume_target_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.volume_target.update.assert_called_once_with( - 'volume_target_uuid', patch) - - def test_do_volume_target_update_wrong_op(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = 'volume_target_uuid' - args.op = 'foo' - args.attributes = [['arg1=val1', 'arg2=val2']] - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_update, - client_mock, args) - self.assertFalse(client_mock.volume_target.update.called) - - def _get_client_mock_args(self, node=None, marker=None, limit=None, - sort_dir=None, sort_key=None, detail=False, - fields=None, json=False): - args = mock.MagicMock(spec=True) - args.node = node - args.marker = marker - args.limit = limit - args.sort_dir = sort_dir - args.sort_key = sort_key - args.detail = detail - args.fields = fields - args.json = json - - return args - - def test_do_volume_target_list(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args() - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with(detail=False) - - def test_do_volume_target_list_detail(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(detail=True) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with(detail=True) - - def test_do_volume_target_list_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', detail=False) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with( - sort_key='uuid', detail=False) - - def test_do_volume_target_list_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', detail=False) - - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_list, - client_mock, args) - self.assertFalse(client_mock.volume_target.list.called) - - def test_do_volume_target_list_detail_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='uuid', detail=True) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with( - sort_key='uuid', detail=True) - - def test_do_volume_target_list_detail_wrong_sort_key(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_key='node_uuid', detail=True) - - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_list, - client_mock, args) - self.assertFalse(client_mock.volume_target.list.called) - - def test_do_volume_target_list_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['uuid', 'boot_index']]) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with( - fields=['uuid', 'boot_index'], detail=False) - - def test_do_volume_target_list_invalid_fields(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(fields=[['foo', 'bar']]) - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_list, - client_mock, args) - - def test_do_volume_target_list_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='desc', detail=False) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with( - sort_dir='desc', detail=False) - - def test_do_volume_target_list_detail_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='asc', detail=True) - - vt_shell.do_volume_target_list(client_mock, args) - client_mock.volume_target.list.assert_called_once_with( - sort_dir='asc', detail=True) - - def test_do_volume_target_wrong_sort_dir(self): - client_mock = mock.MagicMock() - args = self._get_client_mock_args(sort_dir='abc', detail=False) - - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_list, - client_mock, args) - self.assertFalse(client_mock.volume_target.list.called) - - def test_do_volume_target_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.json = False - vt_shell.do_volume_target_create(client_mock, args) - client_mock.volume_target.create.assert_called_once_with() - - def test_do_volume_target_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = uuidutils.generate_uuid() - args.json = False - - vt_shell.do_volume_target_create(client_mock, args) - client_mock.volume_target.create.assert_called_once_with( - uuid=args.uuid) - - def test_do_volume_target_create_valid_fields_values(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_type = 'volume_type' - args.properties = ["key1=val1", "key2=val2"] - args.boot_index = 100 - args.node_uuid = 'uuid' - args.volume_id = 'volume_id' - args.extra = ["key1=val1", "key2=val2"] - args.json = False - vt_shell.do_volume_target_create(client_mock, args) - client_mock.volume_target.create.assert_called_once_with( - volume_type='volume_type', - properties={'key1': 'val1', 'key2': 'val2'}, - boot_index=100, node_uuid='uuid', volume_id='volume_id', - extra={'key1': 'val1', 'key2': 'val2'}) - - def test_do_volume_target_create_invalid_extra_fields(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_type = 'volume_type' - args.properties = ["key1=val1", "key2=val2"] - args.boot_index = 100 - args.node_uuid = 'uuid' - args.volume_id = 'volume_id' - args.extra = ["foo"] - args.json = False - self.assertRaises(exceptions.CommandError, - vt_shell.do_volume_target_create, - client_mock, args) - - def test_do_volume_target_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = ['volume_target_uuid'] - vt_shell.do_volume_target_delete(client_mock, args) - client_mock.volume_target.delete.assert_called_once_with( - 'volume_target_uuid') - - def test_do_volume_target_delete_multi(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = ['uuid1', 'uuid2'] - vt_shell.do_volume_target_delete(client_mock, args) - self.assertEqual([mock.call('uuid1'), mock.call('uuid2')], - client_mock.volume_target.delete.call_args_list) - - def test_do_volume_target_delete_multi_error(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.volume_target = ['uuid1', 'uuid2'] - client_mock.volume_target.delete.side_effect = [ - exceptions.ClientException('error'), None] - self.assertRaises(exceptions.ClientException, - vt_shell.do_volume_target_delete, - client_mock, args) - self.assertEqual([mock.call('uuid1'), mock.call('uuid2')], - client_mock.volume_target.delete.call_args_list) diff --git a/ironicclient/v1/chassis_shell.py b/ironicclient/v1/chassis_shell.py deleted file mode 100644 index bc5c85245..000000000 --- a/ironicclient/v1/chassis_shell.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import cliutils -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_chassis_show(chassis, fields=None, json=False): - if fields is None: - fields = res_fields.CHASSIS_DETAILED_RESOURCE.fields - - data = dict([(f, getattr(chassis, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg('chassis', metavar='', help="UUID of the chassis.") -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more chassis fields. Only these fields will be fetched from " - "the server.") -def do_chassis_show(cc, args): - """Show detailed information about a chassis.""" - utils.check_empty_arg(args.chassis, '') - fields = args.fields[0] if args.fields else None - utils.check_for_invalid_fields( - fields, res_fields.CHASSIS_DETAILED_RESOURCE.fields) - chassis = cc.chassis.get(args.chassis, fields=fields) - _print_chassis_show(chassis, fields=fields, json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the chassis.") -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of chassis to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Chassis UUID (for example, of the last chassis in the list ' - 'from a previous request). Returns the list of chassis ' - 'after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Chassis field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more chassis fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -def do_chassis_list(cc, args): - """List the chassis.""" - if args.detail: - fields = res_fields.CHASSIS_DETAILED_RESOURCE.fields - field_labels = res_fields.CHASSIS_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.CHASSIS_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.CHASSIS_RESOURCE.fields - field_labels = res_fields.CHASSIS_RESOURCE.labels - - sort_fields = res_fields.CHASSIS_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.CHASSIS_DETAILED_RESOURCE.sort_labels - - params = utils.common_params_for_list(args, sort_fields, - sort_field_labels) - - chassis = cc.chassis.list(**params) - cliutils.print_list(chassis, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg( - '-d', '--description', - metavar='', - help='Description of the chassis.') -@cliutils.arg( - '-e', '--extra', - metavar="", - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -@cliutils.arg( - '-u', '--uuid', - metavar='', - help="UUID of the chassis.") -def do_chassis_create(cc, args): - """Create a new chassis.""" - field_list = ['description', 'extra', 'uuid'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - chassis = cc.chassis.create(**fields) - - data = dict([(f, getattr(chassis, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg( - 'chassis', - metavar='', - nargs='+', - help="UUID of the chassis.") -def do_chassis_delete(cc, args): - """Delete a chassis.""" - for c in args.chassis: - cc.chassis.delete(c) - print('Deleted chassis %s' % c) - - -@cliutils.arg('chassis', metavar='', help="UUID of the chassis.") -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified " - "multiple times. For 'remove', only is necessary.") -def do_chassis_update(cc, args): - """Update information about a chassis.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - chassis = cc.chassis.update(args.chassis, patch) - _print_chassis_show(chassis, json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the nodes.") -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of nodes to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Node UUID (for example, of the last node in the list from ' - 'a previous request). Returns the list of nodes after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Node field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg('chassis', metavar='', help="UUID of the chassis.") -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more node fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -@cliutils.arg( - '--maintenance', - metavar='', - help="List nodes in maintenance mode: 'true' or 'false'.") -@cliutils.arg( - '--associated', - metavar='', - help="List nodes by instance association: 'true' or 'false'.") -@cliutils.arg( - '--provision-state', - metavar='', - help="List nodes in specified provision state.") -def do_chassis_node_list(cc, args): - """List the nodes contained in a chassis.""" - params = {} - if args.associated is not None: - params['associated'] = utils.bool_argument_value("--associated", - args.associated) - if args.maintenance is not None: - params['maintenance'] = utils.bool_argument_value("--maintenance", - args.maintenance) - if args.provision_state is not None: - params['provision_state'] = args.provision_state - - if args.detail: - fields = res_fields.NODE_DETAILED_RESOURCE.fields - field_labels = res_fields.NODE_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.NODE_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.NODE_RESOURCE.fields - field_labels = res_fields.NODE_RESOURCE.labels - - sort_fields = res_fields.NODE_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.NODE_DETAILED_RESOURCE.sort_labels - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - - nodes = cc.chassis.list_nodes(args.chassis, **params) - cliutils.print_list(nodes, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) diff --git a/ironicclient/v1/create_resources_shell.py b/ironicclient/v1/create_resources_shell.py deleted file mode 100644 index 03c86282d..000000000 --- a/ironicclient/v1/create_resources_shell.py +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import cliutils -from ironicclient.v1 import create_resources - - -@cliutils.arg('resource_files', nargs='+', metavar='', default=[], - help='File (.yaml or .json) containing descriptions of the ' - 'resources to create. Can be specified multiple times.') -def do_create(cc, args): - """Create baremetal resources (chassis, nodes, port groups and ports). - - The resources may be described in one or more JSON or YAML files. If any - file cannot be validated, no resources are created. An attempt is made to - create all the resources; those that could not be created are skipped - (with a corresponding error message). - """ - create_resources.create_resources(cc, args.resource_files) diff --git a/ironicclient/v1/driver_shell.py b/ironicclient/v1/driver_shell.py deleted file mode 100644 index ba857768e..000000000 --- a/ironicclient/v1/driver_shell.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from ironicclient.common import cliutils -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields -from ironicclient.v1 import utils as v1_utils - - -def _print_driver_show(driver, json=False): - fields = res_fields.DRIVER_DETAILED_RESOURCE.fields - data = dict([(f, getattr(driver, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg('-t', '--type', - metavar='', - choices=["classic", "dynamic"], - help='Type of driver ("classic" or "dynamic"). ' - 'The default is to list all of them.') -@cliutils.arg('--detail', - dest='detail', - action='store_true', - default=None, - help="Show detailed information about the drivers.") -def do_driver_list(cc, args): - """List the enabled drivers.""" - drivers = cc.driver.list(driver_type=args.type, detail=args.detail) - # NOTE(lucasagomes): For list-type properties, show the values as - # comma separated strings. It's easier to read. - data = [utils.convert_list_props_to_comma_separated(d._info) - for d in drivers] - - if args.detail: - field_labels = res_fields.DRIVER_DETAILED_RESOURCE.labels - fields = res_fields.DRIVER_DETAILED_RESOURCE.fields - else: - field_labels = res_fields.DRIVER_RESOURCE.labels - fields = res_fields.DRIVER_RESOURCE.fields - - cliutils.print_list(data, fields, field_labels=field_labels, - json_flag=args.json) - - -@cliutils.arg('driver_name', metavar='', - help='Name of the driver.') -def do_driver_show(cc, args): - """Show information about a driver.""" - driver = cc.driver.get(args.driver_name) - _print_driver_show(driver, json=args.json) - - -@cliutils.arg('driver_name', metavar='', - help="Name of the driver.") -@cliutils.arg('--wrap', dest='wrap', metavar='', - type=int, default=0, - help=('Wrap the output to a specified length. ' - 'Positive number can realize wrap functionality. ' - '0 is default for disabled.')) -def do_driver_properties(cc, args): - """Get properties of a driver.""" - properties = cc.driver.properties(args.driver_name) - cliutils.print_dict( - properties, - wrap=args.wrap, - dict_value='Description', - json_flag=args.json) - - -@cliutils.arg('driver_name', metavar='', - help="Name of the driver.") -@cliutils.arg('--wrap', dest='wrap', metavar='', - type=int, default=0, - help=('Wrap the output to a specified length. ' - 'Positive number can realize wrap functionality. ' - '0 is default for disabled.')) -def do_driver_raid_logical_disk_properties(cc, args): - """Get RAID logical disk properties for a driver.""" - properties = cc.driver.raid_logical_disk_properties(args.driver_name) - cliutils.print_dict( - properties, - wrap=args.wrap, - dict_value='Description') - - -@cliutils.arg('driver_name', - metavar='', - help='Name of the driver.') -@cliutils.arg('method', - metavar='', - help="Vendor-passthru method to be called.") -@cliutils.arg('arguments', - metavar='', - nargs='*', - action='append', - default=[], - help="Argument to be passed to the vendor-passthru method. " - "Can be specified multiple times.") -@cliutils.arg('--http-method', - metavar='', - choices=v1_utils.HTTP_METHODS, - help=("The HTTP method to use in the request. Valid HTTP " - "methods are: %s. Defaults to 'POST'." % - ', '.join(v1_utils.HTTP_METHODS))) -@cliutils.arg('--http_method', - help=argparse.SUPPRESS) -def do_driver_vendor_passthru(cc, args): - """Call a vendor-passthru extension for a driver.""" - arguments = utils.key_value_pairs_to_dict(args.arguments[0]) - - resp = cc.driver.vendor_passthru(args.driver_name, args.method, - http_method=args.http_method, - args=arguments) - if resp: - # Print the raw response we don't know how it should be formated - print(str(resp.to_dict())) - - -@cliutils.arg('driver_name', - metavar='', - help='Name of the driver.') -def do_driver_get_vendor_passthru_methods(cc, args): - """Get the vendor passthru methods for a driver.""" - methods = cc.driver.get_vendor_passthru_methods(args.driver_name) - data = [] - for method, response in methods.items(): - response['name'] = method - http_methods = ','.join(response['http_methods']) - response['http_methods'] = http_methods - data.append(response) - fields = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.fields - field_labels = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.labels - cliutils.print_list(data, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) diff --git a/ironicclient/v1/node_shell.py b/ironicclient/v1/node_shell.py deleted file mode 100644 index 8f0713fae..000000000 --- a/ironicclient/v1/node_shell.py +++ /dev/null @@ -1,716 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import six - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient import exc -from ironicclient.v1 import resource_fields as res_fields -from ironicclient.v1 import utils as v1_utils - - -def _print_node_show(node, fields=None, json=False): - if fields is None: - fields = res_fields.NODE_DETAILED_RESOURCE.fields - - data = dict( - [(f, getattr(node, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg( - 'node', - metavar='', - help="Name or UUID of the node " - "(or instance UUID if --instance is specified).") -@cliutils.arg( - '--instance', - dest='instance_uuid', - action='store_true', - default=False, - help=' is an instance UUID.') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more node fields. Only these fields will be fetched from " - "the server.") -def do_node_show(cc, args): - """Show detailed information about a node.""" - fields = args.fields[0] if args.fields else None - utils.check_empty_arg(args.node, '') - utils.check_for_invalid_fields( - fields, res_fields.NODE_DETAILED_RESOURCE.fields) - if args.instance_uuid: - node = cc.node.get_by_instance_uuid(args.node, fields=fields) - else: - node = cc.node.get(args.node, fields=fields) - _print_node_show(node, fields=fields, json=args.json) - - -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of nodes to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Node UUID (for example, of the last node in the list from ' - 'a previous request). Returns the list of nodes after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Node field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - '--maintenance', - metavar='', - help="List nodes in maintenance mode: 'true' or 'false'.") -@cliutils.arg( - '--associated', - metavar='', - help="List nodes by instance association: 'true' or 'false'.") -@cliutils.arg( - '--provision-state', - metavar='', - help="List nodes in specified provision state.") -@cliutils.arg( - '--driver', - metavar='', - help="List nodes using specified driver.") -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the nodes.") -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more node fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -@cliutils.arg( - '--resource-class', - dest='resource_class', - metavar='', - help="List nodes using specified resource class.") -def do_node_list(cc, args): - """List the nodes which are registered with the Ironic service.""" - params = {} - if args.associated is not None: - params['associated'] = utils.bool_argument_value("--associated", - args.associated) - if args.maintenance is not None: - params['maintenance'] = utils.bool_argument_value("--maintenance", - args.maintenance) - if args.provision_state is not None: - params['provision_state'] = args.provision_state - - if args.driver is not None: - params['driver'] = args.driver - - if args.resource_class is not None: - params['resource_class'] = args.resource_class - - if args.detail: - fields = res_fields.NODE_DETAILED_RESOURCE.fields - field_labels = res_fields.NODE_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.NODE_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.NODE_RESOURCE.fields - field_labels = res_fields.NODE_RESOURCE.labels - - sort_fields = res_fields.NODE_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.NODE_DETAILED_RESOURCE.sort_labels - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - nodes = cc.node.list(**params) - cliutils.print_list(nodes, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg( - '-c', '--chassis', - dest='chassis_uuid', - metavar='', - help='UUID of the chassis that this node belongs to.') -@cliutils.arg( - '--chassis_uuid', - help=argparse.SUPPRESS) -@cliutils.arg( - '-d', '--driver', - metavar='', - required=True, - help='Driver used to control the node.') -@cliutils.arg( - '-i', '--driver-info', - metavar='', - action='append', - help='Key/value pair used by the driver, such as out-of-band management ' - 'credentials. Can be specified multiple times.') -@cliutils.arg( - '--driver_info', - action='append', - help=argparse.SUPPRESS) -@cliutils.arg( - '-p', '--properties', - metavar='', - action='append', - help='Key/value pair describing the physical characteristics of the ' - 'node. This is exported to Nova and used by the scheduler. ' - 'Can be specified multiple times.') -@cliutils.arg( - '-e', '--extra', - metavar='', - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -@cliutils.arg( - '-u', '--uuid', - metavar='', - help="Unique UUID for the node.") -@cliutils.arg( - '-n', '--name', - metavar='', - help="Unique name for the node.") -@cliutils.arg( - '--boot-interface', - metavar='', - help='Boot interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--console-interface', - metavar='', - help='Console interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--deploy-interface', - metavar='', - help='Deploy interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--inspect-interface', - metavar='', - help='Inspect interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--management-interface', - metavar='', - help='Management interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--network-interface', - metavar='', - help='Network interface used for switching node to cleaning/provisioning ' - 'networks.') -@cliutils.arg( - '--power-interface', - metavar='', - help='Power interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--raid-interface', - metavar='', - help='RAID interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--storage-interface', - metavar='', - help='Storage interface used by the node\'s driver.') -@cliutils.arg( - '--vendor-interface', - metavar='', - help='Vendor interface used by the node\'s driver. This is ' - 'only applicable when the specified --driver is a ' - 'hardware type.') -@cliutils.arg( - '--resource-class', - metavar='', - help='Resource class for classifying or grouping nodes. Used, for ' - 'example, to classify nodes in Nova\'s placement engine.') -def do_node_create(cc, args): - """Register a new node with the Ironic service.""" - field_list = ['chassis_uuid', 'driver', 'driver_info', - 'properties', 'extra', 'uuid', 'name', - 'boot_interface', 'console_interface', - 'deploy_interface', 'inspect_interface', - 'management_interface', 'network_interface', - 'power_interface', 'raid_interface', - 'storage_interface', 'vendor_interface', - 'resource_class'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'driver_info') - fields = utils.args_array_to_dict(fields, 'extra') - fields = utils.args_array_to_dict(fields, 'properties') - node = cc.node.create(**fields) - - data = dict([(f, getattr(node, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg('node', - metavar='', - nargs='+', - help="Name or UUID of the node.") -def do_node_delete(cc, args): - """Unregister node(s) from the Ironic service. - - Returns errors for any nodes that could not be unregistered. - """ - - failures = [] - for n in args.node: - try: - cc.node.delete(n) - print(_('Deleted node %s') % n) - except exceptions.ClientException as e: - failures.append(_("Failed to delete node %(node)s: %(error)s") - % {'node': n, 'error': e}) - if failures: - raise exceptions.ClientException("\n".join(failures)) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified " - "multiple times. For 'remove', only is necessary. " - "For nested attributes, separate the components with slashes, eg " - "'driver_info/deploy_kernel=uuid'.") -def do_node_update(cc, args): - """Update information about a registered node.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - node = cc.node.update(args.node, patch) - _print_node_show(node, json=args.json) - - -@cliutils.arg('node', - metavar='', - help="Name or UUID of the node.") -@cliutils.arg('method', - metavar='', - help="Vendor-passthru method to be called.") -@cliutils.arg('arguments', - metavar='', - nargs='*', - action='append', - default=[], - help=("Argument to be passed to the vendor-passthru method. Can " - "be specified multiple times.")) -@cliutils.arg('--http-method', - metavar='', - choices=v1_utils.HTTP_METHODS, - help=("The HTTP method to use in the request. Valid HTTP " - "methods are: %s. Defaults to 'POST'." % - ', '.join(v1_utils.HTTP_METHODS))) -@cliutils.arg('--http_method', - help=argparse.SUPPRESS) -def do_node_vendor_passthru(cc, args): - """Call a vendor-passthru extension for a node.""" - arguments = utils.key_value_pairs_to_dict(args.arguments[0]) - - resp = cc.node.vendor_passthru(args.node, args.method, - http_method=args.http_method, - args=arguments) - if resp: - # Print the raw response we don't know how it should be formated - print(str(resp.to_dict())) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the ports.") -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of ports to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Port UUID (for example, of the last port in the list from a ' - 'previous request). Returns the list of ports after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Port field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more port fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -def do_node_port_list(cc, args): - """List the ports associated with a node.""" - if args.detail: - fields = res_fields.PORT_DETAILED_RESOURCE.fields - field_labels = res_fields.PORT_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.PORT_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.PORT_RESOURCE.fields - field_labels = res_fields.PORT_RESOURCE.labels - - sort_fields = res_fields.PORT_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.PORT_DETAILED_RESOURCE.sort_labels - - params = utils.common_params_for_list(args, sort_fields, - sort_field_labels) - - ports = cc.node.list_ports(args.node, **params) - - cliutils.print_list(ports, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'maintenance_mode', - metavar='', - help="'true' or 'false'; 'on' or 'off'.") -@cliutils.arg( - '--reason', - metavar='', - default=None, - help=("Reason for setting maintenance mode to 'true' or 'on';" - " not valid when setting to 'false' or 'off'.")) -def do_node_set_maintenance(cc, args): - """Enable or disable maintenance mode for a node.""" - maintenance_mode = utils.bool_argument_value("", - args.maintenance_mode) - if args.reason and not maintenance_mode: - raise exceptions.CommandError(_('Cannot set "reason" when turning off ' - 'maintenance mode.')) - cc.node.set_maintenance(args.node, maintenance_mode, - maint_reason=args.reason) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'power_state', - metavar='', - choices=['on', 'off', 'reboot'], - help="'on', 'off', or 'reboot'.") -@cliutils.arg( - '--soft', - dest='soft', - action='store_true', - default=False, - help=("Gracefully change the power state. Only valid for 'off' and " - "'reboot' power states.")) -@cliutils.arg( - '--power-timeout', - metavar='', - type=int, - default=None, - help=("Timeout (in seconds, positive integer) to wait for the target " - "power state before erroring out.")) -def do_node_set_power_state(cc, args): - """Power a node on or off or reboot.""" - try: - cc.node.set_power_state(args.node, args.power_state, args.soft, - timeout=args.power_timeout) - except ValueError as e: - raise exc.CommandError(six.text_type(e)) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'target_raid_config', - metavar='', - help=("A file containing JSON data of the desired RAID configuration. " - "Use '-' to read the contents from standard input. " - "It also accepts the valid json string as input if " - "file/standard input are not used for providing input. " - "The input can be an empty dictionary too which " - "unsets the node.target_raid_config on the node.")) -def do_node_set_target_raid_config(cc, args): - """Set target RAID config on a node.""" - target_raid_config = args.target_raid_config - if not target_raid_config: - raise exc.InvalidAttribute( - _("target RAID configuration not provided")) - - if target_raid_config == '-': - target_raid_config = utils.get_from_stdin('target_raid_config') - target_raid_config = utils.handle_json_or_file_arg(target_raid_config) - - cc.node.set_target_raid_config(args.node, target_raid_config) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'provision_state', - metavar='', - choices=v1_utils.PROVISION_STATES, - help="Supported states: %s." % ', '.join(v1_utils.PROVISION_STATES)) -@cliutils.arg( - '--config-drive', - metavar='', - default=None, - help=("A gzipped, base64-encoded configuration drive string OR the path " - "to the configuration drive file OR the path to a directory " - "containing the config drive files. In case it's a directory, a " - "config drive will be generated from it. This argument is only " - "valid when setting provision-state to 'active'.")) -@cliutils.arg( - '--clean-steps', - metavar='', - default=None, - help=("The clean steps in JSON format. May be the path to a file " - "containing the clean steps; OR '-', with the clean steps being " - "read from standard input; OR a string. The value should be " - "a list of clean-step dictionaries; each dictionary should have " - "keys 'interface' and 'step', and optional key 'args'. " - "This argument must be specified (and is only valid) when " - "setting provision-state to 'clean'.")) -@cliutils.arg( - '--wait', - type=int, - dest='wait_timeout', - default=None, - const=0, - nargs='?', - help=("Wait for a node to reach the expected state. Not supported " - "for 'abort'. Optionally takes a timeout in seconds. " - "The default value is 0, meaning no timeout. " - "Fails if the node reaches an unexpected stable state, a failure " - "state or a state with last_error set.")) -def do_node_set_provision_state(cc, args): - """Initiate a provisioning state change for a node.""" - if args.config_drive and args.provision_state != 'active': - raise exceptions.CommandError(_('--config-drive is only valid when ' - 'setting provision state to "active"')) - elif args.clean_steps and args.provision_state != 'clean': - raise exceptions.CommandError(_('--clean-steps is only valid when ' - 'setting provision state to "clean"')) - elif args.provision_state == 'clean' and not args.clean_steps: - raise exceptions.CommandError(_('--clean-steps must be specified when ' - 'setting provision state to "clean"')) - - if args.wait_timeout is not None: - wait_args = v1_utils.PROVISION_ACTIONS.get(args.provision_state) - if wait_args is None: - raise exceptions.CommandError( - _("--wait is not supported for provision state '%s'") - % args.provision_state) - - clean_steps = args.clean_steps - if args.clean_steps == '-': - clean_steps = utils.get_from_stdin('clean steps') - if clean_steps: - clean_steps = utils.handle_json_or_file_arg(clean_steps) - cc.node.set_provision_state(args.node, args.provision_state, - configdrive=args.config_drive, - cleansteps=clean_steps) - if args.wait_timeout is not None: - print(_('Waiting for provision state %(state)s on node %(node)s') % - {'state': wait_args['expected_state'], 'node': args.node}) - cc.node.wait_for_provision_state(args.node, timeout=args.wait_timeout, - **wait_args) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_validate(cc, args): - """Validate a node's driver interfaces.""" - ifaces = cc.node.validate(args.node) - obj_list = [] - for key, value in ifaces.to_dict().items(): - data = {'interface': key} - data.update(value) - obj_list.append(type('iface', (object,), data)) - field_labels = ['Interface', 'Result', 'Reason'] - fields = ['interface', 'result', 'reason'] - cliutils.print_list(obj_list, fields, field_labels=field_labels, - json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_get_console(cc, args): - """Get the connection information for a node's console, if enabled.""" - info = cc.node.get_console(args.node) - cliutils.print_dict(info, wrap=72, json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'enabled', - metavar='', - help="Enable or disable console access for a node: 'true' or 'false'.") -def do_node_set_console_mode(cc, args): - """Enable or disable serial console access for a node.""" - enable = utils.bool_argument_value("", args.enabled) - cc.node.set_console_mode(args.node, enable) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg( - 'device', - metavar='', - choices=v1_utils.BOOT_DEVICES, - help="One of %s." % ', '.join(v1_utils.BOOT_DEVICES)) -@cliutils.arg( - '--persistent', - dest='persistent', - action='store_true', - default=False, - help="Make changes persistent for all future boots.") -def do_node_set_boot_device(cc, args): - """Set the boot device for a node.""" - cc.node.set_boot_device(args.node, args.device, args.persistent) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_get_boot_device(cc, args): - """Get the current boot device for a node.""" - boot_device = cc.node.get_boot_device(args.node) - cliutils.print_dict(boot_device, wrap=72, json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_inject_nmi(cc, args): - """Inject NMI to a node.""" - cc.node.inject_nmi(args.node) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_get_supported_boot_devices(cc, args): - """Get the supported boot devices for a node.""" - boot_devices = cc.node.get_supported_boot_devices(args.node) - boot_device_list = boot_devices.get('supported_boot_devices', []) - boot_devices['supported_boot_devices'] = ', '.join(boot_device_list) - cliutils.print_dict(boot_devices, wrap=72, json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_show_states(cc, args): - """Show information about the node's states.""" - states = cc.node.states(args.node) - cliutils.print_dict(states.to_dict(), wrap=72, json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_get_vendor_passthru_methods(cc, args): - """Get the vendor passthru methods for a node.""" - methods = cc.node.get_vendor_passthru_methods(args.node) - data = [] - for method, response in methods.items(): - response['name'] = method - http_methods = ','.join(response['http_methods']) - response['http_methods'] = http_methods - data.append(response) - fields = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.fields - field_labels = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.labels - cliutils.print_list(data, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -def do_node_vif_list(cc, args): - """List VIFs for a given node.""" - vifs = cc.node.vif_list(args.node) - fields = res_fields.VIF_RESOURCE.fields - field_labels = res_fields.VIF_RESOURCE.labels - cliutils.print_list(vifs, fields, field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg('vif_id', metavar='', - help="Name or UUID of the VIF to attach to node.") -@cliutils.arg('--vif-info', metavar='', - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times. The mandatory 'id' " - "parameter cannot be specified as a key.") -def do_node_vif_attach(cc, args): - """Attach VIF to a given node.""" - fields = utils.key_value_pairs_to_dict(args.vif_info or []) - cc.node.vif_attach(args.node, args.vif_id, **fields) - - -@cliutils.arg('node', metavar='', help="Name or UUID of the node.") -@cliutils.arg('vif_id', metavar='', - help="Name or UUID of the VIF to detach from node.") -def do_node_vif_detach(cc, args): - """Detach VIF from a given node.""" - cc.node.vif_detach(args.node, args.vif_id) diff --git a/ironicclient/v1/port_shell.py b/ironicclient/v1/port_shell.py deleted file mode 100644 index e360b6799..000000000 --- a/ironicclient/v1/port_shell.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_port_show(port, fields=None, json=False): - if fields is None: - fields = res_fields.PORT_DETAILED_RESOURCE.fields - - data = dict([(f, getattr(port, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg( - 'port', - metavar='', - help="UUID of the port (or MAC address if --address is specified).") -@cliutils.arg( - '--address', - dest='address', - action='store_true', - default=False, - help=' is the MAC address (instead of the UUID) of the port.') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more port fields. Only these fields will be fetched from " - "the server.") -def do_port_show(cc, args): - """Show detailed information about a port.""" - fields = args.fields[0] if args.fields else None - utils.check_for_invalid_fields( - fields, res_fields.PORT_DETAILED_RESOURCE.fields) - if args.address: - port = cc.port.get_by_address(args.port, fields=fields) - else: - utils.check_empty_arg(args.port, '') - port = cc.port.get(args.port, fields=fields) - _print_port_show(port, fields=fields, json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about ports.") -@cliutils.arg( - '--address', - metavar='', - help='Only show information for the port with this MAC address.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of ports to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Port UUID (for example, of the last port in the list from a ' - 'previous request). Returns the list of ports after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Port field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more port fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -def do_port_list(cc, args): - """List the ports.""" - params = {} - - if args.address is not None: - params['address'] = args.address - - if args.detail: - fields = res_fields.PORT_DETAILED_RESOURCE.fields - field_labels = res_fields.PORT_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.PORT_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.PORT_RESOURCE.fields - field_labels = res_fields.PORT_RESOURCE.labels - - sort_fields = res_fields.PORT_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.PORT_DETAILED_RESOURCE.sort_labels - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - - port = cc.port.list(**params) - cliutils.print_list(port, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg( - '-a', '--address', - metavar='
', - required=True, - help='MAC address for this port.') -@cliutils.arg( - '-n', '--node', '--node_uuid', - dest='node_uuid', - metavar='', - required=True, - help='UUID of the node that this port belongs to.') -@cliutils.arg( - '-l', '--local-link-connection', - metavar="", - action='append', - help="Key/value metadata describing Local link connection information. " - "Valid keys are switch_info, switch_id, port_id." - "Can be specified multiple times.") -@cliutils.arg( - '--portgroup', - metavar="", - dest='portgroup_uuid', - help='UUID of the portgroup that this port belongs to.') -@cliutils.arg( - '--pxe-enabled', - metavar='', - help='Indicates whether this Port should be used when ' - 'PXE booting this Node.') -@cliutils.arg( - '--physical-network', - metavar='', - help="Physical network of the port.") -@cliutils.arg( - '-e', '--extra', - metavar="", - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -@cliutils.arg( - '-u', '--uuid', - metavar='', - help="UUID of the port.") -def do_port_create(cc, args): - """Create a new port.""" - field_list = ['address', 'extra', 'node_uuid', 'uuid', - 'local_link_connection', 'portgroup_uuid', - 'pxe_enabled', 'physical_network'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - fields = utils.args_array_to_dict(fields, 'local_link_connection') - port = cc.port.create(**fields) - - data = dict([(f, getattr(port, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg('port', metavar='', nargs='+', help="UUID of the port.") -def do_port_delete(cc, args): - """Delete a port.""" - failures = [] - for p in args.port: - try: - cc.port.delete(p) - print(_('Deleted port %s') % p) - except exceptions.ClientException as e: - failures.append(_("Failed to delete port %(port)s: %(error)s") - % {'port': p, 'error': e}) - if failures: - raise exceptions.ClientException("\n".join(failures)) - - -@cliutils.arg('port', metavar='', help="UUID of the port.") -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified multiple " - "times. For 'remove', only is necessary.") -def do_port_update(cc, args): - """Update information about a port.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - port = cc.port.update(args.port, patch) - _print_port_show(port, json=args.json) diff --git a/ironicclient/v1/portgroup_shell.py b/ironicclient/v1/portgroup_shell.py deleted file mode 100644 index 8e4f25283..000000000 --- a/ironicclient/v1/portgroup_shell.py +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright 2015 SAP Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_portgroup_show(portgroup, fields=None, json=False): - if fields is None: - fields = res_fields.PORTGROUP_DETAILED_RESOURCE.fields - - data = dict([(f, getattr(portgroup, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg( - 'portgroup', - metavar='', - help="Name or UUID of the portgroup " - "(or MAC address if --address is specified).") -@cliutils.arg( - '--address', - dest='address', - action='store_true', - default=False, - help=' is the MAC address (instead of the UUID) of the portgroup.') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more portgroup fields. Only these fields will be fetched " - "from the server.") -def do_portgroup_show(cc, args): - """Show detailed information about a portgroup.""" - fields = args.fields[0] if args.fields else None - utils.check_for_invalid_fields( - fields, res_fields.PORTGROUP_DETAILED_RESOURCE.fields) - if args.address: - portgroup = cc.portgroup.get_by_address(args.portgroup, fields=fields) - else: - utils.check_empty_arg(args.portgroup, '') - portgroup = cc.portgroup.get(args.portgroup, fields=fields) - _print_portgroup_show(portgroup, fields=fields, json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about portgroups.") -@cliutils.arg( - '-n', '--node', - dest='node', - metavar='', - help='UUID of the node that this portgroup belongs to.') -@cliutils.arg( - '-a', '--address', - metavar='', - help='Only show information for the portgroup with this MAC address.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of portgroups to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Portgroup UUID (for example, of the last portgroup in the list ' - 'from a previous request). ' - 'Returns the list of portgroups after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Portgroup field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more portgroup fields. Only these fields will be fetched " - "from the server. Can not be used when '--detail' is specified.") -def do_portgroup_list(cc, args): - """List the portgroups.""" - params = {} - - if args.address is not None: - params['address'] = args.address - if args.node is not None: - params['node'] = args.node - - if args.detail: - fields = res_fields.PORTGROUP_DETAILED_RESOURCE.fields - field_labels = res_fields.PORTGROUP_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.PORTGROUP_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.PORTGROUP_RESOURCE.fields - field_labels = res_fields.PORTGROUP_RESOURCE.labels - - sort_fields = res_fields.PORTGROUP_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.PORTGROUP_DETAILED_RESOURCE.sort_labels - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - - portgroup = cc.portgroup.list(**params) - cliutils.print_list(portgroup, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg( - '-a', '--address', - metavar='
', - help='MAC address for this portgroup.') -@cliutils.arg( - '-n', '--node', - dest='node_uuid', - metavar='', - required=True, - help='UUID of the node that this portgroup belongs to.') -@cliutils.arg( - '--name', - metavar="", - help='Name for the portgroup.') -@cliutils.arg( - '-e', '--extra', - metavar="", - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -@cliutils.arg( - '--standalone-ports-supported', - metavar="", - help='Specifies whether ports from this portgroup can be used ' - 'in stand alone mode.') -@cliutils.arg( - '-u', '--uuid', - metavar='', - help="UUID of the portgroup.") -@cliutils.arg( - '-m', '--mode', - metavar='', - help="Portgroup mode. For possible values, refer to " - "https://www.kernel.org/doc/Documentation/networking/bonding.txt") -@cliutils.arg( - '-p', '--properties', - metavar="", - action='append', - help="Record key/value properties related to this portgroup's " - "configuration.") -def do_portgroup_create(cc, args): - """Create a new portgroup.""" - field_list = ['address', 'extra', 'node_uuid', 'name', 'uuid', - 'standalone_ports_supported', 'mode', 'properties'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - fields = utils.args_array_to_dict(fields, 'properties') - portgroup = cc.portgroup.create(**fields) - - data = dict([(f, getattr(portgroup, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the ports.") -@cliutils.arg( - '--limit', - metavar='', - type=int, - help='Maximum number of ports to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='', - help='Port UUID (for example, of the last port in the list from a ' - 'previous request). Returns the list of ports after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='', - help='Port field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - 'portgroup', - metavar='', - help="Name or UUID of the portgroup.") -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help="One or more port fields. Only these fields will be fetched from " - "the server. Can not be used when '--detail' is specified.") -def do_portgroup_port_list(cc, args): - """List the ports associated with a portgroup.""" - if args.detail: - fields = res_fields.PORT_DETAILED_RESOURCE.fields - field_labels = res_fields.PORT_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], res_fields.PORT_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.PORT_RESOURCE.fields - field_labels = res_fields.PORT_RESOURCE.labels - - sort_fields = res_fields.PORT_DETAILED_RESOURCE.sort_fields - sort_field_labels = res_fields.PORT_DETAILED_RESOURCE.sort_labels - - params = utils.common_params_for_list(args, sort_fields, - sort_field_labels) - - ports = cc.portgroup.list_ports(args.portgroup, **params) - - cliutils.print_list(ports, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg('portgroup', metavar='', nargs='+', - help="UUID or Name of the portgroup.") -def do_portgroup_delete(cc, args): - """Delete a portgroup.""" - failures = [] - for p in args.portgroup: - try: - cc.portgroup.delete(p) - print('Deleted portgroup %s' % p) - except exceptions.ClientException as e: - failures.append(_("Failed to delete portgroup %(pg)s: %(error)s") - % {'pg': p, 'error': e}) - if failures: - raise exceptions.ClientException("\n".join(failures)) - - -@cliutils.arg('portgroup', metavar='', - help="UUID or Name of the portgroup.") -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified multiple " - "times. For 'remove', only is necessary.") -def do_portgroup_update(cc, args): - """Update information about a portgroup.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - portgroup = cc.portgroup.update(args.portgroup, patch) - _print_portgroup_show(portgroup, json=args.json) diff --git a/ironicclient/v1/shell.py b/ironicclient/v1/shell.py deleted file mode 100644 index a31422f61..000000000 --- a/ironicclient/v1/shell.py +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from ironicclient.common import utils -from ironicclient.v1 import chassis_shell -from ironicclient.v1 import create_resources_shell -from ironicclient.v1 import driver_shell -from ironicclient.v1 import node_shell -from ironicclient.v1 import port_shell -from ironicclient.v1 import portgroup_shell -from ironicclient.v1 import volume_connector_shell -from ironicclient.v1 import volume_target_shell - -COMMAND_MODULES = [ - chassis_shell, - node_shell, - port_shell, - portgroup_shell, - driver_shell, - create_resources_shell, - volume_connector_shell, - volume_target_shell, -] - - -def enhance_parser(parser, subparsers, cmd_mapper): - """Enhance parser with API version specific options. - - Take a basic (nonversioned) parser and enhance it with - commands and options specific for this version of API. - - :param parser: top level parser - :param subparsers: top level parser's subparsers collection - where subcommands will go - """ - for command_module in COMMAND_MODULES: - utils.define_commands_from_module(subparsers, command_module, - cmd_mapper) diff --git a/ironicclient/v1/volume_connector_shell.py b/ironicclient/v1/volume_connector_shell.py deleted file mode 100644 index c6d3fa04b..000000000 --- a/ironicclient/v1/volume_connector_shell.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2017 Hitachi Data Systems -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_volume_connector_show(volume_connector, fields=None, json=False): - if fields is None: - fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields - - data = dict([(f, getattr(volume_connector, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg( - 'volume_connector', - metavar='', - help=_("UUID of the volume connector.")) -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help=_("One or more volume connector fields. Only these fields will be " - "fetched from the server.")) -def do_volume_connector_show(cc, args): - """Show detailed information about a volume connector.""" - fields = args.fields[0] if args.fields else None - utils.check_for_invalid_fields( - fields, res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields) - utils.check_empty_arg(args.volume_connector, '') - volume_connector = cc.volume_connector.get(args.volume_connector, - fields=fields) - _print_volume_connector_show(volume_connector, fields=fields, - json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help=_("Show detailed information about volume connectors.")) -@cliutils.arg( - '-n', '--node', - metavar='', - help=_('Only list volume connectors of this node (name or UUID)')) -@cliutils.arg( - '--limit', - metavar='', - type=int, - help=_('Maximum number of volume connectors to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Baremetal API Service.')) -@cliutils.arg( - '--marker', - metavar='', - help=_('Volume connector UUID (for example, of the last volume connector ' - 'in the list from a previous request). Returns the list of volume ' - 'connectors after this UUID.')) -@cliutils.arg( - '--sort-key', - metavar='', - help=_('Volume connector field that will be used for sorting.')) -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help=_('Sort direction: "asc" (the default) or "desc".')) -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help=_("One or more volume connector fields. Only these fields will be " - "fetched from the server. Can not be used when '--detail' is " - "specified.")) -def do_volume_connector_list(cc, args): - """List the volume connectors.""" - params = {} - - if args.node is not None: - params['node'] = args.node - - if args.detail: - fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields - field_labels = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], - res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.VOLUME_CONNECTOR_RESOURCE.fields - field_labels = res_fields.VOLUME_CONNECTOR_RESOURCE.labels - - sort_fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.sort_fields - sort_field_labels = ( - res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.sort_labels) - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - - volume_connector = cc.volume_connector.list(**params) - cliutils.print_list(volume_connector, fields, - field_labels=field_labels, - sortby_index=None, - json_flag=args.json) - - -@cliutils.arg( - '-e', '--extra', - metavar="", - action='append', - help=_("Record arbitrary key/value metadata. " - "Can be specified multiple times.")) -@cliutils.arg( - '-n', '--node', - dest='node_uuid', - metavar='', - required=True, - help=_('UUID of the node that this volume connector belongs to.')) -@cliutils.arg( - '-t', '--type', - metavar="", - required=True, - choices=['iqn', 'ip', 'mac', 'wwnn', 'wwpn'], - help=_("Type of the volume connector. Can be 'iqn', 'ip', 'mac', 'wwnn', " - "'wwpn'.")) -@cliutils.arg( - '-i', '--connector_id', - metavar="", - required=True, - help=_("ID of the Volume connector in the specified type.")) -@cliutils.arg( - '-u', '--uuid', - metavar='', - help=_("UUID of the volume connector.")) -def do_volume_connector_create(cc, args): - """Create a new volume connector.""" - field_list = ['extra', 'type', 'connector_id', 'node_uuid', 'uuid'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - volume_connector = cc.volume_connector.create(**fields) - - data = dict([(f, getattr(volume_connector, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg('volume_connector', metavar='', nargs='+', - help=_("UUID of the volume connector.")) -def do_volume_connector_delete(cc, args): - """Delete a volume connector.""" - failures = [] - for vc in args.volume_connector: - try: - cc.volume_connector.delete(vc) - print(_('Deleted volume connector %s') % vc) - except exceptions.ClientException as e: - failures.append(_("Failed to delete volume connector %(vc)s: " - "%(error)s") - % {'vc': vc, 'error': e}) - if failures: - raise exceptions.ClientException("\n".join(failures)) - - -@cliutils.arg('volume_connector', metavar='', - help=_("UUID of the volume connector.")) -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help=_("Operation: 'add', 'replace', or 'remove'.")) -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help=_("Attribute to add, replace, or remove. Can be specified multiple " - "times. For 'remove', only is necessary.")) -def do_volume_connector_update(cc, args): - """Update information about a volume connector.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - volume_connector = cc.volume_connector.update(args.volume_connector, patch) - _print_volume_connector_show(volume_connector, json=args.json) diff --git a/ironicclient/v1/volume_target_shell.py b/ironicclient/v1/volume_target_shell.py deleted file mode 100644 index fd9d48663..000000000 --- a/ironicclient/v1/volume_target_shell.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright 2017 Hitachi, Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common.apiclient import exceptions -from ironicclient.common import cliutils -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_volume_target_show(volume_target, fields=None, json=False): - if fields is None: - fields = res_fields.VOLUME_TARGET_DETAILED_RESOURCE.fields - - data = dict([(f, getattr(volume_target, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72, json_flag=json) - - -@cliutils.arg( - 'volume_target', - metavar='', - help=_("UUID of the volume target.")) -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help=_("One or more volume target fields. Only these fields will be " - "fetched from the server.")) -def do_volume_target_show(cc, args): - """Show detailed information about a volume target.""" - fields = args.fields[0] if args.fields else None - utils.check_for_invalid_fields( - fields, res_fields.VOLUME_TARGET_DETAILED_RESOURCE.fields) - utils.check_empty_arg(args.volume_target, '') - volume_target = cc.volume_target.get(args.volume_target, fields=fields) - _print_volume_target_show(volume_target, fields=fields, json=args.json) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help=_("Show detailed information about volume targets.")) -@cliutils.arg( - '-n', '--node', - metavar='', - help=_('Only list volume targets of this node (name or UUID)')) -@cliutils.arg( - '--limit', - metavar='', - type=int, - help=_('Maximum number of volume targets to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Baremetal API Service.')) -@cliutils.arg( - '--marker', - metavar='', - help=_('Volume target UUID (for example, of the last volume target in ' - 'the list from a previous request). Returns the list of volume ' - 'targets after this UUID.')) -@cliutils.arg( - '--sort-key', - metavar='', - help=_('Volume target field that will be used for sorting.')) -@cliutils.arg( - '--sort-dir', - metavar='', - choices=['asc', 'desc'], - help=_('Sort direction: "asc" (the default) or "desc".')) -@cliutils.arg( - '--fields', - nargs='+', - dest='fields', - metavar='', - action='append', - default=[], - help=_("One or more volume target fields. Only these fields will be " - "fetched from the server. Can not be used when '--detail' is " - "specified.")) -def do_volume_target_list(cc, args): - """List the volume targets.""" - params = {} - - if args.node is not None: - params['node'] = args.node - - if args.detail: - fields = res_fields.VOLUME_TARGET_DETAILED_RESOURCE.fields - field_labels = res_fields.VOLUME_TARGET_DETAILED_RESOURCE.labels - elif args.fields: - utils.check_for_invalid_fields( - args.fields[0], - res_fields.VOLUME_TARGET_DETAILED_RESOURCE.fields) - resource = res_fields.Resource(args.fields[0]) - fields = resource.fields - field_labels = resource.labels - else: - fields = res_fields.VOLUME_TARGET_RESOURCE.fields - field_labels = res_fields.VOLUME_TARGET_RESOURCE.labels - - sort_fields = res_fields.VOLUME_TARGET_DETAILED_RESOURCE.sort_fields - sort_field_labels = ( - res_fields.VOLUME_TARGET_DETAILED_RESOURCE.sort_labels) - - params.update(utils.common_params_for_list(args, - sort_fields, - sort_field_labels)) - - volume_target = cc.volume_target.list(**params) - cliutils.print_list(volume_target, fields, field_labels=field_labels, - sortby_index=None, json_flag=args.json) - - -@cliutils.arg( - '-e', '--extra', - metavar="", - action='append', - help=_("Record arbitrary key/value metadata. " - "Can be specified multiple times.")) -@cliutils.arg( - '-n', '--node', - dest='node_uuid', - metavar='', - required=True, - help=_('UUID of the node that this volume target belongs to.')) -@cliutils.arg( - '-t', '--type', - metavar="", - required=True, - help=_("Type of the volume target, e.g. 'iscsi', 'fibre_channel'.")) -@cliutils.arg( - '-p', '--properties', - metavar="", - action='append', - help=_("Key/value property related to the type of this volume " - "target. Can be specified multiple times.")) -@cliutils.arg( - '-b', '--boot-index', - metavar="", - required=True, - help=_("Boot index of the volume target.")) -@cliutils.arg( - '-i', '--volume_id', - metavar="", - required=True, - help=_("ID of the volume associated with this target.")) -@cliutils.arg( - '-u', '--uuid', - metavar='', - help=_("UUID of the volume target.")) -def do_volume_target_create(cc, args): - """Create a new volume target.""" - field_list = ['extra', 'volume_type', 'properties', - 'boot_index', 'node_uuid', 'volume_id', 'uuid'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'properties') - fields = utils.args_array_to_dict(fields, 'extra') - volume_target = cc.volume_target.create(**fields) - - data = dict([(f, getattr(volume_target, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72, json_flag=args.json) - - -@cliutils.arg('volume_target', metavar='', nargs='+', - help=_("UUID of the volume target.")) -def do_volume_target_delete(cc, args): - """Delete a volume target.""" - failures = [] - for vt in args.volume_target: - try: - cc.volume_target.delete(vt) - print(_('Deleted volume target %s') % vt) - except exceptions.ClientException as e: - failures.append(_("Failed to delete volume target %(vt)s: " - "%(error)s") - % {'vt': vt, 'error': e}) - if failures: - raise exceptions.ClientException("\n".join(failures)) - - -@cliutils.arg('volume_target', metavar='', - help=_("UUID of the volume target.")) -@cliutils.arg( - 'op', - metavar='', - choices=['add', 'replace', 'remove'], - help=_("Operation: 'add', 'replace', or 'remove'.")) -@cliutils.arg( - 'attributes', - metavar='', - nargs='+', - action='append', - default=[], - help=_("Attribute to add, replace, or remove. Can be specified multiple " - "times. For 'remove', only is necessary.")) -def do_volume_target_update(cc, args): - """Update information about a volume target.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - volume_target = cc.volume_target.update(args.volume_target, patch) - _print_volume_target_show(volume_target, json=args.json) diff --git a/releasenotes/notes/remove-ironic-command-5c9f7bc4946996e0.yaml b/releasenotes/notes/remove-ironic-command-5c9f7bc4946996e0.yaml new file mode 100644 index 000000000..e614ccea6 --- /dev/null +++ b/releasenotes/notes/remove-ironic-command-5c9f7bc4946996e0.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + The long deprecated ``ironic`` command has been removed. + The ``openstack baremetal`` command must now be used. + Please update any scripts that you may be using with ironic. diff --git a/requirements.txt b/requirements.txt index c15ce97b9..5e76b37fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,6 @@ osc-lib>=1.10.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 -PrettyTable<0.8,>=0.7.1 # BSD PyYAML>=3.12 # MIT requests>=2.14.2 # Apache-2.0 six>=1.10.0 # MIT diff --git a/setup.cfg b/setup.cfg index 7a7188576..08828087e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,9 +22,6 @@ classifier = packages = ironicclient [entry_points] -console_scripts = - ironic = ironicclient.shell:main - openstack.cli.extension = baremetal = ironicclient.osc.plugin diff --git a/tools/ironic.bash_completion b/tools/ironic.bash_completion deleted file mode 100644 index fbc32f2f0..000000000 --- a/tools/ironic.bash_completion +++ /dev/null @@ -1,27 +0,0 @@ -_ironic_opts="" # lazy init -_ironic_flags="" # lazy init -_ironic_opts_exp="" # lazy init -_ironic() -{ - local cur prev nbc cflags - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - if [ "x$_ironic_opts" == "x" ] ; then - nbc="`ironic bash-completion | sed -e "s/ *-h */ /" -e "s/ *-i */ /"`" - _ironic_opts="`echo "$nbc" | sed -e "s/--[a-z0-9_-]*//g" -e "s/ */ /g"`" - _ironic_flags="`echo " $nbc" | sed -e "s/ [^-][^-][a-z0-9_-]*//g" -e "s/ */ /g"`" - _ironic_opts_exp="`echo "$_ironic_opts" | tr ' ' '|'`" - fi - - if [[ " ${COMP_WORDS[@]} " =~ " "($_ironic_opts_exp)" " && "$prev" != "help" ]] ; then - COMPLETION_CACHE=$HOME/.cache/python-ironicclient/*/*-cache - cflags="$_ironic_flags "$(cat $COMPLETION_CACHE 2> /dev/null | tr '\n' ' ') - COMPREPLY=($(compgen -W "${cflags}" -- ${cur})) - else - COMPREPLY=($(compgen -W "${_ironic_opts}" -- ${cur})) - fi - return 0 -} -complete -F _ironic ironic