plugin/nec: Make sure resources on OFC is globally unique.

Fixes bug 1127664

Network cannot be created in NEC plugin when OFC network ID is
unique inside a tenant. Some OFC implmenetations generate a network
ID unique inside a tenant. In this case generated network IDs on can
be duplicated in system-wide. To fix it, this changes resource ID on
OFC to REST URI to make sure IDs on OFC globally unique.

Fixes bug 1120962

Make sure NEC plugin creates shared networks

In Quantum resource relationship is not limited inside a tenant.
E.g., a non-owner tenant can create a port on a shared network.
To deal with it the provider layer should not be aware of tenants
each resource belongs to even when it has a kind of tenant concept.

This commit changes ofc_manager to pass a parent resource for resource
creation and identify a resouce by REST URI used to access OFC resources.
It decouples Quantum resource access model from OFC resource models.
OFC IDs created before this commit are also looked up.

Primary keys of OFC ID mapping tables are changed to quantum_id because
most of all accesses to these mapping tables are done by quantum_id.
However the current version of alembic does not support changing primary
keys, so new OFC ID mapping tables for tenant, network, port and packet
filter are created. Dropping the previous mapping tables will be done
along with the data migration logic.

This commit also changes the following minor issues.
- Make sure ID on ProgrammableFlow OpenFlow controller (PFC) is less than
  32 chars. The current PFC accepts only 31 chars max as ID and 127 chars
  as a description string.
- Some database accesses created their own session and did not support
  subtransactions. Make sure to use context.session passed from the API layer.
- Removes Unused methods (update_network, update_port) in trema/pfc drivers.

Change-Id: Ib4bb830e5f537c789974fa7b77f06eaeacb65333
This commit is contained in:
Akihiro MOTOKI 2013-01-31 13:51:28 +09:00
parent 4298be01bf
commit 7a7675c748
15 changed files with 1397 additions and 467 deletions

View File

@ -0,0 +1,84 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 OpenStack LLC
#
# 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.
#
"""NEC plugin sharednet
Revision ID: 3b54bf9e29f7
Revises: 54c2c487e913
Create Date: 2013-02-17 09:21:48.287134
"""
# revision identifiers, used by Alembic.
revision = '3b54bf9e29f7'
down_revision = '54c2c487e913'
# Change to ['*'] if this migration applies to all plugins
migration_for_plugins = [
'quantum.plugins.nec.nec_plugin.NECPluginV2'
]
from alembic import op
import sqlalchemy as sa
from quantum.db import migration
def upgrade(active_plugin=None, options=None):
if not migration.should_run(active_plugin, migration_for_plugins):
return
op.create_table(
'ofctenantmappings',
sa.Column('ofc_id', sa.String(length=255), nullable=False),
sa.Column('quantum_id', sa.String(length=36), nullable=False),
sa.PrimaryKeyConstraint('quantum_id'),
sa.UniqueConstraint('ofc_id')
)
op.create_table(
'ofcnetworkmappings',
sa.Column('ofc_id', sa.String(length=255), nullable=False),
sa.Column('quantum_id', sa.String(length=36), nullable=False),
sa.PrimaryKeyConstraint('quantum_id'),
sa.UniqueConstraint('ofc_id')
)
op.create_table(
'ofcportmappings',
sa.Column('ofc_id', sa.String(length=255), nullable=False),
sa.Column('quantum_id', sa.String(length=36), nullable=False),
sa.PrimaryKeyConstraint('quantum_id'),
sa.UniqueConstraint('ofc_id')
)
op.create_table(
'ofcfiltermappings',
sa.Column('ofc_id', sa.String(length=255), nullable=False),
sa.Column('quantum_id', sa.String(length=36), nullable=False),
sa.PrimaryKeyConstraint('quantum_id'),
sa.UniqueConstraint('ofc_id')
)
def downgrade(active_plugin=None, options=None):
if not migration.should_run(active_plugin, migration_for_plugins):
return
op.drop_table('ofcfiltermappings')
op.drop_table('ofcportmappings')
op.drop_table('ofcnetworkmappings')
op.drop_table('ofctenantmappings')

View File

@ -54,9 +54,10 @@ class OFCClient(object):
return httplib.HTTPConnection return httplib.HTTPConnection
def do_request(self, method, action, body=None): def do_request(self, method, action, body=None):
LOG.debug(_("Client request: %(method)s %(action)s [%(body)s]"), LOG.debug(_("Client request: %(host)s:%(port)s "
locals()) "%(method)s %(action)s [%(body)s]"),
{'host': self.host, 'port': self.port,
'method': method, 'action': action, 'body': body})
if type(body) is dict: if type(body) is dict:
body = json.dumps(body) body = json.dumps(body)
try: try:

View File

