From f62758cda5953ac22614a783df0165e42e76d60b Mon Sep 17 00:00:00 2001 From: Julia Kreger Date: Wed, 14 Aug 2019 16:26:41 -0400 Subject: [PATCH] Remove the ironic command The ironic command is dead, long live the OSC baremetal command. Also removed the json_respose tests, which seemed ot be geared to checking json returned data on the command line. For ironic these tests seemed to be very explicit for our CLI where as OSC should be covering the return data handling, the only real end effect is field level expectation enforcement in the functional test... which seems excessive and un-needed. Story: 1726605 Task: 11974 Depends-on: https://review.opendev.org/677183 Change-Id: I3e3ae416a65d8e01956434ba51bd3187ab001f80 --- README.rst | 47 +- doc/source/cli/index.rst | 1 - doc/source/cli/ironic_client.rst | 100 -- doc/source/index.rst | 3 +- doc/source/user/create_command.rst | 22 +- ironicclient/common/cliutils.py | 296 ---- ironicclient/shell.py | 496 ------ ironicclient/tests/functional/test_chassis.py | 213 --- .../tests/functional/test_chassis_create.py | 129 -- ironicclient/tests/functional/test_driver.py | 56 - .../tests/functional/test_help_msg.py | 69 - .../tests/functional/test_json_response.py | 289 ---- ironicclient/tests/functional/test_node.py | 213 --- .../functional/test_node_set_power_state.py | 89 -- ironicclient/tests/functional/test_port.py | 134 -- .../tests/functional/test_portgroup.py | 114 -- .../tests/functional/test_table_structure.py | 62 - .../tests/unit/common/test_cliutils.py | 740 --------- ironicclient/tests/unit/test_shell.py | 520 ------- .../tests/unit/v1/test_chassis_shell.py | 391 ----- .../unit/v1/test_create_resources_shell.py | 31 - .../tests/unit/v1/test_driver_shell.py | 196 --- ironicclient/tests/unit/v1/test_node_shell.py | 1327 ----------------- ironicclient/tests/unit/v1/test_port_shell.py | 329 ---- ironicclient/tests/unit/v1/test_portgroup.py | 22 - .../tests/unit/v1/test_portgroup_shell.py | 298 ---- .../unit/v1/test_volume_connector_shell.py | 284 ---- .../tests/unit/v1/test_volume_target_shell.py | 288 ---- ironicclient/v1/chassis_shell.py | 258 ---- ironicclient/v1/create_resources_shell.py | 28 - ironicclient/v1/driver_shell.py | 150 -- ironicclient/v1/node_shell.py | 716 --------- ironicclient/v1/port_shell.py | 227 --- ironicclient/v1/portgroup_shell.py | 304 ---- ironicclient/v1/shell.py | 48 - ironicclient/v1/volume_connector_shell.py | 209 --- ironicclient/v1/volume_target_shell.py | 216 --- ...emove-ironic-command-5c9f7bc4946996e0.yaml | 6 + requirements.txt | 1 - setup.cfg | 3 - tools/ironic.bash_completion | 27 - 41 files changed, 10 insertions(+), 8942 deletions(-) delete mode 100644 doc/source/cli/ironic_client.rst delete mode 100644 ironicclient/common/cliutils.py delete mode 100644 ironicclient/shell.py delete mode 100644 ironicclient/tests/functional/test_chassis.py delete mode 100644 ironicclient/tests/functional/test_chassis_create.py delete mode 100644 ironicclient/tests/functional/test_driver.py delete mode 100644 ironicclient/tests/functional/test_help_msg.py delete mode 100644 ironicclient/tests/functional/test_json_response.py delete mode 100644 ironicclient/tests/functional/test_node.py delete mode 100644 ironicclient/tests/functional/test_node_set_power_state.py delete mode 100644 ironicclient/tests/functional/test_port.py delete mode 100644 ironicclient/tests/functional/test_portgroup.py delete mode 100644 ironicclient/tests/functional/test_table_structure.py delete mode 100644 ironicclient/tests/unit/common/test_cliutils.py delete mode 100644 ironicclient/tests/unit/test_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_chassis_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_create_resources_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_driver_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_node_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_port_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_portgroup_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_volume_connector_shell.py delete mode 100644 ironicclient/tests/unit/v1/test_volume_target_shell.py delete mode 100644 ironicclient/v1/chassis_shell.py delete mode 100644 ironicclient/v1/create_resources_shell.py delete mode 100644 ironicclient/v1/driver_shell.py delete mode 100644 ironicclient/v1/node_shell.py delete mode 100644 ironicclient/v1/port_shell.py delete mode 100644 ironicclient/v1/portgroup_shell.py delete mode 100644 ironicclient/v1/shell.py delete mode 100644 ironicclient/v1/volume_connector_shell.py delete mode 100644 ironicclient/v1/volume_target_shell.py create mode 100644 releasenotes/notes/remove-ironic-command-5c9f7bc4946996e0.yaml delete mode 100644 tools/ironic.bash_completion 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