diff --git a/os_cloud_config/nodes.py b/os_cloud_config/nodes.py index 9cc9f85..989564f 100644 --- a/os_cloud_config/nodes.py +++ b/os_cloud_config/nodes.py @@ -19,6 +19,9 @@ import time from ironicclient import client as ironicclient from ironicclient.openstack.common.apiclient import exceptions as ironicexp +from novaclient.extension import Extension +from novaclient.v1_1 import client as novav11client +from novaclient.v1_1.contrib import baremetal def _get_id_line(lines, id_description, position=3): @@ -43,15 +46,14 @@ def _check_output(command): def register_nova_bm_node(service_host, node, client=None): if not service_host: raise ValueError("Nova-baremetal requires a service host.") - out = _check_output(["nova", "baremetal-node-create", - "--pm_address=%s" % node["pm_addr"], - "--pm_user=%s" % node["pm_user"], - "--pm_password=%s" % node["pm_password"], - service_host, node["cpu"], node["memory"], - node["disk"], node["mac"][0]]) - bm_id = _get_id_line(out, " id ") + bm_node = client.baremetal.create(service_host, node["cpu"], + node["memory"], node["disk"], + node["mac"][0], + pm_address=node["pm_addr"], + pm_user=node["pm_user"], + pm_password=node["pm_password"]) for mac in node["mac"][1:]: - subprocess.check_call(["nova", "baremetal-interface-add", bm_id, mac]) + client.baremetal.add_interface(bm_node, mac) def register_ironic_node(service_host, node, client=None): @@ -87,6 +89,15 @@ def register_ironic_node(service_host, node, client=None): client.node.set_power_state(ironic_node.uuid, 'off') +def _get_nova_bm_client(): + baremetal_extension = Extension('baremetal', baremetal) + return novav11client.Client(os.environ["OS_USERNAME"], + os.environ["OS_PASSWORD"], + os.environ["OS_TENANT_NAME"], + os.environ["OS_AUTH_URL"], + extensions=[baremetal_extension]) + + def _get_ironic_client(): kwargs = {'os_username': os.environ['OS_USERNAME'], 'os_password': os.environ['OS_PASSWORD'], @@ -101,6 +112,8 @@ def register_all_nodes(service_host, nodes_list, client=None): client = _get_ironic_client() register_func = register_ironic_node else: + if client is None: + client = _get_nova_bm_client() register_func = register_nova_bm_node for node in nodes_list: register_func(service_host, node, client=client) diff --git a/os_cloud_config/tests/test_nodes.py b/os_cloud_config/tests/test_nodes.py index d087902..58b48cb 100644 --- a/os_cloud_config/tests/test_nodes.py +++ b/os_cloud_config/tests/test_nodes.py @@ -33,16 +33,27 @@ class NodesTest(base.TestCase): self.assertEqual("/dev/null\n", nodes._check_output(["ls", "/dev/null"])) - @mock.patch('os_cloud_config.nodes._check_output') + @mock.patch('os.environ') + @mock.patch('novaclient.v1_1.client.Client') + def test_get_nova_bm_client(self, client_mock, environ): + nodes._get_nova_bm_client() + client_mock.assert_called_once_with(environ["OS_USERNAME"], + environ["OS_PASSWORD"], + environ["OS_AUTH_URL"], + environ["OS_TENANT_NAME"], + extensions=[mock.ANY]) + @mock.patch('os_cloud_config.nodes.using_ironic', return_value=False) - def test_register_all_nodes_nova_bm(self, ironic_mock, check_mock): + def test_register_all_nodes_nova_bm(self, ironic_mock): node_list = [self._get_node(), self._get_node()] - nodes.register_all_nodes('servicehost', node_list) + node_list[0]["mac"].append("bbb") + client = mock.MagicMock() + nodes.register_all_nodes('servicehost', node_list, client=client) nova_bm_call = mock.call( - ["nova", "baremetal-node-create", "--pm_address=foo.bar", - "--pm_user=test", "--pm_password=random", "servicehost", "1", - "2048", "30", "aaa"]) - check_mock.has_calls([nova_bm_call, nova_bm_call]) + "servicehost", "1", "2048", "30", "aaa", pm_address="foo.bar", + pm_user="test", pm_password="random") + client.baremetal.create.has_calls([nova_bm_call, nova_bm_call]) + client.baremetal.add_interface.assert_called_once_with(mock.ANY, "bbb") @mock.patch('os.environ') @mock.patch('ironicclient.client.get_client') diff --git a/requirements.txt b/requirements.txt index 763f1bf..83acbe3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ argparse Babel>=1.3 python-ironicclient python-keystoneclient>=0.6.0 +python-novaclient>=2.17.0 oslo.config>=1.2.0 pyOpenSSL>=0.11 simplejson>=2.0.9