From 78a3dcb5223034a1e7371db4cba32cca69f72b3b Mon Sep 17 00:00:00 2001 From: Dao Cong Tien Date: Tue, 10 Jan 2017 19:20:36 +0700 Subject: [PATCH] Add args to CLI 'node-create' for selecting hardware interfaces Adds the below args to CLI 'ironic node-create' and OSC: --boot-interface --console-interface --deploy-interface --inspect-interface --management-interface --power-interface --raid-interface --vendor-interface Change-Id: I405d067ad2cd71f272241c10ce3760549de94711 Partial-Bug: #1524745 Depends-On: Ic8398a6093189a65a7c1ab5cf7e682577dde3257 --- ironicclient/osc/plugin.py | 2 +- ironicclient/osc/v1/baremetal_node.py | 54 +++++++++++- .../tests/unit/osc/v1/test_baremetal_node.py | 54 +++++++++++- ironicclient/tests/unit/v1/test_node_shell.py | 88 +++++++++++++++++++ ironicclient/v1/node.py | 6 +- ironicclient/v1/node_shell.py | 54 +++++++++++- ironicclient/v1/resource_fields.py | 16 ++++ ...dds-node-create-args-a7ace744515e5943.yaml | 6 ++ 8 files changed, 275 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/bug-1524745-adds-node-create-args-a7ace744515e5943.yaml diff --git a/ironicclient/osc/plugin.py b/ironicclient/osc/plugin.py index 5e4dc7cb5..cf71e0a53 100644 --- a/ironicclient/osc/plugin.py +++ b/ironicclient/osc/plugin.py @@ -25,7 +25,7 @@ LOG = logging.getLogger(__name__) API_VERSION_OPTION = 'os_baremetal_api_version' API_NAME = 'baremetal' -LAST_KNOWN_API_VERSION = 28 +LAST_KNOWN_API_VERSION = 31 API_VERSIONS = { '1.%d' % i: 'ironicclient.v1.client.Client' for i in range(1, LAST_KNOWN_API_VERSION + 1) diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py index 34954370b..5f0f2fb8d 100644 --- a/ironicclient/osc/v1/baremetal_node.py +++ b/ironicclient/osc/v1/baremetal_node.py @@ -293,11 +293,59 @@ class CreateBaremetalNode(command.ShowOne): '--name', metavar='', help="Unique name for the node.") + parser.add_argument( + '--boot-interface', + metavar='', + help='Boot interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--console-interface', + metavar='', + help='Console interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--deploy-interface', + metavar='', + help='Deploy interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--inspect-interface', + metavar='', + help='Inspect interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--management-interface', + metavar='', + help='Management interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') parser.add_argument( '--network-interface', metavar='', help='Network interface used for switching node to ' 'cleaning/provisioning networks.') + parser.add_argument( + '--power-interface', + metavar='', + help='Power interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--raid-interface', + metavar='', + help='RAID interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') + parser.add_argument( + '--vendor-interface', + metavar='', + help='Vendor interface used by the node\'s driver. This is ' + 'only applicable when the specified --driver is a ' + 'hardware type.') parser.add_argument( '--resource-class', metavar='', @@ -312,7 +360,11 @@ class CreateBaremetalNode(command.ShowOne): field_list = ['chassis_uuid', 'driver', 'driver_info', 'properties', 'extra', 'uuid', 'name', - 'network_interface', 'resource_class'] + 'boot_interface', 'console_interface', + 'deploy_interface', 'inspect_interface', + 'management_interface', 'network_interface', + 'power_interface', 'raid_interface', + 'vendor_interface', 'resource_class'] 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') diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py index 942e9e87c..f1b503812 100644 --- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py +++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py @@ -334,11 +334,51 @@ class TestBaremetalCreate(TestBaremetal): [('name', 'name')], {'name': 'name'}) + def test_baremetal_create_with_boot_interface(self): + self.check_with_options(['--boot-interface', 'boot'], + [('boot_interface', 'boot')], + {'boot_interface': 'boot'}) + + def test_baremetal_create_with_console_interface(self): + self.check_with_options(['--console-interface', 'console'], + [('console_interface', 'console')], + {'console_interface': 'console'}) + + def test_baremetal_create_with_deploy_interface(self): + self.check_with_options(['--deploy-interface', 'deploy'], + [('deploy_interface', 'deploy')], + {'deploy_interface': 'deploy'}) + + def test_baremetal_create_with_inspect_interface(self): + self.check_with_options(['--inspect-interface', 'inspect'], + [('inspect_interface', 'inspect')], + {'inspect_interface': 'inspect'}) + + def test_baremetal_create_with_management_interface(self): + self.check_with_options(['--management-interface', 'management'], + [('management_interface', 'management')], + {'management_interface': 'management'}) + def test_baremetal_create_with_network_interface(self): self.check_with_options(['--network-interface', 'neutron'], [('network_interface', 'neutron')], {'network_interface': 'neutron'}) + def test_baremetal_create_with_power_interface(self): + self.check_with_options(['--power-interface', 'power'], + [('power_interface', 'power')], + {'power_interface': 'power'}) + + def test_baremetal_create_with_raid_interface(self): + self.check_with_options(['--raid-interface', 'raid'], + [('raid_interface', 'raid')], + {'raid_interface': 'raid'}) + + def test_baremetal_create_with_vendor_interface(self): + self.check_with_options(['--vendor-interface', 'vendor'], + [('vendor_interface', 'vendor')], + {'vendor_interface': 'vendor'}) + def test_baremetal_create_with_resource_class(self): self.check_with_options(['--resource-class', 'foo'], [('resource_class', 'foo')], @@ -499,7 +539,11 @@ class TestBaremetalList(TestBaremetal): 'Target RAID configuration', 'Updated At', 'Inspection Finished At', 'Inspection Started At', 'UUID', 'Name', - 'Network Interface') + 'Boot Interface', 'Console Interface', + 'Deploy Interface', 'Inspect Interface', + 'Management Interface', 'Network Interface', + 'Power Interface', 'RAID Interface', + 'Vendor Interface') self.assertEqual(collist, columns) datalist = (( '', @@ -531,6 +575,14 @@ class TestBaremetalList(TestBaremetal): baremetal_fakes.baremetal_uuid, baremetal_fakes.baremetal_name, '', + '', + '', + '', + '', + '', + '', + '', + '', ), ) self.assertEqual(datalist, tuple(data)) diff --git a/ironicclient/tests/unit/v1/test_node_shell.py b/ironicclient/tests/unit/v1/test_node_shell.py index 8cd572c17..a4f12f481 100644 --- a/ironicclient/tests/unit/v1/test_node_shell.py +++ b/ironicclient/tests/unit/v1/test_node_shell.py @@ -47,7 +47,15 @@ class NodeShellTest(utils.BaseTestCase): 'maintenance', 'maintenance_reason', 'name', + 'boot_interface', + 'console_interface', + 'deploy_interface', + 'inspect_interface', + 'management_interface', 'network_interface', + 'power_interface', + 'raid_interface', + 'vendor_interface', 'power_state', 'properties', 'provision_state', @@ -198,6 +206,56 @@ class NodeShellTest(utils.BaseTestCase): 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() @@ -208,6 +266,36 @@ class NodeShellTest(utils.BaseTestCase): 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_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() diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py index ac806f3f4..c95bd4182 100644 --- a/ironicclient/v1/node.py +++ b/ironicclient/v1/node.py @@ -46,7 +46,11 @@ class NodeManager(base.CreateManager): resource_class = Node _creation_attributes = ['chassis_uuid', 'driver', 'driver_info', 'extra', 'uuid', 'properties', 'name', - 'network_interface', 'resource_class'] + 'boot_interface', 'console_interface', + 'deploy_interface', 'inspect_interface', + 'management_interface', 'network_interface', + 'power_interface', 'raid_interface', + 'vendor_interface', 'resource_class'] _resource_name = 'nodes' def list(self, associated=None, maintenance=None, marker=None, limit=None, diff --git a/ironicclient/v1/node_shell.py b/ironicclient/v1/node_shell.py index 6b22b3c89..72449137e 100644 --- a/ironicclient/v1/node_shell.py +++ b/ironicclient/v1/node_shell.py @@ -212,11 +212,59 @@ def do_node_list(cc, args): '-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( + '--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='', @@ -226,7 +274,11 @@ 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', - 'network_interface', 'resource_class'] + 'boot_interface', 'console_interface', + 'deploy_interface', 'inspect_interface', + 'management_interface', 'network_interface', + 'power_interface', 'raid_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') diff --git a/ironicclient/v1/resource_fields.py b/ironicclient/v1/resource_fields.py index 4408080ad..e7ed956dd 100644 --- a/ironicclient/v1/resource_fields.py +++ b/ironicclient/v1/resource_fields.py @@ -70,7 +70,15 @@ class Resource(object): 'local_link_connection': 'Local Link Connection', 'pxe_enabled': 'PXE boot enabled', 'portgroup_uuid': 'Portgroup UUID', + 'boot_interface': 'Boot Interface', + 'console_interface': 'Console Interface', + 'deploy_interface': 'Deploy Interface', + 'inspect_interface': 'Inspect Interface', + 'management_interface': 'Management Interface', 'network_interface': 'Network Interface', + 'power_interface': 'Power Interface', + 'raid_interface': 'RAID Interface', + 'vendor_interface': 'Vendor Interface', 'standalone_ports_supported': 'Standalone Ports Supported', 'id': 'ID', } @@ -161,7 +169,15 @@ NODE_DETAILED_RESOURCE = Resource( 'inspection_started_at', 'uuid', 'name', + 'boot_interface', + 'console_interface', + 'deploy_interface', + 'inspect_interface', + 'management_interface', 'network_interface', + 'power_interface', + 'raid_interface', + 'vendor_interface', ], sort_excluded=[ # The server cannot sort on "chassis_uuid" because it isn't a column in diff --git a/releasenotes/notes/bug-1524745-adds-node-create-args-a7ace744515e5943.yaml b/releasenotes/notes/bug-1524745-adds-node-create-args-a7ace744515e5943.yaml new file mode 100644 index 000000000..209705ba1 --- /dev/null +++ b/releasenotes/notes/bug-1524745-adds-node-create-args-a7ace744515e5943.yaml @@ -0,0 +1,6 @@ +--- +features: + - Add new arguments to the CLI node-create to allow selecting + boot, console, deploy, inspect, management, power, raid, and vendor + hardware interfaces, when hardware types are used. They are available + starting with ironic API microversion 1.31.