summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlan Quillin <alanquillin@gmail.com>2016-06-03 13:23:51 -0400
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-06-09 13:06:57 +0900
commit35a98fca3e92d716feee4c7cf4734c8d86f32368 (patch)
tree894d75646f04e15f3cdd85293a1e05b2d21143b8
parent865d6e52d7e925e31a761cd0a9017576104a6f9d (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.py273
-rw-r--r--ryu/services/protocols/ovsdb/event.py11
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):