On Thu, 13 Jul 2017 13:15:46 +0900
Takashi YAMAMOTO <yamam...@ovn.org> wrote:

> On Thu, Jul 13, 2017 at 10:00 AM, fumihiko kakuma <kak...@valinux.co.jp>
> wrote:
> 
> > On Thu, 13 Jul 2017 09:15:25 +0900
> > Takashi YAMAMOTO <yamam...@ovn.org> wrote:
> >
> > > On Thu, Jul 13, 2017 at 7:04 AM, fumihiko kakuma <kak...@valinux.co.jp>
> > > wrote:
> > >
> > > > Hi Yamamoto-San,
> > > >
> > > > On Wed, 12 Jul 2017 23:43:25 +0900
> > > > Takashi YAMAMOTO <yamam...@ovn.org> wrote:
> > > >
> > > > > this breaks openstack neutron_dynamic_routing, doesn't it?
> > > >
> > > > I thank for advice. I know that.
> > > > So as soon as the ryu version with this commit is released,
> > > > I am going to push a patch to fix a breake to neutron-dynamic-routing.
> > > >
> > >
> > > is it difficult to avoid breaking it?
> > > eg. make it try-import new and old locations.
> > >
> >
> > This change only breaks scenario tests in neutron-dynamic-routing
> > and currently they are non-voting job.
> > Don't you like it?
> >
> 
> i don't like any breaking changes.
> import errors in tempest plugins is often a disaster.
> 

Hmm, it seems not to affect other projects.
Anyway, I think this change will not be merged, as fujita-san also
don't like any breaks.

