summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorNaoto Hanaue <hanaue.naoto@po.ntts.co.jp>2015-09-02 17:43:39 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-09-04 22:15:12 +0900
commit03789fa0cee9a11bf272d202c74bf03f2ad0ec51 (patch)
treef6c5a5cc80b7f5df60586ea36f338c3020e170ce /test
parent52c96558a2fd993cd0ce380785740198ffa00c62 (diff)
scenario_test: add zebra test
Diffstat (limited to 'test')
-rw-r--r--test/scenario_test/bgp_zebra_test.py175
-rw-r--r--test/scenario_test/lib/base.py31
-rw-r--r--test/scenario_test/lib/gobgp.py45
-rw-r--r--test/scenario_test/lib/quagga.py29
4 files changed, 272 insertions, 8 deletions
diff --git a/test/scenario_test/bgp_zebra_test.py b/test/scenario_test/bgp_zebra_test.py
new file mode 100644
index 00000000..e8170086
--- /dev/null
+++ b/test/scenario_test/bgp_zebra_test.py
@@ -0,0 +1,175 @@
+# 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.
+
+import unittest
+from fabric.api import local
+from lib import base
+from lib.gobgp import *
+from lib.quagga import *
+import sys
+import os
+import time
+import nose
+from noseplugin import OptionParser, parser_option
+from itertools import chain
+
+class GoBGPTestBase(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ gobgp_ctn_image_name = parser_option.gobgp_image
+ base.TEST_PREFIX = parser_option.test_prefix
+
+ g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1',
+ ctn_image_name=gobgp_ctn_image_name,
+ log_level=parser_option.gobgp_log_level,
+ zebra=True)
+ q1 = QuaggaBGPContainer(name='q1', asn=65001, router_id='192.168.0.2', zebra=True)
+ o1 = QuaggaBGPContainer(name='o1', asn=65002, router_id='192.168.0.3')
+ o2 = QuaggaBGPContainer(name='o2', asn=65002, router_id='192.168.0.4')
+
+ # preparing the bridge of ipv4
+ br01v4 = Bridge(name='br01', subnet='192.168.10.0/24')
+ br02v4 = Bridge(name='br02', subnet='192.168.20.0/24')
+ br03v4 = Bridge(name='br03', subnet='192.168.30.0/24')
+
+ # preparing the bridge of ipv6
+ br01v6 = Bridge(name='br01', subnet='2001:10::/32')
+ br02v6 = Bridge(name='br02', subnet='2001:20::/32')
+ br03v6 = Bridge(name='br03', subnet='2001:30::/32')
+
+ cls.ctns = [g1, q1, o1, o2]
+ cls.gobgps = {'g1': g1}
+ cls.quaggas = {'q1': q1}
+ cls.others = {'o1': o1, 'o2': o2}
+ cls.bridges = {'ipv4': {'br01': br01v4, 'br02': br02v4, 'br03': br03v4},
+ 'ipv6': {'br01': br01v6, 'br02': br02v6, 'br03': br03v6}}
+
+ """
+ No.1 start up ipv4 containers and check state
+ each neighbor is established in ipv4 environment
+ """
+ def test_01_check_neighbor_established(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o1 = self.others['o1']
+ o2 = self.others['o2']
+
+ # start up containers of ipv4 environment
+ initial_wait_time = max(ctn.run() for ctn in self.ctns)
+ time.sleep(initial_wait_time)
+
+ # make ipv4 bridge and set ip to each container
+ [self.bridges['ipv4']['br01'].addif(ctn) for ctn in [o1, g1]]
+ [self.bridges['ipv4']['br02'].addif(ctn) for ctn in [g1, q1]]
+ [self.bridges['ipv4']['br03'].addif(ctn) for ctn in [q1, o2]]
+
+ for _, q in self.quaggas.items():
+ g1.add_peer(q)
+ q.add_peer(g1)
+
+ g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1)
+
+ """
+ No.2 check whether the ping is reachable in container
+ that have previously beyond the gobpg in ipv4 environment
+ """
+ def test_02_check_reachablily_beyond_gobgp_from_quagga(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o1 = self.others['o1']
+
+ next_hop = g1.ip_addrs[1][1].split('/')[0]
+ o1.add_static_route(self.bridges['ipv4']['br01'].subnet, next_hop)
+ q1.get_reachablily('192.168.30.2')
+
+ """
+ No.3 check whether the ping is reachable in container
+ that have previously beyond the quagga in ipv4 environment
+ """
+ def test_03_check_reachablily_beyond_quagga_from_gobgp(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o2 = self.others['o2']
+
+ next_hop = q1.ip_addrs[0][1].split('/')[0]
+ o2.add_static_route(self.bridges['ipv4']['br03'].subnet, next_hop)
+ g1.get_reachablily('192.168.10.2')
+
+ """
+ No.4 start up ipv4 containers and check state
+ each neighbor is established in ipv6 environment
+ """
+ def test_04_check_neighbor_established_v6(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o1 = self.others['o1']
+ o2 = self.others['o2']
+
+ # stop containers of ipv4 environment
+ # and start up containers of ipv6 environment
+ [ctn.stop() for ctn in self.ctns]
+ initial_wait_time = max(ctn.run() for ctn in self.ctns)
+ time.sleep(initial_wait_time)
+
+ # make ipv4 bridge and set ip to each container
+ [self.bridges['ipv6']['br01'].addif(ctn) for ctn in [o1, g1]]
+ [self.bridges['ipv6']['br02'].addif(ctn) for ctn in [g1, q1]]
+ [self.bridges['ipv6']['br03'].addif(ctn) for ctn in [q1, o2]]
+
+ for _, q in self.quaggas.items():
+ g1.add_peer(q)
+ q.add_peer(g1)
+
+ g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1)
+
+ """
+ No.5 check whether the ping is reachable in container
+ that have previously beyond the gobpg in ipv6 environment
+ """
+ def test_05_check_reachablily_beyond_gobgp_from_quagga(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o1 = self.others['o1']
+
+ next_hop = g1.ip_addrs[1][1].split('/')[0]
+ o1.add_static_route(self.bridges['ipv6']['br01'].subnet, next_hop)
+ q1.get_reachablily('2001:30::2')
+
+ """
+ No.6 check whether the ping is reachable in container
+ that have previously beyond the quagga in ipv6 environment
+ """
+ def test_06_check_reachablily_beyond_quagga_from_gobgp(self):
+ g1 = self.gobgps['g1']
+ q1 = self.quaggas['q1']
+ o2 = self.others['o2']
+
+ next_hop = q1.ip_addrs[0][1].split('/')[0]
+ o2.add_static_route(self.bridges['ipv6']['br03'].subnet, next_hop)
+ g1.get_reachablily('2001:10::2')
+
+
+if __name__ == '__main__':
+ if os.geteuid() is not 0:
+ print "you are not root."
+ sys.exit(1)
+ output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True)
+ if int(output) is not 0:
+ print "docker not found"
+ sys.exit(1)
+
+ nose.main(argv=sys.argv, addplugins=[OptionParser()],
+ defaultTest=sys.argv[0])
diff --git a/test/scenario_test/lib/base.py b/test/scenario_test/lib/base.py
index 7f73516b..42cdc0e1 100644
--- a/test/scenario_test/lib/base.py
+++ b/test/scenario_test/lib/base.py
@@ -86,6 +86,8 @@ def make_gobgp_ctn(tag='gobgp', local_gobgp_path='', from_image='golang:1.4'):
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'
+ c << 'RUN apt-get update'
+ c << 'RUN apt-get install -qy --no-install-recommends quagga telnet'
rindex = local_gobgp_path.rindex('gobgp')
if rindex < 0:
@@ -133,6 +135,7 @@ class Bridge(object):
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)
@@ -312,6 +315,30 @@ class BGPContainer(Container):
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/{0} -c 1 -w 1 {1}'.format(ping_cmd, addr)
+
+ interval = 1
+ count = 0
+ while True:
+ res = self.local(cmd, capture=True)
+ print colors.yellow(res)
+ if '0% packet loss' in res:
+ 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
@@ -329,6 +356,10 @@ class BGPContainer(Container):
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 create_config(self):
raise Exception('implement create_config() method')
diff --git a/test/scenario_test/lib/gobgp.py b/test/scenario_test/lib/gobgp.py
index 04b89ffe..f969ca14 100644
--- a/test/scenario_test/lib/gobgp.py
+++ b/test/scenario_test/lib/gobgp.py
@@ -22,23 +22,29 @@ from itertools import chain
class GoBGPContainer(BGPContainer):
SHARED_VOLUME = '/root/shared_volume'
+ QUAGGA_VOLUME = '/etc/quagga'
def __init__(self, name, asn, router_id, ctn_image_name='gobgp',
- log_level='debug'):
+ log_level='debug', zebra=False):
super(GoBGPContainer, self).__init__(name, asn, router_id,
ctn_image_name)
self.shared_volumes.append((self.config_dir, self.SHARED_VOLUME))
+
self.log_level = log_level
self.prefix_set = None
self.neighbor_set = None
self.bgp_set = None
self.default_policy = None
+ self.zebra = zebra
def _start_gobgp(self):
+ zebra_op = ''
+ if self.zebra:
+ zebra_op = '-z'
c = CmdBuffer()
c << '#!/bin/bash'
- c << '/go/bin/gobgpd -f {0}/gobgpd.conf -l {1} -p > ' \
- '{0}/gobgpd.log 2>&1'.format(self.SHARED_VOLUME, self.log_level)
+ c << '/go/bin/gobgpd -f {0}/gobgpd.conf -l {1} -p {2} > ' \
+ '{0}/gobgpd.log 2>&1'.format(self.SHARED_VOLUME, self.log_level, zebra_op)
cmd = 'echo "{0:s}" > {1}/start.sh'.format(c, self.config_dir)
local(cmd, capture=True)
@@ -46,8 +52,16 @@ class GoBGPContainer(BGPContainer):
local(cmd, capture=True)
self.local("{0}/start.sh".format(self.SHARED_VOLUME), flag='-d')
+ def _start_zebra(self):
+ cmd = 'cp {0}/zebra.conf {1}/'.format(self.SHARED_VOLUME, self.QUAGGA_VOLUME)
+ self.local(cmd)
+ cmd = '/usr/lib/quagga/zebra -f {0}/zebra.conf'.format(self.QUAGGA_VOLUME)
+ self.local(cmd, flag='-d')
+
def run(self):
super(GoBGPContainer, self).run()
+ if self.zebra:
+ self._start_zebra()
self._start_gobgp()
return self.WAIT_FOR_BOOT
@@ -152,6 +166,11 @@ class GoBGPContainer(BGPContainer):
self.bgp_set = bs
def create_config(self):
+ self._create_config_bgp()
+ if self.zebra:
+ self._create_config_zebra()
+
+ def _create_config_bgp(self):
config = {'Global': {'GlobalConfig': {'As': self.asn, 'RouterId': self.router_id}}}
for peer, info in self.peers.iteritems():
afi_safi_list = []
@@ -259,9 +278,25 @@ class GoBGPContainer(BGPContainer):
print colors.yellow(indent(toml.dumps(config)))
f.write(toml.dumps(config))
+ def _create_config_zebra(self):
+ c = CmdBuffer()
+ c << 'hostname zebra'
+ c << 'password zebra'
+ c << 'log file {0}/zebra.log'.format(self.QUAGGA_VOLUME)
+
+ with open('{0}/zebra.conf'.format(self.config_dir), 'w') as f:
+ print colors.yellow('[{0}\'s new config]'.format(self.name))
+ print colors.yellow(indent(str(c)))
+ f.writelines(str(c))
+
def reload_config(self):
- cmd = '/usr/bin/pkill gobgpd -SIGHUP'
- self.local(cmd)
+ daemon = []
+ daemon.append('gobgpd')
+ if self.zebra:
+ daemon.append('zebra')
+ for d in daemon:
+ cmd = '/usr/bin/pkill {0} -SIGHUP'.format(d)
+ self.local(cmd)
for v in self.routes.itervalues():
if v['rf'] == 'ipv4' or v['rf'] == 'ipv6':
cmd = 'gobgp global '\
diff --git a/test/scenario_test/lib/quagga.py b/test/scenario_test/lib/quagga.py
index 8d3e0612..b881f6ed 100644
--- a/test/scenario_test/lib/quagga.py
+++ b/test/scenario_test/lib/quagga.py
@@ -44,10 +44,11 @@ class QuaggaBGPContainer(BGPContainer):
WAIT_FOR_BOOT = 1
SHARED_VOLUME = '/etc/quagga'
- def __init__(self, name, asn, router_id, ctn_image_name='osrg/quagga'):
+ def __init__(self, name, asn, router_id, ctn_image_name='osrg/quagga', zebra=False):
super(QuaggaBGPContainer, self).__init__(name, asn, router_id,
ctn_image_name)
self.shared_volumes.append((self.config_dir, self.SHARED_VOLUME))
+ self.zebra = zebra
def run(self):
super(QuaggaBGPContainer, self).run()
@@ -152,6 +153,11 @@ class QuaggaBGPContainer(BGPContainer):
raise Exception('not found peer {0}'.format(peer.router_id))
def create_config(self):
+ self._create_config_bgp()
+ if self.zebra:
+ self._create_config_zebra()
+
+ def _create_config_bgp(self):
c = CmdBuffer()
c << 'hostname bgpd'
c << 'password zebra'
@@ -205,6 +211,23 @@ class QuaggaBGPContainer(BGPContainer):
print colors.yellow(indent(str(c)))
f.writelines(str(c))
+ def _create_config_zebra(self):
+ c = CmdBuffer()
+ c << 'hostname zebra'
+ c << 'password zebra'
+ c << 'log file {0}/zebra.log'.format(self.SHARED_VOLUME)
+
+ with open('{0}/zebra.conf'.format(self.config_dir), 'w') as f:
+ print colors.yellow('[{0}\'s new config]'.format(self.name))
+ print colors.yellow(indent(str(c)))
+ f.writelines(str(c))
+
def reload_config(self):
- cmd = '/usr/bin/pkill bgpd -SIGHUP'
- self.local(cmd)
+ daemon = []
+ daemon.append('bgpd')
+ if self.zebra:
+ daemon.append('zebra')
+ for d in daemon:
+ cmd = '/usr/bin/pkill {0} -SIGHUP'.format(d)
+ self.local(cmd)
+