In this recipe, we will attach existing containers to our simple network emulation. To avoid creating Docker images on our own, as it is out of scope for this book, we will use the example included in the Containernet Vagrant image.
Docker containers can be initialized in place of hosts and switches as nodes in constructing the links. Various parameters and the volumes that define the container can be specified.
Listing 9.5 gives a simple emulation of a network with containers as follows:
#!/usr/bin/env python # Python Network Programming Cookbook, Second Edition -- Chapter - 9 # This program is optimized for Python 2.7.12. # It may run on any other version with/without modifications. # Adopted from https://github.com/containernet/containernet/blob/master/examples/dockerhosts.py """ This example shows how to create a simple network and how to create docker containers (based on existing images) to it. """ from mininet.net import Containernet from mininet.node import Controller, Docker, OVSSwitch from mininet.cli import CLI from mininet.log import setLogLevel, info from mininet.link import TCLink, Link def emulate(): "Create a network with some docker containers acting as hosts." net = Containernet(controller=Controller) info('*** Adding controller ') net.addController('c0') info('*** Adding hosts ') h1 = net.addHost('h1') h2 = net.addHost('h2') info('*** Adding docker containers ') d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty") # A container with more specific params: cpu period and cpu quota d2 = net.addDocker('d2', ip='10.0.0.252', dimage="ubuntu:trusty",
cpu_period=50000, cpu_quota=25000) # Add a container as a host, using Docker class option. d3 = net.addHost('d3', ip='11.0.0.253', cls=Docker,
dimage="ubuntu:trusty", cpu_shares=20) # Add a container with a specific volume. d5 = net.addDocker('d5', dimage="ubuntu:trusty",
volumes=["/:/mnt/vol1:rw"]) info('*** Adding switch ') s1 = net.addSwitch('s1') s2 = net.addSwitch('s2', cls=OVSSwitch) s3 = net.addSwitch('s3') info('*** Creating links ') net.addLink(h1, s1) net.addLink(s1, d1) net.addLink(h2, s2) net.addLink(d2, s2) net.addLink(s1, s2) # try to add a second interface to a docker container net.addLink(d2, s3, params1={"ip": "11.0.0.254/8"}) net.addLink(d3, s3) info('*** Starting network ') net.start() # The typical ping example, with two docker instances
in place of hosts. net.ping([d1, d2]) # our extended ping functionality net.ping([d1], manualdestip="10.0.0.252") net.ping([d2, d3], manualdestip="11.0.0.254") info('*** Dynamically add a container at runtime ') d4 = net.addDocker('d4', dimage="ubuntu:trusty") # we have to specify a manual ip when we add a link at runtime net.addLink(d4, s1, params1={"ip": "10.0.0.254/8"}) # Ping docker instance d1. net.ping([d1], manualdestip="10.0.0.254") info('*** Running CLI ') CLI(net) info('*** Stopping network') net.stop() if __name__ == '__main__': setLogLevel('info') emulate()
This is the simple ping example that we have been testing in previous recipes, this time with container support. You may extend this to have more container-specific workloads and tasks. You may leverage more processes from the container itself, than from the hosting server (as opposed to the previous situation where we were able to execute applications such as vim and gedit installed in the server from the hosts emulated in Mininet):
$ python 19_5_containernet_emulation.py *** Adding controller *** Adding hosts *** Adding docker containers d1: update resources {'cpu_quota': -1} d2: update resources {'cpu_period': 50000, 'cpu_quota': 25000} d3: update resources {'cpu_quota': -1, 'cpu_shares': 20} d5: update resources {'cpu_quota': -1} *** Adding switch *** Creating links *** Starting network *** Configuring hosts h1 h2 d1 d2 d3 d5 *** defaultIntf: warning: d5 has no interfaces *** Starting controller c0 *** Starting 3 switches s1 s2 s3 ... d1 -> d2 d2 -> d1 *** Results: 0% dropped (2/2 received) d1 -> 10.0.0.252 *** Results: 0% dropped (1/1 received) d2 -> 11.0.0.254 d3 -> 11.0.0.254 *** Results: 0% dropped (2/2 received) *** Dynamically add a container at runtime d4: update resources {'cpu_quota': -1} d1 -> 10.0.0.254 *** Results: 0% dropped (1/1 received) *** Running CLI *** Starting CLI: containernet>