persistence of l2network & ucs plugins using mysql

- db_conn.ini - configuration details of making a connection to the database
- db_test_plugin.py - contains abstraction methods for storing database values in a dict and unit test cases for DB testing
- l2network_db.py - db methods for l2network models
- l2network_models.py - class definitions for the l2 network tables
- ucs_db.py - db methods for ucs models
- ucs_models.py - class definition for the ucs tables 
dynamic loading of the 2nd layer plugin db's based on passed arguments 
Create, Delete, Get, Getall, Update database methods at - Quantum, L2Network and Ucs
Unit test cases for create, delete, getall and update operations for L2Network and Ucs plugins
pep8 checks done
branch based off revision 34 plugin-framework

changes after review comments - 
merged the latest changes from plugin-framework branch - revision 39
confirming to the new directory structure and moving all db related modules into cisco/db folder
updated db_test_plugin.py 
 - added import of cisco constants module 
 - added getLogger to LOG for logging component name   
 - updated import module paths for l2network_models/db and ucs_models/db to use the new directory structure
 - updated (rearranged) imports section to obey openstack alphabetical placement convention
updated db_conn.ini 
 - updated database name from cisco_naas to quantum_l2network
unit test cases ran successfully and pep8 checks done again


-------------s This line and the following will be ignored --------------

added:
  quantum/plugins/cisco/db/db_conn.ini
  quantum/plugins/cisco/db/db_test_plugin.py
  quantum/plugins/cisco/db/l2network_db.py
  quantum/plugins/cisco/db/l2network_models.py
  quantum/plugins/cisco/db/ucs_db.py
  quantum/plugins/cisco/db/ucs_models.py
modified:
  quantum/plugins/cisco/README
pending merges:
  rohitagarwalla 2011-07-31 [merge] merged the latest changes from plugin-framework branch - revision 39
    rohitagarwalla 2011-07-29 persistence of l2network & ucs plugins using mysql
This commit is contained in:
rohitagarwalla 2011-07-31 23:46:15 -07:00
commit c1e123de81
7 changed files with 1814 additions and 0 deletions

View File

@ -76,3 +76,11 @@ mysql -uroot -p<mysql_password_here> nova -e 'create table ports (port_id VARCHA
/usr/lib/python2.6/site-packages/nova/virt/cisco_ucs.py
* Restart nova-compute service
**L2network database usage requirements -
* mysql database "quantum_l2network" is required for persistence of the l2network plugin data.
+ The database can be created as follows -
- # mysql -uroot -pnova; (username/password here is root/nova)
- mysql> create database quantum_l2network;
- mysql> use quantum_l2network;
+ The database and login details must be specified in quantum/plugins/cisco/db/db_conn.ini.

View File

