2 Script to add bridges/ports/termination points to ovsdb config
4 __author__ = 'Marcus Williams'
5 __copyright__ = "Copyright (c) 2015, Intel Corp Inc., Cisco Systems Inc. and others"
6 __credits__ = ["Jan Medved, Lori Jakab"]
7 __license__ = "New-style BSD"
8 __email__ = "marcus.williams@intel.com"
16 class OvsdbConfigBlaster (object):
17 PUT_HEADERS = {'Content-Type': 'application/json',
18 'Authorization': 'Basic YWRtaW46YWRtaW4=',
19 'Accept': 'application/json'}
20 GET_HEADERS = {'Accept': 'application/json',
21 'Authorization': 'Basic YWRtaW46YWRtaW4='}
30 vswitch_remote_ovsdb_port,
35 :param controller_ip: The ODL host ip used to send RPCs
36 :param controller_port: The RESTCONF port on the ODL host
37 :param vswitch_ip: The ip of Open vSwitch to use
38 :param vswitch_ovsdb_port: The ovsdb port of Open vSwitch to use
39 :param vswitch_remote_ip: The ip of remote Open vSwitch to use
40 :param vswitch_remote_ovsdb_port: The ovsdb port of remote Open vSwitch to use
41 :param vswitch_port_type: Port type to create
42 :param num_instances: The number of instances (bridges, ports etc) to be added
44 logging.basicConfig(level=logging.DEBUG)
45 self.session = requests.Session()
46 self.controller_ip = controller_ip
47 self.controller_port = controller_port
48 self.vswitch_dict = dict()
49 self.add_vswitch_to_dict(
52 vswitch_ovsdb_port, 'ovs-1')
54 self.add_vswitch_to_dict(
57 vswitch_remote_ovsdb_port, 'ovs-2')
58 self.vswitch_port_type = vswitch_port_type
59 self.num_instances = num_instances
61 self.connect_vswitch(self.vswitch_dict['ovs-1'])
62 if self.vswitch_dict.get('ovs-2'):
63 self.connect_vswitch(self.vswitch_dict['ovs-2'])
66 def return_ovsdb_url(vswitch_ip, vswitch_ovsdb_port, url_type="config"):
67 """ Return an ovsdb restconf url
69 :param vswitch_ip: The ip of Open vSwitch to use
70 :param vswitch_ovsdb_port: The ovsdb port of Open vSwitch to use
71 :param url_tyep: The type of url 'config' | 'oper'
74 if url_type == "config":
75 url_prefix = 'restconf/config/'
76 elif url_type == "oper":
77 url_prefix = 'restconf/operational/'
78 ovsdb_url = url_prefix \
79 + 'network-topology:' \
80 'network-topology/topology/' \
81 'ovsdb:1/node/ovsdb:%2F%2F' \
87 def add_vswitch_to_dict(self, vswitch_ip, vswitch_remote_ip, vswitch_ovsdb_port, vswitch_name):
88 """ Add details of an Open vSwitch instance to self.vswitch_dict
90 :param vswitch_ip: The ip of Open vSwitch to use
91 :param vswitch_remote_ip: The ip of remote Open vSwitch to use
92 :param vswitch_ovsdb_port: The ovsdb port of Open vSwitch to use
93 :param vswitch_name: The name to label the added Open vSwitch instance
95 urlprefix = 'http://' \
96 + self.controller_ip + \
98 + self.controller_port + \
100 self.vswitch_dict.update({vswitch_name: {
101 'name': vswitch_name,
103 'remote-ip': vswitch_remote_ip,
104 'ovsdb-port': vswitch_ovsdb_port,
105 'node-id': 'ovsdb://%s:%s'
108 'post-url': urlprefix
109 + OvsdbConfigBlaster.return_ovsdb_url(
112 'get-config-url': urlprefix
113 + OvsdbConfigBlaster.return_ovsdb_url(
116 'get-oper-url': urlprefix
117 + OvsdbConfigBlaster.return_ovsdb_url(
119 vswitch_ovsdb_port)}})
121 def connect_vswitch(self, vswitch_dict):
122 """ Connect ODL to an Open vSwitch instance using restconf
124 :param vswitch_dict: A dictionary detailing
125 an instance of Open vSwitch
128 u'network-topology:node': [
130 u'node-id': unicode(vswitch_dict['node-id']),
131 u'connection-info': {
132 u'ovsdb:remote-port': unicode(vswitch_dict['ovsdb-port']),
133 u'ovsdb:remote-ip': unicode(vswitch_dict['ip'])
138 self.send_rest(self.session,
139 vswitch_dict['post-url'],
142 def add_bridge(self, num_instances, vswitch_name='ovs-1'):
143 """Add num_instances of bridge to ODL config
145 :param num_instances: Number of bridges to create
146 :param vswitch_name: A name describing
147 an instance of Open vSwitch
150 for i in range(num_instances):
151 bridge_name = unicode('br-' + str(i) + '-test')
153 u"network-topology:node": [
155 u"node-id": u"%s/bridge/%s"
156 % (unicode(self.vswitch_dict[vswitch_name]
158 unicode(bridge_name)),
159 u"ovsdb:bridge-name": unicode(bridge_name),
160 u"ovsdb:datapath-id": u"00:00:b2:bf:48:25:f2:4b",
161 u"ovsdb:protocol-entry": [
164 u"ovsdb:ovsdb-bridge-protocol-openflow-13"
166 u"ovsdb:controller-entry": [
168 u"target": u"tcp:%s:%s" % (self.controller_ip,
169 self.controller_port)
171 u"ovsdb:managed-by": u"/network-topology:network-topology/"
172 u"network-topology:topology"
173 u"[network-topology:topology-id"
174 u"='ovsdb:1']/network-topology:node"
175 u"[network-topology:node-id="
177 % unicode(self.vswitch_dict[vswitch_name]
182 self.send_rest(self.session,
183 self.vswitch_dict[vswitch_name]
190 def add_port(self, port_type="ovsdb:interface-type-vxlan"):
191 """Add self.num_instances of port to ODL config
193 :param port_type: The type of port to create
194 default: 'ovsdb:interface-type-vxlan'
196 bridge_name = 'br-0-test'
197 self.add_bridge(1, 'ovs-1')
198 self.add_bridge(1, 'ovs-2')
200 for instance in range(self.num_instances):
201 for vswitch in self.vswitch_dict.itervalues():
202 if port_type == "ovsdb:interface-type-vxlan":
204 ovsdb_rest_url = vswitch.get('post-url') \
207 + '/termination-point/'
208 body_name = 'tp-body'
210 port_prefix = "port-"
211 ovsdb_rest_url = vswitch.get('post-url') \
215 body_name = 'port-body'
216 port_name = port_prefix + str(instance) + '-test-' + vswitch.get('ip')
218 u"network-topology:termination-point": [
222 u"ovsdb:option": u"remote_ip",
223 u"ovsdb:value": unicode(vswitch.get('remote-ip'))
226 u"ovsdb:name": unicode(port_name),
227 u"ovsdb:interface-type": unicode(port_type),
228 u"tp-id": unicode(port_name),
229 u"vlan-tag": unicode(instance + 1),
235 u"vlan-mode": u"access"
241 self.send_rest(self.session,
242 ovsdb_rest_url + port_name,
247 def send_rest(self, session, rest_url, json_body):
248 """Send an HTTP PUT to the Rest URL and return the status code
250 :param session: The HTTP session handle
251 :param json_body: the JSON body to be sent
253 :return int: status_code - HTTP status code
255 ret = session.put(rest_url,
257 headers=self.PUT_HEADERS,
259 timeout=self.TIMEOUT)
261 if ret.status_code is not 200:
262 raise ValueError(ret.text,
266 return ret.status_code
268 if __name__ == "__main__":
269 parser = argparse.ArgumentParser(description='Add bridge/port/term-points'
272 parser.add_argument('--mode', default='bridge',
273 help='Operating mode, can be "bridge", "port" or "term" \
274 (default is "bridge")')
275 parser.add_argument('--controller', default='127.0.0.1',
276 help='IP of running ODL controller (default \
278 parser.add_argument('--controllerport', default='8181',
279 help='Port of ODL RESTCONF \
281 parser.add_argument('--vswitch', default='127.0.0.1',
282 help='IP of Open vSwitch \
283 (default is 127.0.0.1)')
284 parser.add_argument('--vswitchport', default='6640',
285 help='Port of Open vSwitch OVSDB server \
287 parser.add_argument('--vswitchremote', default=None,
288 help='IP of remote Open vSwitch \
290 parser.add_argument('--vswitchremoteport', default=None,
291 help='Port of remote Open vSwitch OVSDB server \
293 parser.add_argument('--vswitchporttype', default=None,
294 help='Port of remote Open vSwitch OVSDB server \
296 parser.add_argument('--instances', type=int, default=1,
297 help='Number of instances to add/get (default 1)')
299 args = parser.parse_args()
301 ovsdb_config_blaster = OvsdbConfigBlaster(args.controller,
306 args.vswitchremoteport,
307 args.vswitchporttype,
310 if args.mode == "bridge":
311 ovsdb_config_blaster.add_bridge(ovsdb_config_blaster.num_instances)
312 elif args.mode == "term":
313 ovsdb_config_blaster.add_port()
314 elif args.mode == "port" and args.vswitchporttype is not None:
315 ovsdb_config_blaster.add_port(args.vswitchporttype)
317 print "Unsupported mode:", args.mode