[OVN] Prevent binding a virtual type port
A LSP is type=virtual when its IP address is used by other ports as allowed address. If a LSP is type=virtual, this port cannot be bound (that means cannot be used as a port for a virtual machine). Closes-Bug: #2018529 Change-Id: I1943e6e0d7d8e255e95f93881cc3caec16ab67fe
This commit is contained in:
parent
2968e4523b
commit
68ecae5ff9
@ -1051,3 +1051,27 @@ def determine_bind_host(sb_idl, port, port_context=None):
|
||||
bp_info.bp_param[
|
||||
constants.VIF_DETAILS_CARD_SERIAL_NUMBER]).hostname
|
||||
return ''
|
||||
|
||||
|
||||
def validate_port_binding_and_virtual_port(
|
||||
port_context, nb_idl, sb_idl, ml2_plugin, port):
|
||||
"""If the port is type=virtual and it is bound, raise BadRequest"""
|
||||
if not determine_bind_host(sb_idl, port, port_context=port_context):
|
||||
# The port is not bound, exit.
|
||||
return
|
||||
|
||||
fixed_ips = port.get('fixed_ips', [])
|
||||
subnet_ids = set([fixed_ip['subnet_id'] for fixed_ip in fixed_ips
|
||||
if 'subnet_id' in fixed_ip])
|
||||
if not subnet_ids:
|
||||
# If the port has no fixed_ips/subnets, it cannot be virtual.
|
||||
return
|
||||
|
||||
subnets = ml2_plugin.get_subnets(port_context.plugin_context,
|
||||
filters={'id': list(subnet_ids)})
|
||||
port_type, _, _ = get_port_type_virtual_and_parents(
|
||||
subnets, fixed_ips, port['network_id'], port['id'], nb_idl)
|
||||
if port_type == constants.LSP_TYPE_VIRTUAL:
|
||||
raise n_exc.BadRequest(
|
||||
resource='port',
|
||||
msg='A virtual logical switch port cannot be bound to a host')
|
||||
|
@ -818,6 +818,8 @@ class OVNMechanismDriver(api.MechanismDriver):
|
||||
self._validate_ignored_port(port, original_port)
|
||||
ovn_utils.validate_and_get_data_from_binding_profile(port)
|
||||
self._validate_port_extra_dhcp_opts(port)
|
||||
ovn_utils.validate_port_binding_and_virtual_port(
|
||||
context, self.nb_ovn, self.sb_ovn, self._plugin, port)
|
||||
if self._is_port_provisioning_required(port, context.host,
|
||||
context.original_host):
|
||||
self._insert_port_provisioning_block(context.plugin_context,
|
||||
|
@ -4345,7 +4345,7 @@ class TestOVNVVirtualPort(OVNMechanismDriverTestCase):
|
||||
self.fmt, name='net1', admin_state_up=True)['network']
|
||||
self.subnet = self._make_subnet(
|
||||
self.fmt, {'network': self.net},
|
||||
'10.0.0.1', '10.0.0.0/24')['subnet']
|
||||
'10.0.0.1', '10.0.0.0/24')
|
||||
|
||||
@mock.patch.object(ovn_utils, 'determine_bind_host')
|
||||
def test_create_port_with_virtual_type_and_options(self, *args):
|
||||
@ -4356,7 +4356,7 @@ class TestOVNVVirtualPort(OVNMechanismDriverTestCase):
|
||||
'mac_address': '00:00:00:00:00:00',
|
||||
'device_owner': device_owner,
|
||||
'network_id': self.net['id'],
|
||||
'fixed_ips': [{'subnet_id': self.subnet['id'],
|
||||
'fixed_ips': [{'subnet_id': self.subnet['subnet']['id'],
|
||||
'ip_address': '10.0.0.55'}],
|
||||
portbindings.PROFILE: {},
|
||||
}
|
||||
@ -4419,6 +4419,25 @@ class TestOVNVVirtualPort(OVNMechanismDriverTestCase):
|
||||
self.nb_idl.unset_lswitch_port_to_virtual_type.assert_called_once_with(
|
||||
virt_port['id'], parent['id'], if_exists=True)
|
||||
|
||||
def test_update_port_bound(self):
|
||||
with self.port(subnet=self.subnet, is_admin=True) as port:
|
||||
port = port['port']
|
||||
updated_port = copy.deepcopy(port)
|
||||
updated_port[portbindings.HOST_ID] = 'host1'
|
||||
context = mock.Mock(current=updated_port, original=port)
|
||||
with mock.patch.object(self.mech_driver._plugin, 'get_subnets') \
|
||||
as mock_get_subnets:
|
||||
mock_get_subnets.return_value = [self.subnet['subnet']]
|
||||
# 1) The port is not virtual, it has no parents.
|
||||
self.mock_vp_parents.return_value = ''
|
||||
self.mech_driver.update_port_precommit(context)
|
||||
# 2) The port (LSP) has parents, that means it is a virtual
|
||||
# port.
|
||||
self.mock_vp_parents.return_value = ['parent-0', 'parent-1']
|
||||
self.assertRaises(n_exc.BadRequest,
|
||||
self.mech_driver.update_port_precommit,
|
||||
context)
|
||||
|
||||
|
||||
class TestOVNAvailabilityZone(OVNMechanismDriverTestCase):
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
other:
|
||||
- |
|
||||
A ML2/OVN virtual port cannot be bound to a virtual machine. If a port
|
||||
IP address is assigned as an allowed address pair into another port, the
|
||||
first one is considered a virtual port. If the second port (non-virtual)
|
||||
is bound to ML2/OVN, the virtual port cannot be bound to a virtual
|
||||
machine; a virtual port is created only to reserve a set of IP addresses
|
||||
to be used by other ports.
|
Loading…
Reference in New Issue
Block a user