@ -0,0 +1,5 @@
[DATABASE]
name = quantum_l2network
user = root
pass = nova
host = 127.0.0.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,239 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
from sqlalchemy.orm import exc
import l2network_models
import quantum.db.api as db
import quantum.db.models as models
def get_all_vlan_bindings():
"""Lists all the vlan to network associations"""
session = db.get_session()
try:
bindings = session.query(l2network_models.VlanBinding).\
all()
return bindings
except exc.NoResultFound:
return []
def get_vlan_binding(netid):
"""Lists the vlan given a network_id"""
session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
one()
return binding
except exc.NoResultFound:
raise Exception("No network found with net-id = %s" % network_id)
def add_vlan_binding(vlanid, vlanname, netid):
"""Adds a vlan to network association"""
session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(vlan_id=vlanid).\
one()
raise Exception("Vlan with id \"%s\" already exists" % vlanid)
except exc.NoResultFound:
binding = l2network_models.VlanBinding(vlanid, vlanname, netid)
session.add(binding)
session.flush()
return binding
def remove_vlan_binding(netid):
"""Removes a vlan to network association"""
session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
one()
session.delete(binding)
session.flush()
return binding
except exc.NoResultFound:
pass
def update_vlan_binding(netid, newvlanid=None, newvlanname=None):
"""Updates a vlan to network association"""
session = db.get_session()
try:
binding = session.query(l2network_models.VlanBinding).\
filter_by(network_id=netid).\
one()
if newvlanid:
binding.vlan_id = newvlanid
if newvlanname:
binding.vlan_name = newvlanname
session.merge(binding)
session.flush()
return binding
except exc.NoResultFound:
raise Exception("No vlan binding found with network_id = %s" % netid)
def get_all_portprofiles():
"""Lists all the port profiles"""
session = db.get_session()
try:
pps = session.query(l2network_models.PortProfile).\
all()
return pps
except exc.NoResultFound:
return []
def get_portprofile(ppid):
"""Lists a port profile"""
session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
one()
return pp
except exc.NoResultFound:
raise Exception("No portprofile found with id = %s" % ppid)
def add_portprofile(ppname, vlanid, qos):
"""Adds a port profile"""
session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(name=ppname).\
one()
raise Exception("Port profile with name %s already exists" % ppname)
except exc.NoResultFound:
pp = l2network_models.PortProfile(ppname, vlanid, qos)
session.add(pp)
session.flush()
return pp
def remove_portprofile(ppid):
"""Removes a port profile"""
session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
one()
session.delete(pp)
session.flush()
return pp
except exc.NoResultFound:
pass
def update_portprofile(ppid, newppname=None, newvlanid=None, newqos=None):
"""Updates port profile"""
session = db.get_session()
try:
pp = session.query(l2network_models.PortProfile).\
filter_by(uuid=ppid).\
one()
if newppname:
pp.name = newppname
if newvlanid:
pp.vlan_id = newvlanid
if newqos:
pp.qos = newqos
session.merge(pp)
session.flush()
return pp
except exc.NoResultFound:
raise Exception("No port profile with id = %s" % ppid)
def get_all_pp_bindings():
"""Lists all the port profiles"""
session = db.get_session()
try:
bindings = session.query(l2network_models.PortProfileBinding).\
all()
return bindings
except exc.NoResultFound:
return []
def get_pp_binding(ppid):
"""Lists a port profile binding"""
session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
one()
return binding
except exc.NoResultFound:
raise Exception("No portprofile binding found with id = %s" % ppid)
def add_pp_binding(tenantid, networkid, ppid, default):
"""Adds a port profile binding"""
session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
one()
raise Exception("Port profile binding with id \"%s\" already \
exists" % ppid)
except exc.NoResultFound:
binding = l2network_models.PortProfileBinding(tenantid, networkid, \
ppid, default)
session.add(binding)
session.flush()
return binding
def remove_pp_binding(ppid):
"""Removes a port profile binding"""
session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
one()
session.delete(binding)
session.flush()
return binding
except exc.NoResultFound:
pass
def update_pp_binding(ppid, newtenantid=None, newnetworkid=None, \
newdefault=None):
"""Updates port profile binding"""
session = db.get_session()
try:
binding = session.query(l2network_models.PortProfileBinding).\
filter_by(portprofile_id=ppid).\
one()
if newtenantid:
binding.tenant_id = newtenantid
if newnetworkid:
binding.network_id = newnetworkid
if newdefault:
binding.default = newdefault
session.merge(binding)
session.flush()
return binding
except exc.NoResultFound:
raise Exception("No port profile binding with id = %s" % ppid)

View File

