Nested-Containers: vlan driver
Add support to enable isolation of container's traffic within host(nova instances) using vlan segmentations. Partially Implements blueprint containers-in-instances Change-Id: If4800594adfac27a8f30dedac4787d79c8634b65
This commit is contained in:
parent
ac38fdc0b0
commit
116052f9db
@ -13,7 +13,8 @@ from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
|
||||
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
|
||||
segmentation_id=None):
|
||||
"""Binds the Neutron port to the network interface on the host.
|
||||
|
||||
:param endpoint_id: the ID of the endpoint as string
|
||||
@ -27,6 +28,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
python-neutronclient. Binding is being done for the
|
||||
port of a container which is running inside this Nova
|
||||
instance (either ipvlan/macvlan or a subport).
|
||||
:param segmentation_id: ID of the segment for container traffic isolation)
|
||||
:returns: the tuple of the names of the veth pair and the tuple of stdout
|
||||
and stderr returned by processutils.execute invoked with the
|
||||
executable script for binding
|
||||
@ -34,9 +36,9 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
processutils.ProcessExecutionError
|
||||
"""
|
||||
driver = importutils.import_module(cfg.CONF.binding.driver)
|
||||
|
||||
return driver.port_bind(endpoint_id, port, subnets, network=network,
|
||||
vm_port=vm_port)
|
||||
vm_port=vm_port,
|
||||
segmentation_id=segmentation_id)
|
||||
|
||||
|
||||
def port_unbind(endpoint_id, neutron_port):
|
||||
|
@ -20,7 +20,8 @@ KIND = 'ipvlan'
|
||||
IPVLAN_MODE_L2 = ifinfmsg.ifinfo.ipvlan_data.modes['IPVLAN_MODE_L2']
|
||||
|
||||
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
|
||||
segmentation_id=None):
|
||||
"""Binds the Neutron port to the network interface on the host.
|
||||
|
||||
:param endpoint_id: the ID of the endpoint as string
|
||||
@ -33,6 +34,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
:param vm_port: the Nova instance port dictionary, as returned by
|
||||
python-neutronclient. Container is running inside
|
||||
this instance (either ipvlan/macvlan or a subport)
|
||||
:param segmentation_id: ID of the segment for container traffic isolation)
|
||||
:returns: the tuple of the names of the veth pair and the tuple of stdout
|
||||
and stderr returned by processutils.execute invoked with the
|
||||
executable script for binding
|
||||
|
@ -19,7 +19,8 @@ KIND = 'macvlan'
|
||||
MACVLAN_MODE_BRIDGE = 'bridge'
|
||||
|
||||
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
|
||||
segmentation_id=None):
|
||||
"""Binds the Neutron port to the network interface on the host.
|
||||
|
||||
:param endpoint_id: the ID of the endpoint as string
|
||||
@ -32,6 +33,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
:param vm_port: the Nova instance port dictionary, as returned by
|
||||
python-neutronclient. Container is running inside
|
||||
instance.
|
||||
:param segmentation_id: ID of the segment for container traffic isolation)
|
||||
:returns: the tuple of the names of the veth pair and the tuple of stdout
|
||||
and stderr returned by processutils.execute invoked with the
|
||||
executable script for binding
|
||||
|
@ -32,7 +32,8 @@ VIF_DETAILS_KEY = 'binding:vif_details'
|
||||
VIF_TYPE_KEY = 'binding:vif_type'
|
||||
|
||||
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
|
||||
segmentation_id=None):
|
||||
"""Binds the Neutron port to the network interface on the host.
|
||||
|
||||
:param endpoint_id: the ID of the endpoint as string
|
||||
@ -46,6 +47,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None):
|
||||
python-neutronclient. Container port under binding is
|
||||
running inside this instance (either ipvlan/macvlan or
|
||||
a subport)
|
||||
:param segmentation_id: ID of the segment for container traffic isolation)
|
||||
:returns: the tuple of the names of the veth pair and the tuple of stdout
|
||||
and stderr returned by processutils.execute invoked with the
|
||||
executable script for binding
|
||||
|
56
kuryr/lib/binding/drivers/vlan.py
Normal file
56
kuryr/lib/binding/drivers/vlan.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""It only supports container-in-vm deployments"""
|
||||
|
||||
from kuryr.lib.binding.drivers import nested
|
||||
from kuryr.lib.binding.drivers import utils
|
||||
|
||||
KIND = 'vlan'
|
||||
|
||||
|
||||
def port_bind(endpoint_id, port, subnets, network=None,
|
||||
vm_port=None, segmentation_id=None):
|
||||
"""Binds the Neutron port to the network interface on the host.
|
||||
|
||||
:param endpoint_id: the ID of the endpoint as string
|
||||
:param port: the container Neutron port dictionary as returned by
|
||||
python-neutronclient
|
||||
:param subnets: an iterable of all the Neutron subnets which the
|
||||
endpoint is trying to join
|
||||
:param network: the Neutron network which the endpoint is trying to
|
||||
join
|
||||
:param vm_port: the Nova instance port dictionary, as returned by
|
||||
python-neutronclient. Container is running inside this
|
||||
instance (either ipvlan/macvlan or a subport)
|
||||
:param segmentation_id: ID of the segment for container traffic isolation)
|
||||
:returns: the tuple of the names of the veth pair and the tuple of stdout
|
||||
and stderr returned by processutils.execute invoked with the
|
||||
executable script for binding
|
||||
:raises: kuryr.common.exceptions.VethCreationFailure,
|
||||
processutils.ProcessExecutionError
|
||||
"""
|
||||
ip = utils.get_ipdb()
|
||||
port_id = port['id']
|
||||
_, devname = utils.get_veth_pair_names(port_id)
|
||||
link_iface = nested.get_link_iface(vm_port)
|
||||
with ip.create(ifname=devname, kind=KIND,
|
||||
link=ip.interfaces[link_iface],
|
||||
address=port.get(utils.MAC_ADDRESS_KEY),
|
||||
vlan_id=segmentation_id) as container_iface:
|
||||
utils._configure_container_iface(
|
||||
container_iface, subnets,
|
||||
fixed_ips=port.get(utils.FIXED_IP_KEY))
|
||||
|
||||
return None, devname, ('', None)
|
||||
|
||||
|
||||
port_unbind = nested.port_unbind
|
@ -18,3 +18,7 @@ DEVICE_OWNER = 'kuryr:container'
|
||||
NIC_NAME_LEN = 14
|
||||
VETH_PREFIX = 'tap'
|
||||
CONTAINER_VETH_PREFIX = 't_c'
|
||||
|
||||
# For VLAN type segmentation
|
||||
MIN_VLAN_TAG = 1
|
||||
MAX_VLAN_TAG = 4094
|
||||
|
@ -94,3 +94,19 @@ class ExportPortFailure(KuryrException):
|
||||
This exception is thrown when performing Neutron security group failed
|
||||
for an exported port and Kuryr can't proceed the expose further.
|
||||
"""
|
||||
|
||||
|
||||
class SegmentationIdAllocationFailure(KuryrException):
|
||||
"""Exception represents when segmentation id could not be allocated.
|
||||
|
||||
This exception is thrown when the segmentaion id for the isolation of
|
||||
container traffic could not be allocated and Kuryr can't proceed further.
|
||||
"""
|
||||
|
||||
|
||||
class SegmentationDriverBindingDriverCompatibilityFailure(KuryrException):
|
||||
"""Exception represents when no segmentation type driver is loaded.
|
||||
|
||||
This exception is thrown when configured binding driver does not have
|
||||
a supporting segmentation type driver.
|
||||
"""
|
||||
|
42
kuryr/lib/segmentation_type_drivers/__init__.py
Normal file
42
kuryr/lib/segmentation_type_drivers/__init__.py
Normal file
@ -0,0 +1,42 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
|
||||
from kuryr.lib import exceptions as ex
|
||||
|
||||
BASE_PATH = 'kuryr.lib.segmentation_type_drivers'
|
||||
|
||||
driver_name = cfg.CONF.binding.driver.rsplit('.', 1)[1]
|
||||
|
||||
# REVISIT(vikasc): Need to remove this if check
|
||||
if driver_name == 'vlan':
|
||||
seg_driver_path = '.'.join([BASE_PATH, driver_name])
|
||||
segmentation_driver = importutils.import_module(seg_driver_path)
|
||||
driver = segmentation_driver.SegmentationDriver()
|
||||
|
||||
|
||||
def allocate_segmentation_id(allocated_ids=set()):
|
||||
"""Allocates a segmentation ID."""
|
||||
try:
|
||||
id = driver.allocate_segmentation_id(allocated_ids)
|
||||
except NameError:
|
||||
raise ex.SegmentationDriverBindingDriverCompatibilityFailure
|
||||
return id
|
||||
|
||||
|
||||
def release_segmentation_id(id):
|
||||
"""Releases the segmentation ID."""
|
||||
try:
|
||||
driver.release_segmentation_id(id)
|
||||
except NameError:
|
||||
raise ex.SegmentationDriverBindingDriverCompatibilityFailure
|
33
kuryr/lib/segmentation_type_drivers/vlan.py
Normal file
33
kuryr/lib/segmentation_type_drivers/vlan.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from six import moves
|
||||
|
||||
from kuryr.lib import constants as const
|
||||
from kuryr.lib import exceptions
|
||||
|
||||
|
||||
class SegmentationDriver(object):
|
||||
def __init__(self):
|
||||
self.available_local_vlans = set(moves.range(const.MIN_VLAN_TAG,
|
||||
const.MAX_VLAN_TAG + 1))
|
||||
|
||||
def allocate_segmentation_id(self, allocated_ids=set()):
|
||||
self.available_local_vlans.difference_update(allocated_ids)
|
||||
try:
|
||||
allocated = self.available_local_vlans.pop()
|
||||
except KeyError:
|
||||
raise exceptions.segmentationIdAllocationFailure
|
||||
|
||||
return allocated
|
||||
|
||||
def release_segmentation_id(self, id):
|
||||
self.available_local_vlans.add(id)
|
Loading…
Reference in New Issue
Block a user