Blame examples/python/gi/setting-user-data.py

Packit 5756e2
#!/usr/bin/env python
Packit Service 87a54e
# SPDX-License-Identifier: GPL-2.0-or-later
Packit 5756e2
#
Packit 5756e2
# Copyright (C) 2017 Red Hat, Inc.
Packit 5756e2
#
Packit 5756e2
Packit 5756e2
#
Packit 5756e2
# set and show user-data for a connection:
Packit 5756e2
#
Packit 5756e2
# - Show all user data for all connections:
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py
Packit 5756e2
# - Filter to show only connections with matching id or uuid
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py id my-connection
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py uuid 123e4567-e89b-12d3-a456-426655440000
Packit 5756e2
# - id and uuid can be repeated to select multiple connections
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py id my-connection1 id my-other-connection
Packit 5756e2
#
Packit 5756e2
# - Specify the user-data keys you want to see
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py id my-connection my.user.field.1
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py id my-connection my.user.field.1 my.other.userfield
Packit 5756e2
# - Prefix the field name with ~ to use a regex
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py '~^my\.user\.'
Packit 5756e2
#
Packit 5756e2
# - set the fields, you need to select exactly one connection
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py set id "$NAME" my.field.1 my-value1
Packit 5756e2
# - delete a user-setting
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py set id "$NAME" -d my.field.1
Packit 5756e2
# - set/delete multiple user data values at once
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py set id "$NAME" my.field.1 my-value1 -d my.other.field
Packit 5756e2
#
Packit 5756e2
# - libnm already client side rejects invalid values, like
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py set id "$NAME" invalid_name 'has-no-dot'
Packit 5756e2
# - to allow client side to specify invalid values and send them to the
Packit 5756e2
#   server, pass --set-gobject
Packit 5756e2
#   $ ./examples/python/gi/setting-user-data.py set id "$NAME" invalid_name 'has-no-dot' --set-gobject
Packit 5756e2
#
Packit 5756e2
Packit 5756e2
import sys
Packit 5756e2
import re
Packit 5756e2
Packit 5756e2
import gi
Packit 5756e2
Packit 5756e2
gi.require_version("NM", "1.0")
Packit 5756e2
from gi.repository import NM
Packit 5756e2
Packit 5756e2
Packit 5756e2
def pr(v):
Packit 5756e2
    import pprint
Packit 5756e2
Packit 5756e2
    pprint.pprint(v, indent=4, depth=5, width=60)
Packit 5756e2
Packit 5756e2
Packit 5756e2
def parse_args():
Packit 5756e2
    args = {"set": False, "set-gobject": False, "filter": [], "data": []}
Packit 5756e2
    i = 1
Packit 5756e2
    while i < len(sys.argv):
Packit 5756e2
        a = sys.argv[i]
Packit 5756e2
        if i == 1:
Packit 5756e2
            if a in ["s", "set"]:
Packit 5756e2
                args["set"] = True
Packit 5756e2
                i += 1
Packit 5756e2
                continue
Packit 5756e2
            elif a in ["g", "get"]:
Packit 5756e2
                args["set"] = False
Packit 5756e2
                i += 1
Packit 5756e2
                continue
Packit 5756e2
        if a in ["id", "uuid"]:
Packit 5756e2
            args["filter"].append((a, sys.argv[i + 1]))
Packit 5756e2
            i += 2
Packit 5756e2
            continue
Packit 5756e2
Packit 5756e2
        if a in ["--set-gobject"]:
Packit 5756e2
            args["set-gobject"] = True
Packit 5756e2
            i += 1
Packit 5756e2
            continue
Packit 5756e2
Packit 5756e2
        if a == "data":
Packit 5756e2
            i += 1
Packit 5756e2
            a = sys.argv[i]
Packit 5756e2
        if args["set"]:
Packit 5756e2
            if a == "-d":
Packit 5756e2
                args["data"].append((sys.argv[i + 1], None))