@ -0,0 +1,86 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
import uuid
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
from sqlalchemy.orm import relation
from quantum.db.models import BASE
class VlanBinding(BASE):
"""Represents a binding of vlan_id to network_id"""
__tablename__ = 'vlan_bindings'
vlan_id = Column(Integer, primary_key=True)
vlan_name = Column(String(255))
network_id = Column(String(255), nullable=False)
#foreign key to networks.uuid
def __init__(self, vlan_id, vlan_name, network_id):
self.vlan_id = vlan_id
self.vlan_name = vlan_name
self.network_id = network_id
def __repr__(self):
return "<VlanBinding(%d,%s,%s)>" % \
(self.vlan_id, self.vlan_name, self.network_id)
class PortProfile(BASE):
"""Represents Cisco plugin level PortProfile for a network"""
__tablename__ = 'portprofiles'
uuid = Column(String(255), primary_key=True)
name = Column(String(255))
vlan_id = Column(Integer)
qos = Column(String(255))
def __init__(self, name, vlan_id, qos=None):
self.uuid = uuid.uuid4()
self.name = name
self.vlan_id = vlan_id
self.qos = qos
def __repr__(self):
return "<PortProfile(%s,%s,%d,%s)>" % \
(self.uuid, self.name, self.vlan_id, self.qos)
class PortProfileBinding(BASE):
"""Represents PortProfile binding to tenant and network"""
__tablename__ = 'portprofile_bindings'
id = Column(Integer, primary_key=True, autoincrement=True)
tenant_id = Column(String(255))
network_id = Column(String(255), nullable=False)
#foreign key to networks.uuid
portprofile_id = Column(String(255), nullable=False)
#foreign key to portprofiles.uuid
default = Column(Boolean)
def __init__(self, tenant_id, network_id, portprofile_id, default):
self.tenant_id = tenant_id
self.network_id = network_id
self.portprofile_id = portprofile_id
self.default = default
def __repr__(self):
return "<PortProfile Binding(%s,%s,%s,%s)>" % \
(self.tenant_id, self.network_id, self.portprofile_id, self.default)

View File

