Multi-DVS Support When Hypervisor is vCenter
This patch supports creation and deletion of portgroups on multiple distributed switches on vCenter. If user doesn't provide --provider-physical-network argument, then portgroup is created on configured DVS in nsx.ini else if the --provider-physical-network argument is provided with dvs name in vcenter then portgroup is created on that distributed virtual switch(DVS). Change-Id: I0636745835a6f4b0e5fae6e01b6ee754e1d9176d Closes-Bug: #1714428
This commit is contained in:
parent
1c3873c6fd
commit
d07d4f0d12
@ -38,40 +38,28 @@ class SingleDvsManager(object):
|
||||
the operations supported by the manager.
|
||||
"""
|
||||
def __init__(self):
|
||||
self._dvs = DvsManager()
|
||||
self.dvs = DvsManager()
|
||||
self._dvs_moref = self._get_dvs_moref_by_name(
|
||||
self._dvs.get_vc_session(),
|
||||
self.dvs.get_vc_session(),
|
||||
dvs_utils.dvs_name_get())
|
||||
|
||||
def _get_dvs_moref_by_name(self, session, dvs_name):
|
||||
"""Get the moref of the configured DVS."""
|
||||
results = session.invoke_api(vim_util,
|
||||
'get_objects',
|
||||
session.vim,
|
||||
'DistributedVirtualSwitch',
|
||||
100)
|
||||
while results:
|
||||
for dvs in results.objects:
|
||||
for prop in dvs.propSet:
|
||||
if dvs_name == prop.val:
|
||||
vim_util.cancel_retrieval(session.vim, results)
|
||||
return dvs.obj
|
||||
results = vim_util.continue_retrieval(session.vim, results)
|
||||
raise nsx_exc.DvsNotFound(dvs=dvs_name)
|
||||
return self.dvs.get_dvs_moref_by_name(dvs_name, session)
|
||||
|
||||
def add_port_group(self, net_id, vlan_tag=None, trunk_mode=False):
|
||||
return self._dvs.add_port_group(self._dvs_moref, net_id,
|
||||
vlan_tag=vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
return self.dvs.add_port_group(self._dvs_moref, net_id,
|
||||
vlan_tag=vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
|
||||
def delete_port_group(self, net_id):
|
||||
return self._dvs.delete_port_group(self._dvs_moref, net_id)
|
||||
return self.dvs.delete_port_group(self._dvs_moref, net_id)
|
||||
|
||||
def get_port_group_info(self, net_id):
|
||||
return self._dvs.get_port_group_info(self._dvs_moref, net_id)
|
||||
return self.dvs.get_port_group_info(self._dvs_moref, net_id)
|
||||
|
||||
def net_id_to_moref(self, net_id):
|
||||
return self._dvs._net_id_to_moref(self._dvs_moref, net_id)
|
||||
return self.dvs._net_id_to_moref(self._dvs_moref, net_id)
|
||||
|
||||
|
||||
class VCManagerBase(object):
|
||||
@ -95,6 +83,24 @@ class DvsManager(VCManagerBase):
|
||||
The dvs-id is not a class member, since multiple dvs-es can be supported.
|
||||
"""
|
||||
|
||||
def get_dvs_moref_by_name(self, dvs_name, session=None):
|
||||
"""Get the moref of DVS."""
|
||||
if not session:
|
||||
session = self.get_vc_session()
|
||||
results = session.invoke_api(vim_util,
|
||||
'get_objects',
|
||||
session.vim,
|
||||
'DistributedVirtualSwitch',
|
||||
100)
|
||||
while results:
|
||||
for dvs in results.objects:
|
||||
for prop in dvs.propSet:
|
||||
if dvs_name == prop.val:
|
||||
vim_util.cancel_retrieval(session.vim, results)
|
||||
return dvs.obj
|
||||
results = vim_util.continue_retrieval(session.vim, results)
|
||||
raise nsx_exc.DvsNotFound(dvs=dvs_name)
|
||||
|
||||
def _get_dvs_moref_by_id(self, dvs_id):
|
||||
return vim_util.get_moref(dvs_id, 'VmwareDistributedVirtualSwitch')
|
||||
|
||||
|
@ -176,6 +176,18 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
# maximum prefix for name is 43
|
||||
return '%s-%s' % (net_data['name'][:43], net_data['id'])
|
||||
|
||||
def _add_port_group(self, dvs_id, net_data, vlan_tag, trunk_mode):
|
||||
if validators.is_attr_set(net_data.get(pnet.PHYSICAL_NETWORK)):
|
||||
dvs_name = net_data.get(pnet.PHYSICAL_NETWORK)
|
||||
dvs_moref = self._dvs.dvs.get_dvs_moref_by_name(dvs_name)
|
||||
self._dvs.dvs.add_port_group(dvs_moref, dvs_id, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
else:
|
||||
dvs_name = dvs_utils.dvs_name_get()
|
||||
self._dvs.add_port_group(dvs_id, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
return dvs_name
|
||||
|
||||
def _dvs_create_network(self, context, network):
|
||||
net_data = network['network']
|
||||
if net_data['admin_state_up'] is False:
|
||||
@ -192,7 +204,7 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
if net_data.get(vlan_apidef.VLANTRANSPARENT) is True:
|
||||
trunk_mode = True
|
||||
|
||||
net_id = None
|
||||
net_id = dvs_name = None
|
||||
if net_data.get(pnet.NETWORK_TYPE) == c_utils.NetworkTypes.PORTGROUP:
|
||||
net_id = net_data.get(pnet.PHYSICAL_NETWORK)
|
||||
pg_info = self._dvs.get_port_group_info(net_id)
|
||||
@ -206,8 +218,8 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
else:
|
||||
dvs_id = self._dvs_get_id(net_data)
|
||||
try:
|
||||
self._dvs.add_port_group(dvs_id, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
dvs_name = self._add_port_group(dvs_id, net_data, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
except dvs_utils.DvsOperationBulkFault:
|
||||
LOG.warning('One or more hosts may not be configured')
|
||||
|
||||
@ -230,17 +242,17 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
nsx_db.add_network_binding(
|
||||
context.session, new_net['id'],
|
||||
net_data.get(pnet.NETWORK_TYPE),
|
||||
net_id or 'dvs',
|
||||
net_id or dvs_name,
|
||||
vlan_tag)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception('Failed to create network')
|
||||
if (net_data.get(pnet.NETWORK_TYPE) !=
|
||||
c_utils.NetworkTypes.PORTGROUP):
|
||||
self._dvs.delete_port_group(dvs_id)
|
||||
self._delete_port_group(dvs_id, dvs_name)
|
||||
|
||||
new_net[pnet.NETWORK_TYPE] = net_data.get(pnet.NETWORK_TYPE)
|
||||
new_net[pnet.PHYSICAL_NETWORK] = net_id or 'dvs'
|
||||
new_net[pnet.PHYSICAL_NETWORK] = net_id or dvs_name
|
||||
new_net[pnet.SEGMENTATION_ID] = vlan_tag
|
||||
|
||||
# this extra lookup is necessary to get the
|
||||
@ -294,6 +306,13 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
self._validate_network(context, network['network'])
|
||||
return self._dvs_create_network(context, network)
|
||||
|
||||
def _delete_port_group(self, dvs_id, dvs_name):
|
||||
if dvs_name == dvs_utils.dvs_name_get():
|
||||
self._dvs.delete_port_group(dvs_id)
|
||||
else:
|
||||
dvs_moref = self._dvs.dvs.get_dvs_moref_by_name(dvs_name)
|
||||
self._dvs.dvs.delete_port_group(dvs_moref, dvs_id)
|
||||
|
||||
def _dvs_delete_network(self, context, id):
|
||||
network = self._get_network(context, id)
|
||||
dvs_id = self._dvs_get_id(network)
|
||||
@ -304,7 +323,8 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
try:
|
||||
if (not bindings or
|
||||
bindings[0].binding_type != c_utils.NetworkTypes.PORTGROUP):
|
||||
self._dvs.delete_port_group(dvs_id)
|
||||
dvs_name = bindings[0].phy_uuid
|
||||
self._delete_port_group(dvs_id, dvs_name)
|
||||
except Exception:
|
||||
LOG.exception('Unable to delete DVS port group %s', id)
|
||||
self.handle_network_dhcp_access(context, id, action='delete_network')
|
||||
|
@ -75,7 +75,7 @@ class DvsTestCase(base.BaseTestCase):
|
||||
return_value='fake-spec')
|
||||
def test_add_port_group_with_exception(self, fake_get_spec):
|
||||
with (
|
||||
mock.patch.object(self._dvs._dvs._session, 'wait_for_task',
|
||||
mock.patch.object(self._dvs.dvs._session, 'wait_for_task',
|
||||
side_effect=exp.NeutronException())
|
||||
):
|
||||
self.assertRaises(exp.NeutronException,
|
||||
@ -95,7 +95,7 @@ class DvsTestCase(base.BaseTestCase):
|
||||
return_value='fake-moref')
|
||||
def test_delete_port_group_with_exception(self, fake_get_moref):
|
||||
with (
|
||||
mock.patch.object(self._dvs._dvs._session, 'wait_for_task',
|
||||
mock.patch.object(self._dvs.dvs._session, 'wait_for_task',
|
||||
side_effect=exp.NeutronException())
|
||||
):
|
||||
self.assertRaises(exp.NeutronException,
|
||||
@ -166,9 +166,17 @@ class NeutronSimpleDvsTest(NeutronSimpleDvsTestCase):
|
||||
with mock.patch.object(self._plugin._dvs,
|
||||
'add_port_group') as mock_add,\
|
||||
mock.patch.object(self._plugin._dvs,
|
||||
'delete_port_group') as mock_delete,\
|
||||
'delete_port_group') as mock_delete,\
|
||||
mock.patch.object(dvs.DvsManager,
|
||||
'_get_trunk_vlan_spec') as mock_trunk_vlan:
|
||||
'add_port_group') as mock_dvs_add,\
|
||||
mock.patch.object(dvs.DvsManager,
|
||||
'delete_port_group'),\
|
||||
mock.patch.object(dvs.DvsManager,
|
||||
'get_dvs_moref_by_name',
|
||||
return_value=mock.MagicMock()
|
||||
) as mock_dvs_moref,\
|
||||
mock.patch.object(dvs.DvsManager,
|
||||
'_get_trunk_vlan_spec') as mock_trunk_vlan:
|
||||
with self.network(**params) as network:
|
||||
ctx = context.get_admin_context()
|
||||
id = network['network']['id']
|
||||
@ -178,11 +186,11 @@ class NeutronSimpleDvsTest(NeutronSimpleDvsTestCase):
|
||||
if network_type == 'flat':
|
||||
self.assertEqual('flat', binding[0].binding_type)
|
||||
self.assertEqual(0, binding[0].vlan_id)
|
||||
self.assertEqual('dvs', binding[0].phy_uuid)
|
||||
self.assertEqual('fake-moid', binding[0].phy_uuid)
|
||||
elif network_type == 'vlan':
|
||||
self.assertEqual('vlan', binding[0].binding_type)
|
||||
self.assertEqual(vlan_tag, binding[0].vlan_id)
|
||||
self.assertEqual('dvs', binding[0].phy_uuid)
|
||||
self.assertEqual('fake-moid', binding[0].phy_uuid)
|
||||
elif network_type == 'portgroup':
|
||||
self.assertEqual('portgroup', binding[0].binding_type)
|
||||
self.assertEqual(0, binding[0].vlan_id)
|
||||
@ -190,8 +198,10 @@ class NeutronSimpleDvsTest(NeutronSimpleDvsTestCase):
|
||||
else:
|
||||
self.fail()
|
||||
if network_type != 'portgroup':
|
||||
mock_add.assert_called_once_with(dvs_id, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
mock_dvs_add.assert_called_once_with(
|
||||
mock_dvs_moref.return_value,
|
||||
dvs_id, vlan_tag,
|
||||
trunk_mode=trunk_mode)
|
||||
else:
|
||||
mock_add.call_count = 0
|
||||
mock_delete.call_count = 0
|
||||
@ -235,7 +245,10 @@ class NeutronSimpleDvsTest(NeutronSimpleDvsTestCase):
|
||||
'provider:segmentation_id': 7}
|
||||
params['arg_list'] = tuple(params.keys())
|
||||
with mock.patch.object(self._plugin._dvs, 'add_port_group'),\
|
||||
mock.patch.object(self._plugin._dvs, 'delete_port_group'):
|
||||
mock.patch.object(self._plugin._dvs, 'delete_port_group'),\
|
||||
mock.patch.object(dvs.DvsManager, 'get_dvs_moref_by_name'),\
|
||||
mock.patch.object(dvs.DvsManager, 'add_port_group'),\
|
||||
mock.patch.object(dvs.DvsManager, 'delete_port_group'):
|
||||
with self.network(**params) as network,\
|
||||
self.subnet(network) as subnet,\
|
||||
self.port(subnet) as port:
|
||||
|
Loading…
x
Reference in New Issue
Block a user