4 Spin-up script for Opendaylight GBP and GBPSFC sample concept demonstrations.
6 This script has to be run from the environment on which OVS switches and Docker
7 containers are located. This script works together with infrastructure_config.py
8 configuration script where the entire topology for specific scenario is configured. This
9 file defines to which already existing switch docker containers have to be connected.
10 OVS switch have to be created on the same hosting environment as this script is executed
11 from. Local switch name should match one of the names specified in configuration file so that
12 docker containers are created and connected to it.
22 from subprocess import call
23 from subprocess import check_output
24 from infrastructure_config import switches
25 from infrastructure_config import hosts
26 from infrastructure_config import defaultContainerImage
29 def add_controller(sw, ip):
30 """Connects OVS switch to a controller. The switch is specified
31 by it's name and the controller by it's IP address.
34 :param sw: name of a switch on which controller is set
36 :param ip: IP address of controller
39 :Required controller should listen on TCP port 6653.
45 print "Error: %s is not a valid IPv4 address of controller!" % ip
48 call(['sudo', 'ovs-vsctl', 'set-controller', sw, 'tcp:%s:6653' % ip])
52 """Sets OVSDB manager for OVS instance.
55 :param ip: IP address of specified manager
58 :Required manager should listen on TCP port 6640.
64 print "Error: %s is not a valid IPv4 address of manager!" % ip
67 cmd = ['sudo', 'ovs-vsctl', 'set-manager', 'tcp:%s:6640' % ip]
71 def add_switch(name, dpid=None):
72 """Adds switch to OVS instance and sets it's DataPath ID
76 :param ip: name of new switch
78 :param dpid: DataPath ID of new switch
81 call(['sudo', 'ovs-vsctl', 'add-br', name]) # Add bridge
83 if len(dpid) < 16: # DPID must be 16-bytes in later versions of OVS
84 filler = '0000000000000000'
85 # prepending zeros to match 16-byt length, e.g. 123 -> 0000000000000123
86 dpid = filler[:len(filler) - len(dpid)] + dpid
88 print 'DPID: %s is too long' % dpid
90 call(['sudo', 'ovs-vsctl', 'set', 'bridge', name,
91 'other-config:datapath-id=%s' % dpid])
94 def set_of_version(sw, version='OpenFlow13,OpenFlow12,OpenFlow10'):
95 """Sets OpenFlow protocol versions on OVS switch
98 :param sw: name of switch
100 :param sw: OpenFlow versions to support on switch
103 call(['sudo', 'ovs-vsctl', 'set', 'bridge', sw, 'protocols={}'.format(version)])
106 def add_vxlan_tunnel(sw):
107 """Adds VXLAN tunnel to OVS switch.
110 :param sw: name of switch
113 :Remote IP is read from flows.
115 ifaceName = '{}-vxlan-0'.format(sw)
116 cmd = ['sudo', 'ovs-vsctl', 'add-port', sw, ifaceName,
117 '--', 'set', 'Interface', ifaceName,
119 'options:remote_ip=flow',
124 def add_gpe_tunnel(sw):
125 """Adds GPE tunnel to OVS switch.
128 :param sw: name of switch
130 :param dpid: DataPath ID of new switches
133 :Remote IP is read from flows.
136 ifaceName = '{}-vxlangpe-0'.format(sw)
137 cmd = ['sudo', 'ovs-vsctl', 'add-port', sw, ifaceName,
138 '--', 'set', 'Interface', ifaceName,
140 'options:remote_ip=flow',
141 'options:dst_port=6633',
142 'options:nshc1=flow',
143 'options:nshc2=flow',
144 'options:nshc3=flow',
145 'options:nshc4=flow',
152 def launch_container(host, containerImage):
154 """Runs docker container in background.
157 :param host: container host name
159 :param dpid: DataPath ID of new switch
162 :returns string: container ID
169 containerID = check_output(['docker',
173 '--name=%s' % host['name'],
181 return containerID[:-1] # Remove extraneous \n from output of above
184 def connect_container_to_switch(sw, host, containerID):
185 """Connects docker to OVS switch.
188 :param sw: name of switch
190 :param host: host object to process.
191 Here is an example of such as object
193 'mac': '00:00:00:00:35:02',
194 'ip': '10.0.35.2/24',
196 Note: 'switch' - name of OVS switch to
197 which the host will be connected
199 :param containerID: ID of docker container
204 nw = ipaddr.IPv4Network(hostIP)
205 broadcast = "{}".format(nw.broadcast)
206 router = "{}".format(nw.network + 1)
207 ovswork_path = os.path.dirname(os.path.realpath(__file__)) + '/ovswork.sh'
217 cmd.append(host['vlan'])
221 def launch(switches, hosts, odl_ip='127.0.0.1'):
222 """Connects hosts to switches. Arguments are
223 tied to underlying configuration file. Processing runs
224 for switch, that is present on local environment and
225 for hosts configured to be connected to the switch.
228 :param switches: switches to connect to
229 Example of switch object
233 :param hosts: hosts to connect
234 Example of host object
236 'mac': '00:00:00:00:35:02',
237 'ip': '10.0.35.2/24',
239 Note: 'switch' - name of OVS switch to
240 which the host will be connected
242 :param odl_ip: IP address of ODL, acting as
243 both - manager and controller.
244 Default value is '127.0.0.1'
252 if host['switch'] == sw['name']:
254 add_switch(sw['name'], sw['dpid'])
255 set_of_version(sw['name'])
256 add_controller(sw['name'], odl_ip)
257 add_gpe_tunnel(sw['name'])
258 add_vxlan_tunnel(sw['name'])
260 containerImage = defaultContainerImage # from Config
261 if ('container_image') in host: # from Config
262 containerImage = host['container_image']
263 containerID = launch_container(host, containerImage)
265 connect_container_to_switch(
266 sw['name'], host, containerID)
267 host['port-name'] = 'vethl-' + host['name']
268 print "Created container: %s with IP: %s. Connect using docker attach %s," \
269 "disconnect with 'ctrl-p-q'." % (host['name'], host['ip'], host['name'])
271 if __name__ == "__main__":
272 if len(sys.argv) < 2 or len(sys.argv) > 3:
273 print "Please, specify IP of ODL and switch index in arguments."
274 print "usage: ./infrastructure_launch.py ODL_IP SWITCH_INDEX"
277 controller = sys.argv[1]
279 socket.inet_aton(controller)
281 print "Error: %s is not a valid IPv4 address!" % controller
284 sw_index = int(sys.argv[2])
286 print switches[sw_index]
287 if sw_index not in range(0, len(switches) + 1):
288 print len(switches) + 1
289 print "Error: %s is not a valid switch index!" % sw_index
292 sw_type = switches[sw_index]['type']
293 sw_name = switches[sw_index]['name']
295 print "*****************************"
296 print "Configuring %s as a GBP node." % sw_name
297 print "*****************************"
299 launch([switches[sw_index]], hosts, controller)
300 print "*****************************"
304 call(['sudo', 'ovs-vsctl', 'show'])
306 print "Docker containers:"
307 print "------------------"
308 call(['docker', 'ps'])
309 print "*****************************"
310 elif sw_type == 'sff':
311 print "*****************************"
312 print "Configuring %s as an SFF." % sw_name
313 print "*****************************"
314 call(['sudo', 'ovs-vsctl', 'set-manager', 'tcp:%s:6640' % controller])
316 elif sw_type == 'sf':
317 print "*****************************"
318 print "Configuring %s as an SF." % sw_name
319 print "*****************************"
320 call(['%s/sf-config.sh' % os.path.dirname(os.path.realpath(__file__)), '%s' % sw_name])