summaryrefslogtreecommitdiffhomepage
path: root/test/scenario_test
diff options
context:
space:
mode:
Diffstat (limited to 'test/scenario_test')
-rw-r--r--test/scenario_test/docker_control.py236
-rw-r--r--test/scenario_test/pip-requires.txt4
-rw-r--r--test/scenario_test/quagga-rsconfig.go145
-rw-r--r--test/scenario_test/quagga_access.py68
-rw-r--r--test/scenario_test/route_server_test.py401
5 files changed, 854 insertions, 0 deletions
diff --git a/test/scenario_test/docker_control.py b/test/scenario_test/docker_control.py
new file mode 100644
index 00000000..e081df26
--- /dev/null
+++ b/test/scenario_test/docker_control.py
@@ -0,0 +1,236 @@
+from fabric.api import local
+import time
+import os
+
+GOBGP_CONTAINER_NAME = "gobgp"
+GOBGP_ADDRESS = "10.0.255.1/16"
+GOBGP_CONFIG_FILE = "gobgpd.conf"
+BRIDGE_ADDRESS = "10.0.255.2"
+CONFIG_DIR = "/usr/local/gobgp"
+CONFIG_DIRR = "/usr/local/gobgp/"
+STARTUP_FILE_NAME = "gobgp_startup.sh"
+STARTUP_FILE = "/mnt/" + STARTUP_FILE_NAME
+BRIDGE_0 = "br0"
+BRIDGE_1 = "br1"
+BRIDGE_2 = "br2"
+
+def test_user_check():
+ root = False
+ outbuf = local("echo $USER", capture=True)
+ user = outbuf
+ if user == "root":
+ root = True
+
+ return root
+
+
+def docker_related_installation():
+ local("apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9", capture=True)
+ local('sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"', capture=True)
+ local("apt-get update", capture=True)
+ local("apt-get install -y --force-yes lxc-docker-1.3.2", capture=True)
+ local("ln -sf /usr/bin/docker.io /usr/local/bin/docker", capture=True)
+ local("gpasswd -a `whoami` docker", capture=True)
+ local("apt-get install -y --force-yes emacs23-nox", capture=True)
+ local("apt-get install -y --force-yes wireshark", capture=True)
+ local("apt-get install -y --force-yes iputils-arping", capture=True)
+ local("apt-get install -y --force-yes bridge-utils", capture=True)
+ local("apt-get install -y --force-yes tcpdump", capture=True)
+ local("apt-get install -y --force-yes lv", capture=True)
+ local("wget https://raw.github.com/jpetazzo/pipework/master/pipework -O /usr/local/bin/pipework", capture=True)
+ local("chmod 755 /usr/local/bin/pipework", capture=True)
+ local("docker pull osrg/quagga", capture=True)
+ local("docker pull osrg/gobgp", capture=True)
+ local("mkdir /usr/local/gobgp", capture=True)
+ local("docker run --privileged=true -v /usr/local/gobgp:/mnt --name gobgp --rm osrg/gobgp go run /root/gobgp/tools/route-server/quagga-rsconfig.go -c /mnt", capture=True)
+
+
+def docker_pkg_check():
+ docker_exists = False
+ outbuf = local("dpkg -l | grep docker | awk '{print $2}'", capture=True)
+ dpkg_list = outbuf.split('\n')
+ for dpkg in dpkg_list:
+ # print "lxc-docker in ",dpkg
+ if ("lxc-docker" in dpkg):
+ docker_exists = True
+ return docker_exists
+
+
+def docker_container_check():
+ container_exists = False
+ outbuf = local("docker ps", capture=True)
+ docker_ps = outbuf.split('\n')
+ for container in docker_ps:
+ container_name = container.split()[-1]
+ if container_name == GOBGP_CONTAINER_NAME:
+ container_exists = True
+ return container_exists
+
+
+def get_docker_containers():
+ containers = []
+ cmd = "docker ps | awk '{print $NF}' | grep -e '^[q][0-9][0-9]*$'"
+ outbuf = local(cmd, capture=True)
+ docker_ps = outbuf.split('\n')
+ for container in docker_ps:
+ if container != "NAMES":
+ containers.append(container.split()[-1])
+ return containers
+
+
+def docker_run_quagga(quagga_num):
+ quagga_name = "q" + str(quagga_num)
+ cmd = "docker run --privileged=true -v " + CONFIG_DIR + "/" + quagga_name + ":/etc/quagga --name " + quagga_name + " -id osrg/quagga"
+ local(cmd, capture=True)
+ quagga_address = "10.0.0." + str(quagga_num) + "/16"
+ cmd = "pipework " + BRIDGE_0 + " " + quagga_name + " " + quagga_address
+ local(cmd, capture=True)
+
+
+def docker_run_gobgp():
+ cmd = "docker run --privileged=true -v " + CONFIG_DIR + ":/mnt -d --name " + GOBGP_CONTAINER_NAME + " -id osrg/gobgp"
+ local(cmd, capture=True)
+ cmd = "pipework " + BRIDGE_0 + " " + GOBGP_CONTAINER_NAME + " " + GOBGP_ADDRESS
+ local(cmd, capture=True)
+
+
+def make_startup_file():
+ file_buff = '#!/bin/bash' + '\n'
+ file_buff += 'cd /root/gobgp' + '\n'
+ file_buff += 'git pull origin master' + '\n'
+ file_buff += 'go get -v' + '\n'
+ file_buff += 'go build' + '\n'
+ file_buff += './gobgp -f /mnt/gobgpd.conf'
+ cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIRR + STARTUP_FILE_NAME
+ local(cmd, capture=True)
+ cmd = "chmod 755 " + CONFIG_DIRR + STARTUP_FILE_NAME
+ local(cmd, capture=True)
+
+
+def docker_containers_create(quagga_num):
+ bridge_setting_for_docker_connection(BRIDGE_0)
+ pwd = local("pwd", capture=True)
+ cmd = "go run " + pwd + "/quagga-rsconfig.go -n " + str(quagga_num) + " -c /usr/local/gobgp"
+ local(cmd, capture=True)
+ for num in range(1, quagga_num + 1):
+ docker_run_quagga(num)
+ docker_run_gobgp()
+ make_startup_file()
+
+
+def docker_stop_quagga(quagga):
+ cmd = "docker rm -f " + quagga
+ local(cmd, capture=True)
+ cmd = "rm -rf " + CONFIG_DIRR + quagga
+ local(cmd, capture=True)
+
+
+def docker_stop_gobgp():
+ cmd = "docker rm -f " + GOBGP_CONTAINER_NAME
+ local(cmd, capture=True)
+
+
+def docker_containers_destroy():
+ if docker_container_check() is True:
+ containers = get_docker_containers()
+ for container in containers:
+ docker_stop_quagga(container)
+ docker_stop_gobgp()
+ bridge_unsetting_for_docker_connection(BRIDGE_0)
+ cmd = "rm -rf " + CONFIG_DIRR + GOBGP_CONFIG_FILE
+ local(cmd, capture=True)
+ cmd = "rm -rf " + CONFIG_DIRR + STARTUP_FILE_NAME
+ local(cmd, capture=True)
+ else:
+ print "docker containers not exists."
+ os.exit(1)
+
+
+def docker_containers_recreate(quagga_num):
+ docker_containers_destroy()
+ docker_containers_create(quagga_num)
+
+
+def docker_container_append(quagga_num):
+ print "start append docker container."
+ pwd = local("pwd", capture=True)
+ cmd = "go run " + pwd + "/quagga-rsconfig.go -a " + str(quagga_num) + " -c /usr/local/gobgp"
+ local(cmd, capture=True)
+ docker_run_quagga(quagga_num)
+ cmd = "docker exec gobgp /usr/bin/pkill gobgp -SIGHUP"
+ local(cmd, capture=True)
+ print "please wait"
+ sleep_time = 15
+ time.sleep(sleep_time)
+ print "complete append docker container."
+
+
+def docker_container_depend(quagga_num):
+ print "start remove docker container."
+ quagga = "q" + str(quagga_num)
+ docker_stop_quagga(quagga)
+ print "please wait"
+ sleep_time = 15
+ time.sleep(sleep_time)
+ print "complete remove docker container."
+
+
+def bridge_setting_for_docker_connection(bridge):
+ sysfs_name = "/sys/class/net/" + bridge
+ if os.path.exists(sysfs_name):
+ bridge_unsetting_for_docker_connection(bridge)
+ bridge_setting_for_docker_connection(bridge)
+ else:
+ cmd = "brctl addbr " + bridge
+ local(cmd, capture=True)
+ cmd = "ifconfig " + bridge + " " + BRIDGE_ADDRESS
+ local(cmd, capture=True)
+ cmd = "ifconfig " + bridge + " up"
+ local(cmd, capture=True)
+
+
+def bridge_unsetting_for_docker_connection(bridge):
+ sysfs_name = "/sys/class/net/" + bridge
+ if os.path.exists(sysfs_name):
+ cmd = "ifconfig " + bridge + " down"
+ local(cmd, capture=True)
+ cmd = "brctl delbr " + bridge
+ local(cmd, capture=True)
+
+
+def gobgp_start():
+ cmd = "docker exec gobgp " + STARTUP_FILE + " > /dev/null 2>&1 &"
+ # cmd = "docker exec gobgp " + STARTUP_FILE
+ local(cmd, capture=True)
+
+
+def init_test_env_executor(quagga_num):
+ print "start initialization of test environment."
+ if test_user_check() is False:
+ print "you are not root"
+ print "please run the test after you login as root"
+ return
+
+ if docker_pkg_check():
+ if docker_container_check():
+ print "gobgp test environment already exists."
+ print "so that remake gobgp test environment."
+ docker_containers_recreate(quagga_num)
+ else:
+ print "make gobgp test environment."
+ docker_containers_create(quagga_num)
+ gobgp_start()
+
+ print "please wait"
+ sleep_time = 15
+ time.sleep(sleep_time)
+ print "complete initialization of test environment."
+
+
+def docker_related_install_executor():
+ print "start install of docker related"
+ if test_user_check() is False:
+ print "you are not root"
+ print "please run the test after you login as root"
+ return
+ docker_related_installation() \ No newline at end of file
diff --git a/test/scenario_test/pip-requires.txt b/test/scenario_test/pip-requires.txt
new file mode 100644
index 00000000..d84d69b4
--- /dev/null
+++ b/test/scenario_test/pip-requires.txt
@@ -0,0 +1,4 @@
+nose
+toml
+ciscoconfparse
+fabric
diff --git a/test/scenario_test/quagga-rsconfig.go b/test/scenario_test/quagga-rsconfig.go
new file mode 100644
index 00000000..bede8326
--- /dev/null
+++ b/test/scenario_test/quagga-rsconfig.go
@@ -0,0 +1,145 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "github.com/BurntSushi/toml"
+ "github.com/jessevdk/go-flags"
+ "github.com/osrg/gobgp/config"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+)
+
+type QuaggaConfig struct {
+ id int
+ config *config.NeighborType
+ gobgpConfig *config.GlobalType
+ serverIP net.IP
+}
+
+func NewQuaggaConfig(id int, gConfig *config.GlobalType, myConfig *config.NeighborType, server net.IP) *QuaggaConfig {
+ return &QuaggaConfig{
+ id: id,
+ config: myConfig,
+ gobgpConfig: gConfig,
+ serverIP: server,
+ }
+}
+
+func (qt *QuaggaConfig) Config() *bytes.Buffer {
+ buf := bytes.NewBuffer(nil)
+
+ buf.WriteString("hostname bgpd\n")
+ buf.WriteString("password zebra\n")
+ buf.WriteString(fmt.Sprintf("router bgp %d\n", qt.config.PeerAs))
+ buf.WriteString(fmt.Sprintf("bgp router-id 192.168.0.%d\n", qt.id))
+ buf.WriteString(fmt.Sprintf("network 192.168.%d.0/24\n", qt.id))
+ buf.WriteString(fmt.Sprintf("neighbor %s remote-as %d\n", qt.serverIP, qt.gobgpConfig.As))
+ buf.WriteString(fmt.Sprintf("neighbor %s password %s\n", qt.serverIP, qt.config.AuthPassword))
+ buf.WriteString("log file /var/log/quagga/bgpd.log")
+ return buf
+}
+
+func create_config_files(nr int, outputDir string) {
+ quaggaConfigList := make([]*QuaggaConfig, 0)
+
+ gobgpConf := config.BgpType{
+ Global: config.GlobalType{
+ As: 65000,
+ RouterId: net.ParseIP("192.168.255.1"),
+ },
+ }
+
+ for i := 1; i < nr+1; i++ {
+ c := config.NeighborType{
+ PeerAs: 65000 + uint32(i),
+ NeighborAddress: net.ParseIP(fmt.Sprintf("10.0.0.%d", i)),
+ AuthPassword: fmt.Sprintf("hoge%d", i),
+ }
+ gobgpConf.NeighborList = append(gobgpConf.NeighborList, c)
+ q := NewQuaggaConfig(i, &gobgpConf.Global, &c, net.ParseIP("10.0.255.1"))
+ quaggaConfigList = append(quaggaConfigList, q)
+ os.Mkdir(fmt.Sprintf("%s/q%d", outputDir, i), 0755)
+ err := ioutil.WriteFile(fmt.Sprintf("%s/q%d/bgpd.conf", outputDir, i), q.Config().Bytes(), 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ var buffer bytes.Buffer
+ encoder := toml.NewEncoder(&buffer)
+ encoder.Encode(gobgpConf)
+
+ err := ioutil.WriteFile(fmt.Sprintf("%s/gobgpd.conf", outputDir), buffer.Bytes(), 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func append_config_files(ar int, outputDir string) {
+ gobgpConf := config.BgpType{
+ Global: config.GlobalType{
+ As: 65000,
+ RouterId: net.ParseIP("192.168.255.1"),
+ },
+ }
+ c := config.NeighborType{
+ PeerAs: 65000 + uint32(ar),
+
+ NeighborAddress: net.ParseIP(fmt.Sprintf("10.0.0.%d", ar)),
+ AuthPassword: fmt.Sprintf("hoge%d", ar),
+ }
+ q := NewQuaggaConfig(ar, &gobgpConf.Global, &c, net.ParseIP("10.0.255.1"))
+ os.Mkdir(fmt.Sprintf("%s/q%d", outputDir, ar), 0755)
+ err := ioutil.WriteFile(fmt.Sprintf("%s/q%d/bgpd.conf", outputDir, ar), q.Config().Bytes(), 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+ newConf := config.BgpType{}
+ _, d_err := toml.DecodeFile(fmt.Sprintf("%s/gobgpd.conf", outputDir), &newConf)
+ if d_err != nil {
+ log.Fatal(err)
+ }
+ newConf.NeighborList = append(newConf.NeighborList, c)
+ var buffer bytes.Buffer
+ encoder := toml.NewEncoder(&buffer)
+ encoder.Encode(newConf)
+ e_err := ioutil.WriteFile(fmt.Sprintf("%s/gobgpd.conf", outputDir), buffer.Bytes(), 0644)
+ if e_err != nil {
+ log.Fatal(err)
+ }
+}
+
+func main() {
+ var opts struct {
+ ClientNumber int `short:"n" long:"client-number" description:"specfying the number of clients" default:"8"`
+ OutputDir string `short:"c" long:"output" description:"specifing the output directory"`
+ AppendClient int `short:"a" long:"append" description:"specifing the add client number" default:"0"`
+ }
+ parser := flags.NewParser(&opts, flags.Default)
+
+ _, err := parser.Parse()
+ if err != nil {
+ os.Exit(1)
+ }
+
+ if opts.OutputDir == "" {
+ opts.OutputDir, _ = filepath.Abs(".")
+ } else {
+ if _, err := os.Stat(opts.OutputDir); os.IsNotExist(err) {
+ os.Mkdir(opts.OutputDir, 0755)
+ }
+ }
+
+ if opts.AppendClient == 0 {
+ create_config_files(opts.ClientNumber, opts.OutputDir)
+ } else {
+ if _, err := os.Stat(fmt.Sprintf("%s/gobgpd.conf", opts.OutputDir)); os.IsNotExist(err) {
+ log.Fatal(err)
+ }
+ append_config_files(opts.AppendClient, opts.OutputDir)
+ }
+}
diff --git a/test/scenario_test/quagga_access.py b/test/scenario_test/quagga_access.py
new file mode 100644
index 00000000..87152c02
--- /dev/null
+++ b/test/scenario_test/quagga_access.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import telnetlib
+
+PASSWORD = "zebra"
+QLPORT = 2605
+
+def login(host):
+ tn = telnetlib.Telnet(host, QLPORT)
+ tn.read_until("Password: ")
+ tn.write(PASSWORD + "\n")
+
+ tn.write("enable\n")
+ #print tn.read_all()
+ return tn
+
+def add_network(tn, as_number, network):
+ tn.write("configure terminal\n")
+ tn.write("router bgp "+str(as_number)+"\n")
+ tn.write("network "+ network + " \n")
+ tn.write("exit\n")
+ tn.write("exit\n")
+ print tn.read_until("bgpd#")
+
+def show_config(tn):
+ tn.write("show run\n")
+ print tn.read_until("bgpd#")
+ tn.write("exit\n")
+ print tn.read_all()
+
+def show_rib(tn):
+ tn.write("show ip bgp\n")
+ tn.read_until(" Network Next Hop Metric LocPrf Weight Path")
+ rib = tn.read_until("bgpd#")
+ # print header
+ return rib_parser(rib)
+
+def rib_parser(rib):
+ lines = rib.split("\n")
+ paths = []
+ for line in lines:
+ path = {}
+ if line[0] == "*":
+ elems = line.split()
+ path['Network'] = elems[1]
+ path['Next Hop'] = elems[2]
+ # path['Metric'] = elems[3]
+ # path['LocPrf'] = elems[4]
+ # path['Weight'] = elems[5]
+ # path['Path'] = elems[6]
+ if len(path) > 0:
+ paths.append(path)
+ return paths
+
diff --git a/test/scenario_test/route_server_test.py b/test/scenario_test/route_server_test.py
new file mode 100644
index 00000000..9b9b1991
--- /dev/null
+++ b/test/scenario_test/route_server_test.py
@@ -0,0 +1,401 @@
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import requests
+import json
+import toml
+import os
+import quagga_access as qaccess
+from ciscoconfparse import CiscoConfParse
+import docker_control as fab
+
+
+class GoBGPTest(unittest.TestCase):
+
+ gobgp_ip = "10.0.255.1"
+ gobgp_port = "8080"
+ base_dir = "/usr/local/gobgp/"
+ gobgp_config_file = "/usr/local/gobgp/gobgpd.conf"
+ gobgp_config = None
+ quagga_num = 3
+ appending_quagga = 10
+ deleting_quagga = 10
+ appending_quagga_best = 20
+ fab.init_test_env_executor(quagga_num)
+
+ def __init__(self, *args, **kwargs):
+ super(GoBGPTest, self).__init__(*args, **kwargs)
+
+ def setUp(self):
+ self.quagga_configs = []
+ self.load_gobgp_config()
+ self.load_quagga_config()
+
+ # test each neighbor state is turned establish
+ def test_01_neighbor_established(self):
+ print "test_neighbor_established"
+ if self.check_load_config() is False:
+ return
+ addresses = self.get_neighbor_address(self.gobgp_config)
+
+ for address in addresses:
+ # get neighbor state and remote ip from gobgp connections
+ print "check of [ " + address + " ]"
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + address
+ r = requests.get(url)
+ neighbor = json.loads(r.text)
+ state = neighbor['info']['bgp_state']
+ remote_ip = neighbor['conf']['remote_ip']
+ self.assertEqual(address, remote_ip)
+ self.assertEqual(state, "BGP_FSM_ESTABLISHED")
+
+ # Test of advertised route gobgp from each quagga
+ def test_02_received_route(self):
+ print "test_received_route"
+ if self.check_load_config() is False:
+ return
+
+ for address in self.get_neighbor_address(self.gobgp_config):
+ print "check of [ " + address + " ]"
+ # get local-rib per peer
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + address + "/local-rib"
+ r = requests.get(url)
+ local_rib = json.loads(r.text)
+
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix, "my ip !!!"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 0)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ # Test of advertising route to each quagga form gobgp
+ def test_03_advertising_route(self):
+ print "test_advertising_route"
+ if self.check_load_config() is False:
+ return
+
+ for address in self.get_neighbor_address(self.gobgp_config):
+ print "check of [ " + address + " ]"
+ tn = qaccess.login(address)
+ q_rib = qaccess.show_rib(tn)
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop, "my ip !!!"
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and "0.0.0.0" == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and c_path.nexthop == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ # check if quagga that is appended can establish connection with gobgp
+ def test_04_established_with_appended_quagga(self):
+ print "test_established_with_appended_quagga"
+
+ # append new quagga container
+ fab.docker_container_append(self.appending_quagga)
+ append_quagga_address = "10.0.0." + str(self.appending_quagga)
+
+ # get neighbor state and remote ip of new quagga
+ print "check of [" + append_quagga_address + " ]"
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + append_quagga_address
+ r = requests.get(url)
+ neighbor = json.loads(r.text)
+ state = neighbor['info']['bgp_state']
+ remote_ip = neighbor['conf']['remote_ip']
+ self.assertEqual(append_quagga_address, remote_ip)
+ self.assertEqual(state, "BGP_FSM_ESTABLISHED")
+
+ # Test of advertised route gobgp from each quagga when append quagga container
+ def test_05_received_route_when_appended_quagga(self):
+ print "test_received_route_by_appended_quagga"
+ if self.check_load_config() is False:
+ return
+
+ for address in self.get_neighbor_address(self.gobgp_config):
+ print "check of [ " + address + " ]"
+ # get local-rib per peer
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + address + "/local-rib"
+ r = requests.get(url)
+ local_rib = json.loads(r.text)
+
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix, "my ip !!!"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 0)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix,"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ # Test of advertising route to each quagga form gobgp when append quagga container
+ def test_06_advertising_route_when_appended_quagga(self):
+ print "test_advertising_route_to_appended_quagga"
+ if self.check_load_config() is False:
+ return
+
+ for address in self.get_neighbor_address(self.gobgp_config):
+ print "check of [ " + address + " ]"
+ tn = qaccess.login(address)
+ q_rib = qaccess.show_rib(tn)
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop, "my ip !!!"
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and "0.0.0.0" == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and c_path.nexthop == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ def test_07_active_when_depend_quagga(self):
+ print "test_active_when_depend_quagga"
+
+ # remove quagga container
+ fab.docker_container_depend(self.deleting_quagga)
+ depend_quagga_address = "10.0.0." + str(self.deleting_quagga)
+
+ # get neighbor state and remote ip of depend quagga
+ print "check of [" + depend_quagga_address + " ]"
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + depend_quagga_address
+ r = requests.get(url)
+ neighbor = json.loads(r.text)
+ state = neighbor['info']['bgp_state']
+ remote_ip = neighbor['conf']['remote_ip']
+ self.assertEqual(depend_quagga_address, remote_ip)
+ self.assertEqual(state, "BGP_FSM_ACTIVE")
+
+ def test_08_received_route_when_depend_quagga(self):
+ print "test_received_route_when_depend_quagga"
+ if self.check_load_config() is False:
+ return
+
+ deleting_quagga_address = "10.0.0." + str(self.deleting_quagga)
+ for address in self.get_neighbor_address(self.gobgp_config):
+ if deleting_quagga_address == address:
+ continue
+
+ print "check of [ " + address + " ]"
+ # get local-rib per peer
+ url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/neighbor/" + address + "/local-rib"
+ r = requests.get(url)
+ local_rib = json.loads(r.text)
+
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix, "my ip !!!"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 0)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ # print "config : ", c_dest.prefix,"
+ g_dests = local_rib['Destinations']
+ exist_n = 0
+ for g_dest in g_dests:
+ # print "gobgp : ", g_dest['Prefix']
+ if c_dest.prefix == g_dest['Prefix']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ def test_09_advertising_route_when_depend_quagga(self):
+ print "test_advertising_route_when_depend_quagga"
+ if self.check_load_config() is False:
+ return
+
+ deleting_quagga_address = "10.0.0." + str(self.deleting_quagga)
+ for address in self.get_neighbor_address(self.gobgp_config):
+ if deleting_quagga_address == address:
+ continue
+
+ print "check of [ " + address + " ]"
+ tn = qaccess.login(address)
+ q_rib = qaccess.show_rib(tn)
+ for quagga_config in self.quagga_configs:
+ if quagga_config.peer_ip == address:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop, "my ip !!!"
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and "0.0.0.0" == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+ else:
+ for c_dest in quagga_config.destinations.itervalues():
+ exist_n = 0
+ for c_path in c_dest.paths:
+ # print "conf : ", c_path.network, c_path.nexthop
+ for q_path in q_rib:
+ # print "quag : ", q_path['Network'], q_path['Next Hop']
+ if c_path.network.split("/")[0] == q_path['Network'] and c_path.nexthop == q_path['Next Hop']:
+ exist_n += 1
+ self.assertEqual(exist_n, 1)
+
+ def test_10_bestpath_selection_by_received_route(self):
+ pass
+
+ # load configration from gobgp(gobgpd.conf)
+ def load_gobgp_config(self):
+ try:
+ self.gobgp_config = toml.loads(open(self.gobgp_config_file).read())
+ except IOError, (errno, strerror):
+ print "I/O error(%s): %s" % (errno, strerror)
+
+ # load configration from quagga(bgpd.conf)
+ def load_quagga_config(self):
+ dirs = []
+ try:
+ content = os.listdir(self.base_dir)
+ for item in content:
+ if os.path.isdir(os.path.join(self.base_dir, item)):
+ dirs.append(item)
+ except OSError, (errno, strerror):
+ print "I/O error(%s): %s" % (errno, strerror)
+
+ for dir in dirs:
+ config_path = self.base_dir + dir + "/bgpd.conf"
+ config = CiscoConfParse(config_path)
+ peer_ip = "10.0.0." + str(dir).replace("q", "")
+ peer_id = config.find_objects(r"^bgp\srouter-id")[0].text
+ peer_as = config.find_objects(r"^router\sbgp")[0].text
+ quagga_config = Peer(peer_ip, peer_id, peer_as)
+
+ networks = config.find_objects(r"^network")
+ if len(networks) == 0:
+ continue
+ for network in networks:
+ elems = network.text.split(" ")
+ prefix = elems[1].split("/")[0]
+ network = elems[1]
+ nexthop = peer_ip
+ path = Path(network, nexthop)
+ dest = Destination(prefix)
+ dest.paths.append(path)
+ quagga_config.destinations[prefix] = dest
+
+ neighbors = config.find_objects(r"^neighbor\s.*\sremote-as")
+ if len(neighbors) == 0:
+ continue
+ for neighbor in neighbors:
+ elems = neighbor.text.split(" ")
+ neighbor = Peer(elems[1], None, elems[3])
+ quagga_config.neighbors.append(neighbor)
+
+ self.quagga_configs.append(quagga_config)
+
+ # get address of each neighbor from gobpg configration
+ def get_neighbor_address(self, config):
+ address = []
+ neighbors_config = config['NeighborList']
+ for neighbor_config in neighbors_config:
+ neighbor_ip = neighbor_config['NeighborAddress']
+ address.append(neighbor_ip)
+ return address
+
+ def check_load_config(self):
+ if self.gobgp_config is None:
+ print "Failed to read the gobgp configuration file"
+ return False
+ if len(self.quagga_configs) == 0:
+ print "Failed to read the quagga configuration file"
+ return False
+ return True
+
+
+class Peer:
+ def __init__(self, peer_ip, peer_id, peer_as):
+ self.peer_ip = peer_ip
+ self.peer_id = peer_id
+ self.peer_as = peer_as
+ self.neighbors = []
+ self.destinations = {}
+
+
+class Destination:
+ def __init__(self, prefix):
+ self.prefix = prefix
+ self.paths = []
+
+
+class Path:
+ def __init__(self, network, nexthop):
+ self.network = network
+ self.nexthop = nexthop
+ self.origin = None
+ self.as_path = []
+ self.metric = None
+
+