diff options
Diffstat (limited to 'test/scenario_test/lib/base.py')
-rw-r--r-- | test/scenario_test/lib/base.py | 382 |
1 files changed, 0 insertions, 382 deletions
diff --git a/test/scenario_test/lib/base.py b/test/scenario_test/lib/base.py deleted file mode 100644 index 139cecc4..00000000 --- a/test/scenario_test/lib/base.py +++ /dev/null @@ -1,382 +0,0 @@ -# Copyright (C) 2015 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, lcd -from fabric import colors -from fabric.utils import indent -from fabric.state import env - -import netaddr -import os -import time -import itertools - -DEFAULT_TEST_PREFIX = '' -DEFAULT_TEST_BASE_DIR = '/tmp/gobgp' -TEST_PREFIX = DEFAULT_TEST_PREFIX -TEST_BASE_DIR = DEFAULT_TEST_BASE_DIR - -BGP_FSM_IDLE = 'BGP_FSM_IDLE' -BGP_FSM_ACTIVE = 'BGP_FSM_ACTIVE' -BGP_FSM_ESTABLISHED = 'BGP_FSM_ESTABLISHED' - -BGP_ATTR_TYPE_ORIGIN = 1 -BGP_ATTR_TYPE_AS_PATH = 2 -BGP_ATTR_TYPE_NEXT_HOP = 3 -BGP_ATTR_TYPE_MULTI_EXIT_DISC = 4 -BGP_ATTR_TYPE_LOCAL_PREF = 5 -BGP_ATTR_TYPE_COMMUNITIES = 8 -BGP_ATTR_TYPE_MP_REACH_NLRI = 14 -BGP_ATTR_TYPE_EXTENDED_COMMUNITIES = 16 - -env.abort_exception = RuntimeError - -def try_several_times(f, t=3, s=1): - e = None - for i in range(t): - try: - r = f() - except RuntimeError as e: - time.sleep(s) - else: - return r - raise e - - -def get_bridges(): - return try_several_times(lambda : local("brctl show | awk 'NR > 1{print $1}'", capture=True)).split('\n') - - -def get_containers(): - return try_several_times(lambda : local("docker ps -a | awk 'NR > 1 {print $NF}'", capture=True)).split('\n') - - -class CmdBuffer(list): - def __init__(self, delim='\n'): - super(CmdBuffer, self).__init__() - self.delim = delim - - def __lshift__(self, value): - self.append(value) - - def __str__(self): - return self.delim.join(self) - - -def make_gobgp_ctn(tag='gobgp', local_gobgp_path='', from_image='osrg/quagga'): - if local_gobgp_path == '': - local_gobgp_path = os.getcwd() - - c = CmdBuffer() - c << 'FROM {0}'.format(from_image) - c << 'ADD gobgp /go/src/github.com/osrg/gobgp/' - c << 'RUN go get github.com/osrg/gobgp/gobgpd' - c << 'RUN go install github.com/osrg/gobgp/gobgpd' - c << 'RUN go get github.com/osrg/gobgp/gobgp' - c << 'RUN go install github.com/osrg/gobgp/gobgp' - - rindex = local_gobgp_path.rindex('gobgp') - if rindex < 0: - raise Exception('{0} seems not gobgp dir'.format(local_gobgp_path)) - - workdir = local_gobgp_path[:rindex] - with lcd(workdir): - local('echo \'{0}\' > Dockerfile'.format(str(c))) - local('docker build -t {0} .'.format(tag)) - local('rm Dockerfile') - - -class Bridge(object): - def __init__(self, name, subnet='', with_ip=True, self_ip=False): - self.name = '{0}_{1}'.format(TEST_PREFIX, name) - self.with_ip = with_ip - if with_ip: - self.subnet = netaddr.IPNetwork(subnet) - - def f(): - for host in self.subnet: - yield host - self._ip_generator = f() - # throw away first network address - self.next_ip_address() - - def f(): - if self.name in get_bridges(): - self.delete() - local("ip link add {0} type bridge".format(self.name)) - try_several_times(f) - try_several_times(lambda : local("ip link set up dev {0}".format(self.name))) - - self.self_ip = self_ip - if self_ip: - self.ip_addr = self.next_ip_address() - try_several_times(lambda :local("ip addr add {0} dev {1}".format(self.ip_addr, self.name))) - self.ctns = [] - - def next_ip_address(self): - return "{0}/{1}".format(self._ip_generator.next(), - self.subnet.prefixlen) - - def addif(self, ctn): - name = ctn.next_if_name() - self.ctns.append(ctn) - if self.with_ip: - - ctn.pipework(self, self.next_ip_address(), name) - else: - ctn.pipework(self, '0/0', name) - - def delete(self): - try_several_times(lambda : local("ip link set down dev {0}".format(self.name))) - try_several_times(lambda : local("ip link delete {0} type bridge".format(self.name))) - - -class Container(object): - def __init__(self, name, image): - self.name = name - self.image = image - self.shared_volumes = [] - self.ip_addrs = [] - self.is_running = False - self.eths = [] - - if self.docker_name() in get_containers(): - self.remove() - - def docker_name(self): - if TEST_PREFIX == DEFAULT_TEST_PREFIX: - return self.name - return '{0}_{1}'.format(TEST_PREFIX, self.name) - - def next_if_name(self): - name = 'eth{0}'.format(len(self.eths)+1) - self.eths.append(name) - return name - - def run(self): - c = CmdBuffer(' ') - c << "docker run --privileged=true" - for sv in self.shared_volumes: - c << "-v {0}:{1}".format(sv[0], sv[1]) - c << "--name {0} -id {1}".format(self.docker_name(), self.image) - self.id = try_several_times(lambda : local(str(c), capture=True)) - self.is_running = True - self.local("ip li set up dev lo") - for line in self.local("ip a show dev eth0", capture=True).split('\n'): - if line.strip().startswith("inet "): - elems = [e.strip() for e in line.strip().split(' ')] - self.ip_addrs.append(('eth0', elems[1], 'docker0')) - return 0 - - def stop(self): - ret = try_several_times(lambda : local("docker stop -t 0 " + self.docker_name(), capture=True)) - self.is_running = False - return ret - - def remove(self): - ret = try_several_times(lambda : local("docker rm -f " + self.docker_name(), capture=True)) - self.is_running = False - return ret - - def pipework(self, bridge, ip_addr, intf_name=""): - if not self.is_running: - print colors.yellow('call run() before pipeworking') - return - c = CmdBuffer(' ') - c << "pipework {0}".format(bridge.name) - - if intf_name != "": - c << "-i {0}".format(intf_name) - else: - intf_name = "eth1" - c << "{0} {1}".format(self.docker_name(), ip_addr) - self.ip_addrs.append((intf_name, ip_addr, bridge.name)) - try_several_times(lambda :local(str(c))) - - def local(self, cmd, capture=False, flag=''): - return local("docker exec {0} {1} {2}".format(flag, - self.docker_name(), - cmd), capture) - - def get_pid(self): - if self.is_running: - cmd = "docker inspect -f '{{.State.Pid}}' " + self.docker_name() - return int(local(cmd, capture=True)) - return -1 - - -class BGPContainer(Container): - - WAIT_FOR_BOOT = 1 - RETRY_INTERVAL = 5 - - def __init__(self, name, asn, router_id, ctn_image_name): - self.config_dir = '/'.join((TEST_BASE_DIR, TEST_PREFIX, name)) - local('if [ -e {0} ]; then rm -r {0}; fi'.format(self.config_dir)) - local('mkdir -p {0}'.format(self.config_dir)) - local('chmod 777 {0}'.format(self.config_dir)) - self.asn = asn - self.router_id = router_id - self.peers = {} - self.routes = {} - self.policies = {} - super(BGPContainer, self).__init__(name, ctn_image_name) - - def __repr__(self): - return str({'name':self.name, 'asn':self.asn, 'router_id':self.router_id}) - - def run(self): - self.create_config() - super(BGPContainer, self).run() - return self.WAIT_FOR_BOOT - - def add_peer(self, peer, passwd=None, evpn=False, is_rs_client=False, - policies=None, passive=False, - is_rr_client=False, cluster_id=None, - flowspec=False, bridge='', reload_config=True): - neigh_addr = '' - local_addr = '' - for me, you in itertools.product(self.ip_addrs, peer.ip_addrs): - if bridge != '' and bridge != me[2]: - continue - if me[2] == you[2]: - neigh_addr = you[1] - local_addr = me[1] - break - - if neigh_addr == '': - raise Exception('peer {0} seems not ip reachable'.format(peer)) - - if not policies: - policies = {} - - self.peers[peer] = {'neigh_addr': neigh_addr, - 'passwd': passwd, - 'evpn': evpn, - 'flowspec': flowspec, - 'is_rs_client': is_rs_client, - 'is_rr_client': is_rr_client, - 'cluster_id': cluster_id, - 'policies': policies, - 'passive': passive, - 'local_addr': local_addr} - if self.is_running and reload_config: - self.create_config() - self.reload_config() - - def del_peer(self, peer, reload_config=True): - del self.peers[peer] - if self.is_running and reload_config: - self.create_config() - self.reload_config() - - def disable_peer(self, peer): - raise Exception('implement disable_peer() method') - - def enable_peer(self, peer): - raise Exception('implement enable_peer() method') - - def log(self): - return local('cat {0}/*.log'.format(self.config_dir), capture=True) - - def add_route(self, route, rf='ipv4', attribute=None, aspath=None, - community=None, med=None, extendedcommunity=None, - nexthop=None, matchs=None, thens=None, - local_pref=None, reload_config=True): - self.routes[route] = {'prefix': route, - 'rf': rf, - 'attr': attribute, - 'next-hop': nexthop, - 'as-path': aspath, - 'community': community, - 'med': med, - 'local-pref': local_pref, - 'extended-community': extendedcommunity, - 'matchs': matchs, - 'thens' : thens} - if self.is_running and reload_config: - self.create_config() - self.reload_config() - - def add_policy(self, policy, peer=None, reload_config=True): - self.policies[policy['name']] = policy - if peer in self.peers: - self.peers[peer]['policies'][policy['name']] = policy - if self.is_running and reload_config: - self.create_config() - self.reload_config() - - def get_local_rib(self, peer, rf): - raise Exception('implement get_local_rib() method') - - def get_global_rib(self, rf): - raise Exception('implement get_global_rib() method') - - def get_neighbor_state(self, peer_id): - raise Exception('implement get_neighbor() method') - - def get_reachablily(self, prefix, timeout=20): - version = netaddr.IPNetwork(prefix).version - addr = prefix.split('/')[0] - if version == 4: - ping_cmd = 'ping' - elif version == 6: - ping_cmd = 'ping6' - else: - raise Exception('unsupported route family: {0}'.format(version)) - cmd = '/bin/bash -c "/bin/{0} -c 1 -w 1 {1} | xargs echo"'.format(ping_cmd, addr) - interval = 1 - count = 0 - while True: - res = self.local(cmd, capture=True) - print colors.yellow(res) - if '1 packets received' in res and '0% packet loss': - break - time.sleep(interval) - count += interval - if count >= timeout: - raise Exception('timeout') - return True - - def wait_for(self, expected_state, peer, timeout=120): - interval = 1 - count = 0 - while True: - state = self.get_neighbor_state(peer) - y = colors.yellow - print y("{0}'s peer {1} state: {2}".format(self.router_id, - peer.router_id, - state)) - if state == expected_state: - return - - time.sleep(interval) - count += interval - if count >= timeout: - raise Exception('timeout') - - def add_static_route(self, network, next_hop): - cmd = '/sbin/ip route add {0} via {1}'.format(network, next_hop) - self.local(cmd) - - def set_ipv6_forward(self): - cmd = 'sysctl -w net.ipv6.conf.all.forwarding=1' - self.local(cmd) - - def create_config(self): - raise Exception('implement create_config() method') - - def reload_config(self): - raise Exception('implement reload_config() method') |