diff options
Diffstat (limited to 'src/op_mode')
-rwxr-xr-x | src/op_mode/dns_forwarding_statistics.py | 2 | ||||
-rwxr-xr-x | src/op_mode/powerctrl.py | 291 | ||||
-rwxr-xr-x | src/op_mode/show_dhcp.py | 91 | ||||
-rwxr-xr-x | src/op_mode/show_dhcpv6.py | 74 | ||||
-rwxr-xr-x | src/op_mode/show_interfaces.py | 37 | ||||
-rwxr-xr-x | src/op_mode/version.py | 93 | ||||
-rwxr-xr-x | src/op_mode/vrrp.py | 1 | ||||
-rwxr-xr-x | src/op_mode/wireguard.py | 8 |
8 files changed, 316 insertions, 281 deletions
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py index 8ae92beb7..1fb61d263 100755 --- a/src/op_mode/dns_forwarding_statistics.py +++ b/src/op_mode/dns_forwarding_statistics.py @@ -4,7 +4,7 @@ import jinja2 from sys import exit from vyos.config import Config -from vyos.config import cmd +from vyos.util import cmd PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns' diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py index 4ab91384b..69af427ec 100755 --- a/src/op_mode/powerctrl.py +++ b/src/op_mode/powerctrl.py @@ -15,168 +15,179 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import sys -import argparse import re +from argparse import ArgumentParser from datetime import datetime, timedelta, time as type_time, date as type_date -from vyos.util import ask_yes_no -from vyos.util import cmd -from vyos.util import call -from vyos.util import run -from vyos.util import STDOUT +from sys import exit +from time import time + +from vyos.util import ask_yes_no, cmd, call, run, STDOUT systemd_sched_file = "/run/systemd/shutdown/scheduled" -def parse_time(s): - try: - if re.match(r'^\d{1,2}$', s): - return datetime.strptime(s, "%M").time() - else: - return datetime.strptime(s, "%H:%M").time() - except ValueError: - return None +def utc2local(datetime): + now = time() + offs = datetime.fromtimestamp(now) - datetime.utcfromtimestamp(now) + return datetime + offs -def parse_date(s): - for fmt in ["%d%m%Y", "%d/%m/%Y", "%d.%m.%Y", "%d:%m:%Y", "%Y-%m-%d"]: +def parse_time(s): try: - return datetime.strptime(s, fmt).date() + if re.match(r'^\d{1,2}$', s): + return datetime.strptime(s, "%M").time() + else: + return datetime.strptime(s, "%H:%M").time() except ValueError: - continue - # If nothing matched... - return None + return None + + +def parse_date(s): + for fmt in ["%d%m%Y", "%d/%m/%Y", "%d.%m.%Y", "%d:%m:%Y", "%Y-%m-%d"]: + try: + return datetime.strptime(s, fmt).date() + except ValueError: + continue + # If nothing matched... + return None + def get_shutdown_status(): - if os.path.exists(systemd_sched_file): - # Get scheduled from systemd file - with open(systemd_sched_file, 'r') as f: - data = f.read().rstrip('\n') - r_data = {} - for line in data.splitlines(): - tmp_split = line.split("=") - if tmp_split[0] == "USEC": - # Convert USEC to human readable format - r_data['DATETIME'] = datetime.utcfromtimestamp(int(tmp_split[1])/1000000).strftime('%Y-%m-%d %H:%M:%S') - else: - r_data[tmp_split[0]] = tmp_split[1] - return r_data - return None + if os.path.exists(systemd_sched_file): + # Get scheduled from systemd file + with open(systemd_sched_file, 'r') as f: + data = f.read().rstrip('\n') + r_data = {} + for line in data.splitlines(): + tmp_split = line.split("=") + if tmp_split[0] == "USEC": + # Convert USEC to human readable format + r_data['DATETIME'] = datetime.utcfromtimestamp( + int(tmp_split[1])/1000000).strftime('%Y-%m-%d %H:%M:%S') + else: + r_data[tmp_split[0]] = tmp_split[1] + return r_data + return None + def check_shutdown(): - output = get_shutdown_status() - if output and 'MODE' in output: - if output['MODE'] == 'reboot': - print("Reboot is scheduled", output['DATETIME']) - elif output['MODE'] == 'poweroff': - print("Poweroff is scheduled", output['DATETIME']) - else: - print("Reboot or poweroff is not scheduled") + output = get_shutdown_status() + if output and 'MODE' in output: + dt = datetime.strptime(output['DATETIME'], '%Y-%m-%d %H:%M:%S') + if output['MODE'] == 'reboot': + print("Reboot is scheduled", utc2local(dt)) + elif output['MODE'] == 'poweroff': + print("Poweroff is scheduled", utc2local(dt)) + else: + print("Reboot or poweroff is not scheduled") + def cancel_shutdown(): - output = get_shutdown_status() - if output and 'MODE' in output: - timenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - try: - cmd('/sbin/shutdown -c --no-wall') - except OSError as e: - sys.exit("Could not cancel a reboot or poweroff: %s" % e) - message = "Scheduled %s has been cancelled %s" % (output['MODE'], timenow) - run(f'wall {message}') - else: - print("Reboot or poweroff is not scheduled") - -def execute_shutdown(time, reboot = True, ask=True): - if not ask: - action = "reboot" if reboot else "poweroff" - if not ask_yes_no("Are you sure you want to %s this system?" % action): - sys.exit(0) - - action = "-r" if reboot else "-P" - - if len(time) == 0: - ### T870 legacy reboot job support - chk_vyatta_based_reboots() - ### - - out = cmd(f'/sbin/shutdown {action} now', stderr=STDOUT) - print(out.split(",",1)[0]) - return - elif len(time) == 1: - # Assume the argument is just time - ts = parse_time(time[0]) - if ts: - cmd(f'/sbin/shutdown {action} {time[0]}', stderr=STDOUT) + output = get_shutdown_status() + if output and 'MODE' in output: + timenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + try: + run('/sbin/shutdown -c --no-wall') + except OSError as e: + exit("Could not cancel a reboot or poweroff: %s" % e) + + message = 'Scheduled {} has been cancelled {}'.format(output['MODE'], timenow) + run(f'wall {message} > /dev/null 2>&1') else: - sys.exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0])) - elif len(time) == 2: - # Assume it's date and time - ts = parse_time(time[0]) - ds = parse_date(time[1]) - if ts and ds: - t = datetime.combine(ds, ts) - td = t - datetime.now() - t2 = 1 + int(td.total_seconds())//60 # Get total minutes - cmd('/sbin/shutdown {action} {t2}', stderr=STDOUT) + print("Reboot or poweroff is not scheduled") + + +def execute_shutdown(time, reboot=True, ask=True): + if not ask: + action = "reboot" if reboot else "poweroff" + if not ask_yes_no("Are you sure you want to %s this system?" % action): + exit(0) + + action = "-r" if reboot else "-P" + + if len(time) == 0: + # T870 legacy reboot job support + chk_vyatta_based_reboots() + ### + + out = cmd(f'/sbin/shutdown {action} now', stderr=STDOUT) + print(out.split(",", 1)[0]) + return + elif len(time) == 1: + # Assume the argument is just time + ts = parse_time(time[0]) + if ts: + cmd(f'/sbin/shutdown {action} {time[0]}', stderr=STDOUT) + else: + exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0])) + elif len(time) == 2: + # Assume it's date and time + ts = parse_time(time[0]) + ds = parse_date(time[1]) + if ts and ds: + t = datetime.combine(ds, ts) + td = t - datetime.now() + t2 = 1 + int(td.total_seconds())//60 # Get total minutes + cmd('/sbin/shutdown {action} {t2}', stderr=STDOUT) + else: + if not ts: + exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0])) + else: + exit("Invalid time \"{0}\". A valid format is YYYY-MM-DD [HH:MM]".format(time[1])) else: - if not ts: - sys.exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0])) - else: - sys.exit("Invalid time \"{0}\". A valid format is YYYY-MM-DD [HH:MM]".format(time[1])) - else: - sys.exit("Could not decode date and time. Valids formats are HH:MM or YYYY-MM-DD HH:MM") - check_shutdown() + exit("Could not decode date and time. Valids formats are HH:MM or YYYY-MM-DD HH:MM") + check_shutdown() + def chk_vyatta_based_reboots(): - ### T870 commit-confirm is still using the vyatta code base, once gone, the code below can be removed - ### legacy scheduled reboot s are using at and store the is as /var/run/<name>.job - ### name is the node of scheduled the job, commit-confirm checks for that + # T870 commit-confirm is still using the vyatta code base, once gone, the code below can be removed + # legacy scheduled reboot s are using at and store the is as /var/run/<name>.job + # name is the node of scheduled the job, commit-confirm checks for that + + f = r'/var/run/confirm.job' + if os.path.exists(f): + jid = open(f).read().strip() + if jid != 0: + call(f'sudo atrm {jid}') + os.remove(f) - f = r'/var/run/confirm.job' - if os.path.exists(f): - jid = open(f).read().strip() - if jid != 0: - call(f'sudo atrm {jid}') - os.remove(f) def main(): - parser = argparse.ArgumentParser() - parser.add_argument("--yes", "-y", - help="Do not ask for confirmation", - action="store_true", - dest="yes") - action = parser.add_mutually_exclusive_group(required=True) - action.add_argument("--reboot", "-r", - help="Reboot the system", - nargs="*", - metavar="Minutes|HH:MM") - - action.add_argument("--poweroff", "-p", - help="Poweroff the system", - nargs="*", - metavar="Minutes|HH:MM") - - action.add_argument("--cancel", "-c", - help="Cancel pending shutdown", - action="store_true") - - action.add_argument("--check", - help="Check pending chutdown", - action="store_true") - args = parser.parse_args() - - try: - if args.reboot is not None: - execute_shutdown(args.reboot, reboot=True, ask=args.yes) - if args.poweroff is not None: - execute_shutdown(args.poweroff, reboot=False,ask=args.yes) - if args.cancel: - cancel_shutdown() - if args.check: - check_shutdown() - except KeyboardInterrupt: - sys.exit("Interrupted") + parser = ArgumentParser() + parser.add_argument("--yes", "-y", + help="Do not ask for confirmation", + action="store_true", + dest="yes") + action = parser.add_mutually_exclusive_group(required=True) + action.add_argument("--reboot", "-r", + help="Reboot the system", + nargs="*", + metavar="Minutes|HH:MM") + + action.add_argument("--poweroff", "-p", + help="Poweroff the system", + nargs="*", + metavar="Minutes|HH:MM") + + action.add_argument("--cancel", "-c", + help="Cancel pending shutdown", + action="store_true") + + action.add_argument("--check", + help="Check pending chutdown", + action="store_true") + args = parser.parse_args() + try: + if args.reboot is not None: + execute_shutdown(args.reboot, reboot=True, ask=args.yes) + if args.poweroff is not None: + execute_shutdown(args.poweroff, reboot=False, ask=args.yes) + if args.cancel: + cancel_shutdown() + if args.check: + check_shutdown() + except KeyboardInterrupt: + exit("Interrupted") if __name__ == "__main__": - main() - + main() diff --git a/src/op_mode/show_dhcp.py b/src/op_mode/show_dhcp.py index c49e604b7..f9577e57e 100755 --- a/src/op_mode/show_dhcp.py +++ b/src/op_mode/show_dhcp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2019 VyOS maintainers and contributors +# Copyright (C) 2018-2020 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 @@ -14,14 +14,14 @@ # 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 json -import argparse -import ipaddress -import tabulate -import sys -import collections -import os +# TODO: merge with show_dhcpv6.py + +from json import dumps +from argparse import ArgumentParser +from ipaddress import ip_address +from tabulate import tabulate +from sys import exit +from collections import OrderedDict from datetime import datetime from isc_dhcp_leases import Lease, IscDhcpLeases @@ -33,7 +33,7 @@ from vyos.util import call lease_file = "/config/dhcpd.leases" pool_key = "shared-networkname" -lease_display_fields = collections.OrderedDict() +lease_display_fields = OrderedDict() lease_display_fields['ip'] = 'IP address' lease_display_fields['hardware_address'] = 'Hardware address' lease_display_fields['state'] = 'State' @@ -102,7 +102,7 @@ def get_lease_data(lease): return data -def get_leases(leases, state, pool=None, sort='ip'): +def get_leases(config, leases, state, pool=None, sort='ip'): # get leases from file leases = IscDhcpLeases(lease_file).get() @@ -116,7 +116,7 @@ def get_leases(leases, state, pool=None, sort='ip'): leases = list(filter(lambda x: in_pool(x, pool), leases)) else: print("Pool {0} does not exist.".format(pool)) - sys.exit(0) + exit(0) # should maybe filter all state=active by lease.valid here? @@ -134,7 +134,7 @@ def get_leases(leases, state, pool=None, sort='ip'): # apply output/display sort if sort == 'ip': - leases = sorted(leases, key = lambda lease: int(ipaddress.ip_address(lease['ip']))) + leases = sorted(leases, key = lambda lease: int(ip_address(lease['ip']))) else: leases = sorted(leases, key = lambda lease: lease[sort]) @@ -148,7 +148,7 @@ def show_leases(leases): lease_list_params.append(l[k]) lease_list.append(lease_list_params) - output = tabulate.tabulate(lease_list, lease_display_fields.values()) + output = tabulate(lease_list, lease_display_fields.values()) print(output) @@ -161,18 +161,18 @@ def get_pool_size(config, pool): start = config.return_effective_value("service dhcp-server shared-network-name {0} subnet {1} range {2} start".format(pool, s, r)) stop = config.return_effective_value("service dhcp-server shared-network-name {0} subnet {1} range {2} stop".format(pool, s, r)) - size += int(ipaddress.ip_address(stop)) - int(ipaddress.ip_address(start)) + size += int(ip_address(stop)) - int(ip_address(start)) return size def show_pool_stats(stats): headers = ["Pool", "Size", "Leases", "Available", "Usage"] - output = tabulate.tabulate(stats, headers) + output = tabulate(stats, headers) print(output) if __name__ == '__main__': - parser = argparse.ArgumentParser() + parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-l", "--leases", action="store_true", help="Show DHCP leases") @@ -180,27 +180,50 @@ if __name__ == '__main__': group.add_argument("--allowed", type=str, choices=["pool", "sort", "state"], help="Show allowed values for argument") parser.add_argument("-p", "--pool", type=str, help="Show lease for specific pool") - parser.add_argument("-S", "--sort", type=str, choices=lease_display_fields.keys(), default='ip', help="Sort by") - parser.add_argument("-t", "--state", type=str, nargs="+", choices=lease_valid_states, default="active", help="Lease state to show (can specify multiple with spaces)") + parser.add_argument("-S", "--sort", type=str, default='ip', help="Sort by") + parser.add_argument("-t", "--state", type=str, nargs="+", default=["active"], help="Lease state to show (can specify multiple with spaces)") parser.add_argument("-j", "--json", action="store_true", default=False, help="Produce JSON output") args = parser.parse_args() + conf = Config() + + if args.allowed == 'pool': + if conf.exists_effective('service dhcp-server'): + print(' '.join(conf.list_effective_nodes("service dhcp-server shared-network-name"))) + exit(0) + elif args.allowed == 'sort': + print(' '.join(lease_display_fields.keys())) + exit(0) + elif args.allowed == 'state': + print(' '.join(lease_valid_states)) + exit(0) + elif args.allowed: + parser.print_help() + exit(1) + + if args.sort not in lease_display_fields.keys(): + print(f'Invalid sort key, choose from: {list(lease_display_fields.keys())}') + exit(0) + + if not set(args.state) < set(lease_valid_states): + print(f'Invalid lease state, choose from: {lease_valid_states}') + exit(0) + # Do nothing if service is not configured - config = Config() - if not config.exists_effective('service dhcp-server'): + if not conf.exists_effective('service dhcp-server'): print("DHCP service is not configured.") - sys.exit(0) + exit(0) # if dhcp server is down, inactive leases may still be shown as active, so warn the user. if call('systemctl -q is-active isc-dhcp-server.service') != 0: print("WARNING: DHCP server is configured but not started. Data may be stale.") if args.leases: - leases = get_leases(lease_file, args.state, args.pool, args.sort) + leases = get_leases(conf, lease_file, args.state, args.pool, args.sort) if args.json: - print(json.dumps(leases, indent=4)) + print(dumps(leases, indent=4)) else: show_leases(leases) @@ -211,18 +234,15 @@ if __name__ == '__main__': if args.pool: pools = [args.pool] else: - pools = config.list_effective_nodes("service dhcp-server shared-network-name") + pools = conf.list_effective_nodes("service dhcp-server shared-network-name") # Get pool usage stats stats = [] for p in pools: - size = get_pool_size(config, p) - leases = len(get_leases(lease_file, state='active', pool=p)) + size = get_pool_size(conf, p) + leases = len(get_leases(conf, lease_file, state='active', pool=p)) - if size != 0: - use_percentage = round(leases / size * 100) - else: - use_percentage = 0 + use_percentage = round(leases / size * 100) if size != 0 else 0 if args.json: pool_stats = {"pool": p, "size": size, "leases": leases, @@ -234,15 +254,10 @@ if __name__ == '__main__': # Print stats if args.json: - print(json.dumps(stats, indent=4)) + print(dumps(stats, indent=4)) else: show_pool_stats(stats) - elif args.allowed == 'pool': - print(' '.join(config.list_effective_nodes("service dhcp-server shared-network-name"))) - elif args.allowed == 'sort': - print(' '.join(lease_display_fields.keys())) - elif args.allowed == 'state': - print(' '.join(lease_valid_states)) else: parser.print_help() + exit(1) diff --git a/src/op_mode/show_dhcpv6.py b/src/op_mode/show_dhcpv6.py index d686defc0..ac211fb0a 100755 --- a/src/op_mode/show_dhcpv6.py +++ b/src/op_mode/show_dhcpv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2019 VyOS maintainers and contributors +# Copyright (C) 2018-2020 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 @@ -14,14 +14,14 @@ # 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 json -import argparse -import ipaddress -import tabulate -import sys -import collections -import os +# TODO: merge with show_dhcp.py + +from json import dumps +from argparse import ArgumentParser +from ipaddress import ip_address +from tabulate import tabulate +from sys import exit +from collections import OrderedDict from datetime import datetime from isc_dhcp_leases import Lease, IscDhcpLeases @@ -32,7 +32,7 @@ from vyos.util import call lease_file = "/config/dhcpdv6.leases" pool_key = "shared-networkname" -lease_display_fields = collections.OrderedDict() +lease_display_fields = OrderedDict() lease_display_fields['ip'] = 'IPv6 address' lease_display_fields['state'] = 'State' lease_display_fields['last_comm'] = 'Last communication' @@ -108,7 +108,7 @@ def get_lease_data(lease): return data -def get_leases(leases, state, pool=None, sort='ip'): +def get_leases(config, leases, state, pool=None, sort='ip'): leases = IscDhcpLeases(lease_file).get() # filter leases by state @@ -121,7 +121,7 @@ def get_leases(leases, state, pool=None, sort='ip'): leases = list(filter(lambda x: in_pool(x, pool), leases)) else: print("Pool {0} does not exist.".format(pool)) - sys.exit(0) + exit(0) # should maybe filter all state=active by lease.valid here? @@ -139,7 +139,7 @@ def get_leases(leases, state, pool=None, sort='ip'): # apply output/display sort if sort == 'ip': - leases = sorted(leases, key = lambda k: int(ipaddress.ip_address(k['ip']))) + leases = sorted(leases, key = lambda k: int(ip_address(k['ip']))) else: leases = sorted(leases, key = lambda k: k[sort]) @@ -153,12 +153,12 @@ def show_leases(leases): lease_list_params.append(l[k]) lease_list.append(lease_list_params) - output = tabulate.tabulate(lease_list, lease_display_fields.values()) + output = tabulate(lease_list, lease_display_fields.values()) print(output) if __name__ == '__main__': - parser = argparse.ArgumentParser() + parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-l", "--leases", action="store_true", help="Show DHCPv6 leases") @@ -166,36 +166,54 @@ if __name__ == '__main__': group.add_argument("--allowed", type=str, choices=["pool", "sort", "state"], help="Show allowed values for argument") parser.add_argument("-p", "--pool", type=str, help="Show lease for specific pool") - parser.add_argument("-S", "--sort", type=str, choices=lease_display_fields.keys(), default='ip', help="Sort by") - parser.add_argument("-t", "--state", type=str, nargs="+", choices=lease_valid_states, default="active", help="Lease state to show (can specify multiple with spaces)") + parser.add_argument("-S", "--sort", type=str, default='ip', help="Sort by") + parser.add_argument("-t", "--state", type=str, nargs="+", default=["active"], help="Lease state to show (can specify multiple with spaces)") parser.add_argument("-j", "--json", action="store_true", default=False, help="Produce JSON output") args = parser.parse_args() + conf = Config() + + if args.allowed == 'pool': + if conf.exists_effective('service dhcpv6-server'): + print(' '.join(conf.list_effective_nodes("service dhcpv6-server shared-network-name"))) + exit(0) + elif args.allowed == 'sort': + print(' '.join(lease_display_fields.keys())) + exit(0) + elif args.allowed == 'state': + print(' '.join(lease_valid_states)) + exit(0) + elif args.allowed: + parser.print_help() + exit(1) + + if args.sort not in lease_display_fields.keys(): + print(f'Invalid sort key, choose from: {list(lease_display_fields.keys())}') + exit(0) + + if not set(args.state) < set(lease_valid_states): + print(f'Invalid lease state, choose from: {lease_valid_states}') + exit(0) + # Do nothing if service is not configured - c = Config() - if not c.exists_effective('service dhcpv6-server'): + if not conf.exists_effective('service dhcpv6-server'): print("DHCPv6 service is not configured") - sys.exit(0) + exit(0) # if dhcp server is down, inactive leases may still be shown as active, so warn the user. if call('systemctl -q is-active isc-dhcp-server6.service') != 0: print("WARNING: DHCPv6 server is configured but not started. Data may be stale.") if args.leases: - leases = get_leases(lease_file, args.state, args.pool, args.sort) + leases = get_leases(conf, lease_file, args.state, args.pool, args.sort) if args.json: - print(json.dumps(leases, indent=4)) + print(dumps(leases, indent=4)) else: show_leases(leases) elif args.statistics: print("DHCPv6 statistics option is not available") - elif args.allowed == 'pool': - print(' '.join(c.list_effective_nodes("service dhcpv6-server shared-network-name"))) - elif args.allowed == 'sort': - print(' '.join(lease_display_fields.keys())) - elif args.allowed == 'state': - print(' '.join(lease_valid_states)) else: parser.print_help() + exit(1) diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py index 8b6690b7d..7041c7e16 100755 --- a/src/op_mode/show_interfaces.py +++ b/src/op_mode/show_interfaces.py @@ -18,6 +18,7 @@ import os import re import sys +import glob import datetime import argparse import netifaces @@ -146,9 +147,20 @@ def run_allowed(**kwarg): sys.stdout.write(' '.join(Section.interfaces())) +def pppoe(ifname): + out = cmd(f'ps -C pppd -f') + if ifname in out: + return 'C' + elif ifname in [_.split('/')[-1] for _ in glob.glob('/etc/ppp/peers/pppoe*')]: + return 'D' + return '' + + @register('show') def run_show_intf(ifnames, iftypes, vif, vrrp): + handled = [] for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): + handled.append(interface.ifname) cache = interface.operational.load_counters() out = cmd(f'ip addr show {interface.ifname}') @@ -173,6 +185,17 @@ def run_show_intf(ifnames, iftypes, vif, vrrp): print() print(interface.operational.formated_stats()) + for ifname in ifnames: + if ifname not in handled and ifname.startswith('pppoe'): + state = pppoe(ifname) + if not state: + continue + string = { + 'C': 'Coming up', + 'D': 'Link down', + }[state] + print('{}: {}'.format(ifname, string)) + @register('show-brief') def run_show_intf_brief(ifnames, iftypes, vif, vrrp): @@ -183,7 +206,10 @@ def run_show_intf_brief(ifnames, iftypes, vif, vrrp): print(format1 % ("Interface", "IP Address", "S/L", "Description")) print(format1 % ("---------", "----------", "---", "-----------")) + handled = [] for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): + handled.append(interface.ifname) + oper_state = interface.operational.get_state() admin_state = interface.get_admin_state() @@ -206,6 +232,17 @@ def run_show_intf_brief(ifnames, iftypes, vif, vrrp): print(format2 % (i, a)) print(format1 % ('', '', '/'.join(s+l), d)) + for ifname in ifnames: + if ifname not in handled and ifname.startswith('pppoe'): + state = pppoe(ifname) + if not state: + continue + string = { + 'C': 'u/D', + 'D': 'A/D', + }[state] + print(format1 % (ifname, '', string, '')) + @register('show-count') def run_show_counters(ifnames, iftypes, vif, vrrp): diff --git a/src/op_mode/version.py b/src/op_mode/version.py index 2791f5e5c..c335eefce 100755 --- a/src/op_mode/version.py +++ b/src/op_mode/version.py @@ -25,14 +25,13 @@ import sys import argparse import json -import pystache - import vyos.version import vyos.limericks from vyos.util import cmd from vyos.util import call from vyos.util import run +from vyos.util import read_file from vyos.util import DEVNULL @@ -41,90 +40,42 @@ parser.add_argument("-a", "--all", action="store_true", help="Include individual parser.add_argument("-f", "--funny", action="store_true", help="Add something funny to the output") parser.add_argument("-j", "--json", action="store_true", help="Produce JSON output") -def read_file(name): - try: - with open (name, "r") as f: - data = f.read() - return data.strip() - except: - # This works since we only read /sys/class/* stuff - # with this function - return "Unknown" version_output_tmpl = """ -Version: VyOS {{version}} -Release Train: {{release_train}} +Version: VyOS {version} +Release Train: {release_train} -Built by: {{built_by}} -Built on: {{built_on}} -Build UUID: {{build_uuid}} -Build Commit ID: {{build_git}} +Built by: {built_by} +Built on: {built_on} +Build UUID: {build_uuid} +Build Commit ID: {build_git} -Architecture: {{system_arch}} -Boot via: {{boot_via}} -System type: {{system_type}} +Architecture: {system_arch} +Boot via: {boot_via} +System type: {system_type} -Hardware vendor: {{hardware_vendor}} -Hardware model: {{hardware_model}} -Hardware S/N: {{hardware_serial}} -Hardware UUID: {{hardware_uuid}} +Hardware vendor: {hardware_vendor} +Hardware model: {hardware_model} +Hardware S/N: {hardware_serial} +Hardware UUID: {hardware_uuid} Copyright: VyOS maintainers and contributors - """ if __name__ == '__main__': args = parser.parse_args() - version_data = vyos.version.get_version_data() - - # Get system architecture (well, kernel architecture rather) - version_data['system_arch'] = cmd('uname -m') - - - # Get hypervisor name, if any - system_type = "bare metal" - try: - hypervisor = cmd('hvinfo',stderr=DEVNULL) - system_type = "{0} guest".format(hypervisor) - except OSError: - # hvinfo returns 1 if it cannot detect any hypervisor - pass - version_data['system_type'] = system_type - - - # Get boot type, it can be livecd, installed image, or, possible, a system installed - # via legacy "install system" mechanism - # In installed images, the squashfs image file is named after its image version, - # while on livecd it's just "filesystem.squashfs", that's how we tell a livecd boot - # from an installed image - boot_via = "installed image" - if run(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""") == 0: - boot_via = "livecd" - elif run(""" grep '^overlay /' /proc/mounts >/dev/null """) != 0: - boot_via = "legacy non-image installation" - version_data['boot_via'] = boot_via - - - # Get hardware details from DMI - version_data['hardware_vendor'] = read_file('/sys/class/dmi/id/sys_vendor') - version_data['hardware_model'] = read_file('/sys/class/dmi/id/product_name') - - # These two assume script is run as root, normal users can't access those files - version_data['hardware_serial'] = read_file('/sys/class/dmi/id/subsystem/id/product_serial') - version_data['hardware_uuid'] = read_file('/sys/class/dmi/id/subsystem/id/product_uuid') - + version_data = vyos.version.get_full_version_data() if args.json: print(json.dumps(version_data)) sys.exit(0) - else: - output = pystache.render(version_output_tmpl, version_data).strip() - print(output) - if args.all: - print("Package versions:") - call("dpkg -l") + print(version_output_tmpl.format(**version_data).strip()) + + if args.all: + print("Package versions:") + call("dpkg -l") - if args.funny: - print(vyos.limericks.get_random()) + if args.funny: + print(vyos.limericks.get_random()) diff --git a/src/op_mode/vrrp.py b/src/op_mode/vrrp.py index 923cfa4d4..e024d7f63 100755 --- a/src/op_mode/vrrp.py +++ b/src/op_mode/vrrp.py @@ -21,7 +21,6 @@ import argparse import json import tabulate -import vyos.keepalived import vyos.util from vyos.ifconfig.vrrp import VRRP diff --git a/src/op_mode/wireguard.py b/src/op_mode/wireguard.py index 297ba599d..15bf63e81 100755 --- a/src/op_mode/wireguard.py +++ b/src/op_mode/wireguard.py @@ -147,8 +147,12 @@ if __name__ == '__main__': if args.listkdir: list_key_dirs() if args.showinterface: - intf = WireGuardIf(args.showinterface, create=False, debug=False) - print(intf.operational.show_interface()) + try: + intf = WireGuardIf(args.showinterface, create=False, debug=False) + print(intf.operational.show_interface()) + # the interface does not exists + except Exception: + pass if args.delkdir: if args.location: del_key_dir(args.location) |