
blueprint lb-api-v2-support Plugin support for the linuxbridge using the v2 API 1. The core_plugin in quantum.conf must be set to: quantum.plugins.linuxbridge.LinuxBridgePluginV2.LinuxBridgePluginV2 2. By default the agent is v2. A configuration file entry 'target_v2_api' in the section 'AGENT' can be set as False to support v1. Change-Id: I2e196859c13b28e535c6ec394ec3f5bc907bf019
257 lines
8.1 KiB
Python
257 lines
8.1 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2012, 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 logging
|
|
|
|
from sqlalchemy import func
|
|
from sqlalchemy.orm import exc
|
|
|
|
from quantum.common import exceptions as q_exc
|
|
from quantum.common.utils import find_config_file
|
|
import quantum.db.api as db
|
|
from quantum.plugins.linuxbridge.common import config
|
|
from quantum.plugins.linuxbridge.common import exceptions as c_exc
|
|
from quantum.plugins.linuxbridge.db import l2network_models
|
|
from quantum.plugins.linuxbridge.db import l2network_models_v2
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
CONF_FILE = find_config_file({'plugin': 'linuxbridge'},
|
|
"linuxbridge_conf.ini")
|
|
CONF = config.parse(CONF_FILE)
|
|
|
|
# The global variable for the database version model
|
|
L2_MODEL = l2network_models
|
|
|
|
|
|
def initialize(base=None):
|
|
global L2_MODEL
|
|
options = {"sql_connection": "%s" % CONF.DATABASE.sql_connection}
|
|
options.update({"reconnect_interval": CONF.DATABASE.reconnect_interval})
|
|
if base:
|
|
options.update({"base": base})
|
|
L2_MODEL = l2network_models_v2
|
|
db.configure_db(options)
|
|
create_vlanids()
|
|
|
|
|
|
def create_vlanids():
|
|
"""Prepopulates the vlan_bindings table"""
|
|
LOG.debug("create_vlanids() called")
|
|
session = db.get_session()
|
|
start = CONF.VLANS.vlan_start
|
|
end = CONF.VLANS.vlan_end
|
|
try:
|
|
vlanid = session.query(L2_MODEL.VlanID).one()
|
|
except exc.MultipleResultsFound:
|
|
"""
|
|
TODO (Sumit): Salvatore rightly points out that this will not handle
|
|
change in VLAN ID range across server reboots. This is currently not
|
|
a supported feature. This logic will need to change if this feature
|
|
has to be supported.
|
|
Per Dan's suggestion we just throw a server exception for now.
|
|
"""
|
|
current_start = (
|
|
int(session.query(func.min(L2_MODEL.VlanID.vlan_id)).
|
|
one()[0]))
|
|
current_end = (
|
|
int(session.query(func.max(L2_MODEL.VlanID.vlan_id)).
|
|
one()[0]))
|
|
if current_start != start or current_end != end:
|
|
LOG.debug("Old VLAN range %s-%s" % (current_start, current_end))
|
|
LOG.debug("New VLAN range %s-%s" % (start, end))
|
|
raise c_exc.UnableToChangeVlanRange(range_start=current_start,
|
|
range_end=current_end)
|
|
except exc.NoResultFound:
|
|
LOG.debug("Setting VLAN range to %s-%s" % (start, end))
|
|
while start <= end:
|
|
vlanid = L2_MODEL.VlanID(start)
|
|
session.add(vlanid)
|
|
start += 1
|
|
session.flush()
|
|
return
|
|
|
|
|
|
def get_all_vlanids():
|
|
"""Gets all the vlanids"""
|
|
LOG.debug("get_all_vlanids() called")
|
|
session = db.get_session()
|
|
try:
|
|
vlanids = (session.query(L2_MODEL.VlanID).
|
|
all())
|
|
return vlanids
|
|
except exc.NoResultFound:
|
|
return []
|
|
|
|
|
|
def is_vlanid_used(vlan_id):
|
|
"""Checks if a vlanid is in use"""
|
|
LOG.debug("is_vlanid_used() called")
|
|
session = db.get_session()
|
|
try:
|
|
vlanid = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_id=vlan_id).
|
|
one())
|
|
return vlanid["vlan_used"]
|
|
except exc.NoResultFound:
|
|
raise c_exc.VlanIDNotFound(vlan_id=vlan_id)
|
|
|
|
|
|
def release_vlanid(vlan_id):
|
|
"""Sets the vlanid state to be unused"""
|
|
LOG.debug("release_vlanid() called")
|
|
session = db.get_session()
|
|
try:
|
|
vlanid = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_id=vlan_id).
|
|
one())
|
|
vlanid["vlan_used"] = False
|
|
session.merge(vlanid)
|
|
session.flush()
|
|
return vlanid["vlan_used"]
|
|
except exc.NoResultFound:
|
|
raise c_exc.VlanIDNotFound(vlan_id=vlan_id)
|
|
return
|
|
|
|
|
|
def delete_vlanid(vlan_id):
|
|
"""Deletes a vlanid entry from db"""
|
|
LOG.debug("delete_vlanid() called")
|
|
session = db.get_session()
|
|
try:
|
|
vlanid = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_id=vlan_id).
|
|
one())
|
|
session.delete(vlanid)
|
|
session.flush()
|
|
return vlanid
|
|
except exc.NoResultFound:
|
|
raise c_exc.VlanIDNotFound(vlan_id=vlan_id)
|
|
|
|
|
|
def reserve_vlanid():
|
|
"""Reserves the first unused vlanid"""
|
|
LOG.debug("reserve_vlanid() called")
|
|
session = db.get_session()
|
|
try:
|
|
rvlan = (session.query(L2_MODEL.VlanID).
|
|
first())
|
|
if not rvlan:
|
|
create_vlanids()
|
|
|
|
rvlan = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_used=False).
|
|
first())
|
|
if not rvlan:
|
|
raise c_exc.VlanIDNotAvailable()
|
|
|
|
rvlanid = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_id=rvlan["vlan_id"]).
|
|
one())
|
|
rvlanid["vlan_used"] = True
|
|
session.merge(rvlanid)
|
|
session.flush()
|
|
return rvlan["vlan_id"]
|
|
except exc.NoResultFound:
|
|
raise c_exc.VlanIDNotAvailable()
|
|
|
|
|
|
def get_all_vlanids_used():
|
|
"""Gets all the vlanids used"""
|
|
LOG.debug("get_all_vlanids() called")
|
|
session = db.get_session()
|
|
try:
|
|
vlanids = (session.query(L2_MODEL.VlanID).
|
|
filter_by(vlan_used=True).
|
|
all())
|
|
return vlanids
|
|
except exc.NoResultFound:
|
|
return []
|
|
|
|
|
|
def get_all_vlan_bindings():
|
|
"""Lists all the vlan to network associations"""
|
|
LOG.debug("get_all_vlan_bindings() called")
|
|
session = db.get_session()
|
|
try:
|
|
bindings = (session.query(L2_MODEL.VlanBinding).
|
|
all())
|
|
return bindings
|
|
except exc.NoResultFound:
|
|
return []
|
|
|
|
|
|
def get_vlan_binding(netid):
|
|
"""Lists the vlan given a network_id"""
|
|
LOG.debug("get_vlan_binding() called")
|
|
session = db.get_session()
|
|
try:
|
|
binding = (session.query(L2_MODEL.VlanBinding).
|
|
filter_by(network_id=netid).
|
|
one())
|
|
return binding
|
|
except exc.NoResultFound:
|
|
raise c_exc.NetworkVlanBindingNotFound(network_id=netid)
|
|
|
|
|
|
def add_vlan_binding(vlanid, netid):
|
|
"""Adds a vlan to network association"""
|
|
LOG.debug("add_vlan_binding() called")
|
|
session = db.get_session()
|
|
try:
|
|
binding = (session.query(L2_MODEL.VlanBinding).
|
|
filter_by(vlan_id=vlanid).
|
|
one())
|
|
raise c_exc.NetworkVlanBindingAlreadyExists(vlan_id=vlanid,
|
|
network_id=netid)
|
|
except exc.NoResultFound:
|
|
binding = L2_MODEL.VlanBinding(vlanid, netid)
|
|
session.add(binding)
|
|
session.flush()
|
|
return binding
|
|
|
|
|
|
def remove_vlan_binding(netid):
|
|
"""Removes a vlan to network association"""
|
|
LOG.debug("remove_vlan_binding() called")
|
|
session = db.get_session()
|
|
try:
|
|
binding = (session.query(L2_MODEL.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):
|
|
"""Updates a vlan to network association"""
|
|
LOG.debug("update_vlan_binding() called")
|
|
session = db.get_session()
|
|
try:
|
|
binding = (session.query(L2_MODEL.VlanBinding).
|
|
filter_by(network_id=netid).
|
|
one())
|
|
if newvlanid:
|
|
binding["vlan_id"] = newvlanid
|
|
session.merge(binding)
|
|
session.flush()
|
|
return binding
|
|
except exc.NoResultFound:
|
|
raise q_exc.NetworkNotFound(net_id=netid)
|