Packit 5756e2
            else:
Packit 5756e2
                args["data"].append((a, sys.argv[i + 1]))
Packit 5756e2
            i += 2
Packit 5756e2
        else:
Packit 5756e2
            args["data"].append(a)
Packit 5756e2
            i += 1
Packit 5756e2
Packit 5756e2
    return args
Packit 5756e2
Packit 5756e2
Packit 5756e2
def connection_to_str(connection):
Packit 5756e2
    return "%s (%s)" % (connection.get_id(), connection.get_uuid())
Packit 5756e2
Packit 5756e2
Packit 5756e2
def connections_filter(connections, filter_data):
Packit 5756e2
    connections = list(sorted(connections, key=connection_to_str))
Packit 5756e2
    if not filter_data:
Packit 5756e2
        return connections
Packit 5756e2
    # we preserve the order of the selected connections. And
Packit 5756e2
    # if connections are selected multiple times, we return
Packit 5756e2
    # them multiple times.
Packit 5756e2
    l = []
Packit 5756e2
    for f in filter_data:
Packit 5756e2
        if f[0] == "id":
Packit 5756e2
            for c in connections:
Packit 5756e2
                if f[1] == c.get_id():
Packit 5756e2
                    l.append(c)
Packit 5756e2
        else:
Packit 5756e2
            assert f[0] == "uuid"
Packit 5756e2
            for c in connections:
Packit 5756e2
                if f[1] == c.get_uuid():
Packit 5756e2
                    l.append(c)
Packit 5756e2
    return l
Packit 5756e2
Packit 5756e2
Packit 5756e2
def print_user_data(connection, data_allow_regex, data, prefix=""):
Packit 5756e2
    s_u = connection.get_setting(NM.SettingUser)
Packit 5756e2
    n = "none"
Packit 5756e2
    keys_len = 0
Packit 5756e2
    keys = []
Packit 5756e2
    if s_u is not None:
Packit 5756e2
        all_keys = s_u.get_keys()
Packit 5756e2
        keys_len = len(all_keys)
Packit 5756e2
        if data:
Packit 5756e2
            for d in data:
Packit 5756e2
                if data_allow_regex and len(d) > 0 and d[0] == "~":
Packit 5756e2
                    r = re.compile(d[1:])
Packit 5756e2
                    keys.extend([k for k in all_keys if r.match(k)])
Packit 5756e2
                else:
Packit 5756e2
                    keys.append(d)
Packit 5756e2
        else:
Packit 5756e2
            keys.extend(all_keys)
Packit 5756e2
        n = "%s" % (keys_len)
Packit 5756e2
Packit 5756e2
    print("%s%s [%s]" % (prefix, connection_to_str(connection), n))
Packit 5756e2
    dd = {}
Packit 5756e2
    if s_u is not None:
Packit 5756e2
        dd = s_u.get_property(NM.SETTING_USER_DATA)
Packit 5756e2
    for k in keys:
Packit 5756e2
        if s_u is not None:
Packit 5756e2
            v = s_u.get_data(k)
Packit 5756e2
            if v is None:
Packit 5756e2
                if k in dd:
Packit 5756e2
                    print('%s   INVALID:   "%s" = "%s"' % (prefix, k, dd[k]))
Packit 5756e2
                else:
Packit 5756e2
                    print('%s   MISSING:   "%s"' % (prefix, k))
Packit 5756e2
            else:
Packit 5756e2
                assert v == dd.get(k, None)
Packit 5756e2
                print('%s   SET:       "%s" = "%s"' % (prefix, k, v))
Packit 5756e2
        else:
Packit 5756e2
            print('%s   MISSING:  "%s"' % (prefix, k))
Packit 5756e2
Packit 5756e2
Packit 5756e2
def do_get(connections, data):
Packit 5756e2
    first_line = True
Packit 5756e2
    connections = list(connections)
