Merge "add local network type and use by default for tenant networks"

This commit is contained in:
Jenkins 2012-09-09 12:07:13 +00:00 committed by Gerrit Code Review
commit 59b9b2577a
16 changed files with 284 additions and 119 deletions

View File

@ -1,9 +1,24 @@
[VLANS]
# (StrOpt) Type of network to allocate for tenant networks. The
# default value 'local' is useful only for single-box testing and
# provides no connectivity between hosts. You MUST change this to
# 'vlan' and configure network_vlan_ranges below in order for tenant
# networks to provide connectivity between hosts. Set to 'none' to
# disable creation of tenant networks.
#
# Default: tenant_network_type = local
# Example: tenant_network_type = vlan
# (ListOpt) Comma-separated list of
# <physical_network>:<vlan_min>:<vlan_max> tuples enumerating ranges
# <physical_network>[:<vlan_min>:<vlan_max>] tuples enumerating ranges
# of VLAN IDs on named physical networks that are available for
# allocation.
# network_vlan_ranges = default:1000:2999
# allocation. All physical networks listed are available for flat and
# VLAN provider network creation. Specified ranges of VLAN IDs are
# available for tenant network allocation if tenant_network_type is
# 'vlan'. If empty, only local networks may be created.
#
# Default: network_vlan_ranges =
# Example: network_vlan_ranges = physnet1:1000:2999
[DATABASE]
# This line MUST be changed to actually run the plugin.
@ -21,10 +36,13 @@ reconnect_interval = 2
[LINUX_BRIDGE]
# (ListOpt) Comma-separated list of
# <physical_network>:<physical_interface> tuples mapping physical
# network names to agent's node-specific physical network
# interfaces. Server uses physical network names for validation but
# ignores interfaces.
# physical_interface_mappings = default:eth1
# network names to the agent's node-specific physical network
# interfaces to be used for flat and VLAN networks. All physical
# networks listed in network_vlan_ranges on the server should have
# mappings to appropriate interfaces on each agent.
#
# Default: physical_interface_mappings =
# Example: physical_interface_mappings = physnet1:eth1
[AGENT]
# Agent's polling interval in seconds

View File

@ -12,37 +12,63 @@ sql_connection = sqlite://
reconnect_interval = 2
[OVS]
# (StrOpt) Type of network to allocate for tenant networks. The
# default value 'local' is useful only for single-box testing and
# provides no connectivity between hosts. You MUST either change this
# to 'vlan' and configure network_vlan_ranges below or change this to
# 'gre' and configure tunnel_id_ranges below in order for tenant
# networks to provide connectivity between hosts. Set to 'none' to
# disable creation of tenant networks.
#
# Default: tenant_network_type = local
# Example: tenant_network_type = gre
# (ListOpt) Comma-separated list of
# <physical_network>:<vlan_min>:<vlan_max> tuples enumerating ranges
# <physical_network>[:<vlan_min>:<vlan_max>] tuples enumerating ranges
# of VLAN IDs on named physical networks that are available for
# allocation.
# network_vlan_ranges = default:1000:2999
# allocation. All physical networks listed are available for flat and
# VLAN provider network creation. Specified ranges of VLAN IDs are
# available for tenant network allocation if tenant_network_type is
# 'vlan'. If empty, only gre and local networks may be created.
#
# Default: network_vlan_ranges =
# Example: network_vlan_ranges = physnet1:1000:2999
# (ListOpt) Comma-separated list of <tun_min>:<tun_max> tuples
# enumerating ranges of GRE tunnel IDs that are available for
# allocation.
# tunnel_id_ranges =
# enumerating ranges of GRE tunnel IDs that are available for tenant
# network allocation if tenant_network_type is 'gre'.
#
# Default: tunnel_id_ranges =
# Example: tunnel_id_ranges = 1:1000
# Do not change this parameter unless you have a good reason to.
# This is the name of the OVS integration bridge. There is one per hypervisor.
# The integration bridge acts as a virtual "patch port". All VM VIFs are
# The integration bridge acts as a virtual "patch bay". All VM VIFs are
# attached to this bridge and then "patched" according to their network
# connectivity.
# integration_bridge = br-int
#
# Default: integration_bridge = br-int
# Only used if tunnel_id_ranges (above) is not empty.
# In most cases, the default value should be fine.
# tunnel_bridge = br-tun
# Only used for the agent if tunnel_id_ranges (above) is not empty for
# the server. In most cases, the default value should be fine.
#
# Default: tunnel_bridge = br-tun
# Uncomment this line for the agent if tunnel_id_ranges (above) is not
# empty for the server. Set local-ip to be the local IP address of
# this hypervisor.
#
# Default: local_ip = 10.0.0.3
# (ListOpt) Comma-separated list of <physical_network>:<bridge> tuples
# mapping physical network names to agent's node-specific OVS bridge
# names. Each bridge must exist, and should have physical network
# interface configured as a port.
# bridge_mappings = default:br-eth1
# Uncomment this line if tunnel_id_ranges (above) is not empty.
# Set local-ip to be the local IP address of this hypervisor.
# local_ip = 10.0.0.3
# mapping physical network names to the agent's node-specific OVS
# bridge names to be used for flat and VLAN networks. Each bridge must
# exist, and should have a physical network interface configured as a
# port. All physical networks listed in network_vlan_ranges on the
# server should have mappings to appropriate bridges on each agent.
#
# Default: bridge_mappings =
# Example: bridge_mappings = physnet1:br-eth1
[AGENT]
# Agent's polling interval in seconds

