# 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. from fabric.api import local import re import os import time GOBGP_CONTAINER_NAME = "gobgp" GOBGP_ADDRESS_0 = {"IPv4": "10.0.255.1", "IPv6": "2001::0:192:168:255:1"} GOBGP_ADDRESS_1 = {"IPv4": "11.0.255.1", "IPv6": "2001::1:192:168:255:1"} GOBGP_ADDRESS_2 = {"IPv4": "12.0.255.1", "IPv6": "2001::2:192:168:255:1"} GOBGP_CONFIG_FILE = "gobgpd.conf" CONFIG_DIR = "/tmp/gobgp" CONFIG_DIRR = "/tmp/gobgp/" SHARE_VOLUME = "/root/share_volume" EXABGP_CONTAINER_NAME = "exabgp" EXABGP_ADDRESS = "10.0.0.100/16" EXABGP_CONFDIR = SHARE_VOLUME + "/exabgp_test_conf" EXABGP_LOG_FILE = "exabgpd.log" STARTUP_FILE_NAME = "gobgp_startup.sh" STARTUP_FILE = SHARE_VOLUME + "/" + STARTUP_FILE_NAME IP_VERSION = "IPv4" IF_CONFIG_OPTION = {"IPv4": "inet", "IPv6": "inet6"} BRIDGE_0 = {"BRIDGE_NAME": "br0", "IPv4": "10.0.255.2", "IPv6": "2001::0:192:168:255:2"} BRIDGE_1 = {"BRIDGE_NAME": "br1", "IPv4": "11.0.255.2", "IPv6": "2001::1:192:168:255:2"} BRIDGE_2 = {"BRIDGE_NAME": "br2", "IPv4": "12.0.255.2", "IPv6": "2001::2:192:168:255:2"} BRIDGES = [BRIDGE_0, BRIDGE_1, BRIDGE_2] BASE_NET = {BRIDGE_0["BRIDGE_NAME"]: {"IPv4": "10.0.0.", "IPv6": "2001::0:192:168:0:"}, BRIDGE_1["BRIDGE_NAME"]: {"IPv4": "11.0.0.", "IPv6": "2001::1:192:168:0:"}, BRIDGE_2["BRIDGE_NAME"]: {"IPv4": "12.0.0.", "IPv6": "2001::2:192:168:0:"}} BASE_MASK = {"IPv4": "/16", "IPv6": "/64"} A_PART_OF_CURRENT_DIR = "/test/scenario_test" def test_user_check(): root = False outbuf = local("echo $USER", capture=True) user = outbuf if user == "root": root = True return root def install_docker_and_tools(): print "start install packages of test environment." if test_user_check() is False: print "you are not root" return 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("docker pull osrg/exabgp", capture=True) local("mkdir /tmp/gobgp", 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: if "lxc-docker" in dpkg: docker_exists = True return docker_exists def go_path_check(): go_path_exist = False outbuf = local("echo `which go`", capture=True) if "go" in outbuf: go_path_exist = True return go_path_exist def docker_container_check(): container_exists = False outbuf = local("docker ps -a", capture=True) docker_ps = outbuf.split('\n') for container in docker_ps: container_name = container.split()[-1] if (container_name == GOBGP_CONTAINER_NAME) or \ (container_name == EXABGP_CONTAINER_NAME) or ("q" in container_name): container_exists = True return container_exists def bridge_setting_check(): setting_exists = False for bridge in BRIDGES: sysfs_name = "/sys/class/net/" + bridge["BRIDGE_NAME"] if os.path.exists(sysfs_name): setting_exists = True return setting_exists return setting_exists def docker_containers_get(): containers = [] cmd = "docker ps -a | awk '{print $NF}'" 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_container_set_ipaddress(bridge, name, address): cmd = "pipework " + bridge["BRIDGE_NAME"] + " -i e" + bridge["BRIDGE_NAME"]\ + " " + name + " " + address local(cmd, capture=True) def docker_container_run_quagga(quagga_num, bridge): 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 = BASE_NET[bridge["BRIDGE_NAME"]][IP_VERSION] + str(quagga_num) + BASE_MASK[IP_VERSION] docker_container_set_ipaddress(bridge, quagga_name, quagga_address) # restart the quagga after the docker container has become IP reachable cmd = 'docker kill --signal="HUP" ' + quagga_name local(cmd, capture=True) def docker_container_run_gobgp(bridge): cmd = "docker run --privileged=true -v " + CONFIG_DIR + ":" + SHARE_VOLUME + " -d --name "\ + GOBGP_CONTAINER_NAME + " -id osrg/gobgp" local(cmd, capture=True) docker_container_set_ipaddress(bridge, GOBGP_CONTAINER_NAME, GOBGP_ADDRESS_0[IP_VERSION] + BASE_MASK[IP_VERSION]) def docker_container_run_exabgp(bridge): pwd = local("pwd", capture=True) test_pattern_dir = pwd + "/exabgp_test_conf" cmd = "cp -r " + test_pattern_dir + " " + CONFIG_DIRR local(cmd, capture=True) cmd = "docker run --privileged=true -v " + CONFIG_DIR + ":" + SHARE_VOLUME + " -d --name "\ + EXABGP_CONTAINER_NAME + " -id osrg/exabgp" local(cmd, capture=True) docker_container_set_ipaddress(bridge, EXABGP_CONTAINER_NAME, EXABGP_ADDRESS) def change_owner_to_root(target): cmd = "chown -R root:root " + target local(cmd, capture=True) def create_config_dir(): cmd = "mkdir " + CONFIG_DIR local(cmd, capture=True) def make_startup_file(log_opt=""): file_buff = '#!/bin/bash' + '\n' file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n' file_buff += 'git pull origin master' + '\n' file_buff += 'go get -v' + '\n' file_buff += 'go build' + '\n' file_buff += './gobgp -f ' + SHARE_VOLUME + '/gobgpd.conf ' + log_opt + ' > ' + SHARE_VOLUME + '/gobgpd.log' cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIR + "/" + STARTUP_FILE_NAME local(cmd, capture=True) cmd = "chmod 755 " + CONFIG_DIRR + STARTUP_FILE_NAME local(cmd, capture=True) def make_startup_file_use_local_gobgp(log_opt=""): file_buff = '#!/bin/bash' + '\n' file_buff += 'rm -rf /go/src/github.com/osrg/gobgp' + '\n' file_buff += 'cp -r ' + SHARE_VOLUME + '/gobgp /go/src/github.com/osrg/' + '\n' file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n' file_buff += 'go get -v' + '\n' file_buff += 'go build' + '\n' file_buff += './gobgp -f ' + SHARE_VOLUME + '/gobgpd.conf ' + log_opt + ' > ' + SHARE_VOLUME + '/gobgpd.log' cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIR + "/" + STARTUP_FILE_NAME local(cmd, capture=True) cmd = "chmod 755 " + CONFIG_DIRR + STARTUP_FILE_NAME local(cmd, capture=True) def docker_container_stop_quagga(quagga): cmd = "docker rm -f " + quagga local(cmd, capture=True) cmd = "rm -rf " + CONFIG_DIRR + quagga local(cmd, capture=True) def docker_container_stop_gobgp(): cmd = "docker rm -f " + GOBGP_CONTAINER_NAME local(cmd, capture=True) def docker_container_stop_exabgp(): cmd = "docker rm -f " + EXABGP_CONTAINER_NAME local(cmd, capture=True) def docker_containers_destroy(): containers = docker_containers_get() for container in containers: if re.match(r'q[0-9][0-9]*', container) is not None: docker_container_stop_quagga(container) if container == GOBGP_CONTAINER_NAME: docker_container_stop_gobgp() if container == EXABGP_CONTAINER_NAME: docker_container_stop_exabgp() bridge_unsetting_for_docker_connection() cmd = "rm -rf " + CONFIG_DIRR local(cmd, capture=True) def docker_container_quagga_append(quagga_num, bridge): print "start append docker container." docker_container_run_quagga(quagga_num, bridge) def docker_container_quagga_removed(quagga_num): print "start removed docker container." quagga = "q" + str(quagga_num) docker_container_stop_quagga(quagga) print "complete removed docker container." def bridge_setting_for_docker_connection(bridges): # bridge_unsetting_for_docker_connection() for bridge in bridges: cmd = "brctl addbr " + bridge["BRIDGE_NAME"] local(cmd, capture=True) if IP_VERSION == "IPv6": cmd = "ifconfig " + bridge["BRIDGE_NAME"] + " " + IF_CONFIG_OPTION[IP_VERSION] +\ " add " + bridge[IP_VERSION] + BASE_MASK[IP_VERSION] else: cmd = "ifconfig " + bridge["BRIDGE_NAME"] + " " + bridge[IP_VERSION] local(cmd, capture=True) cmd = "ifconfig " + bridge["BRIDGE_NAME"] + " up" local(cmd, capture=True) def bridge_unsetting_for_docker_connection(): for bridge in BRIDGES: sysfs_name = "/sys/class/net/" + bridge["BRIDGE_NAME"] if os.path.exists(sysfs_name): cmd = "ifconfig " + bridge["BRIDGE_NAME"] + " down" local(cmd, capture=True) cmd = "brctl delbr " + bridge["BRIDGE_NAME"] local(cmd, capture=True) def start_gobgp(): cmd = "docker exec gobgp " + STARTUP_FILE + " > /dev/null 2>&1 &" local(cmd, capture=True) def start_exabgp(conf_file): cmd = "docker exec exabgp cp -f " + SHARE_VOLUME + "/exabgp_test_conf/exabgp.env /root/exabgp/etc/exabgp/exabgp.env" local(cmd, capture=True) conf_path = EXABGP_CONFDIR + "/" + conf_file cmd = "docker exec exabgp /root/exabgp/sbin/exabgp " + conf_path + " > /dev/null 2>&1 &" local(cmd, capture=True) def get_notification_from_exabgp_log(): log_path = CONFIG_DIRR + EXABGP_LOG_FILE cmd = "grep notification " + log_path + " | head -1" err_mgs = local(cmd, capture=True) return err_mgs def make_config(quagga_num, go_path, bridge): if go_path != "": print "specified go path is [ " + go_path + " ]." if os.path.isdir(go_path): go_path += "/" else: print "specified go path do not use." pwd = local("pwd", capture=True) cmd = go_path + "go run " + pwd + "/quagga-rsconfig.go -n " + str(quagga_num) +\ " -c /tmp/gobgp -v " + IP_VERSION + " -i " + bridge["BRIDGE_NAME"][-1] local(cmd, capture=True) def make_config_append(quagga_num, go_path, bridge): if go_path != "": print "specified go path is [ " + go_path + " ]." if os.path.isdir(go_path): go_path += "/" else: print "specified go path do not use." pwd = local("pwd", capture=True) cmd = go_path + "go run " + pwd + "/quagga-rsconfig.go -a " + str(quagga_num) +\ " -c /tmp/gobgp -v " + IP_VERSION + " -i " + bridge["BRIDGE_NAME"][-1] local(cmd, capture=True) def change_exagbp_version(): cmd = "docker exec exabgp git -C /root/exabgp pull origin master" local(cmd, capture=True) def reload_config(): cmd = "docker exec gobgp /usr/bin/pkill gobgp -SIGHUP" local(cmd, capture=True) print "complete append docker container." def init_test_env_executor(quagga_num, use_local, go_path, log_debug=False): print "start initialization of test environment." if docker_container_check() or bridge_setting_check(): print "gobgp test environment already exists." print "so that remake gobgp test environment." docker_containers_destroy() print "make gobgp test environment." create_config_dir() bridge_setting_for_docker_connection(BRIDGES) make_config(quagga_num, go_path, BRIDGE_0) # run gobgp docker container docker_container_run_gobgp(BRIDGE_0) # set log option opt = "-l debug" if log_debug else "" # execute local gobgp program in the docker container if the input option is local if use_local: print "execute gobgp program in local machine." pwd = local("pwd", capture=True) if A_PART_OF_CURRENT_DIR in pwd: gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd) cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR local(cmd, capture=True) make_startup_file_use_local_gobgp(log_opt=opt) else: print "scenario_test directory is not." print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) else: print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) change_owner_to_root(CONFIG_DIR) start_gobgp() # run quagga docker container for num in range(1, quagga_num + 1): docker_container_run_quagga(num, BRIDGE_0) print "complete initialization of test environment." def init_ipv6_test_env_executor(quagga_num, use_local, go_path, log_debug=False): print "start initialization of test environment." if docker_container_check() or bridge_setting_check(): print "gobgp test environment already exists." print "so that remake gobgp test environment." docker_containers_destroy() print "make gobgp test environment." create_config_dir() bridge_setting_for_docker_connection([BRIDGE_0]) make_config(quagga_num, go_path, BRIDGE_0) # run gobgp docker container docker_container_run_gobgp(BRIDGE_0) # set log option opt = "-l debug" if log_debug else "" # execute local gobgp program in the docker container if the input option is local if use_local: print "execute gobgp program in local machine." pwd = local("pwd", capture=True) if A_PART_OF_CURRENT_DIR in pwd: gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd) cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR local(cmd, capture=True) make_startup_file_use_local_gobgp(log_opt=opt) else: print "scenario_test directory is not." print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) else: print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) change_owner_to_root(CONFIG_DIR) start_gobgp() # run quagga docker container for num in range(1, quagga_num + 1): docker_container_run_quagga(num, BRIDGE_0) print "complete initialization of test environment." def init_malformed_test_env_executor(conf_file, use_local, log_debug=False): print "start initialization of exabgp test environment." if docker_container_check() or bridge_setting_check(): print "gobgp test environment already exists." print "so that remake gobgp test environment." docker_containers_destroy() print "make gobgp test environment." create_config_dir() bridge_setting_for_docker_connection(BRIDGES) pwd = local("pwd", capture=True) gobgp_file = pwd + "/exabgp_test_conf/gobgpd.conf" cmd = "cp " + gobgp_file + " " + CONFIG_DIRR local(cmd, capture=True) quagga_dir = CONFIG_DIRR + "q1" cmd = "mkdir " + quagga_dir local(cmd, capture=True) quagga_file = pwd + "/exabgp_test_conf/quagga.conf" cmd = "cp " + quagga_file + " " + quagga_dir + "/bgpd.conf" local(cmd, capture=True) # run gobgp docker container docker_container_run_gobgp(BRIDGE_0) # run exabgp docker container docker_container_run_exabgp(BRIDGE_0) # set log option opt = "-l debug" if log_debug else "" # execute local gobgp program in the docker container if the input option is local if use_local: print "execute gobgp program in local machine." pwd = local("pwd", capture=True) if A_PART_OF_CURRENT_DIR in pwd: gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd) cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR local(cmd, capture=True) make_startup_file_use_local_gobgp(log_opt=opt) else: print "scenario_test directory is not." print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) else: print "execute gobgp program of osrg/master in github." make_startup_file(log_opt=opt) change_owner_to_root(CONFIG_DIR) change_exagbp_version() start_gobgp() # run quagga docker container docker_container_run_quagga(1, BRIDGE_0) start_exabgp(conf_file) def docker_container_quagga_append_executor(quagga_num, go_path): make_config_append(quagga_num, go_path, BRIDGE_0) docker_container_quagga_append(quagga_num, BRIDGE_0) reload_config() def docker_container_ipv6_quagga_append_executor(quagga_nums, go_path): print "append ipv6 quagga container." global IP_VERSION IP_VERSION = "IPv6" bridge_setting_for_docker_connection([BRIDGE_1]) docker_container_set_ipaddress(BRIDGE_1, GOBGP_CONTAINER_NAME, GOBGP_ADDRESS_1[IP_VERSION] + BASE_MASK[IP_VERSION]) for quagga_num in quagga_nums: make_config_append(quagga_num, go_path, BRIDGE_1) docker_container_quagga_append(quagga_num, BRIDGE_1) reload_config() def docker_container_quagga_removed_executor(quagga_num): docker_container_quagga_removed(quagga_num) def docker_container_make_bestpath_env_executor(append_quagga_num, go_path): print "start make bestpath environment" make_config_append(append_quagga_num, go_path, BRIDGE_1) append_quagga_name = "q" + str(append_quagga_num) docker_container_quagga_append(append_quagga_num, BRIDGE_1) reload_config() docker_container_set_ipaddress(BRIDGE_1, "q2", "11.0.0.2/16") docker_container_set_ipaddress(BRIDGE_2, append_quagga_name, "12.0.0.20/16") docker_container_set_ipaddress(BRIDGE_2, "q3", "12.0.0.3/16")