VMware: expand support for Opaque networks
The original support for Opaque networks make use of a configuration flag indicating that a global integration bridge was configured on the ESX host. If this global integration bridge was used then that would be selected as the opaque network. The next generation NSX neutron plugin will not make use of the integration bridge. This will require that we make use of the network ID for the opaque network. The support for VC 6.0 has specific support for this. For 5.5 we make use of a DynamicProperty setting to achieve the same goal. DocImpact For backward compatible opaque support the setting 'CONF.vmware.integration_bridge' needs to be set. If this is not set then the network id will be used as the opaque id. In addition to this the default value has been set to 'None'. Implements blueprint vmware-expand-opaque-support Change-Id: I309ca2bc8186b8eefc0a979d039dd4cd2a6f89f6
This commit is contained in:
parent
98af6b148e
commit
8ee49c6aed
@ -16,7 +16,7 @@
|
|||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_vmware import exceptions as vexc
|
from oslo_vmware import exceptions as vexc
|
||||||
from oslo_vmware import vim_util as vutil
|
from oslo_vmware import vim_util
|
||||||
|
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.network import model as network_model
|
from nova.network import model as network_model
|
||||||
@ -24,6 +24,7 @@ from nova import test
|
|||||||
from nova.tests.unit import matchers
|
from nova.tests.unit import matchers
|
||||||
from nova.tests.unit import utils
|
from nova.tests.unit import utils
|
||||||
from nova.tests.unit.virt.vmwareapi import fake
|
from nova.tests.unit.virt.vmwareapi import fake
|
||||||
|
from nova.virt.vmwareapi import constants
|
||||||
from nova.virt.vmwareapi import network_util
|
from nova.virt.vmwareapi import network_util
|
||||||
from nova.virt.vmwareapi import vif
|
from nova.virt.vmwareapi import vif
|
||||||
from nova.virt.vmwareapi import vm_util
|
from nova.virt.vmwareapi import vm_util
|
||||||
@ -41,7 +42,7 @@ class VMwareVifTestCase(test.NoDBTestCase):
|
|||||||
vlan=3,
|
vlan=3,
|
||||||
bridge_interface='eth0',
|
bridge_interface='eth0',
|
||||||
injected=True)
|
injected=True)
|
||||||
|
self._network = network
|
||||||
self.vif = network_model.NetworkInfo([
|
self.vif = network_model.NetworkInfo([
|
||||||
network_model.VIF(id=None,
|
network_model.VIF(id=None,
|
||||||
address='DE:AD:BE:EF:00:00',
|
address='DE:AD:BE:EF:00:00',
|
||||||
@ -132,12 +133,6 @@ class VMwareVifTestCase(test.NoDBTestCase):
|
|||||||
create_vlan=False)
|
create_vlan=False)
|
||||||
self.assertThat(ref, matchers.DictMatches(network_ref))
|
self.assertThat(ref, matchers.DictMatches(network_ref))
|
||||||
|
|
||||||
def test_get_network_ref_neutron(self):
|
|
||||||
self.mox.StubOutWithMock(vif, 'get_neutron_network')
|
|
||||||
vif.get_neutron_network(self.session, 'fa0', self.cluster, self.vif)
|
|
||||||
self.mox.ReplayAll()
|
|
||||||
vif.get_network_ref(self.session, self.cluster, self.vif, True)
|
|
||||||
|
|
||||||
def test_get_network_ref_flat_dhcp(self):
|
def test_get_network_ref_flat_dhcp(self):
|
||||||
self.mox.StubOutWithMock(vif, 'ensure_vlan_bridge')
|
self.mox.StubOutWithMock(vif, 'ensure_vlan_bridge')
|
||||||
vif.ensure_vlan_bridge(self.session, self.vif, cluster=self.cluster,
|
vif.ensure_vlan_bridge(self.session, self.vif, cluster=self.cluster,
|
||||||
@ -168,110 +163,6 @@ class VMwareVifTestCase(test.NoDBTestCase):
|
|||||||
])[0]
|
])[0]
|
||||||
vif.get_network_ref(self.session, self.cluster, self.vif, False)
|
vif.get_network_ref(self.session, self.cluster, self.vif, False)
|
||||||
|
|
||||||
def test_get_network_ref_bridge_from_opaque(self):
|
|
||||||
opaque_networks = [{'opaqueNetworkId': 'bridge_id',
|
|
||||||
'opaqueNetworkName': 'name',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'}]
|
|
||||||
network_ref = vif._get_network_ref_from_opaque(opaque_networks,
|
|
||||||
'integration_bridge', 'bridge_id')
|
|
||||||
self.assertEqual('bridge_id', network_ref['network-id'])
|
|
||||||
|
|
||||||
def test_get_network_ref_multiple_bridges_from_opaque(self):
|
|
||||||
opaque_networks = [{'opaqueNetworkId': 'bridge_id1',
|
|
||||||
'opaqueNetworkName': 'name1',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'},
|
|
||||||
{'opaqueNetworkId': 'bridge_id2',
|
|
||||||
'opaqueNetworkName': 'name2',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'}]
|
|
||||||
network_ref = vif._get_network_ref_from_opaque(opaque_networks,
|
|
||||||
'integration_bridge', 'bridge_id2')
|
|
||||||
self.assertEqual('bridge_id2', network_ref['network-id'])
|
|
||||||
|
|
||||||
def test_get_network_ref_integration(self):
|
|
||||||
opaque_networks = [{'opaqueNetworkId': 'integration_bridge',
|
|
||||||
'opaqueNetworkName': 'name',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'}]
|
|
||||||
network_ref = vif._get_network_ref_from_opaque(opaque_networks,
|
|
||||||
'integration_bridge', 'bridge_id')
|
|
||||||
self.assertEqual('integration_bridge', network_ref['network-id'])
|
|
||||||
|
|
||||||
def test_get_network_ref_bridge_none(self):
|
|
||||||
opaque_networks = [{'opaqueNetworkId': 'bridge_id1',
|
|
||||||
'opaqueNetworkName': 'name1',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'},
|
|
||||||
{'opaqueNetworkId': 'bridge_id2',
|
|
||||||
'opaqueNetworkName': 'name2',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'}]
|
|
||||||
network_ref = vif._get_network_ref_from_opaque(opaque_networks,
|
|
||||||
'integration_bridge', 'bridge_id')
|
|
||||||
self.assertIsNone(network_ref)
|
|
||||||
|
|
||||||
def test_get_network_ref_integration_multiple(self):
|
|
||||||
opaque_networks = [{'opaqueNetworkId': 'bridge_id1',
|
|
||||||
'opaqueNetworkName': 'name1',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'},
|
|
||||||
{'opaqueNetworkId': 'integration_bridge',
|
|
||||||
'opaqueNetworkName': 'name2',
|
|
||||||
'opaqueNetworkType': 'OpaqueNetwork'}]
|
|
||||||
network_ref = vif._get_network_ref_from_opaque(opaque_networks,
|
|
||||||
'integration_bridge', 'bridge_id')
|
|
||||||
self.assertIsNone(network_ref)
|
|
||||||
|
|
||||||
def test_get_neutron_network(self):
|
|
||||||
self.mox.StubOutWithMock(vm_util, 'get_host_ref')
|
|
||||||
self.mox.StubOutWithMock(self.session, '_call_method')
|
|
||||||
self.mox.StubOutWithMock(vif, '_get_network_ref_from_opaque')
|
|
||||||
vm_util.get_host_ref(self.session,
|
|
||||||
self.cluster).AndReturn('fake-host')
|
|
||||||
opaque = fake.DataObject()
|
|
||||||
opaque.HostOpaqueNetworkInfo = ['fake-network-info']
|
|
||||||
self.session._call_method(vutil, "get_object_property",
|
|
||||||
'fake-host', 'config.network.opaqueNetwork').AndReturn(opaque)
|
|
||||||
vif._get_network_ref_from_opaque(opaque.HostOpaqueNetworkInfo,
|
|
||||||
CONF.vmware.integration_bridge,
|
|
||||||
self.vif['network']['id']).AndReturn('fake-network-ref')
|
|
||||||
self.mox.ReplayAll()
|
|
||||||
network_ref = vif.get_neutron_network(self.session,
|
|
||||||
self.vif['network']['id'],
|
|
||||||
self.cluster,
|
|
||||||
self.vif)
|
|
||||||
self.assertEqual(network_ref, 'fake-network-ref')
|
|
||||||
|
|
||||||
def test_get_neutron_network_opaque_network_not_found(self):
|
|
||||||
self.mox.StubOutWithMock(vm_util, 'get_host_ref')
|
|
||||||
self.mox.StubOutWithMock(self.session, '_call_method')
|
|
||||||
self.mox.StubOutWithMock(vif, '_get_network_ref_from_opaque')
|
|
||||||
vm_util.get_host_ref(self.session,
|
|
||||||
self.cluster).AndReturn('fake-host')
|
|
||||||
opaque = fake.DataObject()
|
|
||||||
opaque.HostOpaqueNetworkInfo = ['fake-network-info']
|
|
||||||
self.session._call_method(vutil, "get_object_property",
|
|
||||||
'fake-host', 'config.network.opaqueNetwork').AndReturn(opaque)
|
|
||||||
vif._get_network_ref_from_opaque(opaque.HostOpaqueNetworkInfo,
|
|
||||||
CONF.vmware.integration_bridge,
|
|
||||||
self.vif['network']['id']).AndReturn(None)
|
|
||||||
self.mox.ReplayAll()
|
|
||||||
self.assertRaises(exception.NetworkNotFoundForBridge,
|
|
||||||
vif.get_neutron_network, self.session,
|
|
||||||
self.vif['network']['id'], self.cluster, self.vif)
|
|
||||||
|
|
||||||
def test_get_neutron_network_bridge_network_not_found(self):
|
|
||||||
self.mox.StubOutWithMock(vm_util, 'get_host_ref')
|
|
||||||
self.mox.StubOutWithMock(self.session, '_call_method')
|
|
||||||
self.mox.StubOutWithMock(network_util, 'get_network_with_the_name')
|
|
||||||
vm_util.get_host_ref(self.session,
|
|
||||||
self.cluster).AndReturn('fake-host')
|
|
||||||
opaque = fake.DataObject()
|
|
||||||
opaque.HostOpaqueNetworkInfo = ['fake-network-info']
|
|
||||||
self.session._call_method(vutil, "get_object_property",
|
|
||||||
'fake-host', 'config.network.opaqueNetwork').AndReturn(None)
|
|
||||||
network_util.get_network_with_the_name(self.session, 0,
|
|
||||||
self.cluster).AndReturn(None)
|
|
||||||
self.mox.ReplayAll()
|
|
||||||
self.assertRaises(exception.NetworkNotFoundForBridge,
|
|
||||||
vif.get_neutron_network, self.session,
|
|
||||||
self.vif['network']['id'], self.cluster, self.vif)
|
|
||||||
|
|
||||||
def test_create_port_group_already_exists(self):
|
def test_create_port_group_already_exists(self):
|
||||||
def fake_call_method(module, method, *args, **kwargs):
|
def fake_call_method(module, method, *args, **kwargs):
|
||||||
if method == 'AddPortGroup':
|
if method == 'AddPortGroup':
|
||||||
@ -304,20 +195,6 @@ class VMwareVifTestCase(test.NoDBTestCase):
|
|||||||
'vswitch_name', vlan_id=0,
|
'vswitch_name', vlan_id=0,
|
||||||
cluster=None)
|
cluster=None)
|
||||||
|
|
||||||
def test_get_neutron_network_invalid_property(self):
|
|
||||||
def fake_call_method(module, method, *args, **kwargs):
|
|
||||||
if method == 'get_object_property':
|
|
||||||
raise vexc.InvalidPropertyException()
|
|
||||||
|
|
||||||
with test.nested(
|
|
||||||
mock.patch.object(vm_util, 'get_host_ref'),
|
|
||||||
mock.patch.object(self.session, '_call_method',
|
|
||||||
fake_call_method),
|
|
||||||
mock.patch.object(network_util, 'get_network_with_the_name')
|
|
||||||
) as (_get_host, _call_method, _get_name):
|
|
||||||
vif.get_neutron_network(self.session, 'network_name',
|
|
||||||
'cluster', self.vif)
|
|
||||||
|
|
||||||
def test_get_vif_info_none(self):
|
def test_get_vif_info_none(self):
|
||||||
vif_info = vif.get_vif_info('fake_session', 'fake_cluster',
|
vif_info = vif.get_vif_info('fake_session', 'fake_cluster',
|
||||||
'is_neutron', 'fake_model', None)
|
'is_neutron', 'fake_model', None)
|
||||||
@ -339,3 +216,97 @@ class VMwareVifTestCase(test.NoDBTestCase):
|
|||||||
'network_ref': 'fake_ref',
|
'network_ref': 'fake_ref',
|
||||||
'vif_model': 'fake_model'}]
|
'vif_model': 'fake_model'}]
|
||||||
self.assertEqual(expected, vif_info)
|
self.assertEqual(expected, vif_info)
|
||||||
|
|
||||||
|
@mock.patch.object(vif, '_check_ovs_supported_version')
|
||||||
|
def test_get_neutron_network_ovs_integration_bridge(self,
|
||||||
|
mock_check):
|
||||||
|
self.flags(integration_bridge='fake-bridge-id', group='vmware')
|
||||||
|
vif_info = network_model.NetworkInfo([
|
||||||
|
network_model.VIF(type=network_model.VIF_TYPE_OVS,
|
||||||
|
address='DE:AD:BE:EF:00:00',
|
||||||
|
network=self._network)]
|
||||||
|
)[0]
|
||||||
|
network_ref = vif._get_neutron_network('fake-session',
|
||||||
|
'fake-cluster',
|
||||||
|
vif_info)
|
||||||
|
expected_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': 'fake-bridge-id',
|
||||||
|
'network-type': 'opaque',
|
||||||
|
'use-external-id': False}
|
||||||
|
self.assertEqual(expected_ref, network_ref)
|
||||||
|
mock_check.assert_called_once_with('fake-session')
|
||||||
|
|
||||||
|
@mock.patch.object(vif, '_check_ovs_supported_version')
|
||||||
|
def test_get_neutron_network_ovs(self, mock_check):
|
||||||
|
vif_info = network_model.NetworkInfo([
|
||||||
|
network_model.VIF(type=network_model.VIF_TYPE_OVS,
|
||||||
|
address='DE:AD:BE:EF:00:00',
|
||||||
|
network=self._network)]
|
||||||
|
)[0]
|
||||||
|
network_ref = vif._get_neutron_network('fake-session',
|
||||||
|
'fake-cluster',
|
||||||
|
vif_info)
|
||||||
|
expected_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': 0,
|
||||||
|
'network-type': 'nsx.LogicalSwitch',
|
||||||
|
'use-external-id': True}
|
||||||
|
self.assertEqual(expected_ref, network_ref)
|
||||||
|
mock_check.assert_called_once_with('fake-session')
|
||||||
|
|
||||||
|
@mock.patch.object(network_util, 'get_network_with_the_name')
|
||||||
|
def test_get_neutron_network_dvs(self, mock_network_name):
|
||||||
|
fake_network_obj = {'type': 'DistributedVirtualPortgroup',
|
||||||
|
'dvpg': 'fake-key',
|
||||||
|
'dvsw': 'fake-props'}
|
||||||
|
mock_network_name.return_value = fake_network_obj
|
||||||
|
vif_info = network_model.NetworkInfo([
|
||||||
|
network_model.VIF(type=network_model.VIF_TYPE_DVS,
|
||||||
|
address='DE:AD:BE:EF:00:00',
|
||||||
|
network=self._network)]
|
||||||
|
)[0]
|
||||||
|
network_ref = vif._get_neutron_network('fake-session',
|
||||||
|
'fake-cluster',
|
||||||
|
vif_info)
|
||||||
|
mock_network_name.assert_called_once_with('fake-session',
|
||||||
|
'fa0',
|
||||||
|
'fake-cluster')
|
||||||
|
self.assertEqual(fake_network_obj, network_ref)
|
||||||
|
|
||||||
|
@mock.patch.object(network_util, 'get_network_with_the_name',
|
||||||
|
return_value=None)
|
||||||
|
def test_get_neutron_network_dvs_no_match(self, mock_network_name):
|
||||||
|
vif_info = network_model.NetworkInfo([
|
||||||
|
network_model.VIF(type=network_model.VIF_TYPE_DVS,
|
||||||
|
address='DE:AD:BE:EF:00:00',
|
||||||
|
network=self._network)]
|
||||||
|
)[0]
|
||||||
|
self.assertRaises(exception.NetworkNotFoundForBridge,
|
||||||
|
vif._get_neutron_network,
|
||||||
|
'fake-session',
|
||||||
|
'fake-cluster',
|
||||||
|
vif_info)
|
||||||
|
|
||||||
|
def test_get_neutron_network_invalid_type(self):
|
||||||
|
vif_info = network_model.NetworkInfo([
|
||||||
|
network_model.VIF(address='DE:AD:BE:EF:00:00',
|
||||||
|
network=self._network)]
|
||||||
|
)[0]
|
||||||
|
self.assertRaises(exception.InvalidInput,
|
||||||
|
vif._get_neutron_network,
|
||||||
|
'fake-session',
|
||||||
|
'fake-cluster',
|
||||||
|
vif_info)
|
||||||
|
|
||||||
|
@mock.patch.object(vif.LOG, 'warning')
|
||||||
|
@mock.patch.object(vim_util, 'get_vc_version',
|
||||||
|
return_value='5.0.0')
|
||||||
|
def test_check_invalid_ovs_version(self, mock_version, mock_warning):
|
||||||
|
vif._check_ovs_supported_version('fake_session')
|
||||||
|
# assert that the min version is in a warning message
|
||||||
|
expected_arg = {'version': constants.MIN_VC_OVS_VERSION}
|
||||||
|
version_arg_found = False
|
||||||
|
for call in mock_warning.call_args_list:
|
||||||
|
if call[0][1] == expected_arg:
|
||||||
|
version_arg_found = True
|
||||||
|
break
|
||||||
|
self.assertTrue(version_arg_found)
|
||||||
|
@ -1012,14 +1012,13 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||||||
_wait_for_task.assert_called_once_with(
|
_wait_for_task.assert_called_once_with(
|
||||||
'fake_reconfigure_task')
|
'fake_reconfigure_task')
|
||||||
|
|
||||||
def test_get_network_attach_config_spec_opaque(self):
|
def _get_network_attach_config_spec_opaque(self, network_ref,
|
||||||
vif_info = {'network_name': 'br-int',
|
vc6_onwards=False):
|
||||||
'mac_address': '00:00:00:ca:fe:01',
|
vif_info = {'network_name': 'fake-name',
|
||||||
'network_ref': {'type': 'OpaqueNetwork',
|
'mac_address': '00:00:00:ca:fe:01',
|
||||||
'network-id': 'fake-network-id',
|
'network_ref': network_ref,
|
||||||
'network-type': 'opaque'},
|
'iface_id': 7,
|
||||||
'iface_id': 7,
|
'vif_model': 'VirtualE1000'}
|
||||||
'vif_model': 'VirtualE1000'}
|
|
||||||
fake_factory = fake.FakeFactory()
|
fake_factory = fake.FakeFactory()
|
||||||
result = vm_util.get_network_attach_config_spec(
|
result = vm_util.get_network_attach_config_spec(
|
||||||
fake_factory, vif_info, 1)
|
fake_factory, vif_info, 1)
|
||||||
@ -1038,6 +1037,14 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
device = fake_factory.create('ns0:VirtualE1000')
|
device = fake_factory.create('ns0:VirtualE1000')
|
||||||
device.macAddress = vif_info['mac_address']
|
device.macAddress = vif_info['mac_address']
|
||||||
|
if network_ref['use-external-id']:
|
||||||
|
if vc6_onwards:
|
||||||
|
device.externalId = vif_info['iface_id']
|
||||||
|
else:
|
||||||
|
dp = fake_factory.create('ns0:DynamicProperty')
|
||||||
|
dp.name = '__externalId__'
|
||||||
|
dp.val = vif_info['iface_id']
|
||||||
|
device.dynamicProperty = [dp]
|
||||||
device.addressType = 'manual'
|
device.addressType = 'manual'
|
||||||
connectable = fake_factory.create('ns0:VirtualDeviceConnectInfo')
|
connectable = fake_factory.create('ns0:VirtualDeviceConnectInfo')
|
||||||
connectable.allowGuestControl = True
|
connectable.allowGuestControl = True
|
||||||
@ -1055,6 +1062,37 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_get_network_attach_config_spec_opaque_integration_bridge(self):
|
||||||
|
network_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': 'fake-network-id',
|
||||||
|
'network-type': 'opaque',
|
||||||
|
'use-external-id': False}
|
||||||
|
self._get_network_attach_config_spec_opaque(network_ref)
|
||||||
|
|
||||||
|
def test_get_network_attach_config_spec_opaque(self):
|
||||||
|
network_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': 'fake-network-id',
|
||||||
|
'network-type': 'nsx.LogicalSwitch',
|
||||||
|
'use-external-id': True}
|
||||||
|
self._get_network_attach_config_spec_opaque(network_ref)
|
||||||
|
|
||||||
|
@mock.patch.object(fake, 'DataObject')
|
||||||
|
def test_get_network_attach_config_spec_opaque_vc6_onwards(self,
|
||||||
|
mock_object):
|
||||||
|
# Add new attribute externalId supported from VC6
|
||||||
|
class FakeVirtualE1000(fake.DataObject):
|
||||||
|
def __init__(self):
|
||||||
|
super(FakeVirtualE1000, self).__init__()
|
||||||
|
self.externalId = None
|
||||||
|
|
||||||
|
mock_object.return_value = FakeVirtualE1000
|
||||||
|
network_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': 'fake-network-id',
|
||||||
|
'network-type': 'nsx.LogicalSwitch',
|
||||||
|
'use-external-id': True}
|
||||||
|
self._get_network_attach_config_spec_opaque(network_ref,
|
||||||
|
vc6_onwards=True)
|
||||||
|
|
||||||
def test_get_network_attach_config_spec_dvs(self):
|
def test_get_network_attach_config_spec_dvs(self):
|
||||||
vif_info = {'network_name': 'br100',
|
vif_info = {'network_name': 'br100',
|
||||||
'mac_address': '00:00:00:ca:fe:01',
|
'mac_address': '00:00:00:ca:fe:01',
|
||||||
|
@ -19,6 +19,8 @@ Shared constants across the VMware driver
|
|||||||
from nova.network import model as network_model
|
from nova.network import model as network_model
|
||||||
|
|
||||||
MIN_VC_VERSION = '5.1.0'
|
MIN_VC_VERSION = '5.1.0'
|
||||||
|
# The minimum VC version for Neutron 'ovs' port type support
|
||||||
|
MIN_VC_OVS_VERSION = '5.5.0'
|
||||||
|
|
||||||
DISK_FORMAT_ISO = 'iso'
|
DISK_FORMAT_ISO = 'iso'
|
||||||
DISK_FORMAT_VMDK = 'vmdk'
|
DISK_FORMAT_VMDK = 'vmdk'
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_vmware import exceptions as vexc
|
from oslo_vmware import vim_util
|
||||||
from oslo_vmware import vim_util as vutil
|
|
||||||
|
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.i18n import _LW
|
from nova.i18n import _, _LW
|
||||||
from nova.network import model
|
from nova.network import model
|
||||||
|
from nova import utils
|
||||||
|
from nova.virt.vmwareapi import constants
|
||||||
from nova.virt.vmwareapi import network_util
|
from nova.virt.vmwareapi import network_util
|
||||||
from nova.virt.vmwareapi import vm_util
|
from nova.virt.vmwareapi import vm_util
|
||||||
|
|
||||||
@ -34,8 +35,11 @@ vmwareapi_vif_opts = [
|
|||||||
default='vmnic0',
|
default='vmnic0',
|
||||||
help='Physical ethernet adapter name for vlan networking'),
|
help='Physical ethernet adapter name for vlan networking'),
|
||||||
cfg.StrOpt('integration_bridge',
|
cfg.StrOpt('integration_bridge',
|
||||||
default='br-int',
|
help='This option should be configured only when using the '
|
||||||
help='Name of Integration Bridge'),
|
'NSX-MH Neutron plugin. This is the name of the '
|
||||||
|
'integration bridge on the ESXi. This should not be set '
|
||||||
|
'for any other Neutron plugin. Hence the default value '
|
||||||
|
'is not set.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF.register_opts(vmwareapi_vif_opts, 'vmware')
|
CONF.register_opts(vmwareapi_vif_opts, 'vmware')
|
||||||
@ -99,63 +103,49 @@ def ensure_vlan_bridge(session, vif, cluster=None, create_vlan=True):
|
|||||||
return network_ref
|
return network_ref
|
||||||
|
|
||||||
|
|
||||||
def _is_valid_opaque_network_id(opaque_id, bridge_id, integration_bridge,
|
def _check_ovs_supported_version(session):
|
||||||
num_networks):
|
# The port type 'ovs' is only support by the VC version 5.5 onwards
|
||||||
return (opaque_id == bridge_id or
|
min_version = utils.convert_version_to_int(
|
||||||
(num_networks == 1 and
|
constants.MIN_VC_OVS_VERSION)
|
||||||
opaque_id == integration_bridge))
|
vc_version = utils.convert_version_to_int(
|
||||||
|
vim_util.get_vc_version(session))
|
||||||
|
if vc_version < min_version:
|
||||||
|
LOG.warning(_LW('VMware vCenter version less than %(version)s '
|
||||||
|
'does not support the \'ovs\' port type.'),
|
||||||
|
{'version': constants.MIN_VC_OVS_VERSION})
|
||||||
|
|
||||||
|
|
||||||
def _get_network_ref_from_opaque(opaque_networks, integration_bridge, bridge):
|
def _get_neutron_network(session, cluster, vif):
|
||||||
num_networks = len(opaque_networks)
|
if vif['type'] == model.VIF_TYPE_OVS:
|
||||||
for network in opaque_networks:
|
_check_ovs_supported_version(session)
|
||||||
if _is_valid_opaque_network_id(network['opaqueNetworkId'], bridge,
|
# Check if this is the NSX-MH plugin is used
|
||||||
integration_bridge, num_networks):
|
if CONF.vmware.integration_bridge:
|
||||||
return {'type': 'OpaqueNetwork',
|
net_id = CONF.vmware.integration_bridge
|
||||||
'network-id': network['opaqueNetworkId'],
|
use_external_id = False
|
||||||
'network-name': network['opaqueNetworkName'],
|
network_type = 'opaque'
|
||||||
'network-type': network['opaqueNetworkType']}
|
else:
|
||||||
LOG.warning(_LW("No valid network found in %(opaque)s, from %(bridge)s "
|
net_id = vif['network']['id']
|
||||||
"or %(integration_bridge)s"),
|
use_external_id = True
|
||||||
{'opaque': opaque_networks, 'bridge': bridge,
|
network_type = 'nsx.LogicalSwitch'
|
||||||
'integration_bridge': integration_bridge})
|
network_ref = {'type': 'OpaqueNetwork',
|
||||||
|
'network-id': net_id,
|
||||||
|
'network-type': network_type,
|
||||||
def _get_opaque_network(session, cluster):
|
'use-external-id': use_external_id}
|
||||||
host = vm_util.get_host_ref(session, cluster)
|
elif vif['type'] == model.VIF_TYPE_DVS:
|
||||||
try:
|
network_id = vif['network']['bridge']
|
||||||
opaque = session._call_method(vutil,
|
|
||||||
"get_object_property",
|
|
||||||
host,
|
|
||||||
"config.network.opaqueNetwork")
|
|
||||||
except vexc.InvalidPropertyException:
|
|
||||||
opaque = None
|
|
||||||
return opaque
|
|
||||||
|
|
||||||
|
|
||||||
def get_neutron_network(session, network_name, cluster, vif):
|
|
||||||
opaque = None
|
|
||||||
if vif['type'] != model.VIF_TYPE_DVS:
|
|
||||||
opaque = _get_opaque_network(session, cluster)
|
|
||||||
if opaque:
|
|
||||||
bridge = vif['network']['id']
|
|
||||||
opaque_networks = opaque.HostOpaqueNetworkInfo
|
|
||||||
network_ref = _get_network_ref_from_opaque(opaque_networks,
|
|
||||||
CONF.vmware.integration_bridge, bridge)
|
|
||||||
else:
|
|
||||||
bridge = network_name
|
|
||||||
network_ref = network_util.get_network_with_the_name(
|
network_ref = network_util.get_network_with_the_name(
|
||||||
session, network_name, cluster)
|
session, network_id, cluster)
|
||||||
if not network_ref:
|
if not network_ref:
|
||||||
raise exception.NetworkNotFoundForBridge(bridge=bridge)
|
raise exception.NetworkNotFoundForBridge(bridge=network_id)
|
||||||
|
else:
|
||||||
|
reason = _('vif type %s not supported') % vif['type']
|
||||||
|
raise exception.InvalidInput(reason=reason)
|
||||||
return network_ref
|
return network_ref
|
||||||
|
|
||||||
|
|
||||||
def get_network_ref(session, cluster, vif, is_neutron):
|
def get_network_ref(session, cluster, vif, is_neutron):
|
||||||
if is_neutron:
|
if is_neutron:
|
||||||
network_name = (vif['network']['bridge'] or
|
network_ref = _get_neutron_network(session, cluster, vif)
|
||||||
CONF.vmware.integration_bridge)
|
|
||||||
network_ref = get_neutron_network(session, network_name, cluster, vif)
|
|
||||||
else:
|
else:
|
||||||
create_vlan = vif['network'].get_meta('should_create_vlan', False)
|
create_vlan = vif['network'].get_meta('should_create_vlan', False)
|
||||||
network_ref = ensure_vlan_bridge(session, vif, cluster=cluster,
|
network_ref = ensure_vlan_bridge(session, vif, cluster=cluster,
|
||||||
|
@ -428,6 +428,16 @@ def _create_vif_spec(client_factory, vif_info):
|
|||||||
'ns0:VirtualEthernetCardOpaqueNetworkBackingInfo')
|
'ns0:VirtualEthernetCardOpaqueNetworkBackingInfo')
|
||||||
backing.opaqueNetworkId = network_ref['network-id']
|
backing.opaqueNetworkId = network_ref['network-id']
|
||||||
backing.opaqueNetworkType = network_ref['network-type']
|
backing.opaqueNetworkType = network_ref['network-type']
|
||||||
|
# Configure externalId
|
||||||
|
if network_ref['use-external-id']:
|
||||||
|
# externalId is only supported from vCenter 6.0 onwards
|
||||||
|
if hasattr(net_device, 'externalId'):
|
||||||
|
net_device.externalId = vif_info['iface_id']
|
||||||
|
else:
|
||||||
|
dp = client_factory.create('ns0:DynamicProperty')
|
||||||
|
dp.name = "__externalId__"
|
||||||
|
dp.val = vif_info['iface_id']
|
||||||
|
net_device.dynamicProperty = [dp]
|
||||||
elif (network_ref and
|
elif (network_ref and
|
||||||
network_ref['type'] == "DistributedVirtualPortgroup"):
|
network_ref['type'] == "DistributedVirtualPortgroup"):
|
||||||
backing = client_factory.create(
|
backing = client_factory.create(
|
||||||
|
Loading…
Reference in New Issue
Block a user