From 9f4e168bf139e196a55061f47206f15f2630ed5c Mon Sep 17 00:00:00 2001 From: Naoto Hanaue Date: Wed, 14 Jan 2015 20:39:25 +0900 Subject: scenario_test: add scenario_test scripts nosetests -s route_server_test.py Signed-off-by: FUJITA Tomonori --- test/scenario_test/docker_control.py | 236 +++++++++++++++++++ test/scenario_test/pip-requires.txt | 4 + test/scenario_test/quagga-rsconfig.go | 145 ++++++++++++ test/scenario_test/quagga_access.py | 68 ++++++ test/scenario_test/route_server_test.py | 401 ++++++++++++++++++++++++++++++++ 5 files changed, 854 insertions(+) create mode 100644 test/scenario_test/docker_control.py create mode 100644 test/scenario_test/pip-requires.txt create mode 100644 test/scenario_test/quagga-rsconfig.go create mode 100644 test/scenario_test/quagga_access.py create mode 100644 test/scenario_test/route_server_test.py (limited to 'test') 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 + + -- cgit v1.2.3