1 # Copyright (c) 2014 Rackspace Hosting
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from ryu.lib import dpid as dpidlib
19 from ryu.services.protocols.ovsdb import event as ovsdb_event
22 def _get_table_row(table, attr_name, attr_value, tables):
25 for row in tables[table].rows.values():
26 if getattr(row, attr_name, sentinel) == attr_value:
30 def _get_controller(tables, attr_val, attr_name='target'):
31 return _get_table_row('Controller', attr_name, attr_val, tables=tables)
34 def _get_bridge(tables, attr_val, attr_name='name'):
35 return _get_table_row('Bridge', attr_name, attr_val, tables=tables)
38 def _get_port(tables, attr_val, attr_name='name'):
39 return _get_table_row('Port', attr_name, attr_val, tables=tables)
42 def _get_iface(tables, attr_val, attr_name='name'):
43 return _get_table_row('Interface', attr_name, attr_val, tables=tables)
46 def match_row(manager, system_id, table, fn):
47 def _match_row(tables):
48 return next((r for r in tables[table].rows.values()
51 request_to_get_tables = ovsdb_event.EventReadRequest(system_id,
53 reply_to_get_tables = manager.send_request(request_to_get_tables)
54 return reply_to_get_tables.result
57 def match_rows(manager, system_id, table, fn):
58 def _match_rows(tables):
59 return (r for r in tables[table].rows.values() if fn(r))
61 request = ovsdb_event.EventReadRequest(system_id, _match_rows)
62 reply = manager.send_request(request)
66 def row_by_name(manager, system_id, name, table='Bridge', fn=None):
67 matched_row = match_row(manager, system_id, table,
68 lambda row: row.name == name)
71 return fn(matched_row)
76 def rows_by_external_id(manager, system_id, key, value,
77 table='Bridge', fn=None):
78 matched_rows = match_rows(manager, system_id, table,
79 lambda r: (key in r.external_ids and
80 r.external_ids.get(key) == value))
82 if matched_rows and fn is not None:
83 return [fn(row) for row in matched_rows]
88 def rows_by_other_config(manager, system_id, key, value,
89 table='Bridge', fn=None):
90 matched_rows = match_rows(manager, system_id, table,
91 lambda r: (key in r.other_config and
92 r.other_config.get(key) == value))
94 if matched_rows and fn is not None:
95 return [fn(row) for row in matched_rows]
100 def get_column_value(manager, table, record, column):
102 Example : To get datapath_id from Bridge table
103 get_column_value('Bridge', <bridge name>, 'datapath_id').strip('"')
105 row = row_by_name(manager, record, table)
106 value = getattr(row, column, "")
108 if isinstance(value, list) and len(value) == 1:
114 def get_iface_by_name(manager, system_id, name, fn=None):
115 iface = row_by_name(manager, system_id, name, 'Interface')
123 def get_ifaces_by_external_id(manager, system_id, key, value, fn=None):
124 return rows_by_external_id(manager, system_id, key, value,
128 def get_ifaces_by_other_config(manager, system_id, key, value, fn=None):
129 return rows_by_other_config(manager, system_id, key, value,
133 def get_port_by_name(manager, system_id, name, fn=None):
134 port = row_by_name(manager, system_id, name, 'Port')
142 def get_bridge_for_iface_name(manager, system_id, iface_name, fn=None):
143 iface = row_by_name(manager, system_id, iface_name, 'Interface')
144 port = match_row(manager, system_id, 'Port',
145 lambda x: iface in x.interfaces)
146 bridge = match_row(manager, system_id, 'Bridge',
147 lambda x: port in x.ports)
155 def get_table(manager, system_id, name):
156 def _get_table(tables):
159 request_to_get_tables = ovsdb_event.EventReadRequest(system_id,
161 reply_to_get_tables = manager.send_request(request_to_get_tables)
162 return reply_to_get_tables.result
165 def get_bridge_by_datapath_id(manager, system_id, datapath_id, fn=None):
167 row_dpid = dpidlib.str_to_dpid(str(row.datapath_id[0]))
168 return row_dpid == datapath_id
170 bridge = match_row(manager, system_id, 'Bridge', _match_fn)
178 def get_datapath_ids_for_systemd_id(manager, system_id):
179 def _get_dp_ids(tables):
182 bridges = tables.get('Bridge')
187 for bridge in bridges.rows.values():
188 datapath_ids = bridge.datapath_id
189 dp_ids.extend(dpidlib.str_to_dpid(dp_id) for dp_id in datapath_ids)
193 request = ovsdb_event.EventReadRequest(system_id, _get_dp_ids)
194 reply = manager.send_request(request)
198 def get_system_id_for_datapath_id(manager, datapath_id):
199 def _get_dp_ids(tables):
200 bridges = tables.get('Bridge')
205 for bridge in bridges.rows.values():
206 datapath_ids = [dpidlib.str_to_dpid(dp_id)
207 for dp_id in bridge.datapath_id]
209 if datapath_id in datapath_ids:
210 openvswitch = tables['Open_vSwitch'].rows
213 row = openvswitch.get(list(openvswitch.keys())[0])
214 return row.external_ids.get('system-id')
218 request = ovsdb_event.EventReadRequest(None, _get_dp_ids)
219 reply = manager.send_request(request)
221 # NOTE(jkoelker) Bulk reads return a tuple of (system_id, result)
222 for result in reply.result:
229 def get_bridges_by_system_id(manager, system_id, fn=None):
230 bridges = get_table(manager, system_id, 'Bridge').rows.values()
238 def bridge_exists(manager, system_id, bridge_name):
239 return bool(row_by_name(manager, system_id, bridge_name))
242 def port_exists(manager, system_id, port_name):
243 return bool(row_by_name(manager, system_id, port_name, 'Port'))
246 def set_external_id(manager, system_id, key, val, fn):
249 def _set_iface_external_id(tables, *_):
255 external_ids = row.external_ids
256 external_ids[key] = val
257 row.external_ids = external_ids
259 req = ovsdb_event.EventModifyRequest(system_id, _set_iface_external_id)
260 return manager.send_request(req)
263 def set_iface_external_id(manager, system_id, iface_name, key, val):
264 return set_external_id(manager, system_id, key, val,
265 lambda tables: _get_iface(tables, iface_name))
268 def set_other_config(manager, system_id, key, val, fn):
271 def _set_iface_other_config(tables, *_):
277 other_config = row.other_config
278 other_config[key] = val
279 row.other_config = other_config
281 req = ovsdb_event.EventModifyRequest(system_id, _set_iface_other_config)
282 return manager.send_request(req)
285 def set_iface_other_config(manager, system_id, iface_name, key, val):
286 return set_other_config(manager, system_id, key, val,
287 lambda tables: _get_iface(tables, iface_name))
290 def del_external_id(manager, system_id, key, fn):
291 def _del_iface_external_id(tables, *_):
297 external_ids = row.external_ids
298 if key in external_ids:
299 external_ids.pop(key)
300 row.external_ids = external_ids
302 req = ovsdb_event.EventModifyRequest(system_id, _del_iface_external_id)
303 return manager.send_request(req)
306 def del_iface_external_id(manager, system_id, iface_name, key):
307 return del_external_id(manager, system_id, key,
308 lambda tables: _get_iface(tables, iface_name))
311 def del_other_config(manager, system_id, key, fn):
312 def _del_iface_other_config(tables, *_):
318 other_config = row.other_config
319 if key in other_config:
320 other_config.pop(key)
321 row.other_config = other_config
323 req = ovsdb_event.EventModifyRequest(system_id, _del_iface_other_config)
324 return manager.send_request(req)
327 def del_iface_other_config(manager, system_id, iface_name, key):
328 return del_other_config(manager, system_id, key,
329 lambda tables: _get_iface(tables, iface_name))
332 def del_port(manager, system_id, bridge_name, fn):
333 def _delete_port(tables, *_):
334 bridge = _get_bridge(tables, bridge_name)
348 req = ovsdb_event.EventModifyRequest(system_id, _delete_port)
350 return manager.send_request(req)
353 def del_port_by_uuid(manager, system_id, bridge_name, port_uuid):
354 return del_port(manager, system_id, bridge_name,
355 lambda tables: _get_port(tables, port_uuid,
359 def del_port_by_name(manager, system_id, bridge_name, port_name):
360 return del_port(manager, system_id, bridge_name,
361 lambda tables: _get_port(tables, port_name))
364 def set_controller(manager, system_id, bridge_name,
365 target, controller_info=None):
366 controller_info = controller_info or {}
368 def _set_controller(tables, insert):
369 bridge = _get_bridge(tables, bridge_name)
371 controller = _get_controller(tables, target)
374 _uuid = controller_info.get('uuid', uuid.uuid4())
375 controller = insert(tables['Controller'], _uuid)
376 controller.target = target
377 controller.connection_mode = ['out-of-band']
379 elif 'out-of-band' not in controller.connection_mode:
380 controller.connection_mode = ['out-of-band']
383 for key, val in controller_info.items():
384 setattr(controller, key, val)
386 bridge.controller = [controller]
390 req = ovsdb_event.EventModifyRequest(system_id, _set_controller)
391 return manager.send_request(req)
394 def create_port(manager, system_id, bridge_name, port_info, iface_info=None,
395 port_insert_uuid=None, iface_insert_uuid=None):
396 if iface_info is None:
399 if not port_insert_uuid:
400 port_insert_uuid = uuid.uuid4()
402 if not iface_insert_uuid:
403 iface_insert_uuid = uuid.uuid4()
405 def _create_port(tables, insert):
406 bridge = _get_bridge(tables, bridge_name)
411 default_port_name = 'port' + str(port_insert_uuid)
413 if 'name' not in iface_info:
414 iface_info['name'] = port_info.get('name', default_port_name)
416 if 'type' not in iface_info:
417 iface_info['type'] = 'internal'
419 if 'name' not in port_info:
420 port_info['name'] = default_port_name
422 iface = insert(tables['Interface'], iface_insert_uuid)
423 for key, val in iface_info.items():
424 setattr(iface, key, val)
426 port = insert(tables['Port'], port_insert_uuid)
427 for key, val in port_info.items():
428 setattr(port, key, val)
430 port.interfaces = [iface]
432 bridge.ports = bridge.ports + [port]
434 return port_insert_uuid, iface_insert_uuid
436 req = ovsdb_event.EventModifyRequest(system_id, _create_port)
438 return manager.send_request(req)