expose openvswitch GRE tunnel_id via provider API

The provider:vlan_id extended attribute is renamed to
provider:segmentation_id, and the openvswitch plugin returns the
tunnel_id of GRE networks as this attribute.

Fixes bug 1044375. Final patch in series that fixes bug 1037341 and
bug 1035492.

Detailed changes:

- Rename provider:vlan_id to provider:segmentation_id.
- Use consts for providernet extension's attribute names
- Remove validation clause from provider:segmentation_id resource attribute map data.
- Validate provider:segmentation_id in linuxbridge and openvswitch plugins.
- Rename physical_id to segmentation_id in the openvswitch schema, plugin, and agent.

Change-Id: Ic023b30b6e3275955bcb8a09c7936035dacf3f87
This commit is contained in:
Bob Kukura 2012-08-31 00:12:41 -04:00
parent 8fb4e6efe8
commit 493903c0d0
8 changed files with 116 additions and 95 deletions

View File

@ -15,21 +15,24 @@
from quantum.api.v2 import attributes from quantum.api.v2 import attributes
NETWORK_TYPE = 'provider:network_type'
PHYSICAL_NETWORK = 'provider:physical_network'
SEGMENTATION_ID = 'provider:segmentation_id'
EXTENDED_ATTRIBUTES_2_0 = { EXTENDED_ATTRIBUTES_2_0 = {
'networks': { 'networks': {
'provider:network_type': {'allow_post': True, 'allow_put': True, NETWORK_TYPE: {'allow_post': True, 'allow_put': True,
'validate': {'type:values': ['flat', 'validate': {'type:values': ['flat',
'vlan']}, 'vlan']},
'default': attributes.ATTR_NOT_SPECIFIED, 'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True}, 'is_visible': True},
'provider:physical_network': {'allow_post': True, 'allow_put': True, PHYSICAL_NETWORK: {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED, 'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True}, 'is_visible': True},
'provider:vlan_id': {'allow_post': True, 'allow_put': True, SEGMENTATION_ID: {'allow_post': True, 'allow_put': True,
'convert_to': int, 'convert_to': int,
'validate': {'type:range': (1, 4095)}, 'default': attributes.ATTR_NOT_SPECIFIED,
'default': attributes.ATTR_NOT_SPECIFIED, 'is_visible': True},
'is_visible': True},
} }
} }
@ -46,7 +49,7 @@ class Providernet(object):
To create a provider VLAN network using the CLI with admin rights: To create a provider VLAN network using the CLI with admin rights:
(shell) net-create --tenant_id <tenant-id> <net-name> \ (shell) net-create --tenant_id <tenant-id> <net-name> \
--provider:vlan_id <vlan-id> --provider:segmentation_id <vlan-id>
With admin rights, network dictionaries returned from CLI commands With admin rights, network dictionaries returned from CLI commands
will also include provider attributes. will also include provider attributes.

View File

@ -25,6 +25,7 @@ from quantum.db import db_base_plugin_v2
from quantum.db import dhcp_rpc_base from quantum.db import dhcp_rpc_base
from quantum.db import l3_db from quantum.db import l3_db
from quantum.db import models_v2 from quantum.db import models_v2
from quantum.extensions import providernet as provider
from quantum.openstack.common import context from quantum.openstack.common import context
from quantum.openstack.common import cfg from quantum.openstack.common import cfg
from quantum.openstack.common import rpc from quantum.openstack.common import rpc
@ -217,24 +218,25 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
def _extend_network_dict(self, context, network): def _extend_network_dict(self, context, network):
if self._check_provider_view_auth(context, network): if self._check_provider_view_auth(context, network):
binding = db.get_network_binding(context.session, network['id']) binding = db.get_network_binding(context.session, network['id'])
network['provider:physical_network'] = binding.physical_network network[provider.PHYSICAL_NETWORK] = binding.physical_network
if binding.vlan_id == lconst.FLAT_VLAN_ID: if binding.vlan_id == lconst.FLAT_VLAN_ID:
network['provider:network_type'] = 'flat' network[provider.NETWORK_TYPE] = 'flat'
network['provider:vlan_id'] = None network[provider.SEGMENTATION_ID] = None
else: else:
network['provider:network_type'] = 'vlan' network[provider.NETWORK_TYPE] = 'vlan'
network['provider:vlan_id'] = binding.vlan_id network[provider.SEGMENTATION_ID] = binding.vlan_id
def _process_provider_create(self, context, attrs): def _process_provider_create(self, context, attrs):
network_type = attrs.get('provider:network_type') network_type = attrs.get(provider.NETWORK_TYPE)
physical_network = attrs.get('provider:physical_network') physical_network = attrs.get(provider.PHYSICAL_NETWORK)
vlan_id = attrs.get('provider:vlan_id') segmentation_id = attrs.get(provider.SEGMENTATION_ID)
network_type_set = attributes.is_attr_set(network_type) network_type_set = attributes.is_attr_set(network_type)
physical_network_set = attributes.is_attr_set(physical_network) physical_network_set = attributes.is_attr_set(physical_network)
vlan_id_set = attributes.is_attr_set(vlan_id) segmentation_id_set = attributes.is_attr_set(segmentation_id)
if not (network_type_set or physical_network_set or vlan_id_set): if not (network_type_set or physical_network_set or
segmentation_id_set):
return (None, None, None) return (None, None, None)
# Authorize before exposing plugin details to client # Authorize before exposing plugin details to client
@ -244,14 +246,18 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:network_type required") msg = _("provider:network_type required")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
elif network_type == 'flat': elif network_type == 'flat':
if vlan_id_set: if segmentation_id_set:
msg = _("provider:vlan_id specified for flat network") msg = _("provider:segmentation_id specified for flat network")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
else: else:
vlan_id = lconst.FLAT_VLAN_ID segmentation_id = lconst.FLAT_VLAN_ID
elif network_type == 'vlan': elif network_type == 'vlan':
if not vlan_id_set: if not segmentation_id_set:
msg = _("provider:vlan_id required") msg = _("provider:segmentation_id required")
raise q_exc.InvalidInput(error_message=msg)
if segmentation_id < 1 or segmentation_id > 4094:
msg = _("provider:segmentation_id out of range "
"(1 through 4094)")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
else: else:
msg = _("invalid provider:network_type %s" % network_type) msg = _("invalid provider:network_type %s" % network_type)
@ -268,18 +274,19 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:physical_network required") msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
return (network_type, physical_network, vlan_id) return (network_type, physical_network, segmentation_id)
def _check_provider_update(self, context, attrs): def _check_provider_update(self, context, attrs):
network_type = attrs.get('provider:network_type') network_type = attrs.get(provider.NETWORK_TYPE)
physical_network = attrs.get('provider:physical_network') physical_network = attrs.get(provider.PHYSICAL_NETWORK)
vlan_id = attrs.get('provider:vlan_id') segmentation_id = attrs.get(provider.SEGMENTATION_ID)
network_type_set = attributes.is_attr_set(network_type) network_type_set = attributes.is_attr_set(network_type)
physical_network_set = attributes.is_attr_set(physical_network) physical_network_set = attributes.is_attr_set(physical_network)
vlan_id_set = attributes.is_attr_set(vlan_id) segmentation_id_set = attributes.is_attr_set(segmentation_id)
if not (network_type_set or physical_network_set or vlan_id_set): if not (network_type_set or physical_network_set or
segmentation_id_set):
return return
# Authorize before exposing plugin details to client # Authorize before exposing plugin details to client

View File

@ -51,20 +51,20 @@ DEAD_VLAN_TAG = "4095"
# A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac' # A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac'
# attributes set). # attributes set).
class LocalVLANMapping: class LocalVLANMapping:
def __init__(self, vlan, network_type, physical_network, physical_id, def __init__(self, vlan, network_type, physical_network, segmentation_id,
vif_ids=None): vif_ids=None):
if vif_ids is None: if vif_ids is None:
vif_ids = [] vif_ids = []
self.vlan = vlan self.vlan = vlan
self.network_type = network_type self.network_type = network_type
self.physical_network = physical_network self.physical_network = physical_network
self.physical_id = physical_id self.segmentation_id = segmentation_id
self.vif_ids = vif_ids self.vif_ids = vif_ids
def __str__(self): def __str__(self):
return ("lv-id = %s type = %s phys-net = %s phys-id = %s" % return ("lv-id = %s type = %s phys-net = %s phys-id = %s" %
(self.vlan, self.network_type, self.physical_network, (self.vlan, self.network_type, self.physical_network,
self.physical_id)) self.segmentation_id))
class Port(object): class Port(object):
@ -121,6 +121,8 @@ class OVSRpcCallbacks():
vif_port = self.int_br.get_vif_port_by_id(port['id']) vif_port = self.int_br.get_vif_port_by_id(port['id'])
if vif_port: if vif_port:
if port['admin_state_up']: if port['admin_state_up']:
# REVISIT(rkukura) This does not seem right. This
# needs to be the local_vlan.
vlan_id = kwargs.get('vlan_id') vlan_id = kwargs.get('vlan_id')
# create the networking for the port # create the networking for the port
self.int_br.set_db_attribute("Port", vif_port.port_name, self.int_br.set_db_attribute("Port", vif_port.port_name,
@ -236,13 +238,13 @@ class OVSQuantumAgent(object):
consumers) consumers)
def provision_local_vlan(self, net_uuid, network_type, physical_network, def provision_local_vlan(self, net_uuid, network_type, physical_network,
physical_id): segmentation_id):
'''Provisions a local VLAN. '''Provisions a local VLAN.
:param net_uuid: the uuid of the network associated with this 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 type of the network ('gre', 'vlan', 'flat')
:param physical_network: the physical network for 'vlan' or 'flat' :param physical_network: the physical network for 'vlan' or 'flat'
:param physical_id: the VLAN ID for 'vlan' or tunnel ID for 'tunnel' :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
''' '''
if not self.available_local_vlans: if not self.available_local_vlans:
@ -251,15 +253,16 @@ class OVSQuantumAgent(object):
LOG.info("Assigning %s as local vlan for net-id=%s" % (lvid, net_uuid)) LOG.info("Assigning %s as local vlan for net-id=%s" % (lvid, net_uuid))
self.local_vlan_map[net_uuid] = LocalVLANMapping(lvid, network_type, self.local_vlan_map[net_uuid] = LocalVLANMapping(lvid, network_type,
physical_network, physical_network,
physical_id) segmentation_id)
if network_type == constants.TYPE_GRE: if network_type == constants.TYPE_GRE:
# outbound # outbound
self.tun_br.add_flow(priority=4, in_port=self.patch_int_ofport, self.tun_br.add_flow(priority=4, in_port=self.patch_int_ofport,
dl_vlan=lvid, dl_vlan=lvid,
actions="set_tunnel:%s,normal" % physical_id) actions="set_tunnel:%s,normal" %
segmentation_id)
# inbound bcast/mcast # inbound bcast/mcast
self.tun_br.add_flow(priority=3, tun_id=physical_id, self.tun_br.add_flow(priority=3, tun_id=segmentation_id,
dl_dst="01:00:00:00:00:00/01:00:00:00:00:00", dl_dst="01:00:00:00:00:00/01:00:00:00:00:00",
actions="mod_vlan_vid:%s,output:%s" % actions="mod_vlan_vid:%s,output:%s" %
(lvid, self.patch_int_ofport)) (lvid, self.patch_int_ofport))
@ -281,11 +284,11 @@ class OVSQuantumAgent(object):
br.add_flow(priority=4, br.add_flow(priority=4,
in_port=self.phys_ofports[physical_network], in_port=self.phys_ofports[physical_network],
dl_vlan=lvid, dl_vlan=lvid,
actions="mod_vlan_vid:%s,normal" % physical_id) actions="mod_vlan_vid:%s,normal" % segmentation_id)
# inbound # inbound
self.int_br.add_flow(priority=3, self.int_br.add_flow(priority=3,
in_port=self.int_ofports[physical_network], in_port=self.int_ofports[physical_network],
dl_vlan=physical_id, dl_vlan=segmentation_id,
actions="mod_vlan_vid:%s,normal" % lvid) actions="mod_vlan_vid:%s,normal" % lvid)
else: else:
LOG.error("provisioning unknown network type %s for net-id=%s" % LOG.error("provisioning unknown network type %s for net-id=%s" %
@ -300,7 +303,7 @@ class OVSQuantumAgent(object):
LOG.info("reclaming vlan = %s from net-id = %s" % (lvm.vlan, net_uuid)) LOG.info("reclaming vlan = %s from net-id = %s" % (lvm.vlan, net_uuid))
if lvm.network_type == constants.TYPE_GRE: if lvm.network_type == constants.TYPE_GRE:
self.tun_br.delete_flows(tun_id=lvm.physical_id) self.tun_br.delete_flows(tun_id=lvm.segmentation_id)
self.tun_br.delete_flows(dl_vlan=lvm.vlan) self.tun_br.delete_flows(dl_vlan=lvm.vlan)
elif network_type == constants.TYPE_FLAT: elif network_type == constants.TYPE_FLAT:
# outbound # outbound
@ -319,7 +322,7 @@ class OVSQuantumAgent(object):
# inbound # inbound
br = self.int_br br = self.int_br
br.delete_flows(in_port=self.int_ofports[lvm.physical_network], br.delete_flows(in_port=self.int_ofports[lvm.physical_network],
dl_vlan=lvm.physical_id) dl_vlan=lvm.segmentation_id)
else: else:
LOG.error("reclaiming unknown network type %s for net-id=%s" % LOG.error("reclaiming unknown network type %s for net-id=%s" %
(lvm.network_type, net_uuid)) (lvm.network_type, net_uuid))
@ -328,7 +331,7 @@ class OVSQuantumAgent(object):
self.available_local_vlans.add(lvm.vlan) self.available_local_vlans.add(lvm.vlan)
def port_bound(self, port, net_uuid, def port_bound(self, port, net_uuid,
network_type, physical_network, physical_id): network_type, physical_network, segmentation_id):
'''Bind port to net_uuid/lsw_id and install flow for inbound traffic '''Bind port to net_uuid/lsw_id and install flow for inbound traffic
to vm. to vm.
@ -336,17 +339,17 @@ class OVSQuantumAgent(object):
:param net_uuid: the net_uuid this port is to be associated with. :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 type of the network ('gre', 'vlan', 'flat')
:param physical_network: the physical network for 'vlan' or 'flat' :param physical_network: the physical network for 'vlan' or 'flat'
:param physical_id: the VLAN ID for 'vlan' or tunnel ID for 'tunnel' :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
''' '''
if net_uuid not in self.local_vlan_map: if net_uuid not in self.local_vlan_map:
self.provision_local_vlan(net_uuid, network_type, self.provision_local_vlan(net_uuid, network_type,
physical_network, physical_id) physical_network, segmentation_id)
lvm = self.local_vlan_map[net_uuid] lvm = self.local_vlan_map[net_uuid]
lvm.vif_ids.append(port.vif_id) lvm.vif_ids.append(port.vif_id)
if network_type == constants.TYPE_GRE: if network_type == constants.TYPE_GRE:
# inbound unicast # inbound unicast
self.tun_br.add_flow(priority=3, tun_id=physical_id, self.tun_br.add_flow(priority=3, tun_id=segmentation_id,
dl_dst=port.vif_mac, dl_dst=port.vif_mac,
actions="mod_vlan_vid:%s,normal" % lvm.vlan) actions="mod_vlan_vid:%s,normal" % lvm.vlan)
@ -573,7 +576,7 @@ class OVSQuantumAgent(object):
self.port_bound(p, new_net_uuid, self.port_bound(p, new_net_uuid,
bind.network_type, bind.network_type,
bind.physical_network, bind.physical_network,
bind.physical_id) bind.segmentation_id)
all_bindings[p.vif_id].status = ( all_bindings[p.vif_id].status = (
q_const.PORT_STATUS_ACTIVE) q_const.PORT_STATUS_ACTIVE)
LOG.info("Port %s on net-id = %s bound to %s " % ( LOG.info("Port %s on net-id = %s bound to %s " % (
@ -633,7 +636,7 @@ class OVSQuantumAgent(object):
self.port_bound(port, details['network_id'], self.port_bound(port, details['network_id'],
details['network_type'], details['network_type'],
details['physical_network'], details['physical_network'],
details['physical_id']) details['segmentation_id'])
else: else:
self.port_unbound(port, details['network_id']) self.port_unbound(port, details['network_id'])
else: else:

View File

@ -51,11 +51,11 @@ def get_network_binding(session, network_id):
def add_network_binding(session, network_id, network_type, def add_network_binding(session, network_id, network_type,
physical_network, physical_id): physical_network, segmentation_id):
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
binding = ovs_models_v2.NetworkBinding(network_id, network_type, binding = ovs_models_v2.NetworkBinding(network_id, network_type,
physical_network, physical_network,
physical_id) segmentation_id)
session.add(binding) session.add(binding)

View File

@ -66,20 +66,20 @@ class NetworkBinding(model_base.BASEV2):
primary_key=True) primary_key=True)
network_type = Column(String(32), nullable=False) # 'gre', 'vlan', 'flat' network_type = Column(String(32), nullable=False) # 'gre', 'vlan', 'flat'
physical_network = Column(String(64)) physical_network = Column(String(64))
physical_id = Column(Integer) # tunnel_id or vlan_id segmentation_id = Column(Integer) # tunnel_id or vlan_id
def __init__(self, network_id, network_type, physical_network, def __init__(self, network_id, network_type, physical_network,
physical_id): segmentation_id):
self.network_id = network_id self.network_id = network_id
self.network_type = network_type self.network_type = network_type
self.physical_network = physical_network self.physical_network = physical_network
self.physical_id = physical_id self.segmentation_id = segmentation_id
def __repr__(self): def __repr__(self):
return "<NetworkBinding(%s,%s,%s,%d)>" % (self.network_id, return "<NetworkBinding(%s,%s,%s,%d)>" % (self.network_id,
self.network_type, self.network_type,
self.physical_network, self.physical_network,
self.physical_id) self.segmentation_id)
class TunnelIP(model_base.BASEV2): class TunnelIP(model_base.BASEV2):

View File

@ -31,6 +31,7 @@ from quantum.common import topics
from quantum.db import db_base_plugin_v2 from quantum.db import db_base_plugin_v2
from quantum.db import dhcp_rpc_base from quantum.db import dhcp_rpc_base
from quantum.db import l3_db from quantum.db import l3_db
from quantum.extensions import providernet as provider
from quantum.openstack.common import context from quantum.openstack.common import context
from quantum.openstack.common import cfg from quantum.openstack.common import cfg
from quantum.openstack.common import rpc from quantum.openstack.common import rpc
@ -75,7 +76,7 @@ class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):
'port_id': port['id'], 'port_id': port['id'],
'admin_state_up': port['admin_state_up'], 'admin_state_up': port['admin_state_up'],
'network_type': binding.network_type, 'network_type': binding.network_type,
'physical_id': binding.physical_id, 'segmentation_id': binding.segmentation_id,
'physical_network': binding.physical_network} 'physical_network': binding.physical_network}
# Set the port status to UP # Set the port status to UP
ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE) ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE)
@ -266,27 +267,28 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
if self._check_provider_view_auth(context, network): if self._check_provider_view_auth(context, network):
binding = ovs_db_v2.get_network_binding(context.session, binding = ovs_db_v2.get_network_binding(context.session,
network['id']) network['id'])
network['provider:network_type'] = binding.network_type network[provider.NETWORK_TYPE] = binding.network_type
if binding.network_type == constants.TYPE_GRE: if binding.network_type == constants.TYPE_GRE:
network['provider:physical_network'] = None network[provider.PHYSICAL_NETWORK] = None
network['provider:vlan_id'] = None network[provider.SEGMENTATION_ID] = binding.segmentation_id
elif binding.network_type == constants.TYPE_FLAT: elif binding.network_type == constants.TYPE_FLAT:
network['provider:physical_network'] = binding.physical_network network[provider.PHYSICAL_NETWORK] = binding.physical_network
network['provider:vlan_id'] = None network[provider.SEGMENTATION_ID] = None
elif binding.network_type == constants.TYPE_VLAN: elif binding.network_type == constants.TYPE_VLAN:
network['provider:physical_network'] = binding.physical_network network[provider.PHYSICAL_NETWORK] = binding.physical_network
network['provider:vlan_id'] = binding.physical_id network[provider.SEGMENTATION_ID] = binding.segmentation_id
def _process_provider_create(self, context, attrs): def _process_provider_create(self, context, attrs):
network_type = attrs.get('provider:network_type') network_type = attrs.get(provider.NETWORK_TYPE)
physical_network = attrs.get('provider:physical_network') physical_network = attrs.get(provider.PHYSICAL_NETWORK)
vlan_id = attrs.get('provider:vlan_id') segmentation_id = attrs.get(provider.SEGMENTATION_ID)
network_type_set = attributes.is_attr_set(network_type) network_type_set = attributes.is_attr_set(network_type)
physical_network_set = attributes.is_attr_set(physical_network) physical_network_set = attributes.is_attr_set(physical_network)
vlan_id_set = attributes.is_attr_set(vlan_id) segmentation_id_set = attributes.is_attr_set(segmentation_id)
if not (network_type_set or physical_network_set or vlan_id_set): if not (network_type_set or physical_network_set or
segmentation_id_set):
return (None, None, None) return (None, None, None)
# Authorize before exposing plugin details to client # Authorize before exposing plugin details to client
@ -296,14 +298,18 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:network_type required") msg = _("provider:network_type required")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
elif network_type == constants.TYPE_FLAT: elif network_type == constants.TYPE_FLAT:
if vlan_id_set: if segmentation_id_set:
msg = _("provider:vlan_id specified for flat network") msg = _("provider:segmentation_id specified for flat network")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
else: else:
vlan_id = constants.FLAT_VLAN_ID segmentation_id = constants.FLAT_VLAN_ID
elif network_type == constants.TYPE_VLAN: elif network_type == constants.TYPE_VLAN:
if not vlan_id_set: if not segmentation_id_set:
msg = _("provider:vlan_id required") msg = _("provider:segmentation_id required")
raise q_exc.InvalidInput(error_message=msg)
if segmentation_id < 1 or segmentation_id > 4094:
msg = _("provider:segmentation_id out of range "
"(1 through 4094)")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
else: else:
msg = _("invalid provider:network_type %s" % network_type) msg = _("invalid provider:network_type %s" % network_type)
@ -320,18 +326,19 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
msg = _("provider:physical_network required") msg = _("provider:physical_network required")
raise q_exc.InvalidInput(error_message=msg) raise q_exc.InvalidInput(error_message=msg)
return (network_type, physical_network, vlan_id) return (network_type, physical_network, segmentation_id)
def _check_provider_update(self, context, attrs): def _check_provider_update(self, context, attrs):
network_type = attrs.get('provider:network_type') network_type = attrs.get(provider.NETWORK_TYPE)
physical_network = attrs.get('provider:physical_network') physical_network = attrs.get(provider.PHYSICAL_NETWORK)
vlan_id = attrs.get('provider:vlan_id') segmentation_id = attrs.get(provider.SEGMENTATION_ID)
network_type_set = attributes.is_attr_set(network_type) network_type_set = attributes.is_attr_set(network_type)
physical_network_set = attributes.is_attr_set(physical_network) physical_network_set = attributes.is_attr_set(physical_network)
vlan_id_set = attributes.is_attr_set(vlan_id) segmentation_id_set = attributes.is_attr_set(segmentation_id)
if not (network_type_set or physical_network_set or vlan_id_set): if not (network_type_set or physical_network_set or
segmentation_id_set):
return return
# Authorize before exposing plugin details to client # Authorize before exposing plugin details to client
@ -342,26 +349,26 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
def create_network(self, context, network): def create_network(self, context, network):
(network_type, physical_network, (network_type, physical_network,
physical_id) = self._process_provider_create(context, segmentation_id) = self._process_provider_create(context,
network['network']) network['network'])
session = context.session session = context.session
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
if not network_type: if not network_type:
try: try:
(physical_network, (physical_network,
physical_id) = ovs_db_v2.reserve_vlan(session) segmentation_id) = ovs_db_v2.reserve_vlan(session)
network_type = constants.TYPE_VLAN network_type = constants.TYPE_VLAN
except q_exc.NoNetworkAvailable: except q_exc.NoNetworkAvailable:
physical_id = ovs_db_v2.reserve_tunnel(session) segmentation_id = ovs_db_v2.reserve_tunnel(session)
network_type = constants.TYPE_GRE network_type = constants.TYPE_GRE
else: else:
ovs_db_v2.reserve_specific_vlan(session, physical_network, ovs_db_v2.reserve_specific_vlan(session, physical_network,
physical_id) segmentation_id)
net = super(OVSQuantumPluginV2, self).create_network(context, net = super(OVSQuantumPluginV2, self).create_network(context,
network) network)
ovs_db_v2.add_network_binding(session, net['id'], network_type, ovs_db_v2.add_network_binding(session, net['id'], network_type,
physical_network, physical_id) physical_network, segmentation_id)
self._extend_network_dict(context, net) self._extend_network_dict(context, net)
# note - exception will rollback entire transaction # note - exception will rollback entire transaction
LOG.debug("Created network: %s" % net['id']) LOG.debug("Created network: %s" % net['id'])
@ -384,11 +391,11 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
result = super(OVSQuantumPluginV2, self).delete_network(context, result = super(OVSQuantumPluginV2, self).delete_network(context,
id) id)
if binding.network_type == constants.TYPE_GRE: if binding.network_type == constants.TYPE_GRE:
ovs_db_v2.release_tunnel(session, binding.physical_id, ovs_db_v2.release_tunnel(session, binding.segmentation_id,
self.tunnel_id_ranges) self.tunnel_id_ranges)
else: else:
ovs_db_v2.release_vlan(session, binding.physical_network, ovs_db_v2.release_vlan(session, binding.physical_network,
binding.physical_id, binding.segmentation_id,
self.network_vlan_ranges) self.network_vlan_ranges)
# the network_binding record is deleted via cascade from # the network_binding record is deleted via cascade from
# the network record, so explicit removal is not necessary # the network record, so explicit removal is not necessary
@ -418,9 +425,10 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
if original_port['admin_state_up'] != port['admin_state_up']: if original_port['admin_state_up'] != port['admin_state_up']:
binding = ovs_db_v2.get_network_binding(None, binding = ovs_db_v2.get_network_binding(None,
port['network_id']) port['network_id'])
# REVISIT(rkukura): needs other binding data as well # REVISIT(rkukura): Either all binding data or no
# binding data needed.
self.notifier.port_update(self.rpc_context, port, self.notifier.port_update(self.rpc_context, port,
binding.physical_id) binding.segmentation_id)
return port return port
def delete_port(self, context, id, l3_port_check=True): def delete_port(self, context, id, l3_port_check=True):

View File

@ -217,4 +217,4 @@ class NetworkBindingsTest(unittest2.TestCase):
self.assertEqual(binding.network_id, TEST_NETWORK_ID) self.assertEqual(binding.network_id, TEST_NETWORK_ID)
self.assertEqual(binding.network_type, 'vlan') self.assertEqual(binding.network_type, 'vlan')
self.assertEqual(binding.physical_network, PHYS_NET) self.assertEqual(binding.physical_network, PHYS_NET)
self.assertEqual(binding.physical_id, 1234) self.assertEqual(binding.segmentation_id, 1234)

View File

@ -105,7 +105,7 @@ class TunnelTest(unittest.TestCase):
self.mox.VerifyAll() self.mox.VerifyAll()
def testReclaimLocalVlan(self): def testReclaimLocalVlan(self):
self.mock_tun_bridge.delete_flows(tun_id=LVM.physical_id) self.mock_tun_bridge.delete_flows(tun_id=LVM.segmentation_id)
self.mock_tun_bridge.delete_flows(dl_vlan=LVM.vlan) self.mock_tun_bridge.delete_flows(dl_vlan=LVM.vlan)