summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-05-04 09:58:45 +0200
committerThomas Haller <thaller@redhat.com>2017-05-05 18:44:26 +0200
commit8537d233f24e200669bfcade476aad5d2623d8c4 (patch)
tree766424615e42fd8a095ff22d8f96b821b0032354
parent7052566ab933e5448a9ecf8e4517fafe6cc7d5ac (diff)
downloadNetworkManager-8537d233f24e200669bfcade476aad5d2623d8c4.tar.gz
examples: add setting-user-data.pyth/user-data-v2-bgo776276
Add an example python script to show and set setting's user-data. This is useful, as nmcli still doesn't support user data.
-rw-r--r--Makefile.examples13
-rwxr-xr-xexamples/python/gi/setting-user-data.py248
2 files changed, 255 insertions, 6 deletions
diff --git a/Makefile.examples b/Makefile.examples
index 172adc17ff..63370e2cbc 100644
--- a/Makefile.examples
+++ b/Makefile.examples
@@ -163,16 +163,17 @@ EXTRA_DIST += \
examples/python/dbus/create-bond.py \
examples/python/dbus/wifi-active-ap.py\
\
- examples/python/gi/list-connections.py \
+ examples/python/gi/README \
+ examples/python/gi/add_connection.py \
+ examples/python/gi/deactivate-all.py \
examples/python/gi/device-state-ip4config.py \
examples/python/gi/firewall-zone.py \
- examples/python/gi/show-wifi-networks.py \
- examples/python/gi/get_ips.py \
- examples/python/gi/add_connection.py \
examples/python/gi/get-active-connections.py \
+ examples/python/gi/get_ips.py \
+ examples/python/gi/list-connections.py \
+ examples/python/gi/setting-user-data.py \
+ examples/python/gi/show-wifi-networks.py \
examples/python/gi/update-ip4-method.py \
- examples/python/gi/deactivate-all.py \
- examples/python/gi/README \
\
examples/python/python-networkmanager/README \
\
diff --git a/examples/python/gi/setting-user-data.py b/examples/python/gi/setting-user-data.py
new file mode 100755
index 0000000000..3b34846032
--- /dev/null
+++ b/examples/python/gi/setting-user-data.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+# -*- Mode: Python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# vim: ft=python ts=4 sts=4 sw=4 et ai
+
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright 2017 Red Hat, Inc.
+
+#
+# set and show user-data for a connection:
+#
+# - Show all user data for all connections:
+# $ ./examples/python/gi/setting-user-data.py
+# - Filter to show only connections with matching id or uuid
+# $ ./examples/python/gi/setting-user-data.py id my-connection
+# $ ./examples/python/gi/setting-user-data.py uuid 123e4567-e89b-12d3-a456-426655440000
+# - id and uuid can be repeated to select multiple connections
+# $ ./examples/python/gi/setting-user-data.py id my-connection1 id my-other-connection
+#
+# - Specify the user-data keys you want to see
+# $ ./examples/python/gi/setting-user-data.py id my-connection my.user.field.1
+# $ ./examples/python/gi/setting-user-data.py id my-connection my.user.field.1 my.other.userfield
+# - Prefix the field name with ~ to use a regex
+# $ ./examples/python/gi/setting-user-data.py '~^my\.user\.'
+#
+# - set the fields, you need to select exactly one connection
+# $ ./examples/python/gi/setting-user-data.py set id "$NAME" my.field.1 my-value1
+# - delete a user-setting
+# $ ./examples/python/gi/setting-user-data.py set id "$NAME" -d my.field.1
+# - set/delete multiple user data values at once
+# $ ./examples/python/gi/setting-user-data.py set id "$NAME" my.field.1 my-value1 -d my.other.field
+#
+# - libnm already client side rejects invalid values, like
+# $ ./examples/python/gi/setting-user-data.py set id "$NAME" invalid_name 'has-no-dot'
+# - to allow client side to specify invalid values and send them to the
+# server, pass --set-gobject
+# $ ./examples/python/gi/setting-user-data.py set id "$NAME" invalid_name 'has-no-dot' --set-gobject
+#
+
+import sys
+import re
+
+import gi
+gi.require_version('NM', '1.0')
+from gi.repository import NM
+
+def pr(v):
+ import pprint
+ pprint.pprint(v, indent=4, depth=5, width=60)
+
+def parse_args():
+ args = {
+ 'set': False,
+ 'set-gobject': False,
+ 'filter': [],
+ 'data': []
+ }
+ i = 1
+ while i < len(sys.argv):
+ a = sys.argv[i]
+ if i == 1:
+ if a in ['s', 'set']:
+ args['set'] = True
+ i += 1
+ continue
+ elif a in ['g', 'get']:
+ args['set'] = False
+ i += 1
+ continue
+ if a in ['id', 'uuid']:
+ args['filter'].append((a, sys.argv[i+1]))
+ i += 2
+ continue
+
+ if a in ['--set-gobject']:
+ args['set-gobject'] = True
+ i += 1
+ continue
+
+ if a == 'data':
+ i += 1
+ a = sys.argv[i]
+ if args['set']:
+ if a == '-d':
+ args['data'].append((sys.argv[i+1], None))
+ else:
+ args['data'].append((a, sys.argv[i+1]))
+ i += 2
+ else:
+ args['data'].append(a)
+ i += 1
+
+ return args
+
+def get_connections(connections, filter):
+ connections = list(sorted(connections, key=connection_to_str))
+ if not filter:
+ return connections
+ # we preserve the order of the selected connections. And
+ # if connections are selected multiple times, we return
+ # them multiple times.
+ l = []
+ for f in filter:
+ if f[0] == 'id':
+ for c in connections:
+ if f[1] == c.get_id():
+ l.append(c)
+ else:
+ assert(f[0] == 'uuid')
+ for c in connections:
+ if f[1] == c.get_uuid():
+ l.append(c)
+ return l
+
+def connection_to_str(connection):
+ return '%s (%s)' % (connection.get_id(), connection.get_uuid())
+
+def print_user_data(connection, data_allow_regex, data, prefix=''):
+ s_u = connection.get_setting(NM.SettingUser)
+ n = 'none'
+ keys_len = 0
+ keys = []
+ if s_u is not None:
+ all_keys = s_u.get_keys()
+ keys_len = len(all_keys)
+ if data:
+ for d in data:
+ if data_allow_regex and len(d) > 0 and d[0] == '~':
+ r = re.compile(d[1:])
+ keys.extend([k for k in all_keys if r.match(k)])
+ else:
+ keys.append (d)
+ else:
+ keys.extend(all_keys)
+ n = '%s' % (keys_len)
+
+ print('%s%s [%s]' % (prefix, connection_to_str(connection), n))
+ dd = { }
+ if s_u is not None:
+ dd = s_u.get_property(NM.SETTING_USER_DATA)
+ for k in keys:
+ if s_u is not None:
+ v = s_u.get_data(k)
+ if v is None:
+ if k in dd:
+ print('%s INVALID: "%s" = "%s"' % (prefix, k, dd[k]))
+ else:
+ print('%s MISSING: "%s"' % (prefix, k))
+ else:
+ assert(v == dd.get(k, None))
+ print('%s SET: "%s" = "%s"' % (prefix, k, v))
+ else:
+ print('%s MISSING: "%s"' % (prefix, k))
+
+
+def do_get(connections, data):
+ first_line = True
+ connections = list(connections)
+ if not connections:
+ print('no connections selected')
+ sys.exit(1)
+ for c in connections:
+ if first_line:
+ first_line = False
+ else:
+ print('')
+ print_user_data(c, True, data)
+
+###############################################################################
+
+def do_set(connection, data, set_gobject):
+ print_user_data(connection, False,
+ [d[0] for d in data],
+ prefix = 'BEFORE: ')
+ print('')
+ s_u = connection.get_setting(NM.SettingUser)
+ if s_u is None:
+ connection.add_setting(NM.SettingUser())
+ s_u = connection.get_setting(NM.SettingUser)
+ for d in data:
+ key = d[0]
+ val = d[1]
+ if val is None:
+ print(' DEL: "%s"' % (key))
+ else:
+ print(' SET: "%s" = "%s"' % (key, val))
+ if set_gobject:
+ d = s_u.get_property(NM.SETTING_USER_DATA)
+ if val is None:
+ d.pop(key, None)
+ else:
+ d[key] = val
+ s_u.set_property(NM.SETTING_USER_DATA, d)
+ else:
+ try:
+ s_u.set_data(key, val)
+ except Exception as e:
+ if val is None:
+ print('error deleting key "%s": %s' % (key, e))
+ else:
+ print('error setting key "%s" = "%s": %s' % (key, val, e))
+ sys.exit(1)
+
+
+ try:
+ connection.commit_changes(True, None)
+ except Exception as e:
+ print('failure to commit connection: %s' % (e))
+ sys.exit(1)
+
+ print('')
+ print_user_data(connection, False,
+ [d[0] for d in data],
+ prefix = 'AFTER: ')
+
+###############################################################################
+
+if __name__ == '__main__':
+ args = parse_args()
+ nm_client = NM.Client.new(None)
+
+ connections = get_connections(nm_client.get_connections(), args['filter'])
+
+ if args['set']:
+ if not args['data']:
+ print('Requires one or more arguments to set or delete')
+ sys.exit(1)
+ if len(connections) != 1:
+ print('To set the user-data 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])))
+ sys.exit(1)
+ do_set(connections[0], args['data'], args['set-gobject'])
+ else:
+ do_get(connections, args['data'])
+