Adding support for OVS Hybrid binding
Allows the OVS binding script to recognize if it has to do hybrid binding or not and operate accordingly. Closes-Bug: #1535828 Change-Id: I7c7d7b115b546c136a07880bc568662558dbc950
This commit is contained in:
parent
b822c22c8f
commit
cc05a7b903
@ -19,9 +19,11 @@ import pyroute2
|
|||||||
|
|
||||||
from kuryr.common import config
|
from kuryr.common import config
|
||||||
from kuryr.common import exceptions
|
from kuryr.common import exceptions
|
||||||
|
from kuryr import utils
|
||||||
|
|
||||||
|
|
||||||
CONTAINER_VETH_POSTFIX = '_c'
|
VETH_PREFIX = 'tap'
|
||||||
|
CONTAINER_VETH_PREFIX = 't_c'
|
||||||
BINDING_SUBCOMMAND = 'bind'
|
BINDING_SUBCOMMAND = 'bind'
|
||||||
DOWN = 'DOWN'
|
DOWN = 'DOWN'
|
||||||
FALLBACK_VIF_TYPE = 'unbound'
|
FALLBACK_VIF_TYPE = 'unbound'
|
||||||
@ -32,8 +34,8 @@ KIND_VETH = 'veth'
|
|||||||
MAC_ADDRESS_KEY = 'mac_address'
|
MAC_ADDRESS_KEY = 'mac_address'
|
||||||
SUBNET_ID_KEY = 'subnet_id'
|
SUBNET_ID_KEY = 'subnet_id'
|
||||||
UNBINDING_SUBCOMMAND = 'unbind'
|
UNBINDING_SUBCOMMAND = 'unbind'
|
||||||
VETH_POSTFIX = '-veth'
|
|
||||||
VIF_TYPE_KEY = 'binding:vif_type'
|
VIF_TYPE_KEY = 'binding:vif_type'
|
||||||
|
VIF_DETAILS_KEY = 'binding:vif_details'
|
||||||
|
|
||||||
_IPDB_CACHE = None
|
_IPDB_CACHE = None
|
||||||
_IPROUTE_CACHE = None
|
_IPROUTE_CACHE = None
|
||||||
@ -113,8 +115,8 @@ def port_bind(endpoint_id, neutron_port, neutron_subnets):
|
|||||||
"""
|
"""
|
||||||
ip = get_ipdb()
|
ip = get_ipdb()
|
||||||
|
|
||||||
ifname = endpoint_id[:8] + VETH_POSTFIX
|
ifname = VETH_PREFIX + endpoint_id[:8]
|
||||||
peer_name = ifname + CONTAINER_VETH_POSTFIX
|
peer_name = CONTAINER_VETH_PREFIX + ifname
|
||||||
subnets_dict = {subnet['id']: subnet for subnet in neutron_subnets}
|
subnets_dict = {subnet['id']: subnet for subnet in neutron_subnets}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -143,6 +145,7 @@ def port_bind(endpoint_id, neutron_port, neutron_subnets):
|
|||||||
'Could not configure the veth endpoint for the container.')
|
'Could not configure the veth endpoint for the container.')
|
||||||
|
|
||||||
vif_type = neutron_port.get(VIF_TYPE_KEY, FALLBACK_VIF_TYPE)
|
vif_type = neutron_port.get(VIF_TYPE_KEY, FALLBACK_VIF_TYPE)
|
||||||
|
vif_details = utils.string_mappings(neutron_port.get(VIF_DETAILS_KEY))
|
||||||
binding_exec_path = os.path.join(config.CONF.bindir, vif_type)
|
binding_exec_path = os.path.join(config.CONF.bindir, vif_type)
|
||||||
port_id = neutron_port['id']
|
port_id = neutron_port['id']
|
||||||
network_id = neutron_port['network_id']
|
network_id = neutron_port['network_id']
|
||||||
@ -151,7 +154,7 @@ def port_bind(endpoint_id, neutron_port, neutron_subnets):
|
|||||||
try:
|
try:
|
||||||
stdout, stderr = processutils.execute(
|
stdout, stderr = processutils.execute(
|
||||||
binding_exec_path, BINDING_SUBCOMMAND, port_id, ifname,
|
binding_exec_path, BINDING_SUBCOMMAND, port_id, ifname,
|
||||||
endpoint_id, mac_address, network_id, tenant_id,
|
endpoint_id, mac_address, network_id, tenant_id, vif_details,
|
||||||
run_as_root=True)
|
run_as_root=True)
|
||||||
except processutils.ProcessExecutionError:
|
except processutils.ProcessExecutionError:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
@ -171,13 +174,14 @@ def port_unbind(endpoint_id, neutron_port):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
vif_type = neutron_port.get(VIF_TYPE_KEY, FALLBACK_VIF_TYPE)
|
vif_type = neutron_port.get(VIF_TYPE_KEY, FALLBACK_VIF_TYPE)
|
||||||
|
vif_details = utils.string_mappings(neutron_port.get(VIF_DETAILS_KEY))
|
||||||
unbinding_exec_path = os.path.join(config.CONF.bindir, vif_type)
|
unbinding_exec_path = os.path.join(config.CONF.bindir, vif_type)
|
||||||
ifname = endpoint_id[:8] + VETH_POSTFIX
|
ifname = VETH_PREFIX + endpoint_id[:8]
|
||||||
port_id = neutron_port['id']
|
port_id = neutron_port['id']
|
||||||
mac_address = neutron_port['mac_address']
|
mac_address = neutron_port['mac_address']
|
||||||
stdout, stderr = processutils.execute(
|
stdout, stderr = processutils.execute(
|
||||||
unbinding_exec_path, UNBINDING_SUBCOMMAND, port_id, ifname,
|
unbinding_exec_path, UNBINDING_SUBCOMMAND, port_id, ifname,
|
||||||
endpoint_id, mac_address, run_as_root=True)
|
endpoint_id, mac_address, vif_details, run_as_root=True)
|
||||||
try:
|
try:
|
||||||
cleanup_veth(ifname)
|
cleanup_veth(ifname)
|
||||||
except pyroute2.netlink.NetlinkError:
|
except pyroute2.netlink.NetlinkError:
|
||||||
|
@ -47,7 +47,7 @@ class TestKuryrJoinFailures(base.TestKuryrFailures):
|
|||||||
fake_ifname = 'fake-veth'
|
fake_ifname = 'fake-veth'
|
||||||
fake_binding_response = (
|
fake_binding_response = (
|
||||||
fake_ifname,
|
fake_ifname,
|
||||||
fake_ifname + binding.CONTAINER_VETH_POSTFIX,
|
binding.CONTAINER_VETH_PREFIX + fake_ifname,
|
||||||
('fake stdout', '')
|
('fake stdout', '')
|
||||||
)
|
)
|
||||||
self.mox.StubOutWithMock(binding, 'port_bind')
|
self.mox.StubOutWithMock(binding, 'port_bind')
|
||||||
|
@ -167,3 +167,11 @@ def make_net_name(netid, tags=True):
|
|||||||
if tags:
|
if tags:
|
||||||
return const.NET_NAME_PREFIX + netid[:8]
|
return const.NET_NAME_PREFIX + netid[:8]
|
||||||
return netid
|
return netid
|
||||||
|
|
||||||
|
|
||||||
|
def string_mappings(mapping_list):
|
||||||
|
"""Make a string out of the mapping list"""
|
||||||
|
details = ''
|
||||||
|
if mapping_list:
|
||||||
|
details = '"' + str(mapping_list) + '"'
|
||||||
|
return details
|
||||||
|
@ -12,42 +12,98 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
INT_BRIDGE="br-int"
|
INT_BRIDGE="br-int"
|
||||||
|
HYBRID_PLUG="'ovs_hybrid_plug': True"
|
||||||
|
|
||||||
OPERATION=$1
|
OPERATION=$1
|
||||||
PORT=$2
|
PORT=$2
|
||||||
VETH=$3
|
VETH=$3
|
||||||
CONTAINER_UUID=$4
|
CONTAINER_UUID=$4
|
||||||
MAC_ADDRESS=$5
|
MAC_ADDRESS=$5
|
||||||
|
|
||||||
|
ovs_bind_port() {
|
||||||
bind_port() {
|
|
||||||
echo "plugging veth $VETH (Neutron port $PORT)..."
|
echo "plugging veth $VETH (Neutron port $PORT)..."
|
||||||
sudo ovs-vsctl -- --may-exist add-port $INT_BRIDGE $VETH -- \
|
ovs-vsctl -- --may-exist add-port $INT_BRIDGE $VETH -- \
|
||||||
set interface $VETH external_ids:attached-mac=$MAC_ADDRESS \
|
set interface $VETH external_ids:attached-mac=$MAC_ADDRESS \
|
||||||
external_ids:iface-id=$PORT external_ids:vm-uuid=$CONTAINER_UUID \
|
external_ids:iface-id=$PORT external_ids:vm-uuid=$CONTAINER_UUID \
|
||||||
external_ids:iface-status=active external_ids:owner=kuryr
|
external_ids:iface-status=active external_ids:owner=kuryr
|
||||||
}
|
}
|
||||||
|
|
||||||
unbind_port() {
|
ovs_unbind_port() {
|
||||||
echo "unplugging veth $PORT..."
|
echo "unplugging port $PORT..."
|
||||||
PORT=`sudo ovs-vsctl --data=bare --no-heading --columns=name \
|
MYPORT=`ovs-vsctl --data=bare --no-heading --columns=name \
|
||||||
find interface external_ids:iface-id=$PORT \
|
find interface external_ids:iface-id=$PORT \
|
||||||
external_ids:owner=kuryr`
|
external_ids:owner=kuryr`
|
||||||
if [ -z "$PORT" ]; then
|
if [ -z "$MYPORT" ]; then
|
||||||
echo >&2 "Failed to find port $PORT."
|
echo >&2 "Failed to find port $PORT."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sudo ovs-vsctl del-port $INT_BRIDGE $PORT
|
ovs-vsctl del-port $INT_BRIDGE $MYPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ovs_hybrid_bind_port() {
|
||||||
|
echo "... plugging veth $VETH (Neutron port $PORT) ..."
|
||||||
|
# create a linux bridge
|
||||||
|
br_name="qbr"${PORT:0:11}
|
||||||
|
ip link add name $br_name type bridge
|
||||||
|
echo 0 > /sys/devices/virtual/net/$br_name/bridge/forward_delay
|
||||||
|
echo 0 > /sys/devices/virtual/net/$br_name/bridge/stp_state
|
||||||
|
|
||||||
|
# connect the veth outside to linux bridge
|
||||||
|
ip link set $VETH up
|
||||||
|
ip link set dev $VETH master $br_name
|
||||||
|
# create a veth pair to connect linux bridge and the integration bridge
|
||||||
|
veth_lb="qvb"${PORT:0:11}
|
||||||
|
veth_ovs="qvo"${PORT:0:11}
|
||||||
|
ip link add $veth_lb type veth peer name $veth_ovs
|
||||||
|
|
||||||
|
# connect one end to the linux bridge
|
||||||
|
ip link set dev $veth_lb master $br_name
|
||||||
|
ip link set $br_name up
|
||||||
|
|
||||||
|
# connect one end to the ovs integration bridge
|
||||||
|
ovs-vsctl add-port $INT_BRIDGE $veth_ovs -- \
|
||||||
|
set interface $veth_ovs external_ids:attached-mac=$MAC_ADDRESS \
|
||||||
|
external_ids:iface-id=$PORT external_ids:vm-id=$CONTAINER_UUID \
|
||||||
|
external_ids:iface-status=active external_ids:owner=kuryr
|
||||||
|
|
||||||
|
ip link set $veth_lb up
|
||||||
|
ip link set $veth_ovs up
|
||||||
|
}
|
||||||
|
|
||||||
|
ovs_hybrid_unbind_port() {
|
||||||
|
echo "unplugging port $PORT ..."
|
||||||
|
br_name="qbr"${PORT:0:11}
|
||||||
|
veth_lb="qvb"${PORT:0:11}
|
||||||
|
veth_ovs="qvo"${PORT:0:11}
|
||||||
|
|
||||||
|
ip link set dev $veth_lb nomaster
|
||||||
|
ovs-vsctl del-port $veth_ovs
|
||||||
|
ip link delete $veth_lb type veth
|
||||||
|
|
||||||
|
ip link set $br_name down
|
||||||
|
ip link delete $br_name type bridge
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case $OPERATION in
|
case $OPERATION in
|
||||||
"bind")
|
"bind")
|
||||||
shift
|
shift
|
||||||
bind_port
|
if [ "${7/$HYBRID_PLUG}" = "$7" ]
|
||||||
|
then
|
||||||
|
ovs_bind_port
|
||||||
|
else
|
||||||
|
ovs_hybrid_bind_port
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
"unbind")
|
"unbind")
|
||||||
shift
|
shift
|
||||||
unbind_port
|
if [ "${5/$HYBRID_PLUG}" = "$5" ]
|
||||||
|
then
|
||||||
|
ovs_unbind_port
|
||||||
|
else
|
||||||
|
ovs_hybrid_unbind_port
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
Loading…
Reference in New Issue
Block a user