2 Script to add bridges/ports/termination points to ovsdb config
8 __author__ = "Marcus Williams"
9 __copyright__ = "Copyright (c) 2015, Intel Corp Inc., Cisco Systems Inc. and others"
10 __credits__ = ["Jan Medved, Lori Jakab"]
11 __license__ = "New-style BSD"
12 __email__ = "marcus.williams@intel.com"
16 class OvsdbConfigBlaster(object):
18 "Content-Type": "application/json",
19 "Authorization": "Basic YWRtaW46YWRtaW4=",
20 "Accept": "application/json",
23 "Accept": "application/json",
24 "Authorization": "Basic YWRtaW46YWRtaW4=",
27 "Accept": "application/json",
28 "Authorization": "Basic YWRtaW46YWRtaW4=",
39 vswitch_remote_ovsdb_port,
47 :param controller_ip: The ODL host ip used to send RPCs
48 :param controller_port: The RESTCONF port on the ODL host
49 :param vswitch_ip: The ip of OpenvSwitch to use
50 :param vswitch_ovsdb_port: The ovsdb port of OpenvSwitch to use
51 :param vswitch_remote_ip: The ip of remote OpenvSwitch to use
52 :param vswitch_remote_ovsdb_port: The ovsdb port of remote OpenvSwitch to use
53 :param vswitch_port_type: Port type to create
54 :param vswitch_lst_del_br: string containing a list of ovs switches on which BR'S should be deleted.
55 :param num_instances: The number of instances (bridges, ports etc)to be added
56 :param delete_ports: The number of ports to be deleted from a bridge
58 logging.basicConfig(level=logging.DEBUG)
59 self.session = requests.Session()
60 self.controller_ip = controller_ip
61 self.controller_port = controller_port
62 self.vswitch_dict = dict()
63 self.add_vswitch_to_dict(
64 vswitch_ip, vswitch_remote_ip, vswitch_ovsdb_port, "ovs-1"
67 self.add_vswitch_to_dict(
68 vswitch_remote_ip, vswitch_ip, vswitch_remote_ovsdb_port, "ovs-2"
70 self.vswitch_port_type = vswitch_port_type
71 self.vswitch_lst_del_br = vswitch_lst_del_br
72 self.num_instances = num_instances
73 self.delete_ports = delete_ports
74 self.connect_vswitch(self.vswitch_dict["ovs-1"])
75 if self.vswitch_dict.get("ovs-2"):
76 self.connect_vswitch(self.vswitch_dict["ovs-2"])
79 def return_ovsdb_url(vswitch_ip, vswitch_ovsdb_port, url_type="config"):
80 """ Return an ovsdb restconf url
82 :param vswitch_ip: The ip of Open vSwitch to use
83 :param vswitch_ovsdb_port: The ovsdb port of Open vSwitch to use
84 :param url_tyep: The type of url 'config' | 'oper'
87 if url_type == "config":
88 url_prefix = "restconf/config/"
89 elif url_type == "oper":
90 url_prefix = "restconf/operational/"
92 url_prefix + "network-topology:"
93 "network-topology/topology/"
94 "ovsdb:1/node/ovsdb:%2F%2F" + vswitch_ip + ":" + vswitch_ovsdb_port
98 def add_vswitch_to_dict(
99 self, vswitch_ip, vswitch_remote_ip, vswitch_ovsdb_port, vswitch_name
101 """ Add details of an Open vSwitch instance to self.vswitch_dict
103 :param vswitch_ip: The ip of Open vSwitch to use
104 :param vswitch_remote_ip: The ip of remote Open vSwitch to use
105 :param vswitch_ovsdb_port: The ovsdb port of Open vSwitch to use
106 :param vswitch_name: The name to label the added Open vSwitch instance
108 urlprefix = "http://" + self.controller_ip + ":" + self.controller_port + "/"
109 self.vswitch_dict.update(
112 "name": vswitch_name,
114 "remote-ip": vswitch_remote_ip,
115 "ovsdb-port": vswitch_ovsdb_port,
116 "node-id": "ovsdb://%s:%s" % (vswitch_ip, vswitch_ovsdb_port),
117 "post-url": urlprefix
118 + OvsdbConfigBlaster.return_ovsdb_url(
119 vswitch_ip, vswitch_ovsdb_port
121 "get-config-url": urlprefix
122 + OvsdbConfigBlaster.return_ovsdb_url(
123 vswitch_ip, vswitch_ovsdb_port
125 "get-oper-url": urlprefix
126 + OvsdbConfigBlaster.return_ovsdb_url(
127 vswitch_ip, vswitch_ovsdb_port
133 def connect_vswitch(self, vswitch_dict):
134 """ Connect ODL to an Open vSwitch instance using restconf
136 :param vswitch_dict: A dictionary detailing
137 an instance of Open vSwitch
140 u"network-topology:node": [
142 u"node-id": unicode(vswitch_dict["node-id"]),
143 u"connection-info": {
144 u"ovsdb:remote-port": unicode(vswitch_dict["ovsdb-port"]),
145 u"ovsdb:remote-ip": unicode(vswitch_dict["ip"]),
150 self.send_rest(self.session, vswitch_dict["post-url"], connect_ovs_body)
152 def add_bridge(self, num_instances, vswitch_name="ovs-1"):
153 """Add num_instances of bridge to ODL config
155 :param num_instances: Number of bridges to create
156 :param vswitch_name: A name describing
157 an instance of Open vSwitch
160 for i in range(num_instances):
161 bridge_name = unicode("br-" + str(i) + "-test")
163 u"network-topology:node": [
165 u"node-id": u"%s/bridge/%s"
167 unicode(self.vswitch_dict[vswitch_name].get("node-id")),
168 unicode(bridge_name),
170 u"ovsdb:bridge-name": unicode(bridge_name),
171 u"ovsdb:datapath-id": u"00:00:b2:bf:48:25:f2:4b",
172 u"ovsdb:protocol-entry": [
173 {u"protocol": u"ovsdb:ovsdb-bridge-protocol-openflow-13"}
175 u"ovsdb:controller-entry": [
177 u"target": u"tcp:%s:%s"
178 % (self.controller_ip, self.controller_port)
181 u"ovsdb:managed-by": u"/network-topology:network-topology/"
182 u"network-topology:topology"
183 u"[network-topology:topology-id"
184 u"='ovsdb:1']/network-topology:node"
185 u"[network-topology:node-id="
187 % unicode(self.vswitch_dict[vswitch_name].get("node-id")),
193 self.vswitch_dict[vswitch_name].get("post-url")
200 def add_port(self, port_type="ovsdb:interface-type-vxlan"):
201 """Add self.num_instances of port to ODL config
203 :param port_type: The type of port to create
204 default: 'ovsdb:interface-type-vxlan'
206 bridge_name = "br-0-test"
207 self.add_bridge(1, "ovs-1")
208 # self.add_bridge(1, 'ovs-2')
210 for instance in range(self.num_instances):
211 for vswitch in self.vswitch_dict.itervalues():
212 if port_type == "ovsdb:interface-type-vxlan":
215 vswitch.get("post-url")
218 + "/termination-point/"
220 body_name = "tp-body"
222 port_prefix = "port-"
224 vswitch.get("post-url")
229 body_name = "port-body"
230 port_name = port_prefix + str(instance) + "-test-" + vswitch.get("ip")
233 u"network-topology:termination-point": [
237 u"ovsdb:option": u"remote_ip",
238 u"ovsdb:value": unicode(
239 vswitch.get("remote-ip")
243 u"ovsdb:name": unicode(port_name),
244 u"ovsdb:interface-type": unicode(port_type),
245 u"tp-id": unicode(port_name),
246 u"vlan-tag": unicode(instance + 1),
247 u"trunks": [{u"trunk": u"5"}],
248 u"vlan-mode": u"access",
256 self.session, ovsdb_rest_url + port_name, body.get(body_name)
261 def delete_bridge(self, vswitch_lst_del_br, num_bridges):
262 """Delete num_instances of bridge in ODL config
264 :param num_bridges: Number of bridges to delete
265 :param vswitch_lst_del_br: A list containing instances of Open vSwitch on which bridges should be deleted.
267 for vswitch_names in vswitch_lst_del_br:
268 for br_num in range(num_bridges):
269 bridge_name = unicode("br-" + str(br_num) + "-test")
272 self.vswitch_dict[vswitch_names].get("post-url")
278 def delete_port(self, num_ports):
279 """Delete ports from ODL config
281 :param num_ports: Number of ports to delete
283 for port in range(num_ports):
284 bridge_name = "br-0-test"
285 for vswitch in self.vswitch_dict.itervalues():
288 vswitch.get("post-url")
291 + "/termination-point/"
293 port_name = port_prefix + str(port) + "-test-" + vswitch.get("ip")
294 self.send_rest_del(self.session, ovsdb_rest_url + port_name)
297 def send_rest_del(self, session, rest_url):
298 """Send an HTTP DELETE to the Rest URL and return the status code
300 :param session: The HTTP session handle
301 :return int: status_code - HTTP status code
303 ret = session.delete(
304 rest_url, headers=self.DELETE_HEADERS, stream=False, timeout=self.TIMEOUT
307 if ret.status_code is not 200:
308 raise ValueError(ret.text, ret.status_code, rest_url)
309 return ret.status_code
311 def send_rest(self, session, rest_url, json_body):
312 """Send an HTTP PUT to the Rest URL and return the status code
314 :param session: The HTTP session handle
315 :param json_body: the JSON body to be sent
317 :return int: status_code - HTTP status code
322 headers=self.PUT_HEADERS,
324 timeout=self.TIMEOUT,
327 if ret.status_code is not 200:
328 raise ValueError(ret.text, ret.status_code, rest_url, json_body)
329 return ret.status_code
332 if __name__ == "__main__":
333 parser = argparse.ArgumentParser(
334 description="Add:delete bridge/port/term-points to OpenDaylight"
340 help='Operating mode, can be "bridge", "port" or "term" \
341 (default is "bridge")',
346 help="IP of running ODL controller \
347 (default is 127.0.0.1)",
352 help="Port of ODL RESTCONF \
358 help="IP of Open vSwitch \
359 (default is 127.0.0.1)",
364 help="Port of Open vSwitch OVSDB server \
370 help="IP of remote Open vSwitch \
374 "--vswitchremoteport",
376 help="Port of remote Open vSwitch OVSDB server \
382 help="Port of remote Open vSwitch OVSDB server \
390 help="A list of switches on which to delete bridges, "
391 'uses instances for number of bridges. \
392 Example: "ovs-1 ovs2" \
399 help="delete ports of remote open vswitch ovsdb server (default 1)",
405 help="Number of instances to add/get (default 1)",
408 args = parser.parse_args()
410 ovsdb_config_blaster = OvsdbConfigBlaster(
416 args.vswitchremoteport,
417 args.vswitchporttype,
422 if args.mode == "bridge":
423 if args.deletebridges is not None:
424 ovsdb_config_blaster.delete_bridge(
425 ovsdb_config_blaster.vswitch_lst_del_br,
426 ovsdb_config_blaster.num_instances,
429 ovsdb_config_blaster.add_bridge(ovsdb_config_blaster.num_instances)
430 elif args.mode == "term":
431 if args.deleteports is not None:
432 ovsdb_config_blaster.delete_port(ovsdb_config_blaster.delete_ports)
434 ovsdb_config_blaster.add_port()
437 "please use: python ovsdbconfigblaster.py --help " "\nUnsupported mode: ",