diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | debian/control | 1 | ||||
-rw-r--r-- | interface-definitions/tftp-server.xml | 57 | ||||
-rw-r--r-- | interface-definitions/wireguard.xml | 9 | ||||
-rw-r--r-- | op-mode-definitions/dns-forwarding.xml | 3 | ||||
-rw-r--r-- | op-mode-definitions/dynamic-dns.xml | 25 | ||||
-rw-r--r-- | op-mode-definitions/force-arp.xml | 79 | ||||
-rw-r--r-- | op-mode-definitions/poweroff.xml | 4 | ||||
-rw-r--r-- | op-mode-definitions/reboot.xml | 4 | ||||
-rw-r--r-- | op-mode-definitions/wireguard-keys.xml | 42 | ||||
-rw-r--r-- | op-mode-definitions/wireguard.xml | 76 | ||||
-rwxr-xr-x | src/conf_mode/ntp.py | 6 | ||||
-rwxr-xr-x | src/conf_mode/ssh.py | 4 | ||||
-rwxr-xr-x | src/conf_mode/tftp_server.py | 162 | ||||
-rwxr-xr-x | src/conf_mode/wireguard.py | 38 | ||||
-rwxr-xr-x | src/helpers/validate-value.py | 2 | ||||
-rwxr-xr-x | src/op_mode/dynamic_dns.py (renamed from src/op_mode/dynamic_dns_status.py) | 29 | ||||
-rwxr-xr-x | src/op_mode/powerctrl.py | 4 |
18 files changed, 485 insertions, 62 deletions
@@ -26,7 +26,7 @@ op_mode_definitions: # XXX: delete top level op mode node.def's that now live in other packages rm -f $(OP_TMPL_DIR)/set/node.def rm -f $(OP_TMPL_DIR)/show/node.def - rm -f $(OP_TMPL_DIR)/show/dns/node.def + rm -f $(OP_TMPL_DIR)/show/interfaces/node.def rm -f $(OP_TMPL_DIR)/reset/node.def rm -f $(OP_TMPL_DIR)/restart/node.def rm -f $(OP_TMPL_DIR)/monitor/node.def diff --git a/debian/control b/debian/control index 70bf7a61c..04b228737 100644 --- a/debian/control +++ b/debian/control @@ -38,6 +38,7 @@ Depends: python3, beep, keepalived (>=2.0.5), wireguard, + tftpd-hpa, ${shlibs:Depends}, ${misc:Depends} Description: VyOS configuration scripts and data diff --git a/interface-definitions/tftp-server.xml b/interface-definitions/tftp-server.xml new file mode 100644 index 000000000..2874b034c --- /dev/null +++ b/interface-definitions/tftp-server.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<!-- TFTP configuration --> +<interfaceDefinition> + <node name="service"> + <children> + <node name="tftp-server" owner="${vyos_conf_scripts_dir}/tftp_server.py"> + <properties> + <help>Trivial File Transfer Protocol (TFTP) server</help> + <priority>990</priority> + </properties> + <children> + <leafNode name="directory"> + <properties> + <help>Folder containing files served by TFTP [REQUIRED]</help> + </properties> + </leafNode> + <leafNode name="allow-upload"> + <properties> + <help>Allow TFTP file uploads</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="port"> + <properties> + <help>Port for TFTP service</help> + <valueHelp> + <format>1-65535</format> + <description>Numeric IP port (default: 69)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + </leafNode> + <leafNode name="listen-address"> + <properties> + <help>Addresses for TFTP server to listen [REQUIRED]</help> + <valueHelp> + <format>ipv4</format> + <description>TFTP IPv4 listen address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>TFTP IPv6 listen address</description> + </valueHelp> + <multi/> + <constraint> + <validator name="ipv4-address"/> + <validator name="ipv6-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/wireguard.xml b/interface-definitions/wireguard.xml index 008f82a0b..1437e9f0c 100644 --- a/interface-definitions/wireguard.xml +++ b/interface-definitions/wireguard.xml @@ -68,6 +68,15 @@ <help>Remote endpoint</help> </properties> </leafNode> + <leafNode name="persistent-keepalive"> + <properties> + <help>how often send keep alives in seconds</help> + <constraint> + <regex>^(1|[1-9][0-9]{1,5})$</regex> + </constraint> + <constraintErrorMessage>keepliave timer has to be between 1 and 99999 seconds</constraintErrorMessage> + </properties> + </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/dns-forwarding.xml b/op-mode-definitions/dns-forwarding.xml index e789f4aee..be71302cd 100644 --- a/op-mode-definitions/dns-forwarding.xml +++ b/op-mode-definitions/dns-forwarding.xml @@ -4,6 +4,9 @@ <node name="show"> <children> <node name="dns"> + <properties> + <help>Show DNS information</help> + </properties> <children> <node name="forwarding"> <properties> diff --git a/op-mode-definitions/dynamic-dns.xml b/op-mode-definitions/dynamic-dns.xml index c67769a83..76c473fd7 100644 --- a/op-mode-definitions/dynamic-dns.xml +++ b/op-mode-definitions/dynamic-dns.xml @@ -4,6 +4,9 @@ <node name="show"> <children> <node name="dns"> + <properties> + <help>Show DNS information</help> + </properties> <children> <node name="dynamic"> <properties> @@ -14,7 +17,7 @@ <properties> <help>Show Dynamic DNS status</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/dynamic_dns_status.py</command> + <command>sudo ${vyos_op_scripts_dir}/dynamic_dns.py --status</command> </leafNode> </children> </node> @@ -22,4 +25,24 @@ </node> </children> </node> + <node name="update"> + <properties> + <help>Update data for a service</help> + </properties> + <children> + <node name="dns"> + <properties> + <help>Update DNS information</help> + </properties> + <children> + <node name="dynamic"> + <properties> + <help>Update Dynamic DNS information</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/dynamic_dns.py --update</command> + </node> + </children> + </node> + </children> + </node> </interfaceDefinition> diff --git a/op-mode-definitions/force-arp.xml b/op-mode-definitions/force-arp.xml new file mode 100644 index 000000000..3eadabf0a --- /dev/null +++ b/op-mode-definitions/force-arp.xml @@ -0,0 +1,79 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="force"> + <properties> + <help>Force an operation</help> + </properties> + <children> + <node name="arp"> + <properties> + <help>Send gratuitous ARP request or reply</help> + </properties> + <children> + <node name="reply"> + <properties> + <help>Send gratuitous ARP reply</help> + </properties> + <children> + <tagNode name="interface"> + <properties> + <help>Send gratuitous ARP reply on specified interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + </properties> + <children> + <tagNode name="address"> + <properties> + <help>Send gratuitous ARP reply for specified address</help> + </properties> + <command>sudo arping -I $5 -c 1 -A $7</command> + <children> + <tagNode name="count"> + <properties> + <help>Send specified number of ARP replies</help> + </properties> + <command>sudo arping -I $5 -c $9 -A $7</command> + </tagNode> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> + <node name="request"> + <properties> + <help>Send gratuitous ARP request</help> + </properties> + <children> + <tagNode name="interface"> + <properties> + <help>Send gratuitous ARP request on specified interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + </properties> + <children> + <tagNode name="address"> + <properties> + <help>Send gratuitous ARP request for specified address</help> + </properties> + <command>sudo arping -I $5 -c 1 -U $7</command> + <children> + <tagNode name="count"> + <properties> + <help>Send specified number of ARP requests</help> + </properties> + <command>sudo arping -I $5 -c $9 -U $7</command> + </tagNode> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/poweroff.xml b/op-mode-definitions/poweroff.xml index ff27f4f4d..e2483fefc 100644 --- a/op-mode-definitions/poweroff.xml +++ b/op-mode-definitions/poweroff.xml @@ -4,14 +4,14 @@ <properties> <help>Poweroff the system</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --poweroff now</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --poweroff</command> <children> <leafNode name="now"> <properties> <help>Poweroff the system without confirmation</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --poweroff now</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --poweroff</command> </leafNode> <leafNode name="cancel"> diff --git a/op-mode-definitions/reboot.xml b/op-mode-definitions/reboot.xml index 340c8ca82..affdffd98 100644 --- a/op-mode-definitions/reboot.xml +++ b/op-mode-definitions/reboot.xml @@ -4,14 +4,14 @@ <properties> <help>Reboot the system</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --reboot now</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --reboot</command> <children> <leafNode name="now"> <properties> <help>Reboot the system without confirmation</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot now</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot</command> </leafNode> <leafNode name="cancel"> diff --git a/op-mode-definitions/wireguard-keys.xml b/op-mode-definitions/wireguard-keys.xml deleted file mode 100644 index 29fce33b6..000000000 --- a/op-mode-definitions/wireguard-keys.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0"?> -<!-- wireguard key management --> -<interfaceDefinition> - <node name="generate"> - <children> - <node name="wireguard"> - <properties> - <help>wireguard key generation utility</help> - </properties> - <children> - <leafNode name="keypair"> - <properties> - <help>generate a wireguard keypair</help> - </properties> - <command>${vyos_op_scripts_dir}/wireguard_key.py --genkey</command> - </leafNode> - </children> - </node> - </children> - </node> - <node name="show"> - <children> - <node name="wireguard"> - <children> - <leafNode name="pubkey"> - <properties> - <help>show wireguard public key</help> - </properties> - <command>${vyos_op_scripts_dir}/wireguard_key.py --showpub</command> - </leafNode> - <leafNode name="privkey"> - <properties> - <help>show wireguard private key</help> - </properties> - <command>${vyos_op_scripts_dir}/wireguard_key.py --showpriv</command> - </leafNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> - diff --git a/op-mode-definitions/wireguard.xml b/op-mode-definitions/wireguard.xml new file mode 100644 index 000000000..a7e156d8d --- /dev/null +++ b/op-mode-definitions/wireguard.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- wireguard key management --> +<interfaceDefinition> + <node name="generate"> + <children> + <node name="wireguard"> + <properties> + <help>wireguard key generation utility</help> + </properties> + <children> + <leafNode name="keypair"> + <properties> + <help>generate a wireguard keypair</help> + </properties> + <command>${vyos_op_scripts_dir}/wireguard_key.py --genkey</command> + </leafNode> + </children> + </node> + </children> + </node> + <node name="show"> + <children> + <node name="wireguard"> + <children> + <leafNode name="pubkey"> + <properties> + <help>show wireguard public key</help> + </properties> + <command>${vyos_op_scripts_dir}/wireguard_key.py --showpub</command> + </leafNode> + <leafNode name="privkey"> + <properties> + <help>show wireguard private key</help> + </properties> + <command>${vyos_op_scripts_dir}/wireguard_key.py --showpriv</command> + </leafNode> + </children> + </node> + <node name="interfaces"> + <children> + <tagNode name="wireguard"> + <properties> + <help>show wireguard interface information</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py -t wireguard</script> + </completionHelp> + </properties> + <command>sudo wg show "$4"</command> + <children> + <leafNode name="allowed-ips"> + <properties> + <help>show all allowed-ips for the specified interface</help> + </properties> + <command>sudo wg show "$4" allowed-ips</command> + </leafNode> + <leafNode name="endpoints"> + <properties> + <help>show all endpoints for the specified interface</help> + </properties> + <command>sudo wg show "$4" endpoints</command> + </leafNode> + <leafNode name="peers"> + <properties> + <help>show all peer IDs for the specified interface</help> + </properties> + <command>sudo wg show "$4" peers</command> + </leafNode> + <!-- more commands upon request --> + </children> + </tagNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> + diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py index 2a6088575..8533411cc 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -154,10 +154,10 @@ def generate(ntp): def apply(ntp): if ntp is not None: - os.system('sudo /usr/sbin/invoke-rc.d ntp force-reload') + os.system('sudo systemctl restart ntp.service') else: - # NTP suuport is removed in the commit - os.system('sudo /usr/sbin/invoke-rc.d ntp stop') + # NTP support is removed in the commit + os.system('sudo systemctl stop ntp.service') os.unlink(config_file) return None diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index f1ac19473..beca7bb9a 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -236,10 +236,10 @@ def generate(ssh): def apply(ssh): if ssh is not None and 'port' in ssh.keys(): - os.system("sudo systemctl restart ssh") + os.system("sudo systemctl restart ssh.service") else: # SSH access is removed in the commit - os.system("sudo systemctl stop ssh") + os.system("sudo systemctl stop ssh.service") os.unlink(config_file) return None diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py new file mode 100755 index 000000000..9cf4489af --- /dev/null +++ b/src/conf_mode/tftp_server.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018 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 os +import stat +import pwd + +import jinja2 +import ipaddress +import netifaces + +from vyos.config import Config +from vyos import ConfigError + +config_file = r'/etc/default/tftpd-hpa' + +# Please be careful if you edit the template. +config_tmpl = """ +### Autogenerated by tftp_server.py ### + +# See manual at https://linux.die.net/man/8/tftpd + +TFTP_USERNAME="tftp" +TFTP_DIRECTORY="{{ directory }}" +{% if listen_ipv4 and listen_ipv6 -%} +TFTP_ADDRESS="{% for a in listen_ipv4 -%}{{ a }}:{{ port }}{{- " --address " if not loop.last -}}{% endfor -%} {% for a in listen_ipv6 %} --address [{{ a }}]:{{ port }}{% endfor -%}" +{% elif listen_ipv4 -%} +TFTP_ADDRESS="{% for a in listen_ipv4 -%}{{ a }}:{{ port }}{{- " --address " if not loop.last -}}{% endfor %} -4" +{% elif listen_ipv6 -%} +TFTP_ADDRESS="{% for a in listen_ipv6 -%}[{{ a }}]:{{ port }}{{- " --address " if not loop.last -}}{% endfor %} -6" +{%- endif %} + +TFTP_OPTIONS="--secure {% if allow_upload %}--create --umask 002{% endif %}" +""" + +default_config_data = { + 'directory': '', + 'allow_upload': False, + 'port': '69', + 'listen_ipv4': [], + 'listen_ipv6': [] +} + +# Verify if an IP address is assigned to any interface, IPv4 and IPv6 +def addrok(ipaddr, ipversion): + # For every available interface on this system + for interface in netifaces.interfaces(): + # If it has any IPv4 or IPv6 address (depending on ipversion) configured + if ipversion in netifaces.ifaddresses(interface).keys(): + # For every configured IP address + for addr in netifaces.ifaddresses(interface)[ipversion]: + # Check if it matches to the address requested + if addr['addr'] == ipaddr: + return True + + return False + +def get_config(): + tftpd = default_config_data + conf = Config() + if not conf.exists('service tftp-server'): + return None + else: + conf.set_level('service tftp-server') + + if conf.exists('directory'): + tftpd['directory'] = conf.return_value('directory') + + if conf.exists('allow-upload'): + tftpd['allow_upload'] = True + + if conf.exists('port'): + tftpd['port'] = conf.return_value('port') + + if conf.exists('listen-address'): + for addr in conf.return_values('listen-address'): + if (ipaddress.ip_address(addr).version == 4): + tftpd['listen_ipv4'].append(addr) + + if (ipaddress.ip_address(addr).version == 6): + tftpd['listen_ipv6'].append(addr) + + return tftpd + +def verify(tftpd): + # bail out early - looks like removal from running config + if tftpd is None: + return None + + # Configuring allowed clients without a server makes no sense + if not tftpd['directory']: + raise ConfigError('TFTP root directory must be configured!') + + if not (tftpd['listen_ipv4'] or tftpd['listen_ipv6']): + raise ConfigError('TFTP server listen address must be configured!') + + for address in tftpd['listen_ipv4']: + if not addrok(address, netifaces.AF_INET): + raise ConfigError('TFTP server listen address "{0}" not configured on this system.'.format(address)) + + for address in tftpd['listen_ipv6']: + if not addrok(address, netifaces.AF_INET6): + raise ConfigError('TFTP server listen address "{0}" not configured on this system.'.format(address)) + + return None + +def generate(tftpd): + # bail out early - looks like removal from running config + if tftpd is None: + return None + + tmpl = jinja2.Template(config_tmpl) + config_text = tmpl.render(tftpd) + with open(config_file, 'w') as f: + f.write(config_text) + + return None + +def apply(tftpd): + if tftpd is not None: + + tftp_root = tftpd['directory'] + if not os.path.exists(tftp_root): + os.makedirs(tftp_root) + os.chmod(tftp_root, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) + # get UNIX uid for user 'tftp' + tftp_uid = pwd.getpwnam('tftp').pw_uid + os.chown(tftp_root, tftp_uid, -1) + + os.system('sudo systemctl restart tftpd-hpa.service') + else: + # TFTP server support is removed in the commit + os.system('sudo systemctl stop tftpd-hpa.service') + os.unlink(config_file) + + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + sys.exit(1) diff --git a/src/conf_mode/wireguard.py b/src/conf_mode/wireguard.py index 7d52cfe94..a4f876397 100755 --- a/src/conf_mode/wireguard.py +++ b/src/conf_mode/wireguard.py @@ -116,6 +116,10 @@ def get_config(): if c.exists(cnf + ' peer ' + p + ' endpoint'): config_data['interfaces'][intfc]['peer'][p]['endpoint'] = c.return_value(cnf + ' peer ' + p + ' endpoint') + ### persistent-keepalive + if c.exists(cnf + ' peer ' + p + ' persistent-keepalive'): + config_data['interfaces'][intfc]['peer'][p]['persistent-keepalive'] = c.return_value(cnf + ' peer ' + p + ' persistent-keepalive') + #print (config_data) return config_data @@ -135,8 +139,6 @@ def verify(c): for p in c['interfaces'][i]['peer']: if not c['interfaces'][i]['peer'][p]['allowed-ips']: raise ConfigError("allowed-ips required on interface " + i + " for peer " + p) - if not c['interfaces'][i]['peer'][p]['endpoint']: - raise ConfigError("endpoint required on interface " + i + " for peer " + p) ### eventually check allowed-ips (if it's an ip and valid CIDR or so) ### endpoint needs to be IP:port @@ -192,6 +194,26 @@ def apply(c): for addr in addr_add: add_addr(intf, addr) + ### persistent-keepalive + for p in c_eff.list_nodes(intf + ' peer'): + val_eff = "" + val = "" + + if c_eff.exists_effective(intf + ' peer ' + p + ' persistent-keepalive'): + val_eff = c_eff.return_effective_value(intf + ' peer ' + p + ' persistent-keepalive') + + if 'persistent-keepalive' in c['interfaces'][intf]['peer'][p]: + val = c['interfaces'][intf]['peer'][p]['persistent-keepalive'] + + ### disable keepalive + if val_eff and not val: + c['interfaces'][intf]['peer'][p]['persistent-keepalive'] = 0 + + ### set new keepalive value + if not val_eff and val: + c['interfaces'][intf]['peer'][p]['persistent-keepalive'] = val + + ## wg command call configure_interface(c,intf) ### ifalias for snmp from description @@ -205,14 +227,22 @@ def configure_interface(c, intf): cmd = "wg set " + intf + \ " listen-port " + c['interfaces'][intf]['lport'] + \ " private-key " + pk + \ - " peer " + p + \ - " endpoint " + c['interfaces'][intf]['peer'][p]['endpoint'] + " peer " + p cmd += " allowed-ips " + for ap in c['interfaces'][intf]['peer'][p]['allowed-ips']: if ap != c['interfaces'][intf]['peer'][p]['allowed-ips'][-1]: cmd += ap + "," else: cmd += ap + + ## endpoint is only required if wg runs as client + if c['interfaces'][intf]['peer'][p]['endpoint']: + cmd += " endpoint " + c['interfaces'][intf]['peer'][p]['endpoint'] + + if 'persistent-keepalive' in c['interfaces'][intf]['peer'][p]: + cmd += " persistent-keepalive " + str( c['interfaces'][intf]['peer'][p]['persistent-keepalive']) + sl.syslog(sl.LOG_NOTICE, "sudo " + cmd) subprocess.call([ 'sudo ' + cmd], shell=True) diff --git a/src/helpers/validate-value.py b/src/helpers/validate-value.py index d702739b5..36f996d38 100755 --- a/src/helpers/validate-value.py +++ b/src/helpers/validate-value.py @@ -23,7 +23,7 @@ try: except Exception as exn: if debug: print(exn) - else: + else: pass try: diff --git a/src/op_mode/dynamic_dns_status.py b/src/op_mode/dynamic_dns.py index bbff01f49..7ac3dfe9f 100755 --- a/src/op_mode/dynamic_dns_status.py +++ b/src/op_mode/dynamic_dns.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 - +import os +import argparse import jinja2 import sys import time @@ -18,7 +19,8 @@ update-status: {{ entry.status }} {% endfor -%} """ -if __name__ == '__main__': + +def show_status(): # Do nothing if service is not configured c = Config() if not c.exists_effective('service dns dynamic'): @@ -65,3 +67,26 @@ if __name__ == '__main__': tmpl = jinja2.Template(OUT_TMPL_SRC) print(tmpl.render(data)) + + +def update_ddns(): + os.system('systemctl stop ddclient') + os.remove(cache_file) + os.system('systemctl start ddclient') + + +def main(): + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + group.add_argument("--status", help="Show DDNS status", action="store_true") + group.add_argument("--update", help="Update DDNS on a given interface", action="store_true") + args = parser.parse_args() + + if args.status: + show_status() + elif args.update: + update_ddns() + + +if __name__ == '__main__': + main() diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py index f73d6c005..8a66b3afd 100755 --- a/src/op_mode/powerctrl.py +++ b/src/op_mode/powerctrl.py @@ -126,9 +126,9 @@ def main(): args = parser.parse_args() try: - if args.reboot: + if args.reboot is not None: execute_shutdown(args.reboot, reboot=True, ask=args.yes) - if args.poweroff: + if args.poweroff is not None: execute_shutdown(args.poweroff, reboot=False,ask=args.yes) if args.cancel: cancel_shutdown() |