[Ironic]Match vif-pif mac address before setting 'vif_port_id'

When booting an ironic instance with multi networks, the ironic port
'vif_port_id' may mismatch with the corresponding neutron port.

Closes-Bug: #1549068
Co-Authored-By: Sivaramakrishna Garimella (sivaramakrishna.garimella@hp.com)

Change-Id: Id5f033136283987eef8de4ce2f6be256e48cdbf8
(cherry picked from commit e147a63cb3)
This commit is contained in:
Zhenguo Niu 2016-02-24 17:14:59 +08:00
parent aa4edd349d
commit 21141158f7
3 changed files with 71 additions and 9 deletions

View File

@ -1322,7 +1322,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test_plug_vifs_with_port(self, mock_uvifs, mock_port_udt, mock_lp):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
port = ironic_utils.get_test_port()
# make the address be consistent with network_info's
port = ironic_utils.get_test_port(address='fake')
mock_lp.return_value = [port]
@ -1356,6 +1357,46 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_get.assert_called_once_with(node_uuid)
mock__plug_vifs.assert_called_once_with(node, instance, network_info)
@mock.patch.object(FAKE_CLIENT.port, 'update')
@mock.patch.object(FAKE_CLIENT.node, 'list_ports')
@mock.patch.object(ironic_driver.IronicDriver, '_unplug_vifs')
def test_plug_vifs_multiple_ports(self, mock_uvifs, mock_lp,
mock_port_udt):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
first_ironic_port_uuid = 'aaaaaaaa-bbbb-1111-dddd-eeeeeeeeeeee'
first_port = ironic_utils.get_test_port(uuid=first_ironic_port_uuid,
node_uuid=node_uuid,
address='11:FF:FF:FF:FF:FF')
second_ironic_port_uuid = 'aaaaaaaa-bbbb-2222-dddd-eeeeeeeeeeee'
second_port = ironic_utils.get_test_port(uuid=second_ironic_port_uuid,
node_uuid=node_uuid,
address='22:FF:FF:FF:FF:FF')
mock_lp.return_value = [second_port, first_port]
instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
first_vif_id = 'aaaaaaaa-vv11-cccc-dddd-eeeeeeeeeeee'
second_vif_id = 'aaaaaaaa-vv22-cccc-dddd-eeeeeeeeeeee'
first_vif = ironic_utils.get_test_vif(
address='22:FF:FF:FF:FF:FF',
id=second_vif_id)
second_vif = ironic_utils.get_test_vif(
address='11:FF:FF:FF:FF:FF',
id=first_vif_id)
network_info = [first_vif, second_vif]
self.driver._plug_vifs(node, instance, network_info)
# asserts
mock_uvifs.assert_called_once_with(node, instance, network_info)
mock_lp.assert_called_once_with(node_uuid)
calls = (mock.call(first_ironic_port_uuid,
[{'op': 'add', 'path': '/extra/vif_port_id',
'value': first_vif_id}]),
mock.call(second_ironic_port_uuid,
[{'op': 'add', 'path': '/extra/vif_port_id',
'value': second_vif_id}]))
mock_port_udt.assert_has_calls(calls, any_order=True)
@mock.patch.object(FAKE_CLIENT.port, 'update')
@mock.patch.object(FAKE_CLIENT.node, 'list_ports')
@mock.patch.object(ironic_driver.IronicDriver, '_unplug_vifs')

View File

@ -60,6 +60,24 @@ def get_test_port(**kw):
'updated_at': kw.get('updated_at')})()
def get_test_vif(**kw):
return {
'profile': kw.get('profile', {}),
'ovs_interfaceid': kw.get('ovs_interfaceid'),
'preserve_on_delete': kw.get('preserve_on_delete', False),
'network': kw.get('network', {}),
'devname': kw.get('devname', 'tapaaaaaaaa-00'),
'vnic_type': kw.get('vnic_type', 'baremetal'),
'qbh_params': kw.get('qbh_params'),
'meta': kw.get('meta', {}),
'details': kw.get('details', {}),
'address': kw.get('address', 'FF:FF:FF:FF:FF:FF'),
'active': kw.get('active', True),
'type': kw.get('type', 'ironic'),
'id': kw.get('id', 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'),
'qbg_params': kw.get('qbg_params')}
def get_test_flavor(**kw):
default_extra_specs = {'baremetal:deploy_kernel_id':
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',

View File

@ -1085,13 +1085,16 @@ class IronicDriver(virt_driver.ComputeDriver):
if len(network_info) > 0:
# not needed if no vif are defined
for vif, pif in zip(network_info, ports):
# attach what neutron needs directly to the port
port_id = six.text_type(vif['id'])
patch = [{'op': 'add',
'path': '/extra/vif_port_id',
'value': port_id}]
self.ironicclient.call("port.update", pif.uuid, patch)
for vif in network_info:
for pif in ports:
if vif['address'] == pif.address:
# attach what neutron needs directly to the port
port_id = six.text_type(vif['id'])
patch = [{'op': 'add',
'path': '/extra/vif_port_id',
'value': port_id}]
self.ironicclient.call("port.update", pif.uuid, patch)
break
def _unplug_vifs(self, node, instance, network_info):
# NOTE(PhilDay): Accessing network_info will block if the thread
@ -1106,7 +1109,7 @@ class IronicDriver(virt_driver.ComputeDriver):
detail=True)
# not needed if no vif are defined
for vif, pif in zip(network_info, ports):
for pif in ports:
if 'vif_port_id' in pif.extra:
# we can not attach a dict directly
patch = [{'op': 'remove', 'path': '/extra/vif_port_id'}]