mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-21 00:40:46 +02:00
ovs: merge branch 'th/ovs-external-ids-2'
https://bugzilla.redhat.com/show_bug.cgi?id=1866227 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/679
This commit is contained in:
commit
7595a8f817
12 changed files with 819 additions and 282 deletions
|
|
@ -12,25 +12,68 @@ import sys
|
|||
import os
|
||||
import re
|
||||
import pprint
|
||||
import subprocess
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version("NM", "1.0")
|
||||
from gi.repository import GLib, NM
|
||||
|
||||
###############################################################################
|
||||
|
||||
MODE_GET = "get"
|
||||
MODE_SET = "set"
|
||||
MODE_APPLY = "apply"
|
||||
|
||||
|
||||
def memoize0(f):
|
||||
result = []
|
||||
|
||||
def helper():
|
||||
if len(result) == 0:
|
||||
result.append(f())
|
||||
return result[0]
|
||||
|
||||
return helper
|
||||
|
||||
|
||||
def memoize(f):
|
||||
memo = {}
|
||||
|
||||
def helper(x):
|
||||
if x not in memo:
|
||||
memo[x] = f(x)
|
||||
return memo[x]
|
||||
|
||||
return helper
|
||||
|
||||
|
||||
def pr(v):
|
||||
pprint.pprint(v, indent=4, depth=5, width=60)
|
||||
|
||||
|
||||
HAS_LIBNM_DEBUG = os.getenv("LIBNM_CLIENT_DEBUG") is not None
|
||||
@memoize0
|
||||
def is_libnm_debug():
|
||||
return os.getenv("LIBNM_CLIENT_DEBUG") is not None
|
||||
|
||||
|
||||
@memoize0
|
||||
def can_sudo():
|
||||
try:
|
||||
return (
|
||||
subprocess.run(
|
||||
["sudo", "-n", "true"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
).returncode
|
||||
== 0
|
||||
)
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def _print(msg=""):
|
||||
if HAS_LIBNM_DEBUG:
|
||||
if is_libnm_debug():
|
||||
# we want to use the same logging mechanism as libnm's debug
|
||||
# logging with "LIBNM_CLIENT_DEBUG=trace,stdout".
|
||||
NM.utils_print(0, msg + "\n")
|
||||
|
|
@ -63,12 +106,106 @@ def mainloop_run(timeout_msec=0, mainloop=None):
|
|||
return not timeout_reached
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
def connection_update2(remote_connection, connection):
|
||||
|
||||
mainloop = GLib.MainLoop()
|
||||
result_error = []
|
||||
|
||||
def cb(c, result):
|
||||
try:
|
||||
c.update2_finish(result)
|
||||
except Exception as e:
|
||||
result_error.append(e)
|
||||
mainloop.quit()
|
||||
|
||||
remote_connection.update2(
|
||||
connection.to_dbus(NM.ConnectionSerializationFlags.ALL),
|
||||
NM.SettingsUpdate2Flags.NO_REAPPLY,
|
||||
None,
|
||||
None,
|
||||
cb,
|
||||
)
|
||||
|
||||
mainloop_run(mainloop=mainloop)
|
||||
|
||||
if result_error:
|
||||
raise result_error[0]
|
||||
|
||||
|
||||
def device_get_applied_connection(device):
|
||||
mainloop = GLib.MainLoop()
|
||||
rr = []
|
||||
|
||||
def cb(c, result):
|
||||
try:
|
||||
con, version_id = c.get_applied_connection_finish(result)
|
||||
except Exception as e:
|
||||
rr.append(e)
|
||||
else:
|
||||
rr.append(con)
|
||||
rr.append(version_id)
|
||||
mainloop.quit()
|
||||
|
||||
device.get_applied_connection_async(0, None, cb)
|
||||
|
||||
mainloop_run(mainloop=mainloop)
|
||||
|
||||
if len(rr) == 1:
|
||||
raise rr[0]
|
||||
return rr[0], rr[1]
|
||||
|
||||
|
||||
def device_reapply(device, connection, version_id):
|
||||
|
||||
mainloop = GLib.MainLoop()
|
||||
result_error = []
|
||||
|
||||
def cb(d, result):
|
||||
try:
|
||||
d.reapply_finish(result)
|
||||
except Exception as e:
|
||||
result_error.append(e)
|
||||
mainloop.quit()
|
||||
|
||||
device.reapply_async(connection, version_id, 0, None, cb)
|
||||
|
||||
mainloop_run(mainloop=mainloop)
|
||||
|
||||
if len(result_error) == 1:
|
||||
raise result_error[0]
|
||||
|
||||
|
||||
def ovs_print_external_ids(prefix):
|
||||
if not can_sudo():
|
||||
_print(prefix + ": not running as root and cannot call ovs-vsctl")
|
||||
return
|
||||
|
||||
cmds = [["ovs-vsctl", "show"]]
|
||||
for typ in ["Bridge", "Port", "Interface"]:
|
||||
cmds += [["ovs-vsctl", "--columns=name,external-ids", "list", typ]]
|
||||
|
||||
out = ""
|
||||
for cmd in cmds:
|
||||
p = subprocess.run(cmd, stdout=subprocess.PIPE, check=True,)
|
||||
out += p.stdout.decode("utf-8") + "\n"
|
||||
out = "\n".join([prefix + s for s in out.split("\n")])
|
||||
_print(out)
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
def usage():
|
||||
_print("%s g[et] PROFILE [ GETTER ]" % (sys.argv[0]))
|
||||
_print("%s s[et] [--test] PROFILE SETTER" % (sys.argv[0]))
|
||||
_print("%s g[et] PROFILE [ GETTER ]" % (sys.argv[0]))
|
||||
_print("%s s[et] PROFILE SETTER [--test]" % (sys.argv[0]))
|
||||
_print("%s a[pply] DEVICE SETTER [--test]" % (sys.argv[0]))
|
||||
_print(
|
||||
" PROFILE := [id | uuid | type] STRING | [ ~id | ~type ] REGEX_STRING | STRING"
|
||||
)
|
||||
_print(" DEVICE := [iface] STRING")
|
||||
_print(" GETTER := ( KEY | ~REGEX_KEY ) [... GETTER]")
|
||||
_print(" SETTER := ( + | - | -KEY | [+]KEY VALUE ) [... SETTER]")
|
||||
|
||||
|
|
@ -88,7 +225,7 @@ def parse_args(argv):
|
|||
had_dash_dash = False
|
||||
args = {
|
||||
"mode": MODE_GET,
|
||||
"profile_arg": None,
|
||||
"select_arg": None,
|
||||
"ids_arg": [],
|
||||
"do_test": False,
|
||||
}
|
||||
|
|
@ -101,6 +238,8 @@ def parse_args(argv):
|
|||
args["mode"] = MODE_SET
|
||||
elif a in ["g", "get"]:
|
||||
args["mode"] = MODE_GET
|
||||
elif a in ["a", "apply"]:
|
||||
args["mode"] = MODE_APPLY
|
||||
else:
|
||||
die_usage("unexpected mode argument '%s'" % (a))
|
||||
i += 1
|
||||
|
|
@ -111,17 +250,22 @@ def parse_args(argv):
|
|||
i += 1
|
||||
continue
|
||||
|
||||
if args["profile_arg"] is None:
|
||||
if a in ["id", "~id", "uuid", "type", "~type"]:
|
||||
if args["select_arg"] is None:
|
||||
if args["mode"] == MODE_APPLY:
|
||||
possible_selects = ["iface"]
|
||||
else:
|
||||
possible_selects = ["id", "~id", "uuid", "type", "~type"]
|
||||
|
||||
if a in possible_selects:
|
||||
if i + 1 >= len(argv):
|
||||
die_usage("'%s' requires an argument'" % (a))
|
||||
args["profile_arg"] = (a, argv[i + 1])
|
||||
args["select_arg"] = (a, argv[i + 1])
|
||||
i += 2
|
||||
continue
|
||||
|
||||
if a == "*":
|
||||
a = None
|
||||
args["profile_arg"] = ("*", a)
|
||||
args["select_arg"] = ("*", a)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
|
|
@ -156,6 +300,12 @@ def parse_args(argv):
|
|||
return args
|
||||
|
||||
|
||||
def device_to_str(device, show_type=False):
|
||||
if show_type:
|
||||
return "%s (%s)" % (device.get_iface(), device.get_type_desc())
|
||||
return "%s" % (device.get_iface(),)
|
||||
|
||||
|
||||
def connection_to_str(connection, show_type=False):
|
||||
if show_type:
|
||||
return "%s (%s, %s)" % (
|
||||
|
|
@ -166,15 +316,38 @@ def connection_to_str(connection, show_type=False):
|
|||
return "%s (%s)" % (connection.get_id(), connection.get_uuid())
|
||||
|
||||
|
||||
def connections_filter(connections, profile_arg):
|
||||
def devices_filter(devices, select_arg):
|
||||
devices = list(sorted(devices, key=device_to_str))
|
||||
if not select_arg:
|
||||
return devices
|
||||
# we preserve the order of the selected devices. And
|
||||
# if devices are selected multiple times, we return
|
||||
# them multiple times.
|
||||
l = []
|
||||
f = select_arg
|
||||
for d in devices:
|
||||
if f[0] == "iface":
|
||||
if f[1] == d.get_iface():
|
||||
l.append(d)
|
||||
else:
|
||||
assert f[0] == "*"
|
||||
if f[1] is None:
|
||||
l.append(d)
|
||||
else:
|
||||
if f[1] in [d.get_iface()]:
|
||||
l.append(d)
|
||||
return l
|
||||
|
||||
|
||||
def connections_filter(connections, select_arg):
|
||||
connections = list(sorted(connections, key=connection_to_str))
|
||||
if not profile_arg:
|
||||
if not select_arg:
|
||||
return connections
|
||||
# we preserve the order of the selected connections. And
|
||||
# if connections are selected multiple times, we return
|
||||
# them multiple times.
|
||||
l = []
|
||||
f = profile_arg
|
||||
f = select_arg
|
||||
for c in connections:
|
||||
if f[0] == "id":
|
||||
if f[1] == c.get_id():
|
||||
|
|
@ -218,6 +391,7 @@ def ids_select(ids, mode, ids_arg):
|
|||
if d not in requested:
|
||||
requested.append(d)
|
||||
else:
|
||||
assert mode in [MODE_SET, MODE_APPLY]
|
||||
d2 = d[0]
|
||||
assert d2[0] in ["-", "+"]
|
||||
d3 = d2[1:]
|
||||
|
|
@ -241,7 +415,8 @@ def connection_print(connection, mode, ids_arg, dbus_path, prefix=""):
|
|||
_print(
|
||||
"%s%s [%s]" % (prefix, connection_to_str(connection, show_type=True), num_str)
|
||||
)
|
||||
_print("%s %s" % (prefix, dbus_path))
|
||||
if dbus_path:
|
||||
_print("%s %s" % (prefix, dbus_path))
|
||||
if sett is not None:
|
||||
dd = sett.get_property(NM.SETTING_OVS_EXTERNAL_IDS_DATA)
|
||||
else:
|
||||
|
|
@ -255,25 +430,7 @@ def connection_print(connection, mode, ids_arg, dbus_path, prefix=""):
|
|||
_print('%s "%s" = <unset>' % (prefix, k))
|
||||
|
||||
|
||||
def do_get(connections, ids_arg):
|
||||
first_line = True
|
||||
for c in connections:
|
||||
if first_line:
|
||||
first_line = False
|
||||
else:
|
||||
_print()
|
||||
connection_print(c, MODE_GET, ids_arg, dbus_path=c.get_path())
|
||||
|
||||
|
||||
def do_set(nmc, connection, ids_arg, do_test):
|
||||
|
||||
remote_connection = connection
|
||||
connection = NM.SimpleConnection.new_clone(remote_connection)
|
||||
|
||||
connection_print(
|
||||
connection, MODE_SET, [], remote_connection.get_path(), prefix="BEFORE: "
|
||||
)
|
||||
_print()
|
||||
def sett_update(connection, ids_arg):
|
||||
|
||||
sett = connection.get_setting(NM.SettingOvsExternalIDs)
|
||||
|
||||
|
|
@ -334,34 +491,39 @@ def do_set(nmc, connection, ids_arg, do_test):
|
|||
_print(' SET: "%s" = "%s" (unchanged)' % (key, val))
|
||||
sett.set_data(key, val)
|
||||
|
||||
|
||||
def do_get(connections, ids_arg):
|
||||
first_line = True
|
||||
for c in connections:
|
||||
if first_line:
|
||||
first_line = False
|
||||
else:
|
||||
_print()
|
||||
connection_print(c, MODE_GET, ids_arg, dbus_path=c.get_path())
|
||||
|
||||
|
||||
def do_set(nmc, connection, ids_arg, do_test):
|
||||
|
||||
remote_connection = connection
|
||||
connection = NM.SimpleConnection.new_clone(remote_connection)
|
||||
|
||||
connection_print(
|
||||
connection, MODE_SET, [], remote_connection.get_path(), prefix="BEFORE: "
|
||||
)
|
||||
_print()
|
||||
|
||||
sett_update(connection, ids_arg)
|
||||
|
||||
if do_test:
|
||||
_print()
|
||||
_print("Only show. Run without --test to set")
|
||||
return
|
||||
|
||||
mainloop = GLib.MainLoop()
|
||||
result_error = []
|
||||
|
||||
def callback(c, result):
|
||||
try:
|
||||
c.update2_finish(result)
|
||||
except Exception as e:
|
||||
result_error.append(e)
|
||||
mainloop.quit()
|
||||
|
||||
remote_connection.update2(
|
||||
connection.to_dbus(NM.ConnectionSerializationFlags.ALL),
|
||||
NM.SettingsUpdate2Flags.NO_REAPPLY,
|
||||
None,
|
||||
None,
|
||||
callback,
|
||||
)
|
||||
|
||||
mainloop_run(mainloop=mainloop)
|
||||
|
||||
if result_error:
|
||||
try:
|
||||
connection_update2(remote_connection, connection)
|
||||
except Exception as e:
|
||||
_print()
|
||||
_print("FAILURE to commit connection: %s" % (result_error[0]))
|
||||
_print("FAILURE to commit connection: %s" % (e))
|
||||
return
|
||||
|
||||
# NMClient received the completion of Update2() call. It also received
|
||||
|
|
@ -397,6 +559,68 @@ def do_set(nmc, connection, ids_arg, do_test):
|
|||
_print("WARNING: resulting connection is not as expected")
|
||||
|
||||
|
||||
def do_apply(nmc, device, ids_arg, do_test):
|
||||
|
||||
try:
|
||||
connection_orig, version_id = device_get_applied_connection(device)
|
||||
except Exception as e:
|
||||
_print(
|
||||
'failure to get applied connection for %s: %s"' % (device_to_str(device), e)
|
||||
)
|
||||
die("The device does not seem active? Nothing to reapply")
|
||||
|
||||
_print(
|
||||
"REAPPLY device %s (%s) with connection %s (version-id = %s)"
|
||||
% (
|
||||
device_to_str(device),
|
||||
NM.Object.get_path(device),
|
||||
connection_to_str(connection_orig),
|
||||
version_id,
|
||||
)
|
||||
)
|
||||
_print()
|
||||
|
||||
ovs_print_external_ids("BEFORE-OVS-VSCTL: ")
|
||||
_print()
|
||||
|
||||
connection = NM.SimpleConnection.new_clone(connection_orig)
|
||||
|
||||
connection_print(connection, MODE_APPLY, [], device.get_path(), prefix="BEFORE: ")
|
||||
_print()
|
||||
|
||||
sett_update(connection, ids_arg)
|
||||
|
||||
if do_test:
|
||||
_print()
|
||||
_print("Only show. Run without --test to set")
|
||||
return
|
||||
|
||||
_print()
|
||||
_print("reapply...")
|
||||
|
||||
try:
|
||||
device_reapply(device, connection, version_id)
|
||||
except Exception as e:
|
||||
_print()
|
||||
_print("FAILURE to commit connection: %s" % (e))
|
||||
return
|
||||
|
||||
try:
|
||||
connection_after, version_id = device_get_applied_connection(device)
|
||||
except Exception as e:
|
||||
_print(
|
||||
'failure to get applied connection after reapply for device %s: %s"'
|
||||
% (device_to_str(device), e)
|
||||
)
|
||||
die("FAILURE to get applied connection after reapply")
|
||||
|
||||
_print()
|
||||
connection_print(connection, MODE_APPLY, [], device.get_path(), prefix="AFTER: ")
|
||||
_print()
|
||||
|
||||
ovs_print_external_ids("AFTER-OVS-VSCTL: ")
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
@ -405,21 +629,35 @@ if __name__ == "__main__":
|
|||
|
||||
nmc = NM.Client.new(None)
|
||||
|
||||
connections = connections_filter(nmc.get_connections(), args["profile_arg"])
|
||||
if args["mode"] == MODE_APPLY:
|
||||
|
||||
if args["mode"] == MODE_SET:
|
||||
if len(connections) != 1:
|
||||
devices = devices_filter(nmc.get_devices(), args["select_arg"])
|
||||
|
||||
if len(devices) != 1:
|
||||
_print(
|
||||
"To set the external-ids of a connection, exactly one connection must be selected via id|uuid. Instead, %s connection matched ([%s])"
|
||||
% (
|
||||
len(connections),
|
||||
", ".join([connection_to_str(c) for c in connections]),
|
||||
)
|
||||
"To apply the external-ids of a device, exactly one connection must be selected. Instead, %s devices matched ([%s])"
|
||||
% (len(devices), ", ".join([device_to_str(c) for c in devices]),)
|
||||
)
|
||||
die_usage("Select unique connection to set")
|
||||
do_set(nmc, connections[0], args["ids_arg"], do_test=args["do_test"])
|
||||
die_usage("Select unique device to apply")
|
||||
do_apply(nmc, devices[0], args["ids_arg"], do_test=args["do_test"])
|
||||
|
||||
else:
|
||||
if len(connections) < 1:
|
||||
_print("No connection selected for printing the external ids")
|
||||
die_usage("Select connection to get")
|
||||
do_get(connections, args["ids_arg"])
|
||||
|
||||
connections = connections_filter(nmc.get_connections(), args["select_arg"])
|
||||
|
||||
if args["mode"] == MODE_SET:
|
||||
if len(connections) != 1:
|
||||
_print(
|
||||
"To set the external-ids of a connection, exactly one connection must be selected via id|uuid. Instead, %s connection matched ([%s])"
|
||||
% (
|
||||
len(connections),
|
||||
", ".join([connection_to_str(c) for c in connections]),
|
||||
)
|
||||
)
|
||||
die_usage("Select unique connection to set")
|
||||
do_set(nmc, connections[0], args["ids_arg"], do_test=args["do_test"])
|
||||
else:
|
||||
if len(connections) < 1:
|
||||
_print("No connection selected for printing the external ids")
|
||||
die_usage("Select connection to get")
|
||||
do_get(connections, args["ids_arg"])
|
||||
|
|
|
|||
|
|
@ -478,7 +478,7 @@ nm_setting_ovs_external_ids_init(NMSettingOvsExternalIDs *self)
|
|||
*
|
||||
* Since: 1.30
|
||||
*/
|
||||
gpointer
|
||||
NMSetting *
|
||||
nm_setting_ovs_external_ids_new(void)
|
||||
{
|
||||
return g_object_new(NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NULL);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ NM_AVAILABLE_IN_1_30
|
|||
GType nm_setting_ovs_external_ids_get_type(void);
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
void *nm_setting_ovs_external_ids_new(void);
|
||||
NMSetting *nm_setting_ovs_external_ids_new(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -925,6 +925,8 @@ _nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_f
|
|||
* error reason. Depending on the usage, this might indicate a bug because
|
||||
* usually the target object should stay alive as long as there are pending
|
||||
* operations.
|
||||
* @NM_UTILS_ERROR_NOT_READY: the failure is related to being currently
|
||||
* not ready to perform the operation.
|
||||
*
|
||||
* @NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE: used for a very particular
|
||||
* purpose during nm_device_check_connection_compatible() to indicate that
|
||||
|
|
@ -945,6 +947,7 @@ typedef enum {
|
|||
NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
|
||||
NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
|
||||
NM_UTILS_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/
|
||||
NM_UTILS_ERROR_NOT_READY, /*< nick=NotReady >*/
|
||||
|
||||
/* the following codes have a special meaning and are exactly used for
|
||||
* nm_device_check_connection_compatible() and nm_device_check_connection_available().
|
||||
|
|
@ -1662,6 +1665,19 @@ GPtrArray *_nm_g_ptr_array_copy(GPtrArray * array,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline GHashTable *
|
||||
nm_g_hash_table_ref(GHashTable *hash)
|
||||
{
|
||||
return hash ? g_hash_table_ref(hash) : NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_g_hash_table_unref(GHashTable *hash)
|
||||
{
|
||||
if (hash)
|
||||
g_hash_table_unref(hash);
|
||||
}
|
||||
|
||||
static inline guint
|
||||
nm_g_hash_table_size(GHashTable *hash)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "settings/nm-settings-connection.h"
|
||||
#include "settings/nm-settings.h"
|
||||
#include "nm-setting-ethtool.h"
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
#include "nm-setting-user.h"
|
||||
#include "nm-auth-utils.h"
|
||||
#include "nm-keep-alive.h"
|
||||
|
|
@ -12450,6 +12451,10 @@ can_reapply_change(NMDevice * self,
|
|||
goto out_fail;
|
||||
}
|
||||
|
||||
if (nm_streq(setting_name, NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME)
|
||||
&& NM_DEVICE_GET_CLASS(self)->can_reapply_change_ovs_external_ids)
|
||||
return TRUE;
|
||||
|
||||
out_fail:
|
||||
g_set_error(error,
|
||||
NM_DEVICE_ERROR,
|
||||
|
|
|
|||
|
|
@ -457,6 +457,8 @@ typedef struct _NMDeviceClass {
|
|||
|
||||
bool act_stage1_prepare_set_hwaddr_ethernet : 1;
|
||||
|
||||
bool can_reapply_change_ovs_external_ids : 1;
|
||||
|
||||
} NMDeviceClass;
|
||||
|
||||
GType nm_device_get_type(void);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "nm-default.h"
|
||||
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
|
||||
#include "nm-device-ovs-interface.h"
|
||||
#include "nm-device-ovs-port.h"
|
||||
#include "nm-ovsdb.h"
|
||||
|
||||
|
|
@ -13,6 +15,8 @@
|
|||
#include "nm-active-connection.h"
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-setting-ovs-bridge.h"
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#define _NMLOG_DEVICE_TYPE NMDeviceOvsBridge
|
||||
#include "devices/nm-device-logging.h"
|
||||
|
|
@ -87,6 +91,39 @@ static void
|
|||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
{}
|
||||
|
||||
void
|
||||
nm_device_ovs_reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new)
|
||||
{
|
||||
NMDeviceType device_type;
|
||||
GType type;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(self));
|
||||
nm_assert(g_type_parent(G_TYPE_FROM_INSTANCE(self)) == NM_TYPE_DEVICE);
|
||||
|
||||
/* NMDevice's reapply_connection() doesn't do anything. No need to call the parent
|
||||
* implementation. */
|
||||
|
||||
_LOGD(LOGD_DEVICE, "reapplying settings for OVS device");
|
||||
|
||||
type = G_OBJECT_TYPE(self);
|
||||
if (type == NM_TYPE_DEVICE_OVS_INTERFACE)
|
||||
device_type = NM_DEVICE_TYPE_OVS_INTERFACE;
|
||||
else if (type == NM_TYPE_DEVICE_OVS_PORT)
|
||||
device_type = NM_DEVICE_TYPE_OVS_PORT;
|
||||
else {
|
||||
nm_assert(type == NM_TYPE_DEVICE_OVS_BRIDGE);
|
||||
device_type = NM_DEVICE_TYPE_OVS_BRIDGE;
|
||||
}
|
||||
|
||||
nm_ovsdb_set_external_ids(
|
||||
nm_ovsdb_get(),
|
||||
device_type,
|
||||
nm_device_get_ip_iface(self),
|
||||
nm_connection_get_uuid(con_new),
|
||||
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
|
||||
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -114,12 +151,14 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
|
|||
device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
|
||||
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES();
|
||||
|
||||
device_class->is_master = TRUE;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->unrealize = unrealize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->is_master = TRUE;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->unrealize = unrealize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,4 +22,9 @@ typedef struct _NMDeviceOvsBridgeClass NMDeviceOvsBridgeClass;
|
|||
|
||||
GType nm_device_ovs_bridge_get_type(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_device_ovs_reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ */
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "nm-default.h"
|
||||
|
||||
#include "nm-device-ovs-interface.h"
|
||||
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
#include "nm-ovsdb.h"
|
||||
|
||||
#include "devices/nm-device-private.h"
|
||||
|
|
@ -382,17 +384,19 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass)
|
|||
device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
|
||||
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH);
|
||||
|
||||
device_class->can_update_from_platform_link = can_update_from_platform_link;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->deactivate_async = deactivate_async;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->is_available = is_available;
|
||||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->link_changed = link_changed;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
|
||||
device_class->set_platform_mtu = set_platform_mtu;
|
||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||
device_class->can_update_from_platform_link = can_update_from_platform_link;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->deactivate_async = deactivate_async;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->is_available = is_available;
|
||||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->link_changed = link_changed;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
|
||||
device_class->set_platform_mtu = set_platform_mtu;
|
||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
#include "nm-default.h"
|
||||
|
||||
#include "nm-device-ovs-port.h"
|
||||
|
||||
#include "nm-device-ovs-interface.h"
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
#include "nm-ovsdb.h"
|
||||
|
||||
#include "devices/nm-device-private.h"
|
||||
|
|
@ -182,11 +184,13 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
|
|||
device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME;
|
||||
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES();
|
||||
|
||||
device_class->is_master = TRUE;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->is_master = TRUE;
|
||||
device_class->get_type_description = get_type_description;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@
|
|||
#include <gio/gunixsocketaddress.h>
|
||||
|
||||
#include "nm-glib-aux/nm-jansson.h"
|
||||
#include "nm-glib-aux/nm-str-buf.h"
|
||||
#include "nm-core-utils.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "devices/nm-device.h"
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -51,57 +53,6 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum { DEVICE_ADDED, DEVICE_REMOVED, INTERFACE_FAILED, LAST_SIGNAL };
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
typedef struct {
|
||||
GSocketClient * client;
|
||||
GSocketConnection *conn;
|
||||
GCancellable * cancellable;
|
||||
char buf[4096]; /* Input buffer */
|
||||
size_t bufp; /* Last decoded byte in the input buffer. */
|
||||
GString * input; /* JSON stream waiting for decoding. */
|
||||
GString * output; /* JSON stream to be sent. */
|
||||
guint64 call_id_counter;
|
||||
GArray * calls; /* Method calls waiting for a response. */
|
||||
GHashTable * interfaces; /* interface uuid => OpenvswitchInterface */
|
||||
GHashTable * ports; /* port uuid => OpenvswitchPort */
|
||||
GHashTable * bridges; /* bridge uuid => OpenvswitchBridge */
|
||||
char * db_uuid;
|
||||
guint num_failures;
|
||||
} NMOvsdbPrivate;
|
||||
|
||||
struct _NMOvsdb {
|
||||
GObject parent;
|
||||
NMOvsdbPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMOvsdbClass {
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMOvsdb, nm_ovsdb, G_TYPE_OBJECT)
|
||||
|
||||
#define NM_OVSDB_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMOvsdb, NM_IS_OVSDB)
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_DEVICE
|
||||
#define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__)
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER(NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ovsdb_try_connect(NMOvsdb *self);
|
||||
static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing);
|
||||
static void ovsdb_read(NMOvsdb *self);
|
||||
static void ovsdb_write(NMOvsdb *self);
|
||||
static void ovsdb_next_command(NMOvsdb *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* ovsdb command abstraction. */
|
||||
|
||||
typedef void (*OvsdbMethodCallback)(NMOvsdb *self,
|
||||
json_t * response,
|
||||
GError * error,
|
||||
|
|
@ -112,6 +63,7 @@ typedef enum {
|
|||
OVSDB_ADD_INTERFACE,
|
||||
OVSDB_DEL_INTERFACE,
|
||||
OVSDB_SET_INTERFACE_MTU,
|
||||
OVSDB_SET_EXTERNAL_IDS,
|
||||
} OvsdbCommand;
|
||||
|
||||
#define CALL_ID_UNSPEC G_MAXUINT64
|
||||
|
|
@ -133,8 +85,87 @@ typedef union {
|
|||
char * ifname;
|
||||
guint32 mtu;
|
||||
} set_interface_mtu;
|
||||
struct {
|
||||
NMDeviceType device_type;
|
||||
char * ifname;
|
||||
char * connection_uuid;
|
||||
GHashTable * exid_old;
|
||||
GHashTable * exid_new;
|
||||
} set_external_ids;
|
||||
} OvsdbMethodPayload;
|
||||
|
||||
typedef struct {
|
||||
NMOvsdb * self;
|
||||
CList calls_lst;
|
||||
guint64 call_id;
|
||||
OvsdbCommand command;
|
||||
OvsdbMethodCallback callback;
|
||||
gpointer user_data;
|
||||
OvsdbMethodPayload payload;
|
||||
} OvsdbMethodCall;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum { DEVICE_ADDED, DEVICE_REMOVED, INTERFACE_FAILED, LAST_SIGNAL };
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
typedef struct {
|
||||
GSocketClient * client;
|
||||
GSocketConnection *conn;
|
||||
GCancellable * cancellable;
|
||||
char buf[4096]; /* Input buffer */
|
||||
size_t bufp; /* Last decoded byte in the input buffer. */
|
||||
GString * input; /* JSON stream waiting for decoding. */
|
||||
GString * output; /* JSON stream to be sent. */
|
||||
guint64 call_id_counter;
|
||||
|
||||
CList calls_lst_head;
|
||||
|
||||
GHashTable *interfaces; /* interface uuid => OpenvswitchInterface */
|
||||
GHashTable *ports; /* port uuid => OpenvswitchPort */
|
||||
GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */
|
||||
char * db_uuid;
|
||||
guint num_failures;
|
||||
} NMOvsdbPrivate;
|
||||
|
||||
struct _NMOvsdb {
|
||||
GObject parent;
|
||||
NMOvsdbPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMOvsdbClass {
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMOvsdb, nm_ovsdb, G_TYPE_OBJECT)
|
||||
|
||||
#define NM_OVSDB_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMOvsdb, NM_IS_OVSDB)
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER(NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void ovsdb_try_connect(NMOvsdb *self);
|
||||
static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing);
|
||||
static void ovsdb_read(NMOvsdb *self);
|
||||
static void ovsdb_write(NMOvsdb *self);
|
||||
static void ovsdb_next_command(NMOvsdb *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_DEVICE
|
||||
#define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__)
|
||||
|
||||
#define _NMLOG_call(level, call, ...) \
|
||||
_NMLOG((level), \
|
||||
"call[" NM_HASH_OBFUSCATE_PTR_FMT "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
NM_HASH_OBFUSCATE_PTR((call)) _NM_UTILS_MACRO_REST(__VA_ARGS__))
|
||||
|
||||
#define _LOGT_call(call, ...) _NMLOG_call(LOGL_TRACE, (call), __VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define OVSDB_METHOD_PAYLOAD_MONITOR() \
|
||||
(&((const OvsdbMethodPayload){ \
|
||||
.monitor = {}, \
|
||||
|
|
@ -173,66 +204,55 @@ typedef union {
|
|||
}, \
|
||||
}))
|
||||
|
||||
typedef struct {
|
||||
guint64 call_id;
|
||||
OvsdbCommand command;
|
||||
OvsdbMethodCallback callback;
|
||||
gpointer user_data;
|
||||
OvsdbMethodPayload payload;
|
||||
} OvsdbMethodCall;
|
||||
#define OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(xdevice_type, \
|
||||
xifname, \
|
||||
xconnection_uuid, \
|
||||
xexid_old, \
|
||||
xexid_new) \
|
||||
(&((const OvsdbMethodPayload){ \
|
||||
.set_external_ids = \
|
||||
{ \
|
||||
.device_type = xdevice_type, \
|
||||
.ifname = (char *) NM_CONSTCAST(char, (xifname)), \
|
||||
.connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \
|
||||
.exid_old = (xexid_old), \
|
||||
.exid_new = (xexid_new), \
|
||||
}, \
|
||||
}))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NM_UTILS_LOOKUP_STR_DEFINE(_device_type_to_table,
|
||||
NMDeviceType,
|
||||
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(NULL),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_BRIDGE, "Bridge"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_PORT, "Port"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_INTERFACE,
|
||||
"Interface"),
|
||||
NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), );
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_LOGT_call_do(const char *comment, OvsdbMethodCall *call, json_t *msg)
|
||||
_call_complete(OvsdbMethodCall *call, json_t *response, GError *error)
|
||||
{
|
||||
gs_free char *msg_as_str = NULL;
|
||||
if (response) {
|
||||
gs_free char *str = NULL;
|
||||
|
||||
#define _QUOTE_MSG(msg, msg_as_str) \
|
||||
(msg) ? ": " : "", (msg) ? (msg_as_str = json_dumps((msg), 0)) : ""
|
||||
|
||||
switch (call->command) {
|
||||
case OVSDB_MONITOR:
|
||||
_LOGT("%s: monitor%s%s", comment, _QUOTE_MSG(msg, msg_as_str));
|
||||
break;
|
||||
case OVSDB_ADD_INTERFACE:
|
||||
_LOGT("%s: add-interface bridge=%s port=%s interface=%s%s%s",
|
||||
comment,
|
||||
nm_connection_get_interface_name(call->payload.add_interface.bridge),
|
||||
nm_connection_get_interface_name(call->payload.add_interface.port),
|
||||
nm_connection_get_interface_name(call->payload.add_interface.interface),
|
||||
_QUOTE_MSG(msg, msg_as_str));
|
||||
break;
|
||||
case OVSDB_DEL_INTERFACE:
|
||||
_LOGT("%s: del-interface interface=%s%s%s",
|
||||
comment,
|
||||
call->payload.del_interface.ifname,
|
||||
_QUOTE_MSG(msg, msg_as_str));
|
||||
break;
|
||||
case OVSDB_SET_INTERFACE_MTU:
|
||||
_LOGT("%s: set-interface-mtu interface=%s mtu=%u%s%s",
|
||||
comment,
|
||||
call->payload.set_interface_mtu.ifname,
|
||||
call->payload.set_interface_mtu.mtu,
|
||||
_QUOTE_MSG(msg, msg_as_str));
|
||||
break;
|
||||
str = json_dumps(response, 0);
|
||||
if (error)
|
||||
_LOGT_call(call, "completed: %s ; error: %s", str, error->message);
|
||||
else
|
||||
_LOGT_call(call, "completed: %s", str);
|
||||
} else {
|
||||
nm_assert(error);
|
||||
_LOGT_call(call, "completed: error: %s", error->message);
|
||||
}
|
||||
}
|
||||
|
||||
#define _LOGT_call(comment, call, message) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
if (_LOGT_ENABLED()) \
|
||||
_LOGT_call_do((comment), (call), (message)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
c_list_unlink_stale(&call->calls_lst);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_clear_call(gpointer data)
|
||||
{
|
||||
OvsdbMethodCall *call = data;
|
||||
if (call->callback)
|
||||
call->callback(call->self, response, error, call->user_data);
|
||||
|
||||
switch (call->command) {
|
||||
case OVSDB_MONITOR:
|
||||
|
|
@ -250,7 +270,15 @@ _clear_call(gpointer data)
|
|||
case OVSDB_SET_INTERFACE_MTU:
|
||||
nm_clear_g_free(&call->payload.set_interface_mtu.ifname);
|
||||
break;
|
||||
case OVSDB_SET_EXTERNAL_IDS:
|
||||
nm_clear_g_free(&call->payload.set_external_ids.ifname);
|
||||
nm_clear_g_free(&call->payload.set_external_ids.connection_uuid);
|
||||
nm_clear_pointer(&call->payload.set_external_ids.exid_old, g_hash_table_destroy);
|
||||
nm_clear_pointer(&call->payload.set_external_ids.exid_new, g_hash_table_destroy);
|
||||
break;
|
||||
}
|
||||
|
||||
nm_g_slice_free(call);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -341,24 +369,28 @@ ovsdb_call_method(NMOvsdb * self,
|
|||
/* Ensure we're not unsynchronized before we queue the method call. */
|
||||
ovsdb_try_connect(self);
|
||||
|
||||
if (add_first) {
|
||||
g_array_prepend_val(priv->calls, (OvsdbMethodCall){});
|
||||
call = &g_array_index(priv->calls, OvsdbMethodCall, 0);
|
||||
} else
|
||||
call = nm_g_array_append_new(priv->calls, OvsdbMethodCall);
|
||||
call = g_slice_new(OvsdbMethodCall);
|
||||
*call = (OvsdbMethodCall){
|
||||
.self = self,
|
||||
.call_id = CALL_ID_UNSPEC,
|
||||
.command = command,
|
||||
.callback = callback,
|
||||
.user_data = user_data,
|
||||
};
|
||||
|
||||
call->call_id = CALL_ID_UNSPEC;
|
||||
call->command = command;
|
||||
call->callback = callback;
|
||||
call->user_data = user_data;
|
||||
if (add_first)
|
||||
c_list_link_front(&priv->calls_lst_head, &call->calls_lst);
|
||||
else
|
||||
c_list_link_tail(&priv->calls_lst_head, &call->calls_lst);
|
||||
|
||||
/* Mmigrate the arguments from @payload to @call->payload. Technically,
|
||||
/* Migrate the arguments from @payload to @call->payload. Technically,
|
||||
* this is not a plain copy, because
|
||||
* - call->payload is not initialized (thus no need to free the previous data).
|
||||
* - payload does not own the data. It is merely initialized using the
|
||||
* OVSDB_METHOD_PAYLOAD_*() macros. */
|
||||
switch (command) {
|
||||
case OVSDB_MONITOR:
|
||||
_LOGT_call(call, "new: monitor");
|
||||
break;
|
||||
case OVSDB_ADD_INTERFACE:
|
||||
/* FIXME(applied-connection-immutable): we should not modify the applied
|
||||
|
|
@ -373,18 +405,40 @@ ovsdb_call_method(NMOvsdb * self,
|
|||
g_object_ref(payload->add_interface.bridge_device);
|
||||
call->payload.add_interface.interface_device =
|
||||
g_object_ref(payload->add_interface.interface_device);
|
||||
_LOGT_call(call,
|
||||
"new: add-interface bridge=%s port=%s interface=%s",
|
||||
nm_connection_get_interface_name(call->payload.add_interface.bridge),
|
||||
nm_connection_get_interface_name(call->payload.add_interface.port),
|
||||
nm_connection_get_interface_name(call->payload.add_interface.interface));
|
||||
break;
|
||||
case OVSDB_DEL_INTERFACE:
|
||||
call->payload.del_interface.ifname = g_strdup(payload->del_interface.ifname);
|
||||
_LOGT_call(call, "new: del-interface interface=%s", call->payload.del_interface.ifname);
|
||||
break;
|
||||
case OVSDB_SET_INTERFACE_MTU:
|
||||
call->payload.set_interface_mtu.ifname = g_strdup(payload->set_interface_mtu.ifname);
|
||||
call->payload.set_interface_mtu.mtu = payload->set_interface_mtu.mtu;
|
||||
_LOGT_call(call,
|
||||
"new: set-interface-mtu interface=%s mtu=%u",
|
||||
call->payload.set_interface_mtu.ifname,
|
||||
call->payload.set_interface_mtu.mtu);
|
||||
break;
|
||||
case OVSDB_SET_EXTERNAL_IDS:
|
||||
call->payload.set_external_ids.device_type = payload->set_external_ids.device_type;
|
||||
call->payload.set_external_ids.ifname = g_strdup(payload->set_external_ids.ifname);
|
||||
call->payload.set_external_ids.connection_uuid =
|
||||
g_strdup(payload->set_external_ids.connection_uuid);
|
||||
call->payload.set_external_ids.exid_old =
|
||||
nm_g_hash_table_ref(payload->set_external_ids.exid_old);
|
||||
call->payload.set_external_ids.exid_new =
|
||||
nm_g_hash_table_ref(payload->set_external_ids.exid_new);
|
||||
_LOGT_call(call,
|
||||
"new: set-external-ids con-uuid=%s, interface=%s",
|
||||
call->payload.set_external_ids.connection_uuid,
|
||||
call->payload.set_external_ids.ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
_LOGT_call("enqueue", call, NULL);
|
||||
|
||||
ovsdb_next_command(self);
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +643,94 @@ _set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces)
|
|||
ifname));
|
||||
}
|
||||
|
||||
static json_t *
|
||||
_j_create_external_ids_array_new(NMConnection *connection)
|
||||
{
|
||||
json_t * array;
|
||||
const char *const * external_ids = NULL;
|
||||
guint n_external_ids = 0;
|
||||
guint i;
|
||||
const char * uuid;
|
||||
NMSettingOvsExternalIDs *s_exid;
|
||||
|
||||
nm_assert(NM_IS_CONNECTION(connection));
|
||||
|
||||
array = json_array();
|
||||
|
||||
uuid = nm_connection_get_uuid(connection);
|
||||
nm_assert(uuid);
|
||||
json_array_append_new(array, json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, uuid));
|
||||
|
||||
s_exid = _nm_connection_get_setting(connection, NM_TYPE_SETTING_OVS_EXTERNAL_IDS);
|
||||
if (s_exid)
|
||||
external_ids = nm_setting_ovs_external_ids_get_data_keys(s_exid, &n_external_ids);
|
||||
for (i = 0; i < n_external_ids; i++) {
|
||||
const char *k = external_ids[i];
|
||||
|
||||
json_array_append_new(
|
||||
array,
|
||||
json_pack("[s, s]", k, nm_setting_ovs_external_ids_get_data(s_exid, k)));
|
||||
}
|
||||
|
||||
return json_pack("[s, o]", "map", array);
|
||||
}
|
||||
|
||||
static json_t *
|
||||
_j_create_external_ids_array_update(const char *connection_uuid,
|
||||
GHashTable *exid_old,
|
||||
GHashTable *exid_new)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
json_t * mutations;
|
||||
json_t * array;
|
||||
const char * key;
|
||||
const char * val;
|
||||
|
||||
nm_assert(connection_uuid);
|
||||
|
||||
mutations = json_array();
|
||||
|
||||
if (exid_old) {
|
||||
array = NULL;
|
||||
g_hash_table_iter_init(&iter, exid_old);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) {
|
||||
if (nm_g_hash_table_contains(exid_new, key))
|
||||
continue;
|
||||
if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX))
|
||||
continue;
|
||||
|
||||
if (!array)
|
||||
array = json_array();
|
||||
|
||||
json_array_append_new(array, json_string(key));
|
||||
}
|
||||
if (array) {
|
||||
json_array_append_new(
|
||||
mutations,
|
||||
json_pack("[s, s, [s, o]]", "external_ids", "delete", "set", array));
|
||||
}
|
||||
}
|
||||
|
||||
array = json_array();
|
||||
|
||||
json_array_append_new(
|
||||
array,
|
||||
json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, connection_uuid));
|
||||
|
||||
if (exid_new) {
|
||||
g_hash_table_iter_init(&iter, exid_new);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) {
|
||||
if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX))
|
||||
continue;
|
||||
json_array_append_new(array, json_pack("[s, s]", key, val));
|
||||
}
|
||||
}
|
||||
|
||||
json_array_append_new(mutations,
|
||||
json_pack("[s, s, [s, o]]", "external_ids", "insert", "map", array));
|
||||
return mutations;
|
||||
}
|
||||
|
||||
/**
|
||||
* _insert_interface:
|
||||
*
|
||||
|
|
@ -639,7 +781,7 @@ _insert_interface(json_t * params,
|
|||
json_array_append_new(options, json_array());
|
||||
}
|
||||
|
||||
row = json_pack("{s:s, s:s, s:o, s:[s, [[s, s]]]}",
|
||||
row = json_pack("{s:s, s:s, s:o, s:o}",
|
||||
"name",
|
||||
nm_connection_get_interface_name(interface),
|
||||
"type",
|
||||
|
|
@ -647,9 +789,7 @@ _insert_interface(json_t * params,
|
|||
"options",
|
||||
options,
|
||||
"external_ids",
|
||||
"map",
|
||||
NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID,
|
||||
nm_connection_get_uuid(interface));
|
||||
_j_create_external_ids_array_new(interface));
|
||||
|
||||
if (cloned_mac)
|
||||
json_object_set_new(row, "mac", json_string(cloned_mac));
|
||||
|
|
@ -714,12 +854,7 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
|
|||
|
||||
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port)));
|
||||
json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces));
|
||||
json_object_set_new(row,
|
||||
"external_ids",
|
||||
json_pack("[s, [[s, s]]]",
|
||||
"map",
|
||||
NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID,
|
||||
nm_connection_get_uuid(port)));
|
||||
json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(port));
|
||||
|
||||
/* Create a new one. */
|
||||
json_array_append_new(params,
|
||||
|
|
@ -779,12 +914,7 @@ _insert_bridge(json_t * params,
|
|||
|
||||
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge)));
|
||||
json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports));
|
||||
json_object_set_new(row,
|
||||
"external_ids",
|
||||
json_pack("[s, [[s, s]]]",
|
||||
"map",
|
||||
NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID,
|
||||
nm_connection_get_uuid(bridge)));
|
||||
json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(bridge));
|
||||
|
||||
if (cloned_mac) {
|
||||
json_object_set_new(row,
|
||||
|
|
@ -1123,10 +1253,11 @@ ovsdb_next_command(NMOvsdb *self)
|
|||
|
||||
if (!priv->conn)
|
||||
return;
|
||||
if (!priv->calls->len)
|
||||
|
||||
if (c_list_is_empty(&priv->calls_lst_head))
|
||||
return;
|
||||
|
||||
call = &g_array_index(priv->calls, OvsdbMethodCall, 0);
|
||||
call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst);
|
||||
if (call->call_id != CALL_ID_UNSPEC)
|
||||
return;
|
||||
|
||||
|
|
@ -1201,6 +1332,25 @@ ovsdb_next_command(NMOvsdb *self)
|
|||
"==",
|
||||
call->payload.set_interface_mtu.ifname));
|
||||
break;
|
||||
case OVSDB_SET_EXTERNAL_IDS:
|
||||
json_array_append_new(
|
||||
params,
|
||||
json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
|
||||
"op",
|
||||
"mutate",
|
||||
"table",
|
||||
_device_type_to_table(call->payload.set_external_ids.device_type),
|
||||
"mutations",
|
||||
_j_create_external_ids_array_update(
|
||||
call->payload.set_external_ids.connection_uuid,
|
||||
call->payload.set_external_ids.exid_old,
|
||||
call->payload.set_external_ids.exid_new),
|
||||
"where",
|
||||
"name",
|
||||
"==",
|
||||
call->payload.set_external_ids.ifname));
|
||||
break;
|
||||
|
||||
default:
|
||||
nm_assert_not_reached();
|
||||
break;
|
||||
|
|
@ -1218,9 +1368,9 @@ ovsdb_next_command(NMOvsdb *self)
|
|||
}
|
||||
|
||||
g_return_if_fail(msg);
|
||||
_LOGT_call("send", call, msg);
|
||||
|
||||
cmd = json_dumps(msg, 0);
|
||||
_LOGT_call(call, "send: call-id=%" G_GUINT64_FORMAT ", %s", call->call_id, cmd);
|
||||
g_string_append(priv->output, cmd);
|
||||
free(cmd);
|
||||
|
||||
|
|
@ -1347,6 +1497,29 @@ _external_ids_equal(const GArray *arr1, const GArray *arr2)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static char *
|
||||
_external_ids_to_string(const GArray *arr)
|
||||
{
|
||||
NMStrBuf strbuf;
|
||||
guint i;
|
||||
|
||||
if (!arr)
|
||||
return g_strdup("empty");
|
||||
|
||||
nm_str_buf_init(&strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
|
||||
nm_str_buf_append(&strbuf, "[");
|
||||
for (i = 0; i < arr->len; i++) {
|
||||
const NMUtilsNamedValue *n = &g_array_index(arr, NMUtilsNamedValue, i);
|
||||
|
||||
if (i > 0)
|
||||
nm_str_buf_append_c(&strbuf, ',');
|
||||
nm_str_buf_append_printf(&strbuf, " \"%s\" = \"%s\"]", n->name, n->value_str);
|
||||
}
|
||||
nm_str_buf_append(&strbuf, " ]");
|
||||
|
||||
return nm_str_buf_finalize(&strbuf, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
@ -1478,16 +1651,21 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
changed = TRUE;
|
||||
}
|
||||
if (changed) {
|
||||
_LOGT("obj[iface:%s]: changed an '%s' interface: %s%s%s",
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
_LOGT("obj[iface:%s]: changed an '%s' interface: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
type,
|
||||
ovs_interface->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid,
|
||||
", ",
|
||||
ovs_interface->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_interface->external_ids)));
|
||||
}
|
||||
} else {
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
ovs_interface = g_slice_new(OpenvswitchInterface);
|
||||
*ovs_interface = (OpenvswitchInterface){
|
||||
.interface_uuid = g_strdup(key),
|
||||
|
|
@ -1497,14 +1675,15 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
.external_ids = g_steal_pointer(&external_ids_arr),
|
||||
};
|
||||
g_hash_table_add(priv->interfaces, ovs_interface);
|
||||
_LOGT("obj[iface:%s]: added an '%s' interface: %s%s%s",
|
||||
_LOGT("obj[iface:%s]: added an '%s' interface: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
ovs_interface->type,
|
||||
ovs_interface->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid,
|
||||
", ",
|
||||
ovs_interface->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_interface->external_ids)));
|
||||
if (_openvswitch_interface_should_emit_signal(ovs_interface))
|
||||
_signal_emit_device_added(self, ovs_interface->name, NM_DEVICE_TYPE_OVS_INTERFACE);
|
||||
}
|
||||
|
|
@ -1585,15 +1764,20 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
changed = TRUE;
|
||||
}
|
||||
if (changed) {
|
||||
_LOGT("obj[port:%s]: changed a port: %s%s%s",
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
_LOGT("obj[port:%s]: changed a port: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
ovs_port->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid,
|
||||
", ",
|
||||
ovs_port->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_port->external_ids)));
|
||||
}
|
||||
} else {
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
ovs_port = g_slice_new(OpenvswitchPort);
|
||||
*ovs_port = (OpenvswitchPort){
|
||||
.port_uuid = g_strdup(key),
|
||||
|
|
@ -1603,13 +1787,14 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
.external_ids = g_steal_pointer(&external_ids_arr),
|
||||
};
|
||||
g_hash_table_add(priv->ports, ovs_port);
|
||||
_LOGT("obj[port:%s]: added a port: %s%s%s",
|
||||
_LOGT("obj[port:%s]: added a port: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
ovs_port->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid,
|
||||
", ",
|
||||
ovs_port->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_port->external_ids)));
|
||||
_signal_emit_device_added(self, ovs_port->name, NM_DEVICE_TYPE_OVS_PORT);
|
||||
}
|
||||
}
|
||||
|
|
@ -1685,15 +1870,20 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
changed = TRUE;
|
||||
}
|
||||
if (changed) {
|
||||
_LOGT("obj[bridge:%s]: changed a bridge: %s%s%s",
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
_LOGT("obj[bridge:%s]: changed a bridge: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
ovs_bridge->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid,
|
||||
", ",
|
||||
ovs_bridge->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_bridge->external_ids)));
|
||||
}
|
||||
} else {
|
||||
gs_free char *strtmp = NULL;
|
||||
|
||||
ovs_bridge = g_slice_new(OpenvswitchBridge);
|
||||
*ovs_bridge = (OpenvswitchBridge){
|
||||
.bridge_uuid = g_strdup(key),
|
||||
|
|
@ -1703,13 +1893,14 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
|
|||
.external_ids = g_steal_pointer(&external_ids_arr),
|
||||
};
|
||||
g_hash_table_add(priv->bridges, ovs_bridge);
|
||||
_LOGT("obj[bridge:%s]: added a bridge: %s%s%s",
|
||||
_LOGT("obj[bridge:%s]: added a bridge: %s%s%s, external-ids=%s",
|
||||
key,
|
||||
ovs_bridge->name,
|
||||
NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid,
|
||||
", ",
|
||||
ovs_bridge->connection_uuid,
|
||||
""));
|
||||
""),
|
||||
(strtmp = _external_ids_to_string(ovs_bridge->external_ids)));
|
||||
_signal_emit_device_added(self, ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1753,16 +1944,12 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg)
|
|||
json_error_t json_error = {
|
||||
0,
|
||||
};
|
||||
json_t * json_id = NULL;
|
||||
json_int_t id = (json_int_t) -1;
|
||||
const char * method = NULL;
|
||||
json_t * params = NULL;
|
||||
json_t * result = NULL;
|
||||
json_t * error = NULL;
|
||||
OvsdbMethodCall * call = NULL;
|
||||
OvsdbMethodCallback callback;
|
||||
gpointer user_data;
|
||||
gs_free_error GError *local = NULL;
|
||||
json_t * json_id = NULL;
|
||||
json_int_t id = (json_int_t) -1;
|
||||
const char *method = NULL;
|
||||
json_t * params = NULL;
|
||||
json_t * result = NULL;
|
||||
json_t * error = NULL;
|
||||
|
||||
if (json_unpack_ex(msg,
|
||||
&json_error,
|
||||
|
|
@ -1808,13 +1995,17 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg)
|
|||
}
|
||||
|
||||
if (id >= 0) {
|
||||
OvsdbMethodCall *call;
|
||||
gs_free_error GError *local = NULL;
|
||||
gs_free char * msg_as_str = NULL;
|
||||
|
||||
/* This is a response to a method call. */
|
||||
if (!priv->calls->len) {
|
||||
if (c_list_is_empty(&priv->calls_lst_head)) {
|
||||
_LOGE("there are no queued calls expecting response %" G_GUINT64_FORMAT, (guint64) id);
|
||||
ovsdb_disconnect(self, FALSE, FALSE);
|
||||
return;
|
||||
}
|
||||
call = &g_array_index(priv->calls, OvsdbMethodCall, 0);
|
||||
call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst);
|
||||
if (call->call_id != id) {
|
||||
_LOGE("expected a response to call %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT,
|
||||
call->call_id,
|
||||
|
|
@ -1824,7 +2015,7 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg)
|
|||
}
|
||||
/* Cool, we found a corresponding call. Finish it. */
|
||||
|
||||
_LOGT_call("response", call, msg);
|
||||
_LOGT_call(call, "response: %s", (msg_as_str = json_dumps(msg, 0)));
|
||||
|
||||
if (!json_is_null(error)) {
|
||||
/* The response contains an error. */
|
||||
|
|
@ -1835,10 +2026,8 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg)
|
|||
json_string_value(error));
|
||||
}
|
||||
|
||||
callback = call->callback;
|
||||
user_data = call->user_data;
|
||||
g_array_remove_index(priv->calls, 0);
|
||||
callback(self, result, local, user_data);
|
||||
_call_complete(call, result, local);
|
||||
|
||||
priv->num_failures = 0;
|
||||
|
||||
/* Don't progress further commands in case the callback hit an error
|
||||
|
|
@ -2007,11 +2196,8 @@ ovsdb_write(NMOvsdb *self)
|
|||
static void
|
||||
ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing)
|
||||
{
|
||||
NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self);
|
||||
OvsdbMethodCall * call;
|
||||
OvsdbMethodCallback callback;
|
||||
gpointer user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self);
|
||||
OvsdbMethodCall *call;
|
||||
|
||||
nm_assert(!retry || !is_disposing);
|
||||
|
||||
|
|
@ -2021,18 +2207,19 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing)
|
|||
_LOGD("disconnecting from ovsdb, retry %d", retry);
|
||||
|
||||
if (retry) {
|
||||
if (priv->calls->len != 0)
|
||||
g_array_index(priv->calls, OvsdbMethodCall, 0).call_id = CALL_ID_UNSPEC;
|
||||
} else {
|
||||
nm_utils_error_set_cancelled(&error, is_disposing, "NMOvsdb");
|
||||
|
||||
while (priv->calls->len) {
|
||||
call = &g_array_index(priv->calls, OvsdbMethodCall, priv->calls->len - 1);
|
||||
callback = call->callback;
|
||||
user_data = call->user_data;
|
||||
g_array_remove_index(priv->calls, priv->calls->len - 1);
|
||||
callback(self, NULL, error, user_data);
|
||||
if (!c_list_is_empty(&priv->calls_lst_head)) {
|
||||
call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst);
|
||||
call->call_id = CALL_ID_UNSPEC;
|
||||
}
|
||||
} else {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (is_disposing)
|
||||
nm_utils_error_set_cancelled(&error, is_disposing, "NMOvsdb");
|
||||
else
|
||||
nm_utils_error_set(&error, NM_UTILS_ERROR_NOT_READY, "disconnected from ovsdb");
|
||||
while ((call = c_list_last_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst)))
|
||||
_call_complete(call, NULL, error);
|
||||
}
|
||||
|
||||
priv->bufp = 0;
|
||||
|
|
@ -2231,6 +2418,36 @@ nm_ovsdb_set_interface_mtu(NMOvsdb * self,
|
|||
OVSDB_METHOD_PAYLOAD_SET_INTERFACE_MTU(ifname, mtu));
|
||||
}
|
||||
|
||||
void
|
||||
nm_ovsdb_set_external_ids(NMOvsdb * self,
|
||||
NMDeviceType device_type,
|
||||
const char * ifname,
|
||||
const char * connection_uuid,
|
||||
NMSettingOvsExternalIDs *s_exid_old,
|
||||
NMSettingOvsExternalIDs *s_exid_new)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *exid_old = NULL;
|
||||
gs_unref_hashtable GHashTable *exid_new = NULL;
|
||||
|
||||
exid_old = s_exid_old
|
||||
? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_old))
|
||||
: NULL;
|
||||
exid_new = s_exid_new
|
||||
? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_new))
|
||||
: NULL;
|
||||
|
||||
ovsdb_call_method(self,
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
OVSDB_SET_EXTERNAL_IDS,
|
||||
OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(device_type,
|
||||
ifname,
|
||||
connection_uuid,
|
||||
exid_old,
|
||||
exid_new));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -2238,8 +2455,8 @@ nm_ovsdb_init(NMOvsdb *self)
|
|||
{
|
||||
NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self);
|
||||
|
||||
priv->calls = g_array_new(FALSE, TRUE, sizeof(OvsdbMethodCall));
|
||||
g_array_set_clear_func(priv->calls, _clear_call);
|
||||
c_list_init(&priv->calls_lst_head);
|
||||
|
||||
priv->input = g_string_new(NULL);
|
||||
priv->output = g_string_new(NULL);
|
||||
priv->bridges =
|
||||
|
|
@ -2260,6 +2477,8 @@ dispose(GObject *object)
|
|||
|
||||
ovsdb_disconnect(self, FALSE, TRUE);
|
||||
|
||||
nm_assert(c_list_is_empty(&priv->calls_lst_head));
|
||||
|
||||
if (priv->input) {
|
||||
g_string_free(priv->input, TRUE);
|
||||
priv->input = NULL;
|
||||
|
|
@ -2268,10 +2487,6 @@ dispose(GObject *object)
|
|||
g_string_free(priv->output, TRUE);
|
||||
priv->output = NULL;
|
||||
}
|
||||
if (priv->calls) {
|
||||
g_array_free(priv->calls, TRUE);
|
||||
priv->calls = NULL;
|
||||
}
|
||||
|
||||
nm_clear_pointer(&priv->bridges, g_hash_table_destroy);
|
||||
nm_clear_pointer(&priv->ports, g_hash_table_destroy);
|
||||
|
|
|
|||
|
|
@ -46,4 +46,13 @@ void nm_ovsdb_set_interface_mtu(NMOvsdb * self,
|
|||
NMOvsdbCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
struct _NMSettingOvsExternalIDs;
|
||||
|
||||
void nm_ovsdb_set_external_ids(NMOvsdb * self,
|
||||
NMDeviceType device_type,
|
||||
const char * ifname,
|
||||
const char * connection_uuid,
|
||||
struct _NMSettingOvsExternalIDs *s_exid_old,
|
||||
struct _NMSettingOvsExternalIDs *s_exid_new);
|
||||
|
||||
#endif /* __NETWORKMANAGER_OVSDB_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue