Refactor VIFPortIDMixin: factor out common methods
This change is part of a series of changes which aim to refactor the VIFPortIDMixin mixin class. The refactor aims to reduce code duplication, and separate the neutron interactions from the more general VIF attach/detach behaviour. The neutron separation will be made possible by introducing an inheritence hierarchy to the mixin class. VIFPortIDMixin will become a general VIF attach/detach class, with no neutron interaction. NeutronVIFPortIDMixin will inherit from VIFPortIDMixin and override the subclass behaviour to interact with neutron where appropriate. Once this refactor is complete, a new fake network interface will be added with similar VIF attach/detach behaviour to the flat and neutron network interfaces, but without any interaction with neutron. This interface will be useful in testing environments. This change refactors the NeutronVIFPortIDMixin class by factoring out some common methods into a parent class, VIFPortIDMixin. This will help to avoid code duplication between the classes. Change-Id: I69a104ec967572f65566b0e0d67145d135be3ac9
This commit is contained in:
parent
759ed5d2ea
commit
e28ba70620
|
@ -296,7 +296,108 @@ def plug_port_to_tenant_network(task, port_like_obj, client=None):
|
|||
raise exception.NetworkError(msg)
|
||||
|
||||
|
||||
class NeutronVIFPortIDMixin(object):
|
||||
class VIFPortIDMixin(object):
|
||||
"""VIF port ID mixin class for non-neutron network interfaces.
|
||||
|
||||
Mixin class that provides VIF-related network interface methods for
|
||||
non-neutron network interfaces. There are no effects due to VIF
|
||||
attach/detach that are external to ironic.
|
||||
|
||||
NOTE: This does not yet support the full set of VIF methods, as it does
|
||||
not provide vif_attach, vif_detach, port_changed, or portgroup_changed.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _save_vif_to_port_like_obj(port_like_obj, vif_id):
|
||||
"""Save the ID of a VIF to a port or portgroup.
|
||||
|
||||
:param port_like_obj: port-like object to save to.
|
||||
:param vif_id: VIF ID to save.
|
||||
"""
|
||||
int_info = port_like_obj.internal_info
|
||||
int_info[TENANT_VIF_KEY] = vif_id
|
||||
port_like_obj.internal_info = int_info
|
||||
port_like_obj.save()
|
||||
|
||||
@staticmethod
|
||||
def _clear_vif_from_port_like_obj(port_like_obj):
|
||||
"""Clear the VIF ID field from a port or portgroup.
|
||||
|
||||
:param port_like_obj: port-like object to clear from.
|
||||
"""
|
||||
int_info = port_like_obj.internal_info
|
||||
extra = port_like_obj.extra
|
||||
int_info.pop(TENANT_VIF_KEY, None)
|
||||
extra.pop('vif_port_id', None)
|
||||
port_like_obj.extra = extra
|
||||
port_like_obj.internal_info = int_info
|
||||
port_like_obj.save()
|
||||
|
||||
def _get_port_like_obj_by_vif_id(self, task, vif_id):
|
||||
"""Lookup a port or portgroup by its attached VIF ID.
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:param vif_id: ID of the attached VIF.
|
||||
:returns: A Port or Portgroup object to which the VIF is attached.
|
||||
:raises: VifNotAttached if the VIF is not attached.
|
||||
"""
|
||||
for port_like_obj in task.portgroups + task.ports:
|
||||
vif_port_id = self._get_vif_id_by_port_like_obj(port_like_obj)
|
||||
if vif_port_id == vif_id:
|
||||
return port_like_obj
|
||||
raise exception.VifNotAttached(vif=vif_id, node=task.node.uuid)
|
||||
|
||||
@staticmethod
|
||||
def _get_vif_id_by_port_like_obj(port_like_obj):
|
||||
"""Lookup the VIF attached to a port or portgroup.
|
||||
|
||||
:param port_like_obj: A port or portgroup to check.
|
||||
:returns: The ID of the attached VIF, or None.
|
||||
"""
|
||||
# FIXME(sambetts) Remove this when we no longer support a nova
|
||||
# driver that uses port.extra
|
||||
return (port_like_obj.internal_info.get(TENANT_VIF_KEY) or
|
||||
port_like_obj.extra.get('vif_port_id'))
|
||||
|
||||
def vif_list(self, task):
|
||||
"""List attached VIF IDs for a node
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:returns: List of VIF dictionaries, each dictionary will have an 'id'
|
||||
entry with the ID of the VIF.
|
||||
"""
|
||||
vifs = []
|
||||
for port_like_obj in task.ports + task.portgroups:
|
||||
vif_id = self._get_vif_id_by_port_like_obj(port_like_obj)
|
||||
if vif_id:
|
||||
vifs.append({'id': vif_id})
|
||||
return vifs
|
||||
|
||||
def get_current_vif(self, task, p_obj):
|
||||
"""Returns the currently used VIF associated with port or portgroup
|
||||
|
||||
We are booting the node only in one network at a time, and presence of
|
||||
cleaning_vif_port_id means we're doing cleaning, of
|
||||
provisioning_vif_port_id - provisioning.
|
||||
Otherwise it's a tenant network
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:param p_obj: Ironic port or portgroup object.
|
||||
:returns: VIF ID associated with p_obj or None.
|
||||
"""
|
||||
|
||||
return (p_obj.internal_info.get('cleaning_vif_port_id') or
|
||||
p_obj.internal_info.get('provisioning_vif_port_id') or
|
||||
self._get_vif_id_by_port_like_obj(p_obj) or None)
|
||||
|
||||
|
||||
class NeutronVIFPortIDMixin(VIFPortIDMixin):
|
||||
"""VIF port ID mixin class for neutron network interfaces.
|
||||
|
||||
Mixin class that provides VIF-related network interface methods for neutron
|
||||
network interfaces. On VIF attach/detach, the associated neutron port will
|
||||
be updated.
|
||||
"""
|
||||
|
||||
def port_changed(self, task, port_obj):
|
||||
"""Handle any actions required when a port changes
|
||||
|
@ -313,8 +414,7 @@ class NeutronVIFPortIDMixin(object):
|
|||
if port_obj.portgroup_id:
|
||||
portgroup_obj = [pg for pg in task.portgroups if
|
||||
pg.id == port_obj.portgroup_id][0]
|
||||
vif = (port_obj.internal_info.get(TENANT_VIF_KEY) or
|
||||
port_obj.extra.get('vif_port_id'))
|
||||
vif = self._get_vif_id_by_port_like_obj(port_obj)
|
||||
if 'address' in port_obj.obj_what_changed():
|
||||
if vif:
|
||||
neutron.update_port_address(vif, port_obj.address)
|
||||
|
@ -380,8 +480,7 @@ class NeutronVIFPortIDMixin(object):
|
|||
# Do not touch neutron port if we removed address on portgroup.
|
||||
if ('address' in portgroup_obj.obj_what_changed() and
|
||||
portgroup_obj.address):
|
||||
pg_vif = (portgroup_obj.internal_info.get(TENANT_VIF_KEY) or
|
||||
portgroup_obj.extra.get('vif_port_id'))
|
||||
pg_vif = self._get_vif_id_by_port_like_obj(portgroup_obj)
|
||||
if pg_vif:
|
||||
neutron.update_port_address(pg_vif, portgroup_obj.address)
|
||||
|
||||
|
@ -399,8 +498,7 @@ class NeutronVIFPortIDMixin(object):
|
|||
ports = [p for p in task.ports if
|
||||
p.portgroup_id == portgroup_obj.id]
|
||||
for p in ports:
|
||||
vif = p.internal_info.get(
|
||||
TENANT_VIF_KEY, p.extra.get('vif_port_id'))
|
||||
vif = self._get_vif_id_by_port_like_obj(p)
|
||||
reason = []
|
||||
if p.pxe_enabled:
|
||||
reason.append("'pxe_enabled' is set to True")
|
||||
|
@ -415,21 +513,6 @@ class NeutronVIFPortIDMixin(object):
|
|||
'reason': ', '.join(reason)})
|
||||
raise exception.Conflict(msg)
|
||||
|
||||
def vif_list(self, task):
|
||||
"""List attached VIF IDs for a node
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:returns: List of VIF dictionaries, each dictionary will have an 'id'
|
||||
entry with the ID of the VIF.
|
||||
"""
|
||||
vifs = []
|
||||
for port_like_obj in task.ports + task.portgroups:
|
||||
vif_id = port_like_obj.internal_info.get(
|
||||
TENANT_VIF_KEY, port_like_obj.extra.get('vif_port_id'))
|
||||
if vif_id:
|
||||
vifs.append({'id': vif_id})
|
||||
return vifs
|
||||
|
||||
def vif_attach(self, task, vif_info):
|
||||
"""Attach a virtual network interface to a node
|
||||
|
||||
|
@ -520,10 +603,8 @@ class NeutronVIFPortIDMixin(object):
|
|||
'vif': vif_id, 'port': vif_id,
|
||||
'mac': port_like_obj.address})
|
||||
|
||||
int_info = port_like_obj.internal_info
|
||||
int_info[TENANT_VIF_KEY] = vif_id
|
||||
port_like_obj.internal_info = int_info
|
||||
port_like_obj.save()
|
||||
self._save_vif_to_port_like_obj(port_like_obj, vif_id)
|
||||
|
||||
# NOTE(vsaienko) allow to attach VIF to active instance.
|
||||
if task.node.provision_state == states.ACTIVE:
|
||||
plug_port_to_tenant_network(task, port_like_obj, client=client)
|
||||
|
@ -536,44 +617,12 @@ class NeutronVIFPortIDMixin(object):
|
|||
:raises: VifNotAttached if VIF not attached.
|
||||
:raises: NetworkError: if unbind Neutron port failed.
|
||||
"""
|
||||
# NOTE(mgoddard): Lookup the port first to check that the VIF is
|
||||
# attached, and fail if not.
|
||||
port_like_obj = self._get_port_like_obj_by_vif_id(task, vif_id)
|
||||
|
||||
# NOTE(vsaienko) We picking object to attach on vif-attach side.
|
||||
# Here we should only detach VIF and shouldn't duplicate/follow
|
||||
# attach rules, just walk over all objects and detach VIF.
|
||||
for port_like_obj in task.portgroups + task.ports:
|
||||
# FIXME(sambetts) Remove this when we no longer support a nova
|
||||
# driver that uses port.extra
|
||||
vif_port_id = port_like_obj.internal_info.get(
|
||||
TENANT_VIF_KEY, port_like_obj.extra.get("vif_port_id"))
|
||||
if vif_port_id == vif_id:
|
||||
int_info = port_like_obj.internal_info
|
||||
extra = port_like_obj.extra
|
||||
int_info.pop(TENANT_VIF_KEY, None)
|
||||
extra.pop('vif_port_id', None)
|
||||
port_like_obj.extra = extra
|
||||
port_like_obj.internal_info = int_info
|
||||
port_like_obj.save()
|
||||
# NOTE(vsaienko) allow to unplug VIFs from ACTIVE instance.
|
||||
if task.node.provision_state == states.ACTIVE:
|
||||
neutron.unbind_neutron_port(vif_port_id)
|
||||
break
|
||||
else:
|
||||
raise exception.VifNotAttached(vif=vif_id, node=task.node.uuid)
|
||||
self._clear_vif_from_port_like_obj(port_like_obj)
|
||||
|
||||
def get_current_vif(self, task, p_obj):
|
||||
"""Returns the currently used VIF associated with port or portgroup
|
||||
|
||||
We are booting the node only in one network at a time, and presence of
|
||||
cleaning_vif_port_id means we're doing cleaning, of
|
||||
provisioning_vif_port_id - provisioning.
|
||||
Otherwise it's a tenant network
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:param p_obj: Ironic port or portgroup object.
|
||||
:returns: VIF ID associated with p_obj or None.
|
||||
"""
|
||||
|
||||
return (p_obj.internal_info.get('cleaning_vif_port_id') or
|
||||
p_obj.internal_info.get('provisioning_vif_port_id') or
|
||||
p_obj.internal_info.get(TENANT_VIF_KEY) or
|
||||
p_obj.extra.get('vif_port_id') or None)
|
||||
# NOTE(vsaienko) allow to unplug VIFs from ACTIVE instance.
|
||||
if task.node.provision_state == states.ACTIVE:
|
||||
neutron.unbind_neutron_port(vif_id)
|
||||
|
|
|
@ -436,13 +436,13 @@ class TestCommonFunctions(db_base.DbTestCase):
|
|||
task, self.port)
|
||||
|
||||
|
||||
class TestNeutronVifPortIDMixin(db_base.DbTestCase):
|
||||
class TestVifPortIDMixin(db_base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNeutronVifPortIDMixin, self).setUp()
|
||||
super(TestVifPortIDMixin, self).setUp()
|
||||
self.config(enabled_drivers=['fake'])
|
||||
mgr_utils.mock_the_extension_manager()
|
||||
self.interface = common.NeutronVIFPortIDMixin()
|
||||
self.interface = common.VIFPortIDMixin()
|
||||
self.node = obj_utils.create_test_node(self.context,
|
||||
network_interface='neutron')
|
||||
self.port = obj_utils.create_test_port(
|
||||
|
@ -450,8 +450,121 @@ class TestNeutronVifPortIDMixin(db_base.DbTestCase):
|
|||
address='52:54:00:cf:2d:32',
|
||||
extra={'vif_port_id': uuidutils.generate_uuid(),
|
||||
'client-id': 'fake1'})
|
||||
self.neutron_port = {'id': '132f871f-eaec-4fed-9475-0d54465e0f00',
|
||||
'mac_address': '52:54:00:cf:2d:32'}
|
||||
|
||||
def test__save_vif_to_port_like_obj_port(self):
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
vif_id = "fake_vif_id"
|
||||
self.interface._save_vif_to_port_like_obj(self.port, vif_id)
|
||||
self.port.refresh()
|
||||
self.assertIn(common.TENANT_VIF_KEY, self.port.internal_info)
|
||||
self.assertEqual(vif_id,
|
||||
self.port.internal_info[common.TENANT_VIF_KEY])
|
||||
self.assertEqual({}, self.port.extra)
|
||||
|
||||
def test__save_vif_to_port_like_obj_portgroup(self):
|
||||
vif_id = "fake_vif_id"
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id)
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid()
|
||||
)
|
||||
self.interface._save_vif_to_port_like_obj(pg, vif_id)
|
||||
pg.refresh()
|
||||
self.assertIn(common.TENANT_VIF_KEY, pg.internal_info)
|
||||
self.assertEqual(vif_id,
|
||||
pg.internal_info[common.TENANT_VIF_KEY])
|
||||
self.assertEqual({}, pg.extra)
|
||||
|
||||
def test__clear_vif_from_port_like_obj_in_extra_port(self):
|
||||
self.interface._clear_vif_from_port_like_obj(self.port)
|
||||
self.port.refresh()
|
||||
self.assertNotIn('vif_port_id', self.port.extra)
|
||||
self.assertNotIn(common.TENANT_VIF_KEY, self.port.internal_info)
|
||||
|
||||
def test__clear_vif_from_port_like_obj_in_internal_info_port(self):
|
||||
self.port.internal_info = {
|
||||
common.TENANT_VIF_KEY: self.port.extra['vif_port_id']}
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
|
||||
self.interface._clear_vif_from_port_like_obj(self.port)
|
||||
self.port.refresh()
|
||||
self.assertNotIn('vif_port_id', self.port.extra)
|
||||
self.assertNotIn(common.TENANT_VIF_KEY, self.port.internal_info)
|
||||
|
||||
def test__clear_vif_from_port_like_obj_in_extra_portgroup(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id,
|
||||
extra={'vif_port_id': vif_id})
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid()
|
||||
)
|
||||
self.interface._clear_vif_from_port_like_obj(pg)
|
||||
pg.refresh()
|
||||
self.assertNotIn('vif_port_id', pg.extra)
|
||||
self.assertNotIn(common.TENANT_VIF_KEY, pg.internal_info)
|
||||
|
||||
def test__clear_vif_from_port_like_obj_in_internal_info_portgroup(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id,
|
||||
internal_info={common.TENANT_VIF_KEY: vif_id})
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid()
|
||||
)
|
||||
self.interface._clear_vif_from_port_like_obj(pg)
|
||||
pg.refresh()
|
||||
self.assertNotIn('vif_port_id', pg.extra)
|
||||
self.assertNotIn(common.TENANT_VIF_KEY, pg.internal_info)
|
||||
|
||||
def test__get_port_like_obj_by_vif_id_in_extra(self):
|
||||
vif_id = self.port.extra["vif_port_id"]
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
result = self.interface._get_port_like_obj_by_vif_id(task, vif_id)
|
||||
self.assertEqual(self.port.id, result.id)
|
||||
|
||||
def test__get_port_like_obj_by_vif_id_in_internal_info(self):
|
||||
vif_id = self.port.extra["vif_port_id"]
|
||||
self.port.internal_info = {common.TENANT_VIF_KEY: vif_id}
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
result = self.interface._get_port_like_obj_by_vif_id(task, vif_id)
|
||||
self.assertEqual(self.port.id, result.id)
|
||||
|
||||
def test__get_port_like_obj_by_vif_id_not_attached(self):
|
||||
vif_id = self.port.extra["vif_port_id"]
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaisesRegex(exception.VifNotAttached,
|
||||
"it is not attached to it.",
|
||||
self.interface._get_port_like_obj_by_vif_id,
|
||||
task, vif_id)
|
||||
|
||||
def test__get_vif_id_by_port_like_obj_in_extra(self):
|
||||
vif_id = self.port.extra["vif_port_id"]
|
||||
result = self.interface._get_vif_id_by_port_like_obj(self.port)
|
||||
self.assertEqual(vif_id, result)
|
||||
|
||||
def test__get_vif_id_by_port_like_obj_in_internal_info(self):
|
||||
vif_id = self.port.extra["vif_port_id"]
|
||||
self.port.internal_info = {common.TENANT_VIF_KEY: vif_id}
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
result = self.interface._get_vif_id_by_port_like_obj(self.port)
|
||||
self.assertEqual(vif_id, result)
|
||||
|
||||
def test__get_vif_id_by_port_like_obj_not_attached(self):
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
result = self.interface._get_vif_id_by_port_like_obj(self.port)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_vif_list_extra(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
|
@ -495,265 +608,6 @@ class TestNeutronVifPortIDMixin(db_base.DbTestCase):
|
|||
vifs = self.interface.vif_list(task)
|
||||
self.assertEqual([{'id': vif_id}], vifs)
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach(self, mock_gpbpi, mock_upa, mock_client, mock_gfp):
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
self.port.refresh()
|
||||
self.assertEqual("fake_vif_id", self.port.internal_info.get(
|
||||
common.TENANT_VIF_KEY))
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_with_physnet(self, mock_gpbpi, mock_upa, mock_client,
|
||||
mock_gfp):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1'}
|
||||
mock_gfp.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
self.port.refresh()
|
||||
self.assertEqual("fake_vif_id", self.port.internal_info.get(
|
||||
common.TENANT_VIF_KEY))
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', {'physnet1'})
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_portgroup_no_address(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp):
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id, address=None)
|
||||
mock_gfp.return_value = pg
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
uuid=uuidutils.generate_uuid(), portgroup_id=pg.id)
|
||||
vif = {'id': "fake_vif_id"}
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
pg.refresh()
|
||||
self.assertEqual(vif['id'],
|
||||
pg.internal_info[common.TENANT_VIF_KEY])
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
self.assertFalse(mock_client.return_value.show_port.called)
|
||||
self.assertFalse(mock_upa.called)
|
||||
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_update_port_exception(self, mock_gpbpi, mock_upa,
|
||||
mock_client):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1'}
|
||||
mock_upa.side_effect = (
|
||||
exception.FailedToUpdateMacOnPort(port_id='fake'))
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.NetworkError, "can not update Neutron port",
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_neutron_absent(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
mock_client.return_value.show_port.side_effect = (
|
||||
neutron_exceptions.NeutronClientException)
|
||||
mock_gpbpi.side_effect = exception.NetworkError
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_upa.called)
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client')
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_portgroup_physnet_inconsistent(self, mock_gpbpi,
|
||||
mock_upa, mock_client,
|
||||
mock_gfp):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'anyphysnet'}
|
||||
mock_gfp.side_effect = exception.PortgroupPhysnetInconsistent(
|
||||
portgroup='fake-portgroup-id', physical_networks='physnet1')
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(
|
||||
exception.PortgroupPhysnetInconsistent,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_upa.called)
|
||||
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client')
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_multiple_segment_mappings(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, uuid=uuidutils.generate_uuid(),
|
||||
address='52:54:00:cf:2d:33', physical_network='physnet2')
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1', 'physnet2'}
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(
|
||||
exception.VifInvalidForAttach,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_gfp.called)
|
||||
self.assertFalse(mock_upa.called)
|
||||
|
||||
def test_vif_detach_in_extra(self):
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(
|
||||
task, self.port.extra['vif_port_id'])
|
||||
self.port.refresh()
|
||||
self.assertFalse('vif_port_id' in self.port.extra)
|
||||
self.assertFalse(common.TENANT_VIF_KEY in self.port.internal_info)
|
||||
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
def test_vif_detach_in_internal_info(self, mock_unp):
|
||||
self.port.internal_info = {
|
||||
common.TENANT_VIF_KEY: self.port.extra['vif_port_id']}
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(
|
||||
task, self.port.internal_info[common.TENANT_VIF_KEY])
|
||||
self.port.refresh()
|
||||
self.assertFalse('vif_port_id' in self.port.extra)
|
||||
self.assertFalse(common.TENANT_VIF_KEY in self.port.internal_info)
|
||||
self.assertFalse(mock_unp.called)
|
||||
|
||||
def test_vif_detach_in_extra_portgroup(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id,
|
||||
extra={'vif_port_id': vif_id})
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid()
|
||||
)
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, vif_id)
|
||||
pg.refresh()
|
||||
self.assertFalse('vif_port_id' in pg.extra)
|
||||
self.assertFalse(common.TENANT_VIF_KEY in pg.internal_info)
|
||||
|
||||
def test_vif_detach_in_extra_portgroup_manually_attached_to_port(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id)
|
||||
port = obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid(),
|
||||
extra={'vif_port_id': vif_id}
|
||||
)
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, vif_id)
|
||||
port.refresh()
|
||||
pg.refresh()
|
||||
self.assertFalse('vif_port_id' in port.extra)
|
||||
self.assertFalse(common.TENANT_VIF_KEY in pg.internal_info)
|
||||
|
||||
def test_vif_detach_in_internal_info_portgroup(self):
|
||||
vif_id = uuidutils.generate_uuid()
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id,
|
||||
internal_info={common.TENANT_VIF_KEY: vif_id})
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, address='52:54:00:cf:2d:01',
|
||||
portgroup_id=pg.id, uuid=uuidutils.generate_uuid()
|
||||
)
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, vif_id)
|
||||
pg.refresh()
|
||||
self.assertFalse('vif_port_id' in pg.extra)
|
||||
self.assertFalse(common.TENANT_VIF_KEY in pg.internal_info)
|
||||
|
||||
def test_vif_detach_not_attached(self):
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.VifNotAttached, "it is not attached to it.",
|
||||
self.interface.vif_detach, task, 'aaa')
|
||||
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
def test_vif_detach_active_node(self, mock_unp):
|
||||
vif_id = self.port.extra['vif_port_id']
|
||||
self.port.internal_info = {
|
||||
common.TENANT_VIF_KEY: vif_id}
|
||||
self.port.extra = {}
|
||||
self.port.save()
|
||||
self.node.provision_state = states.ACTIVE
|
||||
self.node.save()
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(
|
||||
task, self.port.internal_info[common.TENANT_VIF_KEY])
|
||||
self.port.refresh()
|
||||
mock_unp.assert_called_once_with(vif_id)
|
||||
|
||||
def test_get_current_vif_extra_vif_port_id(self):
|
||||
extra = {'vif_port_id': 'foo'}
|
||||
self.port.extra = extra
|
||||
|
@ -797,6 +651,326 @@ class TestNeutronVifPortIDMixin(db_base.DbTestCase):
|
|||
vif = self.interface.get_current_vif(task, self.port)
|
||||
self.assertIsNone(vif)
|
||||
|
||||
|
||||
class TestNeutronVifPortIDMixin(db_base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNeutronVifPortIDMixin, self).setUp()
|
||||
self.config(enabled_drivers=['fake'])
|
||||
mgr_utils.mock_the_extension_manager()
|
||||
self.interface = common.NeutronVIFPortIDMixin()
|
||||
self.node = obj_utils.create_test_node(self.context,
|
||||
network_interface='neutron')
|
||||
self.port = obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id,
|
||||
address='52:54:00:cf:2d:32',
|
||||
extra={'vif_port_id': uuidutils.generate_uuid(),
|
||||
'client-id': 'fake1'})
|
||||
self.neutron_port = {'id': '132f871f-eaec-4fed-9475-0d54465e0f00',
|
||||
'mac_address': '52:54:00:cf:2d:32'}
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach(self, mock_gpbpi, mock_upa, mock_client, mock_gfp,
|
||||
mock_save):
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
mock_save.assert_called_once_with(self.port, "fake_vif_id")
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_failure(self, mock_gpbpi, mock_upa, mock_client,
|
||||
mock_gfp, mock_save):
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.side_effect = exception.NoFreePhysicalPorts(vif='fake-vif')
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(exception.NoFreePhysicalPorts,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
self.assertFalse(mock_save.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_with_physnet(self, mock_gpbpi, mock_upa, mock_client,
|
||||
mock_gfp, mock_save):
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1'}
|
||||
mock_gfp.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', {'physnet1'})
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
mock_save.assert_called_once_with(self.port, "fake_vif_id")
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'plug_port_to_tenant_network', autospec=True)
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_active_node(self, mock_gpbpi, mock_upa, mock_client,
|
||||
mock_gfp, mock_plug, mock_save):
|
||||
self.node.provision_state = states.ACTIVE
|
||||
self.node.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
mock_save.assert_called_once_with(self.port, "fake_vif_id")
|
||||
mock_plug.assert_called_once_with(task, self.port, mock.ANY)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'plug_port_to_tenant_network', autospec=True)
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_active_node_failure(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp, mock_plug,
|
||||
mock_save):
|
||||
self.node.provision_state = states.ACTIVE
|
||||
self.node.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
mock_plug.side_effect = exception.NetworkError
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(exception.NetworkError,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
mock_upa.assert_called_once_with("fake_vif_id", self.port.address)
|
||||
mock_save.assert_called_once_with(self.port, "fake_vif_id")
|
||||
mock_plug.assert_called_once_with(task, self.port, mock.ANY)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_portgroup_no_address(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp, mock_save):
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id, address=None)
|
||||
mock_gfp.return_value = pg
|
||||
vif = {'id': "fake_vif_id"}
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
self.assertFalse(mock_gpbpi.called)
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
self.assertFalse(mock_client.return_value.show_port.called)
|
||||
self.assertFalse(mock_upa.called)
|
||||
mock_save.assert_called_once_with(pg, "fake_vif_id")
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_update_port_exception(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_save):
|
||||
self.port.extra = {}
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1'}
|
||||
mock_upa.side_effect = (
|
||||
exception.FailedToUpdateMacOnPort(port_id='fake'))
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.NetworkError, "can not update Neutron port",
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_save.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_neutron_absent(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp, mock_save):
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gfp.return_value = self.port
|
||||
mock_client.return_value.show_port.side_effect = (
|
||||
neutron_exceptions.NeutronClientException)
|
||||
mock_gpbpi.side_effect = exception.NetworkError
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_attach(task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
mock_gfp.assert_called_once_with(task, 'fake_vif_id', set())
|
||||
mock_client.return_value.show_port.assert_called_once_with(
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_upa.called)
|
||||
self.assertTrue(mock_save.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client')
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_portgroup_physnet_inconsistent(self, mock_gpbpi,
|
||||
mock_upa, mock_client,
|
||||
mock_gfp, mock_save):
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'anyphysnet'}
|
||||
mock_gfp.side_effect = exception.PortgroupPhysnetInconsistent(
|
||||
portgroup='fake-portgroup-id', physical_networks='physnet1')
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(
|
||||
exception.PortgroupPhysnetInconsistent,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_upa.called)
|
||||
self.assertFalse(mock_save.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_save_vif_to_port_like_obj')
|
||||
@mock.patch.object(common, 'get_free_port_like_object', autospec=True)
|
||||
@mock.patch.object(neutron_common, 'get_client')
|
||||
@mock.patch.object(neutron_common, 'update_port_address')
|
||||
@mock.patch.object(neutron_common, 'get_physnets_by_port_uuid',
|
||||
autospec=True)
|
||||
def test_vif_attach_multiple_segment_mappings(self, mock_gpbpi, mock_upa,
|
||||
mock_client, mock_gfp,
|
||||
mock_save):
|
||||
self.port.physical_network = 'physnet1'
|
||||
self.port.save()
|
||||
obj_utils.create_test_port(
|
||||
self.context, node_id=self.node.id, uuid=uuidutils.generate_uuid(),
|
||||
address='52:54:00:cf:2d:33', physical_network='physnet2')
|
||||
vif = {'id': "fake_vif_id"}
|
||||
mock_gpbpi.return_value = {'physnet1', 'physnet2'}
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(
|
||||
exception.VifInvalidForAttach,
|
||||
self.interface.vif_attach, task, vif)
|
||||
mock_client.assert_called_once_with()
|
||||
mock_gpbpi.assert_called_once_with(mock_client.return_value,
|
||||
'fake_vif_id')
|
||||
self.assertFalse(mock_gfp.called)
|
||||
self.assertFalse(mock_upa.called)
|
||||
self.assertFalse(mock_save.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_get_port_like_obj_by_vif_id')
|
||||
def test_vif_detach(self, mock_get, mock_unp, mock_clear):
|
||||
mock_get.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, 'fake_vif_id')
|
||||
mock_get.assert_called_once_with(task, 'fake_vif_id')
|
||||
self.assertFalse(mock_unp.called)
|
||||
mock_clear.assert_called_once_with(self.port)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_get_port_like_obj_by_vif_id')
|
||||
def test_vif_detach_portgroup(self, mock_get, mock_unp, mock_clear):
|
||||
pg = obj_utils.create_test_portgroup(
|
||||
self.context, node_id=self.node.id)
|
||||
mock_get.return_value = pg
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, 'fake_vif_id')
|
||||
mock_get.assert_called_once_with(task, 'fake_vif_id')
|
||||
self.assertFalse(mock_unp.called)
|
||||
mock_clear.assert_called_once_with(pg)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_get_port_like_obj_by_vif_id')
|
||||
def test_vif_detach_not_attached(self, mock_get, mock_unp, mock_clear):
|
||||
mock_get.side_effect = exception.VifNotAttached(vif='fake-vif',
|
||||
node='fake-node')
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.VifNotAttached, "it is not attached to it.",
|
||||
self.interface.vif_detach, task, 'fake_vif_id')
|
||||
mock_get.assert_called_once_with(task, 'fake_vif_id')
|
||||
self.assertFalse(mock_unp.called)
|
||||
self.assertFalse(mock_clear.called)
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_get_port_like_obj_by_vif_id')
|
||||
def test_vif_detach_active_node(self, mock_get, mock_unp, mock_clear):
|
||||
self.node.provision_state = states.ACTIVE
|
||||
self.node.save()
|
||||
mock_get.return_value = self.port
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.interface.vif_detach(task, 'fake_vif_id')
|
||||
mock_get.assert_called_once_with(task, 'fake_vif_id')
|
||||
mock_clear.assert_called_once_with(self.port)
|
||||
mock_unp.assert_called_once_with('fake_vif_id')
|
||||
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_clear_vif_from_port_like_obj')
|
||||
@mock.patch.object(neutron_common, 'unbind_neutron_port', autospec=True)
|
||||
@mock.patch.object(common.VIFPortIDMixin, '_get_port_like_obj_by_vif_id')
|
||||
def test_vif_detach_active_node_failure(self, mock_get, mock_unp,
|
||||
mock_clear):
|
||||
self.node.provision_state = states.ACTIVE
|
||||
self.node.save()
|
||||
mock_get.return_value = self.port
|
||||
mock_unp.side_effect = exception.NetworkError
|
||||
with task_manager.acquire(self.context, self.node.id) as task:
|
||||
self.assertRaises(exception.NetworkError,
|
||||
self.interface.vif_detach, task, 'fake_vif_id')
|
||||
mock_get.assert_called_once_with(task, 'fake_vif_id')
|
||||
mock_clear.assert_called_once_with(self.port)
|
||||
mock_unp.assert_called_once_with('fake_vif_id')
|
||||
|
||||
@mock.patch.object(common_utils, 'warn_about_deprecated_extra_vif_port_id',
|
||||
autospec=True)
|
||||
@mock.patch.object(neutron_common, 'update_port_address', autospec=True)
|
||||
|
|
Loading…
Reference in New Issue