@ -34,6 +34,26 @@ LOG = logging.getLogger(__name__)
OFP_VLAN_NONE = 0xffff OFP_VLAN_NONE = 0xffff
resource_map = {'ofc_tenant': nmodels.OFCTenantMapping,
'ofc_network': nmodels.OFCNetworkMapping,
'ofc_port': nmodels.OFCPortMapping,
'ofc_packet_filter': nmodels.OFCFilterMapping}
old_resource_map = {'ofc_tenant': nmodels.OFCTenant,
'ofc_network': nmodels.OFCNetwork,
'ofc_port': nmodels.OFCPort,
'ofc_packet_filter': nmodels.OFCFilter}
# utitlity methods
def _get_resource_model(resource, old_style):
if old_style:
return old_resource_map[resource]
else:
return resource_map[resource]
def initialize(): def initialize():
db.configure_db() db.configure_db()
@ -42,30 +62,52 @@ def clear_db(base=model_base.BASEV2):
db.clear_db(base) db.clear_db(base)
def get_ofc_item(model, id): def get_ofc_item(session, resource, quantum_id, old_style=False):
session = db.get_session()
try: try:
return (session.query(model). model = _get_resource_model(resource, old_style)
filter_by(id=id). return session.query(model).filter_by(quantum_id=quantum_id).one()
one())
except sa.orm.exc.NoResultFound: except sa.orm.exc.NoResultFound:
return None return None
def find_ofc_item(model, quantum_id): def get_ofc_id(session, resource, quantum_id, old_style=False):
session = db.get_session() ofc_item = get_ofc_item(session, resource, quantum_id, old_style)
if ofc_item:
if old_style:
return ofc_item.id
else:
return ofc_item.ofc_id
else:
return None
def exists_ofc_item(session, resource, quantum_id, old_style=False):
if get_ofc_item(session, resource, quantum_id, old_style):
return True
else:
return False
def find_ofc_item(session, resource, ofc_id, old_style=False):
try: try:
return (session.query(model). model = _get_resource_model(resource, old_style)
filter_by(quantum_id=quantum_id). if old_style:
one()) params = dict(id=ofc_id)
else:
params = dict(ofc_id=ofc_id)
return (session.query(model).filter_by(**params).one())
except sa.orm.exc.NoResultFound: except sa.orm.exc.NoResultFound:
return None return None
def add_ofc_item(model, id, quantum_id): def add_ofc_item(session, resource, quantum_id, ofc_id, old_style=False):
session = db.get_session()
try: try:
item = model(id=id, quantum_id=quantum_id) model = _get_resource_model(resource, old_style)
if old_style:
params = dict(quantum_id=quantum_id, id=ofc_id)
else:
params = dict(quantum_id=quantum_id, ofc_id=ofc_id)
item = model(**params)
session.add(item) session.add(item)
session.flush() session.flush()
except Exception as exc: except Exception as exc:
@ -74,21 +116,61 @@ def add_ofc_item(model, id, quantum_id):
return item return item
def del_ofc_item(model, id): def del_ofc_item(session, resource, quantum_id, old_style=False,
session = db.get_session() warning=True):
try: try:
item = (session.query(model). model = _get_resource_model(resource, old_style)
filter_by(id=id). item = session.query(model).filter_by(quantum_id=quantum_id).one()
one())
session.delete(item) session.delete(item)
session.flush() session.flush()
return True
except sa.orm.exc.NoResultFound: except sa.orm.exc.NoResultFound:
if warning:
LOG.warning(_("_del_ofc_item(): NotFound item " LOG.warning(_("_del_ofc_item(): NotFound item "
"(model=%(model)s, id=%(id)s) "), locals()) "(model=%(model)s, id=%(id)s) "),
{'model': model, 'id': quantum_id})
return False
def get_portinfo(id): def get_ofc_id_lookup_both(session, resource, quantum_id):
session = db.get_session() ofc_id = get_ofc_id(session, resource, quantum_id)
# Lookup old style of OFC mapping table
if not ofc_id:
ofc_id = get_ofc_id(session, resource, quantum_id,
old_style=True)
if not ofc_id:
reason = (_("NotFound %(resource)s for quantum_id=%(id)s.")
% {'resource': resource, 'id': quantum_id})
raise nexc.OFCConsistencyBroken(reason=reason)
return ofc_id
def exists_ofc_item_lookup_both(session, resource, quantum_id):
if exists_ofc_item(session, resource, quantum_id):
return True
# Check old style of OFC mapping table
if exists_ofc_item(session, resource, quantum_id,
old_style=True):
return True
return False
def del_ofc_item_lookup_both(session, resource, quantum_id):
# Delete the mapping from new style of OFC mapping table
if del_ofc_item(session, resource, quantum_id,
old_style=False, warning=False):
return
# Delete old style of OFC mapping table
if del_ofc_item(session, resource, quantum_id,
old_style=True, warning=False):
return
# The specified resource not found
LOG.warning(_("_del_ofc_item(): NotFound item "
"(resource=%(resource)s, id=%(id)s) "),
{'resource': resource, 'id': quantum_id})
def get_portinfo(session, id):
try: try:
return (session.query(nmodels.PortInfo). return (session.query(nmodels.PortInfo).
filter_by(id=id). filter_by(id=id).
@ -97,8 +179,8 @@ def get_portinfo(id):
return None return None
def add_portinfo(id, datapath_id='', port_no=0, vlan_id=OFP_VLAN_NONE, mac=''): def add_portinfo(session, id, datapath_id='', port_no=0,
session = db.get_session() vlan_id=OFP_VLAN_NONE, mac=''):
try: try:
portinfo = nmodels.PortInfo(id=id, datapath_id=datapath_id, portinfo = nmodels.PortInfo(id=id, datapath_id=datapath_id,
port_no=port_no, vlan_id=vlan_id, mac=mac) port_no=port_no, vlan_id=vlan_id, mac=mac)
@ -110,12 +192,9 @@ def add_portinfo(id, datapath_id='', port_no=0, vlan_id=OFP_VLAN_NONE, mac=''):
return portinfo return portinfo
def del_portinfo(id): def del_portinfo(session, id):
session = db.get_session()
try: try:
portinfo = (session.query(nmodels.PortInfo). portinfo = session.query(nmodels.PortInfo).filter_by(id=id).one()
filter_by(id=id).
one())
session.delete(portinfo) session.delete(portinfo)
session.flush() session.flush()
except sa.orm.exc.NoResultFound: except sa.orm.exc.NoResultFound:

View File

@ -21,6 +21,38 @@ from quantum.db import model_base
from quantum.db import models_v2 from quantum.db import models_v2
"""New mapping tables"""
class OFCId(object):
"""Resource ID on OpenFlow Controller"""
ofc_id = sa.Column(sa.String(255), unique=True, nullable=False)
class QuantumId(object):
"""Logical ID on Quantum"""
quantum_id = sa.Column(sa.String(36), primary_key=True)
class OFCTenantMapping(model_base.BASEV2, QuantumId, OFCId):
"""Represents a Tenant on OpenFlow Network/Controller."""
class OFCNetworkMapping(model_base.BASEV2, QuantumId, OFCId):
"""Represents a Network on OpenFlow Network/Controller."""
class OFCPortMapping(model_base.BASEV2, QuantumId, OFCId):
"""Represents a Port on OpenFlow Network/Controller."""
class OFCFilterMapping(model_base.BASEV2, QuantumId, OFCId):
"""Represents a Filter on OpenFlow Network/Controller."""
"""Old mapping tables"""
class HasQuantumId(object): class HasQuantumId(object):
"""Logical ID on Quantum""" """Logical ID on Quantum"""
quantum_id = sa.Column(sa.String(36), nullable=False) quantum_id = sa.Column(sa.String(36), nullable=False)

View File

@ -26,7 +26,9 @@ DRIVER_LIST = {
'trema_port': DRIVER_PATH % "trema.TremaPortBaseDriver", 'trema_port': DRIVER_PATH % "trema.TremaPortBaseDriver",
'trema_portmac': DRIVER_PATH % "trema.TremaPortMACBaseDriver", 'trema_portmac': DRIVER_PATH % "trema.TremaPortMACBaseDriver",
'trema_mac': DRIVER_PATH % "trema.TremaMACBaseDriver", 'trema_mac': DRIVER_PATH % "trema.TremaMACBaseDriver",
'pfc': DRIVER_PATH % "pfc.PFCDriver"} 'pfc': DRIVER_PATH % "pfc.PFCV4Driver",
'pfc_v3': DRIVER_PATH % "pfc.PFCV3Driver",
'pfc_v4': DRIVER_PATH % "pfc.PFCV4Driver"}
def get_driver(driver_name): def get_driver(driver_name):

View File

@ -14,20 +14,24 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
# @author: Akihiro MOTOKI
import re
import uuid
from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.common import ofc_client from quantum.plugins.nec.common import ofc_client
from quantum.plugins.nec import ofc_driver_base from quantum.plugins.nec import ofc_driver_base
TENANTS_PATH = "/tenants" class PFCDriverBase(ofc_driver_base.OFCDriverBase):
TENANT_PATH = "/tenants/%s" """Base Class for PDC Drivers
NETWORKS_PATH = "/tenants/%s/networks"
NETWORK_PATH = "/tenants/%s/networks/%s"
PORTS_PATH = "/tenants/%s/networks/%s/ports"
PORT_PATH = "/tenants/%s/networks/%s/ports/%s"
PFCDriverBase provides methods to handle PFC resources through REST API.
This uses ofc resource path instead of ofc resource ID.
class PFCDriver(ofc_driver_base.OFCDriverBase): The class implements the API for PFC V4.0 or later.
"""
def __init__(self, conf_ofc): def __init__(self, conf_ofc):
self.client = ofc_client.OFCClient(host=conf_ofc.host, self.client = ofc_client.OFCClient(host=conf_ofc.host,
@ -40,62 +44,107 @@ class PFCDriver(ofc_driver_base.OFCDriverBase):
def filter_supported(cls): def filter_supported(cls):
return False return False
def create_tenant(self, description, tenant_id=None): def _generate_pfc_str(self, raw_str):
body = {'description': description} """Generate PFC acceptable String"""
if tenant_id: return re.sub(r'[^0-9a-zA-Z]', '_', raw_str)
body.update({'id': tenant_id})
res = self.client.post(TENANTS_PATH, body=body)
ofc_tenant_id = res['id']
return ofc_tenant_id
def update_tenant(self, ofc_tenant_id, description): def _generate_pfc_id(self, id_str):
path = TENANT_PATH % ofc_tenant_id """Generate ID on PFC
body = {'description': description}
res = self.client.put(path, body=body) Currently, PFC ID must be less than 32.
Shorten UUID string length from 36 to 31 by follows:
* delete UUID Version and hyphen (see RFC4122)
* ensure str length
"""
try:
# openstack.common.uuidutils.is_uuid_like() returns
# False for KeyStone tenant_id, so uuid.UUID is used
# directly here to accept tenant_id as UUID string
uuid_str = str(uuid.UUID(id_str)).replace('-', '')
uuid_no_version = uuid_str[:12] + uuid_str[13:]
return uuid_no_version[:31]
except:
return self._generate_pfc_str(id_str)[:31]
def _generate_pfc_description(self, desc):
"""Generate Description on PFC
Currently, PFC Description must be less than 128.
"""
return self._generate_pfc_str(desc)[:127]
def create_tenant(self, description, tenant_id=None):
ofc_tenant_id = self._generate_pfc_id(tenant_id)
body = {'id': ofc_tenant_id}
res = self.client.post('/tenants', body=body)
return '/tenants/' + ofc_tenant_id
def delete_tenant(self, ofc_tenant_id): def delete_tenant(self, ofc_tenant_id):
path = TENANT_PATH % ofc_tenant_id return self.client.delete(ofc_tenant_id)
return self.client.delete(path)
def create_network(self, ofc_tenant_id, description, network_id=None): def create_network(self, ofc_tenant_id, description, network_id=None):
path = NETWORKS_PATH % ofc_tenant_id path = "%s/networks" % ofc_tenant_id
body = {'description': description} pfc_desc = self._generate_pfc_description(description)
if network_id: body = {'description': pfc_desc}
body.update({'id': network_id})
res = self.client.post(path, body=body) res = self.client.post(path, body=body)
ofc_network_id = res['id'] ofc_network_id = res['id']
return ofc_network_id return path + '/' + ofc_network_id
def update_network(self, ofc_tenant_id, ofc_network_id, description): def delete_network(self, ofc_network_id):
path = NETWORK_PATH % (ofc_tenant_id, ofc_network_id) return self.client.delete(ofc_network_id)
body = {'description': description}
return self.client.put(path, body=body)
def delete_network(self, ofc_tenant_id, ofc_network_id): def create_port(self, ofc_network_id, portinfo,
path = NETWORK_PATH % (ofc_tenant_id, ofc_network_id)
return self.client.delete(path)
def create_port(self, ofc_tenant_id, ofc_network_id, portinfo,
port_id=None): port_id=None):
path = PORTS_PATH % (ofc_tenant_id, ofc_network_id) path = "%s/ports" % ofc_network_id
body = {'datapath_id': portinfo.datapath_id, body = {'datapath_id': portinfo.datapath_id,
'port': str(portinfo.port_no), 'port': str(portinfo.port_no),
'vid': str(portinfo.vlan_id)} 'vid': str(portinfo.vlan_id)}
if port_id:
body.update({'id': port_id})
res = self.client.post(path, body=body) res = self.client.post(path, body=body)
ofc_port_id = res['id'] ofc_port_id = res['id']
return path + '/' + ofc_port_id
def delete_port(self, ofc_port_id):
return self.client.delete(ofc_port_id)
def convert_ofc_tenant_id(self, context, ofc_tenant_id):
# If ofc_tenant_id starts with '/', it is already new-style
if ofc_tenant_id[0] == '/':
return ofc_tenant_id
return '/tenants/%s' % ofc_tenant_id
def convert_ofc_network_id(self, context, ofc_network_id, tenant_id):
# If ofc_network_id starts with '/', it is already new-style
if ofc_network_id[0] == '/':
return ofc_network_id
ofc_tenant_id = ndb.get_ofc_id_lookup_both(
context.session, 'ofc_tenant', tenant_id)
ofc_tenant_id = self.convert_ofc_tenant_id(context, ofc_tenant_id)
params = dict(tenant=ofc_tenant_id, network=ofc_network_id)
return '%(tenant)s/networks/%(network)s' % params
def convert_ofc_port_id(self, context, ofc_port_id, tenant_id, network_id):
# If ofc_port_id starts with '/', it is already new-style
if ofc_port_id[0] == '/':
return ofc_port_id return ofc_port_id
def update_port(self, ofc_tenant_id, ofc_network_id, portinfo, port_id): ofc_network_id = ndb.get_ofc_id_lookup_both(
path = PORT_PATH % (ofc_tenant_id, ofc_network_id, ofc_port_id) context.session, 'ofc_network', network_id)
body = {'datapath_id': portinfo.datapath_id, ofc_network_id = self.convert_ofc_network_id(
'port': str(portinfo.port_no), context, ofc_network_id, tenant_id)
'vid': str(portinfo.vlan_id)} params = dict(network=ofc_network_id, port=ofc_port_id)
res = self.client.put(path, body=body) return '%(network)s/ports/%(port)s' % params
ofc_port_id = res['id']
return ofc_port_id
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id):
path = PORT_PATH % (ofc_tenant_id, ofc_network_id, ofc_port_id) class PFCV3Driver(PFCDriverBase):
return self.client.delete(path)
def create_tenant(self, description, tenant_id):
ofc_tenant_id = self._generate_pfc_id(tenant_id)
return "/tenants/" + ofc_tenant_id
def delete_tenant(self, ofc_tenant_id):
pass
class PFCV4Driver(PFCDriverBase):
pass

View File

@ -14,8 +14,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
# @author: Akihiro MOTOKI
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.common import ofc_client from quantum.plugins.nec.common import ofc_client
from quantum.plugins.nec import ofc_driver_base from quantum.plugins.nec import ofc_driver_base
@ -30,8 +32,17 @@ class TremaDriverBase(ofc_driver_base.OFCDriverBase):
self.client = ofc_client.OFCClient(host=conf_ofc.host, self.client = ofc_client.OFCClient(host=conf_ofc.host,
port=conf_ofc.port) port=conf_ofc.port)
def _get_network_id(self, ofc_network_id):
# ofc_network_id : /networks/<network-id>
return ofc_network_id.split('/')[2]
def _get_tenant_id(self, tenant_id):
# Trema does not use tenant_id, but it returns
# /tenants/<tenant_id> format to keep consistency with PFC driver.
return '/tenants/' + tenant_id
def create_tenant(self, description, tenant_id=None): def create_tenant(self, description, tenant_id=None):
return tenant_id or uuidutils.generate_uuid() return self._get_tenant_id(tenant_id or uuidutils.generate_uuid())
def update_tenant(self, ofc_tenant_id, description): def update_tenant(self, ofc_tenant_id, description):
pass pass
@ -43,25 +54,28 @@ class TremaDriverBase(ofc_driver_base.OFCDriverBase):
ofc_network_id = network_id or uuidutils.generate_uuid() ofc_network_id = network_id or uuidutils.generate_uuid()
body = {'id': ofc_network_id, 'description': description} body = {'id': ofc_network_id, 'description': description}
self.client.post(self.networks_path, body=body) self.client.post(self.networks_path, body=body)
return self.network_path % ofc_network_id
def delete_network(self, ofc_network_id):
return self.client.delete(ofc_network_id)
def convert_ofc_tenant_id(self, context, ofc_tenant_id):
# If ofc_network_id starts with '/', it is already new-style
if ofc_tenant_id[0] == '/':
return ofc_tenant_id
return self._get_tenant_id(ofc_tenant_id)
def convert_ofc_network_id(self, context, ofc_network_id, tenant_id):
# If ofc_network_id starts with '/', it is already new-style
if ofc_network_id[0] == '/':
return ofc_network_id return ofc_network_id
# Trema sliceable switch does not use tenant_id,
def update_network(self, ofc_tenant_id, ofc_network_id, description): # so we can convert ofc_network_id from old id only
path = self.network_path % ofc_network_id return self.network_path % ofc_network_id
body = {'description': description}
return self.client.put(path, body=body)
def delete_network(self, ofc_tenant_id, ofc_network_id):
path = self.network_path % ofc_network_id
return self.client.delete(path)
def update_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id,
portinfo):
self.delete_port(ofc_tenant_id, ofc_network_id, ofc_port_id)
self.create_port(ofc_tenant_id, ofc_network_id, portinfo, ofc_port_id)
class TremaFilterDriver(object): class TremaFilterDriver(object):
"""Trema (Sliceable Switch) PacketFilter Driver""" """Trema (Sliceable Switch) PacketFilter Driver Mixin"""
filters_path = "/filters" filters_path = "/filters"
filter_path = "/filters/%s" filter_path = "/filters/%s"
@ -69,7 +83,7 @@ class TremaFilterDriver(object):
def filter_supported(cls): def filter_supported(cls):
return True return True
def create_filter(self, ofc_tenant_id, ofc_network_id, filter_dict, def create_filter(self, ofc_network_id, filter_dict,
portinfo=None, filter_id=None): portinfo=None, filter_id=None):
if filter_dict['action'].upper() in ["ACCEPT", "ALLOW"]: if filter_dict['action'].upper() in ["ACCEPT", "ALLOW"]:
ofc_action = "ALLOW" ofc_action = "ALLOW"
@ -77,7 +91,7 @@ class TremaFilterDriver(object):
ofc_action = "DENY" ofc_action = "DENY"
body = {'priority': filter_dict['priority'], body = {'priority': filter_dict['priority'],
'slice': ofc_network_id, 'slice': self._get_network_id(ofc_network_id),
'action': ofc_action} 'action': ofc_action}
ofp_wildcards = ["dl_vlan", "dl_vlan_pcp", "nw_tos"] ofp_wildcards = ["dl_vlan", "dl_vlan_pcp", "nw_tos"]
@ -147,11 +161,16 @@ class TremaFilterDriver(object):
body['ofp_wildcards'] = ','.join(ofp_wildcards) body['ofp_wildcards'] = ','.join(ofp_wildcards)
self.client.post(self.filters_path, body=body) self.client.post(self.filters_path, body=body)
return ofc_filter_id return self.filter_path % ofc_filter_id
def delete_filter(self, ofc_tenant_id, ofc_network_id, ofc_filter_id): def delete_filter(self, ofc_filter_id):
path = self.filter_path % ofc_filter_id return self.client.delete(ofc_filter_id)
return self.client.delete(path)
def convert_ofc_filter_id(self, context, ofc_filter_id):
# If ofc_filter_id starts with '/', it is already new-style
if ofc_filter_id[0] == '/':
return ofc_filter_id
return self.filter_path % ofc_filter_id
class TremaPortBaseDriver(TremaDriverBase, TremaFilterDriver): class TremaPortBaseDriver(TremaDriverBase, TremaFilterDriver):
@ -160,23 +179,36 @@ class TremaPortBaseDriver(TremaDriverBase, TremaFilterDriver):
TremaPortBaseDriver uses port base binding. TremaPortBaseDriver uses port base binding.
Ports are identified by datapath_id, port_no and vlan_id. Ports are identified by datapath_id, port_no and vlan_id.
""" """
ports_path = "/networks/%s/ports" ports_path = "%(network)s/ports"
port_path = "/networks/%s/ports/%s" port_path = "%(network)s/ports/%(port)s"
def create_port(self, ofc_tenant_id, ofc_network_id, portinfo, def create_port(self, ofc_network_id, portinfo,
port_id=None): port_id=None):
ofc_port_id = port_id or uuidutils.generate_uuid() ofc_port_id = port_id or uuidutils.generate_uuid()
path = self.ports_path % ofc_network_id path = self.ports_path % {'network': ofc_network_id}
body = {'id': ofc_port_id, body = {'id': ofc_port_id,
'datapath_id': portinfo.datapath_id, 'datapath_id': portinfo.datapath_id,
'port': str(portinfo.port_no), 'port': str(portinfo.port_no),
'vid': str(portinfo.vlan_id)} 'vid': str(portinfo.vlan_id)}
self.client.post(path, body=body) self.client.post(path, body=body)
return self.port_path % {'network': ofc_network_id,
'port': ofc_port_id}
def delete_port(self, ofc_port_id):
return self.client.delete(ofc_port_id)
def convert_ofc_port_id(self, context, ofc_port_id,
tenant_id, network_id):
# If ofc_port_id starts with '/', it is already new-style
if ofc_port_id[0] == '/':
return ofc_port_id return ofc_port_id
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id): ofc_network_id = ndb.get_ofc_id_lookup_both(
path = self.port_path % (ofc_network_id, ofc_port_id) context.session, 'ofc_network', network_id)
return self.client.delete(path) ofc_network_id = self.convert_ofc_network_id(
context, ofc_network_id, tenant_id)
return self.port_path % {'network': ofc_network_id,
'port': ofc_port_id}
class TremaPortMACBaseDriver(TremaDriverBase, TremaFilterDriver): class TremaPortMACBaseDriver(TremaDriverBase, TremaFilterDriver):
@ -185,40 +217,54 @@ class TremaPortMACBaseDriver(TremaDriverBase, TremaFilterDriver):
TremaPortBaseDriver uses port-mac base binding. TremaPortBaseDriver uses port-mac base binding.
Ports are identified by datapath_id, port_no, vlan_id and mac. Ports are identified by datapath_id, port_no, vlan_id and mac.
""" """
ports_path = "/networks/%s/ports" ports_path = "%(network)s/ports"
port_path = "/networks/%s/ports/%s" port_path = "%(network)s/ports/%(port)s"
attachments_path = "/networks/%s/ports/%s/attachments" attachments_path = "%(network)s/ports/%(port)s/attachments"
attachment_path = "/networks/%s/ports/%s/attachments/%s" attachment_path = "%(network)s/ports/%(port)s/attachments/%(attachment)s"
def create_port(self, ofc_tenant_id, ofc_network_id, portinfo, def create_port(self, ofc_network_id, portinfo, port_id=None):
port_id=None):
#NOTE: This Driver create slices with Port-MAC Based bindings on Trema #NOTE: This Driver create slices with Port-MAC Based bindings on Trema
# Sliceable. It's REST API requires Port Based binding before you # Sliceable. It's REST API requires Port Based binding before you
# define Port-MAC Based binding. # define Port-MAC Based binding.
ofc_port_id = port_id or uuidutils.generate_uuid() ofc_port_id = port_id or uuidutils.generate_uuid()
dummy_port_id = "dummy-%s" % ofc_port_id dummy_port_id = "dummy-%s" % ofc_port_id
path = self.ports_path % ofc_network_id path = self.ports_path % {'network': ofc_network_id}
body = {'id': dummy_port_id, body = {'id': dummy_port_id,
'datapath_id': portinfo.datapath_id, 'datapath_id': portinfo.datapath_id,
'port': str(portinfo.port_no), 'port': str(portinfo.port_no),
'vid': str(portinfo.vlan_id)} 'vid': str(portinfo.vlan_id)}
self.client.post(path, body=body) self.client.post(path, body=body)
path = self.attachments_path % (ofc_network_id, dummy_port_id) path = self.attachments_path % {'network': ofc_network_id,
'port': dummy_port_id}
body = {'id': ofc_port_id, 'mac': portinfo.mac} body = {'id': ofc_port_id, 'mac': portinfo.mac}
self.client.post(path, body=body) self.client.post(path, body=body)
path = self.port_path % (ofc_network_id, dummy_port_id) path = self.port_path % {'network': ofc_network_id,
'port': dummy_port_id}
self.client.delete(path) self.client.delete(path)
return self.attachment_path % {'network': ofc_network_id,
'port': dummy_port_id,
'attachment': ofc_port_id}
def delete_port(self, ofc_port_id):
return self.client.delete(ofc_port_id)
def convert_ofc_port_id(self, context, ofc_port_id, tenant_id, network_id):
# If ofc_port_id starts with '/', it is already new-style
if ofc_port_id[0] == '/':
return ofc_port_id return ofc_port_id
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id): ofc_network_id = ndb.get_ofc_id_lookup_both(
dummy_port_id = "dummy-%s" % ofc_port_id context.session, 'ofc_network', network_id)
path = self.attachment_path % (ofc_network_id, dummy_port_id, ofc_network_id = self.convert_ofc_network_id(
ofc_port_id) context, ofc_network_id, tenant_id)
return self.client.delete(path) dummy_port_id = 'dummy-%s' % ofc_port_id
return self.attachment_path % {'network': ofc_network_id,
'port': dummy_port_id,
'attachment': ofc_port_id}
class TremaMACBaseDriver(TremaDriverBase): class TremaMACBaseDriver(TremaDriverBase):
@ -227,21 +273,32 @@ class TremaMACBaseDriver(TremaDriverBase):
TremaPortBaseDriver uses mac base binding. TremaPortBaseDriver uses mac base binding.
Ports are identified by mac. Ports are identified by mac.
""" """
attachments_path = "/networks/%s/attachments" attachments_path = "%(network)s/attachments"
attachment_path = "/networks/%s/attachments/%s" attachment_path = "%(network)s/attachments/%(attachment)s"
@classmethod @classmethod
def filter_supported(cls): def filter_supported(cls):
return False return False
def create_port(self, ofc_tenant_id, ofc_network_id, portinfo, def create_port(self, ofc_network_id, portinfo, port_id=None):
port_id=None):
ofc_port_id = port_id or uuidutils.generate_uuid() ofc_port_id = port_id or uuidutils.generate_uuid()
path = self.attachments_path % ofc_network_id path = self.attachments_path % {'network': ofc_network_id}
body = {'id': ofc_port_id, 'mac': portinfo.mac} body = {'id': ofc_port_id, 'mac': portinfo.mac}
self.client.post(path, body=body) self.client.post(path, body=body)
return self.attachment_path % {'network': ofc_network_id,
'attachment': ofc_port_id}
def delete_port(self, ofc_port_id):
return self.client.delete(ofc_port_id)
def convert_ofc_port_id(self, context, ofc_port_id, tenant_id, network_id):
# If ofc_port_id starts with '/', it is already new-style
if ofc_port_id[0] == '/':
return ofc_port_id return ofc_port_id
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id): ofc_network_id = ndb.get_ofc_id_lookup_both(
path = self.attachment_path % (ofc_network_id, ofc_port_id) context.session, 'ofc_network', network_id)
return self.client.delete(path) ofc_network_id = self.convert_ofc_network_id(
context, ofc_network_id, tenant_id)
return self.attachment_path % {'network': ofc_network_id,
'attachment': ofc_port_id}

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
# @author: Akihiro MOTOKI
from quantum.agent import securitygroups_rpc as sg_rpc from quantum.agent import securitygroups_rpc as sg_rpc
from quantum.common import constants as q_const from quantum.common import constants as q_const
@ -141,7 +142,7 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
LOG.debug(_("activate_port_if_ready(): skip, " LOG.debug(_("activate_port_if_ready(): skip, "
"network.admin_state_up is False.")) "network.admin_state_up is False."))
port_status = OperationalStatus.DOWN port_status = OperationalStatus.DOWN
elif not ndb.get_portinfo(port['id']): elif not ndb.get_portinfo(context.session, port['id']):
LOG.debug(_("activate_port_if_ready(): skip, " LOG.debug(_("activate_port_if_ready(): skip, "
"no portinfo for this port.")) "no portinfo for this port."))
port_status = OperationalStatus.DOWN port_status = OperationalStatus.DOWN
@ -160,14 +161,12 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
in_port=port) in_port=port)
if port_status in [OperationalStatus.ACTIVE]: if port_status in [OperationalStatus.ACTIVE]:
if self.ofc.exists_ofc_port(port['id']): if self.ofc.exists_ofc_port(context, port['id']):
LOG.debug(_("activate_port_if_ready(): skip, " LOG.debug(_("activate_port_if_ready(): skip, "
"ofc_port already exists.")) "ofc_port already exists."))
else: else:
try: try:
self.ofc.create_ofc_port(port['tenant_id'], self.ofc.create_ofc_port(context, port['id'], port)
port['network_id'],
port['id'])
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("create_ofc_port() failed due to %s") % exc reason = _("create_ofc_port() failed due to %s") % exc
LOG.error(reason) LOG.error(reason)
@ -183,11 +182,9 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
Deactivate port and packet_filters associated with the port. Deactivate port and packet_filters associated with the port.
""" """
port_status = OperationalStatus.DOWN port_status = OperationalStatus.DOWN
if self.ofc.exists_ofc_port(port['id']): if self.ofc.exists_ofc_port(context, port['id']):
try: try:
self.ofc.delete_ofc_port(port['tenant_id'], self.ofc.delete_ofc_port(context, port['id'], port)
port['network_id'],
port['id'])
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("delete_ofc_port() failed due to %s") % exc reason = _("delete_ofc_port() failed due to %s") % exc
LOG.error(reason) LOG.error(reason)
@ -228,10 +225,10 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
OperationalStatus.BUILD) OperationalStatus.BUILD)
try: try:
if not self.ofc.exists_ofc_tenant(new_net['tenant_id']): if not self.ofc.exists_ofc_tenant(context, new_net['tenant_id']):
self.ofc.create_ofc_tenant(new_net['tenant_id']) self.ofc.create_ofc_tenant(context, new_net['tenant_id'])
self.ofc.create_ofc_network(new_net['tenant_id'], new_net['id'], self.ofc.create_ofc_network(context, new_net['tenant_id'],
new_net['name']) new_net['id'], new_net['name'])
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("create_network() failed due to %s") % exc reason = _("create_network() failed due to %s") % exc
LOG.error(reason) LOG.error(reason)
@ -250,7 +247,8 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
or deactivate ports and packetfilters associated with the network. or deactivate ports and packetfilters associated with the network.
""" """
LOG.debug(_("NECPluginV2.update_network() called, " LOG.debug(_("NECPluginV2.update_network() called, "
"id=%(id)s network=%(network)s ."), locals()) "id=%(id)s network=%(network)s ."),
{'id': id, 'network': network})
session = context.session session = context.session
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
old_net = super(NECPluginV2, self).get_network(context, id) old_net = super(NECPluginV2, self).get_network(context, id)
@ -311,7 +309,8 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
super(NECPluginV2, self).delete_network(context, id) super(NECPluginV2, self).delete_network(context, id)
try: try:
self.ofc.delete_ofc_network(tenant_id, id) # 'net' parameter is required to lookup old OFC mapping
self.ofc.delete_ofc_network(context, id, net)
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("delete_network() failed due to %s") % exc reason = _("delete_network() failed due to %s") % exc
# NOTE: The OFC configuration of this network could be remained # NOTE: The OFC configuration of this network could be remained
@ -329,7 +328,7 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
nets = super(NECPluginV2, self).get_networks(context, filters=filters) nets = super(NECPluginV2, self).get_networks(context, filters=filters)
if len(nets) == 0: if len(nets) == 0:
try: try:
self.ofc.delete_ofc_tenant(tenant_id) self.ofc.delete_ofc_tenant(context, tenant_id)
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("delete_ofc_tenant() failed due to %s") % exc reason = _("delete_ofc_tenant() failed due to %s") % exc
LOG.warn(reason) LOG.warn(reason)
@ -384,7 +383,8 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
or deactivate the port and packetfilters associated with it. or deactivate the port and packetfilters associated with it.
""" """
LOG.debug(_("NECPluginV2.update_port() called, " LOG.debug(_("NECPluginV2.update_port() called, "
"id=%(id)s port=%(port)s ."), locals()) "id=%(id)s port=%(port)s ."),
{'id': id, 'port': port})
need_port_update_notify = False need_port_update_notify = False
with context.session.begin(subtransactions=True): with context.session.begin(subtransactions=True):
old_port = super(NECPluginV2, self).get_port(context, id) old_port = super(NECPluginV2, self).get_port(context, id)
@ -486,20 +486,19 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
LOG.debug(_("_activate_packet_filter_if_ready(): skip, " LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
"invalid in_port_id.")) "invalid in_port_id."))
pf_status = OperationalStatus.DOWN pf_status = OperationalStatus.DOWN
elif in_port_id and not ndb.get_portinfo(in_port_id): elif in_port_id and not ndb.get_portinfo(context.session, in_port_id):
LOG.debug(_("_activate_packet_filter_if_ready(): skip, " LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
"no portinfo for in_port.")) "no portinfo for in_port."))
pf_status = OperationalStatus.DOWN pf_status = OperationalStatus.DOWN
if pf_status in [OperationalStatus.ACTIVE]: if pf_status in [OperationalStatus.ACTIVE]:
if self.ofc.exists_ofc_packet_filter(packet_filter['id']): if self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
LOG.debug(_("_activate_packet_filter_if_ready(): skip, " LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
"ofc_packet_filter already exists.")) "ofc_packet_filter already exists."))
else: else:
try: try:
(self.ofc. (self.ofc.
create_ofc_packet_filter(packet_filter['tenant_id'], create_ofc_packet_filter(context,
packet_filter['network_id'],
packet_filter['id'], packet_filter['id'],
packet_filter)) packet_filter))
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
@ -515,14 +514,12 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
def _deactivate_packet_filter(self, context, packet_filter): def _deactivate_packet_filter(self, context, packet_filter):
"""Deactivate packet_filter by deleting filter from OFC if exixts.""" """Deactivate packet_filter by deleting filter from OFC if exixts."""
pf_status = OperationalStatus.DOWN pf_status = OperationalStatus.DOWN
if not self.ofc.exists_ofc_packet_filter(packet_filter['id']): if not self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
LOG.debug(_("_deactivate_packet_filter(): skip, " LOG.debug(_("_deactivate_packet_filter(): skip, "
"ofc_packet_filter does not exist.")) "ofc_packet_filter does not exist."))
else: else:
try: try:
self.ofc.delete_ofc_packet_filter(packet_filter['tenant_id'], self.ofc.delete_ofc_packet_filter(context, packet_filter['id'])
packet_filter['network_id'],
packet_filter['id'])
except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
reason = _("delete_ofc_packet_filter() failed due to " reason = _("delete_ofc_packet_filter() failed due to "
"%s") % exc "%s") % exc
@ -553,7 +550,7 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
""" """
LOG.debug(_("NECPluginV2.update_packet_filter() called, " LOG.debug(_("NECPluginV2.update_packet_filter() called, "
"id=%(id)s packet_filter=%(packet_filter)s ."), "id=%(id)s packet_filter=%(packet_filter)s ."),
locals()) {'id': id, 'packet_filter': packet_filter})
old_pf = super(NECPluginV2, self).get_packet_filter(context, id) old_pf = super(NECPluginV2, self).get_packet_filter(context, id)
new_pf = super(NECPluginV2, self).update_packet_filter(context, id, new_pf = super(NECPluginV2, self).update_packet_filter(context, id,
packet_filter) packet_filter)
@ -655,17 +652,18 @@ class NECPluginV2RPCCallbacks(object):
"kwargs=%s ."), kwargs) "kwargs=%s ."), kwargs)
topic = kwargs['topic'] topic = kwargs['topic']
datapath_id = kwargs['datapath_id'] datapath_id = kwargs['datapath_id']
session = rpc_context.session
for p in kwargs.get('port_added', []): for p in kwargs.get('port_added', []):
id = p['id'] id = p['id']
port = self.plugin.get_port(rpc_context, id) port = self.plugin.get_port(rpc_context, id)
if port and ndb.get_portinfo(id): if port and ndb.get_portinfo(session, id):
ndb.del_portinfo(id) ndb.del_portinfo(session, id)
self.plugin.deactivate_port(rpc_context, port) self.plugin.deactivate_port(rpc_context, port)
ndb.add_portinfo(id, datapath_id, p['port_no'], ndb.add_portinfo(session, id, datapath_id, p['port_no'],
mac=p.get('mac', '')) mac=p.get('mac', ''))
self.plugin.activate_port_if_ready(rpc_context, port) self.plugin.activate_port_if_ready(rpc_context, port)
for id in kwargs.get('port_removed', []): for id in kwargs.get('port_removed', []):
port = self.plugin.get_port(rpc_context, id) port = self.plugin.get_port(rpc_context, id)
if port and ndb.get_portinfo(id): if port and ndb.get_portinfo(session, id):
ndb.del_portinfo(id) ndb.del_portinfo(session, id)
self.plugin.deactivate_port(rpc_context, port) self.plugin.deactivate_port(rpc_context, port)

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
# @author: Akihiro MOTOKI
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
@ -53,22 +54,17 @@ class OFCDriverBase(object):
:param ofc_tenant_id: a OFC tenant ID in which a new network belongs. :param ofc_tenant_id: a OFC tenant ID in which a new network belongs.
:param description: A description of this network. :param description: A description of this network.
:param network_id: A hint of a OFC network ID. :param network_id: A hint of an ID of OFC network.
:returns: ID of the network created at OpenFlow Controller. :returns: ID of the network created at OpenFlow Controller.
ID returned must be unique in the OpenFlow Controller.
If a network is identified in conjunction with other information
such as a tenant ID, such information should be included in the ID.
:raises: quantum.plugin.nec.common.exceptions.OFCException :raises: quantum.plugin.nec.common.exceptions.OFCException
""" """
pass pass
@abstractmethod @abstractmethod
def update_network(self, ofc_tenant_id, ofc_network_id, description): def delete_network(self, ofc_network_id):
"""Update description of specified network.
:raises: quantum.plugin.nec.common.exceptions.OFCException
"""
pass
@abstractmethod
def delete_network(self, ofc_tenant_id, ofc_network_id):
"""Delete a netwrok at OpenFlow Controller. """Delete a netwrok at OpenFlow Controller.
:raises: quantum.plugin.nec.common.exceptions.OFCException :raises: quantum.plugin.nec.common.exceptions.OFCException
@ -76,9 +72,9 @@ class OFCDriverBase(object):
pass pass
@abstractmethod @abstractmethod
def create_port(self, ofc_tenant_id, ofc_network_id, portinfo, def create_port(self, ofc_network_id, portinfo,
port_id=None): port_id=None):
"""Create a new port on specified tenant and network at OFC. """Create a new port on specified network at OFC.
:param ofc_network_id: a OFC tenant ID in which a new port belongs. :param ofc_network_id: a OFC tenant ID in which a new port belongs.
:param portinfo: An OpenFlow information of this port. :param portinfo: An OpenFlow information of this port.
@ -87,7 +83,11 @@ class OFCDriverBase(object):
'vlan_id': VLAN ID that a port tagging. 'vlan_id': VLAN ID that a port tagging.
'mac': Mac address. 'mac': Mac address.
} }
:param port_id: A hint of a OFC port ID. :param port_id: A hint of an ID of OFC port.
ID returned must be unique in the OpenFlow Controller.
If a port is identified in combination with a network or
a tenant, such information should be included in the ID.
:returns: ID of the port created at OpenFlow Controller. :returns: ID of the port created at OpenFlow Controller.
:raises: quantum.plugin.nec.common.exceptions.OFCException :raises: quantum.plugin.nec.common.exceptions.OFCException
@ -95,9 +95,41 @@ class OFCDriverBase(object):
pass pass
@abstractmethod @abstractmethod
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id): def delete_port(self, ofc_port_id):
"""Delete a port at OpenFlow Controller. """Delete a port at OpenFlow Controller.
:raises: quantum.plugin.nec.common.exceptions.OFCException :raises: quantum.plugin.nec.common.exceptions.OFCException
""" """
pass pass
@abstractmethod
def convert_ofc_tenant_id(self, context, ofc_tenant_id):
"""Convert old-style ofc tenand id to new-style one.
:param context: quantum context object
:param ofc_tenant_id: ofc_tenant_id to be converted
"""
pass
@abstractmethod
def convert_ofc_network_id(self, context, ofc_network_id,
tenant_id):
"""Convert old-style ofc network id to new-style one.
:param context: quantum context object
:param ofc_network_id: ofc_network_id to be converted
:param tenant_id: quantum tenant_id of the network
"""
pass
@abstractmethod
def convert_ofc_port_id(self, context, ofc_port_id,
tenant_id, network_id):
"""Convert old-style ofc port id to new-style one.
:param context: quantum context object
:param ofc_port_id: ofc_port_id to be converted
:param tenant_id: quantum tenant_id of the port
:param network_id: quantum network_id of the port
"""
pass

