Add openstack baremetal driver commands
Extends the OSC plugin with new commands related to the drivers: * openstack baremetal driver list * openstack baremetal driver passthru call * openstack baremetal driver passthru list * openstack baremetal driver show Change-Id: I68ae82d1ff7e2944c1d04f86c4362b6c0f499df1 Partial-Bug: 1526479 Co-Authored-By: Ruby Loo <ruby.loo@intel.com>
This commit is contained in:
parent
8d86ed4a0a
commit
e31544bf5d
164
ironicclient/osc/v1/baremetal_driver.py
Normal file
164
ironicclient/osc/v1/baremetal_driver.py
Normal file
@ -0,0 +1,164 @@
|
||||
# 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 logging
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils as oscutils
|
||||
|
||||
from ironicclient.common import utils
|
||||
from ironicclient.v1 import resource_fields as res_fields
|
||||
|
||||
|
||||
class ListBaremetalDriver(command.Lister):
|
||||
"""List the enabled drivers."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".ListBaremetalDriver")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListBaremetalDriver, self).get_parser(prog_name)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
client = self.app.client_manager.baremetal
|
||||
|
||||
labels = ['Supported driver(s)', 'Active host(s)']
|
||||
columns = ['name', 'hosts']
|
||||
|
||||
drivers = client.driver.list()
|
||||
drivers = oscutils.sort_items(drivers, 'name')
|
||||
for d in drivers:
|
||||
d.hosts = ', '.join(d.hosts)
|
||||
|
||||
return (labels,
|
||||
(oscutils.get_item_properties(s, columns) for s in drivers))
|
||||
|
||||
|
||||
class PassthruCallBaremetalDriver(command.ShowOne):
|
||||
"""Call a vendor passthru method for a driver."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".PassthruCallBaremetalDriver")
|
||||
http_methods = ['POST', 'PUT', 'GET', 'DELETE', 'PATCH']
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(PassthruCallBaremetalDriver, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'driver',
|
||||
metavar='<driver>',
|
||||
help='Name of the driver.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'method',
|
||||
metavar='<method>',
|
||||
help="Vendor passthru method to be called."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--arg',
|
||||
metavar='<key=value>',
|
||||
action='append',
|
||||
help="Argument to pass to the passthru method (repeat option "
|
||||
"to specify multiple arguments)."
|
||||
)
|
||||
parser.add_argument(
|
||||
'--http-method',
|
||||
dest='http_method',
|
||||
metavar='<http-method>',
|
||||
choices=self.http_methods,
|
||||
default='POST',
|
||||
help="The HTTP method to use in the passthru request. One of "
|
||||
"%s. Defaults to 'POST'." %
|
||||
oscutils.format_list(self.http_methods)
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
baremetal_client = self.app.client_manager.baremetal
|
||||
|
||||
arguments = utils.args_array_to_dict(
|
||||
{'args': parsed_args.arg}, 'args')['args']
|
||||
if not arguments:
|
||||
arguments = {}
|
||||
|
||||
response = (baremetal_client.driver.
|
||||
vendor_passthru(parsed_args.driver,
|
||||
parsed_args.method,
|
||||
http_method=parsed_args.http_method,
|
||||
args=arguments))
|
||||
|
||||
return self.dict2columns(response)
|
||||
|
||||
|
||||
class PassthruListBaremetalDriver(command.Lister):
|
||||
"""List available vendor passthru methods for a driver."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".PassthruListBaremetalDriver")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(PassthruListBaremetalDriver, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'driver',
|
||||
metavar='<driver>',
|
||||
help='Name of the driver.')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
baremetal_client = self.app.client_manager.baremetal
|
||||
|
||||
columns = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.fields
|
||||
labels = res_fields.VENDOR_PASSTHRU_METHOD_RESOURCE.labels
|
||||
|
||||
methods = baremetal_client.driver.get_vendor_passthru_methods(
|
||||
parsed_args.driver)
|
||||
|
||||
params = []
|
||||
for method, response in methods.items():
|
||||
response['name'] = method
|
||||
http_methods = ', '.join(response['http_methods'])
|
||||
response['http_methods'] = http_methods
|
||||
params.append(response)
|
||||
|
||||
return (labels,
|
||||
(oscutils.get_dict_properties(s, columns) for s in params))
|
||||
|
||||
|
||||
class ShowBaremetalDriver(command.ShowOne):
|
||||
"""Show information about a driver."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".ShowBaremetalDriver")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowBaremetalDriver, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'driver',
|
||||
metavar='<driver>',
|
||||
help='Name of the driver.')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
baremetal_client = self.app.client_manager.baremetal
|
||||
|
||||
driver = baremetal_client.driver.get(parsed_args.driver)._info
|
||||
driver.pop("links", None)
|
||||
driver.pop("properties", None)
|
||||
# NOTE(rloo): this will show the hosts as a comma-separated string
|
||||
# whereas 'ironic driver show' displays this as a list
|
||||
# of hosts (eg "host1, host2" vs "[u'host1', u'host2']"
|
||||
driver['hosts'] = ', '.join(driver.get('hosts', ()))
|
||||
return zip(*sorted(driver.items()))
|
@ -47,6 +47,21 @@ BAREMETAL_PORT = {
|
||||
'node_uuid': baremetal_uuid,
|
||||
}
|
||||
|
||||
baremetal_driver_hosts = ['fake-host1', 'fake-host2']
|
||||
baremetal_driver_name = 'fakedrivername'
|
||||
|
||||
BAREMETAL_DRIVER = {
|
||||
'hosts': baremetal_driver_hosts,
|
||||
'name': baremetal_driver_name,
|
||||
}
|
||||
|
||||
baremetal_driver_passthru_method = 'lookup'
|
||||
|
||||
BAREMETAL_DRIVER_PASSTHRU = {"lookup": {"attach": "false",
|
||||
"http_methods": ["POST"],
|
||||
"description": "",
|
||||
"async": "false"}}
|
||||
|
||||
|
||||
class TestBaremetal(utils.TestCommand):
|
||||
|
||||
|
223
ironicclient/tests/unit/osc/v1/test_baremetal_driver.py
Normal file
223
ironicclient/tests/unit/osc/v1/test_baremetal_driver.py
Normal file
@ -0,0 +1,223 @@
|
||||
# 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 copy
|
||||
|
||||
from osc_lib.tests import utils as oscutils
|
||||
|
||||
from ironicclient.osc.v1 import baremetal_driver
|
||||
from ironicclient.tests.unit.osc.v1 import fakes as baremetal_fakes
|
||||
|
||||
|
||||
class TestBaremetalDriver(baremetal_fakes.TestBaremetal):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBaremetalDriver, self).setUp()
|
||||
|
||||
self.baremetal_mock = self.app.client_manager.baremetal
|
||||
self.baremetal_mock.reset_mock()
|
||||
|
||||
|
||||
class TestListBaremetalDriver(TestBaremetalDriver):
|
||||
|
||||
def setUp(self):
|
||||
super(TestListBaremetalDriver, self).setUp()
|
||||
|
||||
self.baremetal_mock.driver.list.return_value = [
|
||||
baremetal_fakes.FakeBaremetalResource(
|
||||
None,
|
||||
copy.deepcopy(baremetal_fakes.BAREMETAL_DRIVER),
|
||||
loaded=True)
|
||||
]
|
||||
self.cmd = baremetal_driver.ListBaremetalDriver(self.app, None)
|
||||
|
||||
def test_baremetal_driver_list(self):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
collist = (
|
||||
"Supported driver(s)",
|
||||
"Active host(s)")
|
||||
self.assertEqual(collist, tuple(columns))
|
||||
|
||||
datalist = ((
|
||||
baremetal_fakes.baremetal_driver_name,
|
||||
', '.join(baremetal_fakes.baremetal_driver_hosts)), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
|
||||
class TestPassthruCallBaremetalDriver(TestBaremetalDriver):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPassthruCallBaremetalDriver, self).setUp()
|
||||
|
||||
self.baremetal_mock.driver.vendor_passthru.return_value = (
|
||||
baremetal_fakes.BAREMETAL_DRIVER_PASSTHRU
|
||||
)
|
||||
|
||||
self.cmd = baremetal_driver.PassthruCallBaremetalDriver(self.app, None)
|
||||
|
||||
def test_baremetal_driver_passthru_call_with_min_args(self):
|
||||
|
||||
arglist = [
|
||||
baremetal_fakes.baremetal_driver_name,
|
||||
baremetal_fakes.baremetal_driver_passthru_method,
|
||||
]
|
||||
|
||||
verifylist = [
|
||||
('driver', baremetal_fakes.baremetal_driver_name),
|
||||
('method', baremetal_fakes.baremetal_driver_passthru_method),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
args = [
|
||||
baremetal_fakes.baremetal_driver_name,
|
||||
baremetal_fakes.baremetal_driver_passthru_method,
|
||||
]
|
||||
kwargs = {
|
||||
'http_method': 'POST',
|
||||
'args': {}
|
||||
}
|
||||
(self.baremetal_mock.driver.vendor_passthru.
|
||||
assert_called_once_with(*args, **kwargs))
|
||||
|
||||
def test_baremetal_driver_passthru_call_with_all_args(self):
|
||||
|
||||
arglist = [
|
||||
baremetal_fakes.baremetal_driver_name,
|
||||
baremetal_fakes.baremetal_driver_passthru_method,
|
||||
'--arg', 'arg1=val1', '--arg', 'arg2=val2',
|
||||
'--http-method', 'POST'
|
||||
]
|
||||
|
||||
verifylist = [
|
||||
('driver', baremetal_fakes.baremetal_driver_name),
|
||||
('method', baremetal_fakes.baremetal_driver_passthru_method),
|
||||
('arg', ['arg1=val1', 'arg2=val2']),
|
||||
('http_method', 'POST')
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
args = [
|
||||
baremetal_fakes.baremetal_driver_name,
|
||||
baremetal_fakes.baremetal_driver_passthru_method,
|
||||
]
|
||||
kwargs = {
|
||||
'http_method': 'POST',
|
||||
'args': {'arg1': 'val1', 'arg2': 'val2'}
|
||||
}
|
||||
(self.baremetal_mock.driver.vendor_passthru.
|
||||
assert_called_once_with(*args, **kwargs))
|
||||
|
||||
def test_baremetal_driver_passthru_call_no_arg(self):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
self.assertRaises(oscutils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
|
||||
class TestPassthruListBaremetalDriver(TestBaremetalDriver):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPassthruListBaremetalDriver, self).setUp()
|
||||
|
||||
self.baremetal_mock.driver.get_vendor_passthru_methods.return_value = (
|
||||
baremetal_fakes.BAREMETAL_DRIVER_PASSTHRU
|
||||
)
|
||||
self.cmd = baremetal_driver.PassthruListBaremetalDriver(self.app, None)
|
||||
|
||||
def test_baremetal_driver_passthru_list(self):
|
||||
arglist = ['fakedrivername']
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
args = ['fakedrivername']
|
||||
(self.baremetal_mock.driver.get_vendor_passthru_methods.
|
||||
assert_called_with(*args))
|
||||
|
||||
collist = (
|
||||
"Name",
|
||||
"Supported HTTP methods",
|
||||
"Async",
|
||||
"Description",
|
||||
"Response is attachment",
|
||||
)
|
||||
self.assertEqual(collist, tuple(columns))
|
||||
|
||||
datalist = (('lookup', 'POST', 'false', '', 'false'),)
|
||||
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_baremetal_driver_passthru_list_no_arg(self):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
self.assertRaises(oscutils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
|
||||
class TestShowBaremetalDriver(TestBaremetalDriver):
|
||||
|
||||
def setUp(self):
|
||||
super(TestShowBaremetalDriver, self).setUp()
|
||||
|
||||
self.baremetal_mock.driver.get.return_value = (
|
||||
baremetal_fakes.FakeBaremetalResource(
|
||||
None,
|
||||
copy.deepcopy(baremetal_fakes.BAREMETAL_DRIVER),
|
||||
loaded=True))
|
||||
self.cmd = baremetal_driver.ShowBaremetalDriver(self.app, None)
|
||||
|
||||
def test_baremetal_driver_show(self):
|
||||
arglist = ['fakedrivername']
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
args = ['fakedrivername']
|
||||
self.baremetal_mock.driver.get.assert_called_with(*args)
|
||||
self.assertFalse(self.baremetal_mock.driver.properties.called)
|
||||
|
||||
collist = ('hosts', 'name')
|
||||
self.assertEqual(collist, columns)
|
||||
|
||||
datalist = (
|
||||
', '.join(baremetal_fakes.baremetal_driver_hosts),
|
||||
baremetal_fakes.baremetal_driver_name)
|
||||
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_baremetal_driver_show_no_arg(self):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
self.assertRaises(oscutils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
10
releasenotes/notes/osc-plugin-b82e1edd55fb6185.yaml
Normal file
10
releasenotes/notes/osc-plugin-b82e1edd55fb6185.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Extend the OpenStackClient plugin with new commands:
|
||||
|
||||
* openstack baremetal driver list
|
||||
* openstack baremetal driver passthru call
|
||||
* openstack baremetal driver passthru list
|
||||
* openstack baremetal driver show
|
||||
|
@ -31,6 +31,10 @@ openstack.cli.extension =
|
||||
openstack.baremetal.v1 =
|
||||
baremetal_create = ironicclient.osc.v1.baremetal_create:CreateBaremetal
|
||||
baremetal_delete = ironicclient.osc.v1.baremetal_node:DeleteBaremetal
|
||||
baremetal_driver_list = ironicclient.osc.v1.baremetal_driver:ListBaremetalDriver
|
||||
baremetal_driver_passthru_call = ironicclient.osc.v1.baremetal_driver:PassthruCallBaremetalDriver
|
||||
baremetal_driver_passthru_list = ironicclient.osc.v1.baremetal_driver:PassthruListBaremetalDriver
|
||||
baremetal_driver_show = ironicclient.osc.v1.baremetal_driver:ShowBaremetalDriver
|
||||
baremetal_list = ironicclient.osc.v1.baremetal_node:ListBaremetal
|
||||
baremetal_node_abort = ironicclient.osc.v1.baremetal_node:AbortBaremetalNode
|
||||
baremetal_node_adopt = ironicclient.osc.v1.baremetal_node:AdoptBaremetalNode
|
||||
|
Loading…
Reference in New Issue
Block a user