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']))
272 if __name__ == "__main__":
273 if len(sys.argv) < 2 or len(sys.argv) > 3:
274 print("Please, specify IP of ODL and switch index in arguments.")
275 print("usage: ./infrastructure_launch.py ODL_IP SWITCH_INDEX")
278 controller = sys.argv[1]
280 socket.inet_aton(controller)
282 print("Error: %s is not a valid IPv4 address!" % (controller))
285 sw_index = int(sys.argv[2])
287 print(switches[sw_index])
288 if sw_index not in range(0, len(switches) + 1):
289 print(len(switches) + 1)
290 print("Error: %s is not a valid switch index!" % (sw_index))
293 sw_type = switches[sw_index]['type']
294 sw_name = switches[sw_index]['name']
296 print("*****************************")
297 print("Configuring %s as a GBP node." % (sw_name))
298 print("*****************************")
300 launch([switches[sw_index]], hosts, controller)
301 print("*****************************")
305 call(['sudo', 'ovs-vsctl', 'show'])
307 print("Docker containers:")
308 print("------------------")
309 call(['docker', 'ps'])
310 print("*****************************")
311 elif sw_type == 'sff':
312 print("*****************************")
313 print("Configuring %s as an SFF." % (sw_name))
314 print("*****************************")
315 call(['sudo', 'ovs-vsctl', 'set-manager', 'tcp:%s:6640' % controller])
317 elif sw_type == 'sf':
318 print("*****************************")
319 print("Configuring %s as an SF." % (sw_name))
320 print("*****************************")
321 call(['%s/sf-config.sh' % os.path.dirname(os.path.realpath(__file__)), '%s' % sw_name])