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:
parent
865d6e52d7
commit
35a98fca3e
@ -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)
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user