Introduce openstackclient plugin
Adds the code necessary for ironicclient to work as a plugin for openstackclient. * baremetal list * baremetal show * baremetal delete * baremetal create * baremetal set * baremetal unset Change-Id: I91ea4f4a63b0e7a8ea004c47422d19ca0f288dcd
This commit is contained in:
parent
b5a720f7a4
commit
a5a15e40a5
0
ironicclient/osc/__init__.py
Normal file
0
ironicclient/osc/__init__.py
Normal file
51
ironicclient/osc/client.py
Normal file
51
ironicclient/osc/client.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Copyright 2010 Jacob Kaplan-Moss
|
||||||
|
# Copyright 2011 OpenStack Foundation
|
||||||
|
# Copyright 2011 Piston Cloud Computing, Inc.
|
||||||
|
#
|
||||||
|
# Modified by: Brad P. Crochet <brad@redhat.com>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
OpenStack Client factory.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
from ironicclient.common.i18n import _
|
||||||
|
from ironicclient import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def get_client_class(version):
|
||||||
|
version_map = {
|
||||||
|
'1': 'ironicclient.v1.client.Client',
|
||||||
|
'1.5': 'ironicclient.v1.client.Client',
|
||||||
|
'1.6': 'ironicclient.v1.client.Client',
|
||||||
|
'1.9': 'ironicclient.v1.client.Client',
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
client_path = version_map[str(version)]
|
||||||
|
except (KeyError, ValueError):
|
||||||
|
msg = _("Invalid client version '%(version)s'. must be one of: "
|
||||||
|
"%(keys)s") % {'version': version,
|
||||||
|
'keys': ', '.join(version_map)}
|
||||||
|
raise exceptions.UnsupportedVersion(msg)
|
||||||
|
|
||||||
|
return importutils.import_class(client_path)
|
||||||
|
|
||||||
|
|
||||||
|
def Client(version, *args, **kwargs):
|
||||||
|
client_class = get_client_class(version)
|
||||||
|
return client_class(*args, **kwargs)
|
70
ironicclient/osc/plugin.py
Normal file
70
ironicclient/osc/plugin.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2015 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 logging
|
||||||
|
|
||||||
|
from openstackclient.common import exceptions
|
||||||
|
from openstackclient.common import utils
|
||||||
|
|
||||||
|
from ironicclient.osc import client as ironic_client
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DEFAULT_BAREMETAL_API_VERSION = '1.6'
|
||||||
|
API_VERSION_OPTION = 'os_baremetal_api_version'
|
||||||
|
API_NAME = 'baremetal'
|
||||||
|
API_VERSIONS = {
|
||||||
|
'1': 'ironicclient.osc.client',
|
||||||
|
'1.5': 'ironicclient.osc.client',
|
||||||
|
'1.6': 'ironicclient.osc.client',
|
||||||
|
'1.9': 'ironicclient.osc.client',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def make_client(instance):
|
||||||
|
"""Returns a baremetal service client."""
|
||||||
|
try:
|
||||||
|
baremetal_client = ironic_client.get_client_class(
|
||||||
|
instance._api_version[API_NAME])
|
||||||
|
except Exception:
|
||||||
|
msg = "Invalid %s client version '%s'. Must be one of %s" % (
|
||||||
|
(API_NAME, instance._api_version[API_NAME],
|
||||||
|
", ".join(sorted(API_VERSIONS))))
|
||||||
|
raise exceptions.UnsupportedVersion(msg)
|
||||||
|
LOG.debug('Instantiating baremetal client: %s', baremetal_client)
|
||||||
|
|
||||||
|
client = baremetal_client(
|
||||||
|
os_ironic_api_version=instance._api_version[API_NAME],
|
||||||
|
session=instance.session,
|
||||||
|
region_name=instance._region_name,
|
||||||
|
endpoint=instance.auth_ref.auth_url,
|
||||||
|
)
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
def build_option_parser(parser):
|
||||||
|
"""Hook to add global options."""
|
||||||
|
parser.add_argument(
|
||||||
|
'--os-baremetal-api-version',
|
||||||
|
metavar='<baremetal-api-version>',
|
||||||
|
default=utils.env(
|
||||||
|
'OS_BAREMETAL_API_VERSION',
|
||||||
|
default=DEFAULT_BAREMETAL_API_VERSION),
|
||||||
|
help='Baremetal API version, default=' +
|
||||||
|
DEFAULT_BAREMETAL_API_VERSION +
|
||||||
|
' (Env: OS_BAREMETAL_API_VERSION)')
|
||||||
|
return parser
|
0
ironicclient/osc/v1/__init__.py
Normal file
0
ironicclient/osc/v1/__init__.py
Normal file
320
ironicclient/osc/v1/baremetal.py
Normal file
320
ironicclient/osc/v1/baremetal.py
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2015 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 logging
|
||||||
|
import six
|
||||||
|
|
||||||
|
from cliff import command
|
||||||
|
from cliff import lister
|
||||||
|
from cliff import show
|
||||||
|
from openstackclient.common import utils as oscutils
|
||||||
|
|
||||||
|
from ironicclient.common.i18n import _
|
||||||
|
from ironicclient.common import utils
|
||||||
|
from ironicclient import exc
|
||||||
|
from ironicclient.v1 import resource_fields as res_fields
|
||||||
|
|
||||||
|
|
||||||
|
class CreateBaremetal(show.ShowOne):
|
||||||
|
"""Register a new node with the baremetal service"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".CreateBaremetal")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CreateBaremetal, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--chassis-uuid',
|
||||||
|
dest='chassis_uuid',
|
||||||
|
metavar='<chassis>',
|
||||||
|
help='UUID of the chassis that this node belongs to.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--driver',
|
||||||
|
metavar='<driver>',
|
||||||
|
required=True,
|
||||||
|
help='Driver used to control the node [REQUIRED].')
|
||||||
|
parser.add_argument(
|
||||||
|
'--driver-info',
|
||||||
|
metavar='<key=value>',
|
||||||
|
action='append',
|
||||||
|
help='Key/value pair used by the driver, such as out-of-band '
|
||||||
|
'management credentials. Can be specified multiple times.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--property',
|
||||||
|
dest='properties',
|
||||||
|
metavar='<key=value>',
|
||||||
|
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.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--extra',
|
||||||
|
metavar='<key=value>',
|
||||||
|
action='append',
|
||||||
|
help="Record arbitrary key/value metadata. "
|
||||||
|
"Can be specified multiple times.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--uuid',
|
||||||
|
metavar='<uuid>',
|
||||||
|
help="Unique UUID for the node.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--name',
|
||||||
|
metavar='<name>',
|
||||||
|
help="Unique name for the node.")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
|
field_list = ['chassis_uuid', 'driver', 'driver_info',
|
||||||
|
'properties', 'extra', 'uuid', 'name']
|
||||||
|
fields = dict((k, v) for (k, v) in vars(parsed_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 = baremetal_client.node.create(**fields)._info
|
||||||
|
|
||||||
|
node.pop('links', None)
|
||||||
|
|
||||||
|
return self.dict2columns(node)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteBaremetal(command.Command):
|
||||||
|
"""Unregister a baremetal node"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".DeleteBaremetal")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(DeleteBaremetal, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"node",
|
||||||
|
metavar="<node>",
|
||||||
|
help="Node to delete (name or ID)")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
|
node = oscutils.find_resource(baremetal_client.node,
|
||||||
|
parsed_args.node)
|
||||||
|
baremetal_client.node.delete(node.uuid)
|
||||||
|
|
||||||
|
|
||||||
|
class ListBaremetal(lister.Lister):
|
||||||
|
"""List baremetal nodes"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".ListBaremetal")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ListBaremetal, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
metavar='<limit>',
|
||||||
|
type=int,
|
||||||
|
help='Maximum number of nodes to return per request, '
|
||||||
|
'0 for no limit. Default is the maximum number used '
|
||||||
|
'by the Baremetal API Service.'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<node>',
|
||||||
|
help='Node UUID (for example, of the last node in the list from '
|
||||||
|
'a previous request). Returns the list of nodes after this '
|
||||||
|
'UUID.'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--sort',
|
||||||
|
metavar="<key>[:<direction>]",
|
||||||
|
help='Sort output by selected keys and directions(asc or desc) '
|
||||||
|
'(default: asc), multiple keys and directions can be '
|
||||||
|
'specified separated by comma',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--maintenance',
|
||||||
|
dest='maintenance',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help="List nodes in maintenance mode.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--associated',
|
||||||
|
dest='associated',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help="List only nodes associated with an instance."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--long',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help="Show detailed information about the nodes."
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)" % parsed_args)
|
||||||
|
client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
|
columns = res_fields.NODE_RESOURCE
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
if parsed_args.limit is not None and parsed_args.limit < 0:
|
||||||
|
raise exc.CommandError(
|
||||||
|
_('Expected non-negative --limit, got %s') %
|
||||||
|
parsed_args.limit)
|
||||||
|
params['limit'] = parsed_args.limit
|
||||||
|
params['marker'] = parsed_args.marker
|
||||||
|
if parsed_args.associated:
|
||||||
|
params['associated'] = parsed_args.associated
|
||||||
|
if parsed_args.maintenance:
|
||||||
|
params['maintenance'] = parsed_args.maintenance
|
||||||
|
|
||||||
|
if parsed_args.long:
|
||||||
|
columns = res_fields.NODE_DETAILED_RESOURCE
|
||||||
|
params['detail'] = parsed_args.long
|
||||||
|
|
||||||
|
self.log.debug("params(%s)" % params)
|
||||||
|
data = client.node.list(**params)
|
||||||
|
|
||||||
|
data = oscutils.sort_items(data, parsed_args.sort)
|
||||||
|
|
||||||
|
return (columns.labels,
|
||||||
|
(oscutils.get_item_properties(s, columns.fields, formatters={
|
||||||
|
'Properties': oscutils.format_dict},) for s in data))
|
||||||
|
|
||||||
|
|
||||||
|
class SetBaremetal(command.Command):
|
||||||
|
"""Set baremetal properties"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".SetBaremetal")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(SetBaremetal, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'node',
|
||||||
|
metavar='<node>',
|
||||||
|
help="Name or UUID of the node."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--property",
|
||||||
|
metavar="<path=value>",
|
||||||
|
action='append',
|
||||||
|
help='Property to add to this baremetal host '
|
||||||
|
'(repeat option to set multiple properties)',
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
|
properties = []
|
||||||
|
if parsed_args.property:
|
||||||
|
properties = utils.args_array_to_patch(
|
||||||
|
'add', parsed_args.property)
|
||||||
|
baremetal_client.node.update(parsed_args.node, properties)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowBaremetal(show.ShowOne):
|
||||||
|
"""Show baremetal node details"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".ShowBaremetal")
|
||||||
|
LONG_FIELDS = [
|
||||||
|
'extra',
|
||||||
|
'properties',
|
||||||
|
'ports',
|
||||||
|
'driver_info',
|
||||||
|
'driver_internal_info',
|
||||||
|
'instance_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShowBaremetal, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"node",
|
||||||
|
metavar="<node>",
|
||||||
|
help="Name or UUID of the node (or instance UUID if --instance "
|
||||||
|
"is specified)")
|
||||||
|
parser.add_argument(
|
||||||
|
'--instance',
|
||||||
|
dest='instance_uuid',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='<node> is an instance UUID.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--long',
|
||||||
|
action='store_true')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
if parsed_args.instance_uuid:
|
||||||
|
node = baremetal_client.node.get_by_instance_uuid(
|
||||||
|
parsed_args.node)._info
|
||||||
|
else:
|
||||||
|
node = oscutils.find_resource(baremetal_client.node,
|
||||||
|
parsed_args.node)._info
|
||||||
|
node.pop("links", None)
|
||||||
|
if not parsed_args.long:
|
||||||
|
for field in self.LONG_FIELDS:
|
||||||
|
node.pop(field, None)
|
||||||
|
|
||||||
|
return zip(*sorted(six.iteritems(node)))
|
||||||
|
|
||||||
|
|
||||||
|
class UnsetBaremetal(command.Command):
|
||||||
|
"""Unset baremetal properties"""
|
||||||
|
log = logging.getLogger(__name__ + ".UnsetBaremetal")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(UnsetBaremetal, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'node',
|
||||||
|
metavar='<node>',
|
||||||
|
help="Name or UUID of the node."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--property',
|
||||||
|
metavar='<path>',
|
||||||
|
action='append',
|
||||||
|
help='Property to unset on this baremetal host '
|
||||||
|
'(repeat option to unset multiple properties)',
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
|
if not parsed_args.node and not parsed_args.property:
|
||||||
|
return
|
||||||
|
|
||||||
|
patch = utils.args_array_to_patch('remove', parsed_args.property)
|
||||||
|
baremetal_client.node.update(parsed_args.node, patch)
|
0
ironicclient/tests/unit/osc/__init__.py
Normal file
0
ironicclient/tests/unit/osc/__init__.py
Normal file
58
ironicclient/tests/unit/osc/fakes.py
Normal file
58
ironicclient/tests/unit/osc/fakes.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2015 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 sys
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
AUTH_TOKEN = "foobar"
|
||||||
|
AUTH_URL = "http://0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
class FakeApp(object):
|
||||||
|
def __init__(self):
|
||||||
|
_stdout = None
|
||||||
|
self.client_manager = None
|
||||||
|
self.stdin = sys.stdin
|
||||||
|
self.stdout = _stdout or sys.stdout
|
||||||
|
self.stderr = sys.stderr
|
||||||
|
self.restapi = None
|
||||||
|
|
||||||
|
|
||||||
|
class FakeClientManager(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.identity = None
|
||||||
|
self.auth_ref = None
|
||||||
|
|
||||||
|
|
||||||
|
class FakeResource(object):
|
||||||
|
def __init__(self, manager, info, loaded=False):
|
||||||
|
self.__name__ = type(self).__name__
|
||||||
|
self.manager = manager
|
||||||
|
self._info = info
|
||||||
|
self._add_details(info)
|
||||||
|
self._loaded = loaded
|
||||||
|
|
||||||
|
def _add_details(self, info):
|
||||||
|
for (k, v) in six.iteritems(info):
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and
|
||||||
|
k != 'manager')
|
||||||
|
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
|
||||||
|
return "<%s %s>" % (self.__class__.__name__, info)
|
0
ironicclient/tests/unit/osc/v1/__init__.py
Normal file
0
ironicclient/tests/unit/osc/v1/__init__.py
Normal file
52
ironicclient/tests/unit/osc/v1/fakes.py
Normal file
52
ironicclient/tests/unit/osc/v1/fakes.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2015 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 mock
|
||||||
|
from openstackclient.tests import utils
|
||||||
|
|
||||||
|
from ironicclient.tests.unit.osc import fakes
|
||||||
|
|
||||||
|
baremetal_uuid = 'xxx-xxxxxx-xxxx'
|
||||||
|
baremetal_name = 'fake name'
|
||||||
|
baremetal_instance_uuid = 'yyy-yyyyyy-yyyy'
|
||||||
|
baremetal_power_state = None
|
||||||
|
baremetal_provision_state = None
|
||||||
|
baremetal_maintenance = False
|
||||||
|
|
||||||
|
BAREMETAL = {
|
||||||
|
'uuid': baremetal_uuid,
|
||||||
|
'name': baremetal_name,
|
||||||
|
'instance_uuid': baremetal_instance_uuid,
|
||||||
|
'power_state': baremetal_power_state,
|
||||||
|
'provision_state': baremetal_provision_state,
|
||||||
|
'maintenance': baremetal_maintenance,
|
||||||
|
'links': []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetal(utils.TestCommand):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetal, self).setUp()
|
||||||
|
|
||||||
|
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
|
||||||
|
self.app.client_manager.baremetal = mock.Mock()
|
||||||
|
|
||||||
|
|
||||||
|
class FakeBaremetalResource(fakes.FakeResource):
|
||||||
|
|
||||||
|
def get_keys(self):
|
||||||
|
return {'property': 'value'}
|
515
ironicclient/tests/unit/osc/v1/test_baremetal.py
Normal file
515
ironicclient/tests/unit/osc/v1/test_baremetal.py
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2015 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 copy
|
||||||
|
|
||||||
|
from openstackclient.tests import utils as oscutils
|
||||||
|
|
||||||
|
from ironicclient.osc.v1 import baremetal
|
||||||
|
from ironicclient.tests.unit.osc.v1 import fakes as baremetal_fakes
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetal(baremetal_fakes.TestBaremetal):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetal, self).setUp()
|
||||||
|
|
||||||
|
# Get a shortcut to the FlavorManager Mock
|
||||||
|
self.baremetal_mock = self.app.client_manager.baremetal
|
||||||
|
self.baremetal_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalCreate(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalCreate, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.create.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.CreateBaremetal(self.app, None)
|
||||||
|
self.arglist = ['--driver', 'fake_driver']
|
||||||
|
self.verifylist = [('driver', 'fake_driver')]
|
||||||
|
self.collist = (
|
||||||
|
'instance_uuid',
|
||||||
|
'maintenance',
|
||||||
|
'name',
|
||||||
|
'power_state',
|
||||||
|
'provision_state',
|
||||||
|
'uuid'
|
||||||
|
)
|
||||||
|
self.datalist = (
|
||||||
|
'yyy-yyyyyy-yyyy',
|
||||||
|
baremetal_fakes.baremetal_maintenance,
|
||||||
|
baremetal_fakes.baremetal_name,
|
||||||
|
baremetal_fakes.baremetal_power_state,
|
||||||
|
baremetal_fakes.baremetal_provision_state,
|
||||||
|
baremetal_fakes.baremetal_uuid,
|
||||||
|
)
|
||||||
|
self.actual_kwargs = {
|
||||||
|
'driver': 'fake_driver',
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_with_options(self, addl_arglist, addl_verifylist, addl_kwargs):
|
||||||
|
arglist = copy.copy(self.arglist) + addl_arglist
|
||||||
|
verifylist = copy.copy(self.verifylist) + addl_verifylist
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
collist = copy.copy(self.collist)
|
||||||
|
self.assertEqual(collist, columns)
|
||||||
|
|
||||||
|
datalist = copy.copy(self.datalist)
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
kwargs = copy.copy(self.actual_kwargs)
|
||||||
|
kwargs.update(addl_kwargs)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.create.assert_called_once_with(**kwargs)
|
||||||
|
|
||||||
|
def test_baremetal_create_no_options(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
self.assertRaises(oscutils.ParserException,
|
||||||
|
self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
def test_baremetal_create_with_driver(self):
|
||||||
|
arglist = copy.copy(self.arglist)
|
||||||
|
|
||||||
|
verifylist = copy.copy(self.verifylist)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
collist = copy.copy(self.collist)
|
||||||
|
self.assertEqual(collist, columns)
|
||||||
|
|
||||||
|
datalist = copy.copy(self.datalist)
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
kwargs = copy.copy(self.actual_kwargs)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.create.assert_called_once_with(**kwargs)
|
||||||
|
|
||||||
|
def test_baremetal_create_with_chassis(self):
|
||||||
|
self.check_with_options(['--chassis', 'chassis_uuid'],
|
||||||
|
[('chassis_uuid', 'chassis_uuid')],
|
||||||
|
{'chassis_uuid': 'chassis_uuid'})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_driver_info(self):
|
||||||
|
self.check_with_options(['--driver-info', 'arg1=val1',
|
||||||
|
'--driver-info', 'arg2=val2'],
|
||||||
|
[('driver_info',
|
||||||
|
['arg1=val1',
|
||||||
|
'arg2=val2'])],
|
||||||
|
{'driver_info': {
|
||||||
|
'arg1': 'val1',
|
||||||
|
'arg2': 'val2'}})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_properties(self):
|
||||||
|
self.check_with_options(['--property', 'arg1=val1',
|
||||||
|
'--property', 'arg2=val2'],
|
||||||
|
[('properties',
|
||||||
|
['arg1=val1',
|
||||||
|
'arg2=val2'])],
|
||||||
|
{'properties': {
|
||||||
|
'arg1': 'val1',
|
||||||
|
'arg2': 'val2'}})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_extra(self):
|
||||||
|
self.check_with_options(['--extra', 'arg1=val1',
|
||||||
|
'--extra', 'arg2=val2'],
|
||||||
|
[('extra',
|
||||||
|
['arg1=val1',
|
||||||
|
'arg2=val2'])],
|
||||||
|
{'extra': {
|
||||||
|
'arg1': 'val1',
|
||||||
|
'arg2': 'val2'}})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_uuid(self):
|
||||||
|
self.check_with_options(['--uuid', 'uuid'],
|
||||||
|
[('uuid', 'uuid')],
|
||||||
|
{'uuid': 'uuid'})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_name(self):
|
||||||
|
self.check_with_options(['--name', 'name'],
|
||||||
|
[('name', 'name')],
|
||||||
|
{'name': 'name'})
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalDelete(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalDelete, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.get.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.DeleteBaremetal(self.app, None)
|
||||||
|
|
||||||
|
def test_baremetal_delete(self):
|
||||||
|
arglist = ['xxx-xxxxxx-xxxx']
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
args = ['xxx-xxxxxx-xxxx']
|
||||||
|
|
||||||
|
self.baremetal_mock.node.delete.assert_called_with(
|
||||||
|
*args
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalList(TestBaremetal):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalList, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list.return_value = [
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.ListBaremetal(self.app, None)
|
||||||
|
|
||||||
|
def test_baremetal_list_no_options(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
kwargs = {
|
||||||
|
'detail': False,
|
||||||
|
'marker': None,
|
||||||
|
'limit': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list.assert_called_with(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = (
|
||||||
|
"UUID",
|
||||||
|
"Name",
|
||||||
|
"Instance UUID",
|
||||||
|
"Power State",
|
||||||
|
"Provisioning State",
|
||||||
|
"Maintenance"
|
||||||
|
)
|
||||||
|
self.assertEqual(collist, columns)
|
||||||
|
datalist = ((
|
||||||
|
baremetal_fakes.baremetal_uuid,
|
||||||
|
baremetal_fakes.baremetal_name,
|
||||||
|
baremetal_fakes.baremetal_instance_uuid,
|
||||||
|
baremetal_fakes.baremetal_power_state,
|
||||||
|
baremetal_fakes.baremetal_provision_state,
|
||||||
|
baremetal_fakes.baremetal_maintenance,
|
||||||
|
), )
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_baremetal_list_long(self):
|
||||||
|
arglist = [
|
||||||
|
'--long',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('long', True),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
kwargs = {
|
||||||
|
'detail': True,
|
||||||
|
'marker': None,
|
||||||
|
'limit': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list.assert_called_with(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = ('Chassis UUID', 'Created At', 'Clean Step',
|
||||||
|
'Console Enabled', 'Driver', 'Driver Info',
|
||||||
|
'Driver Internal Info', 'Extra', 'Instance Info',
|
||||||
|
'Instance UUID', 'Last Error', 'Maintenance',
|
||||||
|
'Maintenance Reason', 'Power State', 'Properties',
|
||||||
|
'Provisioning State', 'Provision Updated At', 'Reservation',
|
||||||
|
'Target Power State', 'Target Provision State',
|
||||||
|
'Updated At', 'Inspection Finished At',
|
||||||
|
'Inspection Started At', 'UUID', 'Name')
|
||||||
|
self.assertEqual(collist, columns)
|
||||||
|
datalist = ((
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
baremetal_fakes.baremetal_instance_uuid,
|
||||||
|
'',
|
||||||
|
baremetal_fakes.baremetal_maintenance,
|
||||||
|
'',
|
||||||
|
baremetal_fakes.baremetal_power_state,
|
||||||
|
'',
|
||||||
|
baremetal_fakes.baremetal_provision_state,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
baremetal_fakes.baremetal_uuid,
|
||||||
|
baremetal_fakes.baremetal_name,
|
||||||
|
), )
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalSet(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalSet, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.SetBaremetal(self.app, None)
|
||||||
|
|
||||||
|
def test_baremetal_set_no_options(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
self.assertRaises(oscutils.ParserException,
|
||||||
|
self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
def test_baremetal_set_one_property(self):
|
||||||
|
arglist = ['node_uuid', '--property', 'path/to/property=value']
|
||||||
|
verifylist = [
|
||||||
|
('node', 'node_uuid'),
|
||||||
|
('property', ['path/to/property=value']),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid',
|
||||||
|
[{'path': '/path/to/property', 'value': 'value', 'op': 'add'}])
|
||||||
|
|
||||||
|
def test_baremetal_set_multiple_properties(self):
|
||||||
|
arglist = [
|
||||||
|
'node_uuid',
|
||||||
|
'--property', 'path/to/property=value',
|
||||||
|
'--property', 'other/path=value2'
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('node', 'node_uuid'),
|
||||||
|
('property',
|
||||||
|
[
|
||||||
|
'path/to/property=value',
|
||||||
|
'other/path=value2',
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid',
|
||||||
|
[{'path': '/path/to/property', 'value': 'value', 'op': 'add'},
|
||||||
|
{'path': '/other/path', 'value': 'value2', 'op': 'add'}]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalShow(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalShow, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.get.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
self.baremetal_mock.node.get_by_instance_uuid.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.ShowBaremetal(self.app, None)
|
||||||
|
|
||||||
|
def test_baremetal_show(self):
|
||||||
|
arglist = ['xxx-xxxxxx-xxxx']
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
args = ['xxx-xxxxxx-xxxx']
|
||||||
|
|
||||||
|
self.baremetal_mock.node.get.assert_called_with(
|
||||||
|
*args
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = (
|
||||||
|
'instance_uuid',
|
||||||
|
'maintenance',
|
||||||
|
'name',
|
||||||
|
'power_state',
|
||||||
|
'provision_state',
|
||||||
|
'uuid'
|
||||||
|
)
|
||||||
|
self.assertEqual(collist, columns)
|
||||||
|
datalist = (
|
||||||
|
'yyy-yyyyyy-yyyy',
|
||||||
|
baremetal_fakes.baremetal_maintenance,
|
||||||
|
baremetal_fakes.baremetal_name,
|
||||||
|
baremetal_fakes.baremetal_power_state,
|
||||||
|
baremetal_fakes.baremetal_provision_state,
|
||||||
|
baremetal_fakes.baremetal_uuid
|
||||||
|
)
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
def test_baremetal_show_no_node(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
self.assertRaises(oscutils.ParserException,
|
||||||
|
self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
def test_baremetal_show_with_instance_uuid(self):
|
||||||
|
arglist = [
|
||||||
|
'xxx-xxxxxx-xxxx',
|
||||||
|
'--instance',
|
||||||
|
]
|
||||||
|
|
||||||
|
verifylist = [
|
||||||
|
('instance_uuid', True)
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
args = ['xxx-xxxxxx-xxxx']
|
||||||
|
|
||||||
|
self.baremetal_mock.node.get_by_instance_uuid.assert_called_with(
|
||||||
|
*args
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaremetalUnset(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaremetalUnset, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.return_value = (
|
||||||
|
baremetal_fakes.FakeBaremetalResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(baremetal_fakes.BAREMETAL),
|
||||||
|
loaded=True,
|
||||||
|
))
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal.UnsetBaremetal(self.app, None)
|
||||||
|
|
||||||
|
def test_baremetal_unset_no_options(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
|
||||||
|
self.assertRaises(oscutils.ParserException,
|
||||||
|
self.check_parser,
|
||||||
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
def test_baremetal_unset_one_property(self):
|
||||||
|
arglist = ['node_uuid', '--property', 'path/to/property']
|
||||||
|
verifylist = [('node', 'node_uuid'),
|
||||||
|
('property', ['path/to/property'])]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid',
|
||||||
|
[{'path': '/path/to/property', 'op': 'remove'}])
|
||||||
|
|
||||||
|
def test_baremetal_unset_multiple_properties(self):
|
||||||
|
arglist = ['node_uuid',
|
||||||
|
'--property', 'path/to/property',
|
||||||
|
'--property', 'other/path']
|
||||||
|
verifylist = [('node', 'node_uuid'),
|
||||||
|
('property',
|
||||||
|
['path/to/property',
|
||||||
|
'other/path'])]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid',
|
||||||
|
[{'path': '/path/to/property', 'op': 'remove'},
|
||||||
|
{'path': '/other/path', 'op': 'remove'}]
|
||||||
|
)
|
@ -5,10 +5,12 @@ pbr<2.0,>=1.4
|
|||||||
anyjson>=0.3.3
|
anyjson>=0.3.3
|
||||||
appdirs>=1.3.0 # MIT License
|
appdirs>=1.3.0 # MIT License
|
||||||
dogpile.cache>=0.5.4
|
dogpile.cache>=0.5.4
|
||||||
|
cliff>=1.14.0 # Apache-2.0
|
||||||
httplib2>=0.7.5
|
httplib2>=0.7.5
|
||||||
lxml>=2.3
|
lxml>=2.3
|
||||||
oslo.i18n>=1.5.0 # Apache-2.0
|
oslo.i18n>=1.5.0 # Apache-2.0
|
||||||
oslo.utils>=2.0.0 # Apache-2.0
|
oslo.utils>=2.0.0 # Apache-2.0
|
||||||
PrettyTable<0.8,>=0.7
|
PrettyTable<0.8,>=0.7
|
||||||
python-keystoneclient>=1.6.0
|
python-keystoneclient>=1.6.0
|
||||||
|
python-openstackclient>=1.5.0
|
||||||
six>=1.9.0
|
six>=1.9.0
|
||||||
|
11
setup.cfg
11
setup.cfg
@ -25,6 +25,17 @@ packages = ironicclient
|
|||||||
console_scripts =
|
console_scripts =
|
||||||
ironic = ironicclient.shell:main
|
ironic = ironicclient.shell:main
|
||||||
|
|
||||||
|
openstack.cli.extension =
|
||||||
|
baremetal = ironicclient.osc.plugin
|
||||||
|
|
||||||
|
openstack.baremetal.v1 =
|
||||||
|
baremetal_create = ironicclient.osc.v1.baremetal:CreateBaremetal
|
||||||
|
baremetal_delete = ironicclient.osc.v1.baremetal:DeleteBaremetal
|
||||||
|
baremetal_list = ironicclient.osc.v1.baremetal:ListBaremetal
|
||||||
|
baremetal_set = ironicclient.osc.v1.baremetal:SetBaremetal
|
||||||
|
baremetal_show = ironicclient.osc.v1.baremetal:ShowBaremetal
|
||||||
|
baremetal_unset = ironicclient.osc.v1.baremetal:UnsetBaremetal
|
||||||
|
|
||||||
[pbr]
|
[pbr]
|
||||||
autodoc_index_modules = True
|
autodoc_index_modules = True
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user