Merge "add local network type and use by default for tenant networks"
This commit is contained in:
commit
59b9b2577a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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":
|
||||
|
@ -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.LOCAL_VLAN_ID:
|
||||
self.ensure_local_bridge(network_id)
|
||||
else:
|
||||
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)
|
||||
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?
|
||||
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)
|
||||
|
||||
|
@ -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> "
|
||||
|
@ -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'
|
||||
|
@ -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):
|
||||
|
@ -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'])
|
||||
if binding.vlan_id == constants.FLAT_VLAN_ID:
|
||||
network[provider.NETWORK_TYPE] = constants.TYPE_FLAT
|
||||
network[provider.PHYSICAL_NETWORK] = binding.physical_network
|
||||
if binding.vlan_id == lconst.FLAT_VLAN_ID:
|
||||
network[provider.NETWORK_TYPE] = 'flat'
|
||||
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,10 +271,24 @@ 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:
|
||||
msg = _("invalid provider:network_type %s" % network_type)
|
||||
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 = _("provider:network_type %s not supported" % network_type)
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
|
||||
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" %
|
||||
@ -303,9 +329,20 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
if not network_type:
|
||||
# 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,6 +371,7 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
binding = db.get_network_binding(session, id)
|
||||
result = super(LinuxBridgePluginV2, self).delete_network(context,
|
||||
id)
|
||||
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
|
||||
|
@ -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'
|
||||
'''
|
||||
|
@ -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> "
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,10 +325,34 @@ 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:
|
||||
msg = _("invalid provider:network_type %s" % network_type)
|
||||
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 = _("provider:network_type %s not supported" % network_type)
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
|
||||
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" %
|
||||
@ -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:
|
||||
# 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)
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user