diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index 136ac1fd7..ceb3a1b0b 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -37,7 +37,7 @@ from ironicclient import exc # http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa # for full details. DEFAULT_VER = '1.9' -LAST_KNOWN_API_VERSION = 65 +LAST_KNOWN_API_VERSION = 66 LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION) LOG = logging.getLogger(__name__) diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py index 9b25c8e7a..e45778415 100755 --- a/ironicclient/osc/v1/baremetal_node.py +++ b/ironicclient/osc/v1/baremetal_node.py @@ -39,6 +39,14 @@ CONFIG_DRIVE_ARG_HELP = _( "more details).") +NETWORK_DATA_ARG_HELP = _( + "JSON string or a file or '-' for stdin to read static network " + "configuration for the baremetal node associated with this ironic node. " + "Format of this file should comply with Nova network data metadata " + "(network_data.json). Depending on ironic boot interface capabilities " + "being used, network configuration may or may not been served to the " + "node for offline network configuration.") + SUPPORTED_INTERFACES = ['bios', 'boot', 'console', 'deploy', 'inspect', 'management', 'network', 'power', 'raid', 'rescue', 'storage', 'vendor'] @@ -402,6 +410,11 @@ class CreateBaremetalNode(command.ShowOne): 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-data', + metavar="", + dest='network_data', + help=NETWORK_DATA_ARG_HELP) parser.add_argument( '--network-interface', metavar='', @@ -477,6 +490,9 @@ class CreateBaremetalNode(command.ShowOne): 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') + if parsed_args.network_data: + fields['network_data'] = utils.handle_json_arg( + parsed_args.network_data, 'static network configuration') fields = utils.args_array_to_dict(fields, 'properties') node = baremetal_client.node.create(**fields)._info @@ -1123,6 +1139,12 @@ class SetBaremetalNode(command.Command): reset_help=_('Reset the network interface to its hardware type ' 'default'), ) + parser.add_argument( + '--network-data', + metavar="", + dest='network_data', + help=NETWORK_DATA_ARG_HELP + ) self._add_interface_args( parser, 'power', set_help=_('Set the power interface for the node'), @@ -1300,6 +1322,12 @@ class SetBaremetalNode(command.Command): properties.extend(utils.args_array_to_patch( 'add', ['instance_info/' + x for x in parsed_args.instance_info])) + if parsed_args.network_data: + network_data = utils.handle_json_arg( + parsed_args.network_data, 'static network configuration') + network_data = ["network_data=%s" % json.dumps(network_data)] + properties.extend(utils.args_array_to_patch('add', network_data)) + if properties: baremetal_client.node.update( parsed_args.node, properties, @@ -1474,6 +1502,11 @@ class UnsetBaremetalNode(command.Command): action='store_true', help=_('Unset inspect interface on this baremetal node'), ) + parser.add_argument( + '--network-data', + action='store_true', + help=_("Unset network data on this baremetal port.") + ) parser.add_argument( "--management-interface", dest='management_interface', @@ -1607,6 +1640,9 @@ class UnsetBaremetalNode(command.Command): properties.extend(utils.args_array_to_patch('remove', ['instance_info/' + x for x in parsed_args.instance_info])) + if parsed_args.network_data: + properties.extend(utils.args_array_to_patch( + 'remove', ["network_data"])) if properties: baremetal_client.node.update(parsed_args.node, properties) elif not parsed_args.target_raid_config: diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py index dbca38a34..99708f5ef 100644 --- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py +++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py @@ -415,6 +415,11 @@ class TestBaremetalCreate(TestBaremetal): [('management_interface', 'management')], {'management_interface': 'management'}) + def test_baremetal_create_with_network_data(self): + self.check_with_options(['--network-data', '{"a": ["b"]}'], + [('network_data', '{"a": ["b"]}')], + {'network_data': {"a": ["b"]}}) + def test_baremetal_create_with_network_interface(self): self.check_with_options(['--network-interface', 'neutron'], [('network_interface', 'neutron')], @@ -2779,10 +2784,33 @@ class TestBaremetalSet(TestBaremetal): self.cmd.take_action(parsed_args) + self.baremetal_mock.node.update.assert_called_once_with( + 'node_uuid', [{'op': 'add', + 'path': '/lessee', + 'value': 'lessee 1'}], + reset_interfaces=None + ) + + @mock.patch.object(commonutils, 'get_from_stdin', autospec=True) + @mock.patch.object(commonutils, 'handle_json_or_file_arg', autospec=True) + def test_baremetal_set_network_data(self, mock_handle, mock_stdin): + self.cmd.log = mock.Mock(autospec=True) + network_data_string = '{"a": ["b"]}' + expected_network_data = {'a': ['b']} + mock_handle.return_value = expected_network_data.copy() + + arglist = ['node_uuid', + '--network-data', network_data_string] + verifylist = [('node', 'node_uuid'), + ('network_data', network_data_string)] + + 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': '/lessee', - 'value': 'lessee 1', + [{'path': '/network_data', 'value': expected_network_data, 'op': 'add'}], reset_interfaces=None, ) @@ -3405,6 +3433,25 @@ class TestBaremetalUnset(TestBaremetal): [{'path': '/lessee', 'op': 'remove'}] ) + def test_baremetal_unset_network_data(self): + arglist = [ + 'node_uuid', + '--network-data', + ] + verifylist = [ + ('node', 'node_uuid'), + ('network_data', True) + ] + + 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': '/network_data', 'op': 'remove'}] + ) + class TestValidate(TestBaremetal): def setUp(self): diff --git a/ironicclient/tests/unit/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py index 70a23efa4..e0d7ddaff 100644 --- a/ironicclient/tests/unit/v1/test_node.py +++ b/ironicclient/tests/unit/v1/test_node.py @@ -36,6 +36,7 @@ NODE1 = {'uuid': '66666666-7777-8888-9999-000000000000', 'driver_info': {'user': 'foo', 'password': 'bar'}, 'properties': {'num_cpu': 4}, 'name': 'fake-node-1', + 'network_data': {}, 'resource_class': 'foo', 'extra': {}, 'conductor_group': 'in-the-closet-to-the-left'} @@ -46,6 +47,7 @@ NODE2 = {'uuid': '66666666-7777-8888-9999-111111111111', 'driver': 'fake too', 'driver_info': {'user': 'foo', 'password': 'bar'}, 'properties': {'num_cpu': 4}, + 'network_data': {}, 'resource_class': 'bar', 'extra': {}, 'owner': '33333333-2222-1111-0000-111111111111', diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py index d70fc6c1c..29f1c8f44 100644 --- a/ironicclient/v1/node.py +++ b/ironicclient/v1/node.py @@ -53,7 +53,7 @@ class NodeManager(base.CreateManager): 'raid_interface', 'rescue_interface', 'storage_interface', 'vendor_interface', 'resource_class', 'conductor_group', - 'automated_clean'] + 'automated_clean', 'network_data'] _resource_name = 'nodes' def list(self, associated=None, maintenance=None, marker=None, diff --git a/ironicclient/v1/resource_fields.py b/ironicclient/v1/resource_fields.py index 3970a9e08..98ad1e0c2 100644 --- a/ironicclient/v1/resource_fields.py +++ b/ironicclient/v1/resource_fields.py @@ -93,6 +93,7 @@ class Resource(object): 'fault': 'Fault', 'mode': 'Mode', 'name': 'Name', + 'network_data': 'Network Configuration', 'node_uuid': 'Node UUID', 'owner': 'Owner', 'power_state': 'Power State', diff --git a/releasenotes/notes/add-network-data-node-attr-81dec9cecb7491b9.yaml b/releasenotes/notes/add-network-data-node-attr-81dec9cecb7491b9.yaml new file mode 100644 index 000000000..d3d56dff5 --- /dev/null +++ b/releasenotes/notes/add-network-data-node-attr-81dec9cecb7491b9.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds support for adding static network configuration to ports and + portgroups by adding ``network-data`` attribute to port/portgroup + commands.