Browse Source

Remove use of the arista_provisioned_nets table

Instead make use of neutron's networks and networksegments
tables.

Change-Id: Ief033c3e7e4f8158e77be10f9f764aa024b11729
changes/26/498126/8
Mitchell Jameson 5 years ago
parent
commit
85ba98ef12
  1. 22
      networking_arista/common/db.py
  2. 139
      networking_arista/common/db_lib.py
  3. 2
      networking_arista/db/migration/alembic_migrations/versions/CONTRACT_HEAD
  4. 34
      networking_arista/db/migration/alembic_migrations/versions/queens/contract/39c2eeb67116_drop_aristaprovisionednets.py
  5. 25
      networking_arista/ml2/arista_sync.py
  6. 234
      networking_arista/ml2/mechanism_arista.py
  7. 34
      networking_arista/tests/unit/common/test_db_lib.py
  8. 161
      networking_arista/tests/unit/ml2/test_arista_mechanism_driver.py
  9. 23
      networking_arista/tests/unit/ml2/test_arista_sync.py
  10. 322
      networking_arista/tests/unit/ml2/test_mechanism_arista.py
  11. 15
      networking_arista/tests/unit/utils.py

22
networking_arista/common/db.py

@ -28,28 +28,6 @@ class HasTenant(object):
index=True)
class AristaProvisionedNets(model_base.BASEV2, model_base.HasId,
HasTenant):
"""Stores networks provisioned on Arista EOS.
Saves the segmentation ID for each network that is provisioned
on EOS. This information is used during synchronization between
Neutron and EOS.
"""
__tablename__ = 'arista_provisioned_nets'
network_id = sa.Column(sa.String(UUID_LEN))
segmentation_id = sa.Column(sa.Integer)
def eos_network_representation(self, segmentation_type):
return {u'networkId': self.network_id,
u'segmentationTypeId': self.segmentation_id,
u'segmentationType': segmentation_type,
u'tenantId': self.tenant_id,
u'segmentId': self.id,
}
class AristaProvisionedVms(model_base.BASEV2, model_base.HasId,
HasTenant):
"""Stores VMs provisioned on Arista EOS.

139
networking_arista/common/db_lib.py

@ -96,59 +96,6 @@ def forget_port(port_id, host_id):
host_id=host_id).delete()
def remember_network_segment(tenant_id,
network_id, segmentation_id, segment_id):
"""Stores all relevant information about a Network in repository.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segmentation_id: segmentation id that is assigned to the network
:param segment_id: globally unique neutron network segment identifier
"""
session = db.get_writer_session()
with session.begin():
net = db_models.AristaProvisionedNets(
tenant_id=tenant_id,
id=segment_id,
network_id=network_id,
segmentation_id=segmentation_id)
session.add(net)
def forget_network_segment(tenant_id, network_id, segment_id=None):
"""Deletes all relevant information about a Network from repository.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segment_id: globally unique neutron network segment identifier
"""
filters = {
'tenant_id': tenant_id,
'network_id': network_id
}
if segment_id:
filters['id'] = segment_id
session = db.get_writer_session()
with session.begin():
(session.query(db_models.AristaProvisionedNets).
filter_by(**filters).delete())
def get_segmentation_id(tenant_id, network_id):
"""Returns Segmentation ID (VLAN) associated with a network.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
"""
session = db.get_reader_session()
with session.begin():
net = (session.query(db_models.AristaProvisionedNets).
filter_by(tenant_id=tenant_id,
network_id=network_id).first())
return net.segmentation_id if net else None
def is_vm_provisioned(vm_id, host_id, port_id,
network_id, tenant_id):
"""Checks if a VM is already known to EOS
@ -192,41 +139,6 @@ def is_port_provisioned(port_id, host_id=None):
return num_ports > 0
def is_network_provisioned(tenant_id, network_id, segmentation_id=None,
segment_id=None):
"""Checks if a networks is already known to EOS
:returns: True, if yes; False otherwise.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segment_id: globally unique neutron network segment identifier
"""
session = db.get_reader_session()
with session.begin():
filters = {'tenant_id': tenant_id,
'network_id': network_id}
if segmentation_id:
filters['segmentation_id'] = segmentation_id
if segment_id:
filters['id'] = segment_id
num_nets = (session.query(db_models.AristaProvisionedNets).
filter_by(**filters).count())
return num_nets > 0
def num_nets_provisioned(tenant_id):
"""Returns number of networks for a given tennat.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
return (session.query(db_models.AristaProvisionedNets).
filter_by(tenant_id=tenant_id).count())
def num_vms_provisioned(tenant_id):
"""Returns number of VMs for a given tennat.
@ -238,35 +150,6 @@ def num_vms_provisioned(tenant_id):
filter_by(tenant_id=tenant_id).count())
def get_networks(tenant_id):
"""Returns all networks for a given tenant in EOS-compatible format.
See AristaRPCWrapper.get_network_list() for return value format.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedNets
# hack for pep8 E711: comparison to None should be
# 'if cond is not None'
none = None
all_nets = []
if tenant_id != 'any':
all_nets = (session.query(model).
filter(model.tenant_id == tenant_id,
model.segmentation_id != none))
else:
all_nets = (session.query(model).
filter(model.segmentation_id != none))
res = dict(
(net.network_id, net.eos_network_representation(
VLAN_SEGMENTATION))
for net in all_nets
)
return res
def get_vms(tenant_id):
"""Returns all VMs for a given tenant in EOS-compatible format.
@ -353,6 +236,28 @@ def get_ports(tenant_id=None):
return ports
def get_all_anet_nets():
"""Return the set of networks in the arista_provisioned_vms table."""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedVms
return set(nid[0] for nid in
session.query(model.network_id).distinct())
def tenant_provisioned(tid):
"""Returns true if any networks or ports exist for a tenant."""
session = db.get_reader_session()
with session.begin():
network_model = models_v2.Network
port_model = models_v2.Port
res = bool(
session.query(network_model).filter_by(tenant_id=tid).count() or
session.query(port_model).filter_by(tenant_id=tid).count()
)
return res
def get_tenants():
"""Returns list of all project/tenant ids that may be relevant on CVX."""
session = db.get_reader_session()