Packit 5756e2
    if not connections:
Packit 5756e2
        print("no matching connections (use id|uuid argument)")
Packit 5756e2
        sys.exit(1)
Packit 5756e2
    for c in connections:
Packit 5756e2
        if first_line:
Packit 5756e2
            first_line = False
Packit 5756e2
        else:
Packit 5756e2
            print("")
Packit 5756e2
        print_user_data(c, True, data)
Packit 5756e2
Packit 5756e2
Packit 5756e2
def do_set(connection, data, set_gobject):
Packit 5756e2
    print_user_data(connection, False, [d[0] for d in data], prefix="BEFORE: ")
Packit 5756e2
    print("")
Packit 5756e2
    s_u = connection.get_setting(NM.SettingUser)
Packit 5756e2
    if s_u is None:
Packit 5756e2
        connection.add_setting(NM.SettingUser())
Packit 5756e2
        s_u = connection.get_setting(NM.SettingUser)
Packit 5756e2
    for d in data:
Packit 5756e2
        key = d[0]
Packit 5756e2
        val = d[1]
Packit 5756e2
        if val is None:
Packit 5756e2
            print(' DEL: "%s"' % (key))
Packit 5756e2
        else:
Packit 5756e2
            print(' SET: "%s" = "%s"' % (key, val))
Packit 5756e2
        if set_gobject:
Packit 5756e2
            d = s_u.get_property(NM.SETTING_USER_DATA)
Packit 5756e2
            if val is None:
Packit 5756e2
                d.pop(key, None)
Packit 5756e2
            else:
Packit 5756e2
                d[key] = val
Packit 5756e2
            s_u.set_property(NM.SETTING_USER_DATA, d)
Packit 5756e2
        else:
Packit 5756e2
            try:
Packit 5756e2
                s_u.set_data(key, val)
Packit 5756e2
            except Exception as e:
Packit 5756e2
                if val is None:
Packit 5756e2
                    print('error deleting key "%s": %s' % (key, e))
Packit 5756e2
                else:
Packit 5756e2
                    print('error setting key "%s" = "%s": %s' % (key, val, e))
Packit 5756e2
                sys.exit(1)
Packit 5756e2
Packit 5756e2
    try:
Packit 5756e2
        connection.commit_changes(True, None)
Packit 5756e2
    except Exception as e:
Packit 5756e2
        print("failure to commit connection: %s" % (e))
Packit 5756e2
        sys.exit(1)
Packit 5756e2
Packit 5756e2
    print("")
Packit 5756e2
    print_user_data(connection, False, [d[0] for d in data], prefix="AFTER:  ")
Packit 5756e2
Packit 5756e2
Packit 5756e2
###############################################################################
Packit 5756e2
Packit 5756e2
if __name__ == "__main__":
Packit 5756e2
    args = parse_args()
Packit 5756e2
    nm_client = NM.Client.new(None)
Packit 5756e2
Packit 5756e2
    connections = connections_filter(nm_client.get_connections(), args["filter"])
Packit 5756e2
Packit 5756e2
    if args["set"]:
Packit 5756e2
        if not args["data"]:
Packit 5756e2
            print("Requires one or more arguments to set or delete")
Packit 5756e2
            sys.exit(1)
Packit 5756e2
        if len(connections) != 1:
Packit 5756e2
            print(
Packit 5756e2
                "To set the user-data of a connection, exactly one connection must be selected via id|uuid. Instead, %s connection matched ([%s])"
Packit 5756e2
                % (
Packit 5756e2
                    len(connections),
Packit 5756e2
                    ", ".join([connection_to_str(c) for c in connections]),
Packit 5756e2
                )
Packit 5756e2
            )
Packit 5756e2
            sys.exit(1)
Packit 5756e2
        do_set(connections[0], args["data"], args["set-gobject"])
Packit 5756e2
    else:
Packit 5756e2
        do_get(connections, args["data"])