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:
parent
8fb4e6efe8
commit
493903c0d0
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user