| ... | ... |
@@ -1041,17 +1041,12 @@ |
| 1041 | 1041 |
{
|
| 1042 | 1042 |
"ImportPath": "github.com/openshift/openshift-sdn/ovssubnet", |
| 1043 | 1043 |
"Comment": "v0.1-110-gcdd9955", |
| 1044 |
- "Rev": "cdd9955dc602abe8ef2d934a3c39417375c486c6" |
|
| 1045 |
- }, |
|
| 1046 |
- {
|
|
| 1047 |
- "ImportPath": "github.com/openshift/openshift-sdn/pkg/api", |
|
| 1048 |
- "Comment": "v0.1-110-gcdd9955", |
|
| 1049 |
- "Rev": "cdd9955dc602abe8ef2d934a3c39417375c486c6" |
|
| 1044 |
+ "Rev": "74738c359b670c6e12435c1af10ee2802a4b0b64" |
|
| 1050 | 1045 |
}, |
| 1051 | 1046 |
{
|
| 1052 | 1047 |
"ImportPath": "github.com/openshift/openshift-sdn/pkg/netutils", |
| 1053 | 1048 |
"Comment": "v0.1-110-gcdd9955", |
| 1054 |
- "Rev": "cdd9955dc602abe8ef2d934a3c39417375c486c6" |
|
| 1049 |
+ "Rev": "a15dc76526039229cfb0c93a4c0389d226550bc9" |
|
| 1055 | 1050 |
}, |
| 1056 | 1051 |
{
|
| 1057 | 1052 |
"ImportPath": "github.com/openshift/source-to-image/pkg/api", |
| 1058 | 1053 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,66 @@ |
| 0 |
+package api |
|
| 1 |
+ |
|
| 2 |
+type EventType string |
|
| 3 |
+ |
|
| 4 |
+const ( |
|
| 5 |
+ Added EventType = "ADDED" |
|
| 6 |
+ Deleted EventType = "DELETED" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+type SubnetRegistry interface {
|
|
| 10 |
+ InitSubnets() error |
|
| 11 |
+ GetSubnets() (*[]Subnet, error) |
|
| 12 |
+ GetSubnet(minion string) (*Subnet, error) |
|
| 13 |
+ DeleteSubnet(minion string) error |
|
| 14 |
+ CreateSubnet(sn string, sub *Subnet) error |
|
| 15 |
+ WatchSubnets(receiver chan *SubnetEvent, stop chan bool) error |
|
| 16 |
+ |
|
| 17 |
+ InitMinions() error |
|
| 18 |
+ GetMinions() (*[]string, error) |
|
| 19 |
+ CreateMinion(minion string, data string) error |
|
| 20 |
+ WatchMinions(receiver chan *MinionEvent, stop chan bool) error |
|
| 21 |
+ |
|
| 22 |
+ WriteNetworkConfig(network string, subnetLength uint) error |
|
| 23 |
+ GetContainerNetwork() (string, error) |
|
| 24 |
+ GetSubnetLength() (uint64, error) |
|
| 25 |
+ CheckEtcdIsAlive(seconds uint64) bool |
|
| 26 |
+ |
|
| 27 |
+ WatchNamespaces(receiver chan *NamespaceEvent, stop chan bool) error |
|
| 28 |
+ WatchNetNamespaces(receiver chan *NetNamespaceEvent, stop chan bool) error |
|
| 29 |
+ GetNetNamespaces() ([]NetNamespace, error) |
|
| 30 |
+ GetNetNamespace(name string) (NetNamespace, error) |
|
| 31 |
+ WriteNetNamespace(name string, id uint) error |
|
| 32 |
+ DeleteNetNamespace(name string) error |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+type SubnetEvent struct {
|
|
| 36 |
+ Type EventType |
|
| 37 |
+ Minion string |
|
| 38 |
+ Sub Subnet |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+type MinionEvent struct {
|
|
| 42 |
+ Type EventType |
|
| 43 |
+ Minion string |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+type Subnet struct {
|
|
| 47 |
+ Minion string |
|
| 48 |
+ Sub string |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+type NetNamespace struct {
|
|
| 52 |
+ Name string |
|
| 53 |
+ NetID uint |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+type NetNamespaceEvent struct {
|
|
| 57 |
+ Type EventType |
|
| 58 |
+ Name string |
|
| 59 |
+ NetID uint |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+type NamespaceEvent struct {
|
|
| 63 |
+ Type EventType |
|
| 64 |
+ Name string |
|
| 65 |
+} |
| 0 | 66 |
deleted file mode 100644 |
| ... | ... |
@@ -1,82 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
-set -ex |
|
| 3 |
- |
|
| 4 |
-lock_file=/var/lock/openshift-sdn.lock |
|
| 5 |
- |
|
| 6 |
-action=$1 |
|
| 7 |
-pod_namespace=$2 |
|
| 8 |
-pod_name=$3 |
|
| 9 |
-net_container=$4 |
|
| 10 |
- |
|
| 11 |
-lockwrap() {
|
|
| 12 |
- ( |
|
| 13 |
- flock 200 |
|
| 14 |
- "$@" |
|
| 15 |
- ) 200>${lock_file}
|
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-Init() {
|
|
| 19 |
- true |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-Setup() {
|
|
| 23 |
- source /etc/openshift-sdn/config.env |
|
| 24 |
- cluster_subnet=${OPENSHIFT_CLUSTER_SUBNET}
|
|
| 25 |
- tap_ip=${OPENSHIFT_SDN_TAP1_ADDR}
|
|
| 26 |
- |
|
| 27 |
- pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 28 |
- network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 29 |
- if [ "${network_mode}" == "host" ]; then
|
|
| 30 |
- # quit, nothing for the SDN here |
|
| 31 |
- exit 0 |
|
| 32 |
- fi |
|
| 33 |
- ipaddr=$(docker inspect --format "{{.NetworkSettings.IPAddress}}" ${net_container})
|
|
| 34 |
- new_ip=$ipaddr |
|
| 35 |
- ipaddr_sub=$(docker inspect --format "{{.NetworkSettings.IPPrefixLen}}" ${net_container})
|
|
| 36 |
- docker_gateway=$(docker inspect --format "{{.NetworkSettings.Gateway}}" ${net_container})
|
|
| 37 |
- veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 38 |
- veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 39 |
- |
|
| 40 |
- brctl delif lbr0 $veth_host |
|
| 41 |
- ovs-vsctl add-port br0 ${veth_host}
|
|
| 42 |
- ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 43 |
- ovs-ofctl -O OpenFlow13 add-flow br0 "table=0,cookie=0x${ovs_port},priority=100,ip,nw_dst=${new_ip},actions=output:${ovs_port}"
|
|
| 44 |
- ovs-ofctl -O OpenFlow13 add-flow br0 "table=0,cookie=0x${ovs_port},priority=100,arp,nw_dst=${new_ip},actions=output:${ovs_port}"
|
|
| 45 |
- |
|
| 46 |
- add_subnet_route="ip route add ${cluster_subnet} dev eth0 proto kernel scope link src $ipaddr"
|
|
| 47 |
- nsenter -n -t $pid -- $add_subnet_route |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-Teardown() {
|
|
| 51 |
- source /etc/openshift-sdn/config.env |
|
| 52 |
- cluster_subnet=${OPENSHIFT_CLUSTER_SUBNET}
|
|
| 53 |
- tap_ip=${OPENSHIFT_SDN_TAP1_ADDR}
|
|
| 54 |
- |
|
| 55 |
- pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 56 |
- network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 57 |
- if [ "${network_mode}" == "host" ]; then
|
|
| 58 |
- # quit, nothing for the SDN here |
|
| 59 |
- exit 0 |
|
| 60 |
- fi |
|
| 61 |
- veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 62 |
- veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 63 |
- ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 64 |
- ovs-vsctl del-port $veth_host |
|
| 65 |
- ovs-ofctl -O OpenFlow13 del-flows br0 "table=0,cookie=0x${ovs_port}/0xffffffff"
|
|
| 66 |
-} |
|
| 67 |
- |
|
| 68 |
-case "$action" in |
|
| 69 |
- init) |
|
| 70 |
- lockwrap Init |
|
| 71 |
- ;; |
|
| 72 |
- setup) |
|
| 73 |
- lockwrap Setup |
|
| 74 |
- ;; |
|
| 75 |
- teardown) |
|
| 76 |
- lockwrap Teardown |
|
| 77 |
- ;; |
|
| 78 |
- *) |
|
| 79 |
- echo "Bad input: $@" |
|
| 80 |
- exit 1 |
|
| 81 |
-esac |
|
| 82 |
- |
| 83 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,120 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
- |
|
| 3 |
-set -ex |
|
| 4 |
- |
|
| 5 |
-lock_file=/var/lock/openshift-sdn.lock |
|
| 6 |
-subnet_gateway=$1 |
|
| 7 |
-subnet=$2 |
|
| 8 |
-cluster_subnet=$3 |
|
| 9 |
-subnet_mask_len=$4 |
|
| 10 |
-tun_gateway=$5 |
|
| 11 |
-printf 'Container network is "%s"; local host has subnet "%s" and gateway "%s".\n' "${cluster_subnet}" "${subnet}" "${subnet_gateway}"
|
|
| 12 |
-TUN=tun0 |
|
| 13 |
- |
|
| 14 |
-# Synchronize code execution with a file lock. |
|
| 15 |
-function lockwrap() {
|
|
| 16 |
- ( |
|
| 17 |
- flock 200 |
|
| 18 |
- "$@" |
|
| 19 |
- ) 200>${lock_file}
|
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-function setup_required() {
|
|
| 23 |
- ip=$(echo `ip a s lbr0 2>/dev/null|awk '/inet / {print $2}'`)
|
|
| 24 |
- if [ "$ip" != "${subnet_gateway}/${subnet_mask_len}" ]; then
|
|
| 25 |
- return 0 |
|
| 26 |
- fi |
|
| 27 |
- if ! grep -q lbr0 /run/openshift-sdn/docker-network; then |
|
| 28 |
- return 0 |
|
| 29 |
- fi |
|
| 30 |
- return 1 |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-function setup() {
|
|
| 34 |
- # clear config file |
|
| 35 |
- rm -f /etc/openshift-sdn/config.env |
|
| 36 |
- |
|
| 37 |
- ## openvswitch |
|
| 38 |
- ovs-vsctl del-br br0 || true |
|
| 39 |
- ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure |
|
| 40 |
- ovs-vsctl set bridge br0 protocols=OpenFlow13 |
|
| 41 |
- ovs-vsctl del-port br0 vxlan0 || true |
|
| 42 |
- ovs-vsctl add-port br0 vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip="flow" options:key="flow" ofport_request=1 |
|
| 43 |
- ovs-vsctl add-port br0 ${TUN} -- set Interface ${TUN} type=internal ofport_request=2
|
|
| 44 |
- |
|
| 45 |
- ip link del vlinuxbr || true |
|
| 46 |
- ip link add vlinuxbr type veth peer name vovsbr |
|
| 47 |
- ip link set vlinuxbr up |
|
| 48 |
- ip link set vovsbr up |
|
| 49 |
- ip link set vlinuxbr txqueuelen 0 |
|
| 50 |
- ip link set vovsbr txqueuelen 0 |
|
| 51 |
- |
|
| 52 |
- ovs-vsctl del-port br0 vovsbr || true |
|
| 53 |
- ovs-vsctl add-port br0 vovsbr -- set Interface vovsbr ofport_request=9 |
|
| 54 |
- |
|
| 55 |
- ## linux bridge |
|
| 56 |
- ip link set lbr0 down || true |
|
| 57 |
- brctl delbr lbr0 || true |
|
| 58 |
- brctl addbr lbr0 |
|
| 59 |
- ip addr add ${subnet_gateway}/${subnet_mask_len} dev lbr0
|
|
| 60 |
- ip link set lbr0 up |
|
| 61 |
- brctl addif lbr0 vlinuxbr |
|
| 62 |
- |
|
| 63 |
- # setup tun address |
|
| 64 |
- ip addr add ${tun_gateway}/${subnet_mask_len} dev ${TUN}
|
|
| 65 |
- ip link set ${TUN} up
|
|
| 66 |
- ip route add ${cluster_subnet} dev ${TUN} proto kernel scope link
|
|
| 67 |
- |
|
| 68 |
- ## iptables |
|
| 69 |
- iptables -t nat -D POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE || true
|
|
| 70 |
- iptables -t nat -A POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE
|
|
| 71 |
- iptables -D INPUT -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT || true |
|
| 72 |
- iptables -D INPUT -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT || true
|
|
| 73 |
- lineno=$(iptables -nvL INPUT --line-numbers | grep "state RELATED,ESTABLISHED" | awk '{print $1}')
|
|
| 74 |
- iptables -I INPUT $lineno -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT |
|
| 75 |
- iptables -I INPUT $((lineno+1)) -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT
|
|
| 76 |
- fwd_lineno=$(iptables -nvL FORWARD --line-numbers | grep "reject-with icmp-host-prohibited" | tail -n 1 | awk '{print $1}')
|
|
| 77 |
- iptables -I FORWARD $fwd_lineno -d ${cluster_subnet} -j ACCEPT
|
|
| 78 |
- iptables -I FORWARD $fwd_lineno -s ${cluster_subnet} -j ACCEPT
|
|
| 79 |
- |
|
| 80 |
- ## docker |
|
| 81 |
- if [[ -z "${DOCKER_NETWORK_OPTIONS}" ]]
|
|
| 82 |
- then |
|
| 83 |
- DOCKER_NETWORK_OPTIONS='-b=lbr0 --mtu=1450' |
|
| 84 |
- fi |
|
| 85 |
- |
|
| 86 |
- mkdir -p /run/openshift-sdn |
|
| 87 |
- cat <<EOF > /run/openshift-sdn/docker-network |
|
| 88 |
-# This file has been modified by openshift-sdn. Please modify the |
|
| 89 |
-# DOCKER_NETWORK_OPTIONS variable in /etc/sysconfig/openshift-node if this |
|
| 90 |
-# is an integrated install or /etc/sysconfig/openshift-sdn-node if this is a |
|
| 91 |
-# standalone install. |
|
| 92 |
- |
|
| 93 |
-DOCKER_NETWORK_OPTIONS='${DOCKER_NETWORK_OPTIONS}'
|
|
| 94 |
-EOF |
|
| 95 |
- |
|
| 96 |
- systemctl daemon-reload |
|
| 97 |
- systemctl restart docker.service |
|
| 98 |
- |
|
| 99 |
- # disable iptables for lbr0 |
|
| 100 |
- # for kernel version 3.18+, module br_netfilter needs to be loaded upfront |
|
| 101 |
- # for older ones, br_netfilter may not exist, but is covered by bridge (bridge-utils) |
|
| 102 |
- modprobe br_netfilter || true |
|
| 103 |
- sysctl -w net.bridge.bridge-nf-call-iptables=0 |
|
| 104 |
- |
|
| 105 |
- # delete the subnet routing entry created because of lbr0 |
|
| 106 |
- ip route del ${subnet} dev lbr0 proto kernel scope link src ${subnet_gateway} || true
|
|
| 107 |
- |
|
| 108 |
- mkdir -p /etc/openshift-sdn |
|
| 109 |
- echo "export OPENSHIFT_SDN_TAP1_ADDR=${tun_gateway}" >& "/etc/openshift-sdn/config.env"
|
|
| 110 |
- echo "export OPENSHIFT_CLUSTER_SUBNET=${cluster_subnet}" >> "/etc/openshift-sdn/config.env"
|
|
| 111 |
-} |
|
| 112 |
- |
|
| 113 |
-set +e |
|
| 114 |
-if ! setup_required; then |
|
| 115 |
- echo "SDN setup not required." |
|
| 116 |
- exit 140 |
|
| 117 |
-fi |
|
| 118 |
-set -e |
|
| 119 |
- |
|
| 120 |
-lockwrap setup |
| 121 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,68 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
- |
|
| 3 |
-set -ex |
|
| 4 |
- |
|
| 5 |
-subnet_gateway=$1 |
|
| 6 |
-subnet=$2 |
|
| 7 |
-container_network=$3 |
|
| 8 |
-subnet_mask_len=$4 |
|
| 9 |
-printf 'Container network is "%s"; local host has subnet "%s" and gateway "%s".\n' "${container_network}" "${subnet}" "${subnet_gateway}"
|
|
| 10 |
- |
|
| 11 |
-## openvswitch |
|
| 12 |
-ovs-vsctl del-br br0 || true |
|
| 13 |
-ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure |
|
| 14 |
-ovs-vsctl set bridge br0 protocols=OpenFlow13 |
|
| 15 |
-ovs-vsctl del-port br0 vxlan0 || true |
|
| 16 |
-ovs-vsctl add-port br0 vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip="flow" options:key="flow" ofport_request=10 |
|
| 17 |
-ip link del vlinuxbr || true |
|
| 18 |
-ip link add vlinuxbr type veth peer name vovsbr |
|
| 19 |
-ip link set vlinuxbr up |
|
| 20 |
-ip link set vovsbr up |
|
| 21 |
-ip link set vlinuxbr txqueuelen 0 |
|
| 22 |
-ip link set vovsbr txqueuelen 0 |
|
| 23 |
- |
|
| 24 |
-ovs-vsctl del-port br0 vovsbr || true |
|
| 25 |
-ovs-vsctl add-port br0 vovsbr -- set Interface vovsbr ofport_request=9 |
|
| 26 |
- |
|
| 27 |
-## linux bridge |
|
| 28 |
-ip link set lbr0 down || true |
|
| 29 |
-brctl delbr lbr0 || true |
|
| 30 |
-brctl addbr lbr0 |
|
| 31 |
-ip addr add ${subnet_gateway}/${subnet_mask_len} dev lbr0
|
|
| 32 |
-ip link set lbr0 up |
|
| 33 |
-brctl addif lbr0 vlinuxbr |
|
| 34 |
-ip route del ${subnet} dev lbr0 proto kernel scope link src ${subnet_gateway} || true
|
|
| 35 |
-ip route add ${container_network} dev lbr0 proto kernel scope link src ${subnet_gateway}
|
|
| 36 |
- |
|
| 37 |
- |
|
| 38 |
-## iptables |
|
| 39 |
-iptables -t nat -D POSTROUTING -s ${container_network} ! -d ${container_network} -j MASQUERADE || true
|
|
| 40 |
-iptables -t nat -A POSTROUTING -s ${container_network} ! -d ${container_network} -j MASQUERADE
|
|
| 41 |
-iptables -D INPUT -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT || true |
|
| 42 |
-iptables -D INPUT -i lbr0 -m comment --comment "traffic from docker" -j ACCEPT || true |
|
| 43 |
-lineno=$(iptables -nvL INPUT --line-numbers | grep "state RELATED,ESTABLISHED" | awk '{print $1}')
|
|
| 44 |
-iptables -I INPUT $lineno -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT |
|
| 45 |
-iptables -I INPUT $((lineno+1)) -i lbr0 -m comment --comment "traffic from docker" -j ACCEPT |
|
| 46 |
-fwd_lineno=$(iptables -nvL FORWARD --line-numbers | grep "reject-with icmp-host-prohibited" | tail -n 1 | awk '{print $1}')
|
|
| 47 |
-iptables -I FORWARD $fwd_lineno -d ${container_network} -j ACCEPT
|
|
| 48 |
-iptables -I FORWARD $fwd_lineno -s ${container_network} -j ACCEPT
|
|
| 49 |
- |
|
| 50 |
- |
|
| 51 |
-## docker |
|
| 52 |
-if [[ -z "${DOCKER_NETWORK_OPTIONS}" ]]
|
|
| 53 |
-then |
|
| 54 |
- DOCKER_NETWORK_OPTIONS='-b=lbr0 --mtu=1450' |
|
| 55 |
-fi |
|
| 56 |
- |
|
| 57 |
-mkdir -p /run/openshift-sdn |
|
| 58 |
-cat <<EOF > /run/openshift-sdn/docker-network |
|
| 59 |
-# This file has been modified by openshift-sdn. Please modify the |
|
| 60 |
-# DOCKER_NETWORK_OPTIONS variable in /etc/sysconfig/openshift-node if this |
|
| 61 |
-# is an integrated install or /etc/sysconfig/openshift-sdn-node if this is a |
|
| 62 |
-# standalone install. |
|
| 63 |
- |
|
| 64 |
-DOCKER_NETWORK_OPTIONS='${DOCKER_NETWORK_OPTIONS}'
|
|
| 65 |
-EOF |
|
| 66 |
- |
|
| 67 |
-systemctl daemon-reload |
|
| 68 |
-systemctl restart docker.service |
| ... | ... |
@@ -7,12 +7,17 @@ import ( |
| 7 | 7 |
"net" |
| 8 | 8 |
"time" |
| 9 | 9 |
|
| 10 |
+ "github.com/openshift/openshift-sdn/ovssubnet/api" |
|
| 10 | 11 |
"github.com/openshift/openshift-sdn/ovssubnet/controller/kube" |
| 11 | 12 |
"github.com/openshift/openshift-sdn/ovssubnet/controller/lbr" |
| 12 |
- "github.com/openshift/openshift-sdn/pkg/api" |
|
| 13 |
+ "github.com/openshift/openshift-sdn/ovssubnet/controller/multitenant" |
|
| 13 | 14 |
"github.com/openshift/openshift-sdn/pkg/netutils" |
| 14 | 15 |
) |
| 15 | 16 |
|
| 17 |
+const ( |
|
| 18 |
+ MaxUint = ^uint(0) |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 16 | 21 |
type OvsController struct {
|
| 17 | 22 |
subnetRegistry api.SubnetRegistry |
| 18 | 23 |
localIP string |
| ... | ... |
@@ -22,6 +27,8 @@ type OvsController struct {
|
| 22 | 22 |
sig chan struct{}
|
| 23 | 23 |
ready chan struct{}
|
| 24 | 24 |
flowController FlowController |
| 25 |
+ VnidMap map[string]uint |
|
| 26 |
+ netIDManager *netutils.NetIDAllocator |
|
| 25 | 27 |
} |
| 26 | 28 |
|
| 27 | 29 |
type FlowController interface {
|
| ... | ... |
@@ -38,6 +45,14 @@ func NewKubeController(sub api.SubnetRegistry, hostname string, selfIP string, r |
| 38 | 38 |
return kubeController, err |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
+func NewMultitenantController(sub api.SubnetRegistry, hostname string, selfIP string, ready chan struct{}) (*OvsController, error) {
|
|
| 42 |
+ mtController, err := NewController(sub, hostname, selfIP, ready) |
|
| 43 |
+ if err == nil {
|
|
| 44 |
+ mtController.flowController = multitenant.NewFlowController() |
|
| 45 |
+ } |
|
| 46 |
+ return mtController, err |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 41 | 49 |
func NewDefaultController(sub api.SubnetRegistry, hostname string, selfIP string, ready chan struct{}) (*OvsController, error) {
|
| 42 | 50 |
defaultController, err := NewController(sub, hostname, selfIP, ready) |
| 43 | 51 |
if err == nil {
|
| ... | ... |
@@ -70,6 +85,7 @@ func NewController(sub api.SubnetRegistry, hostname string, selfIP string, ready |
| 70 | 70 |
hostName: hostname, |
| 71 | 71 |
localSubnet: nil, |
| 72 | 72 |
subnetAllocator: nil, |
| 73 |
+ VnidMap: make(map[string]uint), |
|
| 73 | 74 |
sig: make(chan struct{}),
|
| 74 | 75 |
ready: ready, |
| 75 | 76 |
}, nil |
| ... | ... |
@@ -116,10 +132,66 @@ func (oc *OvsController) StartMaster(sync bool, containerNetwork string, contain |
| 116 | 116 |
log.Warningf("Error initializing existing minions: %v", err)
|
| 117 | 117 |
// no worry, we can still keep watching it. |
| 118 | 118 |
} |
| 119 |
+ if _, is_mt := oc.flowController.(*multitenant.FlowController); is_mt {
|
|
| 120 |
+ nets, err := oc.subnetRegistry.GetNetNamespaces() |
|
| 121 |
+ if err != nil {
|
|
| 122 |
+ return err |
|
| 123 |
+ } |
|
| 124 |
+ inUse := make([]uint, 0) |
|
| 125 |
+ for _, net := range nets {
|
|
| 126 |
+ inUse = append(inUse, net.NetID) |
|
| 127 |
+ oc.VnidMap[net.Name] = net.NetID |
|
| 128 |
+ } |
|
| 129 |
+ oc.netIDManager, err = netutils.NewNetIDAllocator(10, MaxUint, inUse) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ return err |
|
| 132 |
+ } |
|
| 133 |
+ go oc.watchNetworks() |
|
| 134 |
+ } |
|
| 119 | 135 |
go oc.watchMinions() |
| 120 | 136 |
return nil |
| 121 | 137 |
} |
| 122 | 138 |
|
| 139 |
+func (oc *OvsController) watchNetworks() {
|
|
| 140 |
+ nsevent := make(chan *api.NamespaceEvent) |
|
| 141 |
+ stop := make(chan bool) |
|
| 142 |
+ go oc.subnetRegistry.WatchNamespaces(nsevent, stop) |
|
| 143 |
+ for {
|
|
| 144 |
+ select {
|
|
| 145 |
+ case ev := <-nsevent: |
|
| 146 |
+ switch ev.Type {
|
|
| 147 |
+ case api.Added: |
|
| 148 |
+ _, err := oc.subnetRegistry.GetNetNamespace(ev.Name) |
|
| 149 |
+ if err != nil {
|
|
| 150 |
+ netid, err := oc.netIDManager.GetNetID() |
|
| 151 |
+ if err != nil {
|
|
| 152 |
+ log.Error("Error getting new network IDS: %v", err)
|
|
| 153 |
+ continue |
|
| 154 |
+ } |
|
| 155 |
+ err = oc.subnetRegistry.WriteNetNamespace(ev.Name, netid) |
|
| 156 |
+ if err != nil {
|
|
| 157 |
+ log.Error("Error writing new network ID: %v", err)
|
|
| 158 |
+ continue |
|
| 159 |
+ } |
|
| 160 |
+ oc.VnidMap[ev.Name] = netid |
|
| 161 |
+ } |
|
| 162 |
+ case api.Deleted: |
|
| 163 |
+ err := oc.subnetRegistry.DeleteNetNamespace(ev.Name) |
|
| 164 |
+ if err != nil {
|
|
| 165 |
+ log.Error("Error while deleting Net Id: %v", err)
|
|
| 166 |
+ } |
|
| 167 |
+ netid := oc.VnidMap[ev.Name] |
|
| 168 |
+ oc.netIDManager.ReleaseNetID(netid) |
|
| 169 |
+ delete(oc.VnidMap, ev.Name) |
|
| 170 |
+ } |
|
| 171 |
+ case <-oc.sig: |
|
| 172 |
+ log.Error("Signal received. Stopping watching of minions.")
|
|
| 173 |
+ stop <- true |
|
| 174 |
+ return |
|
| 175 |
+ } |
|
| 176 |
+ } |
|
| 177 |
+} |
|
| 178 |
+ |
|
| 123 | 179 |
func (oc *OvsController) ServeExistingMinions() error {
|
| 124 | 180 |
minions, err := oc.subnetRegistry.GetMinions() |
| 125 | 181 |
if err != nil {
|
| ... | ... |
@@ -226,6 +298,16 @@ func (oc *OvsController) StartNode(sync, skipsetup bool) error {
|
| 226 | 226 |
for _, s := range *subnets {
|
| 227 | 227 |
oc.flowController.AddOFRules(s.Minion, s.Sub, oc.localIP) |
| 228 | 228 |
} |
| 229 |
+ if _, ok := oc.flowController.(*multitenant.FlowController); ok {
|
|
| 230 |
+ nslist, err := oc.subnetRegistry.GetNetNamespaces() |
|
| 231 |
+ if err != nil {
|
|
| 232 |
+ return err |
|
| 233 |
+ } |
|
| 234 |
+ for _, ns := range nslist {
|
|
| 235 |
+ oc.VnidMap[ns.Name] = ns.NetID |
|
| 236 |
+ } |
|
| 237 |
+ go oc.watchVnids() |
|
| 238 |
+ } |
|
| 229 | 239 |
go oc.watchCluster() |
| 230 | 240 |
|
| 231 | 241 |
if oc.ready != nil {
|
| ... | ... |
@@ -235,6 +317,27 @@ func (oc *OvsController) StartNode(sync, skipsetup bool) error {
|
| 235 | 235 |
return err |
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 |
+func (oc *OvsController) watchVnids() {
|
|
| 239 |
+ netNsEvent := make(chan *api.NetNamespaceEvent) |
|
| 240 |
+ stop := make(chan bool) |
|
| 241 |
+ go oc.subnetRegistry.WatchNetNamespaces(netNsEvent, stop) |
|
| 242 |
+ for {
|
|
| 243 |
+ select {
|
|
| 244 |
+ case ev := <-netNsEvent: |
|
| 245 |
+ switch ev.Type {
|
|
| 246 |
+ case api.Added: |
|
| 247 |
+ oc.VnidMap[ev.Name] = ev.NetID |
|
| 248 |
+ case api.Deleted: |
|
| 249 |
+ delete(oc.VnidMap, ev.Name) |
|
| 250 |
+ } |
|
| 251 |
+ case <-oc.sig: |
|
| 252 |
+ log.Error("Signal received. Stopping watching of NetNamespaces.")
|
|
| 253 |
+ stop <- true |
|
| 254 |
+ return |
|
| 255 |
+ } |
|
| 256 |
+ } |
|
| 257 |
+} |
|
| 258 |
+ |
|
| 238 | 259 |
func (oc *OvsController) initSelfSubnet() error {
|
| 239 | 260 |
// get subnet for self |
| 240 | 261 |
for {
|
| 241 | 262 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,82 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+set -ex |
|
| 2 |
+ |
|
| 3 |
+lock_file=/var/lock/openshift-sdn.lock |
|
| 4 |
+ |
|
| 5 |
+action=$1 |
|
| 6 |
+pod_namespace=$2 |
|
| 7 |
+pod_name=$3 |
|
| 8 |
+net_container=$4 |
|
| 9 |
+ |
|
| 10 |
+lockwrap() {
|
|
| 11 |
+ ( |
|
| 12 |
+ flock 200 |
|
| 13 |
+ "$@" |
|
| 14 |
+ ) 200>${lock_file}
|
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+Init() {
|
|
| 18 |
+ true |
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+Setup() {
|
|
| 22 |
+ source /etc/openshift-sdn/config.env |
|
| 23 |
+ cluster_subnet=${OPENSHIFT_CLUSTER_SUBNET}
|
|
| 24 |
+ tap_ip=${OPENSHIFT_SDN_TAP1_ADDR}
|
|
| 25 |
+ |
|
| 26 |
+ pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 27 |
+ network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 28 |
+ if [ "${network_mode}" == "host" ]; then
|
|
| 29 |
+ # quit, nothing for the SDN here |
|
| 30 |
+ exit 0 |
|
| 31 |
+ fi |
|
| 32 |
+ ipaddr=$(docker inspect --format "{{.NetworkSettings.IPAddress}}" ${net_container})
|
|
| 33 |
+ new_ip=$ipaddr |
|
| 34 |
+ ipaddr_sub=$(docker inspect --format "{{.NetworkSettings.IPPrefixLen}}" ${net_container})
|
|
| 35 |
+ docker_gateway=$(docker inspect --format "{{.NetworkSettings.Gateway}}" ${net_container})
|
|
| 36 |
+ veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 37 |
+ veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 38 |
+ |
|
| 39 |
+ brctl delif lbr0 $veth_host |
|
| 40 |
+ ovs-vsctl add-port br0 ${veth_host}
|
|
| 41 |
+ ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 42 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=0,cookie=0x${ovs_port},priority=100,ip,nw_dst=${new_ip},actions=output:${ovs_port}"
|
|
| 43 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=0,cookie=0x${ovs_port},priority=100,arp,nw_dst=${new_ip},actions=output:${ovs_port}"
|
|
| 44 |
+ |
|
| 45 |
+ add_subnet_route="ip route add ${cluster_subnet} dev eth0 proto kernel scope link src $ipaddr"
|
|
| 46 |
+ nsenter -n -t $pid -- $add_subnet_route |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+Teardown() {
|
|
| 50 |
+ source /etc/openshift-sdn/config.env |
|
| 51 |
+ cluster_subnet=${OPENSHIFT_CLUSTER_SUBNET}
|
|
| 52 |
+ tap_ip=${OPENSHIFT_SDN_TAP1_ADDR}
|
|
| 53 |
+ |
|
| 54 |
+ pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 55 |
+ network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 56 |
+ if [ "${network_mode}" == "host" ]; then
|
|
| 57 |
+ # quit, nothing for the SDN here |
|
| 58 |
+ exit 0 |
|
| 59 |
+ fi |
|
| 60 |
+ veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 61 |
+ veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 62 |
+ ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 63 |
+ ovs-vsctl del-port $veth_host |
|
| 64 |
+ ovs-ofctl -O OpenFlow13 del-flows br0 "table=0,cookie=0x${ovs_port}/0xffffffff"
|
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+case "$action" in |
|
| 68 |
+ init) |
|
| 69 |
+ lockwrap Init |
|
| 70 |
+ ;; |
|
| 71 |
+ setup) |
|
| 72 |
+ lockwrap Setup |
|
| 73 |
+ ;; |
|
| 74 |
+ teardown) |
|
| 75 |
+ lockwrap Teardown |
|
| 76 |
+ ;; |
|
| 77 |
+ *) |
|
| 78 |
+ echo "Bad input: $@" |
|
| 79 |
+ exit 1 |
|
| 80 |
+esac |
|
| 81 |
+ |
| 0 | 82 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,120 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -ex |
|
| 3 |
+ |
|
| 4 |
+lock_file=/var/lock/openshift-sdn.lock |
|
| 5 |
+subnet_gateway=$1 |
|
| 6 |
+subnet=$2 |
|
| 7 |
+cluster_subnet=$3 |
|
| 8 |
+subnet_mask_len=$4 |
|
| 9 |
+tun_gateway=$5 |
|
| 10 |
+printf 'Container network is "%s"; local host has subnet "%s" and gateway "%s".\n' "${cluster_subnet}" "${subnet}" "${subnet_gateway}"
|
|
| 11 |
+TUN=tun0 |
|
| 12 |
+ |
|
| 13 |
+# Synchronize code execution with a file lock. |
|
| 14 |
+function lockwrap() {
|
|
| 15 |
+ ( |
|
| 16 |
+ flock 200 |
|
| 17 |
+ "$@" |
|
| 18 |
+ ) 200>${lock_file}
|
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+function setup_required() {
|
|
| 22 |
+ ip=$(echo `ip a s lbr0 2>/dev/null|awk '/inet / {print $2}'`)
|
|
| 23 |
+ if [ "$ip" != "${subnet_gateway}/${subnet_mask_len}" ]; then
|
|
| 24 |
+ return 0 |
|
| 25 |
+ fi |
|
| 26 |
+ if ! grep -q lbr0 /run/openshift-sdn/docker-network; then |
|
| 27 |
+ return 0 |
|
| 28 |
+ fi |
|
| 29 |
+ return 1 |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+function setup() {
|
|
| 33 |
+ # clear config file |
|
| 34 |
+ rm -f /etc/openshift-sdn/config.env |
|
| 35 |
+ |
|
| 36 |
+ ## openvswitch |
|
| 37 |
+ ovs-vsctl del-br br0 || true |
|
| 38 |
+ ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure |
|
| 39 |
+ ovs-vsctl set bridge br0 protocols=OpenFlow13 |
|
| 40 |
+ ovs-vsctl del-port br0 vxlan0 || true |
|
| 41 |
+ ovs-vsctl add-port br0 vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip="flow" options:key="flow" ofport_request=1 |
|
| 42 |
+ ovs-vsctl add-port br0 ${TUN} -- set Interface ${TUN} type=internal ofport_request=2
|
|
| 43 |
+ |
|
| 44 |
+ ip link del vlinuxbr || true |
|
| 45 |
+ ip link add vlinuxbr type veth peer name vovsbr |
|
| 46 |
+ ip link set vlinuxbr up |
|
| 47 |
+ ip link set vovsbr up |
|
| 48 |
+ ip link set vlinuxbr txqueuelen 0 |
|
| 49 |
+ ip link set vovsbr txqueuelen 0 |
|
| 50 |
+ |
|
| 51 |
+ ovs-vsctl del-port br0 vovsbr || true |
|
| 52 |
+ ovs-vsctl add-port br0 vovsbr -- set Interface vovsbr ofport_request=9 |
|
| 53 |
+ |
|
| 54 |
+ ## linux bridge |
|
| 55 |
+ ip link set lbr0 down || true |
|
| 56 |
+ brctl delbr lbr0 || true |
|
| 57 |
+ brctl addbr lbr0 |
|
| 58 |
+ ip addr add ${subnet_gateway}/${subnet_mask_len} dev lbr0
|
|
| 59 |
+ ip link set lbr0 up |
|
| 60 |
+ brctl addif lbr0 vlinuxbr |
|
| 61 |
+ |
|
| 62 |
+ # setup tun address |
|
| 63 |
+ ip addr add ${tun_gateway}/${subnet_mask_len} dev ${TUN}
|
|
| 64 |
+ ip link set ${TUN} up
|
|
| 65 |
+ ip route add ${cluster_subnet} dev ${TUN} proto kernel scope link
|
|
| 66 |
+ |
|
| 67 |
+ ## iptables |
|
| 68 |
+ iptables -t nat -D POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE || true
|
|
| 69 |
+ iptables -t nat -A POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE
|
|
| 70 |
+ iptables -D INPUT -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT || true |
|
| 71 |
+ iptables -D INPUT -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT || true
|
|
| 72 |
+ lineno=$(iptables -nvL INPUT --line-numbers | grep "state RELATED,ESTABLISHED" | awk '{print $1}')
|
|
| 73 |
+ iptables -I INPUT $lineno -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT |
|
| 74 |
+ iptables -I INPUT $((lineno+1)) -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT
|
|
| 75 |
+ fwd_lineno=$(iptables -nvL FORWARD --line-numbers | grep "reject-with icmp-host-prohibited" | tail -n 1 | awk '{print $1}')
|
|
| 76 |
+ iptables -I FORWARD $fwd_lineno -d ${cluster_subnet} -j ACCEPT
|
|
| 77 |
+ iptables -I FORWARD $fwd_lineno -s ${cluster_subnet} -j ACCEPT
|
|
| 78 |
+ |
|
| 79 |
+ ## docker |
|
| 80 |
+ if [[ -z "${DOCKER_NETWORK_OPTIONS}" ]]
|
|
| 81 |
+ then |
|
| 82 |
+ DOCKER_NETWORK_OPTIONS='-b=lbr0 --mtu=1450' |
|
| 83 |
+ fi |
|
| 84 |
+ |
|
| 85 |
+ mkdir -p /run/openshift-sdn |
|
| 86 |
+ cat <<EOF > /run/openshift-sdn/docker-network |
|
| 87 |
+# This file has been modified by openshift-sdn. Please modify the |
|
| 88 |
+# DOCKER_NETWORK_OPTIONS variable in /etc/sysconfig/openshift-node if this |
|
| 89 |
+# is an integrated install or /etc/sysconfig/openshift-sdn-node if this is a |
|
| 90 |
+# standalone install. |
|
| 91 |
+ |
|
| 92 |
+DOCKER_NETWORK_OPTIONS='${DOCKER_NETWORK_OPTIONS}'
|
|
| 93 |
+EOF |
|
| 94 |
+ |
|
| 95 |
+ systemctl daemon-reload |
|
| 96 |
+ systemctl restart docker.service |
|
| 97 |
+ |
|
| 98 |
+ # disable iptables for lbr0 |
|
| 99 |
+ # for kernel version 3.18+, module br_netfilter needs to be loaded upfront |
|
| 100 |
+ # for older ones, br_netfilter may not exist, but is covered by bridge (bridge-utils) |
|
| 101 |
+ modprobe br_netfilter || true |
|
| 102 |
+ sysctl -w net.bridge.bridge-nf-call-iptables=0 |
|
| 103 |
+ |
|
| 104 |
+ # delete the subnet routing entry created because of lbr0 |
|
| 105 |
+ ip route del ${subnet} dev lbr0 proto kernel scope link src ${subnet_gateway} || true
|
|
| 106 |
+ |
|
| 107 |
+ mkdir -p /etc/openshift-sdn |
|
| 108 |
+ echo "export OPENSHIFT_SDN_TAP1_ADDR=${tun_gateway}" >& "/etc/openshift-sdn/config.env"
|
|
| 109 |
+ echo "export OPENSHIFT_CLUSTER_SUBNET=${cluster_subnet}" >> "/etc/openshift-sdn/config.env"
|
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+set +e |
|
| 113 |
+if ! setup_required; then |
|
| 114 |
+ echo "SDN setup not required." |
|
| 115 |
+ exit 140 |
|
| 116 |
+fi |
|
| 117 |
+set -e |
|
| 118 |
+ |
|
| 119 |
+lockwrap setup |
| 0 | 120 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,68 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -ex |
|
| 3 |
+ |
|
| 4 |
+subnet_gateway=$1 |
|
| 5 |
+subnet=$2 |
|
| 6 |
+container_network=$3 |
|
| 7 |
+subnet_mask_len=$4 |
|
| 8 |
+printf 'Container network is "%s"; local host has subnet "%s" and gateway "%s".\n' "${container_network}" "${subnet}" "${subnet_gateway}"
|
|
| 9 |
+ |
|
| 10 |
+## openvswitch |
|
| 11 |
+ovs-vsctl del-br br0 || true |
|
| 12 |
+ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure |
|
| 13 |
+ovs-vsctl set bridge br0 protocols=OpenFlow13 |
|
| 14 |
+ovs-vsctl del-port br0 vxlan0 || true |
|
| 15 |
+ovs-vsctl add-port br0 vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip="flow" options:key="flow" ofport_request=10 |
|
| 16 |
+ip link del vlinuxbr || true |
|
| 17 |
+ip link add vlinuxbr type veth peer name vovsbr |
|
| 18 |
+ip link set vlinuxbr up |
|
| 19 |
+ip link set vovsbr up |
|
| 20 |
+ip link set vlinuxbr txqueuelen 0 |
|
| 21 |
+ip link set vovsbr txqueuelen 0 |
|
| 22 |
+ |
|
| 23 |
+ovs-vsctl del-port br0 vovsbr || true |
|
| 24 |
+ovs-vsctl add-port br0 vovsbr -- set Interface vovsbr ofport_request=9 |
|
| 25 |
+ |
|
| 26 |
+## linux bridge |
|
| 27 |
+ip link set lbr0 down || true |
|
| 28 |
+brctl delbr lbr0 || true |
|
| 29 |
+brctl addbr lbr0 |
|
| 30 |
+ip addr add ${subnet_gateway}/${subnet_mask_len} dev lbr0
|
|
| 31 |
+ip link set lbr0 up |
|
| 32 |
+brctl addif lbr0 vlinuxbr |
|
| 33 |
+ip route del ${subnet} dev lbr0 proto kernel scope link src ${subnet_gateway} || true
|
|
| 34 |
+ip route add ${container_network} dev lbr0 proto kernel scope link src ${subnet_gateway}
|
|
| 35 |
+ |
|
| 36 |
+ |
|
| 37 |
+## iptables |
|
| 38 |
+iptables -t nat -D POSTROUTING -s ${container_network} ! -d ${container_network} -j MASQUERADE || true
|
|
| 39 |
+iptables -t nat -A POSTROUTING -s ${container_network} ! -d ${container_network} -j MASQUERADE
|
|
| 40 |
+iptables -D INPUT -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT || true |
|
| 41 |
+iptables -D INPUT -i lbr0 -m comment --comment "traffic from docker" -j ACCEPT || true |
|
| 42 |
+lineno=$(iptables -nvL INPUT --line-numbers | grep "state RELATED,ESTABLISHED" | awk '{print $1}')
|
|
| 43 |
+iptables -I INPUT $lineno -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT |
|
| 44 |
+iptables -I INPUT $((lineno+1)) -i lbr0 -m comment --comment "traffic from docker" -j ACCEPT |
|
| 45 |
+fwd_lineno=$(iptables -nvL FORWARD --line-numbers | grep "reject-with icmp-host-prohibited" | tail -n 1 | awk '{print $1}')
|
|
| 46 |
+iptables -I FORWARD $fwd_lineno -d ${container_network} -j ACCEPT
|
|
| 47 |
+iptables -I FORWARD $fwd_lineno -s ${container_network} -j ACCEPT
|
|
| 48 |
+ |
|
| 49 |
+ |
|
| 50 |
+## docker |
|
| 51 |
+if [[ -z "${DOCKER_NETWORK_OPTIONS}" ]]
|
|
| 52 |
+then |
|
| 53 |
+ DOCKER_NETWORK_OPTIONS='-b=lbr0 --mtu=1450' |
|
| 54 |
+fi |
|
| 55 |
+ |
|
| 56 |
+mkdir -p /run/openshift-sdn |
|
| 57 |
+cat <<EOF > /run/openshift-sdn/docker-network |
|
| 58 |
+# This file has been modified by openshift-sdn. Please modify the |
|
| 59 |
+# DOCKER_NETWORK_OPTIONS variable in /etc/sysconfig/openshift-node if this |
|
| 60 |
+# is an integrated install or /etc/sysconfig/openshift-sdn-node if this is a |
|
| 61 |
+# standalone install. |
|
| 62 |
+ |
|
| 63 |
+DOCKER_NETWORK_OPTIONS='${DOCKER_NETWORK_OPTIONS}'
|
|
| 64 |
+EOF |
|
| 65 |
+ |
|
| 66 |
+systemctl daemon-reload |
|
| 67 |
+systemctl restart docker.service |
| 0 | 68 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,89 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+set -ex |
|
| 2 |
+ |
|
| 3 |
+lock_file=/var/lock/openshift-sdn.lock |
|
| 4 |
+ |
|
| 5 |
+action=$1 |
|
| 6 |
+pod_namespace=$2 |
|
| 7 |
+pod_name=$3 |
|
| 8 |
+net_container=$4 |
|
| 9 |
+tenant_id=$5 |
|
| 10 |
+ |
|
| 11 |
+lockwrap() {
|
|
| 12 |
+ ( |
|
| 13 |
+ flock 200 |
|
| 14 |
+ "$@" |
|
| 15 |
+ ) 200>${lock_file}
|
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+Init() {
|
|
| 19 |
+ true |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+Setup() {
|
|
| 23 |
+ source /etc/openshift-sdn/config.env |
|
| 24 |
+ cluster_subnet=${OPENSHIFT_CLUSTER_SUBNET}
|
|
| 25 |
+ |
|
| 26 |
+ pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 27 |
+ network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 28 |
+ if [ "${network_mode}" == "host" ]; then
|
|
| 29 |
+ # quit, nothing for the SDN here |
|
| 30 |
+ exit 0 |
|
| 31 |
+ fi |
|
| 32 |
+ ipaddr=$(docker inspect --format "{{.NetworkSettings.IPAddress}}" ${net_container})
|
|
| 33 |
+ veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 34 |
+ veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 35 |
+ |
|
| 36 |
+ # If the caller didn't pass a tenant ID, we make one up based on |
|
| 37 |
+ # the first two letters of the pod name. |
|
| 38 |
+ # FIXME: remove this when it's no longer needed for testing |
|
| 39 |
+ if [ -z "$tenant_id" ]; then |
|
| 40 |
+ tenant_id=$(echo $pod_name | perl -ne 'print unpack("S", $_)')
|
|
| 41 |
+ fi |
|
| 42 |
+ |
|
| 43 |
+ brctl delif lbr0 $veth_host |
|
| 44 |
+ ovs-vsctl add-port br0 ${veth_host}
|
|
| 45 |
+ ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 46 |
+ |
|
| 47 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=3,cookie=0x${ovs_port},priority=100,in_port=${ovs_port},ip,nw_src=${ipaddr},actions=load:${tenant_id}->NXM_NX_REG0[],goto_table:4"
|
|
| 48 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=5,cookie=0x${ovs_port},priority=100,ip,nw_dst=${ipaddr},reg0=${tenant_id},actions=output:${ovs_port}"
|
|
| 49 |
+ if [ "${tenant_id}" == "0" ]; then
|
|
| 50 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=5,cookie=0x${ovs_port},priority=150,ip,nw_dst=${ipaddr},actions=output:${ovs_port}"
|
|
| 51 |
+ fi |
|
| 52 |
+ |
|
| 53 |
+ add_subnet_route="ip route add ${cluster_subnet} dev eth0 proto kernel scope link src $ipaddr"
|
|
| 54 |
+ nsenter -n -t $pid -- $add_subnet_route |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 57 |
+Teardown() {
|
|
| 58 |
+ source /etc/openshift-sdn/config.env |
|
| 59 |
+ |
|
| 60 |
+ pid=$(docker inspect --format "{{.State.Pid}}" ${net_container})
|
|
| 61 |
+ network_mode=$(docker inspect --format "{{.HostConfig.NetworkMode}}" ${net_container})
|
|
| 62 |
+ if [ "${network_mode}" == "host" ]; then
|
|
| 63 |
+ # quit, nothing for the SDN here |
|
| 64 |
+ exit 0 |
|
| 65 |
+ fi |
|
| 66 |
+ veth_ifindex=$(nsenter -n -t $pid -- ethtool -S eth0 | sed -n -e 's/.*peer_ifindex: //p') |
|
| 67 |
+ veth_host=$(ip link show | sed -ne "s/^$veth_ifindex: \([^:]*\).*/\1/p") |
|
| 68 |
+ ovs_port=$(ovs-ofctl -O OpenFlow13 dump-ports-desc br0 | grep ${veth_host} | cut -d "(" -f 1 | tr -d ' ')
|
|
| 69 |
+ ovs-vsctl del-port $veth_host |
|
| 70 |
+ ovs-ofctl -O OpenFlow13 del-flows br0 "table=3,cookie=0x${ovs_port}/0xffffffff"
|
|
| 71 |
+ ovs-ofctl -O OpenFlow13 del-flows br0 "table=5,cookie=0x${ovs_port}/0xffffffff"
|
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+case "$action" in |
|
| 75 |
+ init) |
|
| 76 |
+ lockwrap Init |
|
| 77 |
+ ;; |
|
| 78 |
+ setup) |
|
| 79 |
+ lockwrap Setup |
|
| 80 |
+ ;; |
|
| 81 |
+ teardown) |
|
| 82 |
+ lockwrap Teardown |
|
| 83 |
+ ;; |
|
| 84 |
+ *) |
|
| 85 |
+ echo "Bad input: $@" |
|
| 86 |
+ exit 1 |
|
| 87 |
+esac |
|
| 88 |
+ |
| 0 | 89 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,154 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -ex |
|
| 3 |
+ |
|
| 4 |
+lock_file=/var/lock/openshift-sdn.lock |
|
| 5 |
+subnet_gateway=$1 |
|
| 6 |
+subnet=$2 |
|
| 7 |
+cluster_subnet=$3 |
|
| 8 |
+subnet_mask_len=$4 |
|
| 9 |
+tun_gateway=$5 |
|
| 10 |
+printf 'Container network is "%s"; local host has subnet "%s" and gateway "%s".\n' "${cluster_subnet}" "${subnet}" "${subnet_gateway}"
|
|
| 11 |
+TUN=tun0 |
|
| 12 |
+ |
|
| 13 |
+# Synchronize code execution with a file lock. |
|
| 14 |
+function lockwrap() {
|
|
| 15 |
+ ( |
|
| 16 |
+ flock 200 |
|
| 17 |
+ "$@" |
|
| 18 |
+ ) 200>${lock_file}
|
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+function setup_required() {
|
|
| 22 |
+ ip=$(echo `ip a s lbr0 2>/dev/null|awk '/inet / {print $2}'`)
|
|
| 23 |
+ if [ "$ip" != "${subnet_gateway}/${subnet_mask_len}" ]; then
|
|
| 24 |
+ return 0 |
|
| 25 |
+ fi |
|
| 26 |
+ if ! grep -q lbr0 /run/openshift-sdn/docker-network; then |
|
| 27 |
+ return 0 |
|
| 28 |
+ fi |
|
| 29 |
+ return 1 |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+function setup() {
|
|
| 33 |
+ # clear config file |
|
| 34 |
+ rm -f /etc/openshift-sdn/config.env |
|
| 35 |
+ |
|
| 36 |
+ ## openvswitch |
|
| 37 |
+ ovs-vsctl del-br br0 || true |
|
| 38 |
+ ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure |
|
| 39 |
+ ovs-vsctl set bridge br0 protocols=OpenFlow13 |
|
| 40 |
+ ovs-vsctl del-port br0 vxlan0 || true |
|
| 41 |
+ ovs-vsctl add-port br0 vxlan0 -- set Interface vxlan0 type=vxlan options:remote_ip="flow" options:key="flow" ofport_request=1 |
|
| 42 |
+ ovs-vsctl add-port br0 ${TUN} -- set Interface ${TUN} type=internal ofport_request=2
|
|
| 43 |
+ |
|
| 44 |
+ ip link del vlinuxbr || true |
|
| 45 |
+ ip link add vlinuxbr type veth peer name vovsbr |
|
| 46 |
+ ip link set vlinuxbr up |
|
| 47 |
+ ip link set vovsbr up |
|
| 48 |
+ ip link set vlinuxbr txqueuelen 0 |
|
| 49 |
+ ip link set vovsbr txqueuelen 0 |
|
| 50 |
+ |
|
| 51 |
+ ovs-vsctl del-port br0 vovsbr || true |
|
| 52 |
+ ovs-vsctl add-port br0 vovsbr -- set Interface vovsbr ofport_request=9 |
|
| 53 |
+ |
|
| 54 |
+ # Table 0; learn MAC addresses and continue with table 1 |
|
| 55 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=0, actions=learn(table=7, priority=200, hard_timeout=900, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], load:NXM_NX_TUN_IPV4_SRC[]->NXM_NX_TUN_IPV4_DST[], output:NXM_OF_IN_PORT[]), goto_table:1" |
|
| 56 |
+ |
|
| 57 |
+ # Table 1; initial dispatch |
|
| 58 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=1, arp, actions=goto_table:7" |
|
| 59 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=1, in_port=1, actions=goto_table:2" |
|
| 60 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=1, in_port=2, actions=goto_table:4" |
|
| 61 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=1, actions=goto_table:3" |
|
| 62 |
+ |
|
| 63 |
+ # Table 2; incoming from vxlan |
|
| 64 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=2, arp, actions=goto_table:7" |
|
| 65 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=2, priority=200, ip, nw_dst=${subnet_gateway}, actions=output:2"
|
|
| 66 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=2, tun_id=0, actions=goto_table:4" |
|
| 67 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=2, priority=100, ip, nw_dst=${subnet}, actions=move:NXM_NX_TUN_ID[0..31]->NXM_NX_REG0[], goto_table:5"
|
|
| 68 |
+ |
|
| 69 |
+ # Table 3; incoming from container; filled in by openshift-ovs-subnet |
|
| 70 |
+ # But let incoming traffic from docker-only containers through (ingress on vovsbr) |
|
| 71 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=3, cookie=0x9, in_port=9, ip, actions=goto_table:4" |
|
| 72 |
+ |
|
| 73 |
+ # Table 4; general routing |
|
| 74 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=4, priority=200, ip, nw_dst=${subnet_gateway}, actions=output:2"
|
|
| 75 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=4, priority=150, ip, nw_dst=${subnet}, actions=goto_table:5"
|
|
| 76 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=4, priority=100, ip, nw_dst=${cluster_subnet}, actions=goto_table:6"
|
|
| 77 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=4, priority=0, ip, actions=output:2" |
|
| 78 |
+ |
|
| 79 |
+ # Table 5; to local container; mostly filled in by openshift-ovs-multitenant |
|
| 80 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=5, priority=200, ip, reg0=0, actions=goto_table:7" |
|
| 81 |
+ |
|
| 82 |
+ # Table 6; to remote container; filled in by multitenant.go |
|
| 83 |
+ |
|
| 84 |
+ # Table 7; MAC dispatch / ARP, filled in by Table 0's learn() rule |
|
| 85 |
+ # and with per-node vxlan ARP rules by multitenant.go |
|
| 86 |
+ ovs-ofctl -O OpenFlow13 add-flow br0 "table=7, priority=0, arp, actions=flood" |
|
| 87 |
+ |
|
| 88 |
+ ## linux bridge |
|
| 89 |
+ ip link set lbr0 down || true |
|
| 90 |
+ brctl delbr lbr0 || true |
|
| 91 |
+ brctl addbr lbr0 |
|
| 92 |
+ ip addr add ${subnet_gateway}/${subnet_mask_len} dev lbr0
|
|
| 93 |
+ ip link set lbr0 up |
|
| 94 |
+ brctl addif lbr0 vlinuxbr |
|
| 95 |
+ |
|
| 96 |
+ # setup tun address |
|
| 97 |
+ ip addr add ${tun_gateway}/${subnet_mask_len} dev ${TUN}
|
|
| 98 |
+ ip link set ${TUN} up
|
|
| 99 |
+ ip route add ${cluster_subnet} dev ${TUN} proto kernel scope link
|
|
| 100 |
+ |
|
| 101 |
+ ## iptables |
|
| 102 |
+ iptables -t nat -D POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE || true
|
|
| 103 |
+ iptables -t nat -A POSTROUTING -s ${cluster_subnet} ! -d ${cluster_subnet} -j MASQUERADE
|
|
| 104 |
+ iptables -D INPUT -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT || true |
|
| 105 |
+ iptables -D INPUT -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT || true
|
|
| 106 |
+ lineno=$(iptables -nvL INPUT --line-numbers | grep "state RELATED,ESTABLISHED" | awk '{print $1}')
|
|
| 107 |
+ iptables -I INPUT $lineno -p udp -m multiport --dports 4789 -m comment --comment "001 vxlan incoming" -j ACCEPT |
|
| 108 |
+ iptables -I INPUT $((lineno+1)) -i ${TUN} -m comment --comment "traffic from docker for internet" -j ACCEPT
|
|
| 109 |
+ fwd_lineno=$(iptables -nvL FORWARD --line-numbers | grep "reject-with icmp-host-prohibited" | tail -n 1 | awk '{print $1}')
|
|
| 110 |
+ iptables -I FORWARD $fwd_lineno -d ${cluster_subnet} -j ACCEPT
|
|
| 111 |
+ iptables -I FORWARD $fwd_lineno -s ${cluster_subnet} -j ACCEPT
|
|
| 112 |
+ |
|
| 113 |
+ ## docker |
|
| 114 |
+ if [[ -z "${DOCKER_NETWORK_OPTIONS}" ]]
|
|
| 115 |
+ then |
|
| 116 |
+ DOCKER_NETWORK_OPTIONS='-b=lbr0 --mtu=1450' |
|
| 117 |
+ fi |
|
| 118 |
+ |
|
| 119 |
+ mkdir -p /run/openshift-sdn |
|
| 120 |
+ cat <<EOF > /run/openshift-sdn/docker-network |
|
| 121 |
+# This file has been modified by openshift-sdn. Please modify the |
|
| 122 |
+# DOCKER_NETWORK_OPTIONS variable in /etc/sysconfig/openshift-node if this |
|
| 123 |
+# is an integrated install or /etc/sysconfig/openshift-sdn-node if this is a |
|
| 124 |
+# standalone install. |
|
| 125 |
+ |
|
| 126 |
+DOCKER_NETWORK_OPTIONS='${DOCKER_NETWORK_OPTIONS}'
|
|
| 127 |
+EOF |
|
| 128 |
+ |
|
| 129 |
+ systemctl daemon-reload |
|
| 130 |
+ systemctl restart docker.service |
|
| 131 |
+ |
|
| 132 |
+ # disable iptables for lbr0 |
|
| 133 |
+ # for kernel version 3.18+, module br_netfilter needs to be loaded upfront |
|
| 134 |
+ # for older ones, br_netfilter may not exist, but is covered by bridge (bridge-utils) |
|
| 135 |
+ modprobe br_netfilter || true |
|
| 136 |
+ sysctl -w net.bridge.bridge-nf-call-iptables=0 |
|
| 137 |
+ |
|
| 138 |
+ # delete the subnet routing entry created because of lbr0 |
|
| 139 |
+ ip route del ${subnet} dev lbr0 proto kernel scope link src ${subnet_gateway} || true
|
|
| 140 |
+ |
|
| 141 |
+ mkdir -p /etc/openshift-sdn |
|
| 142 |
+ echo "export OPENSHIFT_SDN_TAP1_ADDR=${tun_gateway}" >& "/etc/openshift-sdn/config.env"
|
|
| 143 |
+ echo "export OPENSHIFT_CLUSTER_SUBNET=${cluster_subnet}" >> "/etc/openshift-sdn/config.env"
|
|
| 144 |
+} |
|
| 145 |
+ |
|
| 146 |
+set +e |
|
| 147 |
+if ! setup_required; then |
|
| 148 |
+ echo "SDN setup not required." |
|
| 149 |
+ exit 140 |
|
| 150 |
+fi |
|
| 151 |
+set -e |
|
| 152 |
+ |
|
| 153 |
+lockwrap setup |
| 0 | 154 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,96 @@ |
| 0 |
+package multitenant |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/hex" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ log "github.com/golang/glog" |
|
| 6 |
+ "net" |
|
| 7 |
+ "os" |
|
| 8 |
+ "os/exec" |
|
| 9 |
+ "strconv" |
|
| 10 |
+ "syscall" |
|
| 11 |
+ |
|
| 12 |
+ "github.com/openshift/openshift-sdn/pkg/netutils" |
|
| 13 |
+ netutils_server "github.com/openshift/openshift-sdn/pkg/netutils/server" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+type FlowController struct {
|
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+func NewFlowController() *FlowController {
|
|
| 20 |
+ return &FlowController{}
|
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func (c *FlowController) Setup(localSubnet, containerNetwork string) error {
|
|
| 24 |
+ _, ipnet, err := net.ParseCIDR(localSubnet) |
|
| 25 |
+ subnetMaskLength, _ := ipnet.Mask.Size() |
|
| 26 |
+ gateway := netutils.GenerateDefaultGateway(ipnet).String() |
|
| 27 |
+ out, err := exec.Command("openshift-sdn-multitenant-setup.sh", gateway, ipnet.String(), containerNetwork, strconv.Itoa(subnetMaskLength), gateway).CombinedOutput()
|
|
| 28 |
+ log.Infof("Output of setup script:\n%s", out)
|
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ exitErr, ok := err.(*exec.ExitError) |
|
| 31 |
+ if ok {
|
|
| 32 |
+ status := exitErr.ProcessState.Sys().(syscall.WaitStatus) |
|
| 33 |
+ if status.Exited() && status.ExitStatus() == 140 {
|
|
| 34 |
+ // valid, do nothing, its just a benevolent restart |
|
| 35 |
+ return nil |
|
| 36 |
+ } |
|
| 37 |
+ } |
|
| 38 |
+ log.Errorf("Error executing setup script. \n\tOutput: %s\n\tError: %v\n", out, err)
|
|
| 39 |
+ } |
|
| 40 |
+ return err |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func (c *FlowController) manageLocalIpam(ipnet *net.IPNet) error {
|
|
| 44 |
+ ipamHost := "127.0.0.1" |
|
| 45 |
+ ipamPort := uint(9080) |
|
| 46 |
+ inuse := make([]string, 0) |
|
| 47 |
+ ipam, _ := netutils.NewIPAllocator(ipnet.String(), inuse) |
|
| 48 |
+ f, err := os.Create("/etc/openshift-sdn/config.env")
|
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ return err |
|
| 51 |
+ } |
|
| 52 |
+ _, err = f.WriteString(fmt.Sprintf("OPENSHIFT_SDN_TAP1_ADDR=%s\nOPENSHIFT_SDN_IPAM_SERVER=http://%s:%s", netutils.GenerateDefaultGateway(ipnet), ipamHost, ipamPort))
|
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return err |
|
| 55 |
+ } |
|
| 56 |
+ f.Close() |
|
| 57 |
+ // listen and serve does not return the control |
|
| 58 |
+ netutils_server.ListenAndServeNetutilServer(ipam, net.ParseIP(ipamHost), ipamPort, nil) |
|
| 59 |
+ return nil |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func (c *FlowController) AddOFRules(minionIP, subnet, localIP string) error {
|
|
| 63 |
+ if minionIP == localIP {
|
|
| 64 |
+ return nil |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ cookie := generateCookie(minionIP) |
|
| 68 |
+ iprule := fmt.Sprintf("table=6,cookie=0x%s,priority=100,ip,nw_dst=%s,actions=move:NXM_NX_REG0[]->NXM_NX_TUN_ID[0..31],set_field:%s->tun_dst,output:1", cookie, subnet, minionIP)
|
|
| 69 |
+ arprule := fmt.Sprintf("table=7,cookie=0x%s,priority=100,arp,nw_dst=%s,actions=move:NXM_NX_REG0[]->NXM_NX_TUN_ID[0..31],set_field:%s->tun_dst,output:1", cookie, subnet, minionIP)
|
|
| 70 |
+ o, e := exec.Command("ovs-ofctl", "-O", "OpenFlow13", "add-flow", "br0", iprule).CombinedOutput()
|
|
| 71 |
+ log.Infof("Output of adding %s: %s (%v)", iprule, o, e)
|
|
| 72 |
+ o, e = exec.Command("ovs-ofctl", "-O", "OpenFlow13", "add-flow", "br0", arprule).CombinedOutput()
|
|
| 73 |
+ log.Infof("Output of adding %s: %s (%v)", arprule, o, e)
|
|
| 74 |
+ return e |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+func (c *FlowController) DelOFRules(minion, localIP string) error {
|
|
| 78 |
+ if minion == localIP {
|
|
| 79 |
+ return nil |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ log.Infof("Calling del rules for %s", minion)
|
|
| 83 |
+ cookie := generateCookie(minion) |
|
| 84 |
+ iprule := fmt.Sprintf("table=6,cookie=0x%s/0xffffffff", cookie)
|
|
| 85 |
+ arprule := fmt.Sprintf("table=7,cookie=0x%s/0xffffffff", cookie)
|
|
| 86 |
+ o, e := exec.Command("ovs-ofctl", "-O", "OpenFlow13", "del-flows", "br0", iprule).CombinedOutput()
|
|
| 87 |
+ log.Infof("Output of deleting local ip rules %s (%v)", o, e)
|
|
| 88 |
+ o, e = exec.Command("ovs-ofctl", "-O", "OpenFlow13", "del-flows", "br0", arprule).CombinedOutput()
|
|
| 89 |
+ log.Infof("Output of deleting local arp rules %s (%v)", o, e)
|
|
| 90 |
+ return e |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+func generateCookie(ip string) string {
|
|
| 94 |
+ return hex.EncodeToString(net.ParseIP(ip).To4()) |
|
| 95 |
+} |
| 0 | 96 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,385 @@ |
| 0 |
+package registry |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "path" |
|
| 7 |
+ "strconv" |
|
| 8 |
+ "sync" |
|
| 9 |
+ "time" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/coreos/go-etcd/etcd" |
|
| 12 |
+ log "github.com/golang/glog" |
|
| 13 |
+ "github.com/openshift/openshift-sdn/ovssubnet/api" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+type EtcdConfig struct {
|
|
| 17 |
+ Endpoints []string |
|
| 18 |
+ Keyfile string |
|
| 19 |
+ Certfile string |
|
| 20 |
+ CAFile string |
|
| 21 |
+ SubnetPath string |
|
| 22 |
+ SubnetConfigPath string |
|
| 23 |
+ MinionPath string |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+type EtcdSubnetRegistry struct {
|
|
| 27 |
+ mux sync.Mutex |
|
| 28 |
+ cli *etcd.Client |
|
| 29 |
+ etcdCfg *EtcdConfig |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func newMinionEvent(action, key, value string) *api.MinionEvent {
|
|
| 33 |
+ min := &api.MinionEvent{}
|
|
| 34 |
+ switch action {
|
|
| 35 |
+ case "delete", "deleted", "expired": |
|
| 36 |
+ min.Type = api.Deleted |
|
| 37 |
+ default: |
|
| 38 |
+ min.Type = api.Added |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ if key != "" {
|
|
| 42 |
+ _, min.Minion = path.Split(key) |
|
| 43 |
+ return min |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ fmt.Printf("Error decoding minion event: nil key (%s,%s,%s).\n", action, key, value)
|
|
| 47 |
+ return nil |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+func newSubnetEvent(resp *etcd.Response) *api.SubnetEvent {
|
|
| 51 |
+ var value string |
|
| 52 |
+ _, minkey := path.Split(resp.Node.Key) |
|
| 53 |
+ var t api.EventType |
|
| 54 |
+ switch resp.Action {
|
|
| 55 |
+ case "deleted", "delete", "expired": |
|
| 56 |
+ t = api.Deleted |
|
| 57 |
+ value = resp.PrevNode.Value |
|
| 58 |
+ default: |
|
| 59 |
+ t = api.Added |
|
| 60 |
+ value = resp.Node.Value |
|
| 61 |
+ } |
|
| 62 |
+ var sub api.Subnet |
|
| 63 |
+ if err := json.Unmarshal([]byte(value), &sub); err == nil {
|
|
| 64 |
+ return &api.SubnetEvent{
|
|
| 65 |
+ Type: t, |
|
| 66 |
+ Minion: minkey, |
|
| 67 |
+ Sub: sub, |
|
| 68 |
+ } |
|
| 69 |
+ } |
|
| 70 |
+ log.Errorf("Failed to unmarshal response: %v", resp)
|
|
| 71 |
+ return nil |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+func newEtcdClient(c *EtcdConfig) (*etcd.Client, error) {
|
|
| 75 |
+ if c.Keyfile != "" || c.Certfile != "" || c.CAFile != "" {
|
|
| 76 |
+ return etcd.NewTLSClient(c.Endpoints, c.Certfile, c.Keyfile, c.CAFile) |
|
| 77 |
+ } else {
|
|
| 78 |
+ return etcd.NewClient(c.Endpoints), nil |
|
| 79 |
+ } |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func (sub *EtcdSubnetRegistry) CheckEtcdIsAlive(seconds uint64) bool {
|
|
| 83 |
+ for {
|
|
| 84 |
+ status := sub.client().SyncCluster() |
|
| 85 |
+ log.Infof("Etcd cluster status: %v", status)
|
|
| 86 |
+ if status {
|
|
| 87 |
+ return status |
|
| 88 |
+ } |
|
| 89 |
+ if seconds <= 0 {
|
|
| 90 |
+ break |
|
| 91 |
+ } |
|
| 92 |
+ time.Sleep(5 * time.Second) |
|
| 93 |
+ seconds -= 5 |
|
| 94 |
+ } |
|
| 95 |
+ return false |
|
| 96 |
+} |
|
| 97 |
+ |
|
| 98 |
+func NewEtcdSubnetRegistry(config *EtcdConfig) (api.SubnetRegistry, error) {
|
|
| 99 |
+ r := &EtcdSubnetRegistry{
|
|
| 100 |
+ etcdCfg: config, |
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ var err error |
|
| 104 |
+ r.cli, err = newEtcdClient(config) |
|
| 105 |
+ if err != nil {
|
|
| 106 |
+ return nil, err |
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ return r, nil |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+func (sub *EtcdSubnetRegistry) InitSubnets() error {
|
|
| 113 |
+ key := sub.etcdCfg.SubnetPath |
|
| 114 |
+ _, err := sub.client().SetDir(key, 0) |
|
| 115 |
+ if err != nil {
|
|
| 116 |
+ return err |
|
| 117 |
+ } |
|
| 118 |
+ key = sub.etcdCfg.SubnetConfigPath |
|
| 119 |
+ _, err = sub.client().SetDir(key, 0) |
|
| 120 |
+ return err |
|
| 121 |
+} |
|
| 122 |
+ |
|
| 123 |
+func (sub *EtcdSubnetRegistry) InitMinions() error {
|
|
| 124 |
+ key := sub.etcdCfg.MinionPath |
|
| 125 |
+ _, err := sub.client().SetDir(key, 0) |
|
| 126 |
+ return err |
|
| 127 |
+} |
|
| 128 |
+ |
|
| 129 |
+func (sub *EtcdSubnetRegistry) GetMinions() (*[]string, error) {
|
|
| 130 |
+ key := sub.etcdCfg.MinionPath |
|
| 131 |
+ resp, err := sub.client().Get(key, false, true) |
|
| 132 |
+ if err != nil {
|
|
| 133 |
+ return nil, err |
|
| 134 |
+ } |
|
| 135 |
+ |
|
| 136 |
+ if resp.Node.Dir == false {
|
|
| 137 |
+ return nil, errors.New("Minion path is not a directory")
|
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ minions := make([]string, 0) |
|
| 141 |
+ |
|
| 142 |
+ for _, node := range resp.Node.Nodes {
|
|
| 143 |
+ if node.Key == "" {
|
|
| 144 |
+ log.Errorf("Error unmarshalling GetMinions response node %s", node.Key)
|
|
| 145 |
+ continue |
|
| 146 |
+ } |
|
| 147 |
+ _, minion := path.Split(node.Key) |
|
| 148 |
+ minions = append(minions, minion) |
|
| 149 |
+ } |
|
| 150 |
+ return &minions, nil |
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+func (sub *EtcdSubnetRegistry) GetSubnets() (*[]api.Subnet, error) {
|
|
| 154 |
+ key := sub.etcdCfg.SubnetPath |
|
| 155 |
+ resp, err := sub.client().Get(key, false, true) |
|
| 156 |
+ if err != nil {
|
|
| 157 |
+ return nil, err |
|
| 158 |
+ } |
|
| 159 |
+ |
|
| 160 |
+ if resp.Node.Dir == false {
|
|
| 161 |
+ return nil, errors.New("Subnet path is not a directory")
|
|
| 162 |
+ } |
|
| 163 |
+ |
|
| 164 |
+ subnets := make([]api.Subnet, 0) |
|
| 165 |
+ |
|
| 166 |
+ for _, node := range resp.Node.Nodes {
|
|
| 167 |
+ var s api.Subnet |
|
| 168 |
+ err := json.Unmarshal([]byte(node.Value), &s) |
|
| 169 |
+ if err != nil {
|
|
| 170 |
+ log.Errorf("Error unmarshalling GetSubnets response for node %s: %s", node.Value, err.Error())
|
|
| 171 |
+ continue |
|
| 172 |
+ } |
|
| 173 |
+ subnets = append(subnets, s) |
|
| 174 |
+ } |
|
| 175 |
+ return &subnets, err |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+func (sub *EtcdSubnetRegistry) GetSubnet(minionip string) (*api.Subnet, error) {
|
|
| 179 |
+ key := path.Join(sub.etcdCfg.SubnetPath, minionip) |
|
| 180 |
+ resp, err := sub.client().Get(key, false, false) |
|
| 181 |
+ if err == nil {
|
|
| 182 |
+ log.Infof("Unmarshalling response: %s", resp.Node.Value)
|
|
| 183 |
+ var sub api.Subnet |
|
| 184 |
+ if err = json.Unmarshal([]byte(resp.Node.Value), &sub); err == nil {
|
|
| 185 |
+ return &sub, nil |
|
| 186 |
+ } |
|
| 187 |
+ return nil, err |
|
| 188 |
+ } |
|
| 189 |
+ return nil, err |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+func (sub *EtcdSubnetRegistry) DeleteSubnet(minion string) error {
|
|
| 193 |
+ key := path.Join(sub.etcdCfg.SubnetPath, minion) |
|
| 194 |
+ _, err := sub.client().Delete(key, false) |
|
| 195 |
+ return err |
|
| 196 |
+} |
|
| 197 |
+ |
|
| 198 |
+func (sub *EtcdSubnetRegistry) WriteNetworkConfig(network string, subnetLength uint) error {
|
|
| 199 |
+ key := path.Join(sub.etcdCfg.SubnetConfigPath, "ContainerNetwork") |
|
| 200 |
+ _, err := sub.client().Create(key, network, 0) |
|
| 201 |
+ if err != nil {
|
|
| 202 |
+ log.Warningf("Found existing network configuration, overwriting it.")
|
|
| 203 |
+ _, err = sub.client().Update(key, network, 0) |
|
| 204 |
+ if err != nil {
|
|
| 205 |
+ log.Errorf("Failed to write Network configuration to etcd: %v", err)
|
|
| 206 |
+ return err |
|
| 207 |
+ } |
|
| 208 |
+ } |
|
| 209 |
+ |
|
| 210 |
+ key = path.Join(sub.etcdCfg.SubnetConfigPath, "SubnetLength") |
|
| 211 |
+ data := strconv.FormatUint(uint64(subnetLength), 10) |
|
| 212 |
+ _, err = sub.client().Create(key, data, 0) |
|
| 213 |
+ if err != nil {
|
|
| 214 |
+ _, err = sub.client().Update(key, data, 0) |
|
| 215 |
+ if err != nil {
|
|
| 216 |
+ log.Errorf("Failed to write Network configuration to etcd: %v", err)
|
|
| 217 |
+ return err |
|
| 218 |
+ } |
|
| 219 |
+ } |
|
| 220 |
+ return nil |
|
| 221 |
+} |
|
| 222 |
+ |
|
| 223 |
+func (sub *EtcdSubnetRegistry) GetContainerNetwork() (string, error) {
|
|
| 224 |
+ key := path.Join(sub.etcdCfg.SubnetConfigPath, "ContainerNetwork") |
|
| 225 |
+ resp, err := sub.client().Get(key, false, false) |
|
| 226 |
+ if err != nil {
|
|
| 227 |
+ return "", err |
|
| 228 |
+ } |
|
| 229 |
+ return resp.Node.Value, err |
|
| 230 |
+} |
|
| 231 |
+ |
|
| 232 |
+func (sub *EtcdSubnetRegistry) GetSubnetLength() (uint64, error) {
|
|
| 233 |
+ key := path.Join(sub.etcdCfg.SubnetConfigPath, "SubnetLength") |
|
| 234 |
+ resp, err := sub.client().Get(key, false, false) |
|
| 235 |
+ if err == nil {
|
|
| 236 |
+ return strconv.ParseUint(resp.Node.Value, 10, 0) |
|
| 237 |
+ } |
|
| 238 |
+ return 0, err |
|
| 239 |
+} |
|
| 240 |
+ |
|
| 241 |
+func (sub *EtcdSubnetRegistry) CreateMinion(minion string, data string) error {
|
|
| 242 |
+ key := path.Join(sub.etcdCfg.MinionPath, minion) |
|
| 243 |
+ _, err := sub.client().Get(key, false, false) |
|
| 244 |
+ if err != nil {
|
|
| 245 |
+ // good, it does not exist, write it |
|
| 246 |
+ _, err = sub.client().Create(key, data, 0) |
|
| 247 |
+ if err != nil {
|
|
| 248 |
+ log.Errorf("Failed to write new subnet to etcd: %v", err)
|
|
| 249 |
+ return err |
|
| 250 |
+ } |
|
| 251 |
+ } |
|
| 252 |
+ |
|
| 253 |
+ return nil |
|
| 254 |
+} |
|
| 255 |
+ |
|
| 256 |
+func (sub *EtcdSubnetRegistry) CreateSubnet(minion string, subnet *api.Subnet) error {
|
|
| 257 |
+ subbytes, _ := json.Marshal(subnet) |
|
| 258 |
+ data := string(subbytes) |
|
| 259 |
+ log.Infof("Minion subnet structure: %s", data)
|
|
| 260 |
+ key := path.Join(sub.etcdCfg.SubnetPath, minion) |
|
| 261 |
+ _, err := sub.client().Create(key, data, 0) |
|
| 262 |
+ if err != nil {
|
|
| 263 |
+ _, err = sub.client().Update(key, data, 0) |
|
| 264 |
+ if err != nil {
|
|
| 265 |
+ log.Errorf("Failed to write new subnet to etcd: %v", err)
|
|
| 266 |
+ return err |
|
| 267 |
+ } |
|
| 268 |
+ } |
|
| 269 |
+ |
|
| 270 |
+ return nil |
|
| 271 |
+} |
|
| 272 |
+ |
|
| 273 |
+func (sub *EtcdSubnetRegistry) WatchMinions(receiver chan *api.MinionEvent, stop chan bool) error {
|
|
| 274 |
+ var rev uint64 |
|
| 275 |
+ rev = 0 |
|
| 276 |
+ key := sub.etcdCfg.MinionPath |
|
| 277 |
+ log.Infof("Watching %s for new minions.", key)
|
|
| 278 |
+ for {
|
|
| 279 |
+ resp, err := sub.watch(key, rev, stop) |
|
| 280 |
+ if err != nil && err == etcd.ErrWatchStoppedByUser {
|
|
| 281 |
+ log.Infof("New subnet event error: %v", err)
|
|
| 282 |
+ return err |
|
| 283 |
+ } |
|
| 284 |
+ if resp == nil || err != nil {
|
|
| 285 |
+ continue |
|
| 286 |
+ } |
|
| 287 |
+ rev = resp.Node.ModifiedIndex + 1 |
|
| 288 |
+ log.Infof("Issuing a minion event: %v", resp)
|
|
| 289 |
+ minevent := newMinionEvent(resp.Action, resp.Node.Key, resp.Node.Value) |
|
| 290 |
+ receiver <- minevent |
|
| 291 |
+ } |
|
| 292 |
+} |
|
| 293 |
+ |
|
| 294 |
+func (sub *EtcdSubnetRegistry) watch(key string, rev uint64, stop chan bool) (*etcd.Response, error) {
|
|
| 295 |
+ rawResp, err := sub.client().RawWatch(key, rev, true, nil, stop) |
|
| 296 |
+ |
|
| 297 |
+ if err != nil {
|
|
| 298 |
+ if err == etcd.ErrWatchStoppedByUser {
|
|
| 299 |
+ return nil, err |
|
| 300 |
+ } else {
|
|
| 301 |
+ log.Warningf("Temporary error while watching %s: %v\n", key, err)
|
|
| 302 |
+ time.Sleep(time.Second) |
|
| 303 |
+ sub.resetClient() |
|
| 304 |
+ return nil, nil |
|
| 305 |
+ } |
|
| 306 |
+ } |
|
| 307 |
+ |
|
| 308 |
+ if len(rawResp.Body) == 0 {
|
|
| 309 |
+ // etcd timed out, go back but recreate the client as the underlying |
|
| 310 |
+ // http transport gets hosed (http://code.google.com/p/go/issues/detail?id=8648) |
|
| 311 |
+ sub.resetClient() |
|
| 312 |
+ return nil, nil |
|
| 313 |
+ } |
|
| 314 |
+ |
|
| 315 |
+ return rawResp.Unmarshal() |
|
| 316 |
+} |
|
| 317 |
+ |
|
| 318 |
+func (sub *EtcdSubnetRegistry) WatchSubnets(receiver chan *api.SubnetEvent, stop chan bool) error {
|
|
| 319 |
+ for {
|
|
| 320 |
+ var rev uint64 |
|
| 321 |
+ rev = 0 |
|
| 322 |
+ key := sub.etcdCfg.SubnetPath |
|
| 323 |
+ resp, err := sub.watch(key, rev, stop) |
|
| 324 |
+ if resp == nil && err == nil {
|
|
| 325 |
+ continue |
|
| 326 |
+ } |
|
| 327 |
+ rev = resp.Node.ModifiedIndex + 1 |
|
| 328 |
+ if err != nil && err == etcd.ErrWatchStoppedByUser {
|
|
| 329 |
+ log.Infof("New subnet event error: %v", err)
|
|
| 330 |
+ return err |
|
| 331 |
+ } |
|
| 332 |
+ subevent := newSubnetEvent(resp) |
|
| 333 |
+ log.Infof("New subnet event: %v, %v", subevent, resp)
|
|
| 334 |
+ receiver <- subevent |
|
| 335 |
+ } |
|
| 336 |
+} |
|
| 337 |
+ |
|
| 338 |
+func (sub *EtcdSubnetRegistry) WatchNamespaces(receiver chan *api.NamespaceEvent, stop chan bool) error {
|
|
| 339 |
+ // TODO |
|
| 340 |
+ return nil |
|
| 341 |
+} |
|
| 342 |
+ |
|
| 343 |
+func (sub *EtcdSubnetRegistry) WatchNetNamespaces(receiver chan *api.NetNamespaceEvent, stop chan bool) error {
|
|
| 344 |
+ // TODO |
|
| 345 |
+ return nil |
|
| 346 |
+} |
|
| 347 |
+ |
|
| 348 |
+func (sub *EtcdSubnetRegistry) GetNetNamespaces() ([]api.NetNamespace, error) {
|
|
| 349 |
+ nslist := make([]api.NetNamespace, 0) |
|
| 350 |
+ // TODO |
|
| 351 |
+ return nslist, nil |
|
| 352 |
+} |
|
| 353 |
+ |
|
| 354 |
+func (sub *EtcdSubnetRegistry) GetNetNamespace(name string) (api.NetNamespace, error) {
|
|
| 355 |
+ // TODO |
|
| 356 |
+ return api.NetNamespace{}, nil
|
|
| 357 |
+} |
|
| 358 |
+ |
|
| 359 |
+func (sub *EtcdSubnetRegistry) WriteNetNamespace(name string, id uint) error {
|
|
| 360 |
+ // TODO |
|
| 361 |
+ return nil |
|
| 362 |
+} |
|
| 363 |
+ |
|
| 364 |
+func (sub *EtcdSubnetRegistry) DeleteNetNamespace(name string) error {
|
|
| 365 |
+ // TODO |
|
| 366 |
+ return nil |
|
| 367 |
+} |
|
| 368 |
+ |
|
| 369 |
+func (sub *EtcdSubnetRegistry) client() *etcd.Client {
|
|
| 370 |
+ sub.mux.Lock() |
|
| 371 |
+ defer sub.mux.Unlock() |
|
| 372 |
+ return sub.cli |
|
| 373 |
+} |
|
| 374 |
+ |
|
| 375 |
+func (sub *EtcdSubnetRegistry) resetClient() {
|
|
| 376 |
+ sub.mux.Lock() |
|
| 377 |
+ defer sub.mux.Unlock() |
|
| 378 |
+ |
|
| 379 |
+ var err error |
|
| 380 |
+ sub.cli, err = newEtcdClient(sub.etcdCfg) |
|
| 381 |
+ if err != nil {
|
|
| 382 |
+ panic(fmt.Errorf("resetClient: error recreating etcd client: %v", err))
|
|
| 383 |
+ } |
|
| 384 |
+} |
| 0 | 385 |
deleted file mode 100644 |
| ... | ... |
@@ -1,43 +0,0 @@ |
| 1 |
-package api |
|
| 2 |
- |
|
| 3 |
-type EventType string |
|
| 4 |
- |
|
| 5 |
-const ( |
|
| 6 |
- Added EventType = "ADDED" |
|
| 7 |
- Deleted EventType = "DELETED" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-type SubnetRegistry interface {
|
|
| 11 |
- InitSubnets() error |
|
| 12 |
- GetSubnets() (*[]Subnet, error) |
|
| 13 |
- GetSubnet(minion string) (*Subnet, error) |
|
| 14 |
- DeleteSubnet(minion string) error |
|
| 15 |
- CreateSubnet(sn string, sub *Subnet) error |
|
| 16 |
- WatchSubnets(receiver chan *SubnetEvent, stop chan bool) error |
|
| 17 |
- |
|
| 18 |
- InitMinions() error |
|
| 19 |
- GetMinions() (*[]string, error) |
|
| 20 |
- CreateMinion(minion string, data string) error |
|
| 21 |
- WatchMinions(receiver chan *MinionEvent, stop chan bool) error |
|
| 22 |
- |
|
| 23 |
- WriteNetworkConfig(network string, subnetLength uint) error |
|
| 24 |
- GetContainerNetwork() (string, error) |
|
| 25 |
- GetSubnetLength() (uint64, error) |
|
| 26 |
- CheckEtcdIsAlive(seconds uint64) bool |
|
| 27 |
-} |
|
| 28 |
- |
|
| 29 |
-type SubnetEvent struct {
|
|
| 30 |
- Type EventType |
|
| 31 |
- Minion string |
|
| 32 |
- Sub Subnet |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-type MinionEvent struct {
|
|
| 36 |
- Type EventType |
|
| 37 |
- Minion string |
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-type Subnet struct {
|
|
| 41 |
- Minion string |
|
| 42 |
- Sub string |
|
| 43 |
-} |
| 44 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,56 @@ |
| 0 |
+package netutils |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+type NetIDAllocator struct {
|
|
| 7 |
+ min uint |
|
| 8 |
+ max uint |
|
| 9 |
+ allocMap map[uint]bool |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+func NewNetIDAllocator(min uint, max uint, inUse []uint) (*NetIDAllocator, error) {
|
|
| 13 |
+ if max <= min {
|
|
| 14 |
+ return nil, fmt.Errorf("Min should be lesser than max value (Min: %d, Max: %d)", min, max)
|
|
| 15 |
+ } |
|
| 16 |
+ |
|
| 17 |
+ amap := make(map[uint]bool) |
|
| 18 |
+ for _, netid := range inUse {
|
|
| 19 |
+ if netid < min || netid > max {
|
|
| 20 |
+ fmt.Println("Provided net id doesn't belong to range: ", min, max)
|
|
| 21 |
+ continue |
|
| 22 |
+ } |
|
| 23 |
+ amap[netid] = true |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ return &NetIDAllocator{min: min, max: max, allocMap: amap}, nil
|
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func (nia *NetIDAllocator) GetNetID() (uint, error) {
|
|
| 30 |
+ var i uint |
|
| 31 |
+ // We exclude the last address as it is reserved for broadcast |
|
| 32 |
+ for i = nia.min; i <= nia.max; i++ {
|
|
| 33 |
+ taken, found := nia.allocMap[i] |
|
| 34 |
+ if !found || !taken {
|
|
| 35 |
+ nia.allocMap[i] = true |
|
| 36 |
+ return i, nil |
|
| 37 |
+ } |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ return 0, fmt.Errorf("No NetIDs available.")
|
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func (nia *NetIDAllocator) ReleaseNetID(netid uint) error {
|
|
| 44 |
+ if nia.min > netid || nia.max < netid {
|
|
| 45 |
+ return fmt.Errorf("Provided net id %v doesn't belong to the given range (%v-%v)", netid, nia.min, nia.max)
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ taken, found := nia.allocMap[netid] |
|
| 49 |
+ if !found || !taken {
|
|
| 50 |
+ return fmt.Errorf("Provided net id %v is already available.", netid)
|
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ nia.allocMap[netid] = false |
|
| 54 |
+ return nil |
|
| 55 |
+} |
| ... | ... |
@@ -71,7 +71,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| |
| 71 | 71 |
"num_minions" => ENV['OPENSHIFT_NUM_MINIONS'] || 2, |
| 72 | 72 |
"rebuild_yum_cache" => false, |
| 73 | 73 |
"cpus" => ENV['OPENSHIFT_NUM_CPUS'] || 2, |
| 74 |
- "memory" => ENV['OPENSHIFT_MEMORY'] || 1024, |
|
| 74 |
+ "memory" => ENV['OPENSHIFT_MEMORY'] || 2048, |
|
| 75 | 75 |
"sync_folders_type" => nil, |
| 76 | 76 |
"virtualbox" => {
|
| 77 | 77 |
"box_name" => "fedora_inst", |
| ... | ... |
@@ -6805,6 +6805,432 @@ |
| 6805 | 6805 |
] |
| 6806 | 6806 |
}, |
| 6807 | 6807 |
{
|
| 6808 |
+ "path": "/oapi/v1/netnamespaces", |
|
| 6809 |
+ "description": "OpenShift REST API, version v1", |
|
| 6810 |
+ "operations": [ |
|
| 6811 |
+ {
|
|
| 6812 |
+ "type": "v1.NetNamespaceList", |
|
| 6813 |
+ "method": "GET", |
|
| 6814 |
+ "summary": "list or watch objects of kind NetNamespace", |
|
| 6815 |
+ "nickname": "listNetNamespace", |
|
| 6816 |
+ "parameters": [ |
|
| 6817 |
+ {
|
|
| 6818 |
+ "type": "string", |
|
| 6819 |
+ "paramType": "query", |
|
| 6820 |
+ "name": "pretty", |
|
| 6821 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 6822 |
+ "required": false, |
|
| 6823 |
+ "allowMultiple": false |
|
| 6824 |
+ }, |
|
| 6825 |
+ {
|
|
| 6826 |
+ "type": "string", |
|
| 6827 |
+ "paramType": "query", |
|
| 6828 |
+ "name": "labelSelector", |
|
| 6829 |
+ "description": "a selector to restrict the list of returned objects by their labels; defaults to everything", |
|
| 6830 |
+ "required": false, |
|
| 6831 |
+ "allowMultiple": false |
|
| 6832 |
+ }, |
|
| 6833 |
+ {
|
|
| 6834 |
+ "type": "string", |
|
| 6835 |
+ "paramType": "query", |
|
| 6836 |
+ "name": "fieldSelector", |
|
| 6837 |
+ "description": "a selector to restrict the list of returned objects by their fields; defaults to everything", |
|
| 6838 |
+ "required": false, |
|
| 6839 |
+ "allowMultiple": false |
|
| 6840 |
+ }, |
|
| 6841 |
+ {
|
|
| 6842 |
+ "type": "boolean", |
|
| 6843 |
+ "paramType": "query", |
|
| 6844 |
+ "name": "watch", |
|
| 6845 |
+ "description": "watch for changes to the described resources and return them as a stream of add, update, and remove notifications; specify resourceVersion", |
|
| 6846 |
+ "required": false, |
|
| 6847 |
+ "allowMultiple": false |
|
| 6848 |
+ }, |
|
| 6849 |
+ {
|
|
| 6850 |
+ "type": "string", |
|
| 6851 |
+ "paramType": "query", |
|
| 6852 |
+ "name": "resourceVersion", |
|
| 6853 |
+ "description": "when specified with a watch call, shows changes that occur after that particular version of a resource; defaults to changes from the beginning of history", |
|
| 6854 |
+ "required": false, |
|
| 6855 |
+ "allowMultiple": false |
|
| 6856 |
+ } |
|
| 6857 |
+ ], |
|
| 6858 |
+ "responseMessages": [ |
|
| 6859 |
+ {
|
|
| 6860 |
+ "code": 200, |
|
| 6861 |
+ "message": "OK", |
|
| 6862 |
+ "responseModel": "v1.NetNamespaceList" |
|
| 6863 |
+ } |
|
| 6864 |
+ ], |
|
| 6865 |
+ "produces": [ |
|
| 6866 |
+ "application/json" |
|
| 6867 |
+ ], |
|
| 6868 |
+ "consumes": [ |
|
| 6869 |
+ "*/*" |
|
| 6870 |
+ ] |
|
| 6871 |
+ }, |
|
| 6872 |
+ {
|
|
| 6873 |
+ "type": "v1.NetNamespace", |
|
| 6874 |
+ "method": "POST", |
|
| 6875 |
+ "summary": "create a NetNamespace", |
|
| 6876 |
+ "nickname": "createNetNamespace", |
|
| 6877 |
+ "parameters": [ |
|
| 6878 |
+ {
|
|
| 6879 |
+ "type": "string", |
|
| 6880 |
+ "paramType": "query", |
|
| 6881 |
+ "name": "pretty", |
|
| 6882 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 6883 |
+ "required": false, |
|
| 6884 |
+ "allowMultiple": false |
|
| 6885 |
+ }, |
|
| 6886 |
+ {
|
|
| 6887 |
+ "type": "v1.NetNamespace", |
|
| 6888 |
+ "paramType": "body", |
|
| 6889 |
+ "name": "body", |
|
| 6890 |
+ "description": "", |
|
| 6891 |
+ "required": true, |
|
| 6892 |
+ "allowMultiple": false |
|
| 6893 |
+ } |
|
| 6894 |
+ ], |
|
| 6895 |
+ "responseMessages": [ |
|
| 6896 |
+ {
|
|
| 6897 |
+ "code": 200, |
|
| 6898 |
+ "message": "OK", |
|
| 6899 |
+ "responseModel": "v1.NetNamespace" |
|
| 6900 |
+ } |
|
| 6901 |
+ ], |
|
| 6902 |
+ "produces": [ |
|
| 6903 |
+ "application/json" |
|
| 6904 |
+ ], |
|
| 6905 |
+ "consumes": [ |
|
| 6906 |
+ "*/*" |
|
| 6907 |
+ ] |
|
| 6908 |
+ } |
|
| 6909 |
+ ] |
|
| 6910 |
+ }, |
|
| 6911 |
+ {
|
|
| 6912 |
+ "path": "/oapi/v1/watch/netnamespaces", |
|
| 6913 |
+ "description": "OpenShift REST API, version v1", |
|
| 6914 |
+ "operations": [ |
|
| 6915 |
+ {
|
|
| 6916 |
+ "type": "json.WatchEvent", |
|
| 6917 |
+ "method": "GET", |
|
| 6918 |
+ "summary": "watch individual changes to a list of NetNamespace", |
|
| 6919 |
+ "nickname": "watchNetNamespaceList", |
|
| 6920 |
+ "parameters": [ |
|
| 6921 |
+ {
|
|
| 6922 |
+ "type": "string", |
|
| 6923 |
+ "paramType": "query", |
|
| 6924 |
+ "name": "pretty", |
|
| 6925 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 6926 |
+ "required": false, |
|
| 6927 |
+ "allowMultiple": false |
|
| 6928 |
+ }, |
|
| 6929 |
+ {
|
|
| 6930 |
+ "type": "string", |
|
| 6931 |
+ "paramType": "query", |
|
| 6932 |
+ "name": "labelSelector", |
|
| 6933 |
+ "description": "a selector to restrict the list of returned objects by their labels; defaults to everything", |
|
| 6934 |
+ "required": false, |
|
| 6935 |
+ "allowMultiple": false |
|
| 6936 |
+ }, |
|
| 6937 |
+ {
|
|
| 6938 |
+ "type": "string", |
|
| 6939 |
+ "paramType": "query", |
|
| 6940 |
+ "name": "fieldSelector", |
|
| 6941 |
+ "description": "a selector to restrict the list of returned objects by their fields; defaults to everything", |
|
| 6942 |
+ "required": false, |
|
| 6943 |
+ "allowMultiple": false |
|
| 6944 |
+ }, |
|
| 6945 |
+ {
|
|
| 6946 |
+ "type": "boolean", |
|
| 6947 |
+ "paramType": "query", |
|
| 6948 |
+ "name": "watch", |
|
| 6949 |
+ "description": "watch for changes to the described resources and return them as a stream of add, update, and remove notifications; specify resourceVersion", |
|
| 6950 |
+ "required": false, |
|
| 6951 |
+ "allowMultiple": false |
|
| 6952 |
+ }, |
|
| 6953 |
+ {
|
|
| 6954 |
+ "type": "string", |
|
| 6955 |
+ "paramType": "query", |
|
| 6956 |
+ "name": "resourceVersion", |
|
| 6957 |
+ "description": "when specified with a watch call, shows changes that occur after that particular version of a resource; defaults to changes from the beginning of history", |
|
| 6958 |
+ "required": false, |
|
| 6959 |
+ "allowMultiple": false |
|
| 6960 |
+ } |
|
| 6961 |
+ ], |
|
| 6962 |
+ "responseMessages": [ |
|
| 6963 |
+ {
|
|
| 6964 |
+ "code": 200, |
|
| 6965 |
+ "message": "OK", |
|
| 6966 |
+ "responseModel": "json.WatchEvent" |
|
| 6967 |
+ } |
|
| 6968 |
+ ], |
|
| 6969 |
+ "produces": [ |
|
| 6970 |
+ "application/json" |
|
| 6971 |
+ ], |
|
| 6972 |
+ "consumes": [ |
|
| 6973 |
+ "*/*" |
|
| 6974 |
+ ] |
|
| 6975 |
+ } |
|
| 6976 |
+ ] |
|
| 6977 |
+ }, |
|
| 6978 |
+ {
|
|
| 6979 |
+ "path": "/oapi/v1/netnamespaces/{name}",
|
|
| 6980 |
+ "description": "OpenShift REST API, version v1", |
|
| 6981 |
+ "operations": [ |
|
| 6982 |
+ {
|
|
| 6983 |
+ "type": "v1.NetNamespace", |
|
| 6984 |
+ "method": "GET", |
|
| 6985 |
+ "summary": "read the specified NetNamespace", |
|
| 6986 |
+ "nickname": "readNetNamespace", |
|
| 6987 |
+ "parameters": [ |
|
| 6988 |
+ {
|
|
| 6989 |
+ "type": "string", |
|
| 6990 |
+ "paramType": "query", |
|
| 6991 |
+ "name": "pretty", |
|
| 6992 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 6993 |
+ "required": false, |
|
| 6994 |
+ "allowMultiple": false |
|
| 6995 |
+ }, |
|
| 6996 |
+ {
|
|
| 6997 |
+ "type": "string", |
|
| 6998 |
+ "paramType": "path", |
|
| 6999 |
+ "name": "name", |
|
| 7000 |
+ "description": "name of the NetNamespace", |
|
| 7001 |
+ "required": true, |
|
| 7002 |
+ "allowMultiple": false |
|
| 7003 |
+ } |
|
| 7004 |
+ ], |
|
| 7005 |
+ "responseMessages": [ |
|
| 7006 |
+ {
|
|
| 7007 |
+ "code": 200, |
|
| 7008 |
+ "message": "OK", |
|
| 7009 |
+ "responseModel": "v1.NetNamespace" |
|
| 7010 |
+ } |
|
| 7011 |
+ ], |
|
| 7012 |
+ "produces": [ |
|
| 7013 |
+ "application/json" |
|
| 7014 |
+ ], |
|
| 7015 |
+ "consumes": [ |
|
| 7016 |
+ "*/*" |
|
| 7017 |
+ ] |
|
| 7018 |
+ }, |
|
| 7019 |
+ {
|
|
| 7020 |
+ "type": "v1.NetNamespace", |
|
| 7021 |
+ "method": "PUT", |
|
| 7022 |
+ "summary": "replace the specified NetNamespace", |
|
| 7023 |
+ "nickname": "replaceNetNamespace", |
|
| 7024 |
+ "parameters": [ |
|
| 7025 |
+ {
|
|
| 7026 |
+ "type": "string", |
|
| 7027 |
+ "paramType": "query", |
|
| 7028 |
+ "name": "pretty", |
|
| 7029 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 7030 |
+ "required": false, |
|
| 7031 |
+ "allowMultiple": false |
|
| 7032 |
+ }, |
|
| 7033 |
+ {
|
|
| 7034 |
+ "type": "v1.NetNamespace", |
|
| 7035 |
+ "paramType": "body", |
|
| 7036 |
+ "name": "body", |
|
| 7037 |
+ "description": "", |
|
| 7038 |
+ "required": true, |
|
| 7039 |
+ "allowMultiple": false |
|
| 7040 |
+ }, |
|
| 7041 |
+ {
|
|
| 7042 |
+ "type": "string", |
|
| 7043 |
+ "paramType": "path", |
|
| 7044 |
+ "name": "name", |
|
| 7045 |
+ "description": "name of the NetNamespace", |
|
| 7046 |
+ "required": true, |
|
| 7047 |
+ "allowMultiple": false |
|
| 7048 |
+ } |
|
| 7049 |
+ ], |
|
| 7050 |
+ "responseMessages": [ |
|
| 7051 |
+ {
|
|
| 7052 |
+ "code": 200, |
|
| 7053 |
+ "message": "OK", |
|
| 7054 |
+ "responseModel": "v1.NetNamespace" |
|
| 7055 |
+ } |
|
| 7056 |
+ ], |
|
| 7057 |
+ "produces": [ |
|
| 7058 |
+ "application/json" |
|
| 7059 |
+ ], |
|
| 7060 |
+ "consumes": [ |
|
| 7061 |
+ "*/*" |
|
| 7062 |
+ ] |
|
| 7063 |
+ }, |
|
| 7064 |
+ {
|
|
| 7065 |
+ "type": "v1.NetNamespace", |
|
| 7066 |
+ "method": "PATCH", |
|
| 7067 |
+ "summary": "partially update the specified NetNamespace", |
|
| 7068 |
+ "nickname": "patchNetNamespace", |
|
| 7069 |
+ "parameters": [ |
|
| 7070 |
+ {
|
|
| 7071 |
+ "type": "string", |
|
| 7072 |
+ "paramType": "query", |
|
| 7073 |
+ "name": "pretty", |
|
| 7074 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 7075 |
+ "required": false, |
|
| 7076 |
+ "allowMultiple": false |
|
| 7077 |
+ }, |
|
| 7078 |
+ {
|
|
| 7079 |
+ "type": "api.Patch", |
|
| 7080 |
+ "paramType": "body", |
|
| 7081 |
+ "name": "body", |
|
| 7082 |
+ "description": "", |
|
| 7083 |
+ "required": true, |
|
| 7084 |
+ "allowMultiple": false |
|
| 7085 |
+ }, |
|
| 7086 |
+ {
|
|
| 7087 |
+ "type": "string", |
|
| 7088 |
+ "paramType": "path", |
|
| 7089 |
+ "name": "name", |
|
| 7090 |
+ "description": "name of the NetNamespace", |
|
| 7091 |
+ "required": true, |
|
| 7092 |
+ "allowMultiple": false |
|
| 7093 |
+ } |
|
| 7094 |
+ ], |
|
| 7095 |
+ "responseMessages": [ |
|
| 7096 |
+ {
|
|
| 7097 |
+ "code": 200, |
|
| 7098 |
+ "message": "OK", |
|
| 7099 |
+ "responseModel": "v1.NetNamespace" |
|
| 7100 |
+ } |
|
| 7101 |
+ ], |
|
| 7102 |
+ "produces": [ |
|
| 7103 |
+ "application/json" |
|
| 7104 |
+ ], |
|
| 7105 |
+ "consumes": [ |
|
| 7106 |
+ "application/json-patch+json", |
|
| 7107 |
+ "application/merge-patch+json", |
|
| 7108 |
+ "application/strategic-merge-patch+json" |
|
| 7109 |
+ ] |
|
| 7110 |
+ }, |
|
| 7111 |
+ {
|
|
| 7112 |
+ "type": "v1.Status", |
|
| 7113 |
+ "method": "DELETE", |
|
| 7114 |
+ "summary": "delete a NetNamespace", |
|
| 7115 |
+ "nickname": "deleteNetNamespace", |
|
| 7116 |
+ "parameters": [ |
|
| 7117 |
+ {
|
|
| 7118 |
+ "type": "string", |
|
| 7119 |
+ "paramType": "query", |
|
| 7120 |
+ "name": "pretty", |
|
| 7121 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 7122 |
+ "required": false, |
|
| 7123 |
+ "allowMultiple": false |
|
| 7124 |
+ }, |
|
| 7125 |
+ {
|
|
| 7126 |
+ "type": "v1.DeleteOptions", |
|
| 7127 |
+ "paramType": "body", |
|
| 7128 |
+ "name": "body", |
|
| 7129 |
+ "description": "", |
|
| 7130 |
+ "required": true, |
|
| 7131 |
+ "allowMultiple": false |
|
| 7132 |
+ }, |
|
| 7133 |
+ {
|
|
| 7134 |
+ "type": "string", |
|
| 7135 |
+ "paramType": "path", |
|
| 7136 |
+ "name": "name", |
|
| 7137 |
+ "description": "name of the NetNamespace", |
|
| 7138 |
+ "required": true, |
|
| 7139 |
+ "allowMultiple": false |
|
| 7140 |
+ } |
|
| 7141 |
+ ], |
|
| 7142 |
+ "responseMessages": [ |
|
| 7143 |
+ {
|
|
| 7144 |
+ "code": 200, |
|
| 7145 |
+ "message": "OK", |
|
| 7146 |
+ "responseModel": "v1.Status" |
|
| 7147 |
+ } |
|
| 7148 |
+ ], |
|
| 7149 |
+ "produces": [ |
|
| 7150 |
+ "application/json" |
|
| 7151 |
+ ], |
|
| 7152 |
+ "consumes": [ |
|
| 7153 |
+ "*/*" |
|
| 7154 |
+ ] |
|
| 7155 |
+ } |
|
| 7156 |
+ ] |
|
| 7157 |
+ }, |
|
| 7158 |
+ {
|
|
| 7159 |
+ "path": "/oapi/v1/watch/netnamespaces/{name}",
|
|
| 7160 |
+ "description": "OpenShift REST API, version v1", |
|
| 7161 |
+ "operations": [ |
|
| 7162 |
+ {
|
|
| 7163 |
+ "type": "json.WatchEvent", |
|
| 7164 |
+ "method": "GET", |
|
| 7165 |
+ "summary": "watch changes to an object of kind NetNamespace", |
|
| 7166 |
+ "nickname": "watchNetNamespace", |
|
| 7167 |
+ "parameters": [ |
|
| 7168 |
+ {
|
|
| 7169 |
+ "type": "string", |
|
| 7170 |
+ "paramType": "query", |
|
| 7171 |
+ "name": "pretty", |
|
| 7172 |
+ "description": "If 'true', then the output is pretty printed.", |
|
| 7173 |
+ "required": false, |
|
| 7174 |
+ "allowMultiple": false |
|
| 7175 |
+ }, |
|
| 7176 |
+ {
|
|
| 7177 |
+ "type": "string", |
|
| 7178 |
+ "paramType": "query", |
|
| 7179 |
+ "name": "labelSelector", |
|
| 7180 |
+ "description": "a selector to restrict the list of returned objects by their labels; defaults to everything", |
|
| 7181 |
+ "required": false, |
|
| 7182 |
+ "allowMultiple": false |
|
| 7183 |
+ }, |
|
| 7184 |
+ {
|
|
| 7185 |
+ "type": "string", |
|
| 7186 |
+ "paramType": "query", |
|
| 7187 |
+ "name": "fieldSelector", |
|
| 7188 |
+ "description": "a selector to restrict the list of returned objects by their fields; defaults to everything", |
|
| 7189 |
+ "required": false, |
|
| 7190 |
+ "allowMultiple": false |
|
| 7191 |
+ }, |
|
| 7192 |
+ {
|
|
| 7193 |
+ "type": "boolean", |
|
| 7194 |
+ "paramType": "query", |
|
| 7195 |
+ "name": "watch", |
|
| 7196 |
+ "description": "watch for changes to the described resources and return them as a stream of add, update, and remove notifications; specify resourceVersion", |
|
| 7197 |
+ "required": false, |
|
| 7198 |
+ "allowMultiple": false |
|
| 7199 |
+ }, |
|
| 7200 |
+ {
|
|
| 7201 |
+ "type": "string", |
|
| 7202 |
+ "paramType": "query", |
|
| 7203 |
+ "name": "resourceVersion", |
|
| 7204 |
+ "description": "when specified with a watch call, shows changes that occur after that particular version of a resource; defaults to changes from the beginning of history", |
|
| 7205 |
+ "required": false, |
|
| 7206 |
+ "allowMultiple": false |
|
| 7207 |
+ }, |
|
| 7208 |
+ {
|
|
| 7209 |
+ "type": "string", |
|
| 7210 |
+ "paramType": "path", |
|
| 7211 |
+ "name": "name", |
|
| 7212 |
+ "description": "name of the NetNamespace", |
|
| 7213 |
+ "required": true, |
|
| 7214 |
+ "allowMultiple": false |
|
| 7215 |
+ } |
|
| 7216 |
+ ], |
|
| 7217 |
+ "responseMessages": [ |
|
| 7218 |
+ {
|
|
| 7219 |
+ "code": 200, |
|
| 7220 |
+ "message": "OK", |
|
| 7221 |
+ "responseModel": "json.WatchEvent" |
|
| 7222 |
+ } |
|
| 7223 |
+ ], |
|
| 7224 |
+ "produces": [ |
|
| 7225 |
+ "application/json" |
|
| 7226 |
+ ], |
|
| 7227 |
+ "consumes": [ |
|
| 7228 |
+ "*/*" |
|
| 7229 |
+ ] |
|
| 7230 |
+ } |
|
| 7231 |
+ ] |
|
| 7232 |
+ }, |
|
| 7233 |
+ {
|
|
| 6808 | 7234 |
"path": "/oapi/v1/oauthaccesstokens", |
| 6809 | 7235 |
"description": "OpenShift REST API, version v1", |
| 6810 | 7236 |
"operations": [ |
| ... | ... |
@@ -15639,6 +16065,60 @@ |
| 15639 | 15639 |
} |
| 15640 | 15640 |
} |
| 15641 | 15641 |
}, |
| 15642 |
+ "v1.NetNamespaceList": {
|
|
| 15643 |
+ "id": "v1.NetNamespaceList", |
|
| 15644 |
+ "required": [ |
|
| 15645 |
+ "items" |
|
| 15646 |
+ ], |
|
| 15647 |
+ "properties": {
|
|
| 15648 |
+ "kind": {
|
|
| 15649 |
+ "type": "string", |
|
| 15650 |
+ "description": "kind of object, in CamelCase; cannot be updated; see http://releases.k8s.io/v1.0.0/docs/api-conventions.md#types-kinds" |
|
| 15651 |
+ }, |
|
| 15652 |
+ "apiVersion": {
|
|
| 15653 |
+ "type": "string", |
|
| 15654 |
+ "description": "version of the schema the object should have; see http://releases.k8s.io/v1.0.0/docs/api-conventions.md#resources" |
|
| 15655 |
+ }, |
|
| 15656 |
+ "metadata": {
|
|
| 15657 |
+ "$ref": "v1.ListMeta" |
|
| 15658 |
+ }, |
|
| 15659 |
+ "items": {
|
|
| 15660 |
+ "type": "array", |
|
| 15661 |
+ "items": {
|
|
| 15662 |
+ "$ref": "v1.NetNamespace" |
|
| 15663 |
+ }, |
|
| 15664 |
+ "description": "list of net namespaces" |
|
| 15665 |
+ } |
|
| 15666 |
+ } |
|
| 15667 |
+ }, |
|
| 15668 |
+ "v1.NetNamespace": {
|
|
| 15669 |
+ "id": "v1.NetNamespace", |
|
| 15670 |
+ "required": [ |
|
| 15671 |
+ "netname", |
|
| 15672 |
+ "netid" |
|
| 15673 |
+ ], |
|
| 15674 |
+ "properties": {
|
|
| 15675 |
+ "kind": {
|
|
| 15676 |
+ "type": "string", |
|
| 15677 |
+ "description": "kind of object, in CamelCase; cannot be updated; see http://releases.k8s.io/v1.0.0/docs/api-conventions.md#types-kinds" |
|
| 15678 |
+ }, |
|
| 15679 |
+ "apiVersion": {
|
|
| 15680 |
+ "type": "string", |
|
| 15681 |
+ "description": "version of the schema the object should have; see http://releases.k8s.io/v1.0.0/docs/api-conventions.md#resources" |
|
| 15682 |
+ }, |
|
| 15683 |
+ "metadata": {
|
|
| 15684 |
+ "$ref": "v1.ObjectMeta" |
|
| 15685 |
+ }, |
|
| 15686 |
+ "netname": {
|
|
| 15687 |
+ "type": "string", |
|
| 15688 |
+ "description": "Name of the network namespace." |
|
| 15689 |
+ }, |
|
| 15690 |
+ "netid": {
|
|
| 15691 |
+ "type": "uint", |
|
| 15692 |
+ "description": "NetID of the network namespace assigned to each overlay network packet." |
|
| 15693 |
+ } |
|
| 15694 |
+ } |
|
| 15695 |
+ }, |
|
| 15642 | 15696 |
"v1.OAuthAccessTokenList": {
|
| 15643 | 15697 |
"id": "v1.OAuthAccessTokenList", |
| 15644 | 15698 |
"required": [ |
| ... | ... |
@@ -289,15 +289,18 @@ install -p -m 0644 rel-eng/docker-sdn-ovs.conf %{buildroot}%{_unitdir}/docker.se
|
| 289 | 289 |
for pkgname in openshift atomic-enterprise |
| 290 | 290 |
do |
| 291 | 291 |
|
| 292 |
- pushd _thirdpartyhacks/src/%{sdn_import_path}/ovssubnet/bin
|
|
| 292 |
+ pushd _thirdpartyhacks/src/%{sdn_import_path}/ovssubnet/controller/kube/bin
|
|
| 293 | 293 |
install -p -m 755 %{name}-ovs-subnet %{buildroot}%{kube_plugin_path}/${pkgname}-ovs-subnet
|
| 294 | 294 |
install -p -m 755 %{name}-sdn-kube-subnet-setup.sh %{buildroot}%{_bindir}/${pkgname}-sdn-kube-subnet-setup.sh
|
| 295 | 295 |
popd |
| 296 |
+ pushd _thirdpartyhacks/src/%{sdn_import_path}/ovssubnet/controller/multitenant/bin
|
|
| 297 |
+ install -p -m 755 %{name}-ovs-multitenant %{buildroot}%{_bindir}/${pkgname}-ovs-multitenant
|
|
| 298 |
+ install -p -m 755 %{name}-sdn-multitenant-setup.sh %{buildroot}%{_bindir}/${pkgname}-sdn-multitenant-setup.sh
|
|
| 299 |
+ popd |
|
| 296 | 300 |
install -d -m 0755 %{buildroot}%{_unitdir}/${pkgname}-node.service.d
|
| 297 | 301 |
install -p -m 0644 rel-eng/%{name}-sdn-ovs.conf %{buildroot}%{_unitdir}/${pkgname}-node.service.d/${pkgname}-sdn-ovs.conf
|
| 298 | 302 |
done |
| 299 | 303 |
|
| 300 |
- |
|
| 301 | 304 |
# Install bash completions |
| 302 | 305 |
install -d -m 755 %{buildroot}/etc/bash_completion.d/
|
| 303 | 306 |
install -p -m 644 rel-eng/completions/bash/* %{buildroot}/etc/bash_completion.d/
|
| ... | ... |
@@ -2245,6 +2245,46 @@ func deepCopy_api_HostSubnetList(in sdnapi.HostSubnetList, out *sdnapi.HostSubne |
| 2245 | 2245 |
return nil |
| 2246 | 2246 |
} |
| 2247 | 2247 |
|
| 2248 |
+func deepCopy_api_NetNamespace(in sdnapi.NetNamespace, out *sdnapi.NetNamespace, c *conversion.Cloner) error {
|
|
| 2249 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2250 |
+ return err |
|
| 2251 |
+ } else {
|
|
| 2252 |
+ out.TypeMeta = newVal.(api.TypeMeta) |
|
| 2253 |
+ } |
|
| 2254 |
+ if newVal, err := c.DeepCopy(in.ObjectMeta); err != nil {
|
|
| 2255 |
+ return err |
|
| 2256 |
+ } else {
|
|
| 2257 |
+ out.ObjectMeta = newVal.(api.ObjectMeta) |
|
| 2258 |
+ } |
|
| 2259 |
+ out.NetName = in.NetName |
|
| 2260 |
+ out.NetID = in.NetID |
|
| 2261 |
+ return nil |
|
| 2262 |
+} |
|
| 2263 |
+ |
|
| 2264 |
+func deepCopy_api_NetNamespaceList(in sdnapi.NetNamespaceList, out *sdnapi.NetNamespaceList, c *conversion.Cloner) error {
|
|
| 2265 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2266 |
+ return err |
|
| 2267 |
+ } else {
|
|
| 2268 |
+ out.TypeMeta = newVal.(api.TypeMeta) |
|
| 2269 |
+ } |
|
| 2270 |
+ if newVal, err := c.DeepCopy(in.ListMeta); err != nil {
|
|
| 2271 |
+ return err |
|
| 2272 |
+ } else {
|
|
| 2273 |
+ out.ListMeta = newVal.(api.ListMeta) |
|
| 2274 |
+ } |
|
| 2275 |
+ if in.Items != nil {
|
|
| 2276 |
+ out.Items = make([]sdnapi.NetNamespace, len(in.Items)) |
|
| 2277 |
+ for i := range in.Items {
|
|
| 2278 |
+ if err := deepCopy_api_NetNamespace(in.Items[i], &out.Items[i], c); err != nil {
|
|
| 2279 |
+ return err |
|
| 2280 |
+ } |
|
| 2281 |
+ } |
|
| 2282 |
+ } else {
|
|
| 2283 |
+ out.Items = nil |
|
| 2284 |
+ } |
|
| 2285 |
+ return nil |
|
| 2286 |
+} |
|
| 2287 |
+ |
|
| 2248 | 2288 |
func deepCopy_api_Parameter(in templateapi.Parameter, out *templateapi.Parameter, c *conversion.Cloner) error {
|
| 2249 | 2289 |
out.Name = in.Name |
| 2250 | 2290 |
out.Description = in.Description |
| ... | ... |
@@ -2599,6 +2639,8 @@ func init() {
|
| 2599 | 2599 |
deepCopy_api_ClusterNetworkList, |
| 2600 | 2600 |
deepCopy_api_HostSubnet, |
| 2601 | 2601 |
deepCopy_api_HostSubnetList, |
| 2602 |
+ deepCopy_api_NetNamespace, |
|
| 2603 |
+ deepCopy_api_NetNamespaceList, |
|
| 2602 | 2604 |
deepCopy_api_Parameter, |
| 2603 | 2605 |
deepCopy_api_Template, |
| 2604 | 2606 |
deepCopy_api_TemplateList, |
| ... | ... |
@@ -2564,6 +2564,44 @@ func convert_api_HostSubnetList_To_v1_HostSubnetList(in *sdnapi.HostSubnetList, |
| 2564 | 2564 |
return nil |
| 2565 | 2565 |
} |
| 2566 | 2566 |
|
| 2567 |
+func convert_api_NetNamespace_To_v1_NetNamespace(in *sdnapi.NetNamespace, out *sdnapiv1.NetNamespace, s conversion.Scope) error {
|
|
| 2568 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2569 |
+ defaulting.(func(*sdnapi.NetNamespace))(in) |
|
| 2570 |
+ } |
|
| 2571 |
+ if err := convert_api_TypeMeta_To_v1_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2572 |
+ return err |
|
| 2573 |
+ } |
|
| 2574 |
+ if err := convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
|
| 2575 |
+ return err |
|
| 2576 |
+ } |
|
| 2577 |
+ out.NetName = in.NetName |
|
| 2578 |
+ out.NetID = in.NetID |
|
| 2579 |
+ return nil |
|
| 2580 |
+} |
|
| 2581 |
+ |
|
| 2582 |
+func convert_api_NetNamespaceList_To_v1_NetNamespaceList(in *sdnapi.NetNamespaceList, out *sdnapiv1.NetNamespaceList, s conversion.Scope) error {
|
|
| 2583 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2584 |
+ defaulting.(func(*sdnapi.NetNamespaceList))(in) |
|
| 2585 |
+ } |
|
| 2586 |
+ if err := convert_api_TypeMeta_To_v1_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2587 |
+ return err |
|
| 2588 |
+ } |
|
| 2589 |
+ if err := convert_api_ListMeta_To_v1_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
|
| 2590 |
+ return err |
|
| 2591 |
+ } |
|
| 2592 |
+ if in.Items != nil {
|
|
| 2593 |
+ out.Items = make([]sdnapiv1.NetNamespace, len(in.Items)) |
|
| 2594 |
+ for i := range in.Items {
|
|
| 2595 |
+ if err := convert_api_NetNamespace_To_v1_NetNamespace(&in.Items[i], &out.Items[i], s); err != nil {
|
|
| 2596 |
+ return err |
|
| 2597 |
+ } |
|
| 2598 |
+ } |
|
| 2599 |
+ } else {
|
|
| 2600 |
+ out.Items = nil |
|
| 2601 |
+ } |
|
| 2602 |
+ return nil |
|
| 2603 |
+} |
|
| 2604 |
+ |
|
| 2567 | 2605 |
func convert_v1_ClusterNetwork_To_api_ClusterNetwork(in *sdnapiv1.ClusterNetwork, out *sdnapi.ClusterNetwork, s conversion.Scope) error {
|
| 2568 | 2606 |
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
| 2569 | 2607 |
defaulting.(func(*sdnapiv1.ClusterNetwork))(in) |
| ... | ... |
@@ -2641,6 +2679,44 @@ func convert_v1_HostSubnetList_To_api_HostSubnetList(in *sdnapiv1.HostSubnetList |
| 2641 | 2641 |
return nil |
| 2642 | 2642 |
} |
| 2643 | 2643 |
|
| 2644 |
+func convert_v1_NetNamespace_To_api_NetNamespace(in *sdnapiv1.NetNamespace, out *sdnapi.NetNamespace, s conversion.Scope) error {
|
|
| 2645 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2646 |
+ defaulting.(func(*sdnapiv1.NetNamespace))(in) |
|
| 2647 |
+ } |
|
| 2648 |
+ if err := convert_v1_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2649 |
+ return err |
|
| 2650 |
+ } |
|
| 2651 |
+ if err := convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
|
| 2652 |
+ return err |
|
| 2653 |
+ } |
|
| 2654 |
+ out.NetName = in.NetName |
|
| 2655 |
+ out.NetID = in.NetID |
|
| 2656 |
+ return nil |
|
| 2657 |
+} |
|
| 2658 |
+ |
|
| 2659 |
+func convert_v1_NetNamespaceList_To_api_NetNamespaceList(in *sdnapiv1.NetNamespaceList, out *sdnapi.NetNamespaceList, s conversion.Scope) error {
|
|
| 2660 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2661 |
+ defaulting.(func(*sdnapiv1.NetNamespaceList))(in) |
|
| 2662 |
+ } |
|
| 2663 |
+ if err := convert_v1_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2664 |
+ return err |
|
| 2665 |
+ } |
|
| 2666 |
+ if err := convert_v1_ListMeta_To_api_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
|
| 2667 |
+ return err |
|
| 2668 |
+ } |
|
| 2669 |
+ if in.Items != nil {
|
|
| 2670 |
+ out.Items = make([]sdnapi.NetNamespace, len(in.Items)) |
|
| 2671 |
+ for i := range in.Items {
|
|
| 2672 |
+ if err := convert_v1_NetNamespace_To_api_NetNamespace(&in.Items[i], &out.Items[i], s); err != nil {
|
|
| 2673 |
+ return err |
|
| 2674 |
+ } |
|
| 2675 |
+ } |
|
| 2676 |
+ } else {
|
|
| 2677 |
+ out.Items = nil |
|
| 2678 |
+ } |
|
| 2679 |
+ return nil |
|
| 2680 |
+} |
|
| 2681 |
+ |
|
| 2644 | 2682 |
func convert_api_Parameter_To_v1_Parameter(in *templateapi.Parameter, out *templateapiv1.Parameter, s conversion.Scope) error {
|
| 2645 | 2683 |
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
| 2646 | 2684 |
defaulting.(func(*templateapi.Parameter))(in) |
| ... | ... |
@@ -3087,6 +3163,8 @@ func init() {
|
| 3087 | 3087 |
convert_api_IsPersonalSubjectAccessReview_To_v1_IsPersonalSubjectAccessReview, |
| 3088 | 3088 |
convert_api_ListMeta_To_v1_ListMeta, |
| 3089 | 3089 |
convert_api_LocalObjectReference_To_v1_LocalObjectReference, |
| 3090 |
+ convert_api_NetNamespaceList_To_v1_NetNamespaceList, |
|
| 3091 |
+ convert_api_NetNamespace_To_v1_NetNamespace, |
|
| 3090 | 3092 |
convert_api_OAuthAccessTokenList_To_v1_OAuthAccessTokenList, |
| 3091 | 3093 |
convert_api_OAuthAccessToken_To_v1_OAuthAccessToken, |
| 3092 | 3094 |
convert_api_OAuthAuthorizeTokenList_To_v1_OAuthAuthorizeTokenList, |
| ... | ... |
@@ -3163,6 +3241,8 @@ func init() {
|
| 3163 | 3163 |
convert_v1_IsPersonalSubjectAccessReview_To_api_IsPersonalSubjectAccessReview, |
| 3164 | 3164 |
convert_v1_ListMeta_To_api_ListMeta, |
| 3165 | 3165 |
convert_v1_LocalObjectReference_To_api_LocalObjectReference, |
| 3166 |
+ convert_v1_NetNamespaceList_To_api_NetNamespaceList, |
|
| 3167 |
+ convert_v1_NetNamespace_To_api_NetNamespace, |
|
| 3166 | 3168 |
convert_v1_OAuthAccessTokenList_To_api_OAuthAccessTokenList, |
| 3167 | 3169 |
convert_v1_OAuthAccessToken_To_api_OAuthAccessToken, |
| 3168 | 3170 |
convert_v1_OAuthAuthorizeTokenList_To_api_OAuthAuthorizeTokenList, |
| ... | ... |
@@ -2122,6 +2122,46 @@ func deepCopy_v1_HostSubnetList(in sdnapiv1.HostSubnetList, out *sdnapiv1.HostSu |
| 2122 | 2122 |
return nil |
| 2123 | 2123 |
} |
| 2124 | 2124 |
|
| 2125 |
+func deepCopy_v1_NetNamespace(in sdnapiv1.NetNamespace, out *sdnapiv1.NetNamespace, c *conversion.Cloner) error {
|
|
| 2126 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2127 |
+ return err |
|
| 2128 |
+ } else {
|
|
| 2129 |
+ out.TypeMeta = newVal.(v1.TypeMeta) |
|
| 2130 |
+ } |
|
| 2131 |
+ if newVal, err := c.DeepCopy(in.ObjectMeta); err != nil {
|
|
| 2132 |
+ return err |
|
| 2133 |
+ } else {
|
|
| 2134 |
+ out.ObjectMeta = newVal.(v1.ObjectMeta) |
|
| 2135 |
+ } |
|
| 2136 |
+ out.NetName = in.NetName |
|
| 2137 |
+ out.NetID = in.NetID |
|
| 2138 |
+ return nil |
|
| 2139 |
+} |
|
| 2140 |
+ |
|
| 2141 |
+func deepCopy_v1_NetNamespaceList(in sdnapiv1.NetNamespaceList, out *sdnapiv1.NetNamespaceList, c *conversion.Cloner) error {
|
|
| 2142 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2143 |
+ return err |
|
| 2144 |
+ } else {
|
|
| 2145 |
+ out.TypeMeta = newVal.(v1.TypeMeta) |
|
| 2146 |
+ } |
|
| 2147 |
+ if newVal, err := c.DeepCopy(in.ListMeta); err != nil {
|
|
| 2148 |
+ return err |
|
| 2149 |
+ } else {
|
|
| 2150 |
+ out.ListMeta = newVal.(v1.ListMeta) |
|
| 2151 |
+ } |
|
| 2152 |
+ if in.Items != nil {
|
|
| 2153 |
+ out.Items = make([]sdnapiv1.NetNamespace, len(in.Items)) |
|
| 2154 |
+ for i := range in.Items {
|
|
| 2155 |
+ if err := deepCopy_v1_NetNamespace(in.Items[i], &out.Items[i], c); err != nil {
|
|
| 2156 |
+ return err |
|
| 2157 |
+ } |
|
| 2158 |
+ } |
|
| 2159 |
+ } else {
|
|
| 2160 |
+ out.Items = nil |
|
| 2161 |
+ } |
|
| 2162 |
+ return nil |
|
| 2163 |
+} |
|
| 2164 |
+ |
|
| 2125 | 2165 |
func deepCopy_v1_Parameter(in templateapiv1.Parameter, out *templateapiv1.Parameter, c *conversion.Cloner) error {
|
| 2126 | 2166 |
out.Name = in.Name |
| 2127 | 2167 |
out.Description = in.Description |
| ... | ... |
@@ -2481,6 +2521,8 @@ func init() {
|
| 2481 | 2481 |
deepCopy_v1_ClusterNetworkList, |
| 2482 | 2482 |
deepCopy_v1_HostSubnet, |
| 2483 | 2483 |
deepCopy_v1_HostSubnetList, |
| 2484 |
+ deepCopy_v1_NetNamespace, |
|
| 2485 |
+ deepCopy_v1_NetNamespaceList, |
|
| 2484 | 2486 |
deepCopy_v1_Parameter, |
| 2485 | 2487 |
deepCopy_v1_Template, |
| 2486 | 2488 |
deepCopy_v1_TemplateList, |
| ... | ... |
@@ -2500,6 +2500,44 @@ func convert_api_HostSubnetList_To_v1beta3_HostSubnetList(in *sdnapi.HostSubnetL |
| 2500 | 2500 |
return nil |
| 2501 | 2501 |
} |
| 2502 | 2502 |
|
| 2503 |
+func convert_api_NetNamespace_To_v1beta3_NetNamespace(in *sdnapi.NetNamespace, out *sdnapiv1beta3.NetNamespace, s conversion.Scope) error {
|
|
| 2504 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2505 |
+ defaulting.(func(*sdnapi.NetNamespace))(in) |
|
| 2506 |
+ } |
|
| 2507 |
+ if err := convert_api_TypeMeta_To_v1beta3_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2508 |
+ return err |
|
| 2509 |
+ } |
|
| 2510 |
+ if err := convert_api_ObjectMeta_To_v1beta3_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
|
| 2511 |
+ return err |
|
| 2512 |
+ } |
|
| 2513 |
+ out.NetName = in.NetName |
|
| 2514 |
+ out.NetID = in.NetID |
|
| 2515 |
+ return nil |
|
| 2516 |
+} |
|
| 2517 |
+ |
|
| 2518 |
+func convert_api_NetNamespaceList_To_v1beta3_NetNamespaceList(in *sdnapi.NetNamespaceList, out *sdnapiv1beta3.NetNamespaceList, s conversion.Scope) error {
|
|
| 2519 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2520 |
+ defaulting.(func(*sdnapi.NetNamespaceList))(in) |
|
| 2521 |
+ } |
|
| 2522 |
+ if err := convert_api_TypeMeta_To_v1beta3_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2523 |
+ return err |
|
| 2524 |
+ } |
|
| 2525 |
+ if err := convert_api_ListMeta_To_v1beta3_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
|
| 2526 |
+ return err |
|
| 2527 |
+ } |
|
| 2528 |
+ if in.Items != nil {
|
|
| 2529 |
+ out.Items = make([]sdnapiv1beta3.NetNamespace, len(in.Items)) |
|
| 2530 |
+ for i := range in.Items {
|
|
| 2531 |
+ if err := convert_api_NetNamespace_To_v1beta3_NetNamespace(&in.Items[i], &out.Items[i], s); err != nil {
|
|
| 2532 |
+ return err |
|
| 2533 |
+ } |
|
| 2534 |
+ } |
|
| 2535 |
+ } else {
|
|
| 2536 |
+ out.Items = nil |
|
| 2537 |
+ } |
|
| 2538 |
+ return nil |
|
| 2539 |
+} |
|
| 2540 |
+ |
|
| 2503 | 2541 |
func convert_v1beta3_ClusterNetwork_To_api_ClusterNetwork(in *sdnapiv1beta3.ClusterNetwork, out *sdnapi.ClusterNetwork, s conversion.Scope) error {
|
| 2504 | 2542 |
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
| 2505 | 2543 |
defaulting.(func(*sdnapiv1beta3.ClusterNetwork))(in) |
| ... | ... |
@@ -2577,6 +2615,44 @@ func convert_v1beta3_HostSubnetList_To_api_HostSubnetList(in *sdnapiv1beta3.Host |
| 2577 | 2577 |
return nil |
| 2578 | 2578 |
} |
| 2579 | 2579 |
|
| 2580 |
+func convert_v1beta3_NetNamespace_To_api_NetNamespace(in *sdnapiv1beta3.NetNamespace, out *sdnapi.NetNamespace, s conversion.Scope) error {
|
|
| 2581 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2582 |
+ defaulting.(func(*sdnapiv1beta3.NetNamespace))(in) |
|
| 2583 |
+ } |
|
| 2584 |
+ if err := convert_v1beta3_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2585 |
+ return err |
|
| 2586 |
+ } |
|
| 2587 |
+ if err := convert_v1beta3_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
|
| 2588 |
+ return err |
|
| 2589 |
+ } |
|
| 2590 |
+ out.NetName = in.NetName |
|
| 2591 |
+ out.NetID = in.NetID |
|
| 2592 |
+ return nil |
|
| 2593 |
+} |
|
| 2594 |
+ |
|
| 2595 |
+func convert_v1beta3_NetNamespaceList_To_api_NetNamespaceList(in *sdnapiv1beta3.NetNamespaceList, out *sdnapi.NetNamespaceList, s conversion.Scope) error {
|
|
| 2596 |
+ if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
|
| 2597 |
+ defaulting.(func(*sdnapiv1beta3.NetNamespaceList))(in) |
|
| 2598 |
+ } |
|
| 2599 |
+ if err := convert_v1beta3_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
|
| 2600 |
+ return err |
|
| 2601 |
+ } |
|
| 2602 |
+ if err := convert_v1beta3_ListMeta_To_api_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
|
| 2603 |
+ return err |
|
| 2604 |
+ } |
|
| 2605 |
+ if in.Items != nil {
|
|
| 2606 |
+ out.Items = make([]sdnapi.NetNamespace, len(in.Items)) |
|
| 2607 |
+ for i := range in.Items {
|
|
| 2608 |
+ if err := convert_v1beta3_NetNamespace_To_api_NetNamespace(&in.Items[i], &out.Items[i], s); err != nil {
|
|
| 2609 |
+ return err |
|
| 2610 |
+ } |
|
| 2611 |
+ } |
|
| 2612 |
+ } else {
|
|
| 2613 |
+ out.Items = nil |
|
| 2614 |
+ } |
|
| 2615 |
+ return nil |
|
| 2616 |
+} |
|
| 2617 |
+ |
|
| 2580 | 2618 |
func convert_api_Parameter_To_v1beta3_Parameter(in *templateapi.Parameter, out *templateapiv1beta3.Parameter, s conversion.Scope) error {
|
| 2581 | 2619 |
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
| 2582 | 2620 |
defaulting.(func(*templateapi.Parameter))(in) |
| ... | ... |
@@ -3021,6 +3097,8 @@ func init() {
|
| 3021 | 3021 |
convert_api_IsPersonalSubjectAccessReview_To_v1beta3_IsPersonalSubjectAccessReview, |
| 3022 | 3022 |
convert_api_ListMeta_To_v1beta3_ListMeta, |
| 3023 | 3023 |
convert_api_LocalObjectReference_To_v1beta3_LocalObjectReference, |
| 3024 |
+ convert_api_NetNamespaceList_To_v1beta3_NetNamespaceList, |
|
| 3025 |
+ convert_api_NetNamespace_To_v1beta3_NetNamespace, |
|
| 3024 | 3026 |
convert_api_OAuthAccessTokenList_To_v1beta3_OAuthAccessTokenList, |
| 3025 | 3027 |
convert_api_OAuthAccessToken_To_v1beta3_OAuthAccessToken, |
| 3026 | 3028 |
convert_api_OAuthAuthorizeTokenList_To_v1beta3_OAuthAuthorizeTokenList, |
| ... | ... |
@@ -3095,6 +3173,8 @@ func init() {
|
| 3095 | 3095 |
convert_v1beta3_IsPersonalSubjectAccessReview_To_api_IsPersonalSubjectAccessReview, |
| 3096 | 3096 |
convert_v1beta3_ListMeta_To_api_ListMeta, |
| 3097 | 3097 |
convert_v1beta3_LocalObjectReference_To_api_LocalObjectReference, |
| 3098 |
+ convert_v1beta3_NetNamespaceList_To_api_NetNamespaceList, |
|
| 3099 |
+ convert_v1beta3_NetNamespace_To_api_NetNamespace, |
|
| 3098 | 3100 |
convert_v1beta3_OAuthAccessTokenList_To_api_OAuthAccessTokenList, |
| 3099 | 3101 |
convert_v1beta3_OAuthAccessToken_To_api_OAuthAccessToken, |
| 3100 | 3102 |
convert_v1beta3_OAuthAuthorizeTokenList_To_api_OAuthAuthorizeTokenList, |
| ... | ... |
@@ -2112,6 +2112,46 @@ func deepCopy_v1beta3_HostSubnetList(in sdnapiv1beta3.HostSubnetList, out *sdnap |
| 2112 | 2112 |
return nil |
| 2113 | 2113 |
} |
| 2114 | 2114 |
|
| 2115 |
+func deepCopy_v1beta3_NetNamespace(in sdnapiv1beta3.NetNamespace, out *sdnapiv1beta3.NetNamespace, c *conversion.Cloner) error {
|
|
| 2116 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2117 |
+ return err |
|
| 2118 |
+ } else {
|
|
| 2119 |
+ out.TypeMeta = newVal.(v1beta3.TypeMeta) |
|
| 2120 |
+ } |
|
| 2121 |
+ if newVal, err := c.DeepCopy(in.ObjectMeta); err != nil {
|
|
| 2122 |
+ return err |
|
| 2123 |
+ } else {
|
|
| 2124 |
+ out.ObjectMeta = newVal.(v1beta3.ObjectMeta) |
|
| 2125 |
+ } |
|
| 2126 |
+ out.NetName = in.NetName |
|
| 2127 |
+ out.NetID = in.NetID |
|
| 2128 |
+ return nil |
|
| 2129 |
+} |
|
| 2130 |
+ |
|
| 2131 |
+func deepCopy_v1beta3_NetNamespaceList(in sdnapiv1beta3.NetNamespaceList, out *sdnapiv1beta3.NetNamespaceList, c *conversion.Cloner) error {
|
|
| 2132 |
+ if newVal, err := c.DeepCopy(in.TypeMeta); err != nil {
|
|
| 2133 |
+ return err |
|
| 2134 |
+ } else {
|
|
| 2135 |
+ out.TypeMeta = newVal.(v1beta3.TypeMeta) |
|
| 2136 |
+ } |
|
| 2137 |
+ if newVal, err := c.DeepCopy(in.ListMeta); err != nil {
|
|
| 2138 |
+ return err |
|
| 2139 |
+ } else {
|
|
| 2140 |
+ out.ListMeta = newVal.(v1beta3.ListMeta) |
|
| 2141 |
+ } |
|
| 2142 |
+ if in.Items != nil {
|
|
| 2143 |
+ out.Items = make([]sdnapiv1beta3.NetNamespace, len(in.Items)) |
|
| 2144 |
+ for i := range in.Items {
|
|
| 2145 |
+ if err := deepCopy_v1beta3_NetNamespace(in.Items[i], &out.Items[i], c); err != nil {
|
|
| 2146 |
+ return err |
|
| 2147 |
+ } |
|
| 2148 |
+ } |
|
| 2149 |
+ } else {
|
|
| 2150 |
+ out.Items = nil |
|
| 2151 |
+ } |
|
| 2152 |
+ return nil |
|
| 2153 |
+} |
|
| 2154 |
+ |
|
| 2115 | 2155 |
func deepCopy_v1beta3_Parameter(in templateapiv1beta3.Parameter, out *templateapiv1beta3.Parameter, c *conversion.Cloner) error {
|
| 2116 | 2156 |
out.Name = in.Name |
| 2117 | 2157 |
out.Description = in.Description |
| ... | ... |
@@ -2471,6 +2511,8 @@ func init() {
|
| 2471 | 2471 |
deepCopy_v1beta3_ClusterNetworkList, |
| 2472 | 2472 |
deepCopy_v1beta3_HostSubnet, |
| 2473 | 2473 |
deepCopy_v1beta3_HostSubnetList, |
| 2474 |
+ deepCopy_v1beta3_NetNamespace, |
|
| 2475 |
+ deepCopy_v1beta3_NetNamespaceList, |
|
| 2474 | 2476 |
deepCopy_v1beta3_Parameter, |
| 2475 | 2477 |
deepCopy_v1beta3_Template, |
| 2476 | 2478 |
deepCopy_v1beta3_TemplateList, |
| ... | ... |
@@ -61,6 +61,7 @@ func init() {
|
| 61 | 61 |
|
| 62 | 62 |
Validator.Register(&sdnapi.ClusterNetwork{}, sdnvalidation.ValidateClusterNetwork, sdnvalidation.ValidateClusterNetworkUpdate)
|
| 63 | 63 |
Validator.Register(&sdnapi.HostSubnet{}, sdnvalidation.ValidateHostSubnet, sdnvalidation.ValidateHostSubnetUpdate)
|
| 64 |
+ Validator.Register(&sdnapi.NetNamespace{}, sdnvalidation.ValidateNetNamespace, sdnvalidation.ValidateNetNamespaceUpdate)
|
|
| 64 | 65 |
|
| 65 | 66 |
Validator.Register(&templateapi.Template{}, templatevalidation.ValidateTemplate, templatevalidation.ValidateTemplateUpdate)
|
| 66 | 67 |
|
| ... | ... |
@@ -67,7 +67,7 @@ var ( |
| 67 | 67 |
BuildGroupName: {"builds", "buildconfigs", "buildlogs", "buildconfigs/instantiate", "builds/log", "builds/clone", "buildconfigs/webhooks"},
|
| 68 | 68 |
ImageGroupName: {"imagestreams", "imagestreammappings", "imagestreamtags", "imagestreamimages"},
|
| 69 | 69 |
DeploymentGroupName: {"deployments", "deploymentconfigs", "generatedeploymentconfigs", "deploymentconfigrollbacks"},
|
| 70 |
- SDNGroupName: {"clusternetworks", "hostsubnets"},
|
|
| 70 |
+ SDNGroupName: {"clusternetworks", "hostsubnets", "netnamespaces"},
|
|
| 71 | 71 |
TemplateGroupName: {"templates", "templateconfigs", "processedtemplates"},
|
| 72 | 72 |
UserGroupName: {"identities", "users", "useridentitymappings", "groups"},
|
| 73 | 73 |
OAuthGroupName: {"oauthauthorizetokens", "oauthaccesstokens", "oauthclients", "oauthclientauthorizations"},
|
| ... | ... |
@@ -26,6 +26,7 @@ type Interface interface {
|
| 26 | 26 |
DeploymentConfigsNamespacer |
| 27 | 27 |
RoutesNamespacer |
| 28 | 28 |
HostSubnetsInterface |
| 29 |
+ NetNamespacesInterface |
|
| 29 | 30 |
ClusterNetworkingInterface |
| 30 | 31 |
IdentitiesInterface |
| 31 | 32 |
UsersInterface |
| ... | ... |
@@ -100,11 +101,16 @@ func (c *Client) Routes(namespace string) RouteInterface {
|
| 100 | 100 |
return newRoutes(c, namespace) |
| 101 | 101 |
} |
| 102 | 102 |
|
| 103 |
-// HostSubnet provides a REST client for HostSubnet |
|
| 103 |
+// HostSubnets provides a REST client for HostSubnet |
|
| 104 | 104 |
func (c *Client) HostSubnets() HostSubnetInterface {
|
| 105 | 105 |
return newHostSubnet(c) |
| 106 | 106 |
} |
| 107 | 107 |
|
| 108 |
+// NetNamespaces provides a REST client for NetNamespace |
|
| 109 |
+func (c *Client) NetNamespaces() NetNamespaceInterface {
|
|
| 110 |
+ return newNetNamespace(c) |
|
| 111 |
+} |
|
| 112 |
+ |
|
| 108 | 113 |
// ClusterNetwork provides a REST client for ClusterNetworking |
| 109 | 114 |
func (c *Client) ClusterNetwork() ClusterNetworkInterface {
|
| 110 | 115 |
return newClusterNetwork(c) |
| 111 | 116 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,71 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" |
|
| 4 |
+ |
|
| 5 |
+ sdnapi "github.com/openshift/origin/pkg/sdn/api" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// NetNamespaceInterface has methods to work with NetNamespace resources |
|
| 9 |
+type NetNamespacesInterface interface {
|
|
| 10 |
+ NetNamespaces() NetNamespaceInterface |
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+// NetNamespaceInterface exposes methods on NetNamespace resources. |
|
| 14 |
+type NetNamespaceInterface interface {
|
|
| 15 |
+ List() (*sdnapi.NetNamespaceList, error) |
|
| 16 |
+ Get(name string) (*sdnapi.NetNamespace, error) |
|
| 17 |
+ Create(sub *sdnapi.NetNamespace) (*sdnapi.NetNamespace, error) |
|
| 18 |
+ Delete(name string) error |
|
| 19 |
+ Watch(resourceVersion string) (watch.Interface, error) |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// netNamespace implements NetNamespaceInterface interface |
|
| 23 |
+type netNamespace struct {
|
|
| 24 |
+ r *Client |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+// newNetNamespace returns a NetNamespace |
|
| 28 |
+func newNetNamespace(c *Client) *netNamespace {
|
|
| 29 |
+ return &netNamespace{
|
|
| 30 |
+ r: c, |
|
| 31 |
+ } |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+// List returns a list of NetNamespaces that match the label and field selectors. |
|
| 35 |
+func (c *netNamespace) List() (result *sdnapi.NetNamespaceList, err error) {
|
|
| 36 |
+ result = &sdnapi.NetNamespaceList{}
|
|
| 37 |
+ err = c.r.Get(). |
|
| 38 |
+ Resource("netNamespaces").
|
|
| 39 |
+ Do(). |
|
| 40 |
+ Into(result) |
|
| 41 |
+ return |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+// Get returns information about a particular NetNamespace or an error |
|
| 45 |
+func (c *netNamespace) Get(netname string) (result *sdnapi.NetNamespace, err error) {
|
|
| 46 |
+ result = &sdnapi.NetNamespace{}
|
|
| 47 |
+ err = c.r.Get().Resource("netNamespaces").Name(netname).Do().Into(result)
|
|
| 48 |
+ return |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+// Create creates a new NetNamespace. Returns the server's representation of the NetNamespace and error if one occurs. |
|
| 52 |
+func (c *netNamespace) Create(netNamespace *sdnapi.NetNamespace) (result *sdnapi.NetNamespace, err error) {
|
|
| 53 |
+ result = &sdnapi.NetNamespace{}
|
|
| 54 |
+ err = c.r.Post().Resource("netNamespaces").Body(netNamespace).Do().Into(result)
|
|
| 55 |
+ return |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+// Delete takes the name of the NetNamespace, and returns an error if one occurs during deletion of the NetNamespace |
|
| 59 |
+func (c *netNamespace) Delete(name string) error {
|
|
| 60 |
+ return c.r.Delete().Resource("netNamespaces").Name(name).Do().Error()
|
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+// Watch returns a watch.Interface that watches the requested NetNamespaces |
|
| 64 |
+func (c *netNamespace) Watch(resourceVersion string) (watch.Interface, error) {
|
|
| 65 |
+ return c.r.Get(). |
|
| 66 |
+ Prefix("watch").
|
|
| 67 |
+ Resource("netNamespaces").
|
|
| 68 |
+ Param("resourceVersion", resourceVersion).
|
|
| 69 |
+ Watch() |
|
| 70 |
+} |
| ... | ... |
@@ -109,6 +109,11 @@ func (c *Fake) HostSubnets() client.HostSubnetInterface {
|
| 109 | 109 |
return &FakeHostSubnet{Fake: c}
|
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 |
+// NetNamespaces provides a fake REST client for NetNamespaces |
|
| 113 |
+func (c *Fake) NetNamespaces() client.NetNamespaceInterface {
|
|
| 114 |
+ return &FakeNetNamespace{Fake: c}
|
|
| 115 |
+} |
|
| 116 |
+ |
|
| 112 | 117 |
// ClusterNetwork provides a fake REST client for ClusterNetwork |
| 113 | 118 |
func (c *Fake) ClusterNetwork() client.ClusterNetworkInterface {
|
| 114 | 119 |
return &FakeClusterNetwork{Fake: c}
|
| 115 | 120 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 0 |
+package testclient |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" |
|
| 4 |
+ |
|
| 5 |
+ sdnapi "github.com/openshift/origin/pkg/sdn/api" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// FakeNetNamespace implements NetNamespaceInterface. Meant to be embedded into a struct to get a default |
|
| 9 |
+// implementation. This makes faking out just the methods you want to test easier. |
|
| 10 |
+type FakeNetNamespace struct {
|
|
| 11 |
+ Fake *Fake |
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func (c *FakeNetNamespace) List() (*sdnapi.NetNamespaceList, error) {
|
|
| 15 |
+ obj, err := c.Fake.Invokes(FakeAction{Action: "list-netnamespaces"}, &sdnapi.NetNamespaceList{})
|
|
| 16 |
+ return obj.(*sdnapi.NetNamespaceList), err |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+func (c *FakeNetNamespace) Get(name string) (*sdnapi.NetNamespace, error) {
|
|
| 20 |
+ obj, err := c.Fake.Invokes(FakeAction{Action: "get-netnamespaces"}, &sdnapi.NetNamespace{})
|
|
| 21 |
+ return obj.(*sdnapi.NetNamespace), err |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func (c *FakeNetNamespace) Create(sdn *sdnapi.NetNamespace) (*sdnapi.NetNamespace, error) {
|
|
| 25 |
+ obj, err := c.Fake.Invokes(FakeAction{Action: "create-netnamespace"}, &sdnapi.NetNamespace{})
|
|
| 26 |
+ return obj.(*sdnapi.NetNamespace), err |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func (c *FakeNetNamespace) Delete(name string) error {
|
|
| 30 |
+ c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "delete-netnamespace"})
|
|
| 31 |
+ return nil |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+func (c *FakeNetNamespace) Watch(resourceVersion string) (watch.Interface, error) {
|
|
| 35 |
+ c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "watch-netnamespaces"})
|
|
| 36 |
+ return nil, nil |
|
| 37 |
+} |
| ... | ... |
@@ -59,6 +59,7 @@ var MissingDescriberCoverageExceptions = []reflect.Type{
|
| 59 | 59 |
reflect.TypeOf(&oauthapi.OAuthClient{}),
|
| 60 | 60 |
reflect.TypeOf(&sdnapi.ClusterNetwork{}),
|
| 61 | 61 |
reflect.TypeOf(&sdnapi.HostSubnet{}),
|
| 62 |
+ reflect.TypeOf(&sdnapi.NetNamespace{}),
|
|
| 62 | 63 |
} |
| 63 | 64 |
|
| 64 | 65 |
func TestDescriberCoverage(t *testing.T) {
|
| ... | ... |
@@ -56,6 +56,7 @@ var ( |
| 56 | 56 |
IsPersonalSubjectAccessReviewColumns = []string{"NAME"}
|
| 57 | 57 |
|
| 58 | 58 |
hostSubnetColumns = []string{"NAME", "HOST", "HOST IP", "SUBNET"}
|
| 59 |
+ netNamespaceColumns = []string{"NAME", "NETID"}
|
|
| 59 | 60 |
clusterNetworkColumns = []string{"NAME", "NETWORK", "HOST SUBNET LENGTH"}
|
| 60 | 61 |
) |
| 61 | 62 |
|
| ... | ... |
@@ -121,6 +122,8 @@ func NewHumanReadablePrinter(noHeaders, withNamespace, wide bool, columnLabels [ |
| 121 | 121 |
|
| 122 | 122 |
p.Handler(hostSubnetColumns, printHostSubnet) |
| 123 | 123 |
p.Handler(hostSubnetColumns, printHostSubnetList) |
| 124 |
+ p.Handler(netNamespaceColumns, printNetNamespaceList) |
|
| 125 |
+ p.Handler(netNamespaceColumns, printNetNamespace) |
|
| 124 | 126 |
p.Handler(clusterNetworkColumns, printClusterNetwork) |
| 125 | 127 |
p.Handler(clusterNetworkColumns, printClusterNetworkList) |
| 126 | 128 |
|
| ... | ... |
@@ -579,6 +582,20 @@ func printHostSubnetList(list *sdnapi.HostSubnetList, w io.Writer, withNamespace |
| 579 | 579 |
return nil |
| 580 | 580 |
} |
| 581 | 581 |
|
| 582 |
+func printNetNamespace(h *sdnapi.NetNamespace, w io.Writer, withNamespace bool, wide bool, columnLabels []string) error {
|
|
| 583 |
+ _, err := fmt.Fprintf(w, "%s\t%d\n", h.NetName, h.NetID) |
|
| 584 |
+ return err |
|
| 585 |
+} |
|
| 586 |
+ |
|
| 587 |
+func printNetNamespaceList(list *sdnapi.NetNamespaceList, w io.Writer, withNamespace bool, wide bool, columnLabels []string) error {
|
|
| 588 |
+ for _, item := range list.Items {
|
|
| 589 |
+ if err := printNetNamespace(&item, w, withNamespace, wide, columnLabels); err != nil {
|
|
| 590 |
+ return err |
|
| 591 |
+ } |
|
| 592 |
+ } |
|
| 593 |
+ return nil |
|
| 594 |
+} |
|
| 595 |
+ |
|
| 582 | 596 |
func printClusterNetwork(n *sdnapi.ClusterNetwork, w io.Writer, withNamespace, wide bool, columnLabels []string) error {
|
| 583 | 597 |
_, err := fmt.Fprintf(w, "%s\t%s\t%d\n", n.Name, n.Network, n.HostSubnetLength) |
| 584 | 598 |
return err |
| ... | ... |
@@ -456,6 +456,10 @@ func GetBootstrapClusterRoles() []authorizationapi.ClusterRole {
|
| 456 | 456 |
}, |
| 457 | 457 |
{
|
| 458 | 458 |
Verbs: util.NewStringSet("get", "list", "watch"),
|
| 459 |
+ Resources: util.NewStringSet("netnamespaces"),
|
|
| 460 |
+ }, |
|
| 461 |
+ {
|
|
| 462 |
+ Verbs: util.NewStringSet("get", "list", "watch"),
|
|
| 459 | 463 |
Resources: util.NewStringSet("nodes"),
|
| 460 | 464 |
}, |
| 461 | 465 |
{
|
| ... | ... |
@@ -475,6 +479,10 @@ func GetBootstrapClusterRoles() []authorizationapi.ClusterRole {
|
| 475 | 475 |
Resources: util.NewStringSet("hostsubnets"),
|
| 476 | 476 |
}, |
| 477 | 477 |
{
|
| 478 |
+ Verbs: util.NewStringSet("get", "list", "watch", "create", "delete"),
|
|
| 479 |
+ Resources: util.NewStringSet("netnamespaces"),
|
|
| 480 |
+ }, |
|
| 481 |
+ {
|
|
| 478 | 482 |
Verbs: util.NewStringSet("get", "list", "watch"),
|
| 479 | 483 |
Resources: util.NewStringSet("nodes"),
|
| 480 | 484 |
}, |
| ... | ... |
@@ -56,6 +56,7 @@ import ( |
| 56 | 56 |
routeregistry "github.com/openshift/origin/pkg/route/registry/route" |
| 57 | 57 |
clusternetworketcd "github.com/openshift/origin/pkg/sdn/registry/clusternetwork/etcd" |
| 58 | 58 |
hostsubnetetcd "github.com/openshift/origin/pkg/sdn/registry/hostsubnet/etcd" |
| 59 |
+ netnamespaceetcd "github.com/openshift/origin/pkg/sdn/registry/netnamespace/etcd" |
|
| 59 | 60 |
"github.com/openshift/origin/pkg/service" |
| 60 | 61 |
templateregistry "github.com/openshift/origin/pkg/template/registry" |
| 61 | 62 |
templateetcd "github.com/openshift/origin/pkg/template/registry/etcd" |
| ... | ... |
@@ -310,6 +311,7 @@ func (c *MasterConfig) GetRestStorage() map[string]rest.Storage {
|
| 310 | 310 |
|
| 311 | 311 |
routeEtcd := routeetcd.New(c.EtcdHelper) |
| 312 | 312 |
hostSubnetStorage := hostsubnetetcd.NewREST(c.EtcdHelper) |
| 313 |
+ netNamespaceStorage := netnamespaceetcd.NewREST(c.EtcdHelper) |
|
| 313 | 314 |
clusterNetworkStorage := clusternetworketcd.NewREST(c.EtcdHelper) |
| 314 | 315 |
|
| 315 | 316 |
userStorage := useretcd.NewREST(c.EtcdHelper) |
| ... | ... |
@@ -425,6 +427,7 @@ func (c *MasterConfig) GetRestStorage() map[string]rest.Storage {
|
| 425 | 425 |
"projectRequests": projectRequestStorage, |
| 426 | 426 |
|
| 427 | 427 |
"hostSubnets": hostSubnetStorage, |
| 428 |
+ "netNamespaces": netNamespaceStorage, |
|
| 428 | 429 |
"clusterNetworks": clusterNetworkStorage, |
| 429 | 430 |
|
| 430 | 431 |
"users": userStorage, |
| ... | ... |
@@ -39,7 +39,8 @@ import ( |
| 39 | 39 |
configapi "github.com/openshift/origin/pkg/cmd/server/api" |
| 40 | 40 |
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy" |
| 41 | 41 |
serviceaccountcontrollers "github.com/openshift/origin/pkg/serviceaccounts/controllers" |
| 42 |
- "github.com/openshift/origin/plugins/osdn" |
|
| 42 |
+ "github.com/openshift/origin/plugins/osdn/flatsdn" |
|
| 43 |
+ "github.com/openshift/origin/plugins/osdn/multitenant" |
|
| 43 | 44 |
) |
| 44 | 45 |
|
| 45 | 46 |
// RunProjectAuthorizationCache starts the project authorization cache |
| ... | ... |
@@ -306,8 +307,11 @@ func (c *MasterConfig) RunDeploymentImageChangeTriggerController() {
|
| 306 | 306 |
// RunSDNController runs openshift-sdn if the said network plugin is provided |
| 307 | 307 |
func (c *MasterConfig) RunSDNController() {
|
| 308 | 308 |
osclient, kclient := c.SDNControllerClients() |
| 309 |
- if c.Options.NetworkConfig.NetworkPluginName == osdn.NetworkPluginName() {
|
|
| 310 |
- osdn.Master(osclient, kclient, c.Options.NetworkConfig.ClusterNetworkCIDR, c.Options.NetworkConfig.HostSubnetLength) |
|
| 309 |
+ switch c.Options.NetworkConfig.NetworkPluginName {
|
|
| 310 |
+ case flatsdn.NetworkPluginName(): |
|
| 311 |
+ flatsdn.Master(osclient, kclient, c.Options.NetworkConfig.ClusterNetworkCIDR, c.Options.NetworkConfig.HostSubnetLength) |
|
| 312 |
+ case multitenant.NetworkPluginName(): |
|
| 313 |
+ multitenant.Master(osclient, kclient, c.Options.NetworkConfig.ClusterNetworkCIDR, c.Options.NetworkConfig.HostSubnetLength) |
|
| 311 | 314 |
} |
| 312 | 315 |
} |
| 313 | 316 |
|
| ... | ... |
@@ -13,7 +13,8 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" |
| 15 | 15 |
"github.com/openshift/origin/pkg/cmd/server/kubernetes" |
| 16 |
- "github.com/openshift/origin/plugins/osdn" |
|
| 16 |
+ "github.com/openshift/origin/plugins/osdn/flatsdn" |
|
| 17 |
+ "github.com/openshift/origin/plugins/osdn/multitenant" |
|
| 17 | 18 |
|
| 18 | 19 |
"github.com/openshift/origin/pkg/cmd/server/admin" |
| 19 | 20 |
configapi "github.com/openshift/origin/pkg/cmd/server/api" |
| ... | ... |
@@ -242,17 +243,23 @@ func (o NodeOptions) IsRunFromConfig() bool {
|
| 242 | 242 |
} |
| 243 | 243 |
|
| 244 | 244 |
func RunSDNController(config *kubernetes.NodeConfig, nodeConfig configapi.NodeConfig) {
|
| 245 |
- if nodeConfig.NetworkPluginName != osdn.NetworkPluginName() {
|
|
| 246 |
- return |
|
| 247 |
- } |
|
| 248 |
- |
|
| 249 | 245 |
oclient, _, err := configapi.GetOpenShiftClient(nodeConfig.MasterKubeConfig) |
| 250 | 246 |
if err != nil {
|
| 251 | 247 |
glog.Fatal("Failed to get kube client for SDN")
|
| 252 | 248 |
} |
| 253 |
- ch := make(chan struct{})
|
|
| 254 |
- config.KubeletConfig.StartUpdates = ch |
|
| 255 |
- go osdn.Node(oclient, config.Client, nodeConfig.NodeName, "", ch) |
|
| 249 |
+ |
|
| 250 |
+ switch nodeConfig.NetworkPluginName {
|
|
| 251 |
+ case flatsdn.NetworkPluginName(): |
|
| 252 |
+ ch := make(chan struct{})
|
|
| 253 |
+ config.KubeletConfig.StartUpdates = ch |
|
| 254 |
+ go flatsdn.Node(oclient, config.Client, nodeConfig.NodeName, "", ch) |
|
| 255 |
+ case multitenant.NetworkPluginName(): |
|
| 256 |
+ ch := make(chan struct{})
|
|
| 257 |
+ config.KubeletConfig.StartUpdates = ch |
|
| 258 |
+ plugin := multitenant.GetKubeNetworkPlugin() |
|
| 259 |
+ config.KubeletConfig.NetworkPlugins = append(config.KubeletConfig.NetworkPlugins, plugin) |
|
| 260 |
+ go multitenant.Node(oclient, config.Client, nodeConfig.NodeName, "", ch, plugin) |
|
| 261 |
+ } |
|
| 256 | 262 |
} |
| 257 | 263 |
|
| 258 | 264 |
func StartNode(nodeConfig configapi.NodeConfig) error {
|
| ... | ... |
@@ -10,6 +10,8 @@ func init() {
|
| 10 | 10 |
&ClusterNetworkList{},
|
| 11 | 11 |
&HostSubnet{},
|
| 12 | 12 |
&HostSubnetList{},
|
| 13 |
+ &NetNamespace{},
|
|
| 14 |
+ &NetNamespaceList{},
|
|
| 13 | 15 |
) |
| 14 | 16 |
} |
| 15 | 17 |
|
| ... | ... |
@@ -17,3 +19,5 @@ func (*ClusterNetwork) IsAnAPIObject() {}
|
| 17 | 17 |
func (*ClusterNetworkList) IsAnAPIObject() {}
|
| 18 | 18 |
func (*HostSubnet) IsAnAPIObject() {}
|
| 19 | 19 |
func (*HostSubnetList) IsAnAPIObject() {}
|
| 20 |
+func (*NetNamespace) IsAnAPIObject() {}
|
|
| 21 |
+func (*NetNamespaceList) IsAnAPIObject() {}
|
| ... | ... |
@@ -35,3 +35,19 @@ type HostSubnetList struct {
|
| 35 | 35 |
kapi.ListMeta |
| 36 | 36 |
Items []HostSubnet |
| 37 | 37 |
} |
| 38 |
+ |
|
| 39 |
+// NetNamespace holds the network id against its name |
|
| 40 |
+type NetNamespace struct {
|
|
| 41 |
+ kapi.TypeMeta |
|
| 42 |
+ kapi.ObjectMeta |
|
| 43 |
+ |
|
| 44 |
+ NetName string |
|
| 45 |
+ NetID uint |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// NetNamespaceList is a collection of NetNamespaces |
|
| 49 |
+type NetNamespaceList struct {
|
|
| 50 |
+ kapi.TypeMeta |
|
| 51 |
+ kapi.ListMeta |
|
| 52 |
+ Items []NetNamespace |
|
| 53 |
+} |
| ... | ... |
@@ -10,6 +10,8 @@ func init() {
|
| 10 | 10 |
&ClusterNetworkList{},
|
| 11 | 11 |
&HostSubnet{},
|
| 12 | 12 |
&HostSubnetList{},
|
| 13 |
+ &NetNamespace{},
|
|
| 14 |
+ &NetNamespaceList{},
|
|
| 13 | 15 |
) |
| 14 | 16 |
} |
| 15 | 17 |
|
| ... | ... |
@@ -17,3 +19,5 @@ func (*ClusterNetwork) IsAnAPIObject() {}
|
| 17 | 17 |
func (*ClusterNetworkList) IsAnAPIObject() {}
|
| 18 | 18 |
func (*HostSubnet) IsAnAPIObject() {}
|
| 19 | 19 |
func (*HostSubnetList) IsAnAPIObject() {}
|
| 20 |
+func (*NetNamespace) IsAnAPIObject() {}
|
|
| 21 |
+func (*NetNamespaceList) IsAnAPIObject() {}
|
| ... | ... |
@@ -35,3 +35,19 @@ type HostSubnetList struct {
|
| 35 | 35 |
kapi.ListMeta `json:"metadata,omitempty"` |
| 36 | 36 |
Items []HostSubnet `json:"items" description:"list of host subnets"` |
| 37 | 37 |
} |
| 38 |
+ |
|
| 39 |
+// NetNamespace encapsulates the inputs needed to define a unique network namespace on the cluster |
|
| 40 |
+type NetNamespace struct {
|
|
| 41 |
+ kapi.TypeMeta `json:",inline"` |
|
| 42 |
+ kapi.ObjectMeta `json:"metadata,omitempty"` |
|
| 43 |
+ |
|
| 44 |
+ NetName string `json:"netname" description:"Name of the network namespace."` |
|
| 45 |
+ NetID uint `json:"netid" description:"NetID of the network namespace assigned to each overlay network packet."` |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// NetNamespaceList is a collection of NetNamespaces |
|
| 49 |
+type NetNamespaceList struct {
|
|
| 50 |
+ kapi.TypeMeta `json:",inline"` |
|
| 51 |
+ kapi.ListMeta `json:"metadata,omitempty"` |
|
| 52 |
+ Items []NetNamespace `json:"items" description:"list of net namespaces"` |
|
| 53 |
+} |
| ... | ... |
@@ -10,6 +10,8 @@ func init() {
|
| 10 | 10 |
&ClusterNetworkList{},
|
| 11 | 11 |
&HostSubnet{},
|
| 12 | 12 |
&HostSubnetList{},
|
| 13 |
+ &NetNamespace{},
|
|
| 14 |
+ &NetNamespaceList{},
|
|
| 13 | 15 |
) |
| 14 | 16 |
} |
| 15 | 17 |
|
| ... | ... |
@@ -17,3 +19,5 @@ func (*ClusterNetwork) IsAnAPIObject() {}
|
| 17 | 17 |
func (*ClusterNetworkList) IsAnAPIObject() {}
|
| 18 | 18 |
func (*HostSubnet) IsAnAPIObject() {}
|
| 19 | 19 |
func (*HostSubnetList) IsAnAPIObject() {}
|
| 20 |
+func (*NetNamespace) IsAnAPIObject() {}
|
|
| 21 |
+func (*NetNamespaceList) IsAnAPIObject() {}
|
| ... | ... |
@@ -35,3 +35,19 @@ type HostSubnetList struct {
|
| 35 | 35 |
kapi.ListMeta `json:"metadata,omitempty"` |
| 36 | 36 |
Items []HostSubnet `json:"items"` |
| 37 | 37 |
} |
| 38 |
+ |
|
| 39 |
+// NetNamespace encapsulates the inputs needed to define a unique network namespace on the cluster |
|
| 40 |
+type NetNamespace struct {
|
|
| 41 |
+ kapi.TypeMeta `json:",inline"` |
|
| 42 |
+ kapi.ObjectMeta `json:"metadata,omitempty"` |
|
| 43 |
+ |
|
| 44 |
+ NetName string `json:"netname" description:"Name of the network namespace."` |
|
| 45 |
+ NetID uint `json:"netid" description:"NetID of the network namespace assigned to each overlay network packet."` |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// NetNamespaceList is a collection of NetNamespaces |
|
| 49 |
+type NetNamespaceList struct {
|
|
| 50 |
+ kapi.TypeMeta `json:",inline"` |
|
| 51 |
+ kapi.ListMeta `json:"metadata,omitempty"` |
|
| 52 |
+ Items []NetNamespace `json:"items" description:"list of net namespaces"` |
|
| 53 |
+} |
| ... | ... |
@@ -65,3 +65,25 @@ func ValidateHostSubnetUpdate(obj *sdnapi.HostSubnet, old *sdnapi.HostSubnet) fi |
| 65 | 65 |
|
| 66 | 66 |
return allErrs |
| 67 | 67 |
} |
| 68 |
+ |
|
| 69 |
+// ValidateNetNamespace tests fields for a greater-than-zero NetID |
|
| 70 |
+func ValidateNetNamespace(netnamespace *sdnapi.NetNamespace) fielderrors.ValidationErrorList {
|
|
| 71 |
+ allErrs := fielderrors.ValidationErrorList{}
|
|
| 72 |
+ allErrs = append(allErrs, validation.ValidateObjectMeta(&netnamespace.ObjectMeta, false, oapi.MinimalNameRequirements).Prefix("metadata")...)
|
|
| 73 |
+ |
|
| 74 |
+ if netnamespace.NetID < 0 {
|
|
| 75 |
+ allErrs = append(allErrs, fielderrors.NewFieldInvalid("netID", netnamespace.NetID, "invalid Net ID: cannot be negative"))
|
|
| 76 |
+ } |
|
| 77 |
+ return allErrs |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+func ValidateNetNamespaceUpdate(obj *sdnapi.NetNamespace, old *sdnapi.NetNamespace) fielderrors.ValidationErrorList {
|
|
| 81 |
+ allErrs := fielderrors.ValidationErrorList{}
|
|
| 82 |
+ allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &old.ObjectMeta).Prefix("metadata")...)
|
|
| 83 |
+ |
|
| 84 |
+ if obj.NetID != old.NetID {
|
|
| 85 |
+ allErrs = append(allErrs, fielderrors.NewFieldInvalid("netid", obj.NetID, "cannot change the NetID midflight."))
|
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ return allErrs |
|
| 89 |
+} |
| 68 | 90 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,49 @@ |
| 0 |
+package etcd |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
|
| 4 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/fields" |
|
| 5 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" |
|
| 6 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" |
|
| 7 |
+ etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd" |
|
| 8 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" |
|
| 9 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/tools" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/openshift/origin/pkg/sdn/api" |
|
| 12 |
+ "github.com/openshift/origin/pkg/sdn/registry/netnamespace" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+// rest implements a RESTStorage for sdn against etcd |
|
| 16 |
+type REST struct {
|
|
| 17 |
+ etcdgeneric.Etcd |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+const etcdPrefix = "/registry/sdnnetnamespaces" |
|
| 21 |
+ |
|
| 22 |
+// NewREST returns a RESTStorage object that will work against netnamespaces |
|
| 23 |
+func NewREST(h tools.EtcdHelper) *REST {
|
|
| 24 |
+ store := &etcdgeneric.Etcd{
|
|
| 25 |
+ NewFunc: func() runtime.Object { return &api.NetNamespace{} },
|
|
| 26 |
+ NewListFunc: func() runtime.Object { return &api.NetNamespaceList{} },
|
|
| 27 |
+ KeyRootFunc: func(ctx kapi.Context) string {
|
|
| 28 |
+ return etcdPrefix |
|
| 29 |
+ }, |
|
| 30 |
+ KeyFunc: func(ctx kapi.Context, name string) (string, error) {
|
|
| 31 |
+ return (etcdPrefix + "/" + name), nil |
|
| 32 |
+ }, |
|
| 33 |
+ ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
|
| 34 |
+ return obj.(*api.NetNamespace).NetName, nil |
|
| 35 |
+ }, |
|
| 36 |
+ PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
|
| 37 |
+ return netnamespace.MatchNetNamespace(label, field) |
|
| 38 |
+ }, |
|
| 39 |
+ EndpointName: "netnamespace", |
|
| 40 |
+ |
|
| 41 |
+ Helper: h, |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ store.CreateStrategy = netnamespace.Strategy |
|
| 45 |
+ store.UpdateStrategy = netnamespace.Strategy |
|
| 46 |
+ |
|
| 47 |
+ return &REST{*store}
|
|
| 48 |
+} |
| 0 | 49 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,77 @@ |
| 0 |
+package netnamespace |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
|
| 4 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" |
|
| 5 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/fields" |
|
| 6 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" |
|
| 7 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/origin/pkg/sdn/api" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// Registry is an interface implemented by things that know how to store sdn objects. |
|
| 13 |
+type Registry interface {
|
|
| 14 |
+ // ListNetNamespaces obtains a list of NetNamespaces |
|
| 15 |
+ ListNetNamespaces(ctx kapi.Context) (*api.NetNamespaceList, error) |
|
| 16 |
+ // GetNetNamespace returns a specific NetNamespace |
|
| 17 |
+ GetNetNamespace(ctx kapi.Context, name string) (*api.NetNamespace, error) |
|
| 18 |
+ // CreateNetNamespace creates a NetNamespace |
|
| 19 |
+ CreateNetNamespace(ctx kapi.Context, nn *api.NetNamespace) (*api.NetNamespace, error) |
|
| 20 |
+ // DeleteNetNamespace deletes a netnamespace |
|
| 21 |
+ DeleteNetNamespace(ctx kapi.Context, name string) error |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Storage is an interface for a standard REST Storage backend |
|
| 25 |
+// TODO: move me somewhere common |
|
| 26 |
+type Storage interface {
|
|
| 27 |
+ rest.Lister |
|
| 28 |
+ rest.Getter |
|
| 29 |
+ |
|
| 30 |
+ Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) |
|
| 31 |
+ Update(ctx kapi.Context, obj runtime.Object) (runtime.Object, bool, error) |
|
| 32 |
+ Delete(ctx kapi.Context, name string, opts *kapi.DeleteOptions) (runtime.Object, error) |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+// storage puts strong typing around storage calls |
|
| 36 |
+type storage struct {
|
|
| 37 |
+ Storage |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// NewRegistry returns a new Registry interface for the given Storage. Any mismatched |
|
| 41 |
+// types will panic. |
|
| 42 |
+func NewRegistry(s Storage) Registry {
|
|
| 43 |
+ return &storage{s}
|
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (s *storage) ListNetNamespaces(ctx kapi.Context) (*api.NetNamespaceList, error) {
|
|
| 47 |
+ obj, err := s.List(ctx, labels.Everything(), fields.Everything()) |
|
| 48 |
+ if err != nil {
|
|
| 49 |
+ return nil, err |
|
| 50 |
+ } |
|
| 51 |
+ return obj.(*api.NetNamespaceList), nil |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func (s *storage) GetNetNamespace(ctx kapi.Context, name string) (*api.NetNamespace, error) {
|
|
| 55 |
+ obj, err := s.Get(ctx, name) |
|
| 56 |
+ if err != nil {
|
|
| 57 |
+ return nil, err |
|
| 58 |
+ } |
|
| 59 |
+ return obj.(*api.NetNamespace), nil |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func (s *storage) CreateNetNamespace(ctx kapi.Context, nn *api.NetNamespace) (*api.NetNamespace, error) {
|
|
| 63 |
+ obj, err := s.Create(ctx, nn) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return nil, err |
|
| 66 |
+ } |
|
| 67 |
+ return obj.(*api.NetNamespace), nil |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+func (s *storage) DeleteNetNamespace(ctx kapi.Context, name string) error {
|
|
| 71 |
+ _, err := s.Delete(ctx, name, nil) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return err |
|
| 74 |
+ } |
|
| 75 |
+ return nil |
|
| 76 |
+} |
| 0 | 77 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,68 @@ |
| 0 |
+package netnamespace |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ |
|
| 5 |
+ kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
|
| 6 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/fields" |
|
| 7 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" |
|
| 8 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic" |
|
| 9 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" |
|
| 10 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors" |
|
| 11 |
+ |
|
| 12 |
+ "github.com/openshift/origin/pkg/sdn/api" |
|
| 13 |
+ "github.com/openshift/origin/pkg/sdn/api/validation" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+// sdnStrategy implements behavior for NetNamespaces |
|
| 17 |
+type sdnStrategy struct {
|
|
| 18 |
+ runtime.ObjectTyper |
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+// Strategy is the default logic that applies when creating and updating NetNamespace |
|
| 22 |
+// objects via the REST API. |
|
| 23 |
+var Strategy = sdnStrategy{kapi.Scheme}
|
|
| 24 |
+ |
|
| 25 |
+func (sdnStrategy) PrepareForUpdate(obj, old runtime.Object) {}
|
|
| 26 |
+ |
|
| 27 |
+// NamespaceScoped is false for sdns |
|
| 28 |
+func (sdnStrategy) NamespaceScoped() bool {
|
|
| 29 |
+ return false |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func (sdnStrategy) GenerateName(base string) string {
|
|
| 33 |
+ return base |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+func (sdnStrategy) PrepareForCreate(obj runtime.Object) {
|
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// Validate validates a new NetNamespace |
|
| 40 |
+func (sdnStrategy) Validate(ctx kapi.Context, obj runtime.Object) fielderrors.ValidationErrorList {
|
|
| 41 |
+ return validation.ValidateNetNamespace(obj.(*api.NetNamespace)) |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+// AllowCreateOnUpdate is false for NetNamespace |
|
| 45 |
+func (sdnStrategy) AllowCreateOnUpdate() bool {
|
|
| 46 |
+ return false |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+func (sdnStrategy) AllowUnconditionalUpdate() bool {
|
|
| 50 |
+ return false |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+// ValidateUpdate is the default update validation for a NetNamespace |
|
| 54 |
+func (sdnStrategy) ValidateUpdate(ctx kapi.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
|
|
| 55 |
+ return validation.ValidateNetNamespaceUpdate(obj.(*api.NetNamespace), old.(*api.NetNamespace)) |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+// MatchNetNamespace returns a generic matcher for a given label and field selector. |
|
| 59 |
+func MatchNetNamespace(label labels.Selector, field fields.Selector) generic.Matcher {
|
|
| 60 |
+ return generic.MatcherFunc(func(obj runtime.Object) (bool, error) {
|
|
| 61 |
+ _, ok := obj.(*api.NetNamespace) |
|
| 62 |
+ if !ok {
|
|
| 63 |
+ return false, fmt.Errorf("not a NetNamespace")
|
|
| 64 |
+ } |
|
| 65 |
+ return true, nil |
|
| 66 |
+ }) |
|
| 67 |
+} |
| 0 | 68 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,49 @@ |
| 0 |
+package flatsdn |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/golang/glog" |
|
| 4 |
+ "strings" |
|
| 5 |
+ |
|
| 6 |
+ kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" |
|
| 7 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/openshift-sdn/ovssubnet" |
|
| 10 |
+ osclient "github.com/openshift/origin/pkg/client" |
|
| 11 |
+ "github.com/openshift/origin/plugins/osdn" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func NetworkPluginName() string {
|
|
| 15 |
+ return "redhat/openshift-ovs-subnet" |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+func Master(osClient *osclient.Client, kClient *kclient.Client, clusterNetwork string, clusterNetworkLength uint) {
|
|
| 19 |
+ osdnInterface := osdn.NewOsdnRegistryInterface(osClient, kClient) |
|
| 20 |
+ |
|
| 21 |
+ // get hostname from the gateway |
|
| 22 |
+ output, err := exec.New().Command("hostname", "-f").CombinedOutput()
|
|
| 23 |
+ if err != nil {
|
|
| 24 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 25 |
+ } |
|
| 26 |
+ host := strings.TrimSpace(string(output)) |
|
| 27 |
+ |
|
| 28 |
+ kc, err := ovssubnet.NewKubeController(&osdnInterface, host, "", nil) |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 31 |
+ } |
|
| 32 |
+ err = kc.StartMaster(false, clusterNetwork, clusterNetworkLength) |
|
| 33 |
+ if err != nil {
|
|
| 34 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 35 |
+ } |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+func Node(osClient *osclient.Client, kClient *kclient.Client, hostname string, publicIP string, ready chan struct{}) {
|
|
| 39 |
+ osdnInterface := osdn.NewOsdnRegistryInterface(osClient, kClient) |
|
| 40 |
+ kc, err := ovssubnet.NewKubeController(&osdnInterface, hostname, publicIP, ready) |
|
| 41 |
+ if err != nil {
|
|
| 42 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 43 |
+ } |
|
| 44 |
+ err = kc.StartNode(false, false) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ glog.Fatalf("SDN Node failed: %v", err)
|
|
| 47 |
+ } |
|
| 48 |
+} |
| 0 | 49 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,55 @@ |
| 0 |
+package multitenant |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/golang/glog" |
|
| 4 |
+ "strings" |
|
| 5 |
+ |
|
| 6 |
+ kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" |
|
| 7 |
+ knetwork "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network" |
|
| 8 |
+ "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/openshift/openshift-sdn/ovssubnet" |
|
| 11 |
+ osclient "github.com/openshift/origin/pkg/client" |
|
| 12 |
+ "github.com/openshift/origin/plugins/osdn" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+func NetworkPluginName() string {
|
|
| 16 |
+ return "redhat/openshift-ovs-multitenant" |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+func Master(osClient *osclient.Client, kClient *kclient.Client, clusterNetwork string, clusterNetworkLength uint) {
|
|
| 20 |
+ osdnInterface := osdn.NewOsdnRegistryInterface(osClient, kClient) |
|
| 21 |
+ |
|
| 22 |
+ // get hostname from the gateway |
|
| 23 |
+ output, err := exec.New().Command("hostname", "-f").CombinedOutput()
|
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 26 |
+ } |
|
| 27 |
+ host := strings.TrimSpace(string(output)) |
|
| 28 |
+ |
|
| 29 |
+ kc, err := ovssubnet.NewMultitenantController(&osdnInterface, host, "", nil) |
|
| 30 |
+ if err != nil {
|
|
| 31 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 32 |
+ } |
|
| 33 |
+ err = kc.StartMaster(false, clusterNetwork, clusterNetworkLength) |
|
| 34 |
+ if err != nil {
|
|
| 35 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 36 |
+ } |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func Node(osClient *osclient.Client, kClient *kclient.Client, hostname string, publicIP string, ready chan struct{}, plugin knetwork.NetworkPlugin) {
|
|
| 40 |
+ mp, ok := plugin.(*MultitenantPlugin) |
|
| 41 |
+ if !ok {
|
|
| 42 |
+ glog.Fatalf("Failed to type cast provided plugin to a multitenant type plugin")
|
|
| 43 |
+ } |
|
| 44 |
+ osdnInterface := osdn.NewOsdnRegistryInterface(osClient, kClient) |
|
| 45 |
+ kc, err := ovssubnet.NewMultitenantController(&osdnInterface, hostname, publicIP, ready) |
|
| 46 |
+ if err != nil {
|
|
| 47 |
+ glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 48 |
+ } |
|
| 49 |
+ mp.OvsController = kc |
|
| 50 |
+ err = kc.StartNode(false, false) |
|
| 51 |
+ if err != nil {
|
|
| 52 |
+ glog.Fatalf("SDN Node failed: %v", err)
|
|
| 53 |
+ } |
|
| 54 |
+} |
| 0 | 55 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,66 @@ |
| 0 |
+package multitenant |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/golang/glog" |
|
| 4 |
+ "strconv" |
|
| 5 |
+ |
|
| 6 |
+ knetwork "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network" |
|
| 7 |
+ kubeletTypes "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/types" |
|
| 8 |
+ utilexec "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" |
|
| 9 |
+ "github.com/openshift/openshift-sdn/ovssubnet" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ initCmd = "init" |
|
| 14 |
+ setUpCmd = "setup" |
|
| 15 |
+ tearDownCmd = "teardown" |
|
| 16 |
+) |
|
| 17 |
+ |
|
| 18 |
+type MultitenantPlugin struct {
|
|
| 19 |
+ host knetwork.Host |
|
| 20 |
+ OvsController *ovssubnet.OvsController |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func GetKubeNetworkPlugin() knetwork.NetworkPlugin {
|
|
| 24 |
+ return &MultitenantPlugin{}
|
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+func (plugin *MultitenantPlugin) getExecutable() string {
|
|
| 28 |
+ return "openshift-ovs-multitenant" |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+func (plugin *MultitenantPlugin) getVnid(namespace string) (uint, error) {
|
|
| 32 |
+ // get vnid for the namespace |
|
| 33 |
+ vnid, ok := plugin.OvsController.VnidMap[namespace] |
|
| 34 |
+ if !ok {
|
|
| 35 |
+ // vnid does not exist for this pod, set it to zero (or error?) |
|
| 36 |
+ vnid = 0 |
|
| 37 |
+ } |
|
| 38 |
+ return vnid, nil |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (plugin *MultitenantPlugin) Init(host knetwork.Host) error {
|
|
| 42 |
+ plugin.host = host |
|
| 43 |
+ return nil |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (plugin *MultitenantPlugin) Name() string {
|
|
| 47 |
+ return NetworkPluginName() |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+func (plugin *MultitenantPlugin) SetUpPod(namespace string, name string, id kubeletTypes.DockerID) error {
|
|
| 51 |
+ vnid, err := plugin.getVnid(namespace) |
|
| 52 |
+ if err != nil {
|
|
| 53 |
+ return err |
|
| 54 |
+ } |
|
| 55 |
+ out, err := utilexec.New().Command(plugin.getExecutable(), setUpCmd, namespace, name, string(id), strconv.FormatUint(uint64(vnid), 10)).CombinedOutput() |
|
| 56 |
+ glog.V(5).Infof("SetUpPod 'multitenant' network plugin output: %s, %v", string(out), err)
|
|
| 57 |
+ return err |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func (plugin *MultitenantPlugin) TearDownPod(namespace string, name string, id kubeletTypes.DockerID) error {
|
|
| 61 |
+ vnid, err := plugin.getVnid(namespace) |
|
| 62 |
+ out, err := utilexec.New().Command(plugin.getExecutable(), tearDownCmd, namespace, name, string(id), strconv.FormatUint(uint64(vnid), 10)).CombinedOutput() |
|
| 63 |
+ glog.V(5).Infof("TearDownPod 'multitenant' network plugin output: %s, %v", string(out), err)
|
|
| 64 |
+ return err |
|
| 65 |
+} |
| ... | ... |
@@ -2,8 +2,6 @@ package osdn |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
- "github.com/golang/glog" |
|
| 6 |
- "strings" |
|
| 7 | 5 |
"time" |
| 8 | 6 |
|
| 9 | 7 |
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
| ... | ... |
@@ -12,11 +10,9 @@ import ( |
| 12 | 12 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" |
| 13 | 13 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" |
| 14 | 14 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" |
| 15 |
- "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec" |
|
| 16 | 15 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" |
| 17 | 16 |
|
| 18 |
- "github.com/openshift/openshift-sdn/ovssubnet" |
|
| 19 |
- osdnapi "github.com/openshift/openshift-sdn/pkg/api" |
|
| 17 |
+ osdnapi "github.com/openshift/openshift-sdn/ovssubnet/api" |
|
| 20 | 18 |
|
| 21 | 19 |
osclient "github.com/openshift/origin/pkg/client" |
| 22 | 20 |
oscache "github.com/openshift/origin/pkg/client/cache" |
| ... | ... |
@@ -28,40 +24,7 @@ type OsdnRegistryInterface struct {
|
| 28 | 28 |
kClient kclient.Interface |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
-func NetworkPluginName() string {
|
|
| 32 |
- return "redhat/openshift-ovs-subnet" |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-func Master(osClient *osclient.Client, kClient *kclient.Client, clusterNetwork string, clusterNetworkLength uint) {
|
|
| 36 |
- osdnInterface := newOsdnRegistryInterface(osClient, kClient) |
|
| 37 |
- |
|
| 38 |
- // get hostname from the gateway |
|
| 39 |
- output, err := exec.New().Command("hostname", "-f").CombinedOutput()
|
|
| 40 |
- if err != nil {
|
|
| 41 |
- glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 42 |
- } |
|
| 43 |
- host := strings.TrimSpace(string(output)) |
|
| 44 |
- |
|
| 45 |
- kc, err := ovssubnet.NewKubeController(&osdnInterface, host, "", nil) |
|
| 46 |
- if err != nil {
|
|
| 47 |
- glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 48 |
- } |
|
| 49 |
- err = kc.StartMaster(false, clusterNetwork, clusterNetworkLength) |
|
| 50 |
- if err != nil {
|
|
| 51 |
- glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 52 |
- } |
|
| 53 |
-} |
|
| 54 |
- |
|
| 55 |
-func Node(osClient *osclient.Client, kClient *kclient.Client, hostname string, publicIP string, ready chan struct{}) {
|
|
| 56 |
- osdnInterface := newOsdnRegistryInterface(osClient, kClient) |
|
| 57 |
- kc, err := ovssubnet.NewKubeController(&osdnInterface, hostname, publicIP, ready) |
|
| 58 |
- if err != nil {
|
|
| 59 |
- glog.Fatalf("SDN initialization failed: %v", err)
|
|
| 60 |
- } |
|
| 61 |
- kc.StartNode(false, false) |
|
| 62 |
-} |
|
| 63 |
- |
|
| 64 |
-func newOsdnRegistryInterface(osClient *osclient.Client, kClient *kclient.Client) OsdnRegistryInterface {
|
|
| 31 |
+func NewOsdnRegistryInterface(osClient *osclient.Client, kClient *kclient.Client) OsdnRegistryInterface {
|
|
| 65 | 32 |
return OsdnRegistryInterface{osClient, kClient}
|
| 66 | 33 |
} |
| 67 | 34 |
|
| ... | ... |
@@ -228,3 +191,109 @@ func (oi *OsdnRegistryInterface) CheckEtcdIsAlive(seconds uint64) bool {
|
| 228 | 228 |
// always assumed to be true as we run through the apiserver |
| 229 | 229 |
return true |
| 230 | 230 |
} |
| 231 |
+ |
|
| 232 |
+func (oi *OsdnRegistryInterface) WatchNamespaces(receiver chan *osdnapi.NamespaceEvent, stop chan bool) error {
|
|
| 233 |
+ nsEventQueue := oscache.NewEventQueue(cache.MetaNamespaceKeyFunc) |
|
| 234 |
+ listWatch := &cache.ListWatch{
|
|
| 235 |
+ ListFunc: func() (runtime.Object, error) {
|
|
| 236 |
+ return oi.kClient.Namespaces().List(labels.Everything(), fields.Everything()) |
|
| 237 |
+ }, |
|
| 238 |
+ WatchFunc: func(resourceVersion string) (watch.Interface, error) {
|
|
| 239 |
+ return oi.kClient.Namespaces().Watch(labels.Everything(), fields.Everything(), resourceVersion) |
|
| 240 |
+ }, |
|
| 241 |
+ } |
|
| 242 |
+ cache.NewReflector(listWatch, &kapi.Namespace{}, nsEventQueue, 4*time.Minute).Run()
|
|
| 243 |
+ |
|
| 244 |
+ for {
|
|
| 245 |
+ eventType, obj, err := nsEventQueue.Pop() |
|
| 246 |
+ if err != nil {
|
|
| 247 |
+ return err |
|
| 248 |
+ } |
|
| 249 |
+ switch eventType {
|
|
| 250 |
+ case watch.Added: |
|
| 251 |
+ // we should ignore the modified event because status updates cause unnecessary noise |
|
| 252 |
+ // the only time we would care about modified would be if the minion changes its IP address |
|
| 253 |
+ // and hence all nodes need to update their vtep entries for the respective subnet |
|
| 254 |
+ // create minionEvent |
|
| 255 |
+ ns := obj.(*kapi.Namespace) |
|
| 256 |
+ receiver <- &osdnapi.NamespaceEvent{Type: osdnapi.Added, Name: ns.ObjectMeta.Name}
|
|
| 257 |
+ case watch.Deleted: |
|
| 258 |
+ // TODO: There is a chance that a Delete event will not get triggered. |
|
| 259 |
+ // Need to use a periodic sync loop that lists and compares. |
|
| 260 |
+ ns := obj.(*kapi.Namespace) |
|
| 261 |
+ receiver <- &osdnapi.NamespaceEvent{Type: osdnapi.Deleted, Name: ns.ObjectMeta.Name}
|
|
| 262 |
+ } |
|
| 263 |
+ } |
|
| 264 |
+ return nil |
|
| 265 |
+} |
|
| 266 |
+ |
|
| 267 |
+func (oi *OsdnRegistryInterface) WatchNetNamespaces(receiver chan *osdnapi.NetNamespaceEvent, stop chan bool) error {
|
|
| 268 |
+ netNsEventQueue := oscache.NewEventQueue(cache.MetaNamespaceKeyFunc) |
|
| 269 |
+ listWatch := &cache.ListWatch{
|
|
| 270 |
+ ListFunc: func() (runtime.Object, error) {
|
|
| 271 |
+ return oi.oClient.NetNamespaces().List() |
|
| 272 |
+ }, |
|
| 273 |
+ WatchFunc: func(resourceVersion string) (watch.Interface, error) {
|
|
| 274 |
+ return oi.oClient.NetNamespaces().Watch(resourceVersion) |
|
| 275 |
+ }, |
|
| 276 |
+ } |
|
| 277 |
+ cache.NewReflector(listWatch, &api.NetNamespace{}, netNsEventQueue, 4*time.Minute).Run()
|
|
| 278 |
+ |
|
| 279 |
+ for {
|
|
| 280 |
+ eventType, obj, err := netNsEventQueue.Pop() |
|
| 281 |
+ if err != nil {
|
|
| 282 |
+ return err |
|
| 283 |
+ } |
|
| 284 |
+ switch eventType {
|
|
| 285 |
+ case watch.Added: |
|
| 286 |
+ // we should ignore the modified event because status updates cause unnecessary noise |
|
| 287 |
+ // the only time we would care about modified would be if the minion changes its IP address |
|
| 288 |
+ // and hence all nodes need to update their vtep entries for the respective subnet |
|
| 289 |
+ // create minionEvent |
|
| 290 |
+ netns := obj.(*api.NetNamespace) |
|
| 291 |
+ receiver <- &osdnapi.NetNamespaceEvent{Type: osdnapi.Added, Name: netns.NetName, NetID: netns.NetID}
|
|
| 292 |
+ case watch.Deleted: |
|
| 293 |
+ // TODO: There is a chance that a Delete event will not get triggered. |
|
| 294 |
+ // Need to use a periodic sync loop that lists and compares. |
|
| 295 |
+ netns := obj.(*api.NetNamespace) |
|
| 296 |
+ receiver <- &osdnapi.NetNamespaceEvent{Type: osdnapi.Deleted, Name: netns.NetName}
|
|
| 297 |
+ } |
|
| 298 |
+ } |
|
| 299 |
+ return nil |
|
| 300 |
+} |
|
| 301 |
+ |
|
| 302 |
+func (oi *OsdnRegistryInterface) GetNetNamespaces() ([]osdnapi.NetNamespace, error) {
|
|
| 303 |
+ netNamespaceList, err := oi.oClient.NetNamespaces().List() |
|
| 304 |
+ if err != nil {
|
|
| 305 |
+ return nil, err |
|
| 306 |
+ } |
|
| 307 |
+ // convert api.NetNamespace to osdnapi.NetNamespace |
|
| 308 |
+ nsList := make([]osdnapi.NetNamespace, 0) |
|
| 309 |
+ for _, netns := range netNamespaceList.Items {
|
|
| 310 |
+ nsList = append(nsList, osdnapi.NetNamespace{Name: netns.Name, NetID: netns.NetID})
|
|
| 311 |
+ } |
|
| 312 |
+ return nsList, nil |
|
| 313 |
+} |
|
| 314 |
+ |
|
| 315 |
+func (oi *OsdnRegistryInterface) GetNetNamespace(name string) (osdnapi.NetNamespace, error) {
|
|
| 316 |
+ netns, err := oi.oClient.NetNamespaces().Get(name) |
|
| 317 |
+ if err != nil {
|
|
| 318 |
+ return osdnapi.NetNamespace{}, err
|
|
| 319 |
+ } |
|
| 320 |
+ return osdnapi.NetNamespace{Name: netns.Name, NetID: netns.NetID}, nil
|
|
| 321 |
+} |
|
| 322 |
+ |
|
| 323 |
+func (oi *OsdnRegistryInterface) WriteNetNamespace(name string, id uint) error {
|
|
| 324 |
+ netns := &api.NetNamespace{
|
|
| 325 |
+ TypeMeta: kapi.TypeMeta{Kind: "NetNamespace"},
|
|
| 326 |
+ ObjectMeta: kapi.ObjectMeta{Name: name},
|
|
| 327 |
+ NetName: name, |
|
| 328 |
+ NetID: id, |
|
| 329 |
+ } |
|
| 330 |
+ _, err := oi.oClient.NetNamespaces().Create(netns) |
|
| 331 |
+ return err |
|
| 332 |
+} |
|
| 333 |
+ |
|
| 334 |
+func (oi *OsdnRegistryInterface) DeleteNetNamespace(name string) error {
|
|
| 335 |
+ return oi.oClient.NetNamespaces().Delete(name) |
|
| 336 |
+} |
| ... | ... |
@@ -614,6 +614,7 @@ _oc_get() |
| 614 | 614 |
must_have_one_noun+=("ispersonalsubjectaccessreview")
|
| 615 | 615 |
must_have_one_noun+=("limitrange")
|
| 616 | 616 |
must_have_one_noun+=("namespace")
|
| 617 |
+ must_have_one_noun+=("netnamespace")
|
|
| 617 | 618 |
must_have_one_noun+=("node")
|
| 618 | 619 |
must_have_one_noun+=("oauthaccesstoken")
|
| 619 | 620 |
must_have_one_noun+=("oauthauthorizetoken")
|
| ... | ... |
@@ -2033,6 +2033,7 @@ _openshift_cli_get() |
| 2033 | 2033 |
must_have_one_noun+=("ispersonalsubjectaccessreview")
|
| 2034 | 2034 |
must_have_one_noun+=("limitrange")
|
| 2035 | 2035 |
must_have_one_noun+=("namespace")
|
| 2036 |
+ must_have_one_noun+=("netnamespace")
|
|
| 2036 | 2037 |
must_have_one_noun+=("node")
|
| 2037 | 2038 |
must_have_one_noun+=("oauthaccesstoken")
|
| 2038 | 2039 |
must_have_one_noun+=("oauthauthorizetoken")
|
| 2039 | 2040 |
deleted file mode 100755 |
| ... | ... |
@@ -1,88 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
-set -ex |
|
| 3 |
-source $(dirname $0)/provision-config.sh |
|
| 4 |
- |
|
| 5 |
-MINION_IP=$4 |
|
| 6 |
-MINION_ID=$5 |
|
| 7 |
-DOCKER_BRIDGE=kbr0 |
|
| 8 |
-OVS_SWITCH=obr0 |
|
| 9 |
-GRE_TUNNEL_BASE=gre |
|
| 10 |
-BRIDGE_BASE=10.244 |
|
| 11 |
-BRIDGE_ADDRESS=${BRIDGE_BASE}.${MINION_ID}.1
|
|
| 12 |
-BRIDGE_NETWORK=${BRIDGE_ADDRESS}/24
|
|
| 13 |
-BRIDGE_NETMASK=255.255.255.0 |
|
| 14 |
-NETWORK_CONF_PATH=/etc/sysconfig/network-scripts/ |
|
| 15 |
-POST_NETWORK_SCRIPT=/vagrant/network_closure.sh |
|
| 16 |
- |
|
| 17 |
-# Add docker bridge ifcfg file |
|
| 18 |
-cat <<EOF > ${NETWORK_CONF_PATH}ifcfg-${DOCKER_BRIDGE}
|
|
| 19 |
-# Generated by yours truly |
|
| 20 |
-DEVICE=${DOCKER_BRIDGE}
|
|
| 21 |
-ONBOOT=yes |
|
| 22 |
-TYPE=Bridge |
|
| 23 |
-BOOTPROTO=static |
|
| 24 |
-IPADDR=${BRIDGE_ADDRESS}
|
|
| 25 |
-NETMASK=${BRIDGE_NETMASK}
|
|
| 26 |
-STP=yes |
|
| 27 |
-EOF |
|
| 28 |
- |
|
| 29 |
-# Add the ovs bridge ifcfg file |
|
| 30 |
-cat <<EOF > ${NETWORK_CONF_PATH}ifcfg-${OVS_SWITCH}
|
|
| 31 |
-DEVICE=${OVS_SWITCH}
|
|
| 32 |
-ONBOOT=yes |
|
| 33 |
-DEVICETYPE=ovs |
|
| 34 |
-TYPE=OVSBridge |
|
| 35 |
-BOOTPROTO=static |
|
| 36 |
-HOTPLUG=no |
|
| 37 |
-BRIDGE=${DOCKER_BRIDGE}
|
|
| 38 |
-EOF |
|
| 39 |
- |
|
| 40 |
-# Loop through all other minions and create persistent gre tunnels |
|
| 41 |
-MINION_IPS=$3 |
|
| 42 |
-MINION_IP_ARRAY=(`echo ${MINION_IPS} | tr "," "\n"`)
|
|
| 43 |
-GRE_NUM=0 |
|
| 44 |
-for remote_ip in "${MINION_IP_ARRAY[@]}"
|
|
| 45 |
-do |
|
| 46 |
- if [ "${remote_ip}" == "${MINION_IP}" ]; then
|
|
| 47 |
- continue |
|
| 48 |
- fi |
|
| 49 |
- ((GRE_NUM++)) || echo |
|
| 50 |
- GRE_TUNNEL=${GRE_TUNNEL_BASE}${GRE_NUM}
|
|
| 51 |
- # ovs-vsctl add-port ${OVS_SWITCH} ${GRE_TUNNEL} -- set interface ${GRE_TUNNEL} type=gre options:remote_ip=${remote_ip}
|
|
| 52 |
- cat <<EOF > ${NETWORK_CONF_PATH}ifcfg-${GRE_TUNNEL}
|
|
| 53 |
-DEVICE=${GRE_TUNNEL}
|
|
| 54 |
-ONBOOT=yes |
|
| 55 |
-DEVICETYPE=ovs |
|
| 56 |
-TYPE=OVSTunnel |
|
| 57 |
-OVS_BRIDGE=${OVS_SWITCH}
|
|
| 58 |
-OVS_TUNNEL_TYPE=gre |
|
| 59 |
-OVS_TUNNEL_OPTIONS="options:remote_ip=${remote_ip}"
|
|
| 60 |
-EOF |
|
| 61 |
-done |
|
| 62 |
- |
|
| 63 |
-# Add ip route rules such that all pod traffic flows through docker bridge and consequently to the gre tunnels |
|
| 64 |
-cat <<EOF > /${NETWORK_CONF_PATH}route-${DOCKER_BRIDGE}
|
|
| 65 |
-${BRIDGE_BASE}.0.0/16 dev ${DOCKER_BRIDGE} scope link src ${BRIDGE_ADDRESS}
|
|
| 66 |
-EOF |
|
| 67 |
- |
|
| 68 |
-systemctl enable openvswitch |
|
| 69 |
-systemctl start openvswitch |
|
| 70 |
- |
|
| 71 |
-# NAT interface fails to revive on network restart, so OR-gate to true |
|
| 72 |
-systemctl restart network.service || true |
|
| 73 |
- |
|
| 74 |
-# Set docker bridge up, and set stp on the OVS bridge |
|
| 75 |
-ip link set dev ${DOCKER_BRIDGE} up
|
|
| 76 |
-ovs-vsctl set Bridge ${OVS_SWITCH} stp_enable=true
|
|
| 77 |
- |
|
| 78 |
-# Modify the docker service file such that it uses the kube docker bridge and not its own |
|
| 79 |
-sed -ie "s/ExecStart=\/usr\/bin\/docker -d/ExecStart=\/usr\/bin\/docker -d -b=${DOCKER_BRIDGE} --iptables=false/g" /usr/lib/systemd/system/docker.service
|
|
| 80 |
-systemctl daemon-reload |
|
| 81 |
-systemctl enable docker.service |
|
| 82 |
-systemctl restart docker.service |
|
| 83 |
- |
|
| 84 |
-# Setup iptables masquerade rules, so the pods can reach the internet |
|
| 85 |
-iptables -t nat -A POSTROUTING -s ${BRIDGE_BASE}.0.0/16 ! -d ${BRIDGE_BASE}.0.0/16 -j MASQUERADE
|
|
| 86 |
- |
|
| 87 |
-# Persist iptables rules |
|
| 88 |
-iptables-save >& /etc/sysconfig/iptables |
| 89 | 1 |
deleted file mode 100755 |
| ... | ... |
@@ -1,21 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
-set -ex |
|
| 3 |
-source $(dirname $0)/provision-config.sh |
|
| 4 |
- |
|
| 5 |
-pushd $HOME |
|
| 6 |
-# build openshift-sdn |
|
| 7 |
-if [ -d openshift-sdn ]; then |
|
| 8 |
- cd openshift-sdn |
|
| 9 |
- git fetch origin |
|
| 10 |
- git reset --hard origin/master |
|
| 11 |
-else |
|
| 12 |
- git clone https://github.com/openshift/openshift-sdn |
|
| 13 |
- cd openshift-sdn |
|
| 14 |
-fi |
|
| 15 |
- |
|
| 16 |
-make clean |
|
| 17 |
-make |
|
| 18 |
-make install |
|
| 19 |
-popd |
|
| 20 |
- |
|
| 21 |
-# no need to start openshift-sdn, as it is integrated with openshift binary |
| ... | ... |
@@ -4,6 +4,10 @@ set -ex |
| 4 | 4 |
source $(dirname $0)/provision-config.sh |
| 5 | 5 |
|
| 6 | 6 |
OPENSHIFT_SDN=$4 |
| 7 |
+if [ "${OPENSHIFT_SDN}" == "redhat/openshift-ovs-multitenant" ] || [ "${OPENSHIFT_SDN}" == "redhat/openshift-ovs-subnet" ] || [ "${OPENSHIFT_SDN}" == "" ]; then
|
|
| 8 |
+ OPENSHIFT_SDN_PLUGIN=${OPENSHIFT_SDN}
|
|
| 9 |
+fi |
|
| 10 |
+OPENSHIFT_SDN_PLUGIN=${OPENSHIFT_SDN_PLUGIN:-redhat/openshift-ovs-subnet}
|
|
| 7 | 11 |
|
| 8 | 12 |
NETWORK_CONF_PATH=/etc/sysconfig/network-scripts/ |
| 9 | 13 |
sed -i 's/^NM_CONTROLLED=no/#NM_CONTROLLED=no/' ${NETWORK_CONF_PATH}ifcfg-eth1
|
| ... | ... |
@@ -63,7 +67,7 @@ pushd /vagrant |
| 63 | 63 |
--node="${minion}" \
|
| 64 | 64 |
--hostnames="${minion},${ip}" \
|
| 65 | 65 |
--master="https://${MASTER_IP}:8443" \
|
| 66 |
- --network-plugin="redhat/openshift-ovs-subnet" \ |
|
| 66 |
+ --network-plugin="${OPENSHIFT_SDN_PLUGIN}" \
|
|
| 67 | 67 |
--node-client-certificate-authority="${CERT_DIR}/ca.crt" \
|
| 68 | 68 |
--certificate-authority="${CERT_DIR}/ca.crt" \
|
| 69 | 69 |
--signer-cert="${CERT_DIR}/ca.crt" \
|
| ... | ... |
@@ -86,7 +90,7 @@ Requires=docker.service network.service |
| 86 | 86 |
After=network.service |
| 87 | 87 |
|
| 88 | 88 |
[Service] |
| 89 |
-ExecStart=/usr/bin/openshift start master --master=https://${MASTER_IP}:8443 --nodes=${node_list} --network-plugin=redhat/openshift-ovs-subnet
|
|
| 89 |
+ExecStart=/usr/bin/openshift start master --master=https://${MASTER_IP}:8443 --nodes=${node_list} --network-plugin=${OPENSHIFT_SDN_PLUGIN}
|
|
| 90 | 90 |
WorkingDirectory=/vagrant/ |
| 91 | 91 |
|
| 92 | 92 |
[Install] |
| ... | ... |
@@ -97,13 +101,8 @@ EOF |
| 97 | 97 |
systemctl daemon-reload |
| 98 | 98 |
systemctl start openshift-master.service |
| 99 | 99 |
|
| 100 |
-# if SDN requires service on master, then set it up |
|
| 101 |
-if [ "${OPENSHIFT_SDN}" != "ovs-gre" ]; then
|
|
| 102 |
- export ETCD_CAFILE=/vagrant/openshift.local.config/master/ca.crt |
|
| 103 |
- export ETCD_CERTFILE=/vagrant/openshift.local.config/master/master.etcd-client.crt |
|
| 104 |
- export ETCD_KEYFILE=/vagrant/openshift.local.config/master/master.etcd-client.key |
|
| 105 |
- $(dirname $0)/provision-master-sdn.sh $@ |
|
| 106 |
-fi |
|
| 100 |
+# setup SDN |
|
| 101 |
+$(dirname $0)/provision-sdn.sh $@ |
|
| 107 | 102 |
|
| 108 | 103 |
# Set up the KUBECONFIG environment variable for use by oc |
| 109 | 104 |
echo 'export KUBECONFIG=/vagrant/openshift.local.config/master/admin.kubeconfig' >> /root/.bash_profile |
| ... | ... |
@@ -48,15 +48,10 @@ popd |
| 48 | 48 |
cp -r /vagrant/openshift.local.config / |
| 49 | 49 |
chown -R vagrant.vagrant /openshift.local.config |
| 50 | 50 |
|
| 51 |
-if [ "${OPENSHIFT_SDN}" != "ovs-gre" ]; then
|
|
| 52 |
- export ETCD_CAFILE=/openshift.local.config/master/ca.crt |
|
| 53 |
- export ETCD_CERTFILE=/openshift.local.config/master/master.etcd-client.crt |
|
| 54 |
- export ETCD_KEYFILE=/openshift.local.config/master/master.etcd-client.key |
|
| 55 |
- $(dirname $0)/provision-node-sdn.sh $@ |
|
| 56 |
-else |
|
| 57 |
- # Setup default networking between the nodes |
|
| 58 |
- $(dirname $0)/provision-gre-network.sh $@ |
|
| 59 |
-fi |
|
| 51 |
+mkdir -p /openshift.local.volumes |
|
| 52 |
+ |
|
| 53 |
+# Setup SDN |
|
| 54 |
+$(dirname $0)/provision-sdn.sh $@ |
|
| 60 | 55 |
|
| 61 | 56 |
# Create systemd service |
| 62 | 57 |
cat <<EOF > /usr/lib/systemd/system/openshift-node.service |
| 63 | 58 |
deleted file mode 100755 |
| ... | ... |
@@ -1,25 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
-set -ex |
|
| 3 |
-source $(dirname $0)/provision-config.sh |
|
| 4 |
-MINION_IP=$4 |
|
| 5 |
- |
|
| 6 |
-pushd $HOME |
|
| 7 |
-# build openshift-sdn |
|
| 8 |
-if [ -d openshift-sdn ]; then |
|
| 9 |
- cd openshift-sdn |
|
| 10 |
- git fetch origin |
|
| 11 |
- git reset --hard origin/master |
|
| 12 |
-else |
|
| 13 |
- git clone https://github.com/openshift/openshift-sdn |
|
| 14 |
- cd openshift-sdn |
|
| 15 |
-fi |
|
| 16 |
- |
|
| 17 |
-make clean |
|
| 18 |
-make |
|
| 19 |
-make install |
|
| 20 |
-popd |
|
| 21 |
- |
|
| 22 |
-systemctl enable openvswitch |
|
| 23 |
-systemctl start openvswitch |
|
| 24 |
- |
|
| 25 |
-# no need to start openshift-sdn, as it is integrated with openshift binary |
| 26 | 1 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+set -ex |
|
| 2 |
+source $(dirname $0)/provision-config.sh |
|
| 3 |
+ |
|
| 4 |
+pushd $HOME |
|
| 5 |
+# build openshift-sdn |
|
| 6 |
+if [ -d openshift-sdn ]; then |
|
| 7 |
+ cd openshift-sdn |
|
| 8 |
+ git fetch origin |
|
| 9 |
+ git reset --hard origin/master |
|
| 10 |
+ git checkout -b multitenant |
|
| 11 |
+else |
|
| 12 |
+ git clone https://github.com/openshift/openshift-sdn -b multitenant |
|
| 13 |
+ cd openshift-sdn |
|
| 14 |
+fi |
|
| 15 |
+ |
|
| 16 |
+make clean |
|
| 17 |
+make |
|
| 18 |
+make install |
|
| 19 |
+popd |
|
| 20 |
+ |
|
| 21 |
+systemctl enable openvswitch |
|
| 22 |
+systemctl start openvswitch |
|
| 23 |
+ |
|
| 24 |
+# no need to start openshift-sdn, as it is integrated with openshift binary |