@ -0,0 +1,314 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
from sqlalchemy.orm import exc
import quantum.db.api as db
import ucs_models
def get_all_ucsmbinding():
"""Lists all the ucsm bindings"""
session = db.get_session()
try:
bindings = session.query(ucs_models.UcsmBinding).\
all()
return bindings
except exc.NoResultFound:
return []
def get_ucsmbinding(ucsm_ip):
"""Lists a ucsm binding"""
session = db.get_session()
try:
binding = session.query(ucs_models.UcsmBinding).\
filter_by(ucsm_ip=ucsm_ip).\
one()
return binding
except exc.NoResultFound:
raise Exception("No binding found with ip = %s" % ucsm_ip)
def add_ucsmbinding(ucsm_ip, network_id):
"""Adds a ucsm binding"""
session = db.get_session()
try:
ip = session.query(ucs_models.UcsmBinding).\
filter_by(ucsm_ip=ucsm_ip).\
one()
raise Exception("Binding with ucsm ip \"%s\" already exists" % ucsm_ip)
except exc.NoResultFound:
binding = ucs_models.UcsmBinding(ucsm_ip, network_id)
session.add(binding)
session.flush()
return binding
def remove_ucsmbinding(ucsm_ip):
"""Removes a ucsm binding"""
session = db.get_session()
try:
binding = session.query(ucs_models.UcsmBinding).\
filter_by(ucsm_ip=ucsm_ip).\
one()
session.delete(binding)
session.flush()
return binding
except exc.NoResultFound:
pass
def update_ucsmbinding(ucsm_ip, new_network_id):
"""Updates ucsm binding"""
session = db.get_session()
try:
binding = session.query(ucs_models.UcsmBinding).\
filter_by(ucsm_ip=ucsm_ip).\
one()
if new_network_id:
binding.network_id = new_network_id
session.merge(binding)
session.flush()
return binding
except exc.NoResultFound:
raise Exception("No binding with ip = %s" % ucsm_ip)
def get_all_dynamicvnics():
"""Lists all the dynamic vnics"""
session = db.get_session()
try:
vnics = session.query(ucs_models.DynamicVnic).\
all()
return vnics
except exc.NoResultFound:
return []
def get_dynamicvnic(vnic_id):
"""Lists a dynamic vnic"""
session = db.get_session()
try:
vnic = session.query(ucs_models.DynamicVnic).\
filter_by(uuid=vnic_id).\
one()
return vnic
except exc.NoResultFound:
raise Exception("No dynamic vnic found with id = %s" % vnic_id)
def add_dynamicvnic(device_name, blade_id):
"""Adds a dynamic vnic"""
session = db.get_session()
try:
name = session.query(ucs_models.DynamicVnic).\
filter_by(device_name=device_name).\
one()
raise Exception("Dynamic vnic with device name %s already exists" % \
device_name)
except exc.NoResultFound:
vnic = ucs_models.DynamicVnic(device_name, blade_id)
session.add(vnic)
session.flush()
return vnic
def remove_dynamicvnic(vnic_id):
"""Removes a dynamic vnic"""
session = db.get_session()
try:
vnic = session.query(ucs_models.DynamicVnic).\
filter_by(uuid=vnic_id).\
one()
session.delete(vnic)
session.flush()
return vnic
except exc.NoResultFound:
pass
def update_dynamicvnic(vnic_id, new_device_name=None, new_blade_id=None):
"""Updates dynamic vnic"""
session = db.get_session()
try:
vnic = session.query(ucs_models.DynamicVnic).\
filter_by(uuid=vnic_id).\
one()
if new_device_name:
vnic.device_name = new_device_name
if new_blade_id:
vnic.blade_id = new_blade_id
session.merge(vnic)
session.flush()
return vnic
except exc.NoResultFound:
raise Exception("No dynamic vnic with id = %s" % vnic_id)
def get_all_blades():
"""Lists all the blades details"""
session = db.get_session()
try:
blades = session.query(ucs_models.UcsBlade).\
all()
return blades
except exc.NoResultFound:
return []
def get_blade(blade_id):
"""Lists a blade details"""
session = db.get_session()
try:
blade = session.query(ucs_models.UcsBlade).\
filter_by(uuid=blade_id).\
one()
return blade
except exc.NoResultFound:
raise Exception("No blade found with id = %s" % blade_id)
def add_blade(mgmt_ip, mac_addr, chassis_id, ucsm_ip):
"""Adds a blade"""
session = db.get_session()
try:
ip = session.query(ucs_models.UcsBlade).\
filter_by(mgmt_ip=mgmt_ip).\
one()
raise Exception("Blade with ip \"%s\" already exists" % mgmt_ip)
except exc.NoResultFound:
blade = ucs_models.UcsBlade(mgmt_ip, mac_addr, chassis_id, ucsm_ip)
session.add(blade)
session.flush()
return blade
def remove_blade(blade_id):
"""Removes a blade"""
session = db.get_session()
try:
blade = session.query(ucs_models.UcsBlade).\
filter_by(uuid=blade_id).\
one()
session.delete(blade)
session.flush()
return blade
except exc.NoResultFound:
pass
def update_blade(blade_id, new_mgmt_ip=None, new_mac_addr=None, \
new_chassis_id=None, new_ucsm_ip=None):
"""Updates details of a blade"""
session = db.get_session()
try:
blade = session.query(ucs_models.UcsBlade).\
filter_by(uuid=blade_id).\
one()
if new_mgmt_ip:
blade.mgmt_ip = new_mgmt_ip
if new_mac_addr:
blade.mac_addr = new_mac_addr
if new_chassis_id:
blade.chassis_id = new_chassis_id
if new_ucsm_ip:
blade.ucsm_ip = new_ucsm_ip
session.merge(blade)
session.flush()
return blade
except exc.NoResultFound:
raise Exception("No blade with id = %s" % blade_id)
def get_all_portbindings():
"""Lists all the port bindings"""
session = db.get_session()
try:
port_bindings = session.query(ucs_models.PortBinding).\
all()
return port_bindings
except exc.NoResultFound:
return []
def get_portbinding(port_id):
"""Lists a port binding"""
session = db.get_session()
try:
port_binding = session.query(ucs_models.PortBinding).\
filter_by(port_id=port_id).\
one()
return port_binding
except exc.NoResultFound:
raise Exception("No port binding found with port id = %s" % port_id)
def add_portbinding(port_id, dynamic_vnic_id, portprofile_name, \
vlan_name, vlan_id, qos):
"""Adds a port binding"""
session = db.get_session()
try:
port_binding = session.query(ucs_models.PortBinding).\
filter_by(port_id=port_id).\
one()
raise Exception("Port Binding with portid %s already exists" % port_id)
except exc.NoResultFound:
port_binding = ucs_models.PortBinding(port_id, dynamic_vnic_id, \
portprofile_name, vlan_name, vlan_id, qos)
session.add(port_binding)
session.flush()
return port_binding
def remove_portbinding(port_id):
"""Removes a port binding"""
session = db.get_session()
try:
port_binding = session.query(ucs_models.PortBinding).\
filter_by(port_id=port_id).\
one()
session.delete(port_binding)
session.flush()
return port_binding
except exc.NoResultFound:
pass
def update_portbinding(port_id, dynamic_vnic_id=None, portprofile_name=None, \
vlan_name=None, vlan_id=None, qos=None):
"""Updates port binding"""
session = db.get_session()
try:
port_binding = session.query(ucs_models.PortBinding).\
filter_by(port_id=port_id).\
one()
if dynamic_vnic_id:
port_binding.dynamic_vnic_id = dynamic_vnic_id
if portprofile_name:
port_binding.portprofile_name = portprofile_name
if vlan_name:
port_binding.vlan_name = vlan_name
if vlan_name:
port_binding.vlan_id = vlan_id
if qos:
port_binding.qos = qos
session.merge(port_binding)
session.flush()
return port_binding
except exc.NoResultFound:
raise Exception("No port binding with port id = %s" % port_id)

