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>
This commit is contained in:
Alan Quillin 2016-06-03 13:23:51 -04:00 committed by FUJITA Tomonori
parent 865d6e52d7
commit 35a98fca3e
2 changed files with 282 additions and 2 deletions

View File

@ -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)

View File

@ -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):