diff --git a/cisco_ironic_contrib/ironic/agent.py b/cisco_ironic_contrib/ironic/agent.py new file mode 100644 index 0000000..2de4429 --- /dev/null +++ b/cisco_ironic_contrib/ironic/agent.py @@ -0,0 +1,26 @@ +# Copyright 2015, Cisco Systems. +# +# 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. + +from ironic.drivers import agent + +from cisco_ironic_contrib.ironic.cimc import boot as cimc_boot +from cisco_ironic_contrib.ironic.cimc import vendor as cimc_vendor + + +class AgentAndCIMCNeutronDriver(agent.AgentAndCIMCDriver): + + def __init__(self): + super(AgentAndCIMCNeutronDriver, self).__init__() + self.boot = cimc_boot.PXEBoot() + self.vendor = cimc_vendor.CIMCPXEVendorPassthru() diff --git a/cisco_ironic_contrib/ironic/cimc/boot.py b/cisco_ironic_contrib/ironic/cimc/boot.py index faaeaaa..da854e6 100644 --- a/cisco_ironic_contrib/ironic/cimc/boot.py +++ b/cisco_ironic_contrib/ironic/cimc/boot.py @@ -23,6 +23,7 @@ from oslo_utils import importutils from ironic.common import boot_devices from ironic.common import pxe_utils from ironic.common import states +from ironic.conductor import utils as manager_utils from ironic.dhcp import neutron from ironic.drivers.modules import deploy_utils from ironic.drivers.modules import pxe @@ -40,6 +41,8 @@ class PXEBoot(pxe.PXEBoot): def _plug_provisioning(self, task, **kwargs): LOG.debug("Plugging the provisioning!") + if task.node.power_state != states.POWER_ON: + manager_utils.node_power_action(task, states.REBOOT) client = neutron._build_client(task.context.auth_token) port = client.create_port({ @@ -72,6 +75,9 @@ class PXEBoot(pxe.PXEBoot): def _unplug_provisioning(self, task, **kwargs): LOG.debug("Unplugging the provisioning!") + if task.node.power_state != states.POWER_ON: + manager_utils.node_power_action(task, states.REBOOT) + client = neutron._build_client(task.context.auth_token) ports = objects.Port.list_by_node_id(task.context, task.node.id) @@ -131,3 +137,4 @@ class PXEBoot(pxe.PXEBoot): def clean_up_ramdisk(self, task): super(PXEBoot, self).clean_up_ramdisk(task) self._unplug_provisioning(task) + task.ports = objects.Port.list_by_node_id(task.context, task.node.id) diff --git a/cisco_ironic_contrib/ironic/cimc/common.py b/cisco_ironic_contrib/ironic/cimc/common.py index cb8d010..fac83e3 100644 --- a/cisco_ironic_contrib/ironic/cimc/common.py +++ b/cisco_ironic_contrib/ironic/cimc/common.py @@ -59,7 +59,7 @@ def add_vnic(task, name, mac, vlan, pxe=False): method, imcsdk.WriteXmlOption.DIRTY) error = getattr(resp, 'error_code', None) if error: - raise imcsdk.ImcException(error) + raise imcsdk.ImcException(node=task.node.uuid, error=error) def delete_vnic(task, name): diff --git a/cisco_ironic_contrib/tests/unit/ironic/cimc/test_boot.py b/cisco_ironic_contrib/tests/unit/ironic/cimc/test_boot.py index 445b35d..e947bb8 100644 --- a/cisco_ironic_contrib/tests/unit/ironic/cimc/test_boot.py +++ b/cisco_ironic_contrib/tests/unit/ironic/cimc/test_boot.py @@ -20,6 +20,7 @@ from ironic.common import boot_devices from ironic.common import pxe_utils from ironic.common import states from ironic.conductor import task_manager +from ironic.conductor import utils as manager_utils from ironic.dhcp import neutron from ironic.drivers.modules import deploy_utils from ironic.drivers.modules import pxe @@ -45,12 +46,13 @@ def with_task(func): class PXEBootTestCase(test_common.CIMCBaseTestCase): + @mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(objects, 'Port', autospec=True) @mock.patch.object(common, 'add_vnic', autospec=True) @mock.patch.object(neutron, '_build_client', autospec=True) @with_task def test_plug_provisioning(self, task, mock__build_client, - mock_add_vnic, mock_port): + mock_add_vnic, mock_port, mock_power): client = mock__build_client.return_value client.create_port.return_value = { 'port': { @@ -78,6 +80,7 @@ class PXEBootTestCase(test_common.CIMCBaseTestCase): } } + mock_power.assert_called_once_with(task, states.REBOOT) client.create_port.assert_called_once_with(neutron_data) client.show_network.assert_called_once_with( CONF.neutron.cleaning_network_uuid) @@ -92,12 +95,13 @@ class PXEBootTestCase(test_common.CIMCBaseTestCase): mock_port.return_value.create.assert_called_once_with() self.assertEqual('1.2.3.4', ip) + @mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(objects, 'Port', autospec=True) @mock.patch.object(neutron, '_build_client', autospec=True) @mock.patch.object(common, 'delete_vnic', autospec=True) @with_task - def test_unplug_provisioning( - self, task, mock_delete_vnic, mock__build_client, mock_port): + def test_unplug_provisioning(self, task, mock_delete_vnic, + mock__build_client, mock_port, mock_power): portMock1 = mock.MagicMock() portMock1.__getitem__.return_value = { @@ -125,6 +129,7 @@ class PXEBootTestCase(test_common.CIMCBaseTestCase): task.driver.boot._unplug_provisioning(task) + mock_power.assert_called_once_with(task, states.REBOOT) mock_delete_vnic.assert_called_once_with(task, 'port2') client.delete_port.assert_called_once_with('port2') portMock2.destroy.assert_called_once_with() diff --git a/setup.cfg b/setup.cfg index fd5c0eb..bfd0b48 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ packages = [entry_points] ironic.drivers = pxe_iscsi_cimc_neutron = cisco_ironic_contrib.ironic.pxe:PXEAndCIMCNeutronDriver + pxe_agent_cimc_neutron = cisco_ironic_contrib.ironic.agent:AgentAndCIMCNeutronDriver [build_sphinx] source-dir = doc/source