|
|
|
@ -14,16 +14,13 @@
|
|
|
|
|
# limitations under the License. |
|
|
|
|
|
|
|
|
|
import mock |
|
|
|
|
from neutron_lib.api.definitions import portbindings |
|
|
|
|
from neutron_lib.db import api as db_api |
|
|
|
|
from neutron_lib.plugins.ml2 import api as driver_api |
|
|
|
|
from oslo_config import cfg |
|
|
|
|
|
|
|
|
|
from neutron.tests.unit import testlib_api |
|
|
|
|
|
|
|
|
|
from networking_arista.common import db_lib |
|
|
|
|
from networking_arista.ml2 import mechanism_arista |
|
|
|
|
import networking_arista.tests.unit.ml2.utils as utils |
|
|
|
|
from networking_arista.tests.unit import utils |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setup_valid_config(): |
|
|
|
@ -37,21 +34,6 @@ class AristaProvisionedVlansStorageTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
as a group. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def test_tenant_is_remembered(self): |
|
|
|
|
tenant_id = 'test' |
|
|
|
|
|
|
|
|
|
db_lib.remember_tenant(tenant_id) |
|
|
|
|
net_provisioned = db_lib.is_tenant_provisioned(tenant_id) |
|
|
|
|
self.assertTrue(net_provisioned, 'Tenant must be provisioned') |
|
|
|
|
|
|
|
|
|
def test_tenant_is_removed(self): |
|
|
|
|
tenant_id = 'test' |
|
|
|
|
|
|
|
|
|
db_lib.remember_tenant(tenant_id) |
|
|
|
|
db_lib.forget_tenant(tenant_id) |
|
|
|
|
net_provisioned = db_lib.is_tenant_provisioned(tenant_id) |
|
|
|
|
self.assertFalse(net_provisioned, 'The Tenant should be deleted') |
|
|
|
|
|
|
|
|
|
def test_network_is_remembered(self): |
|
|
|
|
tenant_id = 'test' |
|
|
|
|
network_id = '123' |
|
|
|
@ -132,31 +114,6 @@ class AristaProvisionedVlansStorageTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
'There should be %d nets, not %d' % |
|
|
|
|
(expected, num_nets_provisioned)) |
|
|
|
|
|
|
|
|
|
def test_remembers_multiple_tenants(self): |
|
|
|
|
expected_num_tenants = 100 |
|
|
|
|
tenants = ['id%s' % n for n in range(expected_num_tenants)] |
|
|
|
|
for tenant_id in tenants: |
|
|
|
|
db_lib.remember_tenant(tenant_id) |
|
|
|
|
|
|
|
|
|
num_tenants_provisioned = db_lib.num_provisioned_tenants() |
|
|
|
|
self.assertEqual(expected_num_tenants, num_tenants_provisioned, |
|
|
|
|
'There should be %d tenants, not %d' % |
|
|
|
|
(expected_num_tenants, num_tenants_provisioned)) |
|
|
|
|
|
|
|
|
|
def test_removes_multiple_tenants(self): |
|
|
|
|
num_tenants = 100 |
|
|
|
|
tenants = ['id%s' % n for n in range(num_tenants)] |
|
|
|
|
for tenant_id in tenants: |
|
|
|
|
db_lib.remember_tenant(tenant_id) |
|
|
|
|
for tenant_id in tenants: |
|
|
|
|
db_lib.forget_tenant(tenant_id) |
|
|
|
|
|
|
|
|
|
num_tenants_provisioned = db_lib.num_provisioned_tenants() |
|
|
|
|
expected = 0 |
|
|
|
|
self.assertEqual(expected, num_tenants_provisioned, |
|
|
|
|
'There should be %d tenants, not %d' % |
|
|
|
|
(expected, num_tenants_provisioned)) |
|
|
|
|
|
|
|
|
|
def test_num_vm_is_valid(self): |
|
|
|
|
tenant_id = 'test' |
|
|
|
|
network_id = '123' |
|
|
|
@ -233,7 +190,7 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
network_id = 'net1-id' |
|
|
|
|
segmentation_id = 1001 |
|
|
|
|
|
|
|
|
|
network_context = self._get_network_context(tenant_id, |
|
|
|
|
network_context = utils.get_network_context(tenant_id, |
|
|
|
|
network_id, |
|
|
|
|
segmentation_id) |
|
|
|
|
self.drv.create_network_precommit(network_context) |
|
|
|
@ -263,7 +220,7 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
segmentation_id = 1001 |
|
|
|
|
nets = ['id%s' % n for n in range(expected_num_nets)] |
|
|
|
|
for net_id in nets: |
|
|
|
|
network_context = self._get_network_context(tenant_id, |
|
|
|
|
network_context = utils.get_network_context(tenant_id, |
|
|
|
|
net_id, |
|
|
|
|
segmentation_id) |
|
|
|
|
self.drv.create_network_precommit(network_context) |
|
|
|
@ -275,7 +232,7 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
|
|
|
|
|
# Now test the delete networks |
|
|
|
|
for net_id in nets: |
|
|
|
|
network_context = self._get_network_context(tenant_id, |
|
|
|
|
network_context = utils.get_network_context(tenant_id, |
|
|
|
|
net_id, |
|
|
|
|
segmentation_id) |
|
|
|
|
self.drv.delete_network_precommit(network_context) |
|
|
|
@ -292,18 +249,18 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
segmentation_id = 1001 |
|
|
|
|
vms = ['vm1', 'vm2', 'vm3'] |
|
|
|
|
|
|
|
|
|
network_context = self._get_network_context(tenant_id, |
|
|
|
|
network_context = utils.get_network_context(tenant_id, |
|
|
|
|
network_id, |
|
|
|
|
segmentation_id) |
|
|
|
|
self.drv.create_network_precommit(network_context) |
|
|
|
|
|
|
|
|
|
for vm_id in vms: |
|
|
|
|
port_id = '%s_%s' % (vm_id, 101) |
|
|
|
|
port_context = self._get_port_context(port_id, |
|
|
|
|
tenant_id, |
|
|
|
|
port_context = utils.get_port_context(tenant_id, |
|
|
|
|
network_id, |
|
|
|
|
vm_id, |
|
|
|
|
network_context) |
|
|
|
|
network_context, |
|
|
|
|
port_id=port_id) |
|
|
|
|
self.drv.update_port_precommit(port_context) |
|
|
|
|
|
|
|
|
|
vm_list = db_lib.get_vms(tenant_id) |
|
|
|
@ -316,11 +273,11 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
# Now test the delete ports |
|
|
|
|
for vm_id in vms: |
|
|
|
|
port_id = '%s_%s' % (vm_id, 101) |
|
|
|
|
port_context = self._get_port_context(port_id, |
|
|
|
|
tenant_id, |
|
|
|
|
port_context = utils.get_port_context(tenant_id, |
|
|
|
|
network_id, |
|
|
|
|
vm_id, |
|
|
|
|
network_context) |
|
|
|
|
network_context, |
|
|
|
|
port_id=port_id) |
|
|
|
|
self.drv.delete_port_precommit(port_context) |
|
|
|
|
|
|
|
|
|
vm_list = db_lib.get_vms(tenant_id) |
|
|
|
@ -332,22 +289,11 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
|
|
|
|
|
def test_cleanup_on_start(self): |
|
|
|
|
"""Ensures that the driver cleans up the arista database on startup.""" |
|
|
|
|
ndb = db_lib.NeutronNets() |
|
|
|
|
|
|
|
|
|
# create a shared session |
|
|
|
|
session = db_api.get_writer_session() |
|
|
|
|
|
|
|
|
|
# Create some networks in neutron db |
|
|
|
|
n1_context = self._get_network_context('t1', 'n1', 10, session) |
|
|
|
|
ndb.create_network(n1_context, {'network': n1_context.current}) |
|
|
|
|
n2_context = self._get_network_context('t2', 'n2', 20, session) |
|
|
|
|
ndb.create_network(n2_context, {'network': n2_context.current}) |
|
|
|
|
n3_context = self._get_network_context('', 'ha-network', 100, session) |
|
|
|
|
ndb.create_network(n3_context, {'network': n3_context.current}) |
|
|
|
|
|
|
|
|
|
# Objects were created in different sessions, but Neutron no longer |
|
|
|
|
# implicitly flushes subtransactions. |
|
|
|
|
session.flush() |
|
|
|
|
utils.create_network('t1', 'n1', 10) |
|
|
|
|
utils.create_network('t2', 'n2', 20) |
|
|
|
|
utils.create_network('', 'ha-network', 100) |
|
|
|
|
|
|
|
|
|
# Create some networks in Arista db |
|
|
|
|
db_lib.remember_network_segment('t1', 'n1', 10, 'segment_id_10') |
|
|
|
@ -372,139 +318,3 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
ds.assert_called_once_with() |
|
|
|
|
|
|
|
|
|
def _get_network_context(self, tenant_id, net_id, seg_id, session=None): |
|
|
|
|
network = {'id': net_id, |
|
|
|
|
'tenant_id': tenant_id, |
|
|
|
|
'name': net_id, |
|
|
|
|
'admin_state_up': True, |
|
|
|
|
'shared': False, |
|
|
|
|
} |
|
|
|
|
network_segments = [{'segmentation_id': seg_id, |
|
|
|
|
'id': 'segment_%s' % net_id, |
|
|
|
|
'network_type': 'vlan'}] |
|
|
|
|
return FakeNetworkContext(network, network_segments, network, session) |
|
|
|
|
|
|
|
|
|
def _get_port_context(self, port_id, tenant_id, net_id, vm_id, network): |
|
|
|
|
port = {'device_id': vm_id, |
|
|
|
|
'device_owner': 'compute', |
|
|
|
|
'binding:host_id': 'ubuntu1', |
|
|
|
|
'binding:vnic_type': 'normal', |
|
|
|
|
'tenant_id': tenant_id, |
|
|
|
|
'id': port_id, |
|
|
|
|
'network_id': net_id, |
|
|
|
|
'name': '', |
|
|
|
|
'status': 'ACTIVE', |
|
|
|
|
} |
|
|
|
|
binding_levels = [] |
|
|
|
|
for level, segment in enumerate(network.network_segments): |
|
|
|
|
binding_levels.append(FakePortBindingLevel(port['id'], |
|
|
|
|
level, |
|
|
|
|
'vendor-1', |
|
|
|
|
segment['id'])) |
|
|
|
|
return FakePortContext(port, port, network, port['status'], |
|
|
|
|
binding_levels) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FakeNetworkContext(object): |
|
|
|
|
"""To generate network context for testing purposes only.""" |
|
|
|
|
|
|
|
|
|
def __init__(self, network, segments=None, original_network=None, |
|
|
|
|
session=None): |
|
|
|
|
self._network = network |
|
|
|
|
self._original_network = original_network |
|
|
|
|
self._segments = segments |
|
|
|
|
self.is_admin = False |
|
|
|
|
self.tenant_id = network['tenant_id'] |
|
|
|
|
self.session = session or db_api.get_reader_session() |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def current(self): |
|
|
|
|
return self._network |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def original(self): |
|
|
|
|
return self._original_network |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def network_segments(self): |
|
|
|
|
return self._segments |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FakePluginContext(object): |
|
|
|
|
"""Plugin context for testing purposes only.""" |
|
|
|
|
|
|
|
|
|
def __init__(self, tenant_id): |
|
|
|
|
self.tenant_id = tenant_id |
|
|
|
|
self.session = mock.MagicMock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FakePortContext(object): |
|
|
|
|
"""To generate port context for testing purposes only.""" |
|
|
|
|
|
|
|
|
|
def __init__(self, port, original_port, network, status, |
|
|
|
|
binding_levels): |
|
|
|
|
self._plugin_context = None |
|
|
|
|
self._port = port |
|
|
|
|
self._original_port = original_port |
|
|
|
|
self._network_context = network |
|
|
|
|
self._status = status |
|
|
|
|
self._binding_levels = binding_levels |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def current(self): |
|
|
|
|
return self._port |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def original(self): |
|
|
|
|
return self._original_port |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def network(self): |
|
|
|
|
return self._network_context |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def host(self): |
|
|
|
|
return self._port.get(portbindings.HOST_ID) |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def original_host(self): |
|
|
|
|
return self._original_port.get(portbindings.HOST_ID) |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def status(self): |
|
|
|
|
return self._status |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def original_status(self): |
|
|
|
|
if self._original_port: |
|
|
|
|
return self._original_port['status'] |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def binding_levels(self): |
|
|
|
|
if self._binding_levels: |
|
|
|
|
return [{ |
|
|
|
|
driver_api.BOUND_DRIVER: level.driver, |
|
|
|
|
driver_api.BOUND_SEGMENT: |
|
|
|
|
self._expand_segment(level.segment_id) |
|
|
|
|
} for level in self._binding_levels] |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def bottom_bound_segment(self): |
|
|
|
|
if self._binding_levels: |
|
|
|
|
return self._expand_segment(self._binding_levels[-1].segment_id) |
|
|
|
|
|
|
|
|
|
def _expand_segment(self, segment_id): |
|
|
|
|
for segment in self._network_context.network_segments: |
|
|
|
|
if segment[driver_api.ID] == segment_id: |
|
|
|
|
return segment |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FakePortBindingLevel(object): |
|
|
|
|
"""Port binding object for testing purposes only.""" |
|
|
|
|
|
|
|
|
|
def __init__(self, port_id, level, driver, segment_id): |
|
|
|
|
self.port_id = port_id |
|
|
|
|
self.level = level |
|
|
|
|
self.driver = driver |
|
|
|
|
self.segment_id = segment_id |
|
|
|
|