OVS plugin support for v2 Quantum API
blueprint: ovs-api-v2-support This commit allows the ovs_quantum_plugin to work with the v2 api. change-Id: I9e332a799f6bee8a90755f961fbb9711a1ecdaca
This commit is contained in:
parent
6d9ddf1c37
commit
804c936667
@ -38,6 +38,8 @@ polling_interval = 2
|
||||
# Change to "sudo quantum-rootwrap" to limit commands that can be run
|
||||
# as root.
|
||||
root_helper = sudo
|
||||
# Use Quantumv2 API
|
||||
target_v2_api = False
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Sample Configurations.
|
||||
@ -53,6 +55,8 @@ root_helper = sudo
|
||||
# root_helper = sudo
|
||||
# Add the following setting, if you want to log to a file
|
||||
# log_file = /var/log/quantum/ovs_quantum_agent.log
|
||||
# Use Quantumv2 API
|
||||
# target_v2_api = False
|
||||
#
|
||||
# 2. With tunneling.
|
||||
# [DATABASE]
|
||||
|
@ -26,6 +26,7 @@ import inspect
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import uuid
|
||||
|
||||
from quantum.common import exceptions as exception
|
||||
from quantum.common import flags
|
||||
@ -153,3 +154,8 @@ def find_config_file(options, config_file):
|
||||
cfg_file = os.path.join(cfg_dir, config_file)
|
||||
if os.path.exists(cfg_file):
|
||||
return cfg_file
|
||||
|
||||
|
||||
def str_uuid():
|
||||
"""Return a uuid as a string"""
|
||||
return str(uuid.uuid4())
|
||||
|
@ -13,17 +13,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import uuid
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.ext import declarative
|
||||
from sqlalchemy import orm
|
||||
|
||||
|
||||
def str_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class QuantumBase(object):
|
||||
"""Base class for Quantum Models."""
|
||||
|
||||
@ -60,7 +54,6 @@ class QuantumBase(object):
|
||||
|
||||
|
||||
class QuantumBaseV2(QuantumBase):
|
||||
id = sa.Column(sa.String(36), primary_key=True, default=str_uuid)
|
||||
|
||||
@declarative.declared_attr
|
||||
def __tablename__(cls):
|
||||
|
@ -16,6 +16,7 @@
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from quantum.common import utils
|
||||
from quantum.db import model_base
|
||||
|
||||
|
||||
@ -25,7 +26,12 @@ class HasTenant(object):
|
||||
tenant_id = sa.Column(sa.String(255))
|
||||
|
||||
|
||||
class IPAllocationRange(model_base.BASEV2):
|
||||
class HasId(object):
|
||||
"""id mixin, add to subclasses that have an id."""
|
||||
id = sa.Column(sa.String(36), primary_key=True, default=utils.str_uuid)
|
||||
|
||||
|
||||
class IPAllocationRange(model_base.BASEV2, HasId):
|
||||
"""Internal representation of a free IP address range in a Quantum
|
||||
subnet. The range of available ips is [first_ip..last_ip]. The
|
||||
allocation retrieves the first entry from the range. If the first
|
||||
@ -53,7 +59,7 @@ class IPAllocation(model_base.BASEV2):
|
||||
nullable=False, primary_key=True)
|
||||
|
||||
|
||||
class Port(model_base.BASEV2, HasTenant):
|
||||
class Port(model_base.BASEV2, HasId, HasTenant):
|
||||
"""Represents a port on a quantum v2 network."""
|
||||
network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
|
||||
nullable=False)
|
||||
@ -64,7 +70,7 @@ class Port(model_base.BASEV2, HasTenant):
|
||||
device_id = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
|
||||
class Subnet(model_base.BASEV2):
|
||||
class Subnet(model_base.BASEV2, HasId):
|
||||
"""Represents a quantum subnet.
|
||||
|
||||
When a subnet is created the first and last entries will be created. These
|
||||
@ -81,7 +87,7 @@ class Subnet(model_base.BASEV2):
|
||||
# - additional_routes
|
||||
|
||||
|
||||
class Network(model_base.BASEV2, HasTenant):
|
||||
class Network(model_base.BASEV2, HasId, HasTenant):
|
||||
"""Represents a v2 quantum network."""
|
||||
name = sa.Column(sa.String(255))
|
||||
ports = orm.relationship(Port, backref='networks')
|
||||
|
@ -18,6 +18,7 @@
|
||||
# @author: Brad Hall, Nicira Networks, Inc.
|
||||
# @author: Dan Wendlandt, Nicira Networks, Inc.
|
||||
# @author: Dave Lapsley, Nicira Networks, Inc.
|
||||
# @author: Aaron Rosen, Nicira Networks, Inc.
|
||||
|
||||
import logging
|
||||
from optparse import OptionParser
|
||||
@ -59,21 +60,21 @@ class LocalVLANMapping:
|
||||
|
||||
|
||||
class Port(object):
|
||||
'''class stores port data in an ORM-free way,
|
||||
so attributes are still available even if a
|
||||
row has been deleted.
|
||||
'''
|
||||
"""Represents a quantum port.
|
||||
|
||||
Class stores port data in a ORM-free way, so attributres are
|
||||
still available even if a row has been deleted.
|
||||
"""
|
||||
|
||||
def __init__(self, p):
|
||||
self.uuid = p.uuid
|
||||
self.network_id = p.network_id
|
||||
self.interface_id = p.interface_id
|
||||
self.state = p.state
|
||||
self.op_status = p.op_status
|
||||
self.status = p.op_status
|
||||
|
||||
def __eq__(self, other):
|
||||
'''compare only fields that will cause us to re-wire
|
||||
'''
|
||||
'''Compare only fields that will cause us to re-wire.'''
|
||||
try:
|
||||
return (self and other
|
||||
and self.interface_id == other.interface_id
|
||||
@ -88,14 +89,45 @@ class Port(object):
|
||||
return hash(self.uuid)
|
||||
|
||||
|
||||
class Portv2(object):
|
||||
"""Represents a quantumv2 port.
|
||||
|
||||
Class stores port data in a ORM-free way, so attributres are
|
||||
still available even if a row has been deleted.
|
||||
"""
|
||||
|
||||
def __init__(self, p):
|
||||
self.id = p.id
|
||||
self.network_id = p.network_id
|
||||
self.device_id = p.device_id
|
||||
self.admin_state_up = p.admin_state_up
|
||||
self.status = p.status
|
||||
|
||||
def __eq__(self, other):
|
||||
'''Compare only fields that will cause us to re-wire.'''
|
||||
try:
|
||||
return (self and other
|
||||
and self.id == other.id
|
||||
and self.admin_state_up == other.admin_state_up)
|
||||
except:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.id)
|
||||
|
||||
|
||||
class OVSQuantumAgent(object):
|
||||
|
||||
def __init__(self, integ_br, root_helper,
|
||||
polling_interval, reconnect_interval):
|
||||
def __init__(self, integ_br, root_helper, polling_interval,
|
||||
reconnect_interval, target_v2_api=False):
|
||||
self.root_helper = root_helper
|
||||
self.setup_integration_br(integ_br)
|
||||
self.polling_interval = polling_interval
|
||||
self.reconnect_interval = reconnect_interval
|
||||
self.target_v2_api = target_v2_api
|
||||
|
||||
def port_bound(self, port, vlan_id):
|
||||
self.int_br.set_db_attribute("Port", port.port_name,
|
||||
@ -139,7 +171,10 @@ class OVSQuantumAgent(object):
|
||||
continue
|
||||
|
||||
for port in ports:
|
||||
all_bindings[port.interface_id] = port
|
||||
if self.target_v2_api:
|
||||
all_bindings[port.id] = port
|
||||
else:
|
||||
all_bindings[port.interface_id] = port
|
||||
|
||||
vlan_bindings = {}
|
||||
try:
|
||||
@ -177,7 +212,7 @@ class OVSQuantumAgent(object):
|
||||
% (old_b, str(p)))
|
||||
self.port_unbound(p, True)
|
||||
if p.vif_id in all_bindings:
|
||||
all_bindings[p.vif_id].op_status = OP_STATUS_DOWN
|
||||
all_bindings[p.vif_id].status = OP_STATUS_DOWN
|
||||
if new_b is not None:
|
||||
# If we don't have a binding we have to stick it on
|
||||
# the dead vlan
|
||||
@ -185,7 +220,7 @@ class OVSQuantumAgent(object):
|
||||
vlan_id = vlan_bindings.get(net_id, DEAD_VLAN_TAG)
|
||||
self.port_bound(p, vlan_id)
|
||||
if p.vif_id in all_bindings:
|
||||
all_bindings[p.vif_id].op_status = OP_STATUS_UP
|
||||
all_bindings[p.vif_id].status = OP_STATUS_UP
|
||||
LOG.info(("Adding binding to net-id = %s "
|
||||
"for %s on vlan %s") %
|
||||
(new_b, str(p), vlan_id))
|
||||
@ -197,7 +232,7 @@ class OVSQuantumAgent(object):
|
||||
old_b = old_local_bindings[vif_id]
|
||||
self.port_unbound(old_vif_ports[vif_id], False)
|
||||
if vif_id in all_bindings:
|
||||
all_bindings[vif_id].op_status = OP_STATUS_DOWN
|
||||
all_bindings[vif_id].status = OP_STATUS_DOWN
|
||||
|
||||
old_vif_ports = new_vif_ports
|
||||
old_local_bindings = new_local_bindings
|
||||
@ -237,7 +272,7 @@ class OVSQuantumTunnelAgent(object):
|
||||
MAX_VLAN_TAG = 4094
|
||||
|
||||
def __init__(self, integ_br, tun_br, local_ip, root_helper,
|
||||
polling_interval, reconnect_interval):
|
||||
polling_interval, reconnect_interval, target_v2_api=False):
|
||||
'''Constructor.
|
||||
|
||||
:param integ_br: name of the integration bridge.
|
||||
@ -245,7 +280,9 @@ class OVSQuantumTunnelAgent(object):
|
||||
:param local_ip: local IP address of this hypervisor.
|
||||
:param root_helper: utility to use when running shell cmds.
|
||||
:param polling_interval: interval (secs) to poll DB.
|
||||
:param reconnect_internal: retry interval (secs) on DB error.'''
|
||||
:param reconnect_internal: retry interval (secs) on DB error.
|
||||
:param target_v2_api: if True use v2 api.
|
||||
'''
|
||||
self.root_helper = root_helper
|
||||
self.available_local_vlans = set(
|
||||
xrange(OVSQuantumTunnelAgent.MIN_VLAN_TAG,
|
||||
@ -259,6 +296,7 @@ class OVSQuantumTunnelAgent(object):
|
||||
self.local_ip = local_ip
|
||||
self.tunnel_count = 0
|
||||
self.setup_tunnel_br(tun_br)
|
||||
self.target_v2_api = target_v2_api
|
||||
|
||||
def provision_local_vlan(self, net_uuid, lsw_id):
|
||||
'''Provisions a local VLAN.
|
||||
@ -294,7 +332,8 @@ class OVSQuantumTunnelAgent(object):
|
||||
self.available_local_vlans.add(lvm.vlan)
|
||||
|
||||
def port_bound(self, port, net_uuid, lsw_id):
|
||||
'''Bind port to net_uuid/lsw_id.
|
||||
'''Bind port to net_uuid/lsw_id and install flow for inbound traffic
|
||||
to vm.
|
||||
|
||||
:param port: a ovslib.VifPort object.
|
||||
:param net_uuid: the net_uuid this port is to be associated with.
|
||||
@ -405,8 +444,12 @@ class OVSQuantumTunnelAgent(object):
|
||||
|
||||
while True:
|
||||
try:
|
||||
all_bindings = dict((p.interface_id, Port(p))
|
||||
for p in db.ports.all())
|
||||
if self.target_v2_api:
|
||||
all_bindings = dict((p.id, Portv2(p))
|
||||
for p in db.ports.all())
|
||||
else:
|
||||
all_bindings = dict((p.interface_id, Port(p))
|
||||
for p in db.ports.all())
|
||||
all_bindings_vif_port_ids = set(all_bindings)
|
||||
lsw_id_bindings = dict((bind.network_id, bind.vlan_id)
|
||||
for bind in db.vlan_bindings.all())
|
||||
@ -461,7 +504,8 @@ class OVSQuantumTunnelAgent(object):
|
||||
old_net_uuid + " for " + str(p)
|
||||
+ " added to dead vlan")
|
||||
self.port_unbound(p, old_net_uuid)
|
||||
all_bindings[p.vif_id].op_status = OP_STATUS_DOWN
|
||||
if p.vif_id in all_bindings:
|
||||
all_bindings[p.vif_id].status = OP_STATUS_DOWN
|
||||
if not new_port:
|
||||
self.port_dead(p)
|
||||
|
||||
@ -474,7 +518,7 @@ class OVSQuantumTunnelAgent(object):
|
||||
|
||||
lsw_id = lsw_id_bindings[new_net_uuid]
|
||||
self.port_bound(p, new_net_uuid, lsw_id)
|
||||
all_bindings[p.vif_id].op_status = OP_STATUS_UP
|
||||
all_bindings[p.vif_id].status = OP_STATUS_UP
|
||||
LOG.info("Port %s on net-id = %s bound to %s " % (
|
||||
str(p), new_net_uuid,
|
||||
str(self.local_vlan_map[new_net_uuid])))
|
||||
@ -482,7 +526,7 @@ class OVSQuantumTunnelAgent(object):
|
||||
for vif_id in disappeared_vif_ports_ids:
|
||||
LOG.info("Port Disappeared: " + vif_id)
|
||||
if vif_id in all_bindings:
|
||||
all_bindings[vif_id].op_status = OP_STATUS_DOWN
|
||||
all_bindings[vif_id].status = OP_STATUS_DOWN
|
||||
old_port = old_local_bindings.get(vif_id)
|
||||
if old_port:
|
||||
self.port_unbound(old_vif_ports[vif_id],
|
||||
@ -540,17 +584,21 @@ def main():
|
||||
reconnect_interval = conf.DATABASE.reconnect_interval
|
||||
root_helper = conf.AGENT.root_helper
|
||||
|
||||
# Determine API Version to use
|
||||
target_v2_api = conf.AGENT.target_v2_api
|
||||
|
||||
if enable_tunneling:
|
||||
# Get parameters for OVSQuantumTunnelAgent
|
||||
tun_br = conf.OVS.tunnel_bridge
|
||||
# Mandatory parameter.
|
||||
local_ip = conf.OVS.local_ip
|
||||
plugin = OVSQuantumTunnelAgent(integ_br, tun_br, local_ip, root_helper,
|
||||
polling_interval, reconnect_interval)
|
||||
polling_interval, reconnect_interval,
|
||||
target_v2_api)
|
||||
else:
|
||||
# Get parameters for OVSQuantumAgent.
|
||||
plugin = OVSQuantumAgent(integ_br, root_helper,
|
||||
polling_interval, reconnect_interval)
|
||||
plugin = OVSQuantumAgent(integ_br, root_helper, polling_interval,
|
||||
reconnect_interval, target_v2_api)
|
||||
|
||||
# Start everything.
|
||||
plugin.daemon_loop(db_connection_url)
|
||||
|
@ -32,6 +32,7 @@ ovs_opts = [
|
||||
]
|
||||
|
||||
agent_opts = [
|
||||
cfg.BoolOpt('target_v2_api', default=True),
|
||||
cfg.IntOpt('polling_interval', default=2),
|
||||
cfg.StrOpt('root_helper', default='sudo'),
|
||||
cfg.StrOpt('log_file', default=None),
|
||||
|
51
quantum/plugins/openvswitch/ovs_db_v2.py
Normal file
51
quantum/plugins/openvswitch/ovs_db_v2.py
Normal file
@ -0,0 +1,51 @@
|
||||
# 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: Aaron Rosen, Nicira Networks, Inc.
|
||||
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
import quantum.db.api as db
|
||||
from quantum.plugins.openvswitch import ovs_models_v2
|
||||
|
||||
|
||||
def get_vlans():
|
||||
session = db.get_session()
|
||||
try:
|
||||
bindings = (session.query(ovs_models_v2.VlanBinding).
|
||||
all())
|
||||
except exc.NoResultFound:
|
||||
return []
|
||||
return [(binding.vlan_id, binding.network_id) for binding in bindings]
|
||||
|
||||
|
||||
def add_vlan_binding(vlan_id, net_id):
|
||||
session = db.get_session()
|
||||
binding = ovs_models_v2.VlanBinding(vlan_id, net_id)
|
||||
session.add(binding)
|
||||
session.flush()
|
||||
return binding
|
||||
|
||||
|
||||
def remove_vlan_binding(net_id):
|
||||
session = db.get_session()
|
||||
try:
|
||||
binding = (session.query(ovs_models_v2.VlanBinding).
|
||||
filter_by(network_id=net_id).
|
||||
one())
|
||||
session.delete(binding)
|
||||
except exc.NoResultFound:
|
||||
pass
|
||||
session.flush()
|
49
quantum/plugins/openvswitch/ovs_models_v2.py
Normal file
49
quantum/plugins/openvswitch/ovs_models_v2.py
Normal file
@ -0,0 +1,49 @@
|
||||
# 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: Aaron Rosen, Nicira Networks, Inc.
|
||||
|
||||
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from quantum.db import models_v2
|
||||
|
||||
|
||||
class VlanBinding(models_v2.model_base.BASEV2):
|
||||
"""Represents a binding of network_id to vlan_id."""
|
||||
__tablename__ = 'vlan_bindings'
|
||||
|
||||
vlan_id = Column(Integer, primary_key=True)
|
||||
network_id = Column(String(255))
|
||||
|
||||
def __init__(self, vlan_id, network_id):
|
||||
self.network_id = network_id
|
||||
self.vlan_id = vlan_id
|
||||
|
||||
def __repr__(self):
|
||||
return "<VlanBinding(%s,%s)>" % (self.vlan_id, self.network_id)
|
||||
|
||||
|
||||
class TunnelIP(models_v2.model_base.BASEV2):
|
||||
"""Represents a remote IP in tunnel mode."""
|
||||
__tablename__ = 'tunnel_ips'
|
||||
|
||||
ip_address = Column(String(255), primary_key=True)
|
||||
|
||||
def __init__(self, ip_address):
|
||||
self.ip_address = ip_address
|
||||
|
||||
def __repr__(self):
|
||||
return "<TunnelIP(%s)>" % (self.ip_address)
|
@ -17,6 +17,7 @@
|
||||
# @author: Brad Hall, Nicira Networks, Inc.
|
||||
# @author: Dan Wendlandt, Nicira Networks, Inc.
|
||||
# @author: Dave Lapsley, Nicira Networks, Inc.
|
||||
# @author: Aaron Rosen, Nicira Networks, Inc.
|
||||
|
||||
import logging
|
||||
import os
|
||||
@ -24,14 +25,16 @@ import os
|
||||
from quantum.api.api_common import OperationalStatus
|
||||
from quantum.common import exceptions as q_exc
|
||||
from quantum.common.utils import find_config_file
|
||||
import quantum.db.api as db
|
||||
from quantum.db import api as db
|
||||
from quantum.db import db_base_plugin_v2
|
||||
from quantum.db import models_v2
|
||||
from quantum.plugins.openvswitch.common import config
|
||||
from quantum.plugins.openvswitch import ovs_db
|
||||
from quantum.plugins.openvswitch import ovs_db_v2
|
||||
from quantum.quantum_plugin_base import QuantumPluginBase
|
||||
|
||||
|
||||
LOG = logging.getLogger("ovs_quantum_plugin")
|
||||
|
||||
|
||||
CONF_FILE = find_config_file({"plugin": "openvswitch"},
|
||||
"ovs_quantum_plugin.ini")
|
||||
|
||||
@ -47,6 +50,12 @@ class VlanMap(object):
|
||||
free_vlans = set()
|
||||
|
||||
def __init__(self, vlan_min=1, vlan_max=4094):
|
||||
if vlan_min > vlan_max:
|
||||
LOG.warn("Using default VLAN values! vlan_min = %s is larger"
|
||||
" than vlan_max = %s!" % (vlan_min, vlan_max))
|
||||
vlan_min = 1
|
||||
vlan_max = 4094
|
||||
|
||||
self.vlan_min = vlan_min
|
||||
self.vlan_max = vlan_max
|
||||
self.vlans.clear()
|
||||
@ -82,44 +91,26 @@ class VlanMap(object):
|
||||
else:
|
||||
LOG.error("No vlan found with network \"%s\"", network_id)
|
||||
|
||||
def populate_already_used(self, vlans):
|
||||
for vlan_id, network_id in vlans:
|
||||
LOG.debug("Adding already populated vlan %s -> %s" %
|
||||
(vlan_id, network_id))
|
||||
self.already_used(vlan_id, network_id)
|
||||
|
||||
|
||||
class OVSQuantumPlugin(QuantumPluginBase):
|
||||
|
||||
def __init__(self, configfile=None):
|
||||
if configfile is None:
|
||||
if os.path.exists(CONF_FILE):
|
||||
configfile = CONF_FILE
|
||||
else:
|
||||
configfile = find_config(os.path.abspath(
|
||||
os.path.dirname(__file__)))
|
||||
if configfile is None:
|
||||
raise Exception("Configuration file \"%s\" doesn't exist" %
|
||||
(configfile))
|
||||
LOG.debug("Using configuration file: %s" % configfile)
|
||||
conf = config.parse(configfile)
|
||||
conf = config.parse(CONF_FILE)
|
||||
options = {"sql_connection": conf.DATABASE.sql_connection}
|
||||
reconnect_interval = conf.DATABASE.reconnect_interval
|
||||
options.update({"reconnect_interval": reconnect_interval})
|
||||
db.configure_db(options)
|
||||
|
||||
vlan_min = conf.OVS.vlan_min
|
||||
vlan_max = conf.OVS.vlan_max
|
||||
|
||||
if vlan_min > vlan_max:
|
||||
LOG.warn("Using default VLAN values! vlan_min = %s is larger"
|
||||
" than vlan_max = %s!" % (vlan_min, vlan_max))
|
||||
vlan_min = 1
|
||||
vlan_max = 4094
|
||||
|
||||
self.vmap = VlanMap(vlan_min, vlan_max)
|
||||
self.vmap = VlanMap(conf.OVS.vlan_min, conf.OVS.vlan_max)
|
||||
# Populate the map with anything that is already present in the
|
||||
# database
|
||||
vlans = ovs_db.get_vlans()
|
||||
for x in vlans:
|
||||
vlan_id, network_id = x
|
||||
LOG.debug("Adding already populated vlan %s -> %s" %
|
||||
(vlan_id, network_id))
|
||||
self.vmap.already_used(vlan_id, network_id)
|
||||
self.vmap.populate_already_used(ovs_db.get_vlans())
|
||||
|
||||
def get_all_networks(self, tenant_id, **kwargs):
|
||||
nets = []
|
||||
@ -142,8 +133,13 @@ class OVSQuantumPlugin(QuantumPluginBase):
|
||||
def create_network(self, tenant_id, net_name, **kwargs):
|
||||
net = db.network_create(tenant_id, net_name,
|
||||
op_status=OperationalStatus.UP)
|
||||
try:
|
||||
vlan_id = self.vmap.acquire(str(net.uuid))
|
||||
except NoFreeVLANException:
|
||||
db.network_destroy(net.uuid)
|
||||
raise
|
||||
|
||||
LOG.debug("Created network: %s" % net)
|
||||
vlan_id = self.vmap.acquire(str(net.uuid))
|
||||
ovs_db.add_vlan_binding(vlan_id, str(net.uuid))
|
||||
return self._make_net_dict(str(net.uuid), net.name, [], net.op_status)
|
||||
|
||||
@ -233,3 +229,33 @@ class OVSQuantumPlugin(QuantumPluginBase):
|
||||
db.validate_port_ownership(tenant_id, net_id, port_id)
|
||||
res = db.port_get(port_id, net_id)
|
||||
return res.interface_id
|
||||
|
||||
|
||||
class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2):
|
||||
def __init__(self, configfile=None):
|
||||
conf = config.parse(CONF_FILE)
|
||||
options = {"sql_connection": conf.DATABASE.sql_connection}
|
||||
options.update({'base': models_v2.model_base.BASEV2})
|
||||
reconnect_interval = conf.DATABASE.reconnect_interval
|
||||
options.update({"reconnect_interval": reconnect_interval})
|
||||
db.configure_db(options)
|
||||
|
||||
self.vmap = VlanMap(conf.OVS.vlan_min, conf.OVS.vlan_max)
|
||||
self.vmap.populate_already_used(ovs_db_v2.get_vlans())
|
||||
|
||||
def create_network(self, context, network):
|
||||
net = super(OVSQuantumPluginV2, self).create_network(context, network)
|
||||
try:
|
||||
vlan_id = self.vmap.acquire(str(net['id']))
|
||||
except NoFreeVLANException:
|
||||
super(OVSQuantumPluginV2, self).delete_network(context, net['id'])
|
||||
raise
|
||||
|
||||
LOG.debug("Created network: %s" % net['id'])
|
||||
ovs_db_v2.add_vlan_binding(vlan_id, str(net['id']))
|
||||
return net
|
||||
|
||||
def delete_network(self, context, id):
|
||||
ovs_db_v2.remove_vlan_binding(id)
|
||||
self.vmap.release(id)
|
||||
return super(OVSQuantumPluginV2, self).delete_network(context, id)
|
||||
|
Loading…
Reference in New Issue
Block a user