View File

@ -137,6 +137,10 @@ class TunnelIdInUse(InUse):
"The tunnel ID %(tunnel_id)s is in use.")
class TenantNetworksDisabled(QuantumException):
message = _("Tenant network creation is not enabled.")
class ResourceExhausted(QuantumException):
pass

View File

@ -19,11 +19,12 @@ NETWORK_TYPE = 'provider:network_type'
PHYSICAL_NETWORK = 'provider:physical_network'
SEGMENTATION_ID = 'provider:segmentation_id'
NETWORK_TYPE_VALUES = ['flat', 'gre', 'local', 'vlan']
EXTENDED_ATTRIBUTES_2_0 = {
'networks': {
NETWORK_TYPE: {'allow_post': True, 'allow_put': True,
'validate': {'type:values': ['flat',
'vlan']},
'validate': {'type:values': NETWORK_TYPE_VALUES},
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
PHYSICAL_NETWORK: {'allow_post': True, 'allow_put': True,
@ -49,6 +50,8 @@ class Providernet(object):
To create a provider VLAN network using the CLI with admin rights:
(shell) net-create --tenant_id <tenant-id> <net-name> \
--provider:network_type vlan \
--provider:physical_network <physical-net> \
--provider:segmentation_id <vlan-id>
With admin rights, network dictionaries returned from CLI commands
@ -65,7 +68,7 @@ class Providernet(object):
@classmethod
def get_description(cls):
return "Expose mapping of virtual networks to VLANs and flat networks"
return "Expose mapping of virtual networks to physical networks"
@classmethod
def get_namespace(cls):
@ -73,7 +76,7 @@ class Providernet(object):
@classmethod
def get_updated(cls):
return "2012-07-23T10:00:00-00:00"
return "2012-09-07T10:00:00-00:00"
def get_extended_resources(self, version):
if version == "2.0":

View File

@ -192,6 +192,11 @@ class LinuxBridge:
self.ensure_bridge(bridge_name, physical_interface, ips, gateway)
return physical_interface
def ensure_local_bridge(self, network_id):
"""Create a local bridge unless it already exists."""
bridge_name = self.get_bridge_name(network_id)
self.ensure_bridge(bridge_name)
def ensure_vlan(self, physical_interface, vlan_id):
"""Create a vlan unless it already exists."""
interface = self.get_subinterface_name(physical_interface, vlan_id)
@ -237,7 +242,8 @@ class LinuxBridge:
src_device.addr.delete(ip_version=ip['ip_version'],
cidr=ip['cidr'])
def ensure_bridge(self, bridge_name, interface, ips=None, gateway=None):
def ensure_bridge(self, bridge_name, interface=None, ips=None,
gateway=None):
"""
Create a bridge unless it already exists.
"""
@ -259,6 +265,9 @@ class LinuxBridge:
LOG.debug("Done starting bridge %s for subinterface %s" %
(bridge_name, interface))
if not interface:
return
# Update IP info if necessary
self.update_interface_ip_details(bridge_name, interface, ips, gateway)
@ -272,7 +281,7 @@ class LinuxBridge:
bridge_name, e)
return
def add_tap_interface(self, network_id, physical_interface, vlan_id,
def add_tap_interface(self, network_id, physical_network, vlan_id,
tap_device_name):
"""
If a VIF has been plugged into a network, this function will
@ -297,13 +306,25 @@ class LinuxBridge:
tap_device_name], root_helper=self.root_helper):
return False
if int(vlan_id) == lconst.FLAT_VLAN_ID:
self.ensure_flat_bridge(network_id, physical_interface)
if int(vlan_id) == lconst.LOCAL_VLAN_ID:
self.ensure_local_bridge(network_id)
else:
self.ensure_vlan_bridge(network_id, physical_interface, vlan_id)
physical_interface = self.interface_mappings.get(physical_network)
if not physical_interface:
LOG.error("No mapping for physical network %s" %
physical_network)
return False
if int(vlan_id) == lconst.FLAT_VLAN_ID:
self.ensure_flat_bridge(network_id, physical_interface)
else:
self.ensure_vlan_bridge(network_id, physical_interface,
vlan_id)
if utils.execute(['brctl', 'addif', bridge_name, tap_device_name],
root_helper=self.root_helper):
return False
LOG.debug("Done adding device %s to bridge %s" % (tap_device_name,
bridge_name))
return True
@ -317,19 +338,14 @@ class LinuxBridge:
"""
return False
physical_interface = self.interface_mappings.get(physical_network)
if not physical_interface:
LOG.error("No mapping for physical network %s" % physical_network)
return False
if interface_id.startswith(GATEWAY_INTERFACE_PREFIX):
return self.add_tap_interface(network_id,
physical_interface, vlan_id,
physical_network, vlan_id,
interface_id)
else:
tap_device_name = self.get_tap_device_name(interface_id)
return self.add_tap_interface(network_id,
physical_interface, vlan_id,
physical_network, vlan_id,
tap_device_name)
def delete_vlan_bridge(self, bridge_name):
@ -613,9 +629,18 @@ class LinuxBridgeQuantumAgentRPC:
self.setup_rpc(interface_mappings.values())
def setup_rpc(self, physical_interfaces):
# REVISIT try until one succeeds?
mac = utils.get_interface_mac(physical_interfaces[0])
if physical_interfaces:
mac = utils.get_interface_mac(physical_interfaces[0])
else:
devices = ip_lib.IPWrapper(self.root_helper).get_devices(True)
if devices:
mac = utils.get_interface_mac(devices[0].name)
else:
LOG.error("Unable to obtain MAC of any device for agent_id")
exit(1)
self.agent_id = '%s%s' % ('lb', (mac.replace(":", "")))
LOG.info("RPC agent_id: %s" % self.agent_id)
self.topic = topics.AGENT
self.plugin_rpc = agent_rpc.PluginApi(topics.PLUGIN)

View File

@ -19,11 +19,14 @@
from quantum.openstack.common import cfg
DEFAULT_VLAN_RANGES = ['default:1000:2999']
DEFAULT_INTERFACE_MAPPINGS = ['default:eth1']
DEFAULT_VLAN_RANGES = []
DEFAULT_INTERFACE_MAPPINGS = []
vlan_opts = [
cfg.StrOpt('tenant_network_type', default='local',
help="Network type for tenant networks "
"(local, vlan, or none)"),
cfg.ListOpt('network_vlan_ranges',
default=DEFAULT_VLAN_RANGES,
help="List of <physical_network>:<vlan_min>:<vlan_max> "

View File

@ -18,10 +18,10 @@
FLAT_VLAN_ID = -1
LOCAL_VLAN_ID = -2
PORT_UP = "ACTIVE"
PORT_DOWN = "DOWN"
VLANID = 'vlan_id'
PORT_ID = 'port-id'
NET_ID = 'net-id'
# Values for network_type
TYPE_FLAT = 'flat'
TYPE_VLAN = 'vlan'
TYPE_LOCAL = 'local'
TYPE_NONE = 'none'

View File

@ -45,7 +45,7 @@ class NetworkBinding(model_base.BASEV2):
network_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id', ondelete="CASCADE"),
primary_key=True)
physical_network = sa.Column(sa.String(64), nullable=False)
physical_network = sa.Column(sa.String(64))
vlan_id = sa.Column(sa.Integer, nullable=False)
def __init__(self, network_id, physical_network, vlan_id):

View File

@ -17,7 +17,7 @@ import logging
import sys
from quantum.api.v2 import attributes
from quantum.common import constants
from quantum.common import constants as q_const
from quantum.common import exceptions as q_exc
from quantum.common import topics
from quantum.db import api as db_api
@ -31,7 +31,7 @@ from quantum.openstack.common import cfg
from quantum.openstack.common import rpc
from quantum.openstack.common.rpc import dispatcher
from quantum.openstack.common.rpc import proxy
from quantum.plugins.linuxbridge.common import constants as lconst
from quantum.plugins.linuxbridge.common import constants
from quantum.plugins.linuxbridge.db import l2network_db_v2 as db
from quantum import policy
@ -73,7 +73,7 @@ class LinuxBridgeRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):
'port_id': port['id'],
'admin_state_up': port['admin_state_up']}
# Set the port status to UP
db.set_port_status(port['id'], constants.PORT_STATUS_ACTIVE)
db.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE)
else:
entry = {'device': device}
LOG.debug("%s can not be found in database", device)
@ -90,7 +90,7 @@ class LinuxBridgeRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):
entry = {'device': device,
'exists': True}
# Set port status to DOWN
db.set_port_status(port['id'], constants.PORT_STATUS_DOWN)
db.set_port_status(port['id'], q_const.PORT_STATUS_DOWN)
else:
entry = {'device': device,
'exists': False}
@ -159,6 +159,13 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
db.initialize()
self._parse_network_vlan_ranges()
db.sync_network_states(self.network_vlan_ranges)
self.tenant_network_type = cfg.CONF.VLANS.tenant_network_type
if self.tenant_network_type not in [constants.TYPE_LOCAL,
constants.TYPE_VLAN,
constants.TYPE_NONE]:
LOG.error("Invalid tenant_network_type: %s" %
self.tenant_network_type)
sys.exit(1)
self.agent_rpc = cfg.CONF.AGENT.rpc
self._setup_rpc()
LOG.debug("Linux Bridge Plugin initialization complete")
@ -218,12 +225,17 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
def _extend_network_dict_provider(self, context, network):
if self._check_provider_view_auth(context, network):
binding = db.get_network_binding(context.session, network['id'])
network[provider.PHYSICAL_NETWORK] = binding.physical_network
if binding.vlan_id == lconst.FLAT_VLAN_ID:
network[provider.NETWORK_TYPE] = 'flat'
if binding.vlan_id == constants.FLAT_VLAN_ID:
network[provider.NETWORK_TYPE] = constants.TYPE_FLAT
network[provider.PHYSICAL_NETWORK] = binding.physical_network
network[provider.SEGMENTATION_ID] = None
elif binding.vlan_id == constants.LOCAL_VLAN_ID:
network[provider.NETWORK_TYPE] = constants.TYPE_LOCAL
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
else:
network[provider.NETWORK_TYPE] = 'vlan'
network[provider.NETWORK_TYPE] = constants.TYPE_VLAN
network[provider.PHYSICAL_NETWORK] = binding.physical_network
network[provider.SEGMENTATION_ID] = binding.vlan_id
def _process_provider_create(self, context, attrs):
@ -245,13 +257,13 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
if not network_type_set:
msg = _("provider:network_type required")
raise q_exc.InvalidInput(error_message=msg)
elif network_type == 'flat':
elif network_type == constants.TYPE_FLAT:
if segmentation_id_set:
msg = _("provider:segmentation_id specified for flat network")
raise q_exc.InvalidInput(error_message=msg)
else:
segmentation_id = lconst.FLAT_VLAN_ID
elif network_type == 'vlan':
segmentation_id = constants.FLAT_VLAN_ID
elif network_type == constants.TYPE_VLAN:
if not segmentation_id_set:
msg = _("provider:segmentation_id required")
raise q_exc.InvalidInput(error_message=msg)
@ -259,20 +271,34 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:segmentation_id out of range "
"(1 through 4094)")
raise q_exc.InvalidInput(error_message=msg)
elif network_type == constants.TYPE_LOCAL:
if physical_network_set:
msg = _("provider:physical_network specified for local "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
physical_network = None
if segmentation_id_set:
msg = _("provider:segmentation_id specified for local "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
segmentation_id = constants.LOCAL_VLAN_ID
else:
msg = _("invalid provider:network_type %s" % network_type)
msg = _("provider:network_type %s not supported" % network_type)
raise q_exc.InvalidInput(error_message=msg)
if physical_network_set:
if physical_network not in self.network_vlan_ranges:
msg = _("unknown provider:physical_network %s" %
physical_network)
if network_type in [constants.TYPE_VLAN, constants.TYPE_FLAT]:
if physical_network_set:
if physical_network not in self.network_vlan_ranges:
msg = _("unknown provider:physical_network %s" %
physical_network)
raise q_exc.InvalidInput(error_message=msg)
elif 'default' in self.network_vlan_ranges:
physical_network = 'default'
else:
msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg)
elif 'default' in self.network_vlan_ranges:
physical_network = 'default'
else:
msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg)
return (network_type, physical_network, segmentation_id)
@ -303,9 +329,20 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
session = context.session
with session.begin(subtransactions=True):
if not network_type:
physical_network, vlan_id = db.reserve_network(session)
# tenant network
network_type = self.tenant_network_type
if network_type == constants.TYPE_NONE:
raise q_exc.TenantNetworksDisabled()
elif network_type == constants.TYPE_VLAN:
physical_network, vlan_id = db.reserve_network(session)
else: # TYPE_LOCAL
vlan_id = constants.LOCAL_VLAN_ID
else:
db.reserve_specific_network(session, physical_network, vlan_id)
# provider network
if network_type in [constants.TYPE_VLAN, constants.TYPE_FLAT]:
db.reserve_specific_network(session, physical_network,
vlan_id)
# no reservation needed for TYPE_LOCAL
net = super(LinuxBridgePluginV2, self).create_network(context,
network)
db.add_network_binding(session, net['id'],
@ -334,8 +371,9 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
binding = db.get_network_binding(session, id)
result = super(LinuxBridgePluginV2, self).delete_network(context,
id)
db.release_network(session, binding.physical_network,
binding.vlan_id, self.network_vlan_ranges)
if binding.vlan_id != constants.LOCAL_VLAN_ID:
db.release_network(session, binding.physical_network,
binding.vlan_id, self.network_vlan_ranges)
# the network_binding record is deleted via cascade from
# the network record, so explicit removal is not necessary
if self.agent_rpc:

View File

@ -229,7 +229,7 @@ class OVSQuantumAgent(object):
'''Provisions a local VLAN.
:param net_uuid: the uuid of the network associated with this vlan.
:param network_type: the type of the network ('gre', 'vlan', 'flat')
:param network_type: the network type ('gre', 'vlan', 'flat', 'local')
:param physical_network: the physical network for 'vlan' or 'flat'
:param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
'''
@ -277,6 +277,9 @@ class OVSQuantumAgent(object):
in_port=self.int_ofports[physical_network],
dl_vlan=segmentation_id,
actions="mod_vlan_vid:%s,normal" % lvid)
elif network_type == constants.TYPE_LOCAL:
# no flows needed for local networks
pass
else:
LOG.error("provisioning unknown network type %s for net-id=%s" %
(network_type, net_uuid))
@ -311,6 +314,9 @@ class OVSQuantumAgent(object):
br = self.int_br
br.delete_flows(in_port=self.int_ofports[lvm.physical_network],
dl_vlan=lvm.segmentation_id)
elif lvm.network_type == constants.TYPE_LOCAL:
# no flows needed for local networks
pass
else:
LOG.error("reclaiming unknown network type %s for net-id=%s" %
(lvm.network_type, net_uuid))
@ -325,7 +331,7 @@ class OVSQuantumAgent(object):
:param port: a ovslib.VifPort object.
:param net_uuid: the net_uuid this port is to be associated with.
:param network_type: the type of the network ('gre', 'vlan', 'flat')
:param network_type: the network type ('gre', 'vlan', 'flat', 'local')
:param physical_network: the physical network for 'vlan' or 'flat'
:param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
'''

View File

@ -17,8 +17,8 @@
from quantum.openstack.common import cfg
DEFAULT_BRIDGE_MAPPINGS = ['default:br-eth1']
DEFAULT_VLAN_RANGES = ['default:1000:2999']
DEFAULT_BRIDGE_MAPPINGS = []
DEFAULT_VLAN_RANGES = []
DEFAULT_TUNNEL_RANGES = []
database_opts = [
@ -34,6 +34,9 @@ ovs_opts = [
cfg.ListOpt('bridge_mappings',
default=DEFAULT_BRIDGE_MAPPINGS,
help="List of <physical_network>:<bridge>"),
cfg.StrOpt('tenant_network_type', default='local',
help="Network type for tenant networks "
"(local, vlan, gre, or none)"),
cfg.ListOpt('network_vlan_ranges',
default=DEFAULT_VLAN_RANGES,
help="List of <physical_network>:<vlan_min>:<vlan_max> "

View File

@ -23,6 +23,8 @@ TUNNEL = 'tunnel'
TYPE_FLAT = 'flat'
TYPE_VLAN = 'vlan'
TYPE_GRE = 'gre'
TYPE_LOCAL = 'local'
TYPE_NONE = 'none'
# Name prefixes for veth device pair linking the integration bridge
# with the physical bridge for a physical network

View File

@ -64,7 +64,8 @@ class NetworkBinding(model_base.BASEV2):
network_id = Column(String(36),
ForeignKey('networks.id', ondelete="CASCADE"),
primary_key=True)
network_type = Column(String(32), nullable=False) # 'gre', 'vlan', 'flat'
# 'gre', 'vlan', 'flat', 'local'
network_type = Column(String(32), nullable=False)
physical_network = Column(String(64))
segmentation_id = Column(Integer) # tunnel_id or vlan_id

View File

@ -197,6 +197,14 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
ovs_db_v2.sync_vlan_allocations(self.network_vlan_ranges)
self._parse_tunnel_id_ranges()
ovs_db_v2.sync_tunnel_allocations(self.tunnel_id_ranges)
self.tenant_network_type = cfg.CONF.OVS.tenant_network_type
if self.tenant_network_type not in [constants.TYPE_LOCAL,
constants.TYPE_VLAN,
constants.TYPE_GRE,
constants.TYPE_NONE]:
LOG.error("Invalid tenant_network_type: %s" %
self.tenant_network_type)
sys.exit(1)
self.agent_rpc = cfg.CONF.AGENT.rpc
self.setup_rpc()
@ -280,6 +288,9 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
elif binding.network_type == constants.TYPE_VLAN:
network[provider.PHYSICAL_NETWORK] = binding.physical_network
network[provider.SEGMENTATION_ID] = binding.segmentation_id
elif binding.network_type == constants.TYPE_LOCAL:
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
def _process_provider_create(self, context, attrs):
network_type = attrs.get(provider.NETWORK_TYPE)
@ -314,20 +325,44 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:segmentation_id out of range "
"(1 through 4094)")
raise q_exc.InvalidInput(error_message=msg)
elif network_type == constants.TYPE_GRE:
if physical_network_set:
msg = _("provider:physical_network specified for GRE "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
physical_network = None
if not segmentation_id_set:
msg = _("provider:segmentation_id required")
raise q_exc.InvalidInput(error_message=msg)
elif network_type == constants.TYPE_LOCAL:
if physical_network_set:
msg = _("provider:physical_network specified for local "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
physical_network = None
if segmentation_id_set:
msg = _("provider:segmentation_id specified for local "
"network")
raise q_exc.InvalidInput(error_message=msg)
else:
segmentation_id = None
else:
msg = _("invalid provider:network_type %s" % network_type)
msg = _("provider:network_type %s not supported" % network_type)
raise q_exc.InvalidInput(error_message=msg)
if physical_network_set:
if physical_network not in self.network_vlan_ranges:
msg = _("unknown provider:physical_network %s" %
physical_network)
if network_type in [constants.TYPE_VLAN, constants.TYPE_FLAT]:
if physical_network_set:
if physical_network not in self.network_vlan_ranges:
msg = _("unknown provider:physical_network %s" %
physical_network)
raise q_exc.InvalidInput(error_message=msg)
elif 'default' in self.network_vlan_ranges:
physical_network = 'default'
else:
msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg)
elif 'default' in self.network_vlan_ranges:
physical_network = 'default'
else:
msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg)
return (network_type, physical_network, segmentation_id)
@ -358,16 +393,24 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
session = context.session
with session.begin(subtransactions=True):
if not network_type:
try:
# tenant network
network_type = self.tenant_network_type
if network_type == constants.TYPE_NONE:
raise q_exc.TenantNetworksDisabled()
elif network_type == constants.TYPE_VLAN:
(physical_network,
segmentation_id) = ovs_db_v2.reserve_vlan(session)
network_type = constants.TYPE_VLAN
except q_exc.NoNetworkAvailable:
elif network_type == constants.TYPE_GRE:
segmentation_id = ovs_db_v2.reserve_tunnel(session)
network_type = constants.TYPE_GRE
# no reservation needed for TYPE_LOCAL
else:
ovs_db_v2.reserve_specific_vlan(session, physical_network,
segmentation_id)
# provider network
if network_type in [constants.TYPE_VLAN, constants.TYPE_FLAT]:
ovs_db_v2.reserve_specific_vlan(session, physical_network,
segmentation_id)
elif network_type == constants.TYPE_GRE:
ovs_db_v2.reserve_specific_tunnel(session, segmentation_id)
# no reservation needed for TYPE_LOCAL
net = super(OVSQuantumPluginV2, self).create_network(context,
network)
ovs_db_v2.add_network_binding(session, net['id'], network_type,
@ -400,7 +443,8 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
if binding.network_type == constants.TYPE_GRE:
ovs_db_v2.release_tunnel(session, binding.segmentation_id,
self.tunnel_id_ranges)
else:
elif binding.network_type in [constants.TYPE_VLAN,
constants.TYPE_FLAT]:
ovs_db_v2.release_vlan(session, binding.physical_network,
binding.segmentation_id,
self.network_vlan_ranges)

View File

@ -32,11 +32,10 @@ class ConfigurationTest(unittest.TestCase):
cfg.CONF.AGENT.polling_interval)
self.assertEqual('sudo',
cfg.CONF.AGENT.root_helper)
ranges = cfg.CONF.VLANS.network_vlan_ranges
self.assertEqual(1, len(ranges))
self.assertEqual('default:1000:2999', ranges[0])
mappings = cfg.CONF.LINUX_BRIDGE.physical_interface_mappings
self.assertEqual(1, len(mappings))
self.assertEqual('default:eth1', mappings[0])
self.assertEqual('local',
cfg.CONF.VLANS.tenant_network_type)
self.assertEqual(0,
len(cfg.CONF.VLANS.network_vlan_ranges))
self.assertEqual(0,
len(cfg.CONF.LINUX_BRIDGE.
physical_interface_mappings))

View File

@ -29,14 +29,7 @@ class ConfigurationTest(unittest.TestCase):
self.assertEqual(2, cfg.CONF.DATABASE.reconnect_interval)
self.assertEqual(2, cfg.CONF.AGENT.polling_interval)
self.assertEqual('sudo', cfg.CONF.AGENT.root_helper)
mappings = cfg.CONF.OVS.bridge_mappings
self.assertEqual(1, len(mappings))
self.assertEqual('default:br-eth1', mappings[0])
ranges = cfg.CONF.OVS.network_vlan_ranges
self.assertEqual(1, len(ranges))
self.assertEqual('default:1000:2999', ranges[0])
ranges = cfg.CONF.OVS.tunnel_id_ranges
self.assertEqual(0, len(ranges))
self.assertEqual('local', cfg.CONF.OVS.tenant_network_type)
self.assertEqual(0, len(cfg.CONF.OVS.bridge_mappings))
self.assertEqual(0, len(cfg.CONF.OVS.network_vlan_ranges))
self.assertEqual(0, len(cfg.CONF.OVS.tunnel_id_ranges))