--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2011 Nicira Networks, Inc.
+# All Rights Reserved.
+#
+# 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.
+# @author: Somik Behera, Nicira Networks, Inc.
+# @author: Brad Hall, Nicira Networks, Inc.
+# @author: Dan Wendlandt, Nicira Networks, Inc.
+
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker, exc, joinedload
+
+from quantum.common import exceptions as q_exc
+from quantum.plugins.cisco.db import models
+
+_ENGINE = None
+_MAKER = None
+BASE = models.BASE
+
+
+def configure_db(options):
+ """
+ Establish the database, create an engine if needed, and
+ register the models.
+
+ :param options: Mapping of configuration options
+ """
+ global _ENGINE
+ if not _ENGINE:
+ _ENGINE = create_engine(options['sql_connection'],
+ echo=False,
+ echo_pool=True,
+ pool_recycle=3600)
+ register_models()
+
+
+def clear_db():
+ global _ENGINE
+ assert _ENGINE
+ for table in reversed(BASE.metadata.sorted_tables):
+ _ENGINE.execute(table.delete())
+
+
+def get_session(autocommit=True, expire_on_commit=False):
+ """Helper method to grab session"""
+ global _MAKER, _ENGINE
+ if not _MAKER:
+ assert _ENGINE
+ _MAKER = sessionmaker(bind=_ENGINE,
+ autocommit=autocommit,
+ expire_on_commit=expire_on_commit)
+ return _MAKER()
+
+
+def register_models():
+ """Register Models and create properties"""
+ global _ENGINE
+ assert _ENGINE
+ BASE.metadata.create_all(_ENGINE)
+
+
+def unregister_models():
+ """Unregister Models, useful clearing out data before testing"""
+ global _ENGINE
+ assert _ENGINE
+ BASE.metadata.drop_all(_ENGINE)
+
+
+def _check_duplicate_net_name(tenant_id, net_name):
+ session = get_session()
+ try:
+ net = session.query(models.Network).\
+ filter_by(tenant_id=tenant_id, name=net_name).\
+ one()
+ raise q_exc.NetworkNameExists(tenant_id=tenant_id,
+ net_name=net_name, net_id=net.uuid)
+ except exc.NoResultFound:
+ # this is the "normal" path, as API spec specifies
+ # that net-names are unique within a tenant
+ pass
+
+
+def network_create(tenant_id, name):
+ session = get_session()
+
+ _check_duplicate_net_name(tenant_id, name)
+ with session.begin():
+ net = models.Network(tenant_id, name)
+ session.add(net)
+ session.flush()
+ return net
+
+
+def network_list(tenant_id):
+ session = get_session()
+ return session.query(models.Network).\
+ options(joinedload(models.Network.ports)). \
+ filter_by(tenant_id=tenant_id).\
+ all()
+
+
+def network_get(net_id):
+ session = get_session()
+ try:
+ return session.query(models.Network).\
+ options(joinedload(models.Network.ports)). \
+ filter_by(uuid=net_id).\
+ one()
+ except exc.NoResultFound, e:
+ raise q_exc.NetworkNotFound(net_id=net_id)
+
+
+def network_rename(tenant_id, net_id, new_name):
+ session = get_session()
+ net = network_get(net_id)
+ _check_duplicate_net_name(tenant_id, new_name)
+ net.name = new_name
+ session.merge(net)
+ session.flush()
+ return net
+
+
+def network_destroy(net_id):
+ session = get_session()
+ try:
+ net = session.query(models.Network).\
+ filter_by(uuid=net_id).\
+ one()
+ session.delete(net)
+ session.flush()
+ return net
+ except exc.NoResultFound:
+ raise q_exc.NetworkNotFound(net_id=net_id)
+
+
+def port_create(net_id, state=None):
+ # confirm network exists
+ network_get(net_id)
+
+ session = get_session()
+ with session.begin():
+ port = models.Port(net_id)
+ port['state'] = state or 'DOWN'
+ session.add(port)
+ session.flush()
+ return port
+
+
+def port_list(net_id):
+ session = get_session()
+ return session.query(models.Port).\
+ options(joinedload(models.Port.network)). \
+ filter_by(network_id=net_id).\
+ all()
+
+
+def port_get(net_id, port_id):
+ # confirm network exists
+ network_get(net_id)
+ session = get_session()
+ try:
+ return session.query(models.Port).\
+ filter_by(uuid=port_id).\
+ filter_by(network_id=net_id).\
+ one()
+ except exc.NoResultFound:
+ raise q_exc.PortNotFound(net_id=net_id, port_id=port_id)
+
+
+def port_set_state(net_id, port_id, new_state):
+ if new_state not in ('ACTIVE', 'DOWN'):
+ raise q_exc.StateInvalid(port_state=new_state)
+
+ # confirm network exists
+ network_get(net_id)
+
+ port = port_get(net_id, port_id)
+ session = get_session()
+ port.state = new_state
+ session.merge(port)
+ session.flush()
+ return port
+
+
+def port_set_attachment(net_id, port_id, new_interface_id):
+ # confirm network exists
+ network_get(net_id)
+
+ session = get_session()
+ port = port_get(net_id, port_id)
+
+ if new_interface_id != "":
+ # We are setting, not clearing, the attachment-id
+ if port['interface_id']:
+ raise q_exc.PortInUse(net_id=net_id, port_id=port_id,
+ att_id=port['interface_id'])
+
+ try:
+ port = session.query(models.Port).\
+ filter_by(interface_id=new_interface_id).\
+ one()
+ raise q_exc.AlreadyAttached(net_id=net_id,
+ port_id=port_id,
+ att_id=new_interface_id,
+ att_port_id=port['uuid'])
+ except exc.NoResultFound:
+ # this is what should happen
+ pass
+ port.interface_id = new_interface_id
+ session.merge(port)
+ session.flush()
+ return port
+
+
+def port_unset_attachment(net_id, port_id):
+ # confirm network exists
+ network_get(net_id)
+
+ session = get_session()
+ port = port_get(net_id, port_id)
+ port.interface_id = None
+ session.merge(port)
+ session.flush()
+
+
+def port_destroy(net_id, port_id):
+ # confirm network exists
+ network_get(net_id)
+
+ session = get_session()
+ try:
+ port = session.query(models.Port).\
+ filter_by(uuid=port_id).\
+ filter_by(network_id=net_id).\
+ one()
+ if port['interface_id']:
+ raise q_exc.PortInUse(net_id=net_id, port_id=port_id,
+ att_id=port['interface_id'])
+ session.delete(port)
+ session.flush()
+ return port
+ except exc.NoResultFound:
+ raise q_exc.PortNotFound(port_id=port_id)
+
# under the License.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
+import ConfigParser
+from optparse import OptionParser
+import os
+import logging as LOG
+
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, exc, joinedload
-import l2network_models
-
-
-from quantum.common import exceptions as q_exc
-
-
-_ENGINE = None
-_MAKER = None
-BASE = l2network_models.BASE
-
-
-def configure_db(options):
- """
- Establish the database, create an engine if needed, and
- register the models.
-
- :param options: Mapping of configuration options
- """
- global _ENGINE
- if not _ENGINE:
- _ENGINE = create_engine(options['sql_connection'],
- echo=False,
- echo_pool=True,
- pool_recycle=3600)
- register_models()
-
-
-def clear_db():
- global _ENGINE
- assert _ENGINE
- for table in reversed(BASE.metadata.sorted_tables):
- _ENGINE.execute(table.delete())
-
-
-def get_session(autocommit=True, expire_on_commit=False):
- """Helper method to grab session"""
- global _MAKER, _ENGINE
- if not _MAKER:
- assert _ENGINE
- _MAKER = sessionmaker(bind=_ENGINE,
- autocommit=autocommit,
- expire_on_commit=expire_on_commit)
- return _MAKER()
-
-
-def register_models():
- """Register Models and create properties"""
- global _ENGINE
- assert _ENGINE
- BASE.metadata.create_all(_ENGINE)
-
-
-def unregister_models():
- """Unregister Models, useful clearing out data before testing"""
- global _ENGINE
- assert _ENGINE
- BASE.metadata.drop_all(_ENGINE)
-
-
-def _check_duplicate_net_name(tenant_id, net_name):
- session = get_session()
- try:
- net = session.query(l2network_models.Network).\
- filter_by(tenant_id=tenant_id, name=net_name).\
- one()
- raise q_exc.NetworkNameExists(tenant_id=tenant_id,
- net_name=net_name, net_id=net.uuid)
- except exc.NoResultFound:
- # this is the "normal" path, as API spec specifies
- # that net-names are unique within a tenant
- pass
-
-
-def network_create(tenant_id, name):
- session = get_session()
-
- _check_duplicate_net_name(tenant_id, name)
- with session.begin():
- net = l2network_models.Network(tenant_id, name)
- session.add(net)
- session.flush()
- return net
-
-
-def network_list(tenant_id):
- session = get_session()
- return session.query(l2network_models.Network).\
- options(joinedload(l2network_models.Network.ports)). \
- filter_by(tenant_id=tenant_id).\
- all()
-
-
-def network_get(net_id):
- session = get_session()
- try:
- return session.query(l2network_models.Network).\
- filter_by(uuid=net_id).\
- one()
- except exc.NoResultFound, e:
- raise q_exc.NetworkNotFound(net_id=net_id)
-
-
-def network_rename(net_id, tenant_id, new_name):
- session = get_session()
- net = network_get(net_id)
- _check_duplicate_net_name(tenant_id, new_name)
- net.name = new_name
- session.merge(net)
- session.flush()
- return net
+from quantum.plugins.cisco import l2network_plugin_configuration as conf
+import quantum.plugins.cisco.db.api as db
-def network_destroy(net_id):
- session = get_session()
- try:
- net = session.query(l2network_models.Network).\
- filter_by(uuid=net_id).\
- one()
- session.delete(net)
- session.flush()
- return net
- except exc.NoResultFound:
- raise q_exc.NetworkNotFound(net_id=net_id)
-
-
-def port_create(net_id, state=None):
- # confirm network exists
- network_get(net_id)
-
- session = get_session()
- with session.begin():
- port = l2network_models.Port(net_id)
- port['state'] = state or 'DOWN'
- session.add(port)
- session.flush()
- return port
-
-
-def port_list(net_id):
- session = get_session()
- return session.query(l2network_models.Port).\
- options(joinedload(l2network_models.Port.network)). \
- filter_by(network_id=net_id).\
- all()
+import l2network_models
-def port_get(port_id, net_id):
- # confirm network exists
- network_get(net_id)
- session = get_session()
+CONF_FILE = "db_conn.ini"
+
+
+def find_config(basepath):
+ for root, dirs, files in os.walk(basepath):
+ if CONF_FILE in files:
+ return os.path.join(root, CONF_FILE)
+ return None
+
+
+def initialize(configfile=None):
+ config = ConfigParser.ConfigParser()
+ if configfile == None:
+ if os.path.exists(CONF_FILE):
+ configfile = CONF_FILE
+ else:
+ configfile = \
+ find_config(os.path.abspath(os.path.dirname(__file__)))
+ if configfile == None:
+ raise Exception("Configuration file \"%s\" doesn't exist" %
+ (configfile))
+ LOG.debug("Using configuration file: %s" % configfile)
+ config.read(configfile)
+
+ DB_NAME = config.get("DATABASE", "name")
+ DB_USER = config.get("DATABASE", "user")
+ DB_PASS = config.get("DATABASE", "pass")
+ DB_HOST = config.get("DATABASE", "host")
+ options = {"sql_connection": "mysql://%s:%s@%s/%s" % (DB_USER,
+ DB_PASS, DB_HOST, DB_NAME)}
+ db.configure_db(options)
+
+def prepopulate_vlan_bindings():
+ """Prepopulates the vlan_bindings table"""
+ session = db.get_session()
try:
- return session.query(l2network_models.Port).\
- filter_by(uuid=port_id).\
- filter_by(network_id=net_id).\
- one()
+ binding = session.query(l2network_models.VlanBinding).\
+ all()
+ raise Exception("Vlan table not empty id for prepopulation")
except exc.NoResultFound:
- raise q_exc.PortNotFound(net_id=net_id, port_id=port_id)
-
-
-def port_set_state(port_id, net_id, new_state):
- if new_state not in ('ACTIVE', 'DOWN'):
- raise q_exc.StateInvalid(port_state=new_state)
-
- # confirm network exists
- network_get(net_id)
-
- port = port_get(port_id, net_id)
- session = get_session()
- port.state = new_state
- session.merge(port)
- session.flush()
- return port
-
-
-def port_set_attachment(port_id, net_id, new_interface_id):
- # confirm network exists
- network_get(net_id)
-
- session = get_session()
- port = port_get(port_id, net_id)
-
- if new_interface_id != "":
- # We are setting, not clearing, the attachment-id
- if port['interface_id']:
- raise q_exc.PortInUse(net_id=net_id, port_id=port_id,
- att_id=port['interface_id'])
-
- try:
- port = session.query(l2network_models.Port).\
- filter_by(interface_id=new_interface_id).\
- one()
- raise q_exc.AlreadyAttached(net_id=net_id,
- port_id=port_id,
- att_id=new_interface_id,
- att_port_id=port['uuid'])
- except exc.NoResultFound:
- # this is what should happen
- pass
- port.interface_id = new_interface_id
- session.merge(port)
- session.flush()
- return port
-
-
-def port_unset_attachment(port_id, net_id):
- # confirm network exists
- network_get(net_id)
-
- session = get_session()
- port = port_get(port_id, net_id)
- port.interface_id = None
- session.merge(port)
- session.flush()
-
-
-def port_destroy(port_id, net_id):
- # confirm network exists
- network_get(net_id)
-
- session = get_session()
- try:
- port = session.query(l2network_models.Port).\
- filter_by(uuid=port_id).\
- filter_by(network_id=net_id).\
- one()
- if port['interface_id']:
- raise q_exc.PortInUse(net_id=net_id, port_id=port_id,
- att_id=port['interface_id'])
- session.delete(port)
+ start = conf.VLAN_START
+ end = conf.VLAN_END
+ while start < end:
+ binding = l2network_models.VlanBinding(vlanid, "", 0)
+ session.add(binding)
session.flush()
- return port
- except exc.NoResultFound:
- raise q_exc.PortNotFound(port_id=port_id)
-
+ return
def get_all_vlan_bindings():
"""Lists all the vlan to network associations"""
- session = get_session()
+ session = db.get_session()
try:
bindings = session.query(l2network_models.VlanBinding).\
all()
def get_vlan_binding(netid):
"""Lists the vlan given a network_id"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
def add_vlan_binding(vlanid, vlanname, netid):
"""Adds a vlan to network association"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(vlan_id=vlanid).\
def remove_vlan_binding(netid):
"""Removes a vlan to network association"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
def update_vlan_binding(netid, newvlanid=None, newvlanname=None):
"""Updates a vlan to network association"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
def get_all_portprofiles():
"""Lists all the port profiles"""
- session = get_session()
+ session = db.get_session()
try:
pps = session.query(l2network_models.PortProfile).\
all()
def get_portprofile(ppid):
"""Lists a port profile"""
- session = get_session()
+ session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
def add_portprofile(ppname, vlanid, qos):
"""Adds a port profile"""
- session = get_session()
+ session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(name=ppname).\
def remove_portprofile(ppid):
"""Removes a port profile"""
- session = get_session()
+ session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
def update_portprofile(ppid, newppname=None, newvlanid=None, newqos=None):
"""Updates port profile"""
- session = get_session()
+ session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
def get_all_pp_bindings():
"""Lists all the port profiles"""
- session = get_session()
+ session = db.get_session()
try:
bindings = session.query(l2network_models.PortProfileBinding).\
all()
def get_pp_binding(ppid):
"""Lists a port profile binding"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
def add_pp_binding(tenantid, networkid, ppid, default):
"""Adds a port profile binding"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
def remove_pp_binding(ppid):
"""Removes a port profile binding"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
def update_pp_binding(ppid, newtenantid=None, newnetworkid=None, \
newdefault=None):
"""Updates port profile binding"""
- session = get_session()
+ session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, object_mapper
-BASE = declarative_base()
+from quantum.plugins.cisco.db.models import BASE
+from quantum.plugins.cisco.db import models
class L2NetworkBase(object):
return local.iteritems()
-class Port(BASE, L2NetworkBase):
- """Represents a port on a l2network plugin"""
- __tablename__ = 'ports'
-
- uuid = Column(String(255), primary_key=True)
- network_id = Column(String(255), ForeignKey("networks.uuid"),
- nullable=False)
- interface_id = Column(String(255))
- state = Column(String(8))
-
- def __init__(self, network_id):
- self.uuid = str(uuid.uuid4())
- self.network_id = network_id
- self.state = "DOWN"
-
- def __repr__(self):
- return "<Port(%s,%s,%s,%s)>" % (self.uuid, self.network_id,
- self.state, self.interface_id)
-
-
-class Network(BASE, L2NetworkBase):
- """Represents a networ on l2network plugin"""
- __tablename__ = 'networks'
-
- uuid = Column(String(255), primary_key=True)
- tenant_id = Column(String(255), nullable=False)
- name = Column(String(255))
- ports = relation(Port, order_by=Port.uuid, backref="network")
-
- def __init__(self, tenant_id, name):
- self.uuid = str(uuid.uuid4())
- self.tenant_id = tenant_id
- self.name = name
-
- def __repr__(self):
- return "<Network(%s,%s,%s)>" % \
- (self.uuid, self.name, self.tenant_id)
-
-
class VlanBinding(BASE, L2NetworkBase):
"""Represents a binding of vlan_id to network_id"""
__tablename__ = 'vlan_bindings'
vlan_name = Column(String(255))
network_id = Column(String(255), ForeignKey("networks.uuid"), \
nullable=False)
- network = relation(Network, uselist=False)
+ network = relation(models.Network, uselist=False)
def __init__(self, vlan_id, vlan_name, network_id):
self.vlan_id = vlan_id
portprofile_id = Column(String(255), ForeignKey("portprofiles.uuid"), \
nullable=False)
default = Column(Boolean)
- network = relation(Network, uselist=False)
+ network = relation(models.Network, uselist=False)
portprofile = relation(PortProfile, uselist=False)
def __init__(self, tenant_id, network_id, portprofile_id, default):
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2011 Nicira Networks, Inc.
+# All Rights Reserved.
+#
+# 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.
+# @author: Somik Behera, Nicira Networks, Inc.
+# @author: Brad Hall, Nicira Networks, Inc.
+# @author: Dan Wendlandt, Nicira Networks, Inc.
+
+import uuid
+
+from sqlalchemy import Column, String, ForeignKey
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import relation, object_mapper
+
+BASE = declarative_base()
+
+
+class QuantumBase(object):
+ """Base class for Quantum Models."""
+ __table_args__ = {'mysql_engine': 'InnoDB'}
+
+ def __setitem__(self, key, value):
+ setattr(self, key, value)
+
+ def __getitem__(self, key):
+ return getattr(self, key)
+
+ def get(self, key, default=None):
+ return getattr(self, key, default)
+
+ def __iter__(self):
+ self._i = iter(object_mapper(self).columns)
+ return self
+
+ def next(self):
+ n = self._i.next().name
+ return n, getattr(self, n)
+
+ def update(self, values):
+ """Make the model object behave like a dict"""
+ for k, v in values.iteritems():
+ setattr(self, k, v)
+
+ def iteritems(self):
+ """Make the model object behave like a dict.
+ Includes attributes from joins."""
+ local = dict(self)
+ joined = dict([(k, v) for k, v in self.__dict__.iteritems()
+ if not k[0] == '_'])
+ local.update(joined)
+ return local.iteritems()
+
+
+class Port(BASE, QuantumBase):
+ """Represents a port on a quantum network"""
+ __tablename__ = 'ports'
+
+ uuid = Column(String(255), primary_key=True)
+ network_id = Column(String(255), ForeignKey("networks.uuid"),
+ nullable=False)
+ interface_id = Column(String(255))
+ # Port state - Hardcoding string value at the moment
+ state = Column(String(8))
+
+ def __init__(self, network_id):
+ self.uuid = str(uuid.uuid4())
+ self.network_id = network_id
+ self.state = "DOWN"
+
+ def __repr__(self):
+ return "<Port(%s,%s,%s,%s)>" % (self.uuid, self.network_id,
+ self.state, self.interface_id)
+
+
+class Network(BASE, QuantumBase):
+ """Represents a quantum network"""
+ __tablename__ = 'networks'
+
+ uuid = Column(String(255), primary_key=True)
+ tenant_id = Column(String(255), nullable=False)
+ name = Column(String(255))
+ ports = relation(Port, order_by=Port.uuid, backref="network")
+
+ def __init__(self, tenant_id, name):
+ self.uuid = str(uuid.uuid4())
+ self.tenant_id = tenant_id
+ self.name = name
+
+ def __repr__(self):
+ return "<Network(%s,%s,%s)>" % \
+ (self.uuid, self.name, self.tenant_id)