View File

@ -0,0 +1,113 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011, Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
import uuid
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
from sqlalchemy.orm import relation
from quantum.db.models import BASE
class UcsmBinding(BASE):
"""Represents a binding of ucsm to network_id"""
__tablename__ = 'ucsm_bindings'
id = Column(Integer, primary_key=True, autoincrement=True)
ucsm_ip = Column(String(255))
network_id = Column(String(255), nullable=False)
#foreign key to networks.uuid
def __init__(self, ucsm_ip, network_id):
self.ucsm_ip = ucsm_ip
self.network_id = network_id
def __repr__(self):
return "<UcsmBinding(%s,%s)>" % \
(self.ucsm_ip, self.network_id)
class DynamicVnic(BASE):
"""Represents Cisco UCS Dynamic Vnics"""
__tablename__ = 'dynamic_vnics'
uuid = Column(String(255), primary_key=True)
device_name = Column(String(255))
blade_id = Column(String(255), ForeignKey("ucs_blades.uuid"), \
nullable=False)
def __init__(self, device_name, blade_id):
self.uuid = uuid.uuid4()
self.device_name = device_name
self.blade_id = blade_id
def __repr__(self):
return "<Dyanmic Vnic(%s,%s,%s)>" % \
(self.uuid, self.device_name, self.blade_id)
class UcsBlade(BASE):
"""Represents details of ucs blades"""
__tablename__ = 'ucs_blades'
uuid = Column(String(255), primary_key=True)
mgmt_ip = Column(String(255))
mac_addr = Column(String(255))
chassis_id = Column(String(255))
ucsm_ip = Column(String(255))
dynamic_vnics = relation(DynamicVnic, order_by=DynamicVnic.uuid, \
backref="blade")
def __init__(self, mgmt_ip, mac_addr, chassis_id, ucsm_ip):
self.uuid = uuid.uuid4()
self.mgmt_ip = mgmt_ip
self.mac_addr = mac_addr
self.chassis_id = chassis_id
self.ucsm_ip = ucsm_ip
def __repr__(self):
return "<UcsBlades (%s,%s,%s,%s,%s)>" % \
(self.uuid, self.mgmt_ip, self.mac_addr, self.chassis_id, self.ucsm_ip)
class PortBinding(BASE):
"""Represents Port binding to device interface"""
__tablename__ = 'port_bindings'
id = Column(Integer, primary_key=True, autoincrement=True)
port_id = Column(String(255), nullable=False)
#foreign key to ports.uuid
dynamic_vnic_id = Column(String(255), nullable=False)
#foreign key to dynamic_vnics.uuid
portprofile_name = Column(String(255))
vlan_name = Column(String(255))
vlan_id = Column(Integer)
qos = Column(String(255))
def __init__(self, port_id, dynamic_vnic_id, portprofile_name, vlan_name, \
vlan_id, qos):
self.port_id = port_id
self.dynamic_vnic_id = dynamic_vnic_id
self.portprofile_name = portprofile_name
self.vlan_name = vlan_name
self.vlan_id = vlan_id
self.qos = qos
def __repr__(self):
return "<PortProfile Binding(%s,%s,%s,%s,%s,%s)>" % \
(self.port_id, self.dynamic_vnic_id, self.portprofile_name, \
self.vlan_name, self.vlan_id, self.qos)