> >
> >
> > >
> > > >
> > > >
> > > > Thanks,
> > > > Kakuma
> > > >
> > > > >
> > > > > On Mon, Jul 10, 2017 at 12:51 PM, fumihiko kakuma <
> > kak...@valinux.co.jp>
> > > > > wrote:
> > > > >
> > > > > > This patch requires the v2 patch of Iwase-San.
> > > > > >
> > > > > > Signed-off-by: Fumihiko Kakuma <kak...@valinux.co.jp>
> > > > > > ---
> > > > > >  .travis.yml                                        |   2 +-
> > > > > >  ryu/lib/docker/__init__.py                         |   0
> > > > > >  ryu/lib/docker/docker_base.py                      | 801
> > > > > > +++++++++++++++++++++
> > > > > >  ryu/lib/docker/install_docker_test_pkg.sh          |  43 ++
> > > > > >  ryu/lib/docker/install_docker_test_pkg_common.sh   |  39 +
> > > > > >  .../docker/install_docker_test_pkg_for_travis.sh   |  12 +
> > > > > >  ryu/lib/docker/quagga.py                           | 332 +++++++++
> > > > > >  ryu/lib/docker/ryubgp.py                           | 212 ++++++
> > > > > >  ryu/tests/integrated/common/__init__.py            |   0
> > > > > >  ryu/tests/integrated/common/docker_base.py         | 801
> > > > > > ---------------------
> > > > > >  .../integrated/common/install_docker_test_pkg.sh   |  43 --
> > > > > >  .../common/install_docker_test_pkg_common.sh       |  39 -
> > > > > >  .../common/install_docker_test_pkg_for_travis.sh   |  12 -
> > > > > >  ryu/tests/integrated/common/quagga.py              | 332
> > ---------
> > > > > >  ryu/tests/integrated/common/ryubgp.py              | 212 ------
> > > > > >  tests/integrated/bgp/base.py                       |   6 +-
> > > > > >  tests/integrated/bgp/base_ip6.py                   |   6 +-
> > > > > >  tests/integrated/bgp/test_basic.py                 |   2 +-
> > > > > >  tests/integrated/bgp/test_ip6_basic.py             |   2 +-
> > > > > >  19 files changed, 1448 insertions(+), 1448 deletions(-)
> > > > > >  create mode 100644 ryu/lib/docker/__init__.py
> > > > > >  create mode 100644 ryu/lib/docker/docker_base.py
> > > > > >  create mode 100644 ryu/lib/docker/install_docker_test_pkg.sh
> > > > > >  create mode 100644 ryu/lib/docker/install_docker_
> > test_pkg_common.sh
> > > > > >  create mode 100644 ryu/lib/docker/install_docker_
> > > > test_pkg_for_travis.sh
> > > > > >  create mode 100644 ryu/lib/docker/quagga.py
> > > > > >  create mode 100644 ryu/lib/docker/ryubgp.py
> > > > > >  delete mode 100644 ryu/tests/integrated/common/__init__.py
> > > > > >  delete mode 100644 ryu/tests/integrated/common/docker_base.py
> > > > > >  delete mode 100644 ryu/tests/integrated/common/
> > > > install_docker_test_pkg.sh
> > > > > >  delete mode 100644 ryu/tests/integrated/common/
> > > > install_docker_test_pkg_
> > > > > > common.sh
> > > > > >  delete mode 100644 ryu/tests/integrated/common/
> > > > > > install_docker_test_pkg_for_travis.sh
> > > > > >  delete mode 100644 ryu/tests/integrated/common/quagga.py
> > > > > >  delete mode 100644 ryu/tests/integrated/common/ryubgp.py
> > > > > >
> > > > > > diff --git a/.travis.yml b/.travis.yml
> > > > > > index 9e5474a..cd35aac 100644
> > > > > > --- a/.travis.yml
> > > > > > +++ b/.travis.yml
> > > > > > @@ -16,7 +16,7 @@ sudo: required  # Required to enable Docker
> > service
> > > > > >
> > > > > >  install:
> > > > > >    - pip install tox coveralls
> > > > > > -  - bash ryu/tests/integrated/common/install_docker_test_pkg_for_
> > > > > > travis.sh
> > > > > > +  - bash ryu/lib/docker/install_docker_test_pkg_for_travis.sh
> > > > > >
> > > > > >  script:
> > > > > >    - NOSE_VERBOSE=0 tox -e $TOX_ENV
> > > > > > diff --git a/ryu/lib/docker/__init__.py
> > b/ryu/lib/docker/__init__.py
> > > > > > new file mode 100644
> > > > > > index 0000000..e69de29
> > > > > > diff --git a/ryu/lib/docker/docker_base.py
> > > > b/ryu/lib/docker/docker_base.py
> > > > > > new file mode 100644
> > > > > > index 0000000..1ae2cc2
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/docker_base.py
> > > > > > @@ -0,0 +1,801 @@
> > > > > > +# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
> > > > > > +#
> > > > > > +# This is based on the following
> > > > > > +#     https://github.com/osrg/gobgp/test/lib/base.py
> > > > > > +#
> > > > > > +# 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 __future__ import absolute_import
> > > > > > +
> > > > > > +import itertools
> > > > > > +import logging
> > > > > > +import os
> > > > > > +import subprocess
> > > > > > +import time
> > > > > > +
> > > > > > +import netaddr
> > > > > > +import six
> > > > > > +
> > > > > > +LOG = logging.getLogger(__name__)
> > > > > > +
> > > > > > +DEFAULT_TEST_PREFIX = ''
> > > > > > +DEFAULT_TEST_BASE_DIR = '/tmp/ctn_docker/bgp'
> > > > > > +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_ORIGINATOR_ID = 9
> > > > > > +BGP_ATTR_TYPE_CLUSTER_LIST = 10
> > > > > > +BGP_ATTR_TYPE_MP_REACH_NLRI = 14
> > > > > > +BGP_ATTR_TYPE_EXTENDED_COMMUNITIES = 16
> > > > > > +
> > > > > > +BRIDGE_TYPE_DOCKER = 'docker'
> > > > > > +BRIDGE_TYPE_BRCTL = 'brctl'
> > > > > > +BRIDGE_TYPE_OVS = 'ovs'
> > > > > > +
> > > > > > +
> > > > > > +class CommandError(Exception):
> > > > > > +    def __init__(self, out):
> > > > > > +        super(CommandError, self).__init__()
> > > > > > +        self.out = out
> > > > > > +
> > > > > > +
> > > > > > +def try_several_times(f, t=3, s=1):
> > > > > > +    e = RuntimeError()
> > > > > > +    for _ in range(t):
> > > > > > +        try:
> > > > > > +            r = f()
> > > > > > +        except RuntimeError as e:
> > > > > > +            time.sleep(s)
> > > > > > +        else:
> > > > > > +            return r
> > > > > > +    raise e
> > > > > > +
> > > > > > +
> > > > > > +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)
> > > > > > +
> > > > > > +
> > > > > > +class CommandOut(str):
> > > > > > +
> > > > > > +    def __new__(cls, stdout, stderr, command, returncode,
> > **kwargs):
> > > > > > +        stdout = stdout or ''
> > > > > > +        obj = super(CommandOut, cls).__new__(cls, stdout,
> > **kwargs)
> > > > > > +        obj.stderr = stderr or ''
> > > > > > +        obj.command = command
> > > > > > +        obj.returncode = returncode
> > > > > > +        return obj
> > > > > > +
> > > > > > +
> > > > > > +class Command(object):
> > > > > > +
> > > > > > +    def _execute(self, cmd, capture=False, executable=None):
> > > > > > +        """Execute a command using subprocess.Popen()
> > > > > > +        :Parameters:
> > > > > > +            - out: stdout from subprocess.Popen()
> > > > > > +              out has some attributes.
> > > > > > +              out.returncode: returncode of subprocess.Popen()
> > > > > > +              out.stderr: stderr from subprocess.Popen()
> > > > > > +        """
> > > > > > +        if capture:
> > > > > > +            p_stdout = subprocess.PIPE
> > > > > > +            p_stderr = subprocess.PIPE
> > > > > > +        else:
> > > > > > +            p_stdout = None
> > > > > > +            p_stderr = None
> > > > > > +        pop = subprocess.Popen(cmd, shell=True,
> > executable=executable,
> > > > > > +                               stdout=p_stdout,
> > > > > > +                               stderr=p_stderr)
> > > > > > +        __stdout, __stderr = pop.communicate()
> > > > > > +        _stdout = six.text_type(__stdout, 'utf-8')
> > > > > > +        _stderr = six.text_type(__stderr, 'utf-8')
> > > > > > +        out = CommandOut(_stdout, _stderr, cmd, pop.returncode)
> > > > > > +        return out
> > > > > > +
> > > > > > +    def execute(self, cmd, capture=True, try_times=1, interval=1):
> > > > > > +        out = None
> > > > > > +        for i in range(try_times):
> > > > > > +            out = self._execute(cmd, capture=capture)
> > > > > > +            LOG.info(out.command)
> > > > > > +            if out.returncode == 0:
> > > > > > +                return out
> > > > > > +            LOG.error("stdout: %s", out)
> > > > > > +            LOG.error("stderr: %s", out.stderr)
> > > > > > +            if i + 1 >= try_times:
> > > > > > +                break
> > > > > > +            time.sleep(interval)
> > > > > > +        raise CommandError(out)
> > > > > > +
> > > > > > +    def sudo(self, cmd, capture=True, try_times=1, interval=1):
> > > > > > +        cmd = 'sudo %s' % cmd
> > > > > > +        return self.execute(cmd, capture=capture,
> > > > > > +                            try_times=try_times,
> > interval=interval)
> > > > > > +
> > > > > > +
> > > > > > +class DockerImage(object):
> > > > > > +    def __init__(self, baseimage='ubuntu:16.04'):
> > > > > > +        self.baseimage = baseimage
> > > > > > +        self.cmd = Command()
> > > > > > +
> > > > > > +    def get_images(self):
> > > > > > +        out = self.cmd.sudo('sudo docker images')
> > > > > > +        images = []
> > > > > > +        for line in out.splitlines()[1:]:
> > > > > > +            images.append(line.split()[0])
> > > > > > +        return images
> > > > > > +
> > > > > > +    def exist(self, name):
> > > > > > +        return name in self.get_images()
> > > > > > +
> > > > > > +    def build(self, tagname, dockerfile_dir):
> > > > > > +        self.cmd.sudo(
> > > > > > +            "docker build -t {0} {1}".format(tagname,
> > dockerfile_dir),
> > > > > > +            try_times=3)
> > > > > > +
> > > > > > +    def remove(self, tagname, check_exist=False):
> > > > > > +        if check_exist and not self.exist(tagname):
> > > > > > +            return tagname
> > > > > > +        self.cmd.sudo("docker rmi -f %s" % tagname, try_times=3)
> > > > > > +
> > > > > > +    def create_quagga(self, tagname='quagga', image=None,
> > > > > > check_exist=False):
> > > > > > +        if check_exist and self.exist(tagname):
> > > > > > +            return tagname
> > > > > > +        workdir = os.path.join(TEST_BASE_DIR, tagname)
> > > > > > +        pkges = ' '.join([
> > > > > > +            'telnet',
> > > > > > +            'tcpdump',
> > > > > > +            'quagga',
> > > > > > +        ])
> > > > > > +        if image:
> > > > > > +            use_image = image
> > > > > > +        else:
> > > > > > +            use_image = self.baseimage
> > > > > > +        c = CmdBuffer()
> > > > > > +        c << 'FROM %s' % use_image
> > > > > > +        c << 'RUN apt-get update'
> > > > > > +        c << 'RUN apt-get install -qy --no-install-recommends %s'
> > %
> > > > pkges
> > > > > > +        c << 'CMD /usr/lib/quagga/bgpd'
> > > > > > +
> > > > > > +        self.cmd.sudo('rm -rf %s' % workdir)
> > > > > > +        self.cmd.execute('mkdir -p %s' % workdir)
> > > > > > +        self.cmd.execute("echo '%s' > %s/Dockerfile" % (str(c),
> > > > workdir))
> > > > > > +        self.build(tagname, workdir)
> > > > > > +        return tagname
> > > > > > +
> > > > > > +    def create_ryu(self, tagname='ryu', image=None,
> > > > check_exist=False):
> > > > > > +        if check_exist and self.exist(tagname):
> > > > > > +            return tagname
> > > > > > +        workdir = os.path.join(TEST_BASE_DIR, tagname)
> > > > > > +        workdir_ctn = '/root/osrg/ryu'
> > > > > > +        pkges = ' '.join([
> > > > > > +            'tcpdump',
> > > > > > +            'iproute2',
> > > > > > +        ])
> > > > > > +        if image:
> > > > > > +            use_image = image
> > > > > > +        else:
> > > > > > +            use_image = self.baseimage
> > > > > > +        c = CmdBuffer()
> > > > > > +        c << 'FROM %s' % use_image
> > > > > > +        c << 'ADD ryu %s' % workdir_ctn
> > > > > > +        install = ' '.join([
> > > > > > +            'RUN apt-get update',
> > > > > > +            '&& apt-get install -qy --no-install-recommends %s' %
> > > > pkges,
> > > > > > +            '&& cd %s' % workdir_ctn,
> > > > > > +            # Note: Clean previous builds, because "python
> > setup.py
> > > > > > install"
> > > > > > +            # might fail if the current directory contains the
> > > > symlink to
> > > > > > +            # Docker host file systems.
> > > > > > +            '&& rm -rf *.egg-info/ build/ dist/ .tox/ *.log'
> > > > > > +            '&& pip install -r tools/pip-requires -r
> > > > > > tools/optional-requires',
> > > > > > +            '&& python setup.py install',
> > > > > > +        ])
> > > > > > +        c << install
> > > > > > +
> > > > > > +        self.cmd.sudo('rm -rf %s' % workdir)
> > > > > > +        self.cmd.execute('mkdir -p %s' % workdir)
> > > > > > +        self.cmd.execute("echo '%s' > %s/Dockerfile" % (str(c),
> > > > workdir))
> > > > > > +        self.cmd.execute('cp -r ../ryu %s/' % workdir)
> > > > > > +        self.build(tagname, workdir)
> > > > > > +        return tagname
> > > > > > +
> > > > > > +
> > > > > > +class Bridge(object):
> > > > > > +    def __init__(self, name, subnet='', start_ip=None,
> > end_ip=None,
> > > > > > +                 with_ip=True, self_ip=False,
> > > > > > +                 fixed_ip=None, reuse=False,
> > > > > > +                 br_type='docker'):
> > > > > > +        """Manage a bridge
> > > > > > +        :Parameters:
> > > > > > +            - name: bridge name
> > > > > > +            - subnet: network cider to be used in this bridge
> > > > > > +            - start_ip: start address of an ip to be used in the
> > > > subnet
> > > > > > +            - end_ip: end address of an ip to be used in the
> > subnet
> > > > > > +            - with_ip: specify if assign automatically an ip
> > address
> > > > > > +            - self_ip: specify if assign an ip address for the
> > bridge
> > > > > > +            - fixed_ip: an ip address to be assigned to the bridge
> > > > > > +            - reuse: specify if use an existing bridge
> > > > > > +            - br_type: One either in a 'docker', 'brctl' or 'ovs'
> > > > > > +        """
> > > > > > +        self.cmd = Command()
> > > > > > +        self.name = name
> > > > > > +        if br_type not in (BRIDGE_TYPE_DOCKER, BRIDGE_TYPE_BRCTL,
> > > > > > +                           BRIDGE_TYPE_OVS):
> > > > > > +            raise Exception("argument error br_type: %s" %
> > br_type)
> > > > > > +        self.br_type = br_type
> > > > > > +        self.docker_nw = bool(self.br_type == BRIDGE_TYPE_DOCKER)
> > > > > > +        if TEST_PREFIX != '':
> > > > > > +            self.name = '{0}_{1}'.format(TEST_PREFIX, name)
> > > > > > +        self.with_ip = with_ip
> > > > > > +        if with_ip:
> > > > > > +            self.subnet = netaddr.IPNetwork(subnet)
> > > > > > +            if start_ip:
> > > > > > +                self.start_ip = start_ip
> > > > > > +            else:
> > > > > > +                self.start_ip = netaddr.IPAddress(self.subnet.
> > first)
> > > > > > +            if end_ip:
> > > > > > +                self.end_ip = end_ip
> > > > > > +            else:
> > > > > > +                self.end_ip = netaddr.IPAddress(self.subnet.last)
> > > > > > +
> > > > > > +            def _ip_gen():
> > > > > > +                for host in netaddr.IPRange(self.start_ip,
> > > > self.end_ip):
> > > > > > +                    yield host
> > > > > > +            self._ip_generator = _ip_gen()
> > > > > > +            # throw away first network address
> > > > > > +            self.next_ip_address()
> > > > > > +
> > > > > > +        self.self_ip = self_ip
> > > > > > +        if fixed_ip:
> > > > > > +            self.ip_addr = fixed_ip
> > > > > > +        else:
> > > > > > +            self.ip_addr = self.next_ip_address()
> > > > > > +        if not reuse:
> > > > > > +            def f():
> > > > > > +                if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > +                    gw = "--gateway %s" %
> > self.ip_addr.split('/')[0]
> > > > > > +                    v6 = ''
> > > > > > +                    if self.subnet.version == 6:
> > > > > > +                        v6 = '--ipv6'
> > > > > > +                    cmd = ("docker network create --driver bridge
> > %s "
> > > > > > +                           "%s --subnet %s %s" % (v6, gw, subnet,
> > > > > > self.name))
> > > > > > +                elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > +                    cmd = "ip link add {0} type bridge".format(
> > > > self.name)
> > > > > > +                elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > +                    cmd = "ovs-vsctl add-br {0}".format(self.name
> > )
> > > > > > +                else:
> > > > > > +                    raise ValueError('Unsupported br_type: %s' %
> > > > > > self.br_type)
> > > > > > +                self.delete()
> > > > > > +                self.execute(cmd, sudo=True, retry=True)
> > > > > > +            try_several_times(f)
> > > > > > +        if not self.docker_nw:
> > > > > > +            self.execute("ip link set up dev {0}".format(
> > self.name),
> > > > > > +                         sudo=True, retry=True)
> > > > > > +
> > > > > > +        if not self.docker_nw and self_ip:
> > > > > > +            ips = self.check_br_addr(self.name)
> > > > > > +            for key, ip in ips.items():
> > > > > > +                if self.subnet.version == key:
> > > > > > +                    self.execute(
> > > > > > +                        "ip addr del {0} dev {1}".format(ip,
> > > > self.name),
> > > > > > +                        sudo=True, retry=True)
> > > > > > +            self.execute(
> > > > > > +                "ip addr add {0} dev {1}".format(self.ip_addr,
> > > > self.name
> > > > > > ),
> > > > > > +                sudo=True, retry=True)
> > > > > > +        self.ctns = []
> > > > > > +
> > > > > > +    def get_bridges_dc(self):
> > > > > > +        out = self.execute('docker network ls', sudo=True,
> > retry=True)
> > > > > > +        bridges = []
> > > > > > +        for line in out.splitlines()[1:]:
> > > > > > +            bridges.append(line.split()[1])
> > > > > > +        return bridges
> > > > > > +
> > > > > > +    def get_bridges_brctl(self):
> > > > > > +        out = self.execute('brctl show', retry=True)
> > > > > > +        bridges = []
> > > > > > +        for line in out.splitlines()[1:]:
> > > > > > +            bridges.append(line.split()[0])
> > > > > > +        return bridges
> > > > > > +
> > > > > > +    def get_bridges_ovs(self):
> > > > > > +        out = self.execute('ovs-vsctl list-br', sudo=True,
> > retry=True)
> > > > > > +        return out.splitlines()
> > > > > > +
> > > > > > +    def get_bridges(self):
> > > > > > +        if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > +            return self.get_bridges_dc()
> > > > > > +        elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > +            return self.get_bridges_brctl()
> > > > > > +        elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > +            return self.get_bridges_ovs()
> > > > > > +
> > > > > > +    def exist(self):
> > > > > > +        return self.name in self.get_bridges()
> > > > > > +
> > > > > > +    def execute(self, cmd, capture=True, sudo=False, retry=False):
> > > > > > +        if sudo:
> > > > > > +            m = self.cmd.sudo
> > > > > > +        else:
> > > > > > +            m = self.cmd.execute
> > > > > > +        if retry:
> > > > > > +            return m(cmd, capture=capture, try_times=3,
> > interval=1)
> > > > > > +        else:
> > > > > > +            return m(cmd, capture=capture)
> > > > > > +
> > > > > > +    def check_br_addr(self, br):
> > > > > > +        ips = {}
> > > > > > +        cmd = "ip a show dev %s" % br
> > > > > > +        for line in self.execute(cmd, sudo=True).split('\n'):
> > > > > > +            if line.strip().startswith("inet "):
> > > > > > +                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > +                ips[4] = elems[1]
> > > > > > +            elif line.strip().startswith("inet6 "):
> > > > > > +                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > +                ips[6] = elems[1]
> > > > > > +        return ips
> > > > > > +
> > > > > > +    def next_ip_address(self):
> > > > > > +        return "{0}/{1}".format(next(self._ip_generator),
> > > > > > +                                self.subnet.prefixlen)
> > > > > > +
> > > > > > +    def addif(self, ctn):
> > > > > > +        name = ctn.next_if_name()
> > > > > > +        self.ctns.append(ctn)
> > > > > > +        ip_address = None
> > > > > > +        if self.docker_nw:
> > > > > > +            ipv4 = None
> > > > > > +            ipv6 = None
> > > > > > +            ip_address = self.next_ip_address()
> > > > > > +            ip_address_ip = ip_address.split('/')[0]
> > > > > > +            version = 4
> > > > > > +            if netaddr.IPNetwork(ip_address).version == 6:
> > > > > > +                version = 6
> > > > > > +            opt_ip = "--ip %s" % ip_address_ip
> > > > > > +            if version == 4:
> > > > > > +                ipv4 = ip_address
> > > > > > +            else:
> > > > > > +                opt_ip = "--ip6 %s" % ip_address_ip
> > > > > > +                ipv6 = ip_address
> > > > > > +            cmd = "docker network connect %s %s %s" % (
> > > > > > +                opt_ip, self.name, ctn.docker_name())
> > > > > > +            self.execute(cmd, sudo=True)
> > > > > > +            ctn.set_addr_info(bridge=self.name, ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > +                              ifname=name)
> > > > > > +        else:
> > > > > > +            if self.with_ip:
> > > > > > +                ip_address = self.next_ip_address()
> > > > > > +                version = 4
> > > > > > +                if netaddr.IPNetwork(ip_address).version == 6:
> > > > > > +                    version = 6
> > > > > > +                ctn.pipework(self, ip_address, name,
> > version=version)
> > > > > > +            else:
> > > > > > +                ctn.pipework(self, '0/0', name)
> > > > > > +        return ip_address
> > > > > > +
> > > > > > +    def delete(self, check_exist=True):
> > > > > > +        if check_exist:
> > > > > > +            if not self.exist():
> > > > > > +                return
> > > > > > +        if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > +            self.execute("docker network rm %s" % self.name,
> > > > > > +                         sudo=True, retry=True)
> > > > > > +        elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > +            self.execute("ip link set down dev %s" % self.name,
> > > > > > +                         sudo=True, retry=True)
> > > > > > +            self.execute(
> > > > > > +                "ip link delete %s type bridge" % self.name,
> > > > > > +                sudo=True, retry=True)
> > > > > > +        elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > +            self.execute(
> > > > > > +                "ovs-vsctl del-br %s" % self.name,
> > > > > > +                sudo=True, retry=True)
> > > > > > +
> > > > > > +
> > > > > > +class Container(object):
> > > > > > +    def __init__(self, name, image=None):
> > > > > > +        self.name = name
> > > > > > +        self.image = image
> > > > > > +        self.shared_volumes = []
> > > > > > +        self.ip_addrs = []
> > > > > > +        self.ip6_addrs = []
> > > > > > +        self.is_running = False
> > > > > > +        self.eths = []
> > > > > > +        self.id = None
> > > > > > +
> > > > > > +        self.cmd = Command()
> > > > > > +        self.remove()
> > > > > > +
> > > > > > +    def docker_name(self):
> > > > > > +        if TEST_PREFIX == DEFAULT_TEST_PREFIX:
> > > > > > +            return self.name
> > > > > > +        return '{0}_{1}'.format(TEST_PREFIX, self.name)
> > > > > > +
> > > > > > +    def get_docker_id(self):
> > > > > > +        if self.id:
> > > > > > +            return self.id
> > > > > > +        else:
> > > > > > +            return self.docker_name()
> > > > > > +
> > > > > > +    def next_if_name(self):
> > > > > > +        name = 'eth{0}'.format(len(self.eths) + 1)
> > > > > > +        self.eths.append(name)
> > > > > > +        return name
> > > > > > +
> > > > > > +    def set_addr_info(self, bridge, ipv4=None, ipv6=None,
> > > > ifname='eth0'):
> > > > > > +        if ipv4:
> > > > > > +            self.ip_addrs.append((ifname, ipv4, bridge))
> > > > > > +        if ipv6:
> > > > > > +            self.ip6_addrs.append((ifname, ipv6, bridge))
> > > > > > +
> > > > > > +    def get_addr_info(self, bridge, ipv=4):
> > > > > > +        addrinfo = {}
> > > > > > +        if ipv == 4:
> > > > > > +            ip_addrs = self.ip_addrs
> > > > > > +        elif ipv == 6:
> > > > > > +            ip_addrs = self.ip6_addrs
> > > > > > +        else:
> > > > > > +            return None
> > > > > > +        for addr in ip_addrs:
> > > > > > +            if addr[2] == bridge:
> > > > > > +                addrinfo[addr[1]] = addr[0]
> > > > > > +        return addrinfo
> > > > > > +
> > > > > > +    def execute(self, cmd, capture=True, sudo=False, retry=False):
> > > > > > +        if sudo:
> > > > > > +            m = self.cmd.sudo
> > > > > > +        else:
> > > > > > +            m = self.cmd.execute
> > > > > > +        if retry:
> > > > > > +            return m(cmd, capture=capture, try_times=3,
> > interval=1)
> > > > > > +        else:
> > > > > > +            return m(cmd, capture=capture)
> > > > > > +
> > > > > > +    def dcexec(self, cmd, capture=True, retry=False):
> > > > > > +        if retry:
> > > > > > +            return self.cmd.sudo(cmd, capture=capture,
> > try_times=3,
> > > > > > interval=1)
> > > > > > +        else:
> > > > > > +            return self.cmd.sudo(cmd, capture=capture)
> > > > > > +
> > > > > > +    def exec_on_ctn(self, cmd, capture=True, detach=False):
> > > > > > +        name = self.docker_name()
> > > > > > +        flag = '-d' if detach else ''
> > > > > > +        return self.dcexec('docker exec {0} {1} {2}'.format(
> > > > > > +            flag, name, cmd), capture=capture)
> > > > > > +
> > > > > > +    def get_containers(self, allctn=False):
> > > > > > +        cmd = 'docker ps --no-trunc=true'
> > > > > > +        if allctn:
> > > > > > +            cmd += ' --all=true'
> > > > > > +        out = self.dcexec(cmd, retry=True)
> > > > > > +        containers = []
> > > > > > +        for line in out.splitlines()[1:]:
> > > > > > +            containers.append(line.split()[-1])
> > > > > > +        return containers
> > > > > > +
> > > > > > +    def exist(self, allctn=False):
> > > > > > +        return self.docker_name() in self.get_containers(allctn=
> > > > allctn)
> > > > > > +
> > > > > > +    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} --hostname {0} -id
> > > > {1}".format(self.docker_name()
> > > > > > ,
> > > > > > +
> > self.image)
> > > > > > +        self.id = self.dcexec(str(c), retry=True)
> > > > > > +        self.is_running = True
> > > > > > +        self.exec_on_ctn("ip li set up dev lo")
> > > > > > +        ipv4 = None
> > > > > > +        ipv6 = None
> > > > > > +        for line in self.exec_on_ctn("ip a show dev
> > > > eth0").split('\n'):
> > > > > > +            if line.strip().startswith("inet "):
> > > > > > +                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > +                ipv4 = elems[1]
> > > > > > +            elif line.strip().startswith("inet6 "):
> > > > > > +                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > +                ipv6 = elems[1]
> > > > > > +        self.set_addr_info(bridge='docker0', ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > +                           ifname='eth0')
> > > > > > +        return 0
> > > > > > +
> > > > > > +    def stop(self, check_exist=True):
> > > > > > +        if check_exist:
> > > > > > +            if not self.exist(allctn=False):
> > > > > > +                return
> > > > > > +        ctn_id = self.get_docker_id()
> > > > > > +        out = self.dcexec('docker stop -t 0 %s' % ctn_id,
> > retry=True)
> > > > > > +        self.is_running = False
> > > > > > +        return out
> > > > > > +
> > > > > > +    def remove(self, check_exist=True):
> > > > > > +        if check_exist:
> > > > > > +            if not self.exist(allctn=True):
> > > > > > +                return
> > > > > > +        ctn_id = self.get_docker_id()
> > > > > > +        out = self.dcexec('docker rm -f %s' % ctn_id, retry=True)
> > > > > > +        self.is_running = False
> > > > > > +        return out
> > > > > > +
> > > > > > +    def pipework(self, bridge, ip_addr, intf_name="", version=4):
> > > > > > +        if not self.is_running:
> > > > > > +            LOG.warning('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"
> > > > > > +        ipv4 = None
> > > > > > +        ipv6 = None
> > > > > > +        if version == 4:
> > > > > > +            ipv4 = ip_addr
> > > > > > +        else:
> > > > > > +            c << '-a 6'
> > > > > > +            ipv6 = ip_addr
> > > > > > +        c << "{0} {1}".format(self.docker_name(), ip_addr)
> > > > > > +        self.set_addr_info(bridge=bridge.name, ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > +                           ifname=intf_name)
> > > > > > +        self.execute(str(c), sudo=True, retry=True)
> > > > > > +
> > > > > > +    def get_pid(self):
> > > > > > +        if self.is_running:
> > > > > > +            cmd = "docker inspect -f '{{.State.Pid}}' %s" %
> > > > > > self.docker_name()
> > > > > > +            return int(self.dcexec(cmd))
> > > > > > +        return -1
> > > > > > +
> > > > > > +    def start_tcpdump(self, interface=None, filename=None):
> > > > > > +        if not interface:
> > > > > > +            interface = "eth0"
> > > > > > +        if not filename:
> > > > > > +            filename = "{0}/{1}.dump".format(
> > > > > > +                self.shared_volumes[0][1], interface)
> > > > > > +        self.exec_on_ctn(
> > > > > > +            "tcpdump -i {0} -w {1}".format(interface, filename),
> > > > > > +            detach=True)
> > > > > > +
> > > > > > +
> > > > > > +class BGPContainer(Container):
> > > > > > +
> > > > > > +    WAIT_FOR_BOOT = 1
> > > > > > +    RETRY_INTERVAL = 5
> > > > > > +    DEFAULT_PEER_ARG = {'neigh_addr': '',
> > > > > > +                        'passwd': None,
> > > > > > +                        'vpn': False,
> > > > > > +                        'flowspec': False,
> > > > > > +                        'is_rs_client': False,
> > > > > > +                        'is_rr_client': False,
> > > > > > +                        'cluster_id': None,
> > > > > > +                        'policies': None,
> > > > > > +                        'passive': False,
> > > > > > +                        'local_addr': '',
> > > > > > +                        'as2': False,
> > > > > > +                        'graceful_restart': None,
> > > > > > +                        'local_as': None,
> > > > > > +                        'prefix_limit': None}
> > > > > > +    default_peer_keys = sorted(DEFAULT_PEER_ARG.keys())
> > > > > > +    DEFAULT_ROUTE_ARG = {'prefix': None,
> > > > > > +                         'rf': 'ipv4',
> > > > > > +                         'attr': None,
> > > > > > +                         'next-hop': None,
> > > > > > +                         'as-path': None,
> > > > > > +                         'community': None,
> > > > > > +                         'med': None,
> > > > > > +                         'local-pref': None,
> > > > > > +                         'extended-community': None,
> > > > > > +                         'matchs': None,
> > > > > > +                         'thens': None}
> > > > > > +    default_route_keys = sorted(DEFAULT_ROUTE_ARG.keys())
> > > > > > +
> > > > > > +    def __init__(self, name, asn, router_id, ctn_image_name=None):
> > > > > > +        self.config_dir = TEST_BASE_DIR
> > > > > > +        if TEST_PREFIX:
> > > > > > +            self.config_dir = os.path.join(self.config_dir,
> > > > TEST_PREFIX)
> > > > > > +        self.config_dir = os.path.join(self.config_dir, name)
> > > > > > +        self.asn = asn
> > > > > > +        self.router_id = router_id
> > > > > > +        self.peers = {}
> > > > > > +        self.routes = {}
> > > > > > +        self.policies = {}
> > > > > > +        super(BGPContainer, self).__init__(name, ctn_image_name)
> > > > > > +        self.execute(
> > > > > > +            'rm -rf {0}'.format(self.config_dir), sudo=True)
> > > > > > +        self.execute('mkdir -p {0}'.format(self.config_dir))
> > > > > > +        self.execute('chmod 777 {0}'.format(self.config_dir))
> > > > > > +
> > > > > > +    def __repr__(self):
> > > > > > +        return str({'name': self.name, 'asn': self.asn,
> > > > > > +                    'router_id': self.router_id})
> > > > > > +
> > > > > > +    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > +        self.create_config()
> > > > > > +        super(BGPContainer, self).run()
> > > > > > +        if wait:
> > > > > > +            time.sleep(w_time)
> > > > > > +        return w_time
> > > > > > +
> > > > > > +    def add_peer(self, peer, bridge='', reload_config=True,
> > v6=False,
> > > > > > +                 peer_info=None):
> > > > > > +        peer_info = peer_info or {}
> > > > > > +        self.peers[peer] = self.DEFAULT_PEER_ARG.copy()
> > > > > > +        self.peers[peer].update(peer_info)
> > > > > > +        peer_keys = sorted(self.peers[peer].keys())
> > > > > > +        if peer_keys != self.default_peer_keys:
> > > > > > +            raise Exception("argument error peer_info: %s" %
> > > > peer_info)
> > > > > > +
> > > > > > +        neigh_addr = ''
> > > > > > +        local_addr = ''
> > > > > > +        it = itertools.product(self.ip_addrs, peer.ip_addrs)
> > > > > > +        if v6:
> > > > > > +            it = itertools.product(self.ip6_addrs,
> > peer.ip6_addrs)
> > > > > > +
> > > > > > +        for me, you in it:
> > > > > > +            if bridge != '' and bridge != me[2]:
> > > > > > +                continue
> > > > > > +            if me[2] == you[2]:
> > > > > > +                neigh_addr = you[1]
> > > > > > +                local_addr = me[1]
> > > > > > +                if v6:
> > > > > > +                    addr, mask = local_addr.split('/')
> > > > > > +                    local_addr = "{0}%{1}/{2}".format(addr, me[0],
> > > > mask)
> > > > > > +                break
> > > > > > +
> > > > > > +        if neigh_addr == '':
> > > > > > +            raise Exception('peer {0} seems not ip
> > > > > > reachable'.format(peer))
> > > > > > +
> > > > > > +        if not self.peers[peer]['policies']:
> > > > > > +            self.peers[peer]['policies'] = {}
> > > > > > +
> > > > > > +        self.peers[peer]['neigh_addr'] = neigh_addr
> > > > > > +        self.peers[peer]['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 NotImplementedError()
> > > > > > +
> > > > > > +    def enable_peer(self, peer):
> > > > > > +        raise NotImplementedError()
> > > > > > +
> > > > > > +    def log(self):
> > > > > > +        return self.execute('cat {0}/*.log'.format(self.config_
> > dir))
> > > > > > +
> > > > > > +    def add_route(self, route, reload_config=True,
> > route_info=None):
> > > > > > +        route_info = route_info or {}
> > > > > > +        self.routes[route] = self.DEFAULT_ROUTE_ARG.copy()
> > > > > > +        self.routes[route].update(route_info)
> > > > > > +        route_keys = sorted(self.routes[route].keys())
> > > > > > +        if route_keys != self.default_route_keys:
> > > > > > +            raise Exception("argument error route_info: %s" %
> > > > route_info)
> > > > > > +        self.routes[route]['prefix'] = route
> > > > > > +        if self.is_running and reload_config:
> > > > > > +            self.create_config()
> > > > > > +            self.reload_config()
> > > > > > +
> > > > > > +    def add_policy(self, policy, peer, typ, default='accept',
> > > > > > +                   reload_config=True):
> > > > > > +        self.set_default_policy(peer, typ, default)
> > > > > > +        self.define_policy(policy)
> > > > > > +        self.assign_policy(peer, policy, typ)
> > > > > > +        if self.is_running and reload_config:
> > > > > > +            self.create_config()
> > > > > > +            self.reload_config()
> > > > > > +
> > > > > > +    def set_default_policy(self, peer, typ, default):
> > > > > > +        if (typ in ['in', 'out', 'import', 'export'] and
> > > > > > +                default in ['reject', 'accept']):
> > > > > > +            if 'default-policy' not in self.peers[peer]:
> > > > > > +                self.peers[peer]['default-policy'] = {}
> > > > > > +            self.peers[peer]['default-policy'][typ] = default
> > > > > > +        else:
> > > > > > +            raise Exception('wrong type or default')
> > > > > > +
> > > > > > +    def define_policy(self, policy):
> > > > > > +        self.policies[policy['name']] = policy
> > > > > > +
> > > > > > +    def assign_policy(self, peer, policy, typ):
> > > > > > +        if peer not in self.peers:
> > > > > > +            raise Exception('peer {0} not found'.format(peer.name
> > ))
> > > > > > +        name = policy['name']
> > > > > > +        if name not in self.policies:
> > > > > > +            raise Exception('policy {0} not found'.format(name))
> > > > > > +        self.peers[peer]['policies'][typ] = policy
> > > > > > +
> > > > > > +    def get_local_rib(self, peer, rf):
> > > > > > +        raise NotImplementedError()
> > > > > > +
> > > > > > +    def get_global_rib(self, rf):
> > > > > > +        raise NotImplementedError()
> > > > > > +
> > > > > > +    def get_neighbor_state(self, peer_id):
> > > > > > +        raise NotImplementedError()
> > > > > > +
> > > > > > +    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.exec_on_ctn(cmd)
> > > > > > +            LOG.info(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)
> > > > > > +            LOG.info("%s's peer %s state: %s",
> > > > > > +                     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.exec_on_ctn(cmd)
> > > > > > +
> > > > > > +    def set_ipv6_forward(self):
> > > > > > +        cmd = 'sysctl -w net.ipv6.conf.all.forwarding=1'
> > > > > > +        self.exec_on_ctn(cmd)
> > > > > > +
> > > > > > +    def create_config(self):
> > > > > > +        raise NotImplementedError()
> > > > > > +
> > > > > > +    def reload_config(self):
> > > > > > +        raise NotImplementedError()
> > > > > > diff --git a/ryu/lib/docker/install_docker_test_pkg.sh
> > > > > > b/ryu/lib/docker/install_docker_test_pkg.sh
> > > > > > new file mode 100644
> > > > > > index 0000000..a771dfc
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/install_docker_test_pkg.sh
> > > > > > @@ -0,0 +1,43 @@
> > > > > > +#!/bin/bash
> > > > > > +set -ex
> > > > > > +
> > > > > > +RYU_PATH=`dirname $0`
> > > > > > +
> > > > > > +source  ${RYU_PATH}/install_docker_test_pkg_common.sh
> > > > > > +
> > > > > > +function add_docker_aptline {
> > > > > > +    sudo apt-get update
> > > > > > +    if ! apt-cache search docker-engine | grep docker-engine; then
> > > > > > +        VER=`lsb_release -r`
> > > > > > +        if echo $VER | grep 12.04; then
> > > > > > +            REL_NAME=precise
> > > > > > +        elif echo $VER | grep 14.04; then
> > > > > > +            REL_NAME=trusty
> > > > > > +        elif echo $VER | grep 15.10; then
> > > > > > +            REL_NAME=wily
> > > > > > +        elif echo $VER | grep 16.04; then
> > > > > > +            REL_NAME=xenial
> > > > > > +        else
> > > > > > +            retrun 1
> > > > > > +        fi
> > > > > > +        RELEASE=ubuntu-$REL_NAME
> > > > > > +        sudo apt-key adv --keyserver
> > hkp://p80.pool.sks-keyservers.
> > > > net:80
> > > > > > --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
> > > > > > +        sudo sh -c "echo deb https://apt.dockerproject.org/repo
> > > > $RELEASE
> > > > > > main > /etc/apt/sources.list.d/docker.list"
> > > > > > +    fi
> > > > > > +}
> > > > > > +
> > > > > > +init_variables
> > > > > > +process_options "$@"
> > > > > > +
> > > > > > +if [ $APTLINE_DOCKER -eq 1 ]; then
> > > > > > +    add_docker_aptline
> > > > > > +fi
> > > > > > +
> > > > > > +sudo apt-get update
> > > > > > +if apt-cache search docker-engine | grep docker-engine; then
> > > > > > +    DOCKER_PKG=docker-engine
> > > > > > +else
> > > > > > +    DOCKER_PKG=docker.io
> > > > > > +fi
> > > > > > +sudo apt-get install -y $DOCKER_PKG
> > > > > > +install_depends_pkg
> > > > > > diff --git a/ryu/lib/docker/install_docker_test_pkg_common.sh
> > > > > > b/ryu/lib/docker/install_docker_test_pkg_common.sh
> > > > > > new file mode 100644
> > > > > > index 0000000..44a3e10
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/install_docker_test_pkg_common.sh
> > > > > > @@ -0,0 +1,39 @@
> > > > > > +#!/bin/bash
> > > > > > +set -ex
> > > > > > +
> > > > > > +function init_variables {
> > > > > > +    APTLINE_DOCKER=0
> > > > > > +    DIR_BASE=/tmp
> > > > > > +}
> > > > > > +
> > > > > > +function process_options {
> > > > > > +    local max
> > > > > > +    local i
> > > > > > +    max=$#
> > > > > > +    i=1
> > > > > > +    while [ $i -le $max ]; do
> > > > > > +        case "$1" in
> > > > > > +            -a|--add-docker-aptline)
> > > > > > +                APTLINE_DOCKER=1
> > > > > > +                ;;
> > > > > > +            -d|--download-dir)
> > > > > > +                shift; ((i++))
> > > > > > +                DIR_BASE=$1
> > > > > > +                ;;
> > > > > > +        esac
> > > > > > +        shift; ((i++))
> > > > > > +    done
> > > > > > +}
> > > > > > +
> > > > > > +function install_pipework {
> > > > > > +    if ! which /usr/local/bin/pipework >/dev/null
> > > > > > +    then
> > > > > > +        sudo rm -rf $DIR_BASE/pipework
> > > > > > +        git clone https://github.com/jpetazzo/pipework.git
> > > > > > $DIR_BASE/pipework
> > > > > > +        sudo install -m 0755 $DIR_BASE/pipework/pipework
> > > > > > /usr/local/bin/pipework
> > > > > > +    fi
> > > > > > +}
> > > > > > +
> > > > > > +function install_depends_pkg {
> > > > > > +    install_pipework
> > > > > > +}
> > > > > > diff --git a/ryu/lib/docker/install_docker_test_pkg_for_travis.sh
> > > > > > b/ryu/lib/docker/install_docker_test_pkg_for_travis.sh
> > > > > > new file mode 100644
> > > > > > index 0000000..d8c3b49
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/install_docker_test_pkg_for_travis.sh
> > > > > > @@ -0,0 +1,12 @@
> > > > > > +#!/bin/bash
> > > > > > +set -ex
> > > > > > +
> > > > > > +RYU_PATH=`dirname $0`
> > > > > > +
> > > > > > +source  ${RYU_PATH}/install_docker_test_pkg_common.sh
> > > > > > +
> > > > > > +init_variables
> > > > > > +process_options "$@"
> > > > > > +
> > > > > > +sudo apt-get update
> > > > > > +install_depends_pkg
> > > > > > diff --git a/ryu/lib/docker/quagga.py b/ryu/lib/docker/quagga.py
> > > > > > new file mode 100644
> > > > > > index 0000000..9b6d218
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/quagga.py
> > > > > > @@ -0,0 +1,332 @@
> > > > > > +# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
> > > > > > +#
> > > > > > +# This is based on the following
> > > > > > +#     https://github.com/osrg/gobgp/test/lib/quagga.py
> > > > > > +#
> > > > > > +# 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 __future__ import absolute_import
> > > > > > +
> > > > > > +import logging
> > > > > > +import os
> > > > > > +
> > > > > > +import netaddr
> > > > > > +
> > > > > > +from . import docker_base as base
> > > > > > +
> > > > > > +LOG = logging.getLogger(__name__)
> > > > > > +
> > > > > > +
> > > > > > +class QuaggaBGPContainer(base.BGPContainer):
> > > > > > +
> > > > > > +    WAIT_FOR_BOOT = 1
> > > > > > +    SHARED_VOLUME = '/etc/quagga'
> > > > > > +
> > > > > > +    def __init__(self, name, asn, router_id, ctn_image_name,
> > > > 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
> > > > > > +        self._create_config_debian()
> > > > > > +
> > > > > > +    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > +        w_time = super(QuaggaBGPContainer,
> > > > > > +                       self).run(wait=wait,
> > w_time=self.WAIT_FOR_BOOT)
> > > > > > +        return w_time
> > > > > > +
> > > > > > +    def get_global_rib(self, prefix='', rf='ipv4'):
> > > > > > +        rib = []
> > > > > > +        if prefix != '':
> > > > > > +            return self.get_global_rib_with_prefix(prefix, rf)
> > > > > > +
> > > > > > +        out = self.vtysh('show bgp {0} unicast'.format(rf),
> > > > config=False)
> > > > > > +        if out.startswith('No BGP network exists'):
> > > > > > +            return rib
> > > > > > +
> > > > > > +        read_next = False
> > > > > > +
> > > > > > +        for line in out.split('\n'):
> > > > > > +            ibgp = False
> > > > > > +            if line[:2] == '*>':
> > > > > > +                line = line[2:]
> > > > > > +                if line[0] == 'i':
> > > > > > +                    line = line[1:]
> > > > > > +                    ibgp = True
> > > > > > +            elif not read_next:
> > > > > > +                continue
> > > > > > +
> > > > > > +            elems = line.split()
> > > > > > +
> > > > > > +            if len(elems) == 1:
> > > > > > +                read_next = True
> > > > > > +                prefix = elems[0]
> > > > > > +                continue
> > > > > > +            elif read_next:
> > > > > > +                nexthop = elems[0]
> > > > > > +            else:
> > > > > > +                prefix = elems[0]
> > > > > > +                nexthop = elems[1]
> > > > > > +            read_next = False
> > > > > > +
> > > > > > +            rib.append({'prefix': prefix, 'nexthop': nexthop,
> > > > > > +                        'ibgp': ibgp})
> > > > > > +
> > > > > > +        return rib
> > > > > > +
> > > > > > +    def get_global_rib_with_prefix(self, prefix, rf):
> > > > > > +        rib = []
> > > > > > +
> > > > > > +        lines = [line.strip() for line in self.vtysh(
> > > > > > +            'show bgp {0} unicast {1}'.format(rf, prefix),
> > > > > > +            config=False).split('\n')]
> > > > > > +
> > > > > > +        if lines[0] == '% Network not in table':
> > > > > > +            return rib
> > > > > > +
> > > > > > +        lines = lines[2:]
> > > > > > +
> > > > > > +        if lines[0].startswith('Not advertised'):
> > > > > > +            lines.pop(0)  # another useless line
> > > > > > +        elif lines[0].startswith('Advertised to non peer-group
> > > > peers:'):
> > > > > > +            lines = lines[2:]  # other useless lines
> > > > > > +        else:
> > > > > > +            raise Exception('unknown output format
> > {0}'.format(lines))
> > > > > > +
> > > > > > +        if lines[0] == 'Local':
> > > > > > +            aspath = []
> > > > > > +        else:
> > > > > > +            aspath = [int(asn) for asn in lines[0].split()]
> > > > > > +
> > > > > > +        nexthop = lines[1].split()[0].strip()
> > > > > > +        info = [s.strip(',') for s in lines[2].split()]
> > > > > > +        attrs = []
> > > > > > +        if 'metric' in info:
> > > > > > +            med = info[info.index('metric') + 1]
> > > > > > +            attrs.append({'type': base.BGP_ATTR_TYPE_MULTI_EXIT_
> > DISC,
> > > > > > +                          'metric': int(med)})
> > > > > > +        if 'localpref' in info:
> > > > > > +            localpref = info[info.index('localpref') + 1]
> > > > > > +            attrs.append({'type': base.BGP_ATTR_TYPE_LOCAL_PREF,
> > > > > > +                          'value': int(localpref)})
> > > > > > +
> > > > > > +        rib.append({'prefix': prefix, 'nexthop': nexthop,
> > > > > > +                    'aspath': aspath, 'attrs': attrs})
> > > > > > +
> > > > > > +        return rib
> > > > > > +
> > > > > > +    def get_neighbor_state(self, peer):
> > > > > > +        if peer not in self.peers:
> > > > > > +            raise Exception('not found peer
> > > > {0}'.format(peer.router_id))
> > > > > > +
> > > > > > +        neigh_addr = self.peers[peer]['neigh_addr'].split('/')[0]
> > > > > > +
> > > > > > +        info = [l.strip() for l in self.vtysh(
> > > > > > +            'show bgp neighbors {0}'.format(neigh_addr),
> > > > > > +            config=False).split('\n')]
> > > > > > +
> > > > > > +        if not info[0].startswith('BGP neighbor is'):
> > > > > > +            raise Exception('unknown format')
> > > > > > +
> > > > > > +        idx1 = info[0].index('BGP neighbor is ')
> > > > > > +        idx2 = info[0].index(',')
> > > > > > +        n_addr = info[0][idx1 + len('BGP neighbor is '):idx2]
> > > > > > +        if n_addr == neigh_addr:
> > > > > > +            idx1 = info[2].index('= ')
> > > > > > +            state = info[2][idx1 + len('= '):]
> > > > > > +            if state.startswith('Idle'):
> > > > > > +                return base.BGP_FSM_IDLE
> > > > > > +            elif state.startswith('Active'):
> > > > > > +                return base.BGP_FSM_ACTIVE
> > > > > > +            elif state.startswith('Established'):
> > > > > > +                return base.BGP_FSM_ESTABLISHED
> > > > > > +            else:
> > > > > > +                return state
> > > > > > +
> > > > > > +        raise Exception('not found peer
> > {0}'.format(peer.router_id))
> > > > > > +
> > > > > > +    def send_route_refresh(self):
> > > > > > +        self.vtysh('clear ip bgp * soft', config=False)
> > > > > > +
> > > > > > +    def create_config(self):
> > > > > > +        zebra = 'no'
> > > > > > +        self._create_config_bgp()
> > > > > > +        if self.zebra:
> > > > > > +            zebra = 'yes'
> > > > > > +            self._create_config_zebra()
> > > > > > +        self._create_config_daemons(zebra)
> > > > > > +
> > > > > > +    def _create_config_debian(self):
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << 'vtysh_enable=yes'
> > > > > > +        c << 'zebra_options="  --daemon -A 127.0.0.1"'
> > > > > > +        c << 'bgpd_options="   --daemon -A 127.0.0.1"'
> > > > > > +        c << 'ospfd_options="  --daemon -A 127.0.0.1"'
> > > > > > +        c << 'ospf6d_options=" --daemon -A ::1"'
> > > > > > +        c << 'ripd_options="   --daemon -A 127.0.0.1"'
> > > > > > +        c << 'ripngd_options=" --daemon -A ::1"'
> > > > > > +        c << 'isisd_options="  --daemon -A 127.0.0.1"'
> > > > > > +        c << 'babeld_options=" --daemon -A 127.0.0.1"'
> > > > > > +        c << 'watchquagga_enable=yes'
> > > > > > +        c << 'watchquagga_options=(--daemon)'
> > > > > > +        with open('{0}/debian.conf'.format(self.config_dir),
> > 'w') as
> > > > f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def _create_config_daemons(self, zebra='no'):
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << 'zebra=%s' % zebra
> > > > > > +        c << 'bgpd=yes'
> > > > > > +        c << 'ospfd=no'
> > > > > > +        c << 'ospf6d=no'
> > > > > > +        c << 'ripd=no'
> > > > > > +        c << 'ripngd=no'
> > > > > > +        c << 'isisd=no'
> > > > > > +        c << 'babeld=no'
> > > > > > +        with open('{0}/daemons'.format(self.config_dir), 'w') as
> > f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def _create_config_bgp(self):
> > > > > > +
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << 'hostname bgpd'
> > > > > > +        c << 'password zebra'
> > > > > > +        c << 'router bgp {0}'.format(self.asn)
> > > > > > +        c << 'bgp router-id {0}'.format(self.router_id)
> > > > > > +        if any(info['graceful_restart'] for info in
> > > > self.peers.values()):
> > > > > > +            c << 'bgp graceful-restart'
> > > > > > +
> > > > > > +        version = 4
> > > > > > +        for peer, info in self.peers.items():
> > > > > > +            version = netaddr.IPNetwork(info['neigh_
> > addr']).version
> > > > > > +            n_addr = info['neigh_addr'].split('/')[0]
> > > > > > +            if version == 6:
> > > > > > +                c << 'no bgp default ipv4-unicast'
> > > > > > +
> > > > > > +            c << 'neighbor {0} remote-as {1}'.format(n_addr,
> > peer.asn)
> > > > > > +            if info['is_rs_client']:
> > > > > > +                c << 'neighbor {0} route-server-client'.format(n_
> > > > addr)
> > > > > > +            for typ, p in info['policies'].items():
> > > > > > +                c << 'neighbor {0} route-map {1}
> > {2}'.format(n_addr,
> > > > > > p['name'],
> > > > > > +                                                             typ)
> > > > > > +            if info['passwd']:
> > > > > > +                c << 'neighbor {0} password {1}'.format(n_addr,
> > > > > > info['passwd'])
> > > > > > +            if info['passive']:
> > > > > > +                c << 'neighbor {0} passive'.format(n_addr)
> > > > > > +            if version == 6:
> > > > > > +                c << 'address-family ipv6 unicast'
> > > > > > +                c << 'neighbor {0} activate'.format(n_addr)
> > > > > > +                c << 'exit-address-family'
> > > > > > +
> > > > > > +        for route in self.routes.values():
> > > > > > +            if route['rf'] == 'ipv4':
> > > > > > +                c << 'network {0}'.format(route['prefix'])
> > > > > > +            elif route['rf'] == 'ipv6':
> > > > > > +                c << 'address-family ipv6 unicast'
> > > > > > +                c << 'network {0}'.format(route['prefix'])
> > > > > > +                c << 'exit-address-family'
> > > > > > +            else:
> > > > > > +                raise Exception(
> > > > > > +                    'unsupported route faily:
> > > > {0}'.format(route['rf']))
> > > > > > +
> > > > > > +        if self.zebra:
> > > > > > +            if version == 6:
> > > > > > +                c << 'address-family ipv6 unicast'
> > > > > > +                c << 'redistribute connected'
> > > > > > +                c << 'exit-address-family'
> > > > > > +            else:
> > > > > > +                c << 'redistribute connected'
> > > > > > +
> > > > > > +        for name, policy in self.policies.items():
> > > > > > +            c << 'access-list {0} {1} {2}'.format(name,
> > > > policy['type'],
> > > > > > +                                                  policy['match'])
> > > > > > +            c << 'route-map {0} permit 10'.format(name)
> > > > > > +            c << 'match ip address {0}'.format(name)
> > > > > > +            c << 'set metric {0}'.format(policy['med'])
> > > > > > +
> > > > > > +        c << 'debug bgp as4'
> > > > > > +        c << 'debug bgp fsm'
> > > > > > +        c << 'debug bgp updates'
> > > > > > +        c << 'debug bgp events'
> > > > > > +        c << 'log file {0}/bgpd.log'.format(self.SHARED_VOLUME)
> > > > > > +
> > > > > > +        with open('{0}/bgpd.conf'.format(self.config_dir), 'w')
> > as f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def _create_config_zebra(self):
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << 'hostname zebra'
> > > > > > +        c << 'password zebra'
> > > > > > +        c << 'log file {0}/zebra.log'.format(self.SHARED_VOLUME)
> > > > > > +        c << 'debug zebra packet'
> > > > > > +        c << 'debug zebra kernel'
> > > > > > +        c << 'debug zebra rib'
> > > > > > +        c << ''
> > > > > > +
> > > > > > +        with open('{0}/zebra.conf'.format(self.config_dir), 'w')
> > as
> > > > f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def vtysh(self, cmd, config=True):
> > > > > > +        if not isinstance(cmd, list):
> > > > > > +            cmd = [cmd]
> > > > > > +        cmd = ' '.join("-c '{0}'".format(c) for c in cmd)
> > > > > > +        if config:
> > > > > > +            return self.exec_on_ctn(
> > > > > > +                "vtysh -d bgpd -c 'en' -c 'conf t' -c "
> > > > > > +                "'router bgp {0}' {1}".format(self.asn, cmd),
> > > > > > +                capture=True)
> > > > > > +        else:
> > > > > > +            return self.exec_on_ctn("vtysh -d bgpd
> > {0}".format(cmd),
> > > > > > +                                    capture=True)
> > > > > > +
> > > > > > +    def reload_config(self):
> > > > > > +        daemon = []
> > > > > > +        daemon.append('bgpd')
> > > > > > +        if self.zebra:
> > > > > > +            daemon.append('zebra')
> > > > > > +        for d in daemon:
> > > > > > +            cmd = '/usr/bin/pkill {0} -SIGHUP'.format(d)
> > > > > > +            self.exec_on_ctn(cmd, capture=True)
> > > > > > +
> > > > > > +
> > > > > > +class RawQuaggaBGPContainer(QuaggaBGPContainer):
> > > > > > +    def __init__(self, name, config, ctn_image_name,
> > > > > > +                 zebra=False):
> > > > > > +        asn = None
> > > > > > +        router_id = None
> > > > > > +        for line in config.split('\n'):
> > > > > > +            line = line.strip()
> > > > > > +            if line.startswith('router bgp'):
> > > > > > +                asn = int(line[len('router bgp'):].strip())
> > > > > > +            if line.startswith('bgp router-id'):
> > > > > > +                router_id = line[len('bgp router-id'):].strip()
> > > > > > +        if not asn:
> > > > > > +            raise Exception('asn not in quagga config')
> > > > > > +        if not router_id:
> > > > > > +            raise Exception('router-id not in quagga config')
> > > > > > +        self.config = config
> > > > > > +        super(RawQuaggaBGPContainer, self).__init__(name, asn,
> > > > router_id,
> > > > > > +
> > ctn_image_name,
> > > > zebra)
> > > > > > +
> > > > > > +    def create_config(self):
> > > > > > +        with open(os.path.join(self.config_dir, 'bgpd.conf'),
> > 'w')
> > > > as f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(self.config)
> > > > > > +            f.writelines(self.config)
> > > > > > diff --git a/ryu/lib/docker/ryubgp.py b/ryu/lib/docker/ryubgp.py
> > > > > > new file mode 100644
> > > > > > index 0000000..8fe16f4
> > > > > > --- /dev/null
> > > > > > +++ b/ryu/lib/docker/ryubgp.py
> > > > > > @@ -0,0 +1,212 @@
> > > > > > +# Copyright (C) 2016 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 __future__ import absolute_import
> > > > > > +
> > > > > > +import logging
> > > > > > +import os
> > > > > > +import time
> > > > > > +
> > > > > > +from . import docker_base as base
> > > > > > +
> > > > > > +LOG = logging.getLogger(__name__)
> > > > > > +
> > > > > > +
> > > > > > +class RyuBGPContainer(base.BGPContainer):
> > > > > > +
> > > > > > +    WAIT_FOR_BOOT = 1
> > > > > > +    SHARED_VOLUME = '/etc/ryu'
> > > > > > +
> > > > > > +    def __init__(self, name, asn, router_id, ctn_image_name):
> > > > > > +        super(RyuBGPContainer, self).__init__(name, asn,
> > router_id,
> > > > > > +                                              ctn_image_name)
> > > > > > +        self.RYU_CONF = os.path.join(self.config_dir, 'ryu.conf')
> > > > > > +        self.SHARED_RYU_CONF = os.path.join(self.SHARED_VOLUME,
> > > > > > 'ryu.conf')
> > > > > > +        self.SHARED_BGP_CONF = os.path.join(self.SHARED_VOLUME,
> > > > > > 'bgp_conf.py')
> > > > > > +        self.shared_volumes.append((self.config_dir,
> > > > self.SHARED_VOLUME))
> > > > > > +
> > > > > > +    def _create_config_ryu(self):
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << '[DEFAULT]'
> > > > > > +        c << 'verbose=True'
> > > > > > +        c << 'log_file=/etc/ryu/manager.log'
> > > > > > +        with open(self.RYU_CONF, 'w') as f:
> > > > > > +            LOG.info("[%s's new config]" % self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def _create_config_ryu_bgp(self):
> > > > > > +        c = base.CmdBuffer()
> > > > > > +        c << 'import os'
> > > > > > +        c << ''
> > > > > > +        c << 'BGP = {'
> > > > > > +        c << "    'local_as': %s," % str(self.asn)
> > > > > > +        c << "    'router_id': '%s'," % self.router_id
> > > > > > +        c << "    'neighbors': ["
> > > > > > +        c << "        {"
> > > > > > +        for peer, info in self.peers.items():
> > > > > > +            n_addr = info['neigh_addr'].split('/')[0]
> > > > > > +            c << "            'address': '%s'," % n_addr
> > > > > > +            c << "            'remote_as': %s," % str(peer.asn)
> > > > > > +            c << "            'enable_ipv4': True,"
> > > > > > +            c << "            'enable_ipv6': True,"
> > > > > > +            c << "            'enable_vpnv4': True,"
> > > > > > +            c << "            'enable_vpnv6': True,"
> > > > > > +            c << '        },'
> > > > > > +            c << '    ],'
> > > > > > +        c << "    'routes': ["
> > > > > > +        for route in self.routes.values():
> > > > > > +            c << "        {"
> > > > > > +            c << "            'prefix': '%s'," % route['prefix']
> > > > > > +            c << "        },"
> > > > > > +        c << "    ],"
> > > > > > +        c << "}"
> > > > > > +        log_conf = """LOGGING = {
> > > > > > +
> > > > > > +    # We use python logging package for logging.
> > > > > > +    'version': 1,
> > > > > > +    'disable_existing_loggers': False,
> > > > > > +
> > > > > > +    'formatters': {
> > > > > > +        'verbose': {
> > > > > > +            'format': '%(levelname)s %(asctime)s %(module)s ' +
> > > > > > +                      '[%(process)d %(thread)d] %(message)s'
> > > > > > +        },
> > > > > > +        'simple': {
> > > > > > +            'format': '%(levelname)s %(asctime)s %(module)s
> > > > %(lineno)s ' +
> > > > > > +                      '%(message)s'
> > > > > > +        },
> > > > > > +        'stats': {
> > > > > > +            'format': '%(message)s'
> > > > > > +        },
> > > > > > +    },
> > > > > > +
> > > > > > +    'handlers': {
> > > > > > +        # Outputs log to console.
> > > > > > +        'console': {
> > > > > > +            'level': 'DEBUG',
> > > > > > +            'class': 'logging.StreamHandler',
> > > > > > +            'formatter': 'simple'
> > > > > > +        },
> > > > > > +        'console_stats': {
> > > > > > +            'level': 'DEBUG',
> > > > > > +            'class': 'logging.StreamHandler',
> > > > > > +            'formatter': 'stats'
> > > > > > +        },
> > > > > > +        # Rotates log file when its size reaches 10MB.
> > > > > > +        'log_file': {
> > > > > > +            'level': 'DEBUG',
> > > > > > +            'class': 'logging.handlers.RotatingFileHandler',
> > > > > > +            'filename': os.path.join('.', 'bgpspeaker.log'),
> > > > > > +            'maxBytes': '10000000',
> > > > > > +            'formatter': 'verbose'
> > > > > > +        },
> > > > > > +        'stats_file': {
> > > > > > +            'level': 'DEBUG',
> > > > > > +            'class': 'logging.handlers.RotatingFileHandler',
> > > > > > +            'filename': os.path.join('.', 'statistics_bgps.log'),
> > > > > > +            'maxBytes': '10000000',
> > > > > > +            'formatter': 'stats'
> > > > > > +        },
> > > > > > +    },
> > > > > > +
> > > > > > +    # Fine-grained control of logging per instance.
> > > > > > +    'loggers': {
> > > > > > +        'bgpspeaker': {
> > > > > > +            'handlers': ['console', 'log_file'],
> > > > > > +            'handlers': ['console'],
> > > > > > +            'level': 'DEBUG',
> > > > > > +            'propagate': False,
> > > > > > +        },
> > > > > > +        'stats': {
> > > > > > +            'handlers': ['stats_file', 'console_stats'],
> > > > > > +            'level': 'INFO',
> > > > > > +            'propagate': False,
> > > > > > +            'formatter': 'stats',
> > > > > > +        },
> > > > > > +    },
> > > > > > +
> > > > > > +    # Root loggers.
> > > > > > +    'root': {
> > > > > > +        'handlers': ['console', 'log_file'],
> > > > > > +        'level': 'DEBUG',
> > > > > > +        'propagate': True,
> > > > > > +    },
> > > > > > +}"""
> > > > > > +        c << log_conf
> > > > > > +        with open(os.path.join(self.config_dir, 'bgp_conf.py'),
> > 'w')
> > > > as
> > > > > > f:
> > > > > > +            LOG.info("[%s's new config]", self.name)
> > > > > > +            LOG.info(str(c))
> > > > > > +            f.writelines(str(c))
> > > > > > +
> > > > > > +    def create_config(self):
> > > > > > +        self._create_config_ryu()
> > > > > > +        self._create_config_ryu_bgp()
> > > > > > +
> > > > > > +    def is_running_ryu(self):
> > > > > > +        results = self.exec_on_ctn('ps ax')
> > > > > > +        running = False
> > > > > > +        for line in results.split('\n')[1:]:
> > > > > > +            if 'ryu-manager' in line:
> > > > > > +                running = True
> > > > > > +        return running
> > > > > > +
> > > > > > +    def start_ryubgp(self, check_running=True, retry=False):
> > > > > > +        if check_running:
> > > > > > +            if self.is_running_ryu():
> > > > > > +                return True
> > > > > > +        result = False
> > > > > > +        if retry:
> > > > > > +            try_times = 3
> > > > > > +        else:
> > > > > > +            try_times = 1
> > > > > > +        cmd = "ryu-manager --verbose "
> > > > > > +        cmd += "--config-file %s " % self.SHARED_RYU_CONF
> > > > > > +        cmd += "--bgp-app-config-file %s " % self.SHARED_BGP_CONF
> > > > > > +        cmd += "ryu.services.protocols.bgp.application"
> > > > > > +        for _ in range(try_times):
> > > > > > +            self.exec_on_ctn(cmd, detach=True)
> > > > > > +            if self.is_running_ryu():
> > > > > > +                result = True
> > > > > > +                break
> > > > > > +            time.sleep(1)
> > > > > > +        return result
> > > > > > +
> > > > > > +    def stop_ryubgp(self, check_running=True, retry=False):
> > > > > > +        if check_running:
> > > > > > +            if not self.is_running_ryu():
> > > > > > +                return True
> > > > > > +        result = False
> > > > > > +        if retry:
> > > > > > +            try_times = 3
> > > > > > +        else:
> > > > > > +            try_times = 1
> > > > > > +        for _ in range(try_times):
> > > > > > +            cmd = '/usr/bin/pkill ryu-manager -SIGTERM'
> > > > > > +            self.exec_on_ctn(cmd)
> > > > > > +            if not self.is_running_ryu():
> > > > > > +                result = True
> > > > > > +                break
> > > > > > +            time.sleep(1)
> > > > > > +        return result
> > > > > > +
> > > > > > +    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > +        w_time = super(RyuBGPContainer,
> > > > > > +                       self).run(wait=wait,
> > w_time=self.WAIT_FOR_BOOT)
> > > > > > +        return w_time
> > > > > > +
> > > > > > +    def reload_config(self):
> > > > > > +        self.stop_ryubgp(retry=True)
> > > > > > +        self.start_ryubgp(retry=True)
> > > > > > diff --git a/ryu/tests/integrated/common/__init__.py
> > > > > > b/ryu/tests/integrated/common/__init__.py
> > > > > > deleted file mode 100644
> > > > > > index e69de29..0000000
> > > > > > diff --git a/ryu/tests/integrated/common/docker_base.py
> > > > > > b/ryu/tests/integrated/common/docker_base.py
> > > > > > deleted file mode 100644
> > > > > > index 1ae2cc2..0000000
> > > > > > --- a/ryu/tests/integrated/common/docker_base.py
> > > > > > +++ /dev/null
> > > > > > @@ -1,801 +0,0 @@
> > > > > > -# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
> > > > > > -#
> > > > > > -# This is based on the following
> > > > > > -#     https://github.com/osrg/gobgp/test/lib/base.py
> > > > > > -#
> > > > > > -# 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 __future__ import absolute_import
> > > > > > -
> > > > > > -import itertools
> > > > > > -import logging
> > > > > > -import os
> > > > > > -import subprocess
> > > > > > -import time
> > > > > > -
> > > > > > -import netaddr
> > > > > > -import six
> > > > > > -
> > > > > > -LOG = logging.getLogger(__name__)
> > > > > > -
> > > > > > -DEFAULT_TEST_PREFIX = ''
> > > > > > -DEFAULT_TEST_BASE_DIR = '/tmp/ctn_docker/bgp'
> > > > > > -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_ORIGINATOR_ID = 9
> > > > > > -BGP_ATTR_TYPE_CLUSTER_LIST = 10
> > > > > > -BGP_ATTR_TYPE_MP_REACH_NLRI = 14
> > > > > > -BGP_ATTR_TYPE_EXTENDED_COMMUNITIES = 16
> > > > > > -
> > > > > > -BRIDGE_TYPE_DOCKER = 'docker'
> > > > > > -BRIDGE_TYPE_BRCTL = 'brctl'
> > > > > > -BRIDGE_TYPE_OVS = 'ovs'
> > > > > > -
> > > > > > -
> > > > > > -class CommandError(Exception):
> > > > > > -    def __init__(self, out):
> > > > > > -        super(CommandError, self).__init__()
> > > > > > -        self.out = out
> > > > > > -
> > > > > > -
> > > > > > -def try_several_times(f, t=3, s=1):
> > > > > > -    e = RuntimeError()
> > > > > > -    for _ in range(t):
> > > > > > -        try:
> > > > > > -            r = f()
> > > > > > -        except RuntimeError as e:
> > > > > > -            time.sleep(s)
> > > > > > -        else:
> > > > > > -            return r
> > > > > > -    raise e
> > > > > > -
> > > > > > -
> > > > > > -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)
> > > > > > -
> > > > > > -
> > > > > > -class CommandOut(str):
> > > > > > -
> > > > > > -    def __new__(cls, stdout, stderr, command, returncode,
> > **kwargs):
> > > > > > -        stdout = stdout or ''
> > > > > > -        obj = super(CommandOut, cls).__new__(cls, stdout,
> > **kwargs)
> > > > > > -        obj.stderr = stderr or ''
> > > > > > -        obj.command = command
> > > > > > -        obj.returncode = returncode
> > > > > > -        return obj
> > > > > > -
> > > > > > -
> > > > > > -class Command(object):
> > > > > > -
> > > > > > -    def _execute(self, cmd, capture=False, executable=None):
> > > > > > -        """Execute a command using subprocess.Popen()
> > > > > > -        :Parameters:
> > > > > > -            - out: stdout from subprocess.Popen()
> > > > > > -              out has some attributes.
> > > > > > -              out.returncode: returncode of subprocess.Popen()
> > > > > > -              out.stderr: stderr from subprocess.Popen()
> > > > > > -        """
> > > > > > -        if capture:
> > > > > > -            p_stdout = subprocess.PIPE
> > > > > > -            p_stderr = subprocess.PIPE
> > > > > > -        else:
> > > > > > -            p_stdout = None
> > > > > > -            p_stderr = None
> > > > > > -        pop = subprocess.Popen(cmd, shell=True,
> > executable=executable,
> > > > > > -                               stdout=p_stdout,
> > > > > > -                               stderr=p_stderr)
> > > > > > -        __stdout, __stderr = pop.communicate()
> > > > > > -        _stdout = six.text_type(__stdout, 'utf-8')
> > > > > > -        _stderr = six.text_type(__stderr, 'utf-8')
> > > > > > -        out = CommandOut(_stdout, _stderr, cmd, pop.returncode)
> > > > > > -        return out
> > > > > > -
> > > > > > -    def execute(self, cmd, capture=True, try_times=1, interval=1):
> > > > > > -        out = None
> > > > > > -        for i in range(try_times):
> > > > > > -            out = self._execute(cmd, capture=capture)
> > > > > > -            LOG.info(out.command)
> > > > > > -            if out.returncode == 0:
> > > > > > -                return out
> > > > > > -            LOG.error("stdout: %s", out)
> > > > > > -            LOG.error("stderr: %s", out.stderr)
> > > > > > -            if i + 1 >= try_times:
> > > > > > -                break
> > > > > > -            time.sleep(interval)
> > > > > > -        raise CommandError(out)
> > > > > > -
> > > > > > -    def sudo(self, cmd, capture=True, try_times=1, interval=1):
> > > > > > -        cmd = 'sudo %s' % cmd
> > > > > > -        return self.execute(cmd, capture=capture,
> > > > > > -                            try_times=try_times,
> > interval=interval)
> > > > > > -
> > > > > > -
> > > > > > -class DockerImage(object):
> > > > > > -    def __init__(self, baseimage='ubuntu:16.04'):
> > > > > > -        self.baseimage = baseimage
> > > > > > -        self.cmd = Command()
> > > > > > -
> > > > > > -    def get_images(self):
> > > > > > -        out = self.cmd.sudo('sudo docker images')
> > > > > > -        images = []
> > > > > > -        for line in out.splitlines()[1:]:
> > > > > > -            images.append(line.split()[0])
> > > > > > -        return images
> > > > > > -
> > > > > > -    def exist(self, name):
> > > > > > -        return name in self.get_images()
> > > > > > -
> > > > > > -    def build(self, tagname, dockerfile_dir):
> > > > > > -        self.cmd.sudo(
> > > > > > -            "docker build -t {0} {1}".format(tagname,
> > dockerfile_dir),
> > > > > > -            try_times=3)
> > > > > > -
> > > > > > -    def remove(self, tagname, check_exist=False):
> > > > > > -        if check_exist and not self.exist(tagname):
> > > > > > -            return tagname
> > > > > > -        self.cmd.sudo("docker rmi -f %s" % tagname, try_times=3)
> > > > > > -
> > > > > > -    def create_quagga(self, tagname='quagga', image=None,
> > > > > > check_exist=False):
> > > > > > -        if check_exist and self.exist(tagname):
> > > > > > -            return tagname
> > > > > > -        workdir = os.path.join(TEST_BASE_DIR, tagname)
> > > > > > -        pkges = ' '.join([
> > > > > > -            'telnet',
> > > > > > -            'tcpdump',
> > > > > > -            'quagga',
> > > > > > -        ])
> > > > > > -        if image:
> > > > > > -            use_image = image
> > > > > > -        else:
> > > > > > -            use_image = self.baseimage
> > > > > > -        c = CmdBuffer()
> > > > > > -        c << 'FROM %s' % use_image
> > > > > > -        c << 'RUN apt-get update'
> > > > > > -        c << 'RUN apt-get install -qy --no-install-recommends %s'
> > %
> > > > pkges
> > > > > > -        c << 'CMD /usr/lib/quagga/bgpd'
> > > > > > -
> > > > > > -        self.cmd.sudo('rm -rf %s' % workdir)
> > > > > > -        self.cmd.execute('mkdir -p %s' % workdir)
> > > > > > -        self.cmd.execute("echo '%s' > %s/Dockerfile" % (str(c),
> > > > workdir))
> > > > > > -        self.build(tagname, workdir)
> > > > > > -        return tagname
> > > > > > -
> > > > > > -    def create_ryu(self, tagname='ryu', image=None,
> > > > check_exist=False):
> > > > > > -        if check_exist and self.exist(tagname):
> > > > > > -            return tagname
> > > > > > -        workdir = os.path.join(TEST_BASE_DIR, tagname)
> > > > > > -        workdir_ctn = '/root/osrg/ryu'
> > > > > > -        pkges = ' '.join([
> > > > > > -            'tcpdump',
> > > > > > -            'iproute2',
> > > > > > -        ])
> > > > > > -        if image:
> > > > > > -            use_image = image
> > > > > > -        else:
> > > > > > -            use_image = self.baseimage
> > > > > > -        c = CmdBuffer()
> > > > > > -        c << 'FROM %s' % use_image
> > > > > > -        c << 'ADD ryu %s' % workdir_ctn
> > > > > > -        install = ' '.join([
> > > > > > -            'RUN apt-get update',
> > > > > > -            '&& apt-get install -qy --no-install-recommends %s' %
> > > > pkges,
> > > > > > -            '&& cd %s' % workdir_ctn,
> > > > > > -            # Note: Clean previous builds, because "python
> > setup.py
> > > > > > install"
> > > > > > -            # might fail if the current directory contains the
> > > > symlink to
> > > > > > -            # Docker host file systems.
> > > > > > -            '&& rm -rf *.egg-info/ build/ dist/ .tox/ *.log'
> > > > > > -            '&& pip install -r tools/pip-requires -r
> > > > > > tools/optional-requires',
> > > > > > -            '&& python setup.py install',
> > > > > > -        ])
> > > > > > -        c << install
> > > > > > -
> > > > > > -        self.cmd.sudo('rm -rf %s' % workdir)
> > > > > > -        self.cmd.execute('mkdir -p %s' % workdir)
> > > > > > -        self.cmd.execute("echo '%s' > %s/Dockerfile" % (str(c),
> > > > workdir))
> > > > > > -        self.cmd.execute('cp -r ../ryu %s/' % workdir)
> > > > > > -        self.build(tagname, workdir)
> > > > > > -        return tagname
> > > > > > -
> > > > > > -
> > > > > > -class Bridge(object):
> > > > > > -    def __init__(self, name, subnet='', start_ip=None,
> > end_ip=None,
> > > > > > -                 with_ip=True, self_ip=False,
> > > > > > -                 fixed_ip=None, reuse=False,
> > > > > > -                 br_type='docker'):
> > > > > > -        """Manage a bridge
> > > > > > -        :Parameters:
> > > > > > -            - name: bridge name
> > > > > > -            - subnet: network cider to be used in this bridge
> > > > > > -            - start_ip: start address of an ip to be used in the
> > > > subnet
> > > > > > -            - end_ip: end address of an ip to be used in the
> > subnet
> > > > > > -            - with_ip: specify if assign automatically an ip
> > address
> > > > > > -            - self_ip: specify if assign an ip address for the
> > bridge
> > > > > > -            - fixed_ip: an ip address to be assigned to the bridge
> > > > > > -            - reuse: specify if use an existing bridge
> > > > > > -            - br_type: One either in a 'docker', 'brctl' or 'ovs'
> > > > > > -        """
> > > > > > -        self.cmd = Command()
> > > > > > -        self.name = name
> > > > > > -        if br_type not in (BRIDGE_TYPE_DOCKER, BRIDGE_TYPE_BRCTL,
> > > > > > -                           BRIDGE_TYPE_OVS):
> > > > > > -            raise Exception("argument error br_type: %s" %
> > br_type)
> > > > > > -        self.br_type = br_type
> > > > > > -        self.docker_nw = bool(self.br_type == BRIDGE_TYPE_DOCKER)
> > > > > > -        if TEST_PREFIX != '':
> > > > > > -            self.name = '{0}_{1}'.format(TEST_PREFIX, name)
> > > > > > -        self.with_ip = with_ip
> > > > > > -        if with_ip:
> > > > > > -            self.subnet = netaddr.IPNetwork(subnet)
> > > > > > -            if start_ip:
> > > > > > -                self.start_ip = start_ip
> > > > > > -            else:
> > > > > > -                self.start_ip = netaddr.IPAddress(self.subnet.
> > first)
> > > > > > -            if end_ip:
> > > > > > -                self.end_ip = end_ip
> > > > > > -            else:
> > > > > > -                self.end_ip = netaddr.IPAddress(self.subnet.last)
> > > > > > -
> > > > > > -            def _ip_gen():
> > > > > > -                for host in netaddr.IPRange(self.start_ip,
> > > > self.end_ip):
> > > > > > -                    yield host
> > > > > > -            self._ip_generator = _ip_gen()
> > > > > > -            # throw away first network address
> > > > > > -            self.next_ip_address()
> > > > > > -
> > > > > > -        self.self_ip = self_ip
> > > > > > -        if fixed_ip:
> > > > > > -            self.ip_addr = fixed_ip
> > > > > > -        else:
> > > > > > -            self.ip_addr = self.next_ip_address()
> > > > > > -        if not reuse:
> > > > > > -            def f():
> > > > > > -                if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > -                    gw = "--gateway %s" %
> > self.ip_addr.split('/')[0]
> > > > > > -                    v6 = ''
> > > > > > -                    if self.subnet.version == 6:
> > > > > > -                        v6 = '--ipv6'
> > > > > > -                    cmd = ("docker network create --driver bridge
> > %s "
> > > > > > -                           "%s --subnet %s %s" % (v6, gw, subnet,
> > > > > > self.name))
> > > > > > -                elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > -                    cmd = "ip link add {0} type bridge".format(
> > > > self.name)
> > > > > > -                elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > -                    cmd = "ovs-vsctl add-br {0}".format(self.name
> > )
> > > > > > -                else:
> > > > > > -                    raise ValueError('Unsupported br_type: %s' %
> > > > > > self.br_type)
> > > > > > -                self.delete()
> > > > > > -                self.execute(cmd, sudo=True, retry=True)
> > > > > > -            try_several_times(f)
> > > > > > -        if not self.docker_nw:
> > > > > > -            self.execute("ip link set up dev {0}".format(
> > self.name),
> > > > > > -                         sudo=True, retry=True)
> > > > > > -
> > > > > > -        if not self.docker_nw and self_ip:
> > > > > > -            ips = self.check_br_addr(self.name)
> > > > > > -            for key, ip in ips.items():
> > > > > > -                if self.subnet.version == key:
> > > > > > -                    self.execute(
> > > > > > -                        "ip addr del {0} dev {1}".format(ip,
> > > > self.name),
> > > > > > -                        sudo=True, retry=True)
> > > > > > -            self.execute(
> > > > > > -                "ip addr add {0} dev {1}".format(self.ip_addr,
> > > > self.name
> > > > > > ),
> > > > > > -                sudo=True, retry=True)
> > > > > > -        self.ctns = []
> > > > > > -
> > > > > > -    def get_bridges_dc(self):
> > > > > > -        out = self.execute('docker network ls', sudo=True,
> > retry=True)
> > > > > > -        bridges = []
> > > > > > -        for line in out.splitlines()[1:]:
> > > > > > -            bridges.append(line.split()[1])
> > > > > > -        return bridges
> > > > > > -
> > > > > > -    def get_bridges_brctl(self):
> > > > > > -        out = self.execute('brctl show', retry=True)
> > > > > > -        bridges = []
> > > > > > -        for line in out.splitlines()[1:]:
> > > > > > -            bridges.append(line.split()[0])
> > > > > > -        return bridges
> > > > > > -
> > > > > > -    def get_bridges_ovs(self):
> > > > > > -        out = self.execute('ovs-vsctl list-br', sudo=True,
> > retry=True)
> > > > > > -        return out.splitlines()
> > > > > > -
> > > > > > -    def get_bridges(self):
> > > > > > -        if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > -            return self.get_bridges_dc()
> > > > > > -        elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > -            return self.get_bridges_brctl()
> > > > > > -        elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > -            return self.get_bridges_ovs()
> > > > > > -
> > > > > > -    def exist(self):
> > > > > > -        return self.name in self.get_bridges()
> > > > > > -
> > > > > > -    def execute(self, cmd, capture=True, sudo=False, retry=False):
> > > > > > -        if sudo:
> > > > > > -            m = self.cmd.sudo
> > > > > > -        else:
> > > > > > -            m = self.cmd.execute
> > > > > > -        if retry:
> > > > > > -            return m(cmd, capture=capture, try_times=3,
> > interval=1)
> > > > > > -        else:
> > > > > > -            return m(cmd, capture=capture)
> > > > > > -
> > > > > > -    def check_br_addr(self, br):
> > > > > > -        ips = {}
> > > > > > -        cmd = "ip a show dev %s" % br
> > > > > > -        for line in self.execute(cmd, sudo=True).split('\n'):
> > > > > > -            if line.strip().startswith("inet "):
> > > > > > -                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > -                ips[4] = elems[1]
> > > > > > -            elif line.strip().startswith("inet6 "):
> > > > > > -                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > -                ips[6] = elems[1]
> > > > > > -        return ips
> > > > > > -
> > > > > > -    def next_ip_address(self):
> > > > > > -        return "{0}/{1}".format(next(self._ip_generator),
> > > > > > -                                self.subnet.prefixlen)
> > > > > > -
> > > > > > -    def addif(self, ctn):
> > > > > > -        name = ctn.next_if_name()
> > > > > > -        self.ctns.append(ctn)
> > > > > > -        ip_address = None
> > > > > > -        if self.docker_nw:
> > > > > > -            ipv4 = None
> > > > > > -            ipv6 = None
> > > > > > -            ip_address = self.next_ip_address()
> > > > > > -            ip_address_ip = ip_address.split('/')[0]
> > > > > > -            version = 4
> > > > > > -            if netaddr.IPNetwork(ip_address).version == 6:
> > > > > > -                version = 6
> > > > > > -            opt_ip = "--ip %s" % ip_address_ip
> > > > > > -            if version == 4:
> > > > > > -                ipv4 = ip_address
> > > > > > -            else:
> > > > > > -                opt_ip = "--ip6 %s" % ip_address_ip
> > > > > > -                ipv6 = ip_address
> > > > > > -            cmd = "docker network connect %s %s %s" % (
> > > > > > -                opt_ip, self.name, ctn.docker_name())
> > > > > > -            self.execute(cmd, sudo=True)
> > > > > > -            ctn.set_addr_info(bridge=self.name, ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > -                              ifname=name)
> > > > > > -        else:
> > > > > > -            if self.with_ip:
> > > > > > -                ip_address = self.next_ip_address()
> > > > > > -                version = 4
> > > > > > -                if netaddr.IPNetwork(ip_address).version == 6:
> > > > > > -                    version = 6
> > > > > > -                ctn.pipework(self, ip_address, name,
> > version=version)
> > > > > > -            else:
> > > > > > -                ctn.pipework(self, '0/0', name)
> > > > > > -        return ip_address
> > > > > > -
> > > > > > -    def delete(self, check_exist=True):
> > > > > > -        if check_exist:
> > > > > > -            if not self.exist():
> > > > > > -                return
> > > > > > -        if self.br_type == BRIDGE_TYPE_DOCKER:
> > > > > > -            self.execute("docker network rm %s" % self.name,
> > > > > > -                         sudo=True, retry=True)
> > > > > > -        elif self.br_type == BRIDGE_TYPE_BRCTL:
> > > > > > -            self.execute("ip link set down dev %s" % self.name,
> > > > > > -                         sudo=True, retry=True)
> > > > > > -            self.execute(
> > > > > > -                "ip link delete %s type bridge" % self.name,
> > > > > > -                sudo=True, retry=True)
> > > > > > -        elif self.br_type == BRIDGE_TYPE_OVS:
> > > > > > -            self.execute(
> > > > > > -                "ovs-vsctl del-br %s" % self.name,
> > > > > > -                sudo=True, retry=True)
> > > > > > -
> > > > > > -
> > > > > > -class Container(object):
> > > > > > -    def __init__(self, name, image=None):
> > > > > > -        self.name = name
> > > > > > -        self.image = image
> > > > > > -        self.shared_volumes = []
> > > > > > -        self.ip_addrs = []
> > > > > > -        self.ip6_addrs = []
> > > > > > -        self.is_running = False
> > > > > > -        self.eths = []
> > > > > > -        self.id = None
> > > > > > -
> > > > > > -        self.cmd = Command()
> > > > > > -        self.remove()
> > > > > > -
> > > > > > -    def docker_name(self):
> > > > > > -        if TEST_PREFIX == DEFAULT_TEST_PREFIX:
> > > > > > -            return self.name
> > > > > > -        return '{0}_{1}'.format(TEST_PREFIX, self.name)
> > > > > > -
> > > > > > -    def get_docker_id(self):
> > > > > > -        if self.id:
> > > > > > -            return self.id
> > > > > > -        else:
> > > > > > -            return self.docker_name()
> > > > > > -
> > > > > > -    def next_if_name(self):
> > > > > > -        name = 'eth{0}'.format(len(self.eths) + 1)
> > > > > > -        self.eths.append(name)
> > > > > > -        return name
> > > > > > -
> > > > > > -    def set_addr_info(self, bridge, ipv4=None, ipv6=None,
> > > > ifname='eth0'):
> > > > > > -        if ipv4:
> > > > > > -            self.ip_addrs.append((ifname, ipv4, bridge))
> > > > > > -        if ipv6:
> > > > > > -            self.ip6_addrs.append((ifname, ipv6, bridge))
> > > > > > -
> > > > > > -    def get_addr_info(self, bridge, ipv=4):
> > > > > > -        addrinfo = {}
> > > > > > -        if ipv == 4:
> > > > > > -            ip_addrs = self.ip_addrs
> > > > > > -        elif ipv == 6:
> > > > > > -            ip_addrs = self.ip6_addrs
> > > > > > -        else:
> > > > > > -            return None
> > > > > > -        for addr in ip_addrs:
> > > > > > -            if addr[2] == bridge:
> > > > > > -                addrinfo[addr[1]] = addr[0]
> > > > > > -        return addrinfo
> > > > > > -
> > > > > > -    def execute(self, cmd, capture=True, sudo=False, retry=False):
> > > > > > -        if sudo:
> > > > > > -            m = self.cmd.sudo
> > > > > > -        else:
> > > > > > -            m = self.cmd.execute
> > > > > > -        if retry:
> > > > > > -            return m(cmd, capture=capture, try_times=3,
> > interval=1)
> > > > > > -        else:
> > > > > > -            return m(cmd, capture=capture)
> > > > > > -
> > > > > > -    def dcexec(self, cmd, capture=True, retry=False):
> > > > > > -        if retry:
> > > > > > -            return self.cmd.sudo(cmd, capture=capture,
> > try_times=3,
> > > > > > interval=1)
> > > > > > -        else:
> > > > > > -            return self.cmd.sudo(cmd, capture=capture)
> > > > > > -
> > > > > > -    def exec_on_ctn(self, cmd, capture=True, detach=False):
> > > > > > -        name = self.docker_name()
> > > > > > -        flag = '-d' if detach else ''
> > > > > > -        return self.dcexec('docker exec {0} {1} {2}'.format(
> > > > > > -            flag, name, cmd), capture=capture)
> > > > > > -
> > > > > > -    def get_containers(self, allctn=False):
> > > > > > -        cmd = 'docker ps --no-trunc=true'
> > > > > > -        if allctn:
> > > > > > -            cmd += ' --all=true'
> > > > > > -        out = self.dcexec(cmd, retry=True)
> > > > > > -        containers = []
> > > > > > -        for line in out.splitlines()[1:]:
> > > > > > -            containers.append(line.split()[-1])
> > > > > > -        return containers
> > > > > > -
> > > > > > -    def exist(self, allctn=False):
> > > > > > -        return self.docker_name() in self.get_containers(allctn=
> > > > allctn)
> > > > > > -
> > > > > > -    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} --hostname {0} -id
> > > > {1}".format(self.docker_name()
> > > > > > ,
> > > > > > -
> > self.image)
> > > > > > -        self.id = self.dcexec(str(c), retry=True)
> > > > > > -        self.is_running = True
> > > > > > -        self.exec_on_ctn("ip li set up dev lo")
> > > > > > -        ipv4 = None
> > > > > > -        ipv6 = None
> > > > > > -        for line in self.exec_on_ctn("ip a show dev
> > > > eth0").split('\n'):
> > > > > > -            if line.strip().startswith("inet "):
> > > > > > -                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > -                ipv4 = elems[1]
> > > > > > -            elif line.strip().startswith("inet6 "):
> > > > > > -                elems = [e.strip() for e in line.strip().split('
> > ')]
> > > > > > -                ipv6 = elems[1]
> > > > > > -        self.set_addr_info(bridge='docker0', ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > -                           ifname='eth0')
> > > > > > -        return 0
> > > > > > -
> > > > > > -    def stop(self, check_exist=True):
> > > > > > -        if check_exist:
> > > > > > -            if not self.exist(allctn=False):
> > > > > > -                return
> > > > > > -        ctn_id = self.get_docker_id()
> > > > > > -        out = self.dcexec('docker stop -t 0 %s' % ctn_id,
> > retry=True)
> > > > > > -        self.is_running = False
> > > > > > -        return out
> > > > > > -
> > > > > > -    def remove(self, check_exist=True):
> > > > > > -        if check_exist:
> > > > > > -            if not self.exist(allctn=True):
> > > > > > -                return
> > > > > > -        ctn_id = self.get_docker_id()
> > > > > > -        out = self.dcexec('docker rm -f %s' % ctn_id, retry=True)
> > > > > > -        self.is_running = False
> > > > > > -        return out
> > > > > > -
> > > > > > -    def pipework(self, bridge, ip_addr, intf_name="", version=4):
> > > > > > -        if not self.is_running:
> > > > > > -            LOG.warning('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"
> > > > > > -        ipv4 = None
> > > > > > -        ipv6 = None
> > > > > > -        if version == 4:
> > > > > > -            ipv4 = ip_addr
> > > > > > -        else:
> > > > > > -            c << '-a 6'
> > > > > > -            ipv6 = ip_addr
> > > > > > -        c << "{0} {1}".format(self.docker_name(), ip_addr)
> > > > > > -        self.set_addr_info(bridge=bridge.name, ipv4=ipv4,
> > ipv6=ipv6,
> > > > > > -                           ifname=intf_name)
> > > > > > -        self.execute(str(c), sudo=True, retry=True)
> > > > > > -
> > > > > > -    def get_pid(self):
> > > > > > -        if self.is_running:
> > > > > > -            cmd = "docker inspect -f '{{.State.Pid}}' %s" %
> > > > > > self.docker_name()
> > > > > > -            return int(self.dcexec(cmd))
> > > > > > -        return -1
> > > > > > -
> > > > > > -    def start_tcpdump(self, interface=None, filename=None):
> > > > > > -        if not interface:
> > > > > > -            interface = "eth0"
> > > > > > -        if not filename:
> > > > > > -            filename = "{0}/{1}.dump".format(
> > > > > > -                self.shared_volumes[0][1], interface)
> > > > > > -        self.exec_on_ctn(
> > > > > > -            "tcpdump -i {0} -w {1}".format(interface, filename),
> > > > > > -            detach=True)
> > > > > > -
> > > > > > -
> > > > > > -class BGPContainer(Container):
> > > > > > -
> > > > > > -    WAIT_FOR_BOOT = 1
> > > > > > -    RETRY_INTERVAL = 5
> > > > > > -    DEFAULT_PEER_ARG = {'neigh_addr': '',
> > > > > > -                        'passwd': None,
> > > > > > -                        'vpn': False,
> > > > > > -                        'flowspec': False,
> > > > > > -                        'is_rs_client': False,
> > > > > > -                        'is_rr_client': False,
> > > > > > -                        'cluster_id': None,
> > > > > > -                        'policies': None,
> > > > > > -                        'passive': False,
> > > > > > -                        'local_addr': '',
> > > > > > -                        'as2': False,
> > > > > > -                        'graceful_restart': None,
> > > > > > -                        'local_as': None,
> > > > > > -                        'prefix_limit': None}
> > > > > > -    default_peer_keys = sorted(DEFAULT_PEER_ARG.keys())
> > > > > > -    DEFAULT_ROUTE_ARG = {'prefix': None,
> > > > > > -                         'rf': 'ipv4',
> > > > > > -                         'attr': None,
> > > > > > -                         'next-hop': None,
> > > > > > -                         'as-path': None,
> > > > > > -                         'community': None,
> > > > > > -                         'med': None,
> > > > > > -                         'local-pref': None,
> > > > > > -                         'extended-community': None,
> > > > > > -                         'matchs': None,
> > > > > > -                         'thens': None}
> > > > > > -    default_route_keys = sorted(DEFAULT_ROUTE_ARG.keys())
> > > > > > -
> > > > > > -    def __init__(self, name, asn, router_id, ctn_image_name=None):
> > > > > > -        self.config_dir = TEST_BASE_DIR
> > > > > > -        if TEST_PREFIX:
> > > > > > -            self.config_dir = os.path.join(self.config_dir,
> > > > TEST_PREFIX)
> > > > > > -        self.config_dir = os.path.join(self.config_dir, name)
> > > > > > -        self.asn = asn
> > > > > > -        self.router_id = router_id
> > > > > > -        self.peers = {}
> > > > > > -        self.routes = {}
> > > > > > -        self.policies = {}
> > > > > > -        super(BGPContainer, self).__init__(name, ctn_image_name)
> > > > > > -        self.execute(
> > > > > > -            'rm -rf {0}'.format(self.config_dir), sudo=True)
> > > > > > -        self.execute('mkdir -p {0}'.format(self.config_dir))
> > > > > > -        self.execute('chmod 777 {0}'.format(self.config_dir))
> > > > > > -
> > > > > > -    def __repr__(self):
> > > > > > -        return str({'name': self.name, 'asn': self.asn,
> > > > > > -                    'router_id': self.router_id})
> > > > > > -
> > > > > > -    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > -        self.create_config()
> > > > > > -        super(BGPContainer, self).run()
> > > > > > -        if wait:
> > > > > > -            time.sleep(w_time)
> > > > > > -        return w_time
> > > > > > -
> > > > > > -    def add_peer(self, peer, bridge='', reload_config=True,
> > v6=False,
> > > > > > -                 peer_info=None):
> > > > > > -        peer_info = peer_info or {}
> > > > > > -        self.peers[peer] = self.DEFAULT_PEER_ARG.copy()
> > > > > > -        self.peers[peer].update(peer_info)
> > > > > > -        peer_keys = sorted(self.peers[peer].keys())
> > > > > > -        if peer_keys != self.default_peer_keys:
> > > > > > -            raise Exception("argument error peer_info: %s" %
> > > > peer_info)
> > > > > > -
> > > > > > -        neigh_addr = ''
> > > > > > -        local_addr = ''
> > > > > > -        it = itertools.product(self.ip_addrs, peer.ip_addrs)
> > > > > > -        if v6:
> > > > > > -            it = itertools.product(self.ip6_addrs,
> > peer.ip6_addrs)
> > > > > > -
> > > > > > -        for me, you in it:
> > > > > > -            if bridge != '' and bridge != me[2]:
> > > > > > -                continue
> > > > > > -            if me[2] == you[2]:
> > > > > > -                neigh_addr = you[1]
> > > > > > -                local_addr = me[1]
> > > > > > -                if v6:
> > > > > > -                    addr, mask = local_addr.split('/')
> > > > > > -                    local_addr = "{0}%{1}/{2}".format(addr, me[0],
> > > > mask)
> > > > > > -                break
> > > > > > -
> > > > > > -        if neigh_addr == '':
> > > > > > -            raise Exception('peer {0} seems not ip
> > > > > > reachable'.format(peer))
> > > > > > -
> > > > > > -        if not self.peers[peer]['policies']:
> > > > > > -            self.peers[peer]['policies'] = {}
> > > > > > -
> > > > > > -        self.peers[peer]['neigh_addr'] = neigh_addr
> > > > > > -        self.peers[peer]['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 NotImplementedError()
> > > > > > -
> > > > > > -    def enable_peer(self, peer):
> > > > > > -        raise NotImplementedError()
> > > > > > -
> > > > > > -    def log(self):
> > > > > > -        return self.execute('cat {0}/*.log'.format(self.config_
> > dir))
> > > > > > -
> > > > > > -    def add_route(self, route, reload_config=True,
> > route_info=None):
> > > > > > -        route_info = route_info or {}
> > > > > > -        self.routes[route] = self.DEFAULT_ROUTE_ARG.copy()
> > > > > > -        self.routes[route].update(route_info)
> > > > > > -        route_keys = sorted(self.routes[route].keys())
> > > > > > -        if route_keys != self.default_route_keys:
> > > > > > -            raise Exception("argument error route_info: %s" %
> > > > route_info)
> > > > > > -        self.routes[route]['prefix'] = route
> > > > > > -        if self.is_running and reload_config:
> > > > > > -            self.create_config()
> > > > > > -            self.reload_config()
> > > > > > -
> > > > > > -    def add_policy(self, policy, peer, typ, default='accept',
> > > > > > -                   reload_config=True):
> > > > > > -        self.set_default_policy(peer, typ, default)
> > > > > > -        self.define_policy(policy)
> > > > > > -        self.assign_policy(peer, policy, typ)
> > > > > > -        if self.is_running and reload_config:
> > > > > > -            self.create_config()
> > > > > > -            self.reload_config()
> > > > > > -
> > > > > > -    def set_default_policy(self, peer, typ, default):
> > > > > > -        if (typ in ['in', 'out', 'import', 'export'] and
> > > > > > -                default in ['reject', 'accept']):
> > > > > > -            if 'default-policy' not in self.peers[peer]:
> > > > > > -                self.peers[peer]['default-policy'] = {}
> > > > > > -            self.peers[peer]['default-policy'][typ] = default
> > > > > > -        else:
> > > > > > -            raise Exception('wrong type or default')
> > > > > > -
> > > > > > -    def define_policy(self, policy):
> > > > > > -        self.policies[policy['name']] = policy
> > > > > > -
> > > > > > -    def assign_policy(self, peer, policy, typ):
> > > > > > -        if peer not in self.peers:
> > > > > > -            raise Exception('peer {0} not found'.format(peer.name
> > ))
> > > > > > -        name = policy['name']
> > > > > > -        if name not in self.policies:
> > > > > > -            raise Exception('policy {0} not found'.format(name))
> > > > > > -        self.peers[peer]['policies'][typ] = policy
> > > > > > -
> > > > > > -    def get_local_rib(self, peer, rf):
> > > > > > -        raise NotImplementedError()
> > > > > > -
> > > > > > -    def get_global_rib(self, rf):
> > > > > > -        raise NotImplementedError()
> > > > > > -
> > > > > > -    def get_neighbor_state(self, peer_id):
> > > > > > -        raise NotImplementedError()
> > > > > > -
> > > > > > -    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.exec_on_ctn(cmd)
> > > > > > -            LOG.info(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)
> > > > > > -            LOG.info("%s's peer %s state: %s",
> > > > > > -                     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.exec_on_ctn(cmd)
> > > > > > -
> > > > > > -    def set_ipv6_forward(self):
> > > > > > -        cmd = 'sysctl -w net.ipv6.conf.all.forwarding=1'
> > > > > > -        self.exec_on_ctn(cmd)
> > > > > > -
> > > > > > -    def create_config(self):
> > > > > > -        raise NotImplementedError()
> > > > > > -
> > > > > > -    def reload_config(self):
> > > > > > -        raise NotImplementedError()
> > > > > > diff --git a/ryu/tests/integrated/common/
> > install_docker_test_pkg.sh
> > > > > > b/ryu/tests/integrated/common/install_docker_test_pkg.sh
> > > > > > deleted file mode 100644
> > > > > > index a771dfc..0000000
> > > > > > --- a/ryu/tests/integrated/common/install_docker_test_pkg.sh
> > > > > > +++ /dev/null
> > > > > > @@ -1,43 +0,0 @@
> > > > > > -#!/bin/bash
> > > > > > -set -ex
> > > > > > -
> > > > > > -RYU_PATH=`dirname $0`
> > > > > > -
> > > > > > -source  ${RYU_PATH}/install_docker_test_pkg_common.sh
> > > > > > -
> > > > > > -function add_docker_aptline {
> > > > > > -    sudo apt-get update
> > > > > > -    if ! apt-cache search docker-engine | grep docker-engine; then
> > > > > > -        VER=`lsb_release -r`
> > > > > > -        if echo $VER | grep 12.04; then
> > > > > > -            REL_NAME=precise
> > > > > > -        elif echo $VER | grep 14.04; then
> > > > > > -            REL_NAME=trusty
> > > > > > -        elif echo $VER | grep 15.10; then
> > > > > > -            REL_NAME=wily
> > > > > > -        elif echo $VER | grep 16.04; then
> > > > > > -            REL_NAME=xenial
> > > > > > -        else
> > > > > > -            retrun 1
> > > > > > -        fi
> > > > > > -        RELEASE=ubuntu-$REL_NAME
> > > > > > -        sudo apt-key adv --keyserver
> > hkp://p80.pool.sks-keyservers.
> > > > net:80
> > > > > > --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
> > > > > > -        sudo sh -c "echo deb https://apt.dockerproject.org/repo
> > > > $RELEASE
> > > > > > main > /etc/apt/sources.list.d/docker.list"
> > > > > > -    fi
> > > > > > -}
> > > > > > -
> > > > > > -init_variables
> > > > > > -process_options "$@"
> > > > > > -
> > > > > > -if [ $APTLINE_DOCKER -eq 1 ]; then
> > > > > > -    add_docker_aptline
> > > > > > -fi
> > > > > > -
> > > > > > -sudo apt-get update
> > > > > > -if apt-cache search docker-engine | grep docker-engine; then
> > > > > > -    DOCKER_PKG=docker-engine
> > > > > > -else
> > > > > > -    DOCKER_PKG=docker.io
> > > > > > -fi
> > > > > > -sudo apt-get install -y $DOCKER_PKG
> > > > > > -install_depends_pkg
> > > > > > diff --git a/ryu/tests/integrated/common/install_docker_test_pkg_
> > > > common.sh
> > > > > > b/ryu/tests/integrated/common/install_docker_test_pkg_common.sh
> > > > > > deleted file mode 100644
> > > > > > index 44a3e10..0000000
> > > > > > --- a/ryu/tests/integrated/common/install_docker_test_pkg_
> > common.sh
> > > > > > +++ /dev/null
> > > > > > @@ -1,39 +0,0 @@
> > > > > > -#!/bin/bash
> > > > > > -set -ex
> > > > > > -
> > > > > > -function init_variables {
> > > > > > -    APTLINE_DOCKER=0
> > > > > > -    DIR_BASE=/tmp
> > > > > > -}
> > > > > > -
> > > > > > -function process_options {
> > > > > > -    local max
> > > > > > -    local i
> > > > > > -    max=$#
> > > > > > -    i=1
> > > > > > -    while [ $i -le $max ]; do
> > > > > > -        case "$1" in
> > > > > > -            -a|--add-docker-aptline)
> > > > > > -                APTLINE_DOCKER=1
> > > > > > -                ;;
> > > > > > -            -d|--download-dir)
> > > > > > -                shift; ((i++))
> > > > > > -                DIR_BASE=$1
> > > > > > -                ;;
> > > > > > -        esac
> > > > > > -        shift; ((i++))
> > > > > > -    done
> > > > > > -}
> > > > > > -
> > > > > > -function install_pipework {
> > > > > > -    if ! which /usr/local/bin/pipework >/dev/null
> > > > > > -    then
> > > > > > -        sudo rm -rf $DIR_BASE/pipework
> > > > > > -        git clone https://github.com/jpetazzo/pipework.git
> > > > > > $DIR_BASE/pipework
> > > > > > -        sudo install -m 0755 $DIR_BASE/pipework/pipework
> > > > > > /usr/local/bin/pipework
> > > > > > -    fi
> > > > > > -}
> > > > > > -
> > > > > > -function install_depends_pkg {
> > > > > > -    install_pipework
> > > > > > -}
> > > > > > diff --git a/ryu/tests/integrated/common/
> > install_docker_test_pkg_for_
> > > > travis.sh
> > > > > > b/ryu/tests/integrated/common/install_docker_test_pkg_for_
> > travis.sh
> > > > > > deleted file mode 100644
> > > > > > index d8c3b49..0000000
> > > > > > --- a/ryu/tests/integrated/common/install_docker_test_pkg_for_
> > > > travis.sh
> > > > > > +++ /dev/null
> > > > > > @@ -1,12 +0,0 @@
> > > > > > -#!/bin/bash
> > > > > > -set -ex
> > > > > > -
> > > > > > -RYU_PATH=`dirname $0`
> > > > > > -
> > > > > > -source  ${RYU_PATH}/install_docker_test_pkg_common.sh
> > > > > > -
> > > > > > -init_variables
> > > > > > -process_options "$@"
> > > > > > -
> > > > > > -sudo apt-get update
> > > > > > -install_depends_pkg
> > > > > > diff --git a/ryu/tests/integrated/common/quagga.py
> > > > > > b/ryu/tests/integrated/common/quagga.py
> > > > > > deleted file mode 100644
> > > > > > index 9b6d218..0000000
> > > > > > --- a/ryu/tests/integrated/common/quagga.py
> > > > > > +++ /dev/null
> > > > > > @@ -1,332 +0,0 @@
> > > > > > -# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
> > > > > > -#
> > > > > > -# This is based on the following
> > > > > > -#     https://github.com/osrg/gobgp/test/lib/quagga.py
> > > > > > -#
> > > > > > -# 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 __future__ import absolute_import
> > > > > > -
> > > > > > -import logging
> > > > > > -import os
> > > > > > -
> > > > > > -import netaddr
> > > > > > -
> > > > > > -from . import docker_base as base
> > > > > > -
> > > > > > -LOG = logging.getLogger(__name__)
> > > > > > -
> > > > > > -
> > > > > > -class QuaggaBGPContainer(base.BGPContainer):
> > > > > > -
> > > > > > -    WAIT_FOR_BOOT = 1
> > > > > > -    SHARED_VOLUME = '/etc/quagga'
> > > > > > -
> > > > > > -    def __init__(self, name, asn, router_id, ctn_image_name,
> > > > 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
> > > > > > -        self._create_config_debian()
> > > > > > -
> > > > > > -    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > -        w_time = super(QuaggaBGPContainer,
> > > > > > -                       self).run(wait=wait,
> > w_time=self.WAIT_FOR_BOOT)
> > > > > > -        return w_time
> > > > > > -
> > > > > > -    def get_global_rib(self, prefix='', rf='ipv4'):
> > > > > > -        rib = []
> > > > > > -        if prefix != '':
> > > > > > -            return self.get_global_rib_with_prefix(prefix, rf)
> > > > > > -
> > > > > > -        out = self.vtysh('show bgp {0} unicast'.format(rf),
> > > > config=False)
> > > > > > -        if out.startswith('No BGP network exists'):
> > > > > > -            return rib
> > > > > > -
> > > > > > -        read_next = False
> > > > > > -
> > > > > > -        for line in out.split('\n'):
> > > > > > -            ibgp = False
> > > > > > -            if line[:2] == '*>':
> > > > > > -                line = line[2:]
> > > > > > -                if line[0] == 'i':
> > > > > > -                    line = line[1:]
> > > > > > -                    ibgp = True
> > > > > > -            elif not read_next:
> > > > > > -                continue
> > > > > > -
> > > > > > -            elems = line.split()
> > > > > > -
> > > > > > -            if len(elems) == 1:
> > > > > > -                read_next = True
> > > > > > -                prefix = elems[0]
> > > > > > -                continue
> > > > > > -            elif read_next:
> > > > > > -                nexthop = elems[0]
> > > > > > -            else:
> > > > > > -                prefix = elems[0]
> > > > > > -                nexthop = elems[1]
> > > > > > -            read_next = False
> > > > > > -
> > > > > > -            rib.append({'prefix': prefix, 'nexthop': nexthop,
> > > > > > -                        'ibgp': ibgp})
> > > > > > -
> > > > > > -        return rib
> > > > > > -
> > > > > > -    def get_global_rib_with_prefix(self, prefix, rf):
> > > > > > -        rib = []
> > > > > > -
> > > > > > -        lines = [line.strip() for line in self.vtysh(
> > > > > > -            'show bgp {0} unicast {1}'.format(rf, prefix),
> > > > > > -            config=False).split('\n')]
> > > > > > -
> > > > > > -        if lines[0] == '% Network not in table':
> > > > > > -            return rib
> > > > > > -
> > > > > > -        lines = lines[2:]
> > > > > > -
> > > > > > -        if lines[0].startswith('Not advertised'):
> > > > > > -            lines.pop(0)  # another useless line
> > > > > > -        elif lines[0].startswith('Advertised to non peer-group
> > > > peers:'):
> > > > > > -            lines = lines[2:]  # other useless lines
> > > > > > -        else:
> > > > > > -            raise Exception('unknown output format
> > {0}'.format(lines))
> > > > > > -
> > > > > > -        if lines[0] == 'Local':
> > > > > > -            aspath = []
> > > > > > -        else:
> > > > > > -            aspath = [int(asn) for asn in lines[0].split()]
> > > > > > -
> > > > > > -        nexthop = lines[1].split()[0].strip()
> > > > > > -        info = [s.strip(',') for s in lines[2].split()]
> > > > > > -        attrs = []
> > > > > > -        if 'metric' in info:
> > > > > > -            med = info[info.index('metric') + 1]
> > > > > > -            attrs.append({'type': base.BGP_ATTR_TYPE_MULTI_EXIT_
> > DISC,
> > > > > > -                          'metric': int(med)})
> > > > > > -        if 'localpref' in info:
> > > > > > -            localpref = info[info.index('localpref') + 1]
> > > > > > -            attrs.append({'type': base.BGP_ATTR_TYPE_LOCAL_PREF,
> > > > > > -                          'value': int(localpref)})
> > > > > > -
> > > > > > -        rib.append({'prefix': prefix, 'nexthop': nexthop,
> > > > > > -                    'aspath': aspath, 'attrs': attrs})
> > > > > > -
> > > > > > -        return rib
> > > > > > -
> > > > > > -    def get_neighbor_state(self, peer):
> > > > > > -        if peer not in self.peers:
> > > > > > -            raise Exception('not found peer
> > > > {0}'.format(peer.router_id))
> > > > > > -
> > > > > > -        neigh_addr = self.peers[peer]['neigh_addr'].split('/')[0]
> > > > > > -
> > > > > > -        info = [l.strip() for l in self.vtysh(
> > > > > > -            'show bgp neighbors {0}'.format(neigh_addr),
> > > > > > -            config=False).split('\n')]
> > > > > > -
> > > > > > -        if not info[0].startswith('BGP neighbor is'):
> > > > > > -            raise Exception('unknown format')
> > > > > > -
> > > > > > -        idx1 = info[0].index('BGP neighbor is ')
> > > > > > -        idx2 = info[0].index(',')
> > > > > > -        n_addr = info[0][idx1 + len('BGP neighbor is '):idx2]
> > > > > > -        if n_addr == neigh_addr:
> > > > > > -            idx1 = info[2].index('= ')
> > > > > > -            state = info[2][idx1 + len('= '):]
> > > > > > -            if state.startswith('Idle'):
> > > > > > -                return base.BGP_FSM_IDLE
> > > > > > -            elif state.startswith('Active'):
> > > > > > -                return base.BGP_FSM_ACTIVE
> > > > > > -            elif state.startswith('Established'):
> > > > > > -                return base.BGP_FSM_ESTABLISHED
> > > > > > -            else:
> > > > > > -                return state
> > > > > > -
> > > > > > -        raise Exception('not found peer
> > {0}'.format(peer.router_id))
> > > > > > -
> > > > > > -    def send_route_refresh(self):
> > > > > > -        self.vtysh('clear ip bgp * soft', config=False)
> > > > > > -
> > > > > > -    def create_config(self):
> > > > > > -        zebra = 'no'
> > > > > > -        self._create_config_bgp()
> > > > > > -        if self.zebra:
> > > > > > -            zebra = 'yes'
> > > > > > -            self._create_config_zebra()
> > > > > > -        self._create_config_daemons(zebra)
> > > > > > -
> > > > > > -    def _create_config_debian(self):
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << 'vtysh_enable=yes'
> > > > > > -        c << 'zebra_options="  --daemon -A 127.0.0.1"'
> > > > > > -        c << 'bgpd_options="   --daemon -A 127.0.0.1"'
> > > > > > -        c << 'ospfd_options="  --daemon -A 127.0.0.1"'
> > > > > > -        c << 'ospf6d_options=" --daemon -A ::1"'
> > > > > > -        c << 'ripd_options="   --daemon -A 127.0.0.1"'
> > > > > > -        c << 'ripngd_options=" --daemon -A ::1"'
> > > > > > -        c << 'isisd_options="  --daemon -A 127.0.0.1"'
> > > > > > -        c << 'babeld_options=" --daemon -A 127.0.0.1"'
> > > > > > -        c << 'watchquagga_enable=yes'
> > > > > > -        c << 'watchquagga_options=(--daemon)'
> > > > > > -        with open('{0}/debian.conf'.format(self.config_dir),
> > 'w') as
> > > > f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def _create_config_daemons(self, zebra='no'):
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << 'zebra=%s' % zebra
> > > > > > -        c << 'bgpd=yes'
> > > > > > -        c << 'ospfd=no'
> > > > > > -        c << 'ospf6d=no'
> > > > > > -        c << 'ripd=no'
> > > > > > -        c << 'ripngd=no'
> > > > > > -        c << 'isisd=no'
> > > > > > -        c << 'babeld=no'
> > > > > > -        with open('{0}/daemons'.format(self.config_dir), 'w') as
> > f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def _create_config_bgp(self):
> > > > > > -
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << 'hostname bgpd'
> > > > > > -        c << 'password zebra'
> > > > > > -        c << 'router bgp {0}'.format(self.asn)
> > > > > > -        c << 'bgp router-id {0}'.format(self.router_id)
> > > > > > -        if any(info['graceful_restart'] for info in
> > > > self.peers.values()):
> > > > > > -            c << 'bgp graceful-restart'
> > > > > > -
> > > > > > -        version = 4
> > > > > > -        for peer, info in self.peers.items():
> > > > > > -            version = netaddr.IPNetwork(info['neigh_
> > addr']).version
> > > > > > -            n_addr = info['neigh_addr'].split('/')[0]
> > > > > > -            if version == 6:
> > > > > > -                c << 'no bgp default ipv4-unicast'
> > > > > > -
> > > > > > -            c << 'neighbor {0} remote-as {1}'.format(n_addr,
> > peer.asn)
> > > > > > -            if info['is_rs_client']:
> > > > > > -                c << 'neighbor {0} route-server-client'.format(n_
> > > > addr)
> > > > > > -            for typ, p in info['policies'].items():
> > > > > > -                c << 'neighbor {0} route-map {1}
> > {2}'.format(n_addr,
> > > > > > p['name'],
> > > > > > -                                                             typ)
> > > > > > -            if info['passwd']:
> > > > > > -                c << 'neighbor {0} password {1}'.format(n_addr,
> > > > > > info['passwd'])
> > > > > > -            if info['passive']:
> > > > > > -                c << 'neighbor {0} passive'.format(n_addr)
> > > > > > -            if version == 6:
> > > > > > -                c << 'address-family ipv6 unicast'
> > > > > > -                c << 'neighbor {0} activate'.format(n_addr)
> > > > > > -                c << 'exit-address-family'
> > > > > > -
> > > > > > -        for route in self.routes.values():
> > > > > > -            if route['rf'] == 'ipv4':
> > > > > > -                c << 'network {0}'.format(route['prefix'])
> > > > > > -            elif route['rf'] == 'ipv6':
> > > > > > -                c << 'address-family ipv6 unicast'
> > > > > > -                c << 'network {0}'.format(route['prefix'])
> > > > > > -                c << 'exit-address-family'
> > > > > > -            else:
> > > > > > -                raise Exception(
> > > > > > -                    'unsupported route faily:
> > > > {0}'.format(route['rf']))
> > > > > > -
> > > > > > -        if self.zebra:
> > > > > > -            if version == 6:
> > > > > > -                c << 'address-family ipv6 unicast'
> > > > > > -                c << 'redistribute connected'
> > > > > > -                c << 'exit-address-family'
> > > > > > -            else:
> > > > > > -                c << 'redistribute connected'
> > > > > > -
> > > > > > -        for name, policy in self.policies.items():
> > > > > > -            c << 'access-list {0} {1} {2}'.format(name,
> > > > policy['type'],
> > > > > > -                                                  policy['match'])
> > > > > > -            c << 'route-map {0} permit 10'.format(name)
> > > > > > -            c << 'match ip address {0}'.format(name)
> > > > > > -            c << 'set metric {0}'.format(policy['med'])
> > > > > > -
> > > > > > -        c << 'debug bgp as4'
> > > > > > -        c << 'debug bgp fsm'
> > > > > > -        c << 'debug bgp updates'
> > > > > > -        c << 'debug bgp events'
> > > > > > -        c << 'log file {0}/bgpd.log'.format(self.SHARED_VOLUME)
> > > > > > -
> > > > > > -        with open('{0}/bgpd.conf'.format(self.config_dir), 'w')
> > as f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def _create_config_zebra(self):
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << 'hostname zebra'
> > > > > > -        c << 'password zebra'
> > > > > > -        c << 'log file {0}/zebra.log'.format(self.SHARED_VOLUME)
> > > > > > -        c << 'debug zebra packet'
> > > > > > -        c << 'debug zebra kernel'
> > > > > > -        c << 'debug zebra rib'
> > > > > > -        c << ''
> > > > > > -
> > > > > > -        with open('{0}/zebra.conf'.format(self.config_dir), 'w')
> > as
> > > > f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def vtysh(self, cmd, config=True):
> > > > > > -        if not isinstance(cmd, list):
> > > > > > -            cmd = [cmd]
> > > > > > -        cmd = ' '.join("-c '{0}'".format(c) for c in cmd)
> > > > > > -        if config:
> > > > > > -            return self.exec_on_ctn(
> > > > > > -                "vtysh -d bgpd -c 'en' -c 'conf t' -c "
> > > > > > -                "'router bgp {0}' {1}".format(self.asn, cmd),
> > > > > > -                capture=True)
> > > > > > -        else:
> > > > > > -            return self.exec_on_ctn("vtysh -d bgpd
> > {0}".format(cmd),
> > > > > > -                                    capture=True)
> > > > > > -
> > > > > > -    def reload_config(self):
> > > > > > -        daemon = []
> > > > > > -        daemon.append('bgpd')
> > > > > > -        if self.zebra:
> > > > > > -            daemon.append('zebra')
> > > > > > -        for d in daemon:
> > > > > > -            cmd = '/usr/bin/pkill {0} -SIGHUP'.format(d)
> > > > > > -            self.exec_on_ctn(cmd, capture=True)
> > > > > > -
> > > > > > -
> > > > > > -class RawQuaggaBGPContainer(QuaggaBGPContainer):
> > > > > > -    def __init__(self, name, config, ctn_image_name,
> > > > > > -                 zebra=False):
> > > > > > -        asn = None
> > > > > > -        router_id = None
> > > > > > -        for line in config.split('\n'):
> > > > > > -            line = line.strip()
> > > > > > -            if line.startswith('router bgp'):
> > > > > > -                asn = int(line[len('router bgp'):].strip())
> > > > > > -            if line.startswith('bgp router-id'):
> > > > > > -                router_id = line[len('bgp router-id'):].strip()
> > > > > > -        if not asn:
> > > > > > -            raise Exception('asn not in quagga config')
> > > > > > -        if not router_id:
> > > > > > -            raise Exception('router-id not in quagga config')
> > > > > > -        self.config = config
> > > > > > -        super(RawQuaggaBGPContainer, self).__init__(name, asn,
> > > > router_id,
> > > > > > -
> > ctn_image_name,
> > > > zebra)
> > > > > > -
> > > > > > -    def create_config(self):
> > > > > > -        with open(os.path.join(self.config_dir, 'bgpd.conf'),
> > 'w')
> > > > as f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(self.config)
> > > > > > -            f.writelines(self.config)
> > > > > > diff --git a/ryu/tests/integrated/common/ryubgp.py
> > > > > > b/ryu/tests/integrated/common/ryubgp.py
> > > > > > deleted file mode 100644
> > > > > > index 8fe16f4..0000000
> > > > > > --- a/ryu/tests/integrated/common/ryubgp.py
> > > > > > +++ /dev/null
> > > > > > @@ -1,212 +0,0 @@
> > > > > > -# Copyright (C) 2016 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 __future__ import absolute_import
> > > > > > -
> > > > > > -import logging
> > > > > > -import os
> > > > > > -import time
> > > > > > -
> > > > > > -from . import docker_base as base
> > > > > > -
> > > > > > -LOG = logging.getLogger(__name__)
> > > > > > -
> > > > > > -
> > > > > > -class RyuBGPContainer(base.BGPContainer):
> > > > > > -
> > > > > > -    WAIT_FOR_BOOT = 1
> > > > > > -    SHARED_VOLUME = '/etc/ryu'
> > > > > > -
> > > > > > -    def __init__(self, name, asn, router_id, ctn_image_name):
> > > > > > -        super(RyuBGPContainer, self).__init__(name, asn,
> > router_id,
> > > > > > -                                              ctn_image_name)
> > > > > > -        self.RYU_CONF = os.path.join(self.config_dir, 'ryu.conf')
> > > > > > -        self.SHARED_RYU_CONF = os.path.join(self.SHARED_VOLUME,
> > > > > > 'ryu.conf')
> > > > > > -        self.SHARED_BGP_CONF = os.path.join(self.SHARED_VOLUME,
> > > > > > 'bgp_conf.py')
> > > > > > -        self.shared_volumes.append((self.config_dir,
> > > > self.SHARED_VOLUME))
> > > > > > -
> > > > > > -    def _create_config_ryu(self):
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << '[DEFAULT]'
> > > > > > -        c << 'verbose=True'
> > > > > > -        c << 'log_file=/etc/ryu/manager.log'
> > > > > > -        with open(self.RYU_CONF, 'w') as f:
> > > > > > -            LOG.info("[%s's new config]" % self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def _create_config_ryu_bgp(self):
> > > > > > -        c = base.CmdBuffer()
> > > > > > -        c << 'import os'
> > > > > > -        c << ''
> > > > > > -        c << 'BGP = {'
> > > > > > -        c << "    'local_as': %s," % str(self.asn)
> > > > > > -        c << "    'router_id': '%s'," % self.router_id
> > > > > > -        c << "    'neighbors': ["
> > > > > > -        c << "        {"
> > > > > > -        for peer, info in self.peers.items():
> > > > > > -            n_addr = info['neigh_addr'].split('/')[0]
> > > > > > -            c << "            'address': '%s'," % n_addr
> > > > > > -            c << "            'remote_as': %s," % str(peer.asn)
> > > > > > -            c << "            'enable_ipv4': True,"
> > > > > > -            c << "            'enable_ipv6': True,"
> > > > > > -            c << "            'enable_vpnv4': True,"
> > > > > > -            c << "            'enable_vpnv6': True,"
> > > > > > -            c << '        },'
> > > > > > -            c << '    ],'
> > > > > > -        c << "    'routes': ["
> > > > > > -        for route in self.routes.values():
> > > > > > -            c << "        {"
> > > > > > -            c << "            'prefix': '%s'," % route['prefix']
> > > > > > -            c << "        },"
> > > > > > -        c << "    ],"
> > > > > > -        c << "}"
> > > > > > -        log_conf = """LOGGING = {
> > > > > > -
> > > > > > -    # We use python logging package for logging.
> > > > > > -    'version': 1,
> > > > > > -    'disable_existing_loggers': False,
> > > > > > -
> > > > > > -    'formatters': {
> > > > > > -        'verbose': {
> > > > > > -            'format': '%(levelname)s %(asctime)s %(module)s ' +
> > > > > > -                      '[%(process)d %(thread)d] %(message)s'
> > > > > > -        },
> > > > > > -        'simple': {
> > > > > > -            'format': '%(levelname)s %(asctime)s %(module)s
> > > > %(lineno)s ' +
> > > > > > -                      '%(message)s'
> > > > > > -        },
> > > > > > -        'stats': {
> > > > > > -            'format': '%(message)s'
> > > > > > -        },
> > > > > > -    },
> > > > > > -
> > > > > > -    'handlers': {
> > > > > > -        # Outputs log to console.
> > > > > > -        'console': {
> > > > > > -            'level': 'DEBUG',
> > > > > > -            'class': 'logging.StreamHandler',
> > > > > > -            'formatter': 'simple'
> > > > > > -        },
> > > > > > -        'console_stats': {
> > > > > > -            'level': 'DEBUG',
> > > > > > -            'class': 'logging.StreamHandler',
> > > > > > -            'formatter': 'stats'
> > > > > > -        },
> > > > > > -        # Rotates log file when its size reaches 10MB.
> > > > > > -        'log_file': {
> > > > > > -            'level': 'DEBUG',
> > > > > > -            'class': 'logging.handlers.RotatingFileHandler',
> > > > > > -            'filename': os.path.join('.', 'bgpspeaker.log'),
> > > > > > -            'maxBytes': '10000000',
> > > > > > -            'formatter': 'verbose'
> > > > > > -        },
> > > > > > -        'stats_file': {
> > > > > > -            'level': 'DEBUG',
> > > > > > -            'class': 'logging.handlers.RotatingFileHandler',
> > > > > > -            'filename': os.path.join('.', 'statistics_bgps.log'),
> > > > > > -            'maxBytes': '10000000',
> > > > > > -            'formatter': 'stats'
> > > > > > -        },
> > > > > > -    },
> > > > > > -
> > > > > > -    # Fine-grained control of logging per instance.
> > > > > > -    'loggers': {
> > > > > > -        'bgpspeaker': {
> > > > > > -            'handlers': ['console', 'log_file'],
> > > > > > -            'handlers': ['console'],
> > > > > > -            'level': 'DEBUG',
> > > > > > -            'propagate': False,
> > > > > > -        },
> > > > > > -        'stats': {
> > > > > > -            'handlers': ['stats_file', 'console_stats'],
> > > > > > -            'level': 'INFO',
> > > > > > -            'propagate': False,
> > > > > > -            'formatter': 'stats',
> > > > > > -        },
> > > > > > -    },
> > > > > > -
> > > > > > -    # Root loggers.
> > > > > > -    'root': {
> > > > > > -        'handlers': ['console', 'log_file'],
> > > > > > -        'level': 'DEBUG',
> > > > > > -        'propagate': True,
> > > > > > -    },
> > > > > > -}"""
> > > > > > -        c << log_conf
> > > > > > -        with open(os.path.join(self.config_dir, 'bgp_conf.py'),
> > 'w')
> > > > as
> > > > > > f:
> > > > > > -            LOG.info("[%s's new config]", self.name)
> > > > > > -            LOG.info(str(c))
> > > > > > -            f.writelines(str(c))
> > > > > > -
> > > > > > -    def create_config(self):
> > > > > > -        self._create_config_ryu()
> > > > > > -        self._create_config_ryu_bgp()
> > > > > > -
> > > > > > -    def is_running_ryu(self):
> > > > > > -        results = self.exec_on_ctn('ps ax')
> > > > > > -        running = False
> > > > > > -        for line in results.split('\n')[1:]:
> > > > > > -            if 'ryu-manager' in line:
> > > > > > -                running = True
> > > > > > -        return running
> > > > > > -
> > > > > > -    def start_ryubgp(self, check_running=True, retry=False):
> > > > > > -        if check_running:
> > > > > > -            if self.is_running_ryu():
> > > > > > -                return True
> > > > > > -        result = False
> > > > > > -        if retry:
> > > > > > -            try_times = 3
> > > > > > -        else:
> > > > > > -            try_times = 1
> > > > > > -        cmd = "ryu-manager --verbose "
> > > > > > -        cmd += "--config-file %s " % self.SHARED_RYU_CONF
> > > > > > -        cmd += "--bgp-app-config-file %s " % self.SHARED_BGP_CONF
> > > > > > -        cmd += "ryu.services.protocols.bgp.application"
> > > > > > -        for _ in range(try_times):
> > > > > > -            self.exec_on_ctn(cmd, detach=True)
> > > > > > -            if self.is_running_ryu():
> > > > > > -                result = True
> > > > > > -                break
> > > > > > -            time.sleep(1)
> > > > > > -        return result
> > > > > > -
> > > > > > -    def stop_ryubgp(self, check_running=True, retry=False):
> > > > > > -        if check_running:
> > > > > > -            if not self.is_running_ryu():
> > > > > > -                return True
> > > > > > -        result = False
> > > > > > -        if retry:
> > > > > > -            try_times = 3
> > > > > > -        else:
> > > > > > -            try_times = 1
> > > > > > -        for _ in range(try_times):
> > > > > > -            cmd = '/usr/bin/pkill ryu-manager -SIGTERM'
> > > > > > -            self.exec_on_ctn(cmd)
> > > > > > -            if not self.is_running_ryu():
> > > > > > -                result = True
> > > > > > -                break
> > > > > > -            time.sleep(1)
> > > > > > -        return result
> > > > > > -
> > > > > > -    def run(self, wait=False, w_time=WAIT_FOR_BOOT):
> > > > > > -        w_time = super(RyuBGPContainer,
> > > > > > -                       self).run(wait=wait,
> > w_time=self.WAIT_FOR_BOOT)
> > > > > > -        return w_time
> > > > > > -
> > > > > > -    def reload_config(self):
> > > > > > -        self.stop_ryubgp(retry=True)
> > > > > > -        self.start_ryubgp(retry=True)
> > > > > > diff --git a/tests/integrated/bgp/base.py
> > > > b/tests/integrated/bgp/base.py
> > > > > > index 26fa396..2f210de 100644
> > > > > > --- a/tests/integrated/bgp/base.py
> > > > > > +++ b/tests/integrated/bgp/base.py
> > > > > > @@ -20,9 +20,9 @@ import logging
> > > > > >  import sys
> > > > > >  import unittest
> > > > > >
> > > > > > -from ryu.tests.integrated.common import docker_base as ctn_base
> > > > > > -from ryu.tests.integrated.common import ryubgp
> > > > > > -from ryu.tests.integrated.common import quagga
> > > > > > +from ryu.lib.docker import docker_base as ctn_base
> > > > > > +from ryu.lib.docker import ryubgp
> > > > > > +from ryu.lib.docker import quagga
> > > > > >
> > > > > >
> > > > > >  LOG = logging.getLogger(__name__)
> > > > > > diff --git a/tests/integrated/bgp/base_ip6.py
> > > > b/tests/integrated/bgp/base_
> > > > > > ip6.py
> > > > > > index be26faf..d867920 100644
> > > > > > --- a/tests/integrated/bgp/base_ip6.py
> > > > > > +++ b/tests/integrated/bgp/base_ip6.py
> > > > > > @@ -20,9 +20,9 @@ import logging
> > > > > >  import sys
> > > > > >  import unittest
> > > > > >
> > > > > > -from ryu.tests.integrated.common import docker_base as ctn_base
> > > > > > -from ryu.tests.integrated.common import ryubgp
> > > > > > -from ryu.tests.integrated.common import quagga
> > > > > > +from ryu.lib.docker import docker_base as ctn_base
> > > > > > +from ryu.lib.docker import ryubgp
> > > > > > +from ryu.lib.docker import quagga
> > > > > >
> > > > > >
> > > > > >  LOG = logging.getLogger(__name__)
> > > > > > diff --git a/tests/integrated/bgp/test_basic.py
> > > > > > b/tests/integrated/bgp/test_basic.py
> > > > > > index 5817d44..d1eda39 100644
> > > > > > --- a/tests/integrated/bgp/test_basic.py
> > > > > > +++ b/tests/integrated/bgp/test_basic.py
> > > > > > @@ -18,7 +18,7 @@ from __future__ import absolute_import
> > > > > >
> > > > > >  import time
> > > > > >
> > > > > > -from ryu.tests.integrated.common import docker_base as ctn_base
> > > > > > +from ryu.lib.docker import docker_base as ctn_base
> > > > > >
> > > > > >  from . import base
> > > > > >
> > > > > > diff --git a/tests/integrated/bgp/test_ip6_basic.py
> > > > > > b/tests/integrated/bgp/test_ip6_basic.py
> > > > > > index 40461a5..911a0b5 100644
> > > > > > --- a/tests/integrated/bgp/test_ip6_basic.py
> > > > > > +++ b/tests/integrated/bgp/test_ip6_basic.py
> > > > > > @@ -18,7 +18,7 @@ from __future__ import absolute_import
> > > > > >
> > > > > >  import time
> > > > > >
> > > > > > -from ryu.tests.integrated.common import docker_base as ctn_base
> > > > > > +from ryu.lib.docker import docker_base as ctn_base
> > > > > >
> > > > > >  from . import base_ip6 as base
> > > > > >
> > > > > > --
> > > > > > 2.7.4
> > > > > >
> > > > > >
> > > > > > ------------------------------------------------------------
> > > > > > ------------------
> > > > > > Check out the vibrant tech community on one of the world's most
> > > > > > engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> > > > > > _______________________________________________
> > > > > > Ryu-devel mailing list
> > > > > > Ryu-devel@lists.sourceforge.net
> > > > > > https://lists.sourceforge.net/lists/listinfo/ryu-devel
> > > > > >
> > > >
> > > > --
> > > > fumihiko kakuma <kak...@valinux.co.jp>
> > > >
> > > >
> >
> > --
> > fumihiko kakuma <kak...@valinux.co.jp>
> >
> >

-- 
fumihiko kakuma <kak...@valinux.co.jp>


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to