summaryrefslogtreecommitdiff
path: root/src/op_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/op_mode')
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py2
-rwxr-xr-xsrc/op_mode/powerctrl.py291
-rwxr-xr-xsrc/op_mode/show_dhcp.py91
-rwxr-xr-xsrc/op_mode/show_dhcpv6.py74
-rwxr-xr-xsrc/op_mode/show_interfaces.py37
-rwxr-xr-xsrc/op_mode/version.py93
-rwxr-xr-xsrc/op_mode/vrrp.py1
-rwxr-xr-xsrc/op_mode/wireguard.py8
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)