View File

@ -14,11 +14,11 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
# @author: Akihiro MOTOKI
from quantum.plugins.nec.common import config from quantum.plugins.nec.common import config
from quantum.plugins.nec.common import exceptions as nexc from quantum.plugins.nec.common import exceptions as nexc
from quantum.plugins.nec.db import api as ndb from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.db import models as nmodels
from quantum.plugins.nec import drivers from quantum.plugins.nec import drivers
@ -31,121 +31,106 @@ class OFCManager(object):
OFC is identified by a switch ID 'datapath_id' and a port number 'port_no' OFC is identified by a switch ID 'datapath_id' and a port number 'port_no'
of the switch. An ID named as 'ofc_*' is used to identify resource on OFC. of the switch. An ID named as 'ofc_*' is used to identify resource on OFC.
""" """
resource_map = {'ofc_tenant': nmodels.OFCTenant,
'ofc_network': nmodels.OFCNetwork,
'ofc_port': nmodels.OFCPort,
'ofc_packet_filter': nmodels.OFCFilter}
def __init__(self): def __init__(self):
self.driver = drivers.get_driver(config.OFC.driver)(config.OFC) self.driver = drivers.get_driver(config.OFC.driver)(config.OFC)
def _get_ofc_id(self, resource, quantum_id): def _get_ofc_id(self, context, resource, quantum_id):
model = self.resource_map[resource] return ndb.get_ofc_id_lookup_both(context.session,
ofc_item = ndb.find_ofc_item(model, quantum_id) resource, quantum_id)
if not ofc_item:
reason = _("NotFound %(resource)s for "
"quantum_id=%(quantum_id)s.") % locals()
raise nexc.OFCConsistencyBroken(reason=reason)
return ofc_item.id
def _exists_ofc_item(self, resource, quantum_id): def _exists_ofc_item(self, context, resource, quantum_id):
model = self.resource_map[resource] return ndb.exists_ofc_item_lookup_both(context.session,
if ndb.find_ofc_item(model, quantum_id): resource, quantum_id)
return True
else:
return False
# Tenant def _add_ofc_item(self, context, resource, quantum_id, ofc_id):
# Ensure a new item is added to the new mapping table
ndb.add_ofc_item(context.session, resource, quantum_id, ofc_id)
def create_ofc_tenant(self, tenant_id): def _del_ofc_item(self, context, resource, quantum_id):
ndb.del_ofc_item_lookup_both(context.session, resource, quantum_id)
def create_ofc_tenant(self, context, tenant_id):
desc = "ID=%s at OpenStack." % tenant_id desc = "ID=%s at OpenStack." % tenant_id
ofc_tenant_id = self.driver.create_tenant(desc, tenant_id) ofc_tenant_id = self.driver.create_tenant(desc, tenant_id)
ndb.add_ofc_item(nmodels.OFCTenant, ofc_tenant_id, tenant_id) self._add_ofc_item(context, "ofc_tenant", tenant_id, ofc_tenant_id)
def exists_ofc_tenant(self, tenant_id): def exists_ofc_tenant(self, context, tenant_id):
return self._exists_ofc_item("ofc_tenant", tenant_id) return self._exists_ofc_item(context, "ofc_tenant", tenant_id)
def delete_ofc_tenant(self, tenant_id): def delete_ofc_tenant(self, context, tenant_id):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id)
ofc_tenant_id = self.driver.convert_ofc_tenant_id(
context, ofc_tenant_id)
self.driver.delete_tenant(ofc_tenant_id) self.driver.delete_tenant(ofc_tenant_id)
ndb.del_ofc_item(nmodels.OFCTenant, ofc_tenant_id) self._del_ofc_item(context, "ofc_tenant", tenant_id)
# Network def create_ofc_network(self, context, tenant_id, network_id,
network_name=None):
def create_ofc_network(self, tenant_id, network_id, network_name=None): ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id)
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) ofc_tenant_id = self.driver.convert_ofc_tenant_id(
context, ofc_tenant_id)
desc = "ID=%s Name=%s at Quantum." % (network_id, network_name) desc = "ID=%s Name=%s at Quantum." % (network_id, network_name)
ofc_net_id = self.driver.create_network(ofc_tenant_id, desc, ofc_net_id = self.driver.create_network(ofc_tenant_id, desc,
network_id) network_id)
ndb.add_ofc_item(nmodels.OFCNetwork, ofc_net_id, network_id) self._add_ofc_item(context, "ofc_network", network_id, ofc_net_id)
def update_ofc_network(self, tenant_id, network_id, network_name): def exists_ofc_network(self, context, network_id):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) return self._exists_ofc_item(context, "ofc_network", network_id)
ofc_net_id = self._get_ofc_id("ofc_network", network_id)
desc = "ID=%s Name=%s at Quantum." % (network_id, network_name) def delete_ofc_network(self, context, network_id, network):
self.driver.update_network(ofc_tenant_id, ofc_net_id, desc) ofc_net_id = self._get_ofc_id(context, "ofc_network", network_id)
ofc_net_id = self.driver.convert_ofc_network_id(
context, ofc_net_id, network['tenant_id'])
self.driver.delete_network(ofc_net_id)
self._del_ofc_item(context, "ofc_network", network_id)
def exists_ofc_network(self, network_id): def create_ofc_port(self, context, port_id, port):
return self._exists_ofc_item("ofc_network", network_id) ofc_net_id = self._get_ofc_id(context, "ofc_network",
port['network_id'])
def delete_ofc_network(self, tenant_id, network_id): ofc_net_id = self.driver.convert_ofc_network_id(
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) context, ofc_net_id, port['tenant_id'])
ofc_net_id = self._get_ofc_id("ofc_network", network_id) portinfo = ndb.get_portinfo(context.session, port_id)
self.driver.delete_network(ofc_tenant_id, ofc_net_id)
ndb.del_ofc_item(nmodels.OFCNetwork, ofc_net_id)
# Port
def create_ofc_port(self, tenant_id, network_id, port_id):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id)
ofc_net_id = self._get_ofc_id("ofc_network", network_id)
portinfo = ndb.get_portinfo(port_id)
if not portinfo: if not portinfo:
raise nexc.PortInfoNotFound(id=port_id) raise nexc.PortInfoNotFound(id=port_id)
ofc_port_id = self.driver.create_port(ofc_tenant_id, ofc_net_id, ofc_port_id = self.driver.create_port(ofc_net_id, portinfo, port_id)
portinfo, port_id) self._add_ofc_item(context, "ofc_port", port_id, ofc_port_id)
ndb.add_ofc_item(nmodels.OFCPort, ofc_port_id, port_id)
def exists_ofc_port(self, port_id): def exists_ofc_port(self, context, port_id):
return self._exists_ofc_item("ofc_port", port_id) return self._exists_ofc_item(context, "ofc_port", port_id)
def delete_ofc_port(self, tenant_id, network_id, port_id): def delete_ofc_port(self, context, port_id, port):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) ofc_port_id = self._get_ofc_id(context, "ofc_port", port_id)
ofc_net_id = self._get_ofc_id("ofc_network", network_id) ofc_port_id = self.driver.convert_ofc_port_id(
ofc_port_id = self._get_ofc_id("ofc_port", port_id) context, ofc_port_id, port['tenant_id'], port['network_id'])
self.driver.delete_port(ofc_port_id)
self._del_ofc_item(context, "ofc_port", port_id)
self.driver.delete_port(ofc_tenant_id, ofc_net_id, ofc_port_id) def create_ofc_packet_filter(self, context, filter_id, filter_dict):
ndb.del_ofc_item(nmodels.OFCPort, ofc_port_id) ofc_net_id = self._get_ofc_id(context, "ofc_network",
filter_dict['network_id'])
# PacketFilter ofc_net_id = self.driver.convert_ofc_network_id(
context, ofc_net_id, filter_dict['tenant_id'])
def create_ofc_packet_filter(self, tenant_id, network_id, filter_id,
filter_dict):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id)
ofc_net_id = self._get_ofc_id("ofc_network", network_id)
in_port_id = filter_dict.get('in_port') in_port_id = filter_dict.get('in_port')
portinfo = None portinfo = None
if in_port_id: if in_port_id:
portinfo = ndb.get_portinfo(in_port_id) portinfo = ndb.get_portinfo(context.session, in_port_id)
if not portinfo: if not portinfo:
raise nexc.PortInfoNotFound(id=in_port_id) raise nexc.PortInfoNotFound(id=in_port_id)
ofc_pf_id = self.driver.create_filter(ofc_tenant_id, ofc_net_id, ofc_pf_id = self.driver.create_filter(ofc_net_id,
filter_dict, portinfo, filter_id) filter_dict, portinfo, filter_id)
ndb.add_ofc_item(nmodels.OFCFilter, ofc_pf_id, filter_id) self._add_ofc_item(context, "ofc_packet_filter", filter_id, ofc_pf_id)
def exists_ofc_packet_filter(self, filter_id): def exists_ofc_packet_filter(self, context, filter_id):
return self._exists_ofc_item("ofc_packet_filter", filter_id) return self._exists_ofc_item(context, "ofc_packet_filter", filter_id)
def delete_ofc_packet_filter(self, tenant_id, network_id, filter_id): def delete_ofc_packet_filter(self, context, filter_id):
ofc_tenant_id = self._get_ofc_id("ofc_tenant", tenant_id) ofc_pf_id = self._get_ofc_id(context, "ofc_packet_filter", filter_id)
ofc_net_id = self._get_ofc_id("ofc_network", network_id) ofc_pf_id = self.driver.convert_ofc_filter_id(context, ofc_pf_id)
ofc_pf_id = self._get_ofc_id("ofc_packet_filter", filter_id)
res = self.driver.delete_filter(ofc_tenant_id, ofc_net_id, ofc_pf_id) res = self.driver.delete_filter(ofc_pf_id)
ndb.del_ofc_item(nmodels.OFCFilter, ofc_pf_id) self._del_ofc_item(context, "ofc_packet_filter", filter_id)

View File

@ -32,25 +32,37 @@ class StubOFCDriver(ofc_driver_base.OFCDriverBase):
def create_network(self, ofc_tenant_id, description, network_id=None): def create_network(self, ofc_tenant_id, description, network_id=None):
return "ofc-" + network_id[:-4] return "ofc-" + network_id[:-4]
def update_network(self, ofc_tenant_id, ofc_network_id, description): def update_network(self, ofc_network_id, description):
pass pass
def delete_network(self, ofc_tenant_id, ofc_network_id): def delete_network(self, ofc_network_id):
pass pass
def create_port(self, ofc_tenant_id, ofc_network_id, info, port_id=None): def create_port(self, ofc_network_id, info, port_id=None):
return "ofc-" + port_id[:-4] return "ofc-" + port_id[:-4]
def delete_port(self, ofc_tenant_id, ofc_network_id, ofc_port_id): def delete_port(self, ofc_port_id):
pass pass
@classmethod @classmethod
def filter_supported(cls): def filter_supported(cls):
return True return True
def create_filter(self, ofc_tenant_id, ofc_network_id, filter_dict, def create_filter(self, ofc_network_id, filter_dict,
portinfo=None, filter_id=None): portinfo=None, filter_id=None):
return "ofc-" + filter_id[:-4] return "ofc-" + filter_id[:-4]
def delete_filter(self, ofc_tenant_id, ofc_network_id, ofc_filter_id): def delete_filter(self, ofc_filter_id):
pass pass
def convert_ofc_tenant_id(self, context, ofc_tenant_id):
return ofc_tenant_id
def convert_ofc_network_id(self, context, ofc_network_id, tenant_id):
return ofc_network_id
def convert_ofc_port_id(self, context, ofc_port_id, tenant_id, network_id):
return ofc_port_id
def convert_ofc_filter_id(self, context, ofc_filter_id):
return ofc_filter_id

View File

@ -19,17 +19,19 @@ import random
import unittest import unittest
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.db import api as db_api
from quantum.plugins.nec.common import exceptions as nexc from quantum.plugins.nec.common import exceptions as nexc
from quantum.plugins.nec.db import api as ndb from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.db import models as nmodels from quantum.plugins.nec.db import models as nmodels
class NECPluginV2DBTest(unittest.TestCase): class NECPluginV2DBTestBase(object):
"""Class conisting of NECPluginV2 DB unit tests""" """Class conisting of NECPluginV2 DB unit tests"""
def setUp(self): def setUp(self):
"""Setup for tests""" """Setup for tests"""
ndb.initialize() ndb.initialize()
self.session = db_api.get_session()
def tearDown(self): def tearDown(self):
"""Tear Down""" """Tear Down"""
@ -42,53 +44,6 @@ class NECPluginV2DBTest(unittest.TestCase):
none = uuidutils.generate_uuid() none = uuidutils.generate_uuid()
return ofc_id, quantum_id, none return ofc_id, quantum_id, none
def testa_add_ofc_item(self):
"""test add OFC item"""
o, q, n = self.get_ofc_item_random_params()
tenant = ndb.add_ofc_item(nmodels.OFCTenant, o, q)
self.assertEqual(tenant.id, o)
self.assertEqual(tenant.quantum_id, q)
exception_raised = False
try:
ndb.add_ofc_item(nmodels.OFCTenant, o, q)
except nexc.NECDBException:
exception_raised = True
self.assertTrue(exception_raised)
def testb_get_ofc_item(self):
"""test get OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(nmodels.OFCTenant, o, q)
tenant = ndb.get_ofc_item(nmodels.OFCTenant, o)
self.assertEqual(tenant.id, o)
self.assertEqual(tenant.quantum_id, q)
tenant_none = ndb.get_ofc_item(nmodels.OFCTenant, n)
self.assertEqual(None, tenant_none)
def testc_find_ofc_item(self):
"""test find OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(nmodels.OFCTenant, o, q)
tenant = ndb.find_ofc_item(nmodels.OFCTenant, q)
self.assertEqual(tenant.id, o)
self.assertEqual(tenant.quantum_id, q)
tenant_none = ndb.find_ofc_item(nmodels.OFCTenant, n)
self.assertEqual(None, tenant_none)
def testc_del_ofc_item(self):
"""test delete OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(nmodels.OFCTenant, o, q)
ndb.del_ofc_item(nmodels.OFCTenant, o)
tenant_none = ndb.get_ofc_item(nmodels.OFCTenant, q)
self.assertEqual(None, tenant_none)
tenant_none = ndb.find_ofc_item(nmodels.OFCTenant, q)
self.assertEqual(None, tenant_none)
def get_portinfo_random_params(self): def get_portinfo_random_params(self):
"""create random parameters for portinfo test""" """create random parameters for portinfo test"""
port_id = uuidutils.generate_uuid() port_id = uuidutils.generate_uuid()
@ -99,10 +54,80 @@ class NECPluginV2DBTest(unittest.TestCase):
none = uuidutils.generate_uuid() none = uuidutils.generate_uuid()
return port_id, datapath_id, port_no, vlan_id, mac, none return port_id, datapath_id, port_no, vlan_id, mac, none
class NECPluginV2DBTest(NECPluginV2DBTestBase,
unittest.TestCase):
def testa_add_ofc_item(self):
"""test add OFC item"""
o, q, n = self.get_ofc_item_random_params()
tenant = ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
self.assertEqual(tenant.ofc_id, o)
self.assertEqual(tenant.quantum_id, q)
self.assertRaises(nexc.NECDBException,
ndb.add_ofc_item,
self.session, 'ofc_tenant', q, o)
def testb_get_ofc_item(self):
"""test get OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
tenant = ndb.get_ofc_item(self.session, 'ofc_tenant', q)
self.assertEqual(tenant.ofc_id, o)
self.assertEqual(tenant.quantum_id, q)
tenant_none = ndb.get_ofc_item(self.session, 'ofc_tenant', n)
self.assertEqual(None, tenant_none)
def testb_get_ofc_id(self):
"""test get OFC d"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
tenant_id = ndb.get_ofc_id(self.session, 'ofc_tenant', q)
self.assertEqual(tenant_id, o)
tenant_none = ndb.get_ofc_item(self.session, 'ofc_tenant', n)
self.assertEqual(None, tenant_none)
def testb_exists_ofc_item(self):
"""test get OFC d"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
ret = ndb.exists_ofc_item(self.session, 'ofc_tenant', q)
self.assertTrue(ret)
tenant_none = ndb.get_ofc_item(self.session, 'ofc_tenant', n)
self.assertEqual(None, tenant_none)
def testc_find_ofc_item(self):
"""test find OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
tenant = ndb.find_ofc_item(self.session, 'ofc_tenant', o)
self.assertEqual(tenant.ofc_id, o)
self.assertEqual(tenant.quantum_id, q)
tenant_none = ndb.find_ofc_item(self.session, 'ofc_tenant', n)
self.assertEqual(None, tenant_none)
def testc_del_ofc_item(self):
"""test delete OFC item"""
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o)
ndb.del_ofc_item(self.session, 'ofc_tenant', q)
tenant_none = ndb.get_ofc_item(self.session,
'ofc_tenant', q)
self.assertEqual(None, tenant_none)
tenant_none = ndb.find_ofc_item(self.session,
'ofc_tenant', o)
self.assertEqual(None, tenant_none)
def testd_add_portinfo(self): def testd_add_portinfo(self):
"""test add portinfo""" """test add portinfo"""
i, d, p, v, m, n = self.get_portinfo_random_params() i, d, p, v, m, n = self.get_portinfo_random_params()
portinfo = ndb.add_portinfo(i, d, p, v, m) portinfo = ndb.add_portinfo(self.session, i, d, p, v, m)
self.assertEqual(portinfo.id, i) self.assertEqual(portinfo.id, i)
self.assertEqual(portinfo.datapath_id, d) self.assertEqual(portinfo.datapath_id, d)
self.assertEqual(portinfo.port_no, p) self.assertEqual(portinfo.port_no, p)
@ -111,7 +136,7 @@ class NECPluginV2DBTest(unittest.TestCase):
exception_raised = False exception_raised = False
try: try:
ndb.add_portinfo(i, d, p, v, m) ndb.add_portinfo(self.session, i, d, p, v, m)
except nexc.NECDBException: except nexc.NECDBException:
exception_raised = True exception_raised = True
self.assertTrue(exception_raised) self.assertTrue(exception_raised)
@ -119,23 +144,131 @@ class NECPluginV2DBTest(unittest.TestCase):
def teste_get_portinfo(self): def teste_get_portinfo(self):
"""test get portinfo""" """test get portinfo"""
i, d, p, v, m, n = self.get_portinfo_random_params() i, d, p, v, m, n = self.get_portinfo_random_params()
ndb.add_portinfo(i, d, p, v, m) ndb.add_portinfo(self.session, i, d, p, v, m)
portinfo = ndb.get_portinfo(i) portinfo = ndb.get_portinfo(self.session, i)
self.assertEqual(portinfo.id, i) self.assertEqual(portinfo.id, i)
self.assertEqual(portinfo.datapath_id, d) self.assertEqual(portinfo.datapath_id, d)
self.assertEqual(portinfo.port_no, p) self.assertEqual(portinfo.port_no, p)
self.assertEqual(portinfo.vlan_id, v) self.assertEqual(portinfo.vlan_id, v)
self.assertEqual(portinfo.mac, m) self.assertEqual(portinfo.mac, m)
portinfo_none = ndb.get_portinfo(n) portinfo_none = ndb.get_portinfo(self.session, n)
self.assertEqual(None, portinfo_none) self.assertEqual(None, portinfo_none)
def testf_del_portinfo(self): def testf_del_portinfo(self):
"""test delete portinfo""" """test delete portinfo"""
i, d, p, v, m, n = self.get_portinfo_random_params() i, d, p, v, m, n = self.get_portinfo_random_params()
ndb.add_portinfo(i, d, p, v, m) ndb.add_portinfo(self.session, i, d, p, v, m)
portinfo = ndb.get_portinfo(i) portinfo = ndb.get_portinfo(self.session, i)
self.assertEqual(portinfo.id, i) self.assertEqual(portinfo.id, i)
ndb.del_portinfo(i) ndb.del_portinfo(self.session, i)
portinfo_none = ndb.get_portinfo(i) portinfo_none = ndb.get_portinfo(self.session, i)
self.assertEqual(None, portinfo_none) self.assertEqual(None, portinfo_none)
class NECPluginV2DBOldMappingTest(NECPluginV2DBTestBase,
unittest.TestCase):
"""Test related to old ID mapping"""
# Mapping Table mode
OLD = True
NEW = False
def test_add_ofc_item_new(self):
o, q, n = self.get_ofc_item_random_params()
ret = ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, self.NEW)
self.assertEqual(ret.ofc_id, o)
self.assertEqual(ret.quantum_id, q)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.NEW)
self.assertEqual(ret.ofc_id, o)
self.assertEqual(ret.quantum_id, q)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.OLD)
self.assertEqual(ret, None)
def test_add_ofc_item_old(self):
o, q, n = self.get_ofc_item_random_params()
ret = ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, self.OLD)
self.assertEqual(ret.id, o)
self.assertEqual(ret.quantum_id, q)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.NEW)
self.assertEqual(ret, None)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.OLD)
self.assertEqual(ret.id, o)
self.assertEqual(ret.quantum_id, q)
def _check_new_old_item(self, method, q_id, exp_new, exp_old):
ret = method(self.session, 'ofc_tenant', q_id, self.NEW)
self.assertEqual(ret, exp_new)
ret = method(self.session, 'ofc_tenant', q_id, self.OLD)
self.assertEqual(ret, exp_old)
def test_get_ofc_id_new(self):
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, self.NEW)
self._check_new_old_item(ndb.get_ofc_id, q, o, None)
ret = ndb.get_ofc_id_lookup_both(self.session, 'ofc_tenant', q)
self.assertEqual(ret, o)
def test_get_ofc_id_old(self):
o, q, n = self.get_ofc_item_random_params()
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, self.OLD)
self._check_new_old_item(ndb.get_ofc_id, q, None, o)
ret = ndb.get_ofc_id_lookup_both(self.session, 'ofc_tenant', q)
self.assertEqual(ret, o)
def _check_exists_ofc_item(self, mode, exp_new, exp_old):
o, q, n = self.get_ofc_item_random_params()
self._check_new_old_item(ndb.exists_ofc_item, q, False, False)
self.assertFalse(ndb.exists_ofc_item_lookup_both(
self.session, 'ofc_tenant', q))
ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, mode)
self._check_new_old_item(ndb.exists_ofc_item, q, exp_new, exp_old)
self.assertTrue(ndb.exists_ofc_item_lookup_both(
self.session, 'ofc_tenant', q))
ndb.del_ofc_item(self.session, 'ofc_tenant', q, mode)
self._check_new_old_item(ndb.exists_ofc_item, q, False, False)
self.assertFalse(ndb.exists_ofc_item_lookup_both(
self.session, 'ofc_tenant', q))
def test_exists_ofc_item_new(self):
self._check_exists_ofc_item(self.NEW, True, False)
def test_exists_ofc_item_old(self):
self._check_exists_ofc_item(self.OLD, False, True)
def _check_delete_ofc_item(self, mode, detect_mode=False):
o, q, n = self.get_ofc_item_random_params()
ret = ndb.add_ofc_item(self.session, 'ofc_tenant', q, o, mode)
ofc_id = ret.ofc_id if mode == self.NEW else ret.id
self.assertEqual(ofc_id, o)
self.assertEqual(ret.quantum_id, q)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, mode)
ofc_id = ret.ofc_id if mode == self.NEW else ret.id
self.assertEqual(ofc_id, o)
self.assertEqual(ret.quantum_id, q)
if detect_mode:
ndb.del_ofc_item_lookup_both(self.session, 'ofc_tenant', q)
else:
ndb.del_ofc_item(self.session, 'ofc_tenant', q, mode)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.NEW)
self.assertEqual(ret, None)
ret = ndb.get_ofc_item(self.session, 'ofc_tenant', q, self.OLD)
self.assertEqual(ret, None)
def test_delete_ofc_item_new(self):
self._check_delete_ofc_item(self.NEW)
def test_delete_ofc_item_old(self):
self._check_delete_ofc_item(self.OLD)
def test_delete_ofc_item_with_auto_detect_new(self):
self._check_delete_ofc_item(self.NEW, detect_mode=True)
def test_delete_ofc_item_old_auto_detect_new(self):
self._check_delete_ofc_item(self.OLD, detect_mode=True)

View File

@ -17,6 +17,7 @@
import unittest import unittest
from quantum import context
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.plugins.nec.common import config from quantum.plugins.nec.common import config
from quantum.plugins.nec.db import api as ndb from quantum.plugins.nec.db import api as ndb
@ -24,7 +25,7 @@ from quantum.plugins.nec.db import models as nmodels
from quantum.plugins.nec import ofc_manager from quantum.plugins.nec import ofc_manager
class OFCManagerTest(unittest.TestCase): class OFCManagerTestBase(object):
"""Class conisting of OFCManager unit tests""" """Class conisting of OFCManager unit tests"""
def setUp(self): def setUp(self):
@ -32,6 +33,7 @@ class OFCManagerTest(unittest.TestCase):
config.CONF.set_override('driver', driver, 'OFC') config.CONF.set_override('driver', driver, 'OFC')
ndb.initialize() ndb.initialize()
self.ofc = ofc_manager.OFCManager() self.ofc = ofc_manager.OFCManager()
self.ctx = context.get_admin_context()
def tearDown(self): def tearDown(self):
ndb.clear_db() ndb.clear_db()
@ -45,116 +47,230 @@ class OFCManagerTest(unittest.TestCase):
none = uuidutils.generate_uuid() none = uuidutils.generate_uuid()
return tenant, network, port, _filter, none return tenant, network, port, _filter, none
class OFCManagerTest(OFCManagerTestBase, unittest.TestCase):
def testa_create_ofc_tenant(self): def testa_create_ofc_tenant(self):
"""test create ofc_tenant""" """test create ofc_tenant"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.assertFalse(ndb.find_ofc_item(nmodels.OFCTenant, t)) self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t))
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.assertTrue(ndb.find_ofc_item(nmodels.OFCTenant, t)) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t))
tenant = ndb.find_ofc_item(nmodels.OFCTenant, t) tenant = ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t)
self.assertEqual(tenant.id, "ofc-" + t[:-4]) self.assertEqual(tenant.ofc_id, "ofc-" + t[:-4])
def testb_exists_ofc_tenant(self): def testb_exists_ofc_tenant(self):
"""test exists_ofc_tenant""" """test exists_ofc_tenant"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_tenant(t)) self.assertFalse(self.ofc.exists_ofc_tenant(self.ctx, t))
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.assertTrue(self.ofc.exists_ofc_tenant(t)) self.assertTrue(self.ofc.exists_ofc_tenant(self.ctx, t))
def testc_delete_ofc_tenant(self): def testc_delete_ofc_tenant(self):
"""test delete ofc_tenant""" """test delete ofc_tenant"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.assertTrue(ndb.find_ofc_item(nmodels.OFCTenant, t)) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t))
self.ofc.delete_ofc_tenant(t) self.ofc.delete_ofc_tenant(self.ctx, t)
self.assertFalse(ndb.find_ofc_item(nmodels.OFCTenant, t)) self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_tenant', t))
def testd_create_ofc_network(self): def testd_create_ofc_network(self):
"""test create ofc_network""" """test create ofc_network"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.assertFalse(ndb.find_ofc_item(nmodels.OFCNetwork, n)) self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n))
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.assertTrue(ndb.find_ofc_item(nmodels.OFCNetwork, n)) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n))
network = ndb.find_ofc_item(nmodels.OFCNetwork, n) network = ndb.get_ofc_item(self.ctx.session, 'ofc_network', n)
self.assertEqual(network.id, "ofc-" + n[:-4]) self.assertEqual(network.ofc_id, "ofc-" + n[:-4])
def teste_exists_ofc_network(self): def teste_exists_ofc_network(self):
"""test exists_ofc_network""" """test exists_ofc_network"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.assertFalse(self.ofc.exists_ofc_network(n)) self.assertFalse(self.ofc.exists_ofc_network(self.ctx, n))
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.assertTrue(self.ofc.exists_ofc_network(n)) self.assertTrue(self.ofc.exists_ofc_network(self.ctx, n))
def testf_delete_ofc_network(self): def testf_delete_ofc_network(self):
"""test delete ofc_network""" """test delete ofc_network"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.assertTrue(ndb.find_ofc_item(nmodels.OFCNetwork, n)) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n))
self.ofc.delete_ofc_network(t, n) self.ofc.delete_ofc_network(self.ctx, n, {'tenant_id': t})
self.assertFalse(ndb.find_ofc_item(nmodels.OFCNetwork, n)) self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_network', n))
def testg_create_ofc_port(self): def testg_create_ofc_port(self):
"""test create ofc_port""" """test create ofc_port"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
ndb.add_portinfo(p, "0xabc", 1, 65535, "00:11:22:33:44:55") ndb.add_portinfo(self.ctx.session, p, "0xabc", 1, 65535,
self.assertFalse(ndb.find_ofc_item(nmodels.OFCPort, p)) "00:11:22:33:44:55")
self.ofc.create_ofc_port(t, n, p) self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p))
self.assertTrue(ndb.find_ofc_item(nmodels.OFCPort, p)) port = {'tenant_id': t, 'network_id': n}
port = ndb.find_ofc_item(nmodels.OFCPort, p) self.ofc.create_ofc_port(self.ctx, p, port)
self.assertEqual(port.id, "ofc-" + p[:-4]) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p))
port = ndb.get_ofc_item(self.ctx.session, 'ofc_port', p)
self.assertEqual(port.ofc_id, "ofc-" + p[:-4])
def testh_exists_ofc_port(self): def testh_exists_ofc_port(self):
"""test exists_ofc_port""" """test exists_ofc_port"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
ndb.add_portinfo(p, "0xabc", 2, 65535, "00:12:22:33:44:55") ndb.add_portinfo(self.ctx.session, p, "0xabc", 2, 65535,
self.assertFalse(self.ofc.exists_ofc_port(p)) "00:12:22:33:44:55")
self.ofc.create_ofc_port(t, n, p) self.assertFalse(self.ofc.exists_ofc_port(self.ctx, p))
self.assertTrue(self.ofc.exists_ofc_port(p)) port = {'tenant_id': t, 'network_id': n}
self.ofc.create_ofc_port(self.ctx, p, port)
self.assertTrue(self.ofc.exists_ofc_port(self.ctx, p))
def testi_delete_ofc_port(self): def testi_delete_ofc_port(self):
"""test delete ofc_port""" """test delete ofc_port"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
ndb.add_portinfo(p, "0xabc", 3, 65535, "00:13:22:33:44:55") ndb.add_portinfo(self.ctx.session, p, "0xabc", 3, 65535,
self.ofc.create_ofc_port(t, n, p) "00:13:22:33:44:55")
self.assertTrue(ndb.find_ofc_item(nmodels.OFCPort, p)) port = {'tenant_id': t, 'network_id': n}
self.ofc.delete_ofc_port(t, n, p) self.ofc.create_ofc_port(self.ctx, p, port)
self.assertFalse(ndb.find_ofc_item(nmodels.OFCPort, p)) self.assertTrue(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p))
self.ofc.delete_ofc_port(self.ctx, p, port)
self.assertFalse(ndb.get_ofc_item(self.ctx.session, 'ofc_port', p))
def testj_create_ofc_packet_filter(self): def testj_create_ofc_packet_filter(self):
"""test create ofc_filter""" """test create ofc_filter"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.assertFalse(ndb.find_ofc_item(nmodels.OFCFilter, f)) self.assertFalse(ndb.get_ofc_item(self.ctx.session,
self.ofc.create_ofc_packet_filter(t, n, f, {}) 'ofc_packet_filter', f))
self.assertTrue(ndb.find_ofc_item(nmodels.OFCFilter, f)) pf = {'tenant_id': t, 'network_id': n}
_filter = ndb.find_ofc_item(nmodels.OFCFilter, f) self.ofc.create_ofc_packet_filter(self.ctx, f, pf)
self.assertEqual(_filter.id, "ofc-" + f[:-4]) self.assertTrue(ndb.get_ofc_item(self.ctx.session,
'ofc_packet_filter', f))
_filter = ndb.get_ofc_item(self.ctx.session, 'ofc_packet_filter', f)
self.assertEqual(_filter.ofc_id, "ofc-" + f[:-4])
def testk_exists_ofc_packet_filter(self): def testk_exists_ofc_packet_filter(self):
"""test exists_ofc_packet_filter""" """test exists_ofc_packet_filter"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.assertFalse(self.ofc.exists_ofc_packet_filter(f)) self.assertFalse(self.ofc.exists_ofc_packet_filter(self.ctx, f))
self.ofc.create_ofc_packet_filter(t, n, f, {}) pf = {'tenant_id': t, 'network_id': n}
self.assertTrue(self.ofc.exists_ofc_packet_filter(f)) self.ofc.create_ofc_packet_filter(self.ctx, f, pf)
self.assertTrue(self.ofc.exists_ofc_packet_filter(self.ctx, f))
def testl_delete_ofc_packet_filter(self): def testl_delete_ofc_packet_filter(self):
"""test delete ofc_filter""" """test delete ofc_filter"""
t, n, p, f, none = self.get_random_params() t, n, p, f, none = self.get_random_params()
self.ofc.create_ofc_tenant(t) self.ofc.create_ofc_tenant(self.ctx, t)
self.ofc.create_ofc_network(t, n) self.ofc.create_ofc_network(self.ctx, t, n)
self.ofc.create_ofc_packet_filter(t, n, f, {}) pf = {'tenant_id': t, 'network_id': n}
self.assertTrue(ndb.find_ofc_item(nmodels.OFCFilter, f)) self.ofc.create_ofc_packet_filter(self.ctx, f, pf)
self.ofc.delete_ofc_packet_filter(t, n, f) self.assertTrue(ndb.get_ofc_item(self.ctx.session,
self.assertFalse(ndb.find_ofc_item(nmodels.OFCFilter, f)) 'ofc_packet_filter', f))
self.ofc.delete_ofc_packet_filter(self.ctx, f)
self.assertFalse(ndb.get_ofc_item(self.ctx.session,
'ofc_packet_filter', f))
class OFCManagerTestWithOldMapping(OFCManagerTestBase, unittest.TestCase):
def test_exists_ofc_tenant(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_tenant(self.ctx, t))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_tenant', t, ofc_t, old_style=True)
self.assertTrue(self.ofc.exists_ofc_tenant(self.ctx, t))
def test_delete_ofc_tenant(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_tenant(self.ctx, t))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_tenant', t, ofc_t, old_style=True)
self.assertTrue(self.ofc.exists_ofc_tenant(self.ctx, t))
self.ofc.delete_ofc_tenant(self.ctx, t)
self.assertFalse(self.ofc.exists_ofc_tenant(self.ctx, t))
def test_exists_ofc_network(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_network(self.ctx, n))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_network', n, ofc_n, old_style=True)
self.assertTrue(self.ofc.exists_ofc_network(self.ctx, n))
def test_delete_ofc_network(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_network(self.ctx, n))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_network', n, ofc_n, old_style=True)
self.assertTrue(self.ofc.exists_ofc_network(self.ctx, n))
net = {'tenant_id': t}
self.ofc.delete_ofc_network(self.ctx, n, net)
self.assertFalse(self.ofc.exists_ofc_network(self.ctx, n))
def test_exists_ofc_port(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_port(self.ctx, p))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_port', p, ofc_p, old_style=True)
self.assertTrue(self.ofc.exists_ofc_port(self.ctx, p))
def test_delete_ofc_port(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_port(self.ctx, p))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_port', p, ofc_p, old_style=True)
self.assertTrue(self.ofc.exists_ofc_port(self.ctx, p))
port = {'tenant_id': t, 'network_id': n}
self.ofc.delete_ofc_port(self.ctx, p, port)
self.assertFalse(self.ofc.exists_ofc_port(self.ctx, p))
def test_exists_ofc_packet_filter(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_packet_filter(self.ctx, f))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_packet_filter', f, ofc_f,
old_style=True)
self.assertTrue(self.ofc.exists_ofc_packet_filter(self.ctx, f))
def test_delete_ofc_packet_filter(self):
t, n, p, f, none = self.get_random_params()
ofc_t, ofc_n, ofc_p, ofc_f, ofc_none = self.get_random_params()
self.assertFalse(self.ofc.exists_ofc_packet_filter(self.ctx, f))
session = self.ctx.session
ndb.add_ofc_item(session, 'ofc_packet_filter', f, ofc_f,
old_style=True)
self.assertTrue(self.ofc.exists_ofc_packet_filter(self.ctx, f))
self.ofc.delete_ofc_packet_filter(self.ctx, f)
self.assertFalse(self.ofc.exists_ofc_packet_filter(self.ctx, f))

View File

@ -15,11 +15,16 @@
# under the License. # under the License.
# @author: Ryota MIBU # @author: Ryota MIBU
import random
import string
import mox import mox
import unittest import unittest
from quantum import context
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.plugins.nec.common import ofc_client as ofc from quantum.plugins.nec.common import ofc_client as ofc
from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.db import models as nmodels from quantum.plugins.nec.db import models as nmodels
from quantum.plugins.nec import drivers from quantum.plugins.nec import drivers
@ -38,11 +43,13 @@ def _ofc(id):
return "ofc-%s" % id return "ofc-%s" % id
class PFCDriverTestBase(unittest.TestCase): class PFCDriverTestBase():
driver = 'quantum.plugins.nec.drivers.pfc.PFCDriverBase'
def setUp(self): def setUp(self):
self.mox = mox.Mox() self.mox = mox.Mox()
self.driver = drivers.get_driver("pfc")(TestConfig) self.driver = drivers.get_driver(self.driver)(TestConfig)
self.mox.StubOutWithMock(ofc.OFCClient, 'do_request') self.mox.StubOutWithMock(ofc.OFCClient, 'do_request')
def tearDown(self): def tearDown(self):
@ -58,31 +65,40 @@ class PFCDriverTestBase(unittest.TestCase):
mac="11:22:33:44:55:66") mac="11:22:33:44:55:66")
return tenant_id, network_id, portinfo return tenant_id, network_id, portinfo
def testa_create_tenant(self): def _generate_ofc_tenant_id(self, tenant_id):
t, n, p = self.get_ofc_item_random_params() fields = tenant_id.split('-')
description = "desc of %s" % t # Strip 1st character (UUID version) of 3rd field
fields[2] = fields[2][1:]
return ''.join(fields)
def get_ofc_description(self, desc):
"""OFC description consists of [A-Za-z0-9_]."""
return desc.replace('-', '_').replace(' ', '_')
def _create_tenant(self, t, ofc_t, post_id=False, post_desc=False):
tenant_path = '/tenants/%s' % ofc_t
path = "/tenants" path = "/tenants"
body = {'id': t, 'description': description} description = "desc of %s" % t
tenant = {'id': _ofc(t)} body = {}
ofc.OFCClient.do_request("POST", path, body=body).AndReturn(tenant) if post_desc:
ofc_description = self.get_ofc_description(description)
body['description'] = ofc_description
if post_id:
body['id'] = ofc_t
ofc.OFCClient.do_request("POST", path, body=body)
else:
ofc.OFCClient.do_request("POST", path, body=body).\
AndReturn({'id': ofc_t})
self.mox.ReplayAll() self.mox.ReplayAll()
ret = self.driver.create_tenant(description, t) ret = self.driver.create_tenant(description, t)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, _ofc(t)) self.assertEqual(ret, tenant_path)
def testb_update_tenant(self): def testa_create_tenant(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
description = "new desc of %s" % t ofc_t = self._generate_ofc_tenant_id(t)
self._create_tenant(t, ofc_t, post_id=True)
path = "/tenants/%s" % _ofc(t)
body = {'description': description}
ofc.OFCClient.do_request("PUT", path, body=body)
self.mox.ReplayAll()
self.driver.update_tenant(_ofc(t), description)
self.mox.VerifyAll()
def testc_delete_tenant(self): def testc_delete_tenant(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
@ -91,68 +107,252 @@ class PFCDriverTestBase(unittest.TestCase):
ofc.OFCClient.do_request("DELETE", path) ofc.OFCClient.do_request("DELETE", path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_tenant(_ofc(t)) self.driver.delete_tenant(path)
self.mox.VerifyAll() self.mox.VerifyAll()
def testd_create_network(self): def testd_create_network(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
description = "desc of %s" % n description = "desc of %s" % n
ofc_description = self.get_ofc_description(description)
path = "/tenants/%s/networks" % _ofc(t) tenant_path = "/tenants/%s" % _ofc(t)
body = {'id': n, 'description': description} post_path = "%s/networks" % tenant_path
body = {'description': ofc_description}
network = {'id': _ofc(n)} network = {'id': _ofc(n)}
ofc.OFCClient.do_request("POST", path, body=body).AndReturn(network) ofc.OFCClient.do_request("POST", post_path, body=body).\
AndReturn(network)
self.mox.ReplayAll() self.mox.ReplayAll()
ret = self.driver.create_network(_ofc(t), description, n) ret = self.driver.create_network(tenant_path, description, n)
self.mox.VerifyAll()
self.assertEqual(ret, _ofc(n))
def teste_update_network(self):
t, n, p = self.get_ofc_item_random_params()
description = "desc of %s" % n
path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n))
body = {'description': description}
ofc.OFCClient.do_request("PUT", path, body=body)
self.mox.ReplayAll()
self.driver.update_network(_ofc(t), _ofc(n), description)
self.mox.VerifyAll() self.mox.VerifyAll()
net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n))
self.assertEqual(ret, net_path)
def testf_delete_network(self): def testf_delete_network(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n)) net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n))
ofc.OFCClient.do_request("DELETE", path) ofc.OFCClient.do_request("DELETE", net_path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_network(_ofc(t), _ofc(n)) self.driver.delete_network(net_path)
self.mox.VerifyAll() self.mox.VerifyAll()
def testg_create_port(self): def testg_create_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
path = "/tenants/%s/networks/%s/ports" % (_ofc(t), _ofc(n)) net_path = "/tenants/%s/networks/%s" % (_ofc(t), _ofc(n))
body = {'id': p.id, post_path = "%s/ports" % net_path
'datapath_id': p.datapath_id, port_path = "/tenants/%s/networks/%s/ports/%s" % (_ofc(t), _ofc(n),
_ofc(p.id))
body = {'datapath_id': p.datapath_id,
'port': str(p.port_no), 'port': str(p.port_no),
'vid': str(p.vlan_id)} 'vid': str(p.vlan_id)}
port = {'id': _ofc(p.id)} port = {'id': _ofc(p.id)}
ofc.OFCClient.do_request("POST", path, body=body).AndReturn(port) ofc.OFCClient.do_request("POST", post_path, body=body).AndReturn(port)
self.mox.ReplayAll() self.mox.ReplayAll()
ret = self.driver.create_port(_ofc(t), _ofc(n), p, p.id) ret = self.driver.create_port(net_path, p, p.id)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, _ofc(p.id)) self.assertEqual(ret, port_path)
def testh_delete_port(self): def testh_delete_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
path = "/tenants/%s/networks/%s/ports/%s" % (_ofc(t), _ofc(n), port_path = "/tenants/%s/networks/%s/ports/%s" % (_ofc(t), _ofc(n),
_ofc(p.id)) _ofc(p.id))
ofc.OFCClient.do_request("DELETE", path) ofc.OFCClient.do_request("DELETE", port_path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_port(_ofc(t), _ofc(n), _ofc(p.id)) self.driver.delete_port(port_path)
self.mox.VerifyAll() self.mox.VerifyAll()
class PFCDriverBaseTest(PFCDriverTestBase, unittest.TestCase):
pass
class PFCV3DriverTest(PFCDriverTestBase, unittest.TestCase):
driver = 'pfc_v3'
def testa_create_tenant(self):
t, n, p = self.get_ofc_item_random_params()
self.mox.ReplayAll()
ret = self.driver.create_tenant('dummy_desc', t)
self.mox.VerifyAll()
ofc_t_path = "/tenants/" + self._generate_ofc_tenant_id(t)
self.assertEqual(ofc_t_path, ret)
def testc_delete_tenant(self):
pass
class PFCV4DriverTest(PFCDriverTestBase, unittest.TestCase):
driver = 'pfc_v4'
class PFCDriverStringTest(unittest.TestCase):
driver = 'quantum.plugins.nec.drivers.pfc.PFCDriverBase'
def setUp(self):
self.driver = drivers.get_driver(self.driver)(TestConfig)
def tearDown(self):
pass
def test_generate_pfc_id_uuid(self):
id_str = uuidutils.generate_uuid()
exp_str = (id_str[:14] + id_str[15:]).replace('-', '')[:31]
ret_str = self.driver._generate_pfc_id(id_str)
self.assertEqual(exp_str, ret_str)
def test_generate_pfc_id_uuid_no_hyphen(self):
# Keystone tenant_id style uuid
id_str = uuidutils.generate_uuid()
id_no_hyphen = id_str.replace('-', '')
exp_str = (id_str[:14] + id_str[15:]).replace('-', '')[:31]
ret_str = self.driver._generate_pfc_id(id_no_hyphen)
self.assertEqual(exp_str, ret_str)
def test_generate_pfc_id_string(self):
id_str = uuidutils.generate_uuid() + 'x'
exp_str = id_str[:31].replace('-', '_')
ret_str = self.driver._generate_pfc_id(id_str)
self.assertEqual(exp_str, ret_str)
def test_generate_pfc_desc(self):
random_list = [random.choice(string.printable) for x in range(128)]
random_str = ''.join(random_list)
accept_letters = string.letters + string.digits
exp_list = [x if x in accept_letters else '_' for x in random_list]
exp_str = ''.join(exp_list)[:127]
ret_str = self.driver._generate_pfc_description(random_str)
self.assertEqual(exp_str, ret_str)
class PFCIdConvertTest(unittest.TestCase):
driver = 'quantum.plugins.nec.drivers.pfc.PFCDriverBase'
def setUp(self):
self.mox = mox.Mox()
self.driver = drivers.get_driver(self.driver)(TestConfig)
self.ctx = self.mox.CreateMock(context.Context)
self.ctx.session = "session"
self.mox.StubOutWithMock(ndb, 'get_ofc_id_lookup_both')
def tearDown(self):
self.mox.UnsetStubs()
def generate_random_ids(self, count=1):
if count == 1:
return uuidutils.generate_uuid()
else:
return [uuidutils.generate_uuid() for _ in xrange(count)]
def test_convert_tenant_id(self):
ofc_t_id = self.generate_random_ids(1)
print ofc_t_id
ret = self.driver.convert_ofc_tenant_id(self.ctx, ofc_t_id)
self.assertEqual(ret, '/tenants/%s' % ofc_t_id)
def test_convert_tenant_id_noconv(self):
ofc_t_id = '/tenants/%s' % self.generate_random_ids(1)
ret = self.driver.convert_ofc_tenant_id(self.ctx, ofc_t_id)
self.assertEqual(ret, ofc_t_id)
def test_convert_network_id(self):
t_id, ofc_t_id, ofc_n_id = self.generate_random_ids(3)
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_tenant', t_id).AndReturn(ofc_t_id)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_network_id(self.ctx, ofc_n_id, t_id)
self.assertEqual(ret, ('/tenants/%(tenant)s/networks/%(network)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id}))
self.mox.VerifyAll()
def test_convert_network_id_with_new_tenant_id(self):
t_id, ofc_t_id, ofc_n_id = self.generate_random_ids(3)
ofc_t_path = '/tenants/%s' % ofc_t_id
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_tenant', t_id).AndReturn(ofc_t_path)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_network_id(self.ctx, ofc_n_id, t_id)
self.assertEqual(ret, ('/tenants/%(tenant)s/networks/%(network)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id}))
self.mox.VerifyAll()
def test_convert_network_id_noconv(self):
t_id = 'dummy'
ofc_t_id, ofc_n_id = self.generate_random_ids(2)
ofc_n_id = ('/tenants/%(tenant)s/networks/%(network)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id})
ret = self.driver.convert_ofc_network_id(self.ctx, ofc_n_id, t_id)
self.assertEqual(ret, ofc_n_id)
def test_convert_port_id(self):
t_id, n_id = self.generate_random_ids(2)
ofc_t_id, ofc_n_id, ofc_p_id = self.generate_random_ids(3)
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_network', n_id).AndReturn(ofc_n_id)
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_tenant', t_id).AndReturn(ofc_t_id)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
exp = ('/tenants/%(tenant)s/networks/%(network)s/ports/%(port)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id, 'port': ofc_p_id})
self.assertEqual(ret, exp)
self.mox.VerifyAll()
def test_convert_port_id_with_new_tenant_id(self):
t_id, n_id = self.generate_random_ids(2)
ofc_t_id, ofc_n_id, ofc_p_id = self.generate_random_ids(3)
ofc_t_path = '/tenants/%s' % ofc_t_id
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_network', n_id).AndReturn(ofc_n_id)
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_tenant', t_id).AndReturn(ofc_t_path)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
exp = ('/tenants/%(tenant)s/networks/%(network)s/ports/%(port)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id, 'port': ofc_p_id})
self.assertEqual(ret, exp)
self.mox.VerifyAll()
def test_convert_port_id_with_new_network_id(self):
t_id, n_id = self.generate_random_ids(2)
ofc_t_id, ofc_n_id, ofc_p_id = self.generate_random_ids(3)
ofc_n_path = ('/tenants/%(tenant)s/networks/%(network)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id})
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_network', n_id).AndReturn(ofc_n_path)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
exp = ('/tenants/%(tenant)s/networks/%(network)s/ports/%(port)s' %
{'tenant': ofc_t_id, 'network': ofc_n_id, 'port': ofc_p_id})
self.assertEqual(ret, exp)
self.mox.VerifyAll()
def test_convert_port_id_noconv(self):
t_id = n_id = 'dummy'
ofc_t_id, ofc_n_id, ofc_p_id = self.generate_random_ids(3)
ofc_p_id = ('/tenants/%(tenant)s/networs/%(network)s/ports/%(port)s'
% {'tenant': ofc_t_id, 'network': ofc_n_id,
'port': ofc_p_id})
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
self.assertEqual(ret, ofc_p_id)

View File

@ -18,8 +18,10 @@
import mox import mox
import unittest import unittest
from quantum import context
from quantum.openstack.common import uuidutils from quantum.openstack.common import uuidutils
from quantum.plugins.nec.common import ofc_client from quantum.plugins.nec.common import ofc_client
from quantum.plugins.nec.db import api as ndb
from quantum.plugins.nec.db import models as nmodels from quantum.plugins.nec.db import models as nmodels
from quantum.plugins.nec import drivers from quantum.plugins.nec import drivers
@ -63,27 +65,18 @@ class TremaDriverNetworkTestBase(TremaDriverTestBase):
ofc_client.OFCClient.do_request("POST", "/networks", body=body) ofc_client.OFCClient.do_request("POST", "/networks", body=body)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.create_network(t, description, n) ret = self.driver.create_network(t, description, n)
self.mox.VerifyAll()
def testb_update_network(self):
t, n, p = self.get_ofc_item_random_params()
description = "desc of %s" % n
body = {'description': description}
ofc_client.OFCClient.do_request("PUT", "/networks/%s" % n, body=body)
self.mox.ReplayAll()
self.driver.update_network(t, n, description)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, '/networks/%s' % n)
def testc_delete_network(self): def testc_delete_network(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
ofc_client.OFCClient.do_request("DELETE", "/networks/%s" % n) net_path = "/networks/%s" % n
ofc_client.OFCClient.do_request("DELETE", net_path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_network(t, n) self.driver.delete_network(net_path)
self.mox.VerifyAll() self.mox.VerifyAll()
@ -92,8 +85,9 @@ class TremaPortBaseDriverTest(TremaDriverNetworkTestBase, unittest.TestCase):
driver_name = "trema_port" driver_name = "trema_port"
def testd_create_port(self): def testd_create_port(self):
t, n, p = self.get_ofc_item_random_params() _t, n, p = self.get_ofc_item_random_params()
net_path = "/networks/%s" % n
body = {'id': p.id, body = {'id': p.id,
'datapath_id': p.datapath_id, 'datapath_id': p.datapath_id,
'port': str(p.port_no), 'port': str(p.port_no),
@ -102,17 +96,18 @@ class TremaPortBaseDriverTest(TremaDriverNetworkTestBase, unittest.TestCase):
"/networks/%s/ports" % n, body=body) "/networks/%s/ports" % n, body=body)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.create_port(t, n, p, p.id) ret = self.driver.create_port(net_path, p, p.id)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, '/networks/%s/ports/%s' % (n, p.id))
def testd_delete_port(self): def testd_delete_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
ofc_client.OFCClient.do_request("DELETE", p_path = "/networks/%s/ports/%s" % (n, p.id)
"/networks/%s/ports/%s" % (n, p.id)) ofc_client.OFCClient.do_request("DELETE", p_path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_port(t, n, p.id) self.driver.delete_port(p_path)
self.mox.VerifyAll() self.mox.VerifyAll()
@ -125,6 +120,7 @@ class TremaPortMACBaseDriverTest(TremaDriverNetworkTestBase,
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
dummy_port = "dummy-%s" % p.id dummy_port = "dummy-%s" % p.id
net_path = "/networks/%s" % n
path_1 = "/networks/%s/ports" % n path_1 = "/networks/%s/ports" % n
body_1 = {'id': dummy_port, body_1 = {'id': dummy_port,
'datapath_id': p.datapath_id, 'datapath_id': p.datapath_id,
@ -138,8 +134,11 @@ class TremaPortMACBaseDriverTest(TremaDriverNetworkTestBase,
ofc_client.OFCClient.do_request("DELETE", path_3) ofc_client.OFCClient.do_request("DELETE", path_3)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.create_port(t, n, p, p.id) ret = self.driver.create_port(net_path, p, p.id)
self.mox.VerifyAll() self.mox.VerifyAll()
port_path = "/networks/%s/ports/%s/attachments/%s" % (n, dummy_port,
p.id)
self.assertEqual(ret, port_path)
def testd_delete_port(self): def testd_delete_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
@ -149,7 +148,7 @@ class TremaPortMACBaseDriverTest(TremaDriverNetworkTestBase,
ofc_client.OFCClient.do_request("DELETE", path) ofc_client.OFCClient.do_request("DELETE", path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_port(t, n, p.id) self.driver.delete_port(path)
self.mox.VerifyAll() self.mox.VerifyAll()
@ -160,13 +159,15 @@ class TremaMACBaseDriverTest(TremaDriverNetworkTestBase, unittest.TestCase):
def testd_create_port(self): def testd_create_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
net_path = "/networks/%s" % n
path = "/networks/%s/attachments" % n path = "/networks/%s/attachments" % n
body = {'id': p.id, 'mac': p.mac} body = {'id': p.id, 'mac': p.mac}
ofc_client.OFCClient.do_request("POST", path, body=body) ofc_client.OFCClient.do_request("POST", path, body=body)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.create_port(t, n, p, p.id) ret = self.driver.create_port(net_path, p, p.id)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, '/networks/%s/attachments/%s' % (n, p.id))
def testd_delete_port(self): def testd_delete_port(self):
t, n, p = self.get_ofc_item_random_params() t, n, p = self.get_ofc_item_random_params()
@ -175,7 +176,7 @@ class TremaMACBaseDriverTest(TremaDriverNetworkTestBase, unittest.TestCase):
ofc_client.OFCClient.do_request("DELETE", path) ofc_client.OFCClient.do_request("DELETE", path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_port(t, n, p.id) self.driver.delete_port(path)
self.mox.VerifyAll() self.mox.VerifyAll()
@ -208,6 +209,7 @@ class TremaFilterDriverTest(TremaDriverTestBase, unittest.TestCase):
def testa_create_filter(self): def testa_create_filter(self):
t, n, p, f = self.get_ofc_item_random_params() t, n, p, f = self.get_ofc_item_random_params()
net_path = "/networks/%s" % n
ofp_wildcards = 'dl_vlan,dl_vlan_pcp,nw_tos,dl_dst,' + \ ofp_wildcards = 'dl_vlan,dl_vlan_pcp,nw_tos,dl_dst,' + \
'nw_src:32,nw_dst:32,tp_src,tp_dst' 'nw_src:32,nw_dst:32,tp_src,tp_dst'
body = {'id': f.id, body = {'id': f.id,
@ -223,14 +225,162 @@ class TremaFilterDriverTest(TremaDriverTestBase, unittest.TestCase):
ofc_client.OFCClient.do_request("POST", "/filters", body=body) ofc_client.OFCClient.do_request("POST", "/filters", body=body)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.create_filter(t, n, f, p, f.id) ret = self.driver.create_filter(net_path, f, p, f.id)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(ret, '/filters/%s' % f.id)
def testb_delete_filter(self): def testb_delete_filter(self):
t, n, p, f = self.get_ofc_item_random_params() t, n, p, f = self.get_ofc_item_random_params()
ofc_client.OFCClient.do_request("DELETE", "/filters/%s" % f.id) f_path = "/filters/%s" % f.id
ofc_client.OFCClient.do_request("DELETE", f_path)
self.mox.ReplayAll() self.mox.ReplayAll()
self.driver.delete_filter(t, n, f.id) self.driver.delete_filter(f_path)
self.mox.VerifyAll() self.mox.VerifyAll()
def generate_random_ids(count=1):
if count == 1:
return uuidutils.generate_uuid()
else:
return [uuidutils.generate_uuid() for i in xrange(count)]
class TremaIdConvertTest(unittest.TestCase):
driver_name = 'trema'
def setUp(self):
self.driver = drivers.get_driver(self.driver_name)(TestConfig)
self.mox = mox.Mox()
self.ctx = self.mox.CreateMock(context.Context)
def tearDown(self):
self.mox.UnsetStubs()
def test_convert_tenant_id(self):
ofc_t_id = generate_random_ids(1)
ret = self.driver.convert_ofc_tenant_id(self.ctx, ofc_t_id)
self.assertEqual(ret, '/tenants/%s' % ofc_t_id)
def test_convert_tenant_id_noconv(self):
ofc_t_id = '/tenants/%s' % generate_random_ids(1)
ret = self.driver.convert_ofc_tenant_id(self.ctx, ofc_t_id)
self.assertEqual(ret, ofc_t_id)
def test_convert_network_id(self):
t_id, ofc_t_id, ofc_n_id = generate_random_ids(3)
ret = self.driver.convert_ofc_network_id(self.ctx, ofc_n_id, t_id)
self.assertEqual(ret, ('/networks/%s' % ofc_n_id))
def test_convert_network_id_noconv(self):
t_id = 'dummy'
ofc_t_id, ofc_n_id = generate_random_ids(2)
ofc_n_id = '/networks/%s' % ofc_n_id
ret = self.driver.convert_ofc_network_id(self.ctx, ofc_n_id, t_id)
def test_convert_filter_id(self):
ofc_f_id = generate_random_ids(1)
ret = self.driver.convert_ofc_filter_id(self.ctx, ofc_f_id)
self.assertEqual(ret, '/filters/%s' % ofc_f_id)
def test_convert_filter_id_noconv(self):
ofc_f_id = '/filters/%s' % generate_random_ids(1)
ret = self.driver.convert_ofc_filter_id(self.ctx, ofc_f_id)
self.assertEqual(ret, ofc_f_id)
class TremaIdConvertTestBase(object):
def setUp(self):
self.mox = mox.Mox()
self.driver = drivers.get_driver(self.driver_name)(TestConfig)
self.ctx = self.mox.CreateMock(context.Context)
self.ctx.session = "session"
self.mox.StubOutWithMock(ndb, 'get_ofc_id_lookup_both')
def tearDown(self):
self.mox.UnsetStubs()
def _test_convert_port_id(self, port_path_template):
t_id, n_id = generate_random_ids(2)
ofc_n_id, ofc_p_id = generate_random_ids(2)
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_network', n_id).AndReturn(ofc_n_id)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
exp = port_path_template % {'network': ofc_n_id, 'port': ofc_p_id}
self.assertEqual(ret, exp)
self.mox.VerifyAll()
def _test_convert_port_id_with_new_network_id(self, port_path_template):
t_id, n_id = generate_random_ids(2)
ofc_n_id, ofc_p_id = generate_random_ids(2)
ofc_n_path = '/networks/%s' % ofc_n_id
ndb.get_ofc_id_lookup_both(
self.ctx.session, 'ofc_network', n_id).AndReturn(ofc_n_path)
self.mox.ReplayAll()
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
exp = port_path_template % {'network': ofc_n_id, 'port': ofc_p_id}
print 'exp=', exp
print 'ret=', ret
self.assertEqual(ret, exp)
self.mox.VerifyAll()
def _test_convert_port_id_noconv(self, port_path_template):
t_id = n_id = 'dummy'
ofc_n_id, ofc_p_id = generate_random_ids(2)
ofc_p_id = port_path_template % {'network': ofc_n_id, 'port': ofc_p_id}
ret = self.driver.convert_ofc_port_id(self.ctx, ofc_p_id, t_id, n_id)
self.assertEqual(ret, ofc_p_id)
class TremaIdConvertPortBaseTest(TremaIdConvertTestBase, unittest.TestCase):
driver_name = "trema_port"
def test_convert_port_id(self):
self._test_convert_port_id('/networks/%(network)s/ports/%(port)s')
def test_convert_port_id_with_new_network_id(self):
self._test_convert_port_id_with_new_network_id(
'/networks/%(network)s/ports/%(port)s')
def test_convert_port_id_noconv(self):
self._test_convert_port_id_noconv(
'/networs/%(network)s/ports/%(port)s')
class TremaIdConvertPortMACBaseTest(TremaIdConvertTestBase, unittest.TestCase):
driver_name = "trema_portmac"
def test_convert_port_id(self):
self._test_convert_port_id(
'/networks/%(network)s/ports/dummy-%(port)s/attachments/%(port)s')
def test_convert_port_id_with_new_network_id(self):
self._test_convert_port_id_with_new_network_id(
'/networks/%(network)s/ports/dummy-%(port)s/attachments/%(port)s')
def test_convert_port_id_noconv(self):
self._test_convert_port_id_noconv(
'/networs/%(network)s/ports/dummy-%(port)s/attachments/%(port)s')
class TremaIdConvertMACBaseTest(TremaIdConvertTestBase, unittest.TestCase):
driver_name = "trema_mac"
def test_convert_port_id(self):
self._test_convert_port_id(
'/networks/%(network)s/attachments/%(port)s')
def test_convert_port_id_with_new_network_id(self):
self._test_convert_port_id_with_new_network_id(
'/networks/%(network)s/attachments/%(port)s')
def test_convert_port_id_noconv(self):
self._test_convert_port_id_noconv(
'/networs/%(network)s/attachments/%(port)s')