diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/initial-setup | 40 | ||||
-rw-r--r-- | src/utils/vyos-config-file-query | 100 | ||||
-rw-r--r-- | src/utils/vyos-config-to-commands | 29 | ||||
-rw-r--r-- | src/utils/vyos-config-to-json | 40 | ||||
-rw-r--r-- | src/utils/vyos-hostsd-client | 166 |
5 files changed, 375 insertions, 0 deletions
diff --git a/src/utils/initial-setup b/src/utils/initial-setup new file mode 100644 index 0000000..37fc457 --- /dev/null +++ b/src/utils/initial-setup @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import argparse + +import vyos.configtree + + +parser = argparse.ArgumentParser() + +parser.add_argument("--ssh", help="Enable SSH", action="store_true") +parser.add_argument("--ssh-port", help="SSH port", type=int, action="store", default=22) + +parser.add_argument("--intf-address", help="Set interface address", type=str, action="append") + +parser.add_argument("config_file", help="Configuration file to modify", type=str) + +args = parser.parse_args() + +# Load the config file +with open(args.config_file, 'r') as f: + config_file = f.read() + +config = vyos.configtree.ConfigTree(config_file) + + +# Interface names and addresses are comma-separated, +# we need to split them +intf_addrs = list(map(lambda s: s.split(","), args.intf_address)) + +# Enable SSH, if requested +if args.ssh: + config.set(["service", "ssh", "port"], value=str(args.ssh_port)) + +# Assign addresses to interfaces +if intf_addrs: + for a in intf_addrs: + config.set(["interfaces", "ethernet", a[0], "address"], value=a[1]) + config.set_tag(["interfaces", "ethernet"]) + +print( config.to_string() ) diff --git a/src/utils/vyos-config-file-query b/src/utils/vyos-config-file-query new file mode 100644 index 0000000..a10c7e9 --- /dev/null +++ b/src/utils/vyos-config-file-query @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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, see <http://www.gnu.org/licenses/>. +# + +import re +import os +import sys +import json +import argparse + +import vyos.configtree + + +arg_parser = argparse.ArgumentParser() +arg_parser.add_argument('-p', '--path', type=str, + help="VyOS config node, e.g. \"system config-management commit-revisions\"", required=True) +arg_parser.add_argument('-f', '--file', type=str, help="VyOS config file, e.g. /config/config.boot", required=True) + +arg_parser.add_argument('-s', '--separator', type=str, default=' ', help="Value separator for the plain format") +arg_parser.add_argument('-j', '--json', action='store_true') + +op_group = arg_parser.add_mutually_exclusive_group(required=True) +op_group.add_argument('--return-value', action='store_true', help="Return a single node value") +op_group.add_argument('--return-values', action='store_true', help="Return all values of a multi-value node") +op_group.add_argument('--list-nodes', action='store_true', help="List children of a node") +op_group.add_argument('--exists', action='store_true', help="Check if a node exists") + +args = arg_parser.parse_args() + + +try: + with open(args.file, 'r') as f: + config_file = f.read() +except OSError as e: + print("Could not read the config file: {0}".format(e)) + sys.exit(1) + +try: + config = vyos.configtree.ConfigTree(config_file) +except Exception as e: + print(e) + sys.exit(1) + + +path = re.split(r'\s+', args.path) +values = None + +if args.exists: + if config.exists(path): + sys.exit(0) + else: + sys.exit(1) +elif args.return_value: + try: + values = [config.return_value(path)] + except vyos.configtree.ConfigTreeError as e: + print(e) + sys.exit(1) +elif args.return_values: + try: + values = config.return_values(path) + except vyos.configtree.ConfigTreeError as e: + print(e) + sys.exit(1) +elif args.list_nodes: + values = config.list_nodes(path) + if not values: + values = [] +else: + # Can't happen + print("Operation required") + sys.exit(1) + + +if values: + if args.json: + print(json.dumps(values)) + else: + if len(values) == 1: + print(values[0]) + else: + # XXX: assuming values never contain quotes + values = list(map(lambda s: "\'{0}\'".format(s), values)) + values_str = args.separator.join(values) + print(values_str) + +sys.exit(0) diff --git a/src/utils/vyos-config-to-commands b/src/utils/vyos-config-to-commands new file mode 100644 index 0000000..8b50f7c --- /dev/null +++ b/src/utils/vyos-config-to-commands @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +import sys + +from signal import signal, SIGPIPE, SIG_DFL +from vyos.configtree import ConfigTree + +signal(SIGPIPE,SIG_DFL) + +config_string = None +if (len(sys.argv) == 1): + # If no argument given, act as a pipe + config_string = sys.stdin.read() +else: + file_name = sys.argv[1] + try: + with open(file_name, 'r') as f: + config_string = f.read() + except OSError as e: + print("Could not read config file {0}: {1}".format(file_name, e), file=sys.stderr) + +try: + config = ConfigTree(config_string) + commands = config.to_commands() +except ValueError as e: + print("Could not parse the config file: {0}".format(e), file=sys.stderr) + sys.exit(1) + +print(commands) diff --git a/src/utils/vyos-config-to-json b/src/utils/vyos-config-to-json new file mode 100644 index 0000000..e03fd6a --- /dev/null +++ b/src/utils/vyos-config-to-json @@ -0,0 +1,40 @@ +#!/usr/bin/python3 + +import sys +import json + +from signal import signal, SIGPIPE, SIG_DFL +from vyos.configtree import ConfigTree + +signal(SIGPIPE,SIG_DFL) + +config_string = None +if (len(sys.argv) == 1): + # If no argument given, act as a pipe + config_string = sys.stdin.read() +else: + file_name = sys.argv[1] + try: + with open(file_name, 'r') as f: + config_string = f.read() + except OSError as e: + print("Could not read config file {0}: {1}".format(file_name, e), file=sys.stderr) + +# This script is usually called with the output of "cli-shell-api showCfg", which does not +# escape backslashes. "ConfigTree()" expects escaped backslashes when parsing a config +# string (and also prints them itself). Therefore this script would fail. +# Manually escape backslashes here to handle backslashes in any configuration strings +# properly. The alternative would be to modify the output of "cli-shell-api showCfg", +# but that may be break other things who rely on that specific output. +config_string = config_string.replace("\\", "\\\\") + +try: + config = ConfigTree(config_string) + json_str = config.to_json() + # Pretty print + json_str = json.dumps(json.loads(json_str), indent=4, sort_keys=True) +except ValueError as e: + print("Could not parse the config file: {0}".format(e), file=sys.stderr) + sys.exit(1) + +print(json_str) diff --git a/src/utils/vyos-hostsd-client b/src/utils/vyos-hostsd-client new file mode 100644 index 0000000..a051595 --- /dev/null +++ b/src/utils/vyos-hostsd-client @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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, see <http://www.gnu.org/licenses/>. +# +# + +import sys +import argparse + +import vyos.hostsd_client + +parser = argparse.ArgumentParser(allow_abbrev=False) +group = parser.add_mutually_exclusive_group() + +group.add_argument('--add-name-servers', type=str, nargs='*') +group.add_argument('--delete-name-servers', action='store_true') +group.add_argument('--get-name-servers', type=str, const='.*', nargs='?') + +group.add_argument('--add-name-server-tags-recursor', type=str, nargs='*') +group.add_argument('--delete-name-server-tags-recursor', type=str, nargs='*') +group.add_argument('--get-name-server-tags-recursor', action='store_true') + +group.add_argument('--add-name-server-tags-system', type=str, nargs='*') +group.add_argument('--delete-name-server-tags-system', type=str, nargs='*') +group.add_argument('--get-name-server-tags-system', action='store_true') + +group.add_argument('--add-forward-zone', type=str, nargs='?') +group.add_argument('--delete-forward-zones', type=str, nargs='*') +group.add_argument('--get-forward-zones', action='store_true') + +group.add_argument('--add-search-domains', type=str, nargs='*') +group.add_argument('--delete-search-domains', action='store_true') +group.add_argument('--get-search-domains', type=str, const='.*', nargs='?') + +group.add_argument('--add-hosts', type=str, nargs='*') +group.add_argument('--delete-hosts', action='store_true') +group.add_argument('--get-hosts', type=str, const='.*', nargs='?') + +group.add_argument('--set-host-name', type=str) + +# for --set-host-name +parser.add_argument('--domain-name', type=str) + +# for forward zones +parser.add_argument('--nameservers', type=str, nargs='*') +parser.add_argument('--addnta', action='store_true') +parser.add_argument('--recursion-desired', action='store_true') + +parser.add_argument('--tag', type=str) + +# users must call --apply either in the same command or after they're done +parser.add_argument('--apply', action="store_true") + +args = parser.parse_args() + +try: + client = vyos.hostsd_client.Client() + ops = 1 + + if args.add_name_servers: + if not args.tag: + raise ValueError("--tag is required for this operation") + client.add_name_servers({args.tag: args.add_name_servers}) + elif args.delete_name_servers: + if not args.tag: + raise ValueError("--tag is required for this operation") + client.delete_name_servers([args.tag]) + elif args.get_name_servers: + print(client.get_name_servers(args.get_name_servers)) + + elif args.add_name_server_tags_recursor: + client.add_name_server_tags_recursor(args.add_name_server_tags_recursor) + elif args.delete_name_server_tags_recursor: + client.delete_name_server_tags_recursor(args.delete_name_server_tags_recursor) + elif args.get_name_server_tags_recursor: + print(client.get_name_server_tags_recursor()) + + elif args.add_name_server_tags_system: + client.add_name_server_tags_system(args.add_name_server_tags_system) + elif args.delete_name_server_tags_system: + client.delete_name_server_tags_system(args.delete_name_server_tags_system) + elif args.get_name_server_tags_system: + print(client.get_name_server_tags_system()) + + elif args.add_forward_zone: + if not args.nameservers: + raise ValueError("--nameservers is required for this operation") + client.add_forward_zones( + { args.add_forward_zone: { + 'server': args.nameservers, + 'addnta': args.addnta, + 'recursion_desired': args.recursion_desired + } + }) + elif args.delete_forward_zones: + client.delete_forward_zones(args.delete_forward_zones) + elif args.get_forward_zones: + print(client.get_forward_zones()) + + elif args.add_search_domains: + if not args.tag: + raise ValueError("--tag is required for this operation") + client.add_search_domains({args.tag: args.add_search_domains}) + elif args.delete_search_domains: + if not args.tag: + raise ValueError("--tag is required for this operation") + client.delete_search_domains([args.tag]) + elif args.get_search_domains: + print(client.get_search_domains(args.get_search_domains)) + + elif args.add_hosts: + if not args.tag: + raise ValueError("--tag is required for this operation") + data = {} + for h in args.add_hosts: + entry = {} + params = h.split(",") + if len(params) < 2: + raise ValueError("Malformed host entry") + # Address needs to be a list because of changes made in T2683 + entry['address'] = [params[1]] + entry['aliases'] = params[2:] + data[params[0]] = entry + client.add_hosts({args.tag: data}) + elif args.delete_hosts: + if not args.tag: + raise ValueError("--tag is required for this operation") + client.delete_hosts([args.tag]) + elif args.get_hosts: + print(client.get_hosts(args.get_hosts)) + + elif args.set_host_name: + if not args.domain_name: + raise ValueError('--domain-name is required for this operation') + client.set_host_name({'host_name': args.set_host_name, 'domain_name': args.domain_name}) + + elif args.apply: + pass + else: + ops = 0 + + if args.apply: + client.apply() + + if ops == 0: + raise ValueError("Operation required") + +except ValueError as e: + print("Incorrect options: {0}".format(e)) + sys.exit(1) +except vyos.hostsd_client.VyOSHostsdError as e: + print("Server returned an error: {0}".format(e)) + sys.exit(1) + |