2
networking_arista/db/migration/alembic_migrations/versions/CONTRACT_HEAD

@ -1 +1 @@
dc7bf9c1ab4d
39c2eeb67116

34
networking_arista/db/migration/alembic_migrations/versions/queens/contract/39c2eeb67116_drop_aristaprovisionednets.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 AristaProvisionedNets
Revision ID: 39c2eeb67116
Revises: dc7bf9c1ab4d
Create Date: 2017-08-25 16:42:31.814580
"""
# revision identifiers, used by Alembic.
revision = '39c2eeb67116'
down_revision = 'dc7bf9c1ab4d'
branch_labels = None
depends_on = None
from alembic import op
def upgrade():
op.drop_table('arista_provisioned_nets')

25
networking_arista/ml2/arista_sync.py

@ -72,16 +72,12 @@ class AristaSyncWorker(worker.BaseWorker):
LOG.info('Arista Sync: DB Cleanup')
neutron_nets = self.ndb.get_all_networks()
arista_db_nets = db_lib.get_networks(tenant_id='any')
neutron_net_ids = set()
for net in neutron_nets:
neutron_net_ids.add(net['id'])
arista_db_nets = db_lib.get_all_anet_nets()
neutron_net_ids = set([net['id'] for net in neutron_nets])
# Remove networks from the Arista DB if the network does not exist in
# Neutron DB
for net_id in set(arista_db_nets.keys()).difference(neutron_net_ids):
tenant_network = arista_db_nets[net_id]
db_lib.forget_network_segment(tenant_network['tenantId'], net_id)
for net_id in arista_db_nets.difference(neutron_net_ids):
db_lib.forget_all_ports_for_network(net_id)
@ -172,12 +168,6 @@ class SyncService(object):
# operations fail, then force_sync is set to true
self._force_sync = False
# Create a dict of networks keyed by id.
neutron_nets = dict(
(network['id'], network) for network in
self._ndb.get_all_networks()
)
# Get Baremetal port switch_bindings, if any
port_profiles = db_lib.get_all_portbindings()
# To support shared networks, split the sync loop in two parts:
@ -186,7 +176,8 @@ class SyncService(object):
# all tenats are updated before VMs are updated
instances_to_update = {}
for tenant in db_tenants:
db_nets = db_lib.get_networks(tenant)
db_nets = {n['id']: n
for n in self._ndb.get_all_networks_for_tenant(tenant)}
db_instances = db_lib.get_vms(tenant)
eos_nets = self._get_eos_networks(eos_tenants, tenant)
@ -247,10 +238,10 @@ class SyncService(object):
networks = [{
'network_id': net_id,
'network_name':
neutron_nets.get(net_id, {'name': ''})['name'],
db_nets.get(net_id, {'name': ''})['name'],
'shared':
neutron_nets.get(net_id,
{'shared': False})['shared'],
db_nets.get(net_id,
{'shared': False})['shared'],
'segments': self._ndb.get_all_network_segments(net_id),
}
for net_id in nets_to_update

234
networking_arista/ml2/mechanism_arista.py

@ -58,7 +58,6 @@ class AristaDriver(driver_api.MechanismDriver):
def __init__(self, rpc=None):
self.ndb = db_lib.NeutronNets()
self.db_nets = db.AristaProvisionedNets()
self.db_vms = db.AristaProvisionedVms()
confg = cfg.CONF.ml2_arista
@ -91,20 +90,6 @@ class AristaDriver(driver_api.MechanismDriver):
def get_workers(self):
return [arista_sync.AristaSyncWorker(self.rpc, self.ndb)]
def create_network_precommit(self, context):
"""Remember the tenant, and network information."""
network = context.current
segments = context.network_segments
network_id = network['id']
tenant_id = network['tenant_id'] or constants.INTERNAL_TENANT_ID
with self.eos_sync_lock:
for segment in segments:
db_lib.remember_network_segment(tenant_id,
network_id,
segment.get('segmentation_id'),
segment.get('id'))
def create_network_postcommit(self, context):
"""Provision the network on the Arista Hardware."""
@ -115,21 +100,17 @@ class AristaDriver(driver_api.MechanismDriver):
segments = context.network_segments
shared_net = network['shared']
with self.eos_sync_lock:
if db_lib.is_network_provisioned(tenant_id, network_id):
try:
network_dict = {
'network_id': network_id,
'segments': segments,
'network_name': network_name,
'shared': shared_net}
self.rpc.create_network(tenant_id, network_dict)
except arista_exc.AristaRpcError as err:
LOG.error(_LE("create_network_postcommit: Did not create "
"network %(name)s. Reason: %(err)s"),
{'name': network_name, 'err': err})
else:
LOG.info(_LI('Network %s is not created as it is not found in '
'Arista DB'), network_id)
try:
network_dict = {
'network_id': network_id,
'segments': segments,
'network_name': network_name,
'shared': shared_net}
self.rpc.create_network(tenant_id, network_dict)
except arista_exc.AristaRpcError as err:
LOG.error(_LE("create_network_postcommit: Did not create "
"network %(name)s. Reason: %(err)s"),
{'name': network_name, 'err': err})
def update_network_precommit(self, context):
"""At the moment we only support network name change
@ -159,35 +140,28 @@ class AristaDriver(driver_api.MechanismDriver):
constants.INTERNAL_TENANT_ID)
shared_net = new_network['shared']
with self.eos_sync_lock:
if db_lib.is_network_provisioned(tenant_id, network_id):
try:
network_dict = {
'network_id': network_id,
'segments': context.network_segments,
'network_name': network_name,
'shared': shared_net}
self.rpc.create_network(tenant_id, network_dict)
except arista_exc.AristaRpcError as err:
LOG.error(_LE('update_network_postcommit: Did not '
'update network %(name)s. '
'Reason: %(err)s'),
{'name': network_name, 'err': err})
else:
LOG.info(_LI('Network %s is not updated as it is not found'
' in Arista DB'), network_id)
try:
network_dict = {
'network_id': network_id,
'segments': context.network_segments,
'network_name': network_name,
'shared': shared_net}
self.rpc.create_network(tenant_id, network_dict)
except arista_exc.AristaRpcError as err:
LOG.error(_LE('update_network_postcommit: Did not '
'update network %(name)s. '
'Reason: %(err)s'),
{'name': network_name, 'err': err})
def delete_network_precommit(self, context):
"""Delete the network information from the DB."""
network = context.current
network_id = network['id']
tenant_id = network['tenant_id'] or constants.INTERNAL_TENANT_ID
with self.eos_sync_lock:
if db_lib.is_network_provisioned(tenant_id, network_id):
if db_lib.are_ports_attached_to_network(network_id):
db_lib.forget_all_ports_for_network(network_id)
LOG.info(_LI('Deleting all ports on network %s'),
network_id)
db_lib.forget_network_segment(tenant_id, network_id)
if db_lib.are_ports_attached_to_network(network_id):
db_lib.forget_all_ports_for_network(network_id)
LOG.info(_LI('Deleting all ports on network %s'),
network_id)
def delete_network_postcommit(self, context):
"""Send network delete request to Arista HW."""
@ -196,7 +170,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:
# Succeed deleting network in case EOS is not accessible.
# EOS state will be updated by sync thread once EOS gets
# alive.
@ -451,35 +424,26 @@ class AristaDriver(driver_api.MechanismDriver):
tenant_id = self._network_owner_tenant(context, network_id,
tenant_id)
for binding_level in context._original_binding_levels or []:
if self._network_provisioned(
tenant_id, network_id,
segment_id=binding_level.segment_id):
with self.eos_sync_lock:
# Removing the port form original host
self._delete_port(orig_port, orig_host, tenant_id)
# If segment id is not bound to any port, then
# remove it from EOS
segment = self.ndb.get_segment_by_id(
context._plugin_context,
binding_level.segment_id)
if not segment:
try:
segment_info = [{
'id': binding_level.segment_id,
'network_id': network_id,
}]
LOG.debug("migration_postcommit:"
"deleting segment %s", segment_info)
self.rpc.delete_network_segments(tenant_id,
segment_info)
# Remove the segment from the provisioned
# network DB.
db_lib.forget_network_segment(
tenant_id, network_id,
binding_level.segment_id)
except arista_exc.AristaRpcError:
LOG.info(constants.EOS_UNREACHABLE_MSG)
with self.eos_sync_lock:
# Removing the port form original host
self._delete_port(orig_port, orig_host, tenant_id)
# If segment id is not bound to any port, then
# remove it from EOS
segment = self.ndb.get_segment_by_id(
context._plugin_context,
binding_level.segment_id)
if not segment:
try:
segment_info = [{
'id': binding_level.segment_id,
'network_id': network_id,
}]
LOG.debug("migration_postcommit:"
"deleting segment %s", segment_info)
self.rpc.delete_network_segments(tenant_id,
segment_info)
except arista_exc.AristaRpcError:
LOG.info(constants.EOS_UNREACHABLE_MSG)
return True
@ -522,18 +486,6 @@ class AristaDriver(driver_api.MechanismDriver):
# Ensure that we use tenant Id for the network owner
tenant_id = self._network_owner_tenant(context, network_id, tenant_id)
for seg in seg_info:
if not self._network_provisioned(tenant_id, network_id,
seg[driver_api.SEGMENTATION_ID],
seg[driver_api.ID]):
LOG.info(
_LI("Adding %s to provisioned network database"), seg)
with self.eos_sync_lock:
db_lib.remember_network_segment(
tenant_id, network_id,
seg[driver_api.SEGMENTATION_ID],
seg[driver_api.ID])
with self.eos_sync_lock:
port_down = False
if(new_port['device_owner'] ==
@ -649,27 +601,6 @@ class AristaDriver(driver_api.MechanismDriver):
port_provisioned = db_lib.is_port_provisioned(port_id,
port_host_filter)
# If network does not exist under this tenant,
# it may be a shared network. Get shared network owner Id
net_provisioned = self._network_provisioned(
tenant_id, network_id)
for seg in seg_info:
if not self._network_provisioned(
tenant_id, network_id,
segmentation_id=seg[driver_api.SEGMENTATION_ID]):
net_provisioned = False
segments = []
if net_provisioned:
segments = seg_info
all_segments = self.ndb.get_all_network_segments(
network_id, context=context._plugin_context)
try:
self.rpc.create_network_segments(
tenant_id, network_id,
context.network.current['name'], all_segments)
except arista_exc.AristaRpcError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Failed to create network segments"))
try:
orig_host = context.original_host
@ -687,10 +618,19 @@ class AristaDriver(driver_api.MechanismDriver):
# connected to the port was deleted or its in DOWN
# state. So delete the old port on the old host.
self._delete_port(orig_port, orig_host, tenant_id)
if(port_provisioned and net_provisioned and hostname and
if(port_provisioned and hostname and
is_vm_boot and not port_down and
device_id != n_const.DEVICE_ID_RESERVED_DHCP_PORT):
segments = seg_info
all_segments = self.ndb.get_all_network_segments(
network_id, context=context._plugin_context)
try:
self.rpc.create_network_segments(
tenant_id, network_id,
context.network.current['name'], all_segments)
except arista_exc.AristaRpcError:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Failed to create network segments"))
LOG.info(_LI("Port plugged into network"))
# Plug port into the network only if it exists in the db
# and is bound to a host and the port is up.
@ -786,9 +726,6 @@ class AristaDriver(driver_api.MechanismDriver):
return
try:
if not self._network_provisioned(tenant_id, network_id):
# If we do not have network associated with this, ignore it
return
hostname = self._host_name(host)
trunk_details = port.get('trunk_details')
self.rpc.unplug_port_from_network(device_id, device_owner,
@ -817,30 +754,20 @@ class AristaDriver(driver_api.MechanismDriver):
return
for binding_level in context._binding_levels:
LOG.debug("deleting segment %s", binding_level.segment_id)
if self._network_provisioned(tenant_id, network_id,
segment_id=binding_level.segment_id):
segment = self.ndb.get_segment_by_id(
context._plugin_context, binding_level.segment_id)
if not segment:
# The segment is already released. Delete it from EOS
LOG.debug("Deleting segment %s", binding_level.segment_id)
try:
segment_info = {
'id': binding_level.segment_id,
'network_id': network_id,
}
self.rpc.delete_network_segments(tenant_id,
[segment_info])
# Remove the segment from the provisioned network DB.
db_lib.forget_network_segment(
tenant_id, network_id, binding_level.segment_id)
except arista_exc.AristaRpcError:
LOG.info(constants.EOS_UNREACHABLE_MSG)
else:
LOG.debug("Cannot delete segment_id %(segid)s "
"segment is %(seg)s",
{'segid': binding_level.segment_id,
'seg': segment})
segment = self.ndb.get_segment_by_id(
context._plugin_context, binding_level.segment_id)
if not segment:
# The segment is already released. Delete it from EOS
LOG.debug("Deleting segment %s", binding_level.segment_id)
try:
segment_info = {
'id': binding_level.segment_id,
'network_id': network_id,
}
self.rpc.delete_network_segments(tenant_id,
[segment_info])
except arista_exc.AristaRpcError:
LOG.info(constants.EOS_UNREACHABLE_MSG)
def _try_to_release_dynamic_segment(self, context, migration=False):
"""Release dynamic segment allocated by the driver
@ -896,12 +823,10 @@ class AristaDriver(driver_api.MechanismDriver):
def delete_tenant(self, tenant_id):
"""delete a tenant from DB.
A tenant is deleted only if there is no network or VM configured
A tenant is deleted only if there is no networks or ports configured
configured for this tenant.
"""
objects_for_tenant = (db_lib.num_nets_provisioned(tenant_id) +
db_lib.num_vms_provisioned(tenant_id))
if not objects_for_tenant:
if not db_lib.tenant_provisioned(tenant_id):
try:
self.rpc.delete_tenant(tenant_id)
except arista_exc.AristaRpcError:
@ -912,17 +837,6 @@ class AristaDriver(driver_api.MechanismDriver):
fqdns_used = cfg.CONF.ml2_arista['use_fqdn']
return hostname if fqdns_used else hostname.split('.')[0]
def _network_provisioned(self, tenant_id, network_id,
segmentation_id=None, segment_id=None):
# If network does not exist under this tenant,
# it may be a shared network.
return (
db_lib.is_network_provisioned(tenant_id, network_id,
segmentation_id, segment_id) or
self.ndb.get_shared_network_owner_id(network_id)
)
def create_security_group(self, sg):
try:
self.rpc.create_acl(sg)

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

@ -131,3 +131,37 @@ class DbLibTest(testlib_api.SqlTestCase):
tenants = db_lib.get_tenants()
self.assertEqual(tenants, set([tenant_1_id, tenant_2_id,
tenant_3_id, tenant_4_id]))
def test_get_all_anet_nets(self):
net_1_id = 'n1'
net_2_id = 'n2'
db_lib.remember_vm('vm1', 'h1', 'p1', net_1_id, 't1')
db_lib.remember_vm('vm2', 'h2', 'p2', net_2_id, 't2')
db_lib.remember_vm('vm3', 'h3', 'p3', net_2_id, 't3')
self.assertEqual(db_lib.get_all_anet_nets(),
set([net_1_id, net_2_id]))
def test_tenant_provisioned(self):
tenant_1_id = 't1'
port_1_id = 'p1'
tenant_2_id = 't2'
port_2_id = 'p2'
network_id = 'network-id'
self.assertFalse(db_lib.tenant_provisioned(tenant_1_id))
self.assertFalse(db_lib.tenant_provisioned(tenant_2_id))
n_ctx = utils.create_network(tenant_1_id, network_id, 11, shared=True)
self.assertTrue(db_lib.tenant_provisioned(tenant_1_id))
self.assertFalse(db_lib.tenant_provisioned(tenant_2_id))
p1_ctx = utils.create_port(tenant_1_id, network_id, 'vm1',
port_1_id, n_ctx)
self.assertTrue(db_lib.tenant_provisioned(tenant_1_id))
self.assertFalse(db_lib.tenant_provisioned(tenant_2_id))
p2_ctx = utils.create_port(tenant_2_id, network_id, 'vm2',
port_2_id, n_ctx)
self.assertTrue(db_lib.tenant_provisioned(tenant_1_id))
self.assertTrue(db_lib.tenant_provisioned(tenant_2_id))
utils.delete_port(p1_ctx, port_1_id)
utils.delete_port(p2_ctx, port_2_id)
utils.delete_network(n_ctx, network_id)
self.assertFalse(db_lib.tenant_provisioned(tenant_1_id))
self.assertFalse(db_lib.tenant_provisioned(tenant_2_id))

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

@ -34,29 +34,6 @@ class AristaProvisionedVlansStorageTestCase(testlib_api.SqlTestCase):
as a group.
"""
def test_network_is_remembered(self):
tenant_id = 'test'
network_id = '123'
segmentation_id = 456
segment_id = 'segment_id_%s' % segmentation_id
db_lib.remember_network_segment(tenant_id, network_id, segmentation_id,
segment_id)
net_provisioned = db_lib.is_network_provisioned(tenant_id,
network_id)
self.assertTrue(net_provisioned, 'Network must be provisioned')
def test_network_is_removed(self):
tenant_id = 'test'
network_id = '123'
segment_id = 'segment_id_1'
db_lib.remember_network_segment(tenant_id, network_id, '123',
segment_id)
db_lib.forget_network_segment(tenant_id, network_id)
net_provisioned = db_lib.is_network_provisioned(tenant_id, network_id)
self.assertFalse(net_provisioned, 'The network should be deleted')
def test_vm_is_remembered(self):
vm_id = 'VM-1'
tenant_id = 'test'
@ -82,38 +59,6 @@ class AristaProvisionedVlansStorageTestCase(testlib_api.SqlTestCase):
network_id, tenant_id)
self.assertFalse(vm_provisioned, 'The vm should be deleted')
def test_remembers_multiple_networks(self):
tenant_id = 'test'
expected_num_nets = 100
segment_id = 'segment_%s'
nets = ['id%s' % n for n in range(expected_num_nets)]
for net_id in nets:
db_lib.remember_network_segment(tenant_id, net_id, 123,
segment_id % net_id)
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
self.assertEqual(expected_num_nets, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected_num_nets, num_nets_provisioned))
def test_removes_all_networks(self):
tenant_id = 'test'
num_nets = 100
old_nets = db_lib.num_nets_provisioned(tenant_id)
nets = ['id_%s' % n for n in range(num_nets)]
segment_id = 'segment_%s'
for net_id in nets:
db_lib.remember_network_segment(tenant_id, net_id, 123,
segment_id % net_id)
for net_id in nets:
db_lib.forget_network_segment(tenant_id, net_id)
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
expected = old_nets
self.assertEqual(expected, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected, num_nets_provisioned))
def test_num_vm_is_valid(self):
tenant_id = 'test'
network_id = '123'
@ -139,35 +84,6 @@ class AristaProvisionedVlansStorageTestCase(testlib_api.SqlTestCase):
# clean up afterwards
db_lib.forget_port(port_id, host_id)
def test_get_network_list_returns_eos_compatible_data(self):
tenant = u'test-1'
segm_type = 'vlan'
network_id = u'123'
network2_id = u'1234'
vlan_id = 123
vlan2_id = 1234
segment_id1 = '11111-%s' % vlan_id
segment_id2 = '11111-%s' % vlan2_id
expected_eos_net_list = {network_id: {u'networkId': network_id,
u'segmentationTypeId': vlan_id,
u'tenantId': tenant,
u'segmentId': segment_id1,
u'segmentationType': segm_type},
network2_id: {u'networkId': network2_id,
u'tenantId': tenant,
u'segmentId': segment_id2,
u'segmentationTypeId': vlan2_id,
u'segmentationType': segm_type}}
db_lib.remember_network_segment(tenant,
network_id, vlan_id, segment_id1)
db_lib.remember_network_segment(tenant,
network2_id, vlan2_id, segment_id2)
net_list = db_lib.get_networks(tenant)
self.assertEqual(net_list, expected_eos_net_list, ('%s != %s' %
(net_list, expected_eos_net_list)))
class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
"""Main test cases for Arista Mechanism driver.
@ -185,64 +101,6 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
def tearDown(self):
super(RealNetStorageAristaDriverTestCase, self).tearDown()
def test_create_and_delete_network(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
segmentation_id = 1001
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id)
self.drv.create_network_precommit(network_context)
net_provisioned = db_lib.is_network_provisioned(tenant_id, network_id)
self.assertTrue(net_provisioned, 'The network should be created')
expected_num_nets = 1
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
self.assertEqual(expected_num_nets, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected_num_nets, num_nets_provisioned))
# Now test the delete network
self.drv.delete_network_precommit(network_context)
net_provisioned = db_lib.is_network_provisioned(tenant_id, network_id)
self.assertFalse(net_provisioned, 'The network should be created')
expected_num_nets = 0
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
self.assertEqual(expected_num_nets, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected_num_nets, num_nets_provisioned))
def test_create_and_delete_multiple_networks(self):
tenant_id = 'ten-1'
expected_num_nets = 100
segmentation_id = 1001
nets = ['id%s' % n for n in range(expected_num_nets)]
for net_id in nets:
network_context = utils.get_network_context(tenant_id,
net_id,
segmentation_id)
self.drv.create_network_precommit(network_context)
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
self.assertEqual(expected_num_nets, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected_num_nets, num_nets_provisioned))
# Now test the delete networks
for net_id in nets:
network_context = utils.get_network_context(tenant_id,
net_id,
segmentation_id)
self.drv.delete_network_precommit(network_context)
num_nets_provisioned = db_lib.num_nets_provisioned(tenant_id)
expected_num_nets = 0
self.assertEqual(expected_num_nets, num_nets_provisioned,
'There should be %d nets, not %d' %
(expected_num_nets, num_nets_provisioned))
def test_create_and_delete_ports(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
@ -295,12 +153,11 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
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')
db_lib.remember_network_segment('t2', 'n2', 20, 'segment_id_20')
db_lib.remember_network_segment('admin',
'ha-network', 100, 'segment_id_100')
db_lib.remember_network_segment('t3', 'n3', 30, 'segment_id_30')
db_lib.remember_vm('v1', 'h1', 'p1', 'n1', 't1')
db_lib.remember_vm('v2', 'h2', 'p2', 'n2', 't1')
db_lib.remember_vm('ha-instance', 'ha-host', 'ha-port',
'ha-network', 'admin')
db_lib.remember_vm('v3', 'h3', 'p3', 'n3', 't3')
# Initialize the driver which should clean up the extra networks
self.drv.initialize()
@ -309,12 +166,12 @@ class RealNetStorageAristaDriverTestCase(testlib_api.SqlTestCase):
with mock.patch.object(worker.sync_service, 'do_synchronize') as ds:
worker.start()
adb_networks = db_lib.get_networks(tenant_id='any')
adb_ports = db_lib.get_ports()
# 'n3' should now be deleted from the Arista DB
# 'p3' should now be deleted from the Arista DB
self.assertEqual(
set(('n1', 'n2', 'ha-network')),
set(adb_networks.keys())
set(('p1', 'p2', 'ha-port')),
set(adb_ports.keys())
)
ds.assert_called_once_with()

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

@ -68,10 +68,7 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_id = 'tenant-1'
network_id = 'net-1'
segmentation_id = 42
segment_id = 'segment_id_1'
utils.create_network(tenant_id, network_id, segmentation_id)
db_lib.remember_network_segment(tenant_id, network_id, segmentation_id,
segment_id)
self.rpc.get_tenants.return_value = {}
@ -108,8 +105,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
)
)
db_lib.forget_network_segment(tenant_id, network_id)
def test_sync_start_failure(self):
"""Tests that we force another sync when sync_start fails.
@ -172,8 +167,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_1_net_1_seg_id = 11
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'
@ -181,9 +174,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
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')
self.rpc.get_tenants.return_value = {
tenant_1_id: {
'tenantVmInstances': {},
@ -232,9 +222,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
self.rpc.assert_has_calls(expected_calls)
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)
def test_synchronize_all_networks(self):
"""Test to ensure that only the required resources are sent to EOS."""
@ -245,16 +232,12 @@ class SyncServiceTest(testlib_api.SqlTestCase):
tenant_1_net_1_seg_id = 11
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
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')
self.rpc.get_tenants.return_value = {}
@ -307,9 +290,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
# Check if the sync end methods are invoked.
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)
def test_synchronize_shared_network_ports(self):
"""Test to ensure that shared network ports are synchronized.
@ -324,8 +304,6 @@ class SyncServiceTest(testlib_api.SqlTestCase):
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'
@ -418,4 +396,3 @@ class SyncServiceTest(testlib_api.SqlTestCase):
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)

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

@ -45,51 +45,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
def tearDown(self):
super(AristaDriverTestCase, self).tearDown()
def test_create_network_precommit(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
segmentation_id = 1001
self.drv.rpc.hpb_supported.return_value = True
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
self.drv.create_network_precommit(network_context)
segment_id = network_context.network_segments[0]['id']
expected_calls = [
mock.call.remember_network_segment(tenant_id,
network_id,
segmentation_id,
segment_id)
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
# If there is no tenant id associated with the network, then the
# network should be created under the tenant id in the context.
tenant_id = 'ten-2'
network_id = 'net2-id'
segmentation_id = 1002
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
network_context.current['tenant_id'] = ''
self.drv.create_network_precommit(network_context)
segment_id = network_context.network_segments[0]['id']
expected_calls += [
mock.call.remember_network_segment(INTERNAL_TENANT_ID,
network_id,
segmentation_id,
segment_id)
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
def test_create_network_postcommit(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
@ -99,7 +54,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id,
segmentation_id,
False)
mechanism_arista.db_lib.is_network_provisioned.return_value = True
network = network_context.current
segments = network_context.network_segments
net_dict = {
@ -111,7 +65,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
self.drv.create_network_postcommit(network_context)
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id),
mock.call.create_network(tenant_id, net_dict),
]
@ -128,7 +81,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id,
False)
network_context.current['tenant_id'] = ''
mechanism_arista.db_lib.is_network_provisioned.return_value = True
network = network_context.current
segments = network_context.network_segments
net_dict = {
@ -140,90 +92,11 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
self.drv.create_network_postcommit(network_context)
expected_calls += [
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id),
mock.call.create_network(INTERNAL_TENANT_ID, net_dict),
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
def test_delete_network_precommit(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
segmentation_id = 1001
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
mechanism_arista.db_lib.is_network_provisioned.return_value = True
mechanism_arista.db_lib.num_nets_provisioned.return_value = 0
mechanism_arista.db_lib.num_vms_provisioned.return_value = 0
mechanism_arista.db_lib.are_ports_attached_to_network.return_value = (
False)
self.drv.delete_network_precommit(network_context)
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id),
mock.call.are_ports_attached_to_network(network_id),
mock.call.forget_network_segment(tenant_id, network_id),
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
# If there is no tenant id associated with the network, then the
# network should be created under the tenant id in the context.
tenant_id = 'ten-2'
network_id = 'net2-id'
segmentation_id = 1002
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
network_context.current['tenant_id'] = ''
mechanism_arista.db_lib.is_network_provisioned.return_value = True
mechanism_arista.db_lib.num_nets_provisioned.return_value = 0
mechanism_arista.db_lib.num_vms_provisioned.return_value = 0
mechanism_arista.db_lib.are_ports_attached_to_network.return_value = (
False)
self.drv.delete_network_precommit(network_context)
expected_calls += [
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id),
mock.call.are_ports_attached_to_network(network_id),
mock.call.forget_network_segment(INTERNAL_TENANT_ID, network_id),
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
def test_delete_network_precommit_with_ports(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
segmentation_id = 1001
network_context = utils.get_network_context(tenant_id,
network_id,
segmentation_id,
False)
mechanism_arista.db_lib.is_network_provisioned.return_value = True
mechanism_arista.db_lib.num_nets_provisioned.return_value = 0
mechanism_arista.db_lib.num_vms_provisioned.return_value = 0
mechanism_arista.db_lib.are_ports_attached_to_network.return_value = (
True)
try:
self.drv.delete_network_precommit(network_context)
except Exception:
# exception is expeted in this case - as network is not
# deleted in this case and exception is raised
pass
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id),
mock.call.are_ports_attached_to_network(network_id),
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
def test_delete_network_postcommit(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
@ -235,14 +108,12 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
segmentation_id,
False)
mechanism_arista.db_lib.num_nets_provisioned.return_value = 0
mechanism_arista.db_lib.num_vms_provisioned.return_value = 0
mechanism_arista.db_lib.tenant_provisioned.return_value = False
self.drv.delete_network_postcommit(network_context)
expected_calls = [
mock.call.delete_network(tenant_id, network_id,
network_context.network_segments),
mock.call.num_nets_provisioned(tenant_id),
mock.call.num_vms_provisioned(tenant_id),
mock.call.tenant_provisioned(tenant_id),
mock.call.delete_tenant(tenant_id),
]
@ -264,8 +135,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
expected_calls += [
mock.call.delete_network(INTERNAL_TENANT_ID, network_id,
network_context.network_segments),
mock.call.num_nets_provisioned(INTERNAL_TENANT_ID),
mock.call.num_vms_provisioned(INTERNAL_TENANT_ID),
mock.call.tenant_provisioned(INTERNAL_TENANT_ID),
mock.call.delete_tenant(INTERNAL_TENANT_ID),
]
@ -286,7 +156,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_id,
vm_id,
network_context)
mechanism_arista.db_lib.is_network_provisioned.return_value = True
network = {'tenant_id': tenant_id}
self.drv.ndb.get_network_from_net_id.return_value = [network]
@ -296,7 +165,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
self.drv.create_port_precommit(port_context)
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id, None),
mock.call.remember_vm(vm_id, host_id, port_id,
network_id, tenant_id)
]
@ -319,7 +187,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
vm_id,
network_context)
port_context.current['tenant_id'] = ''
mechanism_arista.db_lib.is_network_provisioned.return_value = True
network = {'tenant_id': ''}
self.drv.ndb.get_network_from_net_id.return_value = [network]
@ -329,8 +196,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
self.drv.create_port_precommit(port_context)
expected_calls += [
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id,
None),
mock.call.remember_vm(vm_id, host_id, port_id,
network_id, INTERNAL_TENANT_ID)
]
@ -351,8 +216,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
vm_id,
network_context)
mechanism_arista.db_lib.is_port_provisioned.return_value = True
mechanism_arista.db_lib.is_network_provisioned.return_value = True
mechanism_arista.db_lib.get_shared_network_owner_id.return_value = 1
network = {'tenant_id': tenant_id}
self.drv.ndb.get_network_from_net_id.return_value = [network]
@ -370,7 +233,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
expected_calls = [
mock.call.NeutronNets(),
mock.call.is_port_provisioned(port_id),
mock.call.is_network_provisioned(tenant_id, network_id, None),
mock.call.plug_port_into_network(device_id, host_id, port_id,
network_id, tenant_id,
port_name, device_owner, None,
@ -396,8 +258,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_context)
port_context.current['tenant_id'] = ''
mechanism_arista.db_lib.is_port_provisioned.return_value = True
mechanism_arista.db_lib.is_network_provisioned.return_value = True
mechanism_arista.db_lib.get_shared_network_owner_id.return_value = 1
network = {'tenant_id': ''}
self.drv.ndb.get_network_from_net_id.return_value = [network]
@ -413,8 +273,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
expected_calls += [
mock.call.is_port_provisioned(port_id),
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id,
None),
mock.call.plug_port_into_network(device_id, host_id, port_id,
network_id, INTERNAL_TENANT_ID,
port_name, device_owner, None,
@ -423,7 +281,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mechanism_arista.db_lib.assert_has_calls(expected_calls)
# Now test the delete ports
# Now test the delete ports
def test_delete_port_precommit(self):
tenant_id = 'ten-1'
network_id = 'net1-id'
@ -440,8 +298,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
vm_id,
network_context)
mechanism_arista.db_lib.is_port_provisioned.return_value = True
mechanism_arista.db_lib.num_nets_provisioned.return_value = 0
mechanism_arista.db_lib.num_vms_provisioned.return_value = 0
self.drv.delete_port_precommit(port_context)
port_id = port_context.current['id']
@ -469,8 +325,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
network_context