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)
97 "other-config:datapath-id=%s" % dpid,
102 def set_of_version(sw, version="OpenFlow13,OpenFlow12,OpenFlow10"):
103 """Sets OpenFlow protocol versions on OVS switch
106 :param sw: name of switch
108 :param sw: OpenFlow versions to support on switch
111 call(["sudo", "ovs-vsctl", "set", "bridge", sw, "protocols={}".format(version)])
114 def add_vxlan_tunnel(sw):
115 """Adds VXLAN tunnel to OVS switch.
118 :param sw: name of switch
121 :Remote IP is read from flows.
123 ifaceName = "{}-vxlan-0".format(sw)
135 "options:remote_ip=flow",
141 def add_gpe_tunnel(sw):
142 """Adds GPE tunnel to OVS switch.
145 :param sw: name of switch
147 :param dpid: DataPath ID of new switches
150 :Remote IP is read from flows.
153 ifaceName = "{}-vxlangpe-0".format(sw)
165 "options:remote_ip=flow",
166 "options:dst_port=6633",
167 "options:nshc1=flow",
168 "options:nshc2=flow",
169 "options:nshc3=flow",
170 "options:nshc4=flow",
178 def launch_container(host, containerImage):
180 """Runs docker container in background.
183 :param host: container host name
185 :param dpid: DataPath ID of new switch
188 :returns string: container ID
195 containerID = check_output(
201 "--name=%s" % host["name"],
211 return containerID[:-1] # Remove extraneous \n from output of above
214 def connect_container_to_switch(sw, host, containerID):
215 """Connects docker to OVS switch.
218 :param sw: name of switch
220 :param host: host object to process.
221 Here is an example of such as object
223 'mac': '00:00:00:00:35:02',
224 'ip': '10.0.35.2/24',
226 Note: 'switch' - name of OVS switch to
227 which the host will be connected
229 :param containerID: ID of docker container
234 nw = ipaddr.IPv4Network(hostIP)
235 broadcast = "{}".format(nw.broadcast)
236 router = "{}".format(nw.network + 1)
237 ovswork_path = os.path.dirname(os.path.realpath(__file__)) + "/ovswork.sh"
238 cmd = [ovswork_path, sw, containerID, hostIP, broadcast, router, mac, host["name"]]
240 cmd.append(host["vlan"])
244 def launch(switches, hosts, odl_ip="127.0.0.1"):
245 """Connects hosts to switches. Arguments are
246 tied to underlying configuration file. Processing runs
247 for switch, that is present on local environment and
248 for hosts configured to be connected to the switch.
251 :param switches: switches to connect to
252 Example of switch object
256 :param hosts: hosts to connect
257 Example of host object
259 'mac': '00:00:00:00:35:02',
260 'ip': '10.0.35.2/24',
262 Note: 'switch' - name of OVS switch to
263 which the host will be connected
265 :param odl_ip: IP address of ODL, acting as
266 both - manager and controller.
267 Default value is '127.0.0.1'
275 if host["switch"] == sw["name"]:
277 add_switch(sw["name"], sw["dpid"])
278 set_of_version(sw["name"])
279 add_controller(sw["name"], odl_ip)
280 add_gpe_tunnel(sw["name"])
281 add_vxlan_tunnel(sw["name"])
283 containerImage = defaultContainerImage # from Config
284 if ("container_image") in host: # from Config
285 containerImage = host["container_image"]
286 containerID = launch_container(host, containerImage)
288 connect_container_to_switch(sw["name"], host, containerID)
289 host["port-name"] = "vethl-" + host["name"]
291 "Created container: %s with IP: %s. Connect using docker attach %s,"
292 "disconnect with 'ctrl-p-q'."
293 % (host["name"], host["ip"], host["name"])
297 if __name__ == "__main__":
298 if len(sys.argv) < 2 or len(sys.argv) > 3:
299 print("Please, specify IP of ODL and switch index in arguments.")
300 print("usage: ./infrastructure_launch.py ODL_IP SWITCH_INDEX")
303 controller = sys.argv[1]
305 socket.inet_aton(controller)
307 print("Error: %s is not a valid IPv4 address!" % (controller))
310 sw_index = int(sys.argv[2])
312 print(switches[sw_index])
313 if sw_index not in range(0, len(switches) + 1):
314 print(len(switches) + 1)
315 print("Error: %s is not a valid switch index!" % (sw_index))
318 sw_type = switches[sw_index]["type"]
319 sw_name = switches[sw_index]["name"]
321 print("*****************************")
322 print("Configuring %s as a GBP node." % (sw_name))
323 print("*****************************")
325 launch([switches[sw_index]], hosts, controller)
326 print("*****************************")
330 call(["sudo", "ovs-vsctl", "show"])
332 print("Docker containers:")
333 print("------------------")
334 call(["docker", "ps"])
335 print("*****************************")
336 elif sw_type == "sff":
337 print("*****************************")
338 print("Configuring %s as an SFF." % (sw_name))
339 print("*****************************")
340 call(["sudo", "ovs-vsctl", "set-manager", "tcp:%s:6640" % controller])
342 elif sw_type == "sf":
343 print("*****************************")
344 print("Configuring %s as an SF." % (sw_name))
345 print("*****************************")
348 "%s/sf-config.sh" % os.path.dirname(os.path.realpath(__file__)),