diff options
author | Alan Quillin <alanquillin@gmail.com> | 2016-06-03 13:23:51 -0400 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-06-09 13:06:57 +0900 |
commit | 35a98fca3e92d716feee4c7cf4734c8d86f32368 (patch) | |
tree | 894d75646f04e15f3cdd85293a1e05b2d21143b8 | |
parent | 865d6e52d7e925e31a761cd0a9017576104a6f9d (diff) |
Extend OVSDB api
Adds more ovsdb methods for setting key/values to other_config and
external_ids, adds bility to set the controller for a bridge, and adds the
ability to create a new port/interface on a bridge
Signed-off-by: Alan Quillin <alanquillin@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/services/protocols/ovsdb/api.py | 273 | ||||
-rw-r--r-- | ryu/services/protocols/ovsdb/event.py | 11 |
2 files changed, 282 insertions, 2 deletions
diff --git a/ryu/services/protocols/ovsdb/api.py b/ryu/services/protocols/ovsdb/api.py index 1d399ea9..c1f04398 100644 --- a/ryu/services/protocols/ovsdb/api.py +++ b/ryu/services/protocols/ovsdb/api.py @@ -15,6 +15,34 @@ from ryu.lib import dpid as dpidlib from ryu.services.protocols.ovsdb import event as ovsdb_event +import six + +import uuid + + +def _get_table_row(table, attr_name, attr_value, tables): + sentinel = object() + + for row in tables[table].rows.values(): + if getattr(row, attr_name, sentinel) == attr_value: + return row + + +def _get_controller(tables, attr_val, attr_name='target'): + return _get_table_row('Controller', attr_name, attr_val, tables=tables) + + +def _get_bridge(tables, attr_val, attr_name='name'): + return _get_table_row('Bridge', attr_name, attr_val, tables=tables) + + +def _get_port(tables, attr_val, attr_name='name'): + return _get_table_row('Port', attr_name, attr_val, tables=tables) + + +def _get_iface(tables, attr_val, attr_name='name'): + return _get_table_row('Interface', attr_name, attr_val, tables=tables) + def match_row(manager, system_id, table, fn): def _match_row(tables): @@ -46,6 +74,30 @@ def row_by_name(manager, system_id, name, table='Bridge', fn=None): return matched_row +def rows_by_external_id(manager, system_id, key, value, + table='Bridge', fn=None): + matched_rows = match_rows(manager, system_id, table, + lambda r: (key in r.external_ids and + r.external_ids.get(key) == value)) + + if matched_rows and fn is not None: + return [fn(row) for row in matched_rows] + + return matched_rows + + +def rows_by_other_config(manager, system_id, key, value, + table='Bridge', fn=None): + matched_rows = match_rows(manager, system_id, table, + lambda r: (key in r.other_config and + r.other_config.get(key) == value)) + + if matched_rows and fn is not None: + return [fn(row) for row in matched_rows] + + return matched_rows + + def get_column_value(manager, table, record, column): """ Example : To get datapath_id from Bridge table @@ -69,6 +121,25 @@ def get_iface_by_name(manager, system_id, name, fn=None): return iface +def get_ifaces_by_external_id(manager, system_id, key, value, fn=None): + return rows_by_external_id(manager, system_id, key, value, + 'Interface', fn) + + +def get_ifaces_by_other_config(manager, system_id, key, value, fn=None): + return rows_by_other_config(manager, system_id, key, value, + 'Interface', fn) + + +def get_port_by_name(manager, system_id, name, fn=None): + port = row_by_name(manager, system_id, name, 'Port') + + if fn is not None: + return fn(port) + + return port + + def get_bridge_for_iface_name(manager, system_id, iface_name, fn=None): iface = row_by_name(manager, system_id, iface_name, 'Interface') port = match_row(manager, system_id, 'Port', @@ -156,8 +227,13 @@ def get_system_id_for_datapath_id(manager, datapath_id): return None -def get_bridges_by_system_id(manager, system_id): - return get_table(manager, system_id, 'Bridge').rows.values() +def get_bridges_by_system_id(manager, system_id, fn=None): + bridges = get_table(manager, system_id, 'Bridge').rows.values() + + if fn is not None: + return fn(bridges) + + return bridges def bridge_exists(manager, system_id, bridge_name): @@ -166,3 +242,196 @@ def bridge_exists(manager, system_id, bridge_name): def port_exists(manager, system_id, port_name): return bool(row_by_name(manager, system_id, port_name, 'Port')) + + +def set_external_id(manager, system_id, key, val, fn): + val = str(val) + + def _set_iface_external_id(tables, *_): + row = fn(tables) + + if not row: + return None + + external_ids = row.external_ids + external_ids[key] = val + row.external_ids = external_ids + + req = ovsdb_event.EventModifyRequest(system_id, _set_iface_external_id) + return manager.send_request(req) + + +def set_iface_external_id(manager, system_id, iface_name, key, val): + return set_external_id(manager, system_id, key, val, + lambda tables: _get_iface(tables, iface_name)) + + +def set_other_config(manager, system_id, key, val, fn): + val = str(val) + + def _set_iface_other_config(tables, *_): + row = fn(tables) + + if not row: + return None + + other_config = row.other_config + other_config[key] = val + row.other_config = other_config + + req = ovsdb_event.EventModifyRequest(system_id, _set_iface_other_config) + return manager.send_request(req) + + +def set_iface_other_config(manager, system_id, iface_name, key, val): + return set_other_config(manager, system_id, key, val, + lambda tables: _get_iface(tables, iface_name)) + + +def del_external_id(manager, system_id, key, fn): + def _del_iface_external_id(tables, *_): + row = fn(tables) + + if not row: + return None + + external_ids = row.external_ids + if key in external_ids: + external_ids.pop(key) + row.external_ids = external_ids + + req = ovsdb_event.EventModifyRequest(system_id, _del_iface_external_id) + return manager.send_request(req) + + +def del_iface_external_id(manager, system_id, iface_name, key): + return del_external_id(manager, system_id, key, + lambda tables: _get_iface(tables, iface_name)) + + +def del_other_config(manager, system_id, key, fn): + def _del_iface_other_config(tables, *_): + row = fn(tables) + + if not row: + return None + + other_config = row.other_config + if key in other_config: + other_config.pop(key) + row.other_config = other_config + + req = ovsdb_event.EventModifyRequest(system_id, _del_iface_other_config) + return manager.send_request(req) + + +def del_iface_other_config(manager, system_id, iface_name, key): + return del_other_config(manager, system_id, key, + lambda tables: _get_iface(tables, iface_name)) + + +def del_port(manager, system_id, bridge_name, fn): + def _delete_port(tables, *_): + bridge = _get_bridge(tables, bridge_name) + + if not bridge: + return + + port = fn(tables) + + if not port: + return + + ports = bridge.ports + ports.remove(port) + bridge.ports = ports + + req = ovsdb_event.EventModifyRequest(system_id, _delete_port) + + return manager.send_request(req) + + +def del_port_by_uuid(manager, system_id, bridge_name, port_uuid): + return del_port(manager, system_id, bridge_name, + lambda tables: _get_port(tables, port_uuid, + attr_name='uuid')) + + +def del_port_by_name(manager, system_id, bridge_name, port_name): + return del_port(manager, system_id, bridge_name, + lambda tables, _: _get_port(tables, port_name)) + + +def set_controller(manager, system_id, bridge_name, + target, controller_info=None): + def _set_controller(tables, insert): + bridge = _get_bridge(tables, bridge_name) + + controller = _get_controller(tables, target) + _uuid = None + if not controller: + _uuid = controller_info.get('uuid', uuid.uuid4()) + controller = insert(tables['Controller'], _uuid) + controller.target = target + controller.connection_mode = ['out-of-band'] + + elif 'out-of-band' not in controller.connection_mode: + controller.connection_mode = ['out-of-band'] + + if controller_info: + for key, val in six.iteritems(controller_info): + setattr(controller, key, val) + + bridge.controller = [controller] + + return _uuid + + req = ovsdb_event.EventModifyRequest(system_id, _set_controller) + return manager.send_request(req) + + +def create_port(manager, system_id, bridge_name, port_info, iface_info=None, + port_insert_uuid=None, iface_insert_uuid=None): + if iface_info is None: + iface_info = {} + + if not port_insert_uuid: + port_insert_uuid = uuid.uuid4() + + if not iface_insert_uuid: + iface_insert_uuid = uuid.uuid4() + + def _create_port(tables, insert): + bridge = _get_bridge(tables, bridge_name) + + if not bridge: + return + + default_port_name = 'port' + str(port_insert_uuid) + + if 'name' not in iface_info: + iface_info['name'] = port_info.get('name', default_port_name) + + if 'type' not in iface_info: + iface_info['type'] = 'internal' + + if 'name' not in port_info: + port_info['name'] = default_port_name + + iface = insert(tables['Interface'], iface_insert_uuid) + for key, val in six.iteritems(iface_info): + setattr(iface, key, val) + + port = insert(tables['Port'], port_insert_uuid) + for key, val in six.iteritems(port_info): + setattr(port, key, val) + + port.interfaces = [iface] + + bridge.ports = bridge.ports + [port] + + return port_insert_uuid, iface_insert_uuid + + req = ovsdb_event.EventModifyRequest(system_id, _create_port) + + return manager.send_request(req) diff --git a/ryu/services/protocols/ovsdb/event.py b/ryu/services/protocols/ovsdb/event.py index 2353a4ff..486e5c74 100644 --- a/ryu/services/protocols/ovsdb/event.py +++ b/ryu/services/protocols/ovsdb/event.py @@ -98,6 +98,9 @@ class EventModifyRequest(ryu_event.EventRequestBase): self.system_id = system_id self.func = func + def __str__(self): + return '%s<system_id=%s>' % (self.__class__.__name__, self.system_id) + class EventModifyReply(ryu_event.EventReplyBase): def __init__(self, system_id, status, insert_uuids, err_msg): @@ -106,6 +109,14 @@ class EventModifyReply(ryu_event.EventReplyBase): self.insert_uuids = insert_uuids self.err_msg = err_msg + def __str__(self): + return ('%s<system_id=%s, status=%s, insert_uuids=%s, error_msg=%s>' + % (self.__class__.__name__, + self.system_id, + self.status, + self.insert_uuids, + self.err_msg)) + class EventNewOVSDBConnection(ryu_event.EventBase): def __init__(self, system_id): |