Set binding:host_id on VIFs

Set the 'binding:host_id' on neutron port VIFs when
they are created, or update it for existing ports.

This ensures IP allocation is not deferred by neutron.

If IP allocation is deferred, the config-drive network
metadata will not include enough information to properly
bootstrap the instance networking.

Story: 2009715
Task: 44089
Closes-Bug: #1952573
Change-Id: I7411c1f2fbc57dad0504fe61e278308030f059bf
This commit is contained in:
Harald Jensås 2021-11-30 01:34:13 +01:00
parent 9a890bf0bd
commit 81d820f28f
3 changed files with 52 additions and 1 deletions

View File

@ -73,13 +73,22 @@ class NICs(object):
for nic_type, nic in self._validated:
if nic_type != 'port':
port = self._connection.network.create_port(**nic)
# The 'binding:host_id' must be set to ensure IP allocation
# is not deferred.
# See: https://storyboard.openstack.org/#!/story/2009715
port = self._connection.network.create_port(
binding_host_id=self._node.id, **nic)
self.created_ports.append(port.id)
LOG.info('Created port %(port)s for node %(node)s with '
'%(nic)s', {'port': _utils.log_res(port),
'node': _utils.log_res(self._node),
'nic': nic})
else:
# The 'binding:host_id' must be set to ensure IP allocation
# is not deferred.
# See: https://storyboard.openstack.org/#!/story/2009715
self._connection.network.update_port(
nic, binding_host_id=self._node.id)
port = nic
self._connection.baremetal.attach_vif_to_node(self._node,

View File

@ -529,6 +529,7 @@ class TestProvisionNode(Base):
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -554,6 +555,7 @@ class TestProvisionNode(Base):
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id)
self.api.baremetal.attach_vif_to_node.assert_called_once_with(
self.node, self.api.network.create_port.return_value.id)
@ -594,6 +596,7 @@ class TestProvisionNode(Base):
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -620,6 +623,7 @@ class TestProvisionNode(Base):
config.generate.assert_called_once_with(self.node,
self.allocation.name, mock.ANY)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -659,6 +663,7 @@ class TestProvisionNode(Base):
self.api.baremetal.update_allocation.assert_called_once_with(
self.allocation, name=hostname)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='control-0.example.com-%s' %
self.api.network.find_network.return_value.name)
@ -687,6 +692,7 @@ class TestProvisionNode(Base):
self.assertFalse(self.api.baremetal.update_allocation.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='control-0.example.com-%s' %
self.api.network.find_network.return_value.name)
@ -717,6 +723,7 @@ class TestProvisionNode(Base):
self.assertFalse(self.api.baremetal.update_allocation.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='control-0.example.com-%s' %
self.api.network.find_network.return_value.name)
@ -774,6 +781,7 @@ class TestProvisionNode(Base):
self.api.baremetal.update_allocation.assert_called_once_with(
self.allocation, name=self.node.name)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='control-0-%s' %
self.api.network.find_network.return_value.name)
@ -807,6 +815,7 @@ class TestProvisionNode(Base):
self.assertIs(inst.allocation, self.allocation)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='000-%s' %
self.api.network.find_network.return_value.name)
@ -841,6 +850,7 @@ class TestProvisionNode(Base):
mock.call(self.node.id)
])
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='%s-%s' % (
self.api.baremetal.wait_for_allocation.return_value.name,
@ -878,6 +888,7 @@ class TestProvisionNode(Base):
mock.call(self.node.id)
])
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='%s-%s' % (
self.api.baremetal.wait_for_allocation.return_value.name,
@ -917,6 +928,11 @@ class TestProvisionNode(Base):
[{'port': 'port1'}, {'port': 'port2'}])
self.assertFalse(self.api.network.create_port.called)
self.api.network.update_port.assert_has_calls([
mock.call(self.api.network.find_port.return_value,
binding_host_id=self.node.id),
mock.call(self.api.network.find_port.return_value,
binding_host_id=self.node.id)])
self.api.baremetal.attach_vif_to_node.assert_called_with(
self.node, self.api.network.find_port.return_value.id)
self.assertEqual(2, self.api.baremetal.attach_vif_to_node.call_count)
@ -943,6 +959,7 @@ class TestProvisionNode(Base):
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name,
@ -966,6 +983,7 @@ class TestProvisionNode(Base):
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.get_network.return_value.id,
name='example.com-%s' %
self.api.network.get_network.return_value.name,
@ -994,6 +1012,7 @@ class TestProvisionNode(Base):
self.pr.provision_node(self.node, 'image', [{'network': 'network'}])
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1024,6 +1043,7 @@ class TestProvisionNode(Base):
self.assertFalse(self.api.image.find_image.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1061,6 +1081,7 @@ abcd image
self.assertFalse(self.api.image.find_image.called)
mock_get.assert_called_once_with('https://host/checksums')
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1094,6 +1115,7 @@ abcd image
self.assertFalse(self.api.image.find_image.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1123,6 +1145,7 @@ abcd image
self.assertFalse(self.api.image.find_image.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1154,6 +1177,7 @@ abcd image
self.assertFalse(self.api.image.find_image.called)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1175,6 +1199,7 @@ abcd image
root_size_gb=50)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1196,6 +1221,7 @@ abcd image
swap_size_mb=4096)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1221,6 +1247,7 @@ abcd image
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1246,6 +1273,7 @@ abcd image
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1273,6 +1301,7 @@ abcd image
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1297,6 +1326,7 @@ abcd image
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1322,6 +1352,7 @@ abcd image
self.assertEqual(inst.node, self.node)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)
@ -1345,6 +1376,7 @@ abcd image
wait=3600)
self.api.network.create_port.assert_called_once_with(
binding_host_id=self.node.id,
network_id=self.api.network.find_network.return_value.id,
name='example.com-%s' %
self.api.network.find_network.return_value.name)

View File

@ -0,0 +1,10 @@
---
fixes:
- |
Fixed an issue where instance metadata for network configuration was not
correctly written to the config-drive when using a neutron routed
provider network. The invalid metadata would in most cases cause the
instance network initialization to completely fail, leaving the instance
with no network connectivity. See bug: `2009715
<https://storyboard.openstack.org/#!/story/2009715>`_.