--- /dev/null
+#!/usr/bin/python
+
+"""
+Spin-up script for Opendaylight GBP and GBPSFC sample concept demonstrations.
+
+This script has to be run from the environment on which OVS switches and Docker
+containers are located. This script works together with infrastructure_config.py
+configuration script where the entire topology for specific scenario is configured. This
+file defines to which already existing switch docker containers have to be connected.
+OVS switch have to be created on the same hosting environment as this script is executed
+from. Local switch name should match one of the names specified in configuration file so that
+docker containers are created and connected to it.
+
+Updated: 22.10.2015
+
+"""
+
+import socket
+import os
+import sys
+import ipaddr
+from subprocess import call
+from subprocess import check_output
+from infrastructure_config import switches
+from infrastructure_config import hosts
+from infrastructure_config import defaultContainerImage
+
+
+def add_controller(sw, ip):
+ """Connects OVS switch to a controller. The switch is specified
+ by it's name and the controller by it's IP address.
+
+ Args:
+ :param sw: name of a switch on which controller is set
+
+ :param ip: IP address of controller
+
+ NOTE:
+ :Required controller should listen on TCP port 6653.
+ """
+
+ try:
+ socket.inet_aton(ip)
+ except socket.error:
+ print "Error: %s is not a valid IPv4 address of controller!" % ip
+ os.exit(2)
+
+ call(['sudo', 'ovs-vsctl', 'set-controller', sw, 'tcp:%s:6653' % ip])
+
+
+def add_manager(ip):
+ """Sets OVSDB manager for OVS instance.
+
+ Args:
+ :param ip: IP address of specified manager
+
+ NOTE:
+ :Required manager should listen on TCP port 6640.
+ """
+
+ try:
+ socket.inet_aton(ip)
+ except socket.error:
+ print "Error: %s is not a valid IPv4 address of manager!" % ip
+ os.exit(2)
+
+ cmd = ['sudo', 'ovs-vsctl', 'set-manager', 'tcp:%s:6640' % ip]
+ call(cmd)
+
+
+def add_switch(name, dpid=None):
+ """Adds switch to OVS instance and sets it's DataPath ID
+ if specified.
+
+ Args:
+ :param ip: name of new switch
+
+ :param dpid: DataPath ID of new switch
+ """
+
+ call(['sudo', 'ovs-vsctl', 'add-br', name]) # Add bridge
+ if dpid:
+ if len(dpid) < 16: # DPID must be 16-bytes in later versions of OVS
+ filler = '0000000000000000'
+ # prepending zeros to match 16-byt length, e.g. 123 -> 0000000000000123
+ dpid = filler[:len(filler) - len(dpid)] + dpid
+ elif len(dpid) > 16:
+ print 'DPID: %s is too long' % dpid
+ sys.exit(3)
+ call(['sudo', 'ovs-vsctl', 'set', 'bridge', name,
+ 'other-config:datapath-id=%s' % dpid])
+
+
+def set_of_version(sw, version='OpenFlow13,OpenFlow12,OpenFlow10'):
+ """Sets OpenFlow protocol versions on OVS switch
+
+ Args:
+ :param sw: name of switch
+
+ :param sw: OpenFlow versions to support on switch
+ """
+
+ call(['sudo', 'ovs-vsctl', 'set', 'bridge', sw, 'protocols={}'.format(version)])
+
+
+def add_vxlan_tunnel(sw):
+ """Adds VXLAN tunnel to OVS switch.
+
+ Args:
+ :param sw: name of switch
+
+ NOTE:
+ :Remote IP is read from flows.
+ """
+ ifaceName = '{}-vxlan-0'.format(sw)
+ cmd = ['sudo', 'ovs-vsctl', 'add-port', sw, ifaceName,
+ '--', 'set', 'Interface', ifaceName,
+ 'type=vxlan',
+ 'options:remote_ip=flow',
+ 'options:key=flow']
+ call(cmd)
+
+
+def add_gpe_tunnel(sw):
+ """Adds GPE tunnel to OVS switch.
+
+ Args:
+ :param sw: name of switch
+
+ :param dpid: DataPath ID of new switches
+
+ NOTE:
+ :Remote IP is read from flows.
+ """
+
+ ifaceName = '{}-vxlangpe-0'.format(sw)
+ cmd = ['sudo', 'ovs-vsctl', 'add-port', sw, ifaceName,
+ '--', 'set', 'Interface', ifaceName,
+ 'type=vxlan',
+ 'options:remote_ip=flow',
+ 'options:dst_port=6633',
+ 'options:nshc1=flow',
+ 'options:nshc2=flow',
+ 'options:nshc3=flow',
+ 'options:nshc4=flow',
+ 'options:nsp=flow',
+ 'options:nsi=flow',
+ 'options:key=flow']
+ call(cmd)
+
+
+def launch_container(host, containerImage):
+ # TODO use Docker.py
+ """Runs docker container in background.
+
+ Args:
+ :param host: container host name
+
+ :param dpid: DataPath ID of new switch
+
+ Returns:
+ :returns string: container ID
+
+ NOTE:
+ :No networking set.
+
+ """
+
+ containerID = check_output(['docker',
+ 'run',
+ '-d',
+ '--net=none',
+ '--name=%s' % host['name'],
+ '-h',
+ host['name'],
+ '-t',
+ '-i',
+ '--privileged=True',
+ containerImage,
+ '/bin/bash'])
+ return containerID[:-1] # Remove extraneous \n from output of above
+
+
+def connect_container_to_switch(sw, host, containerID):
+ """Connects docker to OVS switch.
+
+ Args:
+ :param sw: name of switch
+
+ :param host: host object to process.
+ Here is an example of such as object
+ {'name': 'h35_2',
+ 'mac': '00:00:00:00:35:02',
+ 'ip': '10.0.35.2/24',
+ 'switch': 'sw1'}
+ Note: 'switch' - name of OVS switch to
+ which the host will be connected
+
+ :param containerID: ID of docker container
+ """
+
+ hostIP = host['ip']
+ mac = host['mac']
+ nw = ipaddr.IPv4Network(hostIP)
+ broadcast = "{}".format(nw.broadcast)
+ router = "{}".format(nw.network + 1)
+ ovswork_path = os.path.dirname(os.path.realpath(__file__)) + '/ovswork.sh'
+ cmd = [ovswork_path,
+ sw,
+ containerID,
+ hostIP,
+ broadcast,
+ router,
+ mac,
+ host['name']]
+ if ('vlan') in host:
+ cmd.append(host['vlan'])
+ call(cmd)
+
+
+def launch(switches, hosts, odl_ip='127.0.0.1'):
+ """Connects hosts to switches. Arguments are
+ tied to underlying configuration file. Processing runs
+ for switch, that is present on local environment and
+ for hosts configured to be connected to the switch.
+
+ Args:
+ :param switches: switches to connect to
+ Example of switch object
+ {'name': 'sw1',
+ 'dpid': '1'}
+
+ :param hosts: hosts to connect
+ Example of host object
+ {'name': 'h35_2',
+ 'mac': '00:00:00:00:35:02',
+ 'ip': '10.0.35.2/24',
+ 'switch': 'sw1'}
+ Note: 'switch' - name of OVS switch to
+ which the host will be connected
+
+ :param odl_ip: IP address of ODL, acting as
+ both - manager and controller.
+ Default value is '127.0.0.1'
+ """
+
+ for sw in switches:
+ add_manager(odl_ip)
+ ports = 0
+ first_host = True
+ for host in hosts:
+ if host['switch'] == sw['name']:
+ if first_host:
+ add_switch(sw['name'], sw['dpid'])
+ set_of_version(sw['name'])
+ add_controller(sw['name'], odl_ip)
+ add_gpe_tunnel(sw['name'])
+ add_vxlan_tunnel(sw['name'])
+ first_host = False
+ containerImage = defaultContainerImage # from Config
+ if ('container_image') in host: # from Config
+ containerImage = host['container_image']
+ containerID = launch_container(host, containerImage)
+ ports += 1
+ connect_container_to_switch(
+ sw['name'], host, containerID)
+ host['port-name'] = 'vethl-' + host['name']
+ print "Created container: %s with IP: %s. Connect using docker attach %s," \
+ "disconnect with 'ctrl-p-q'." % (host['name'], host['ip'], host['name'])
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2 or len(sys.argv) > 3:
+ print "Please, specify IP of ODL and switch index in arguments."
+ print "usage: ./infrastructure_launch.py ODL_IP SWITCH_INDEX"
+ sys.exit(2)
+
+ controller = sys.argv[1]
+ try:
+ socket.inet_aton(controller)
+ except socket.error:
+ print "Error: %s is not a valid IPv4 address!" % controller
+ sys.exit(2)
+
+ sw_index = int(sys.argv[2])
+ print sw_index
+ print switches[sw_index]
+ if sw_index not in range(0, len(switches) + 1):
+ print len(switches) + 1
+ print "Error: %s is not a valid switch index!" % sw_index
+ sys.exit(2)
+
+ sw_type = switches[sw_index]['type']
+ sw_name = switches[sw_index]['name']
+ if sw_type == 'gbp':
+ print "*****************************"
+ print "Configuring %s as a GBP node." % sw_name
+ print "*****************************"
+ print
+ launch([switches[sw_index]], hosts, controller)
+ print "*****************************"
+ print "OVS status:"
+ print "-----------"
+ print
+ call(['sudo', 'ovs-vsctl', 'show'])
+ print
+ print "Docker containers:"
+ print "------------------"
+ call(['docker', 'ps'])
+ print "*****************************"
+ elif sw_type == 'sff':
+ print "*****************************"
+ print "Configuring %s as an SFF." % sw_name
+ print "*****************************"
+ call(['sudo', 'ovs-vsctl', 'set-manager', 'tcp:%s:6640' % controller])
+ print
+ elif sw_type == 'sf':
+ print "*****************************"
+ print "Configuring %s as an SF." % sw_name
+ print "*****************************"
+ call(['%s/sf-config.sh' % os.path.dirname(os.path.realpath(__file__)), '%s' % sw_name])