Browse Source

Merge "Remove use of the arista_provisioned_tenants table"

changes/78/517378/6
Zuul 4 years ago committed by Gerrit Code Review
parent
commit
b19ac5d5a4
  1. 12
      networking_arista/common/db.py
  2. 86
      networking_arista/common/db_lib.py
  3. 1
      networking_arista/db/migration/alembic_migrations/versions/CONTRACT_HEAD
  4. 1
      networking_arista/db/migration/alembic_migrations/versions/EXPAND_HEAD
  5. 34
      networking_arista/db/migration/alembic_migrations/versions/queens/contract/dc7bf9c1ab4d_drop_aristaprovisionedtenants.py
  6. 4
      networking_arista/ml2/arista_sync.py
  7. 5
      networking_arista/ml2/mechanism_arista.py
  8. 133
      networking_arista/tests/unit/common/test_db_lib.py
  9. 2
      networking_arista/tests/unit/ml2/rpc/test_arista_eapi_rpc_wrapper.py
  10. 2
      networking_arista/tests/unit/ml2/rpc/test_arista_json_rpc_wrapper.py
  11. 218
      networking_arista/tests/unit/ml2/test_arista_mechanism_driver.py
  12. 186
      networking_arista/tests/unit/ml2/test_arista_sync.py
  13. 268
      networking_arista/tests/unit/ml2/test_mechanism_arista.py
  14. 32
      networking_arista/tests/unit/ml2/utils.py
  15. 198
      networking_arista/tests/unit/utils.py

12
networking_arista/common/db.py

@ -69,15 +69,3 @@ class AristaProvisionedVms(model_base.BASEV2, model_base.HasId,
u'deviceId': self.vm_id,
u'hosts': [self.host_id],
u'networkId': self.network_id}
class AristaProvisionedTenants(model_base.BASEV2, model_base.HasId,
HasTenant):
"""Stores Tenants provisioned on Arista EOS.
Tenants list is maintained for sync between Neutron and EOS.
"""
__tablename__ = 'arista_provisioned_tenants'
def eos_tenant_representation(self):
return {u'tenantId': self.tenant_id}

86
networking_arista/common/db_lib.py

@ -20,6 +20,7 @@ from neutron_lib.plugins.ml2 import api as driver_api
import neutron.db.api as db
from neutron.db import db_base_plugin_v2
from neutron.db.models import segment as segment_models
from neutron.db import models_v2
from neutron.db import securitygroups_db as sec_db
from neutron.db import segments_db
from neutron.plugins.ml2 import models as ml2_models
@ -30,46 +31,6 @@ from networking_arista.common import db as db_models
VLAN_SEGMENTATION = 'vlan'
def remember_tenant(tenant_id):
"""Stores a tenant information in repository.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
tenant = (session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).first())
if not tenant:
tenant = db_models.AristaProvisionedTenants(tenant_id=tenant_id)
session.add(tenant)
def forget_tenant(tenant_id):
"""Removes a tenant information from repository.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
(session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).
delete())
def get_all_tenants():
"""Returns a list of all tenants stored in repository."""
session = db.get_reader_session()
with session.begin():
return session.query(db_models.AristaProvisionedTenants).all()
def num_provisioned_tenants():
"""Returns number of tenants stored in repository."""
session = db.get_reader_session()
with session.begin():
return session.query(db_models.AristaProvisionedTenants).count()
def remember_vm(vm_id, host_id, port_id, network_id, tenant_id):
"""Stores all relevant information about a VM in repository.
@ -255,19 +216,6 @@ def is_network_provisioned(tenant_id, network_id, segmentation_id=None,
return num_nets > 0
def is_tenant_provisioned(tenant_id):
"""Checks if a tenant is already known to EOS
:returns: True, if yes; False otherwise.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
num_tenants = (session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).count())
return num_tenants > 0
def num_nets_provisioned(tenant_id):
"""Returns number of networks for a given tennat.
@ -406,16 +354,17 @@ def get_ports(tenant_id=None):
def get_tenants():
"""Returns list of all tenants in EOS-compatible format."""
"""Returns list of all project/tenant ids that may be relevant on CVX."""
session = db.get_reader_session()
project_ids = set()
with session.begin():
model = db_models.AristaProvisionedTenants
all_tenants = session.query(model)
res = dict(
(tenant.tenant_id, tenant.eos_tenant_representation())
for tenant in all_tenants
)
return res
network_model = models_v2.Network
project_ids |= set(pid[0] for pid in
session.query(network_model.project_id).distinct())
port_model = models_v2.Port
project_ids |= set(pid[0] for pid in
session.query(port_model.project_id).distinct())
return project_ids
def _make_port_dict(record):
@ -439,7 +388,7 @@ def get_all_baremetal_ports():
def get_all_portbindings():
"""Returns a list of all ports bindings."""
session = db.get_session()
session = db.get_reader_session()
with session.begin():
query = session.query(ml2_models.PortBinding)
ports = query.all()
@ -500,13 +449,6 @@ class NeutronNets(db_base_plugin_v2.NeutronDbPluginV2,
def __init__(self):
self.admin_ctx = nctx.get_admin_context()
def get_network_name(self, tenant_id, network_id):
network = self._get_network(tenant_id, network_id)
network_name = None
if network:
network_name = network[0]['name']
return network_name
def get_all_networks_for_tenant(self, tenant_id):
filters = {'tenant_id': [tenant_id]}
return super(NeutronNets,
@ -556,12 +498,6 @@ class NeutronNets(db_base_plugin_v2.NeutronDbPluginV2,
return super(NeutronNets,
self).get_networks(ctxt, filters=filters) or []
def _get_network(self, tenant_id, network_id):
filters = {'tenant_id': [tenant_id],
'id': [network_id]}
return super(NeutronNets,
self).get_networks(self.admin_ctx, filters=filters) or []
def get_subnet_info(self, subnet_id):
return self.get_subnet(subnet_id)

1
networking_arista/db/migration/alembic_migrations/versions/CONTRACT_HEAD

@ -0,0 +1 @@
dc7bf9c1ab4d

1
networking_arista/db/migration/alembic_migrations/versions/EXPAND_HEAD

@ -0,0 +1 @@
1c6993ce7db0

34
networking_arista/db/migration/alembic_migrations/versions/queens/contract/dc7bf9c1ab4d_drop_aristaprovisionedtenants.py

@ -0,0 +1,34 @@
# Copyright 2017 Arista Networks, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Drop AristaProvisionedTenants
Revision ID: dc7bf9c1ab4d
Revises: 47036dc8697a
Create Date: 2017-08-23 17:10:36.000671
"""
# revision identifiers, used by Alembic.
revision = 'dc7bf9c1ab4d'
down_revision = '47036dc8697a'
branch_labels = None
depends_on = None
from alembic import op
def upgrade():
op.drop_table('arista_provisioned_tenants')

4
networking_arista/ml2/arista_sync.py

@ -158,7 +158,7 @@ class SyncService(object):
# Delete tenants that are in EOS, but not in the database
tenants_to_delete = frozenset(eos_tenants.keys()).difference(
db_tenants.keys())
db_tenants)
if tenants_to_delete:
try:
@ -185,7 +185,7 @@ class SyncService(object):
# In second loop, update VMs. This is done to ensure that networks for
# all tenats are updated before VMs are updated
instances_to_update = {}
for tenant in db_tenants.keys():
for tenant in db_tenants:
db_nets = db_lib.get_networks(tenant)
db_instances = db_lib.get_vms(tenant)

5
networking_arista/ml2/mechanism_arista.py

@ -60,7 +60,6 @@ class AristaDriver(driver_api.MechanismDriver):
self.ndb = db_lib.NeutronNets()
self.db_nets = db.AristaProvisionedNets()
self.db_vms = db.AristaProvisionedVms()
self.db_tenants = db.AristaProvisionedTenants()
confg = cfg.CONF.ml2_arista
self.segmentation_type = db_lib.VLAN_SEGMENTATION
@ -100,7 +99,6 @@ class AristaDriver(driver_api.MechanismDriver):
network_id = network['id']
tenant_id = network['tenant_id'] or constants.INTERNAL_TENANT_ID
with self.eos_sync_lock:
db_lib.remember_tenant(tenant_id)
for segment in segments:
db_lib.remember_network_segment(tenant_id,
network_id,
@ -531,7 +529,6 @@ class AristaDriver(driver_api.MechanismDriver):
LOG.info(
_LI("Adding %s to provisioned network database"), seg)
with self.eos_sync_lock:
db_lib.remember_tenant(tenant_id)
db_lib.remember_network_segment(
tenant_id, network_id,
seg[driver_api.SEGMENTATION_ID],
@ -562,7 +559,6 @@ class AristaDriver(driver_api.MechanismDriver):
if not port_provisioned:
LOG.info("Remembering the port")
# Create a new port in the DB
db_lib.remember_tenant(tenant_id)
db_lib.remember_vm(device_id, host, port_id,
network_id, tenant_id)
else:
@ -906,7 +902,6 @@ class AristaDriver(driver_api.MechanismDriver):
objects_for_tenant = (db_lib.num_nets_provisioned(tenant_id) +
db_lib.num_vms_provisioned(tenant_id))
if not objects_for_tenant:
db_lib.forget_tenant(tenant_id)
try:
self.rpc.delete_tenant(tenant_id)
except arista_exc.AristaRpcError:

133
networking_arista/tests/unit/common/test_db_lib.py

@ -0,0 +1,133 @@
# Copyright (c) 2017 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from oslo_utils import importutils
from neutron.tests.unit import testlib_api
from networking_arista.common import db_lib
from networking_arista.tests.unit import utils
class DbLibTest(testlib_api.SqlTestCase):
"""Test cases for database helper functions."""
def setUp(self):
super(DbLibTest, self).setUp()
plugin_klass = importutils.import_class(
"neutron.db.db_base_plugin_v2.NeutronDbPluginV2")
directory.add_plugin(plugin_constants.CORE, plugin_klass())
def test_get_tenants_empty(self):
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set())
def test_get_tenants_from_networks(self):
tenant_1_id = 't1'
network_1_id = 'n1'
seg_1_id = 11
utils.create_network(tenant_1_id,
network_1_id,
seg_1_id)
tenant_2_id = 't2'
network_2_id = 'n2'
seg_2_id = 21
utils.create_network(tenant_2_id,
network_2_id,
seg_2_id)
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set([tenant_1_id, tenant_2_id]))
def test_get_tenants_with_shared_network_ports(self):
tenant_1_id = 't1'
port_1_id = 'p1'
device_1_id = 'v1'
tenant_2_id = 't2'
port_2_id = 'p2'
device_2_id = 'v2'
network_id = 'n1'
seg_id = 11
network_ctx = utils.create_network(tenant_1_id,
network_id,
seg_id,
shared=True)
utils.create_port(tenant_1_id, network_id, device_1_id,
port_1_id, network_ctx)
utils.create_port(tenant_2_id, network_id, device_2_id,
port_2_id, network_ctx)
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set([tenant_1_id, tenant_2_id]))
def test_get_tenants_uniqueness(self):
tenant_1_id = 't1'
network_1_id = 'n1'
seg_1_id = 11
network_1_ctx = utils.create_network(tenant_1_id,
network_1_id,
seg_1_id)
tenant_2_id = 't2'
network_2_id = 'n2'
seg_2_id = 21
network_2_ctx = utils.create_network(tenant_2_id,
network_2_id,
seg_2_id)
device_1_id = 'v1'
port_1_id = 'p1'
device_2_id = 'v2'
port_2_id = 'p2'
utils.create_port(tenant_1_id, network_1_id, device_1_id,
port_1_id, network_1_ctx)
utils.create_port(tenant_2_id, network_2_id, device_2_id,
port_2_id, network_2_ctx)
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set([tenant_1_id, tenant_2_id]))
def test_get_tenants_port_network_union(self):
tenant_1_id = 't1'
network_1_id = 'n1'
seg_1_id = 11
network_1_ctx = utils.create_network(tenant_1_id,
network_1_id,
seg_1_id,
shared=True)
tenant_2_id = 't2'
network_2_id = 'n2'
seg_2_id = 21
network_2_ctx = utils.create_network(tenant_2_id,
network_2_id,
seg_2_id,
shared=True)
tenant_3_id = 't3'
port_1_id = 'p1'
device_1_id = 'v1'
utils.create_port(tenant_3_id, network_1_id, device_1_id, port_1_id,
network_1_ctx)
tenant_4_id = 't4'
port_2_id = 'p2'
device_2_id = 'v2'
utils.create_port(tenant_4_id, network_2_id, device_2_id, port_2_id,
network_2_ctx)
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set([tenant_1_id, tenant_2_id,
tenant_3_id, tenant_4_id]))

2
networking_arista/tests/unit/ml2/rpc/test_arista_eapi_rpc_wrapper.py

@ -22,7 +22,7 @@ from neutron.tests.unit import testlib_api
from networking_arista.common import db_lib
from networking_arista.common import exceptions as arista_exc
from networking_arista.ml2.rpc import arista_eapi
import networking_arista.tests.unit.ml2.utils as utils
from networking_arista.tests.unit import utils
EAPI_SEND_FUNC = ('networking_arista.ml2.rpc.arista_eapi.AristaRPCWrapperEapi'

2
networking_arista/tests/unit/ml2/rpc/test_arista_json_rpc_wrapper.py

@ -30,7 +30,7 @@ from neutron.tests.unit import testlib_api
from networking_arista.common import db_lib
from networking_arista.ml2.rpc import arista_json
import networking_arista.tests.unit.ml2.utils as utils
from networking_arista.tests.unit import utils
BASE_RPC = "networking_arista.ml2.rpc.arista_json.AristaRPCWrapperJSON."

218
networking_arista/tests/unit/ml2/test_arista_mechanism_driver.py

@ -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

186
networking_arista/tests/unit/ml2/test_arista_sync.py

@ -22,6 +22,7 @@ from neutron.tests.unit import testlib_api
from networking_arista.common import db_lib
from networking_arista.ml2 import arista_sync
from networking_arista.tests.unit import utils
class SyncServiceTest(testlib_api.SqlTestCase):
@ -68,7 +69,7 @@ class SyncServiceTest(testlib_api.SqlTestCase):
network_id = 'net-1'
segmentation_id = 42
segment_id = 'segment_id_1'
db_lib.remember_tenant(tenant_id)
utils.create_network(tenant_id, network_id, segmentation_id)
db_lib.remember_network_segment(tenant_id, network_id, segmentation_id,
segment_id)
@ -94,7 +95,7 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_id,
[{'network_id': network_id,
'segments': [],
'network_name': '',
'network_name': network_id,
'shared': False}],
sync=True),
mock.call.sync_end(),
@ -108,7 +109,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
)
db_lib.forget_network_segment(tenant_id, network_id)
db_lib.forget_tenant(tenant_id)
def test_sync_start_failure(self):
"""Tests that we force another sync when sync_start fails.
@ -170,14 +170,17 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_1_id = 'tenant-1'
tenant_1_net_1_id = 'ten-1-net-1'
tenant_1_net_1_seg_id = 11
db_lib.remember_tenant(tenant_1_id)
utils.create_network(tenant_1_id, tenant_1_net_1_id,
tenant_1_net_1_seg_id)
db_lib.remember_network_segment(tenant_1_id, tenant_1_net_1_id,
tenant_1_net_1_seg_id, 'segment_id_11')
tenant_2_id = 'tenant-2'
tenant_2_net_1_id = 'ten-2-net-1'
tenant_2_net_1_seg_id = 21
db_lib.remember_tenant(tenant_2_id)
utils.create_network(tenant_2_id, tenant_2_net_1_id,
tenant_2_net_1_seg_id)
db_lib.remember_network_segment(tenant_2_id, tenant_2_net_1_id,
tenant_2_net_1_seg_id, 'segment_id_21')
@ -219,7 +222,7 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_2_id,
[{'network_id': tenant_2_net_1_id,
'segments': [],
'network_name': '',
'network_name': tenant_2_net_1_id,
'shared': False}],
sync=True),
@ -231,25 +234,25 @@ class SyncServiceTest(testlib_api.SqlTestCase):
db_lib.forget_network_segment(tenant_1_id, tenant_1_net_1_id)
db_lib.forget_network_segment(tenant_2_id, tenant_2_net_1_id)
db_lib.forget_tenant(tenant_1_id)
db_lib.forget_tenant(tenant_2_id)
def test_synchronize_all_networks(self):
"""Test to ensure that only the required resources are sent to EOS."""
# Store two tenants in a db and none on EOS.
# The sync should send details of all tenants to EOS
tenant_1_id = u'tenant-1'
tenant_1_net_1_id = u'ten-1-net-1'
tenant_1_id = 'tenant-1'
tenant_1_net_1_id = 'ten-1-net-1'
tenant_1_net_1_seg_id = 11
db_lib.remember_tenant(tenant_1_id)
utils.create_network(tenant_1_id, tenant_1_net_1_id,
tenant_1_net_1_seg_id)
db_lib.remember_network_segment(tenant_1_id, tenant_1_net_1_id,
tenant_1_net_1_seg_id, 'segment_id_11')
tenant_2_id = u'tenant-2'
tenant_2_net_1_id = u'ten-2-net-1'
tenant_2_id = 'tenant-2'
tenant_2_net_1_id = 'ten-2-net-1'
tenant_2_net_1_seg_id = 21
db_lib.remember_tenant(tenant_2_id)
utils.create_network(tenant_2_id, tenant_2_net_1_id,
tenant_2_net_1_seg_id)
db_lib.remember_network_segment(tenant_2_id, tenant_2_net_1_id,
tenant_2_net_1_seg_id, 'segment_id_21')
@ -277,7 +280,7 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_1_id,
[{'network_id': tenant_1_net_1_id,
'segments': [],
'network_name': '',
'network_name': tenant_1_net_1_id,
'shared': False}],
sync=True),
@ -285,51 +288,134 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_2_id,
[{'network_id': tenant_2_net_1_id,
'segments': [],
'network_name': '',
'network_name': tenant_2_net_1_id,
'shared': False}],
sync=True),
mock.call.sync_end(),
mock.call.get_region_updated_time()
]
# The create_network_bulk() can be called in different order. So split
# The create_instance_bulk() can be called in different order. So split
# it up. The first part checks if the initial set of methods are
# invoked.
idx = expected_calls.index(mock.call.get_tenants()) + 1
self.assertTrue(self.rpc.mock_calls[:idx] == expected_calls[:idx],
"Seen: %s\nExpected: %s" % (
self.rpc.mock_calls,
expected_calls,
)
)
# Check if tenant 1 networks are created. It must be one of the two
# methods.
self.assertTrue(self.rpc.mock_calls[idx] in
expected_calls[idx:idx + 2],
"Seen: %s\nExpected: %s" % (
self.rpc.mock_calls,
expected_calls,
)
)
# Check if tenant 2 networks are created. It must be one of the two
# methods.
self.assertTrue(self.rpc.mock_calls[idx + 1] in
expected_calls[idx:idx + 2],
"Seen: %s\nExpected: %s" % (
self.rpc.mock_calls,
expected_calls,
)
)
self.rpc.assert_has_calls(expected_calls[:idx])
# Check if tenant ports are created.
self.rpc.assert_has_calls(expected_calls[idx:idx + 2], any_order=True)
# Check if the sync end methods are invoked.
self.assertTrue(self.rpc.mock_calls[idx + 2:] ==
expected_calls[idx + 2:],
"Seen: %s\nExpected: %s" % (
self.rpc.mock_calls,
expected_calls,
)
)
self.rpc.assert_has_calls(expected_calls[idx + 2:])
db_lib.forget_network_segment(tenant_1_id, tenant_1_net_1_id)
db_lib.forget_network_segment(tenant_2_id, tenant_2_net_1_id)
db_lib.forget_tenant(tenant_1_id)
db_lib.forget_tenant(tenant_2_id)
def test_synchronize_shared_network_ports(self):
"""Test to ensure that shared network ports are synchronized.
This is to ensure that ports whose tenant id does not match the
network tenant id are still sync'd. The test stores a network and
2 ports in the neutron db and only the network in EOS.
The sync should send details of the ports to EOS.
"""
tenant_1_id = 'tenant-1'
network_id = 'net-1'
seg_id = 11
network_ctx = utils.create_network(tenant_1_id, network_id, seg_id,
shared=True)
db_lib.remember_network_segment(tenant_1_id, network_id,
seg_id, 'segment_id_11')
host_id = 'host-1'
port_1_id = 'port-1'
device_1_id = 'vm-1'
utils.create_port(tenant_1_id, network_id, device_1_id, port_1_id,
network_ctx)
db_lib.remember_vm(device_1_id, host_id, port_1_id, network_id,
tenant_1_id)
tenant_2_id = 'tenant-2'
port_2_id = 'port-2'
device_2_id = 'vm-2'
utils.create_port(tenant_2_id, network_id, device_2_id, port_2_id,
network_ctx)
db_lib.remember_vm(device_2_id, host_id, port_2_id, network_id,
tenant_2_id)
self.rpc.get_tenants.return_value = {
tenant_1_id: {
'tenantVmInstances': {},
'tenantBaremetalInstances': {},
'tenantNetworks': {
network_id: {
'networkId': network_id,
'shared': True,
'networkName': '',
'segmenationType': 'vlan',
'segmentationTypeId': seg_id,
}
}
}
}
self.rpc.sync_start.return_value = True
self.rpc.sync_end.return_value = True
self.rpc.check_cvx_availability.return_value = True
self.rpc.get_region_updated_time.return_value = {'regionTimestamp': 1}
self.rpc._baremetal_supported.return_value = False
self.rpc.get_all_baremetal_hosts.return_value = {}
self.sync_service.do_synchronize()
expected_calls = [
mock.call.perform_sync_of_sg(),
mock.call.check_cvx_availability(),
mock.call.get_region_updated_time(),
mock.call.sync_start(),
mock.call.register_with_eos(sync=True),
mock.call.get_tenants(),
mock.call.create_instance_bulk(
tenant_1_id,
{port_1_id: {'device_owner': 'compute',
'device_id': device_1_id,
'name': '',
'id': port_1_id,
'tenant_id': tenant_1_id,
'network_id': network_id}},
db_lib.get_vms(tenant_1_id),
{},
sync=True),
mock.call.create_instance_bulk(
tenant_2_id,
{port_2_id: {'device_owner': 'compute',
'device_id': device_2_id,
'name': '',
'id': port_2_id,
'tenant_id': tenant_2_id,
'network_id': network_id}},
db_lib.get_vms(tenant_2_id),
{},
sync=True),
mock.call.sync_end(),
mock.call.get_region_updated_time()
]
# The create_instance_bulk() can be called in different order. So split
# it up. The first part checks if the initial set of methods are
# invoked.
idx = expected_calls.index(mock.call.get_tenants()) + 1
self.rpc.assert_has_calls(expected_calls[:idx])
# Check if tenant ports are created.
self.rpc.assert_has_calls(expected_calls[idx:idx + 2], any_order=True)
# Check if the sync end methods are invoked.
self.rpc.assert_has_calls(expected_calls[idx + 2:])
db_lib.forget_all_ports_for_network(network_id)
db_lib.forget_network_segment(tenant_1_id, network_id)

268
networking_arista/tests/unit/ml2/test_mechanism_arista.py

@ -14,9 +14,7 @@
# limitations under the License.
import mock
from neutron_lib.api.definitions import portbindings
from neutron_lib import constants as n_const
from neutron_lib.plugins.ml2 import api as driver_api
from neutron.db import models_v2
from neutron.plugins.ml2 import models as port_models
@ -25,6 +23,7 @@ from neutron.services.trunk import models as trunk_models
from neutron.tests.unit import testlib_api
from networking_arista.ml2 import mechanism_arista
from networking_arista.tests.unit import utils
INTERNAL_TENANT_ID = 'INTERNAL-TENANT-ID'
@ -51,7 +50,8 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net1-id'
segmentation_id = 1001
network_context = self._get_network_context(tenant_id,
self.drv.rpc.hpb_supported.return_value = True
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -59,7 +59,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segment_id = network_context.network_segments[0]['id']
expected_calls = [
mock.call.remember_tenant(tenant_id),
mock.call.remember_network_segment(tenant_id,
network_id,
segmentation_id,
@ -74,7 +73,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net2-id'
segmentation_id = 1002
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -83,7 +82,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segment_id = network_context.network_segments[0]['id']
expected_calls += [
mock.call.remember_tenant(INTERNAL_TENANT_ID),
mock.call.remember_network_segment(INTERNAL_TENANT_ID,
network_id,
segmentation_id,
@ -97,7 +95,7 @@ class AristaDriverTestCase(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,
False)
@ -125,7 +123,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net2-id'
segmentation_id = 1002
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -153,7 +151,7 @@ class AristaDriverTestCase(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,
False)
@ -178,7 +176,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net2-id'
segmentation_id = 1002
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -203,7 +201,7 @@ class AristaDriverTestCase(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,
False)
@ -231,7 +229,8 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net1-id'
segmentation_id = 1001
network_context = self._get_network_context(tenant_id,
self.drv.rpc.hpb_supported.return_value = True
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -244,7 +243,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_context.network_segments),
mock.call.num_nets_provisioned(tenant_id),
mock.call.num_vms_provisioned(tenant_id),
mock.call.forget_tenant(tenant_id),
mock.call.delete_tenant(tenant_id),
]
@ -256,7 +254,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id = 'net2-id'
segmentation_id = 1002
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
@ -268,7 +266,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_context.network_segments),
mock.call.num_nets_provisioned(INTERNAL_TENANT_ID),
mock.call.num_vms_provisioned(INTERNAL_TENANT_ID),
mock.call.forget_tenant(INTERNAL_TENANT_ID),
mock.call.delete_tenant(INTERNAL_TENANT_ID),
]
@ -280,12 +277,12 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1001
vm_id = 'vm1'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -300,7 +297,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id, None),
mock.call.remember_tenant(tenant_id),
mock.call.remember_vm(vm_id, host_id, port_id,
network_id, tenant_id)
]
@ -314,11 +310,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1002
vm_id = 'vm2'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -335,7 +331,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
expected_calls += [
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id,
None),
mock.call.remember_tenant(INTERNAL_TENANT_ID),
mock.call.remember_vm(vm_id, host_id, port_id,
network_id, INTERNAL_TENANT_ID)
]
@ -347,11 +342,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1001
vm_id = 'vm1'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -391,11 +386,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1002
vm_id = 'vm2'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -435,12 +430,12 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1001
vm_id = 'vm1'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -464,11 +459,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1002
vm_id = 'vm2'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -492,11 +487,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1001
vm_id = 'vm1'
network_context = self._get_network_context(tenant_id,
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
port_context = self._get_port_context(tenant_id,
port_context = utils.get_port_context(tenant_id,
network_id,
vm_id,
network_context)
@ -529,7 +524,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mock.call.remove_security_group(None, profile),
mock.call.num_nets_provisioned(tenant_id),
mock.call.num_vms_provisioned(tenant_id),
mock.call.forget_tenant(tenant_id),
mock.call.delete_tenant(tenant_id),
]
for binding_level in port_context.binding_levels:
@ -545,11 +539,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id = 1002
vm_id = 'vm2'