diff --git a/quantum/db/__init__.py b/quantum/db/__init__.py new file mode 100644 index 000000000..620282b58 --- /dev/null +++ b/quantum/db/__init__.py @@ -0,0 +1,17 @@ +# 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. diff --git a/quantum/db/api.py b/quantum/db/api.py new file mode 100644 index 000000000..7ae5a2625 --- /dev/null +++ b/quantum/db/api.py @@ -0,0 +1,166 @@ +# 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 +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=True, + echo_pool=True, + pool_recycle=3600) + register_models() + +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 network_create(tenant_id, name): + session = get_session() + net = None + try: + net = session.query(models.Network).\ + filter_by(name=name).\ + one() + raise Exception("Network with name \"%s\" already exists" % name) + except exc.NoResultFound: + 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).\ + filter_by(tenant_id=tenant_id).\ + all() + +def network_get(net_id): + session = get_session() + try: + return session.query(models.Network).\ + filter_by(uuid=net_id).\ + one() + except exc.NoResultFound: + raise Exception("No net found with id = %s" % net_id) + +def network_rename(net_id, tenant_id, new_name): + session = get_session() + # TODO(bgh): Make sure another network doesn't have that name + try: + res = session.query(models.Network).\ + filter_by(name=new_name).\ + one() + except exc.NoResultFound: + net = network_get(net_id) + net.name = new_name + session.merge(net) + session.flush() + return net + raise Exception("A network with name \"%s\" already exists" % new_name) + +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 Exception("No network found with id = %s" % net_id) + +def port_create(net_id): + session = get_session() + with session.begin(): + port = models.Port(net_id) + session.add(port) + session.flush() + return port + +def port_list(net_id): + session = get_session() + return session.query(models.Port).\ + filter_by(network_id=net_id).\ + all() + +def port_get(port_id): + session = get_session() + try: + return session.query(models.Port).\ + filter_by(uuid=port_id).\ + one() + except exc.NoResultFound: + raise Exception("No port found with id = %s " % port_id) + +def port_set_attachment(port_id, new_interface_id): + session = get_session() + # TODO(bgh): check to make sure new_inteface_id is + # unique if it is not None + port = port_get(port_id) + port.interface_id = new_interface_id + session.merge(port) + session.flush() + return port + +def port_destroy(port_id): + session = get_session() + try: + port = session.query(models.Port).\ + filter_by(uuid=port_id).\ + one() + session.delete(port) + session.flush() + return port + except exc.NoResultFound: + raise Exception("No port found with id = %s " % port_id) + diff --git a/quantum/db/models.py b/quantum/db/models.py new file mode 100644 index 000000000..28bc139b9 --- /dev/null +++ b/quantum/db/models.py @@ -0,0 +1,59 @@ +# 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, Integer, String, ForeignKey +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relation + +BASE = declarative_base() + +class Port(BASE): + """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)) + + def __init__(self, network_id): + self.uuid = uuid.uuid4() + self.network_id = network_id + + def __repr__(self): + return "" % (self.uuid, self.network_id, self.interface_id) + +class Network(BASE): + """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 = uuid.uuid4() + self.tenant_id = tenant_id + self.name = name + + def __repr__(self): + return "" % \ + (self.uuid,self.name,self.tenant_id)