diff options
author | Kim Hagen <kim.sidney@gmail.com> | 2018-07-02 11:07:30 +0200 |
---|---|---|
committer | Kim Hagen <kim.sidney@gmail.com> | 2018-07-02 11:07:30 +0200 |
commit | f589232485ea72003b866093a6fbd4c8aac8f8f8 (patch) | |
tree | 6494934d6caade96b2887928bc4ff921a8d9ca21 | |
parent | 48596dcce9e431e448eb8684dc55d922bf7fa2c9 (diff) | |
download | vyos-salt-minion-f589232485ea72003b866093a6fbd4c8aac8f8f8.tar.gz vyos-salt-minion-f589232485ea72003b866093a6fbd4c8aac8f8f8.zip |
rework for one script
94 files changed, 6 insertions, 7230 deletions
@@ -8,13 +8,6 @@ interface_definitions: find $(CURDIR)/interface-definitions/ -type f | xargs -I {} $(CURDIR)/scripts/build-command-templates {} $(CURDIR)/schema/interface_definition.rng $(TMPL_DIR) || exit 1 - # XXX: delete top level node.def's that now live in other packages - rm -f $(TMPL_DIR)/system/node.def - rm -f $(TMPL_DIR)/system/options/node.def - rm -f $(TMPL_DIR)/service/node.def - rm -f $(TMPL_DIR)/service/dns/node.def - rm -f $(TMPL_DIR)/protocols/node.def - .PHONY: op_mode_definitions .ONESHELL: op_mode_definitions: @@ -22,13 +15,6 @@ op_mode_definitions: find $(CURDIR)/op-mode-definitions/ -type f | xargs -I {} $(CURDIR)/scripts/build-command-op-templates {} $(CURDIR)/schema/op-mode-definition.rng $(OP_TMPL_DIR) || exit 1 - # XXX: delete top level op mode node.def's that now live in other packages - rm -f $(OP_TMPL_DIR)/show/node.def - rm -f $(OP_TMPL_DIR)/show/dns/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 - .PHONY: all all: clean interface_definitions op_mode_definitions @@ -36,18 +22,3 @@ all: clean interface_definitions op_mode_definitions clean: rm -rf $(TMPL_DIR)/* rm -rf $(OP_TMPL_DIR)/* - -.PHONY: test -test: - PYTHONPATH=python/ python3 -m "nose" --with-xunit src --with-coverage --cover-erase --cover-xml --cover-package src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators --verbose - -.PHONY: sonar -sonar: - sonar-scanner -X -Dsonar.login=${SONAR_TOKEN} - -.PHONY: docs -.ONESHELL: -docs: - sphinx-apidoc -o sphinx/source/ python/ - cd sphinx/ - PYTHONPATH=../python make html diff --git a/data/interface-types.json b/data/interface-types.json deleted file mode 100644 index c452122..0000000 --- a/data/interface-types.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "loopback": "lo", - "dummy": "dum", - "ethernet": "eth", - "bonding": "bond", - "bridge": "br", - "pseudo-ethernet": "peth", - "openvpn": "vtun", - "tunnel": "tun", - "vti": "vti", - "l2tpv3": "l2tpeth", - "vxlan": "vxlan", - "wireless": "wireless", - "wirelessmodem": "wlm", - "input": "ifb", - "pppoe": "pppoe" -} diff --git a/debian/changelog b/debian/changelog index 0f41838..1df1212 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,40 +1,5 @@ -vyos-1x (1.0.5) unstable; urgency=medium +vyos-salt-minion (1.0.0) unstable; urgency=medium - * T606: Error in DNS Forwarder listen-on - * T608: Cannot configure broadcast-relay service - - -- Christian Poessinger <christian@poessinger.com> Thu, 19 Apr 2018 21:16:28 +0200 - -vyos-1x (1.0.4) unstable; urgency=medium - - * T560: dns-forwarding: replace dnsmasq with pdns-recursor - * T588: Rewrite 'service dns forwarding' in new XML style format - - -- Christian Poessinger <christian@poessinger.com> Sun, 15 Apr 2018 16:13:32 +0200 - -vyos-1x (1.0.3) unstable; urgency=medium - - * T379: Add UDP broadcast relay support - * mdns repeater scripts - remove python subprocess - * Support setting optional 'type' node in command templates - - -- Christian Poessinger <christian@poessinger.com> Sat, 06 Jan 2018 13:18:30 +0100 - -vyos-1x (1.0.2) unstable; urgency=low - - * Added mdns-repeater configuration nodes - - -- Christian Poessinger <christian@poessinger.com> Sat, 09 Dec 2017 10:39:35 +0100 - -vyos-1x (1.0.1) unstable; urgency=low - - * Added the Python library for reading VyOS configs - - -- Daniil Baturin <daniil@baturin.org> Thu, 17 Aug 2017 22:22:17 -0400 - -vyos-1x (1.0.0) unstable; urgency=low - - * Created the package - - -- Daniil Baturin <daniil@baturin.org> Thu, 17 Aug 2017 20:17:04 -0400 + * Initial release + -- Kim Hagen <kim.sidney@gmail.com> Mon, 2 Jul 2018 21:16:28 +0200 diff --git a/debian/control b/debian/control index 51f3966..54203cb 100644 --- a/debian/control +++ b/debian/control @@ -1,4 +1,4 @@ -Source: vyos-1x +Source: vyos-salt-minion Section: contrib/net Priority: extra Maintainer: VyOS Package Maintainers <maintainers@vyos.net> @@ -12,7 +12,7 @@ Build-Depends: debhelper (>= 9), python3-coverage Standards-Version: 3.9.6 -Package: vyos-1x +Package: vyos-salt-minion Architecture: all Depends: python3, ${python3:Depends}, diff --git a/debian/lintian-overrides b/debian/lintian-overrides deleted file mode 100644 index 6c5d671..0000000 --- a/debian/lintian-overrides +++ /dev/null @@ -1,6 +0,0 @@ -# It's FSH compliant! -vyos-1x: file-in-unusual-dir usr/libexec/* -vyos-1x: non-standard-dir-in-usr usr/libexec/ - -# Nothing we can do about that right now -vyos-1x: dir-or-file-in-opt diff --git a/debian/rules b/debian/rules index d284471..ab9f3bb 100755 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,6 @@ #!/usr/bin/make -f -DIR := debian/vyos-1x +DIR := debian/vyos-salt-minion VYOS_SBIN_DIR := usr/sbin/ VYOS_BIN_DIR := usr/bin/ VYOS_LIBEXEC_DIR := usr/libexec/vyos @@ -17,45 +17,10 @@ override_dh_auto_build: make all override_dh_auto_install: - dh_install -pvyos-1x - cd python; python3 setup.py install --install-layout=deb --root ../$(DIR); cd .. - - # Install scripts - mkdir -p $(DIR)/$(VYOS_SBIN_DIR) - mkdir -p $(DIR)/$(VYOS_BIN_DIR) - cp -r src/utils/* $(DIR)/$(VYOS_BIN_DIR) - # Install conf mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode cp -r src/conf_mode/* $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode - # Install op mode scripts - mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/op_mode - cp -r src/op_mode/* $(DIR)/$(VYOS_LIBEXEC_DIR)/op_mode - - # Install validators - mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/validators - cp -r src/validators/* $(DIR)/$(VYOS_LIBEXEC_DIR)/validators - - # Install completion helpers - mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/completion - cp -r src/completion/* $(DIR)/$(VYOS_LIBEXEC_DIR)/completion - - # Install helper scripts - cp -r src/helpers/* $(DIR)/$(VYOS_LIBEXEC_DIR)/ - - # Install migration scripts - mkdir -p $(DIR)/$(MIGRATION_SCRIPTS_DIR) - cp -r src/migration-scripts/* $(DIR)/$(MIGRATION_SCRIPTS_DIR) - # Install configuration command definitions mkdir -p $(DIR)/$(VYOS_CFG_TMPL_DIR) cp -r templates-cfg/* $(DIR)/$(VYOS_CFG_TMPL_DIR) - - # Install operational command definitions - mkdir -p $(DIR)/$(VYOS_OP_TMPL_DIR) - cp -r templates-op/* $(DIR)/$(VYOS_OP_TMPL_DIR) - - # Install data files - mkdir -p $(DIR)/$(VYOS_DATA_DIR) - cp -r data/* $(DIR)/$(VYOS_DATA_DIR) diff --git a/interface-definitions/bcast-relay.xml b/interface-definitions/bcast-relay.xml deleted file mode 100644 index 0437192..0000000 --- a/interface-definitions/bcast-relay.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0"?> -<!-- UDP broadcast relay configuration --> -<interfaceDefinition> - <node name="service"> - <children> - <node name="broadcast-relay"> - <properties> - <help>UDP Broadcast Relay parameters</help> - </properties> - <children> - <tagNode name="id" owner="${vyos_conf_scripts_dir}/bcast_relay.py"> - <properties> - <help>Unique ID for each UDP port to forward</help> - <valueHelp> - <format>1-99</format> - <description>Numerical ID #</description> - </valueHelp> - <priority>990</priority> - <constraint> - <validator name="numeric" argument="--range 1-99"/> - </constraint> - </properties> - <children> - <leafNode name="address"> - <properties> - <help>Set source IP of forwarded packets, otherwise original senders address is used</help> - <valueHelp> - <format>ipv4</format> - <description>Optional source address for forwarded packets</description> - </valueHelp> - <constraint> - <validator name="ipv4"/> - </constraint> - </properties> - </leafNode> - <leafNode name="description"> - <properties> - <help>Description</help> - </properties> - </leafNode> - <leafNode name="interface"> - <properties> - <help>Interface to repeat UDP broadcasts to [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="port"> - <properties> - <help>Destination or source port to listen and retransmit on [REQUIRED]</help> - <valueHelp> - <format>1-65535</format> - <description>UDP port to listen on</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - </properties> - </leafNode> - </children> - </tagNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/beep-on-boot.xml b/interface-definitions/beep-on-boot.xml deleted file mode 100644 index 0da7d0d..0000000 --- a/interface-definitions/beep-on-boot.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0"?> - -<!-- beep once the login target has been reached --> - -<interfaceDefinition> - <node name="system"> - <children> - <node name="options"> - <children> - <leafNode name="beep-if-fully-booted" owner="${vyos_conf_scripts_dir}/beep_if_fully_booted.py"> - <properties> - <help>plays sound via system speaker when you can login</help> - <valueless/> - <priority>9999</priority> - </properties> - </leafNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/cron.xml b/interface-definitions/cron.xml deleted file mode 100644 index 2d4921b..0000000 --- a/interface-definitions/cron.xml +++ /dev/null @@ -1,75 +0,0 @@ -<?xml version="1.0"?> - -<!-- Cron configuration --> - -<interfaceDefinition> - <node name="system"> - <children> - <node name="task-scheduler"> - <properties> - <help>Task scheduler settings</help> - </properties> - <children> - <tagNode name="task" owner="${vyos_conf_scripts_dir}/task_scheduler.py"> - <properties> - <help>Scheduled task</help> - <valueHelp> - <format><string></format> - <description>Task name</description> - </valueHelp> - <priority>999</priority> - </properties> - <children> - <leafNode name="crontab-spec"> - <properties> - <help>UNIX crontab time specification string</help> - </properties> - </leafNode> - <leafNode name="interval"> - <properties> - <help>Execution interval</help> - <valueHelp> - <format><minutes></format> - <description>Execution interval in minutes</description> - </valueHelp> - <valueHelp> - <format><minutes>m</format> - <description>Execution interval in minutes</description> - </valueHelp> - <valueHelp> - <format><hours>h</format> - <description>Execution interval in hours</description> - </valueHelp> - <valueHelp> - <format><days>d</format> - <description>Execution interval in days</description> - </valueHelp> - <constraint> - <regex>[1-9]([0-9]*)([mhd]{0,1})</regex> - </constraint> - </properties> - </leafNode> - <node name="executable"> - <properties> - <help>Executable path and arguments</help> - </properties> - <children> - <leafNode name="path"> - <properties> - <help>Path to executable</help> - </properties> - </leafNode> - <leafNode name="arguments"> - <properties> - <help>Arguments passed to the executable</help> - </properties> - </leafNode> - </children> - </node> - </children> - </tagNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/dns-forwarding.xml b/interface-definitions/dns-forwarding.xml deleted file mode 100644 index a00b23d..0000000 --- a/interface-definitions/dns-forwarding.xml +++ /dev/null @@ -1,135 +0,0 @@ -<?xml version="1.0"?> -<!-- DNS forwarder configuration --> -<interfaceDefinition> - <node name="service"> - <children> - <node name="dns"> - <children> - <node name="forwarding" owner="${vyos_conf_scripts_dir}/dns_forwarding.py"> - <properties> - <help>DNS forwarding</help> - <priority>918</priority> - </properties> - <children> - <leafNode name="cache-size"> - <properties> - <help>DNS forwarding cache size</help> - <valueHelp> - <format>0-10000</format> - <description>DNS forwarding cache size</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-10000"/> - </constraint> - </properties> - </leafNode> - <leafNode name="dhcp"> - <properties> - <help>Use DNS servers received from DHCP server for specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <tagNode name="domain"> - <properties> - <help>Domain to forward to a custom DNS server</help> - </properties> - <children> - <leafNode name="server"> - <properties> - <help>Domain Name Server (DNS) to forward queries to</help> - <valueHelp> - <format>ipv4</format> - <description>Domain Name Server (DNS) IPv4 address</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>Domain Name Server (DNS) IPv6 address</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - </children> - </tagNode> - <leafNode name="ignore-hosts-file"> - <properties> - <help>Do not use local /etc/hosts file in name resolution</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="listen-address"> - <properties> - <help>Addresses to listen for DNS queries [REQUIRED]</help> - <valueHelp> - <format>ipv4</format> - <description>Domain Name Server (DNS) IPv4 address</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>Domain Name Server (DNS) IPv6 address</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - <leafNode name="listen-on"> - <properties> - <help>Interface to listen for DNS queries [DEPRECATED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="negative-ttl"> - <properties> - <help>Maximum amount of time negative entries are cached</help> - <valueHelp> - <format>0-7200</format> - <description>Seconds to cache NXDOMAIN entries</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-7200"/> - </constraint> - </properties> - </leafNode> - <leafNode name="name-server"> - <properties> - <help>Domain Name Servers (DNS) addresses</help> - <valueHelp> - <format>ipv4</format> - <description>Domain Name Server (DNS) IPv4 address</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>Domain Name Server (DNS) IPv6 address</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - <leafNode name="system"> - <properties> - <help>Use system name servers</help> - <valueless/> - </properties> - </leafNode> - </children> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/host-name.xml b/interface-definitions/host-name.xml deleted file mode 100644 index bbe6796..0000000 --- a/interface-definitions/host-name.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0"?> - -<!-- host-name configuration --> - -<interfaceDefinition> - <node name="system"> - <children> - <leafNode name="host-name" owner="${vyos_conf_scripts_dir}/host_name.py"> - <properties> - <help>System host name (default: vyos)</help> - <constraint> - <regex>[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="domain-name" owner="${vyos_conf_scripts_dir}/host_name.py"> - <properties> - <help>System domain name</help> - <constraint> - <regex>[A-Za-z0-9][-.A-Za-z0-9]*</regex> - </constraint> - </properties> - </leafNode> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/mdns-repeater.xml b/interface-definitions/mdns-repeater.xml deleted file mode 100644 index d74e203..0000000 --- a/interface-definitions/mdns-repeater.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0"?> -<!-- mDNS repeater configuration --> -<interfaceDefinition> - <node name="service"> - <children> - <node name="mdns"> - <properties> - <help>Multicast DNS (mDNS) parameters</help> - </properties> - <children> - <node name="repeater" owner="${vyos_conf_scripts_dir}/mdns_repeater.py"> - <properties> - <help>mDNS repeater configuration</help> - <priority>990</priority> - </properties> - <children> - <leafNode name="interface"> - <properties> - <help>Interface to repeat mdns advertisements to [REQUIRED]</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - </children> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/ntp.xml b/interface-definitions/ntp.xml deleted file mode 100644 index d324404..0000000 --- a/interface-definitions/ntp.xml +++ /dev/null @@ -1,89 +0,0 @@ -<?xml version="1.0"?> -<!-- NTP configuration --> -<interfaceDefinition> - <node name="system"> - <children> - <node name="ntp" owner="${vyos_conf_scripts_dir}/ntp.py"> - <properties> - <help>Network Time Protocol (NTP) configuration</help> - <priority>400</priority> - </properties> - <children> - <tagNode name="server"> - <properties> - <help>Network Time Protocol (NTP) server</help> - </properties> - <children> - <leafNode name="dynamic"> - <properties> - <help>Allow server to be configured even if not reachable</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="noselect"> - <properties> - <help>Marks the server as unused</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="preempt"> - <properties> - <help>Specifies the association as preemptable rather than the default persistent</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="prefer"> - <properties> - <help>Marks the server as preferred</help> - <valueless/> - </properties> - </leafNode> - </children> - </tagNode> - <node name="allow-clients"> - <properties> - <help>Network Time Protocol (NTP) server options</help> - </properties> - <children> - <leafNode name="address"> - <properties> - <help>IP address</help> - <valueHelp> - <format>ipv4net</format> - <description>IP address and prefix length</description> - </valueHelp> - <valueHelp> - <format>ipv6net</format> - <description>IPv6 address and prefix length</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ip-prefix"/> - </constraint> - </properties> - </leafNode> - </children> - </node> - <leafNode name="listen-address"> - <properties> - <help>Addresses to listen for NTP queries</help> - <valueHelp> - <format>ipv4</format> - <description>Network Time Protocol (NTP) IPv4 address</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>Network Time Protocol (NTP) IPv6 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/snmp.xml b/interface-definitions/snmp.xml deleted file mode 100644 index 103aa39..0000000 --- a/interface-definitions/snmp.xml +++ /dev/null @@ -1,606 +0,0 @@ -<?xml version="1.0"?> -<!-- SNMP forwarder configuration --> -<interfaceDefinition> - <node name="service"> - <children> - <node name="snmp" owner="${vyos_conf_scripts_dir}/snmp.py"> - <properties> - <help>Simple Network Management Protocol (SNMP)</help> - <priority>980</priority> - </properties> - <children> - <tagNode name="community"> - <properties> - <help>Community name [REQUIRED]</help> - <constraint> - <regex>^[a-zA-Z0-9\-_]{1,100}</regex> - </constraint> - <constraintErrorMessage>Community string is limited to alphanumerical characters only with a total lenght of 100</constraintErrorMessage> - </properties> - <children> - <leafNode name="authorization"> - <properties> - <help>Authorization type (default: 'ro')</help> - <valueHelp> - <format>ro</format> - <description>read only</description> - </valueHelp> - <valueHelp> - <format>rw</format> - <description>read write</description> - </valueHelp> - <constraint> - <regex>(ro|rw)</regex> - </constraint> - <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="client"> - <properties> - <help>IP address of SNMP client allowed to contact system</help> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> - <leafNode name="network"> - <properties> - <help>Subnet of SNMP client(s) allowed to contact system</help> - <valueHelp> - <format>ipv4net</format> - <description>IP address and prefix length</description> - </valueHelp> - <valueHelp> - <format>ipv6net</format> - <description>IPv6 address and prefix length</description> - </valueHelp> - <constraint> - <validator name="ip-prefix"/> - </constraint> - <multi/> - </properties> - </leafNode> - </children> - </tagNode> - <leafNode name="contact"> - <properties> - <help>Contact information</help> - <constraint> - <regex>.{1,255}</regex> - </constraint> - <constraintErrorMessage>Contact information is limited to 255 characters or less</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="description"> - <properties> - <help>Description information</help> - <constraint> - <regex>.{1,255}</regex> - </constraint> - <constraintErrorMessage>Description is limited to 255 characters or less</constraintErrorMessage> - </properties> - </leafNode> - <tagNode name="listen-address"> - <properties> - <help>IP address to listen for incoming SNMP requests</help> - <valueHelp> - <format>ipv4</format> - <description>IPv4 address to listen for incoming SNMP requests</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address to listen for incoming SNMP requests</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - <children> - <leafNode name="port"> - <properties> - <help>Port for SNMP service (default: '161')</help> - <valueHelp> - <format>1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> - </leafNode> - </children> - </tagNode> - <leafNode name="location"> - <properties> - <help>Location information</help> - <constraint> - <regex>.{1,255}</regex> - </constraint> - <constraintErrorMessage>Location is limited to 255 characters or less</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="smux-peer"> - <properties> - <help>Register a subtree for SMUX-based processing</help> - <valueHelp> - <format>oid</format> - <description>Object Identifier</description> - </valueHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="trap-source"> - <properties> - <help>SNMP trap source address</help> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - <tagNode name="trap-target"> - <properties> - <help>Address of trap target</help> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - <children> - <leafNode name="community"> - <properties> - <help>Community used when sending trap information</help> - </properties> - </leafNode> - <leafNode name="port"> - <properties> - <help>Destination port used for trap notification</help> - <valueHelp> - <format>1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> - </leafNode> - </children> - </tagNode> - <node name="v3"> - <properties> - <help>Simple Network Management Protocol (SNMP) v3</help> - </properties> - <children> - <leafNode name="engineid"> - <properties> - <help>Specifies the EngineID that uniquely identify an agent (e.g. 0xff42)</help> - <constraint> - <regex>^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$</regex> - </constraint> - <constraintErrorMessage>ID must contain an even number (from 2 to 36) of hex digits</constraintErrorMessage> - </properties> - </leafNode> - <tagNode name="group"> - <properties> - <help>Specifies the group with name groupname</help> - </properties> - <children> - <leafNode name="mode"> - <properties> - <help>Define group access permission (default: 'ro')</help> - <valueHelp> - <format>ro</format> - <description>read only</description> - </valueHelp> - <valueHelp> - <format>rw</format> - <description>read write</description> - </valueHelp> - <constraint> - <regex>(ro|rw)</regex> - </constraint> - <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="seclevel"> - <properties> - <help>Security levels</help> - <valueHelp> - <format>noauth</format> - <description>Messages not authenticated and not encrypted (noAuthNoPriv)</description> - </valueHelp> - <valueHelp> - <format>auth</format> - <description>Messages are authenticated but not encrypted (authNoPriv)</description> - </valueHelp> - <valueHelp> - <format>priv</format> - <description>Messages are authenticated and encrypted (authPriv)</description> - </valueHelp> - <constraint> - <regex>(noauth|auth|priv)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="view"> - <properties> - <help>Defines the name of view</help> - <completionHelp> - <path>service snmp v3 view</path> - </completionHelp> - </properties> - </leafNode> - </children> - </tagNode> - <tagNode name="trap-target"> - <properties> - <help>Defines SNMP target for inform or traps for IP</help> - <valueHelp> - <format>ipv4</format> - <description>IP address of trap target</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address of trap target</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - <children> - <node name="auth"> - <properties> - <help>Defines the privacy</help> - </properties> - <children> - <leafNode name="encrypted-key"> - <properties> - <help>Defines the encrypted key for authentication</help> - <constraint> - <regex>^0x[0-9a-f]*$</regex> - </constraint> - <constraintErrorMessage>Key must start from '0x' and contain hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="plaintext-key"> - <properties> - <help>Defines the clear text key for authentication</help> - <constraint> - <regex>^.{8,}$</regex> - </constraint> - <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol used for authentication (default: 'md5')</help> - <valueHelp> - <format>md5</format> - <description>Message Digest 5</description> - </valueHelp> - <valueHelp> - <format>sha</format> - <description>Secure Hash Algorithm</description> - </valueHelp> - <constraint> - <regex>(md5|sha)</regex> - </constraint> - </properties> - </leafNode> - </children> - </node> - <leafNode name="engineid"> - <properties> - <help>Specifies the EngineID that uniquely identify an agent (e.g. 0xff42)</help> - <constraint> - <regex>^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$</regex> - </constraint> - <constraintErrorMessage>ID must contain from 2 to 36 hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="port"> - <properties> - <help>Specifies TCP/UDP port of destination SNMP traps/informs (default: '162')</help> - <valueHelp> - <format>1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> - </leafNode> - <node name="privacy"> - <properties> - <help>Defines the privacy</help> - </properties> - <children> - <leafNode name="encrypted-key"> - <properties> - <help>Defines the encrypted key for privacy protocol</help> - <constraint> - <regex>^0x[0-9a-f]*$</regex> - </constraint> - <constraintErrorMessage>Key must start from '0x' and contain hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="plaintext-key"> - <properties> - <help>Defines the clear text key for privacy protocol</help> - <constraint> - <regex>^.{8,}$</regex> - </constraint> - <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol for privacy (default: 'des')</help> - <valueHelp> - <format>des</format> - <description>Data Encryption Standard</description> - </valueHelp> - <valueHelp> - <format>aes</format> - <description>Advanced Encryption Standard</description> - </valueHelp> - <constraint> - <regex>(des|aes)</regex> - </constraint> - </properties> - </leafNode> - </children> - </node> - <leafNode name="protocol"> - <properties> - <help>Defines protocol for notification between TCP and UDP</help> - <valueHelp> - <format>tcp</format> - <description>Use Transmission Control Protocol for notifications</description> - </valueHelp> - <valueHelp> - <format>udp</format> - <description>Use User Datagram Protocol for notifications</description> - </valueHelp> - <constraint> - <regex>(tcp|udp)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>Specifies the type of notification between inform and trap (default: 'inform')</help> - <valueHelp> - <format>inform</format> - <description>Use INFORM</description> - </valueHelp> - <valueHelp> - <format>trap</format> - <description>Use TRAP</description> - </valueHelp> - <constraint> - <regex>(inform|trap)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="user"> - <properties> - <help>Defines username for authentication</help> - <completionHelp> - <path>service snmp v3 user</path> - </completionHelp> - </properties> - </leafNode> - </children> - </tagNode> - <node name="tsm"> - <properties> - <help>Specifies that SNMPv3 uses the Transport Security Model (TSM)</help> - </properties> - <children> - <leafNode name="local-key"> - <properties> - <help>Fingerprint of a TSM server certificate</help> - <constraint> - <regex>^[0-9A-F]{2}(:[0-9A-F]{2}){19}$</regex> - </constraint> - <constraintErrorMessage>Value can be finger print key or filename in /config/snmp/tls/certs</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="port"> - <properties> - <help>Defines the port used for TSM (default: '10161')</help> - <valueHelp> - <format>1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> - </leafNode> - </children> - </node> - <tagNode name="user"> - <properties> - <help>Specifies the user with name username</help> - <constraint> - <regex>^[^\(\)\|\-]+$</regex> - </constraint> - <constraintErrorMessage>Illegal characters in name</constraintErrorMessage> - </properties> - <children> - <node name="auth"> - <properties> - <help>Specifies the auth</help> - </properties> - <children> - <leafNode name="encrypted-key"> - <properties> - <help>Defines the encrypted key for authentication</help> - <constraint> - <regex>^0x[0-9a-f]*$</regex> - </constraint> - <constraintErrorMessage>Key must start from '0x' and contain hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="plaintext-key"> - <properties> - <help>Defines the clear text key for authentication</help> - <constraint> - <regex>^.{8,}$</regex> - </constraint> - <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol used for authentication (default: 'md5')</help> - <valueHelp> - <format>md5</format> - <description>Message Digest 5</description> - </valueHelp> - <valueHelp> - <format>sha</format> - <description>Secure Hash Algorithm</description> - </valueHelp> - <constraint> - <regex>(md5|sha)</regex> - </constraint> - </properties> - </leafNode> - </children> - </node> - <leafNode name="engineid"> - <properties> - <help>Specifies the EngineID that uniquely identify an agent (e.g. 0xff42)</help> - <constraint> - <regex>^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$</regex> - </constraint> - <constraintErrorMessage>ID must contain from 2 to 36 hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="group"> - <properties> - <help>Specifies group for user name</help> - <completionHelp> - <path>service snmp v3 group</path> - </completionHelp> - </properties> - </leafNode> - <leafNode name="mode"> - <properties> - <help>Define users access permission (default: 'ro')</help> - <valueHelp> - <format>ro</format> - <description>read only</description> - </valueHelp> - <valueHelp> - <format>rw</format> - <description>read write</description> - </valueHelp> - <constraint> - <regex>(ro|rw)</regex> - </constraint> - <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> - </properties> - </leafNode> - <node name="privacy"> - <properties> - <help>Defines the privacy</help> - </properties> - <children> - <leafNode name="encrypted-key"> - <properties> - <help>Defines the encrypted key for privacy protocol</help> - <constraint> - <regex>^0x[0-9a-f]*$</regex> - </constraint> - <constraintErrorMessage>Key must start from '0x' and contain hex digits</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="plaintext-key"> - <properties> - <help>Defines the clear text key for privacy protocol</help> - <constraint> - <regex>^.{8,}$</regex> - </constraint> - <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol for privacy (default: 'des')</help> - <valueHelp> - <format>des</format> - <description>Data Encryption Standard</description> - </valueHelp> - <valueHelp> - <format>aes</format> - <description>Advanced Encryption Standard</description> - </valueHelp> - <constraint> - <regex>(des|aes)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="tsm-key"> - <properties> - <help>Specifies finger print or file name of TSM certificate</help> - </properties> - </leafNode> - </children> - </node> - </children> - </tagNode> - <tagNode name="view"> - <properties> - <help>Specifies the view with name viewname</help> - <constraint> - <regex>^[^\(\)\|\-]+$</regex> - </constraint> - <constraintErrorMessage>Illegal characters in name</constraintErrorMessage> - </properties> - <children> - <tagNode name="oid"> - <properties> - <help>Specifies the oid</help> - <constraint> - <regex>^[0-9]+(\\.[0-9]+)*$</regex> - </constraint> - <constraintErrorMessage>OID must start from a number</constraintErrorMessage> - </properties> - <children> - <leafNode name="exclude"> - <properties> - <help>Exclude is an optional argument</help> - </properties> - </leafNode> - <leafNode name="mask"> - <properties> - <help>Defines a bit-mask that is indicating which subidentifiers of the associated subtree OID should be regarded as significant</help> - <constraint> - <regex>^[0-9a-f]{2}([\\.:][0-9a-f]{2})*$</regex> - </constraint> - <constraintErrorMessage>MASK is a list of hex octets, separated by '.' or ':'</constraintErrorMessage> - </properties> - </leafNode> - </children> - </tagNode> - </children> - </tagNode> - </children> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/interface-definitions/ssh.xml b/interface-definitions/ssh.xml deleted file mode 100644 index 9b3a2fd..0000000 --- a/interface-definitions/ssh.xml +++ /dev/null @@ -1,157 +0,0 @@ -<?xml version="1.0"?> - -<!--SSH configuration --> - -<interfaceDefinition> - <node name="service"> - <children> - <node name="ssh" owner="${vyos_conf_scripts_dir}/ssh.py"> - <properties> - <help>Secure SHell (SSH) protocol</help> - <priority>500</priority> - </properties> - <children> - <node name="access-control"> - <properties> - <help>SSH user/group access controls. Directives are processed in this order: deny-users, allow-users, deny-groups and allow-groups</help> - </properties> - <children> - <node name="allow"> - <children> - <leafNode name="group"> - <properties> - <help>Allow members of a group to login</help> - <multi/> - </properties> - </leafNode> - <leafNode name="user"> - <properties> - <help>Allow specific users to login</help> - <multi/> - </properties> - </leafNode> - </children> - </node> - <node name="deny"> - <children> - <leafNode name="group"> - <properties> - <help>Disallow members of a group to login</help> - <multi/> - </properties> - </leafNode> - <leafNode name="user"> - <properties> - <help>Disallow specific users to login</help> - <multi/> - </properties> - </leafNode> - </children> - </node> - </children> - </node> - <leafNode name="allow-root"> - <properties> - <help>Allow the root user to login</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="ciphers"> - <properties> - <help>Allowed ciphers</help> - <completionHelp> - <script>ssh -Q cipher | tr '\n' ' '</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="disable-host-validation"> - <properties> - <help>Don't validate the remote host name with DNS</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="disable-password-authentication"> - <properties> - <help>Disable password-based authentication</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="key-exchange"> - <properties> - <help>Allowed key exchange (KEX) algorithms</help> - <completionHelp> - <script>ssh -Q kex | tr '\n' ' '</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="listen-address"> - <properties> - <help>Local addresses SSH service should listen on</help> - <valueHelp> - <format>ipv4</format> - <description>IP address to listen for incoming connections</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address to listen for incoming connections</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> - <leafNode name="loglevel"> - <properties> - <help>Log level</help> - <valueHelp> - <format>QUIET</format> - <description>stay silent</description> - </valueHelp> - <valueHelp> - <format>FATAL</format> - <description>log fatals only</description> - </valueHelp> - <valueHelp> - <format>ERROR</format> - <description>log errors and fatals only</description> - </valueHelp> - <valueHelp> - <format>INFO</format> - <description>default log level</description> - </valueHelp> - <valueHelp> - <format>VERBOSE</format> - <description>enable logging of failed login attempts</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="mac"> - <properties> - <help>Allowed message authentication code (MAC) algorithms</help> - <completionHelp> - <script>ssh -Q mac | tr '\n' ' '</script> - </completionHelp> - <multi/> - </properties> - </leafNode> - <leafNode name="port"> - <properties> - <help>Port for SSH service</help> - <valueHelp> - <format>1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - </properties> - </leafNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/bandwidth-monitor.xml b/op-mode-definitions/bandwidth-monitor.xml deleted file mode 100644 index 410ab49..0000000 --- a/op-mode-definitions/bandwidth-monitor.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="monitor"> - <children> - <node name="bandwidth"> - <properties> - <help>Monitor interface bandwidth in real time</help> - </properties> - <children> - <tagNode name="interface"> - <command>bmon -p $4</command> - <properties> - <help>Monitor bandwidth usage on specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - </tagNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/dns-forwarding.xml b/op-mode-definitions/dns-forwarding.xml deleted file mode 100644 index e789f4a..0000000 --- a/op-mode-definitions/dns-forwarding.xml +++ /dev/null @@ -1,72 +0,0 @@ -<?xml version="1.0"?> - -<interfaceDefinition> - <node name="show"> - <children> - <node name="dns"> - <children> - <node name="forwarding"> - <properties> - <help>Show DNS forwarding information</help> - </properties> - <children> - <leafNode name="statistics"> - <properties> - <help>Show DNS forwarding statistics</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/dns_forwarding_statistics.py</command> - </leafNode> - </children> - </node> - </children> - </node> - </children> - </node> - <node name="restart"> - <children> - <node name="dns"> - <properties> - <help>Restart a DNS service</help> - </properties> - <children> - <leafNode name="forwarding"> - <properties> - <help>Restart DNS forwarding service</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/dns_forwarding_restart.sh</command> - </leafNode> - </children> - </node> - </children> - </node> - <node name="reset"> - <children> - <node name="dns"> - <properties> - <help>Reset a DNS service state</help> - </properties> - <children> - <node name="forwarding"> - <properties> - <help>Reset DNS forwarding cache</help> - </properties> - <children> - <tagNode name="domain"> - <command>sudo ${vyos_op_scripts_dir}/dns_forwarding_reset.py $5</command> - <properties> - <help>Reset DNS forwarding cache for a domain</help> - </properties> - </tagNode> - <leafNode name="all"> - <command>sudo ${vyos_op_scripts_dir}/dns_forwarding_reset.py --all</command> - <properties> - <help>Reset DNS forwarding cache</help> - </properties> - </leafNode> - </children> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/poweroff.xml b/op-mode-definitions/poweroff.xml deleted file mode 100644 index 07cea79..0000000 --- a/op-mode-definitions/poweroff.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="poweroff"> - <properties> - <help>Poweroff the system</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff</command> - <children> - <leafNode name="now"> - <properties> - <help>Poweroff the system without confirmation</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff --now</command> - </leafNode> - - <leafNode name="cancel"> - <properties> - <help>Cancel a pending poweroff</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_cancel</command> - </leafNode> - - - <tagNode name="at"> - <properties> - <help>Poweroff at a specific time</help> - <completionHelp> - <list>HH:MM</list> - <list>MMDDYY</list> - <list>midnight</list> - <list>noon</list> - </completionHelp> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_at --at_time '$3'</command> - - </tagNode> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/reboot.xml b/op-mode-definitions/reboot.xml deleted file mode 100644 index 2c5a85d..0000000 --- a/op-mode-definitions/reboot.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="reboot"> - <properties> - <help>Reboot the system</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-reboot.pl --action reboot</command> - <children> - <leafNode name="now"> - <properties> - <help>Reboot the system without confirmation</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-reboot.pl --action reboot --now</command> - </leafNode> - - <leafNode name="cancel"> - <properties> - <help>Cancel a pending reboot</help> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-reboot.pl --action reboot_cancel</command> - </leafNode> - - - <tagNode name="at"> - <properties> - <help>Reboot at a specific time</help> - <completionHelp> - <list>HH:MM</list> - <list>MMDDYY</list> - <list>midnight</list> - <list>noon</list> - </completionHelp> - </properties> - <command>/opt/vyatta/bin/sudo-users/vyatta-reboot.pl --action reboot_at --at_time '$3'</command> - - </tagNode> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-arp.xml b/op-mode-definitions/show-arp.xml deleted file mode 100644 index 92c231c..0000000 --- a/op-mode-definitions/show-arp.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="arp"> - <properties> - <help>Show Address Resolution Protocol (ARP) information</help> - </properties> - <command>/usr/sbin/arp -e -n</command> - <children> - <tagNode name="interface"> - <properties> - <help>Show Address Resolution Protocol (ARP) cache for specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py -b</script> - </completionHelp> - </properties> - <command>/usr/sbin/arp -e -n -i '$4'</command> - </tagNode> - </children> - </node> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-bridge.xml b/op-mode-definitions/show-bridge.xml deleted file mode 100644 index a324195..0000000 --- a/op-mode-definitions/show-bridge.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <leafNode name="bridge"> - <properties> - <help>Show bridging information</help> - </properties> - <command>/sbin/brctl show</command> - </leafNode> - <tagNode name="bridge"> - <properties> - <help>Show bridge information for a given bridge interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py --type bridge</script> - </completionHelp> - </properties> - <command>/sbin/brctl show '$3'</command> - <children> - <leafNode name="macs"> - <properties> - <help>Show bridge Media Access Control (MAC) address table</help> - </properties> - <command>/sbin/brctl showmacs '$3'</command> - </leafNode> - <leafNode name="spanning-tree"> - <properties> - <help>Show bridge spanning tree information</help> - </properties> - <command>/sbin/brctl showstp '$3'</command> - </leafNode> - </children> - </tagNode> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-configuration.xml b/op-mode-definitions/show-configuration.xml deleted file mode 100644 index 0b1507b..0000000 --- a/op-mode-definitions/show-configuration.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="configuration"> - <properties> - <help>Show available saved configurations</help> - </properties> - <!-- no admin check --> - <command>cli-shell-api showCfg --show-active-only --show-hide-secrets</command> - - <children> - <node name="all"> - <properties> - <help>Show running configuration (including default values)</help> - </properties> - <!-- no admin check --> - <command>cli-shell-api showCfg --show-show-defaults --show-active-only --show-hide-secrets</command> - </node> - <node name="commands"> - <properties> - <help> Show running configuration as set commands </help> - </properties> - <!-- no admin check --> - <command>cli-shell-api showCfg --show-active-only | vyos-config-to-commands</command> - </node> - <node name="files"> - <properties> - <help> Show available saved configurations </help> - </properties> - <!-- no admin check --> - <command>${vyos_op_scripts_dir}/show-configuration-files.sh</command> - </node> - </children> - </node> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-date.xml b/op-mode-definitions/show-date.xml deleted file mode 100644 index 705172b..0000000 --- a/op-mode-definitions/show-date.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="date"> - <properties> - <help>Show system time and date</help> - </properties> - <command>/bin/date</command> - <children> - <node name="utc"> - <properties> - <help>Show system date and time as Coordinated Universal Time</help> - </properties> - <command>/bin/date -u</command> - <children> - <leafNode name="maya"> - <properties> - <help>Show UTC date in Maya calendar format</help> - </properties> - <command>${vyos_op_scripts_dir}/maya_date.py $(date +%s)</command> - </leafNode> - </children> - </node> - </children> - </node> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-disk.xml b/op-mode-definitions/show-disk.xml deleted file mode 100644 index db47395..0000000 --- a/op-mode-definitions/show-disk.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <tagNode name="disk"> - <properties> - <help>Show status of disk device</help> - <completionHelp> - <script>${vyos_completion_dir}/list_disks.sh</script> - </completionHelp> - </properties> - <children> - <leafNode name="format"> - <properties> - <help>Show disk drive formatting</help> - </properties> - <command>${vyos_op_scripts_dir}/show-disk-format.sh $3</command> - </leafNode> - </children> - </tagNode> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-hardware.xml b/op-mode-definitions/show-hardware.xml deleted file mode 100644 index 6cd912a..0000000 --- a/op-mode-definitions/show-hardware.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="hardware"> - <properties> - <help>Show system hardware details</help> - </properties> - <children> - <node name="cpu"> - <properties> - <help>Show CPU info</help> - </properties> - <command>lscpu</command> - <children> - <node name="detail"> - <properties> - <help> Show system CPU details</help> - </properties> - <command>cat /proc/cpuinfo</command> - </node> - <node name="summary"> - <properties> - <help>Show CPU's on system</help> - </properties> - <command>${vyos_op_scripts_dir}/cpu_summary.py</command> - </node> - </children> - </node> - - <node name="dmi"> - <properties> - <help>Show system DMI details</help> - </properties> - <command>${vyatta_bindir}/vyatta-show-dmi</command> - </node> - - <node name="mem"> - <properties> - <help>Show system RAM details</help> - </properties> - <command>cat /proc/meminfo</command> - </node> - - <node name="pci"> - <properties> - <help>Show system PCI bus details</help> - </properties> - <command>lspci</command> - <children> - <node name="detail"> - <properties> - <help>Show verbose system PCI bus details</help> - </properties> - <command>lspci -vvv</command> - </node> - </children> - </node> - - - <node name="scsi"> - <properties> - <help>Show SCSI device information</help> - </properties> - <command>lsscsi</command> - <children> - <node name="detail"> - <properties> - <help>Show detailed SCSI device information</help> - </properties> - <command>lsscsi -vvv</command> - </node> - </children> - </node> - - <node name="usb"> - <properties> - <help>Show peripherals connected to the USB bus</help> - </properties> - <command>lsusb</command> - <children> - <node name="detail"> - <properties> - <help>Show detailed USB bus information</help> - </properties> - <command>lsusb -v</command> - </node> - </children> - </node> - - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-raid.xml b/op-mode-definitions/show-raid.xml deleted file mode 100644 index b093074..0000000 --- a/op-mode-definitions/show-raid.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <tagNode name="raid"> - <properties> - <help>Show statis of RAID set</help> - <completionHelp> - <script>${vyos_completion_dir}/list_raidset.sh</script> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/show_raid.sh $3</command> - - </tagNode> - - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/show-users.xml b/op-mode-definitions/show-users.xml deleted file mode 100644 index a026e47..0000000 --- a/op-mode-definitions/show-users.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="users"> - <properties> - <help>Show user information</help> - </properties> - <command>who -H</command> - <children> - <node name="recent"> - <properties> - <help>Show 10 recently logged in users</help> - </properties> - <command>last -aF -n 10 | sed -e 's/^wtmp begins/Displaying logins since/'</command> - </node> - <tagNode name="recent"> - <properties> - <help>Show specified number of recently logged in users</help> - <completionHelp> - <list>NUMBER</list> - </completionHelp> - </properties> - <command>last -aF -n $4 | sed -e 's/^wtmp begins/Displaying logins since/'</command> - </tagNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/snmp.xml b/op-mode-definitions/snmp.xml deleted file mode 100644 index a0a47da..0000000 --- a/op-mode-definitions/snmp.xml +++ /dev/null @@ -1,111 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="snmp"> - <properties> - <help>Show status of SNMP on localhost</help> - </properties> - <children> - <tagNode name="community"> - <properties> - <help>Show status of SNMP community</help> - <completionHelp> - <script>${vyos_op_scripts_dir}/snmp.py --allowed</script> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/snmp.py --community="$4"</command> - <children> - <tagNode name="host"> - <properties> - <help>Show status of SNMP on remote host</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp.py --community="$4" --host "$6"</command> - </tagNode> - </children> - </tagNode> - <node name="mib"> - <properties> - <help>Show SNMP MIB information</help> - </properties> - <children> - <node name="ifmib"> - <properties> - <help>Show all SNMP interfaces MIB information</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_ifmib.py</command> - <children> - <tagNode name="ifAlias"> - <properties> - <help>Show SNMP ifAlias for specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifalias="$6"</command> - </tagNode> - <tagNode name="ifDescr"> - <properties> - <help>Show SNMP ifDescr for specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifdescr="$6"</command> - </tagNode> - <tagNode name="ifIndex"> - <properties> - <help>Show SNMP ifDescr for specified interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifindex="$6"</command> - </tagNode> - </children> - </node> - </children> - </node> - <node name="v3"> - <properties> - <help>Show SNMP v3 status on localhost</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3.py --all</command> - <children> - <leafNode name="certificates"> - <properties> - <help>Show TSM certificates</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3_showcerts.sh</command> - </leafNode> - <leafNode name="group"> - <properties> - <help>Show the list of configured groups</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3.py --group</command> - </leafNode> - <leafNode name="trap-target"> - <properties> - <help>Show the list of configured targets</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3.py --trap</command> - </leafNode> - <leafNode name="user"> - <properties> - <help>Show the list of configured users</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3.py --user</command> - </leafNode> - <leafNode name="view"> - <properties> - <help>Show the list of configured views</help> - </properties> - <command>${vyos_op_scripts_dir}/snmp_v3.py --view</command> - </leafNode> - </children> - </node> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/traffic-dump.xml b/op-mode-definitions/traffic-dump.xml deleted file mode 100644 index a681064..0000000 --- a/op-mode-definitions/traffic-dump.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="monitor"> - <children> - <node name="traffic"> - <properties> - <help>Monitor traffic dumps</help> - </properties> - <children> - <tagNode name="interface"> - <command>tcpdump -i $4</command> - <properties> - <help>Monitor traffic dump from an interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_dumpable_interfaces.py</script> - </completionHelp> - </properties> - <children> - <tagNode name="filter"> - <command>tcpdump -n -i $4 $6</command> - <properties> - <help>Monitor traffic matching filter conditions</help> - </properties> - </tagNode> - <tagNode name="save"> - <command>tcpdump -n -i $4 -w $6</command> - <properties> - <help>Save traffic dump from an interface to a file</help> - </properties> - <children> - <tagNode name="filter"> - <command>tcpdump -n -i $4 -w $6 $8</command> - <properties> - <help>Save a dump of traffic matching filter conditions to a file</help> - </properties> - </tagNode> - </children> - </tagNode> - </children> - </tagNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/op-mode-definitions/version.xml b/op-mode-definitions/version.xml deleted file mode 100644 index 593785f..0000000 --- a/op-mode-definitions/version.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="show"> - <children> - <node name="version"> - <properties> - <help>Show system version information</help> - </properties> - <command>${vyos_op_scripts_dir}/version.py</command> - <children> - <leafNode name="funny"> - <properties> - <help>Show system version and some fun stuff</help> - </properties> - <command>${vyos_op_scripts_dir}/version.py --funny</command> - </leafNode> - <leafNode name="all"> - <properties> - <help>Show system version and versions of all packages</help> - </properties> - <command>${vyos_op_scripts_dir}/version.py --all</command> - </leafNode> - </children> - </node> - </children> - </node> -</interfaceDefinition> diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 304ea5c..0000000 --- a/python/setup.py +++ /dev/null @@ -1,21 +0,0 @@ -import os -from setuptools import setup - -setup( - name = "vyos", - version = "1.2.0", - author = "VyOS maintainers and contributors", - author_email = "maintainers@vyos.net", - description = ("VyOS configuration libraries."), - license = "LGPLv2+", - keywords = "vyos", - url = "http://www.vyos.io", - packages=['vyos'], - long_description="VyOS configuration libraries", - classifiers=[ - "Development Status :: 4 - Beta", - "Topic :: Utilities", - "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", - ], -) - diff --git a/python/vyos/__init__.py b/python/vyos/__init__.py deleted file mode 100644 index 9b5ed21..0000000 --- a/python/vyos/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .base import * diff --git a/python/vyos/base.py b/python/vyos/base.py deleted file mode 100644 index 4e23714..0000000 --- a/python/vyos/base.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - - -class ConfigError(Exception): - pass diff --git a/python/vyos/config.py b/python/vyos/config.py deleted file mode 100644 index 5af8304..0000000 --- a/python/vyos/config.py +++ /dev/null @@ -1,416 +0,0 @@ -# Copyright 2017 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -""" -A library for reading VyOS running config data. - -This library is used internally by all config scripts of VyOS, -but its API should be considered stable and it is safe to use -in user scripts. - -Note that this module will not work outside VyOS. - -Node taxonomy -############# - -There are multiple types of config tree nodes in VyOS, each requires -its own set of operations. - -*Leaf nodes* (such as "address" in interfaces) can have values, but cannot -have children. -Leaf nodes can have one value, multiple values, or no values at all. - -For example, "system host-name" is a single-value leaf node, -"system name-server" is a multi-value leaf node (commonly abbreviated "multi node"), -and "system ip disable-forwarding" is a valueless leaf node. - -Non-leaf nodes cannot have values, but they can have child nodes. They are divided into -two classes depending on whether the names of their children are fixed or not. -For example, under "system", the names of all valid child nodes are predefined -("login", "name-server" etc.). - -To the contrary, children of the "system task-scheduler task" node can have arbitrary names. -Such nodes are called *tag nodes*. This terminology is confusing but we keep using it for lack -of a better word. The knowledge of whether in "task Foo" the "tag" is "task" or "Foo" is lost -in time, luckily, the distinction is irrelevant in practice. - -Configuration modes -################### - -VyOS has two distinct modes: operational mode and configuration mode. When a user logins, -the CLI is in the operational mode. In this mode, only the running (effective) config is accessible for reading. - -When a user enters the "configure" command, a configuration session is setup. Every config session -has its *proposed* config built on top of the current running config. When changes are commited, if commit succeeds, -the proposed config is merged into the running config. - -For this reason, this library has two sets of functions. The base versions, such as ``exists`` or ``return_value`` -are only usable in configuration mode. They take all nodes into account, in both proposed and running configs. -Configuration scripts require access to uncommited changes for obvious reasons. Configuration mode completion helpers -should also use these functions because not having nodes you've just created in completion is annoying. - -However, in operational mode, only the running config is available. Currently, you need to use special functions -for reading it from operational mode scripts, they can be distinguished by the word "effective" in their names. -In the future base versions may be made to detect if they are called from a config session or not. -""" - -import subprocess -import re - - -class VyOSError(Exception): - """ - Raised on config access errors, most commonly if the type of a config tree node - in the system does not match the type of operation. - - """ - pass - - -class Config(object): - """ - The class of config access objects. - - Internally, in the current implementation, this object is *almost* stateless, - the only state it keeps is relative *config path* for convenient access to config - subtrees. - """ - def __init__(self): - self._cli_shell_api = "/bin/cli-shell-api" - self._level = "" - - def _make_command(self, op, path): - args = path.split() - cmd = [self._cli_shell_api, op] + args - return cmd - - def _run(self, cmd): - p = subprocess.Popen(cmd, stdout=subprocess.PIPE) - out = p.stdout.read() - p.wait() - if p.returncode != 0: - raise VyOSError() - else: - return out.decode('ascii') - - def set_level(self, path): - """ - Set the *edit level*, that is, a relative config tree path. - Once set, all operations will be relative to this path, - for example, after ``set_level("system")``, calling - ``exists("name-server")`` is equivalent to calling - ``exists("system name-server"`` without ``set_level``. - - Args: - path (str): relative config path - """ - # Make sure there's always a space between default path (level) - # and path supplied as method argument - # XXX: for small strings in-place concatenation is not a problem - self._level = path + " " - - def get_level(self): - """ - Gets the current edit level. - - Returns: - str: current edit level - """ - return(self._level.strip()) - - def exists(self, path): - """ - Checks if a node with given path exists in the running or proposed config - - Returns: - True if node exists, False otherwise - - Note: - This function cannot be used outside a configuration sessions. - In operational mode scripts, use ``exists_effective``. - """ - try: - self._run(self._make_command('exists', self._level + path)) - return True - except VyOSError: - return False - - def session_changed(self): - """ - Returns: - True if the config session has uncommited changes, False otherwise. - """ - try: - self._run(self._make_command('sessionChanged', '')) - return True - except VyOSError: - return False - - def in_session(self): - """ - Returns: - True if called from a configuration session, False otherwise. - """ - try: - self._run(self._make_command('inSession', '')) - return True - except VyOSError: - return False - - def is_multi(self, path): - """ - Args: - path (str): Configuration tree path - - Returns: - True if a node can have multiple values, False otherwise. - - Note: - It also returns False if node doesn't exist. - """ - try: - self._run(self._make_command('isMulti', self._level + path)) - return True - except VyOSError: - return False - - def is_tag(self, path): - """ - Args: - path (str): Configuration tree path - - Returns: - True if a node is a tag node, False otherwise. - - Note: - It also returns False if node doesn't exist. - """ - try: - self._run(self._make_command('isTag', self._level + path)) - return True - except VyOSError: - return False - - def is_leaf(self, path): - """ - Args: - path (str): Configuration tree path - - Returns: - True if a node is a leaf node, False otherwise. - - Note: - It also returns False if node doesn't exist. - """ - try: - self._run(self._make_command('isLeaf', self._level + path)) - return True - except VyOSError: - return False - - def return_value(self, path, default=None): - """ - Retrieve a value of single-value leaf node in the running or proposed config - - Args: - path (str): Configuration tree path - default (str): Default value to return if node does not exist - - Returns: - str: Node value, if it has any - None: if node is valueless *or* if it doesn't exist - - Raises: - VyOSError: if node is not a single-value leaf node - - Note: - Due to the issue with treatment of valueless nodes by this function, - valueless nodes should be checked with ``exists`` instead. - - This function cannot be used outside a configuration session. - In operational mode scripts, use ``return_effective_value``. - """ - full_path = self._level + path - if self.is_multi(path): - raise VyOSError("Cannot use return_value on multi node: {0}".format(full_path)) - elif not self.is_leaf(path): - raise VyOSError("Cannot use return_value on non-leaf node: {0}".format(full_path)) - else: - try: - out = self._run(self._make_command('returnValue', full_path)) - return out - except VyOSError: - return(default) - - def return_values(self, path, default=[]): - """ - Retrieve all values of a multi-value leaf node in the running or proposed config - - Args: - path (str): Configuration tree path - - Returns: - str list: Node values, if it has any - None: if node does not exist - - Raises: - VyOSError: if node is not a multi-value leaf node - - Note: - This function cannot be used outside a configuration session. - In operational mode scripts, use ``return_effective_values``. - """ - full_path = self._level + path - if not self.is_multi(path): - raise VyOSError("Cannot use return_values on non-multi node: {0}".format(full_path)) - elif not self.is_leaf(path): - raise VyOSError("Cannot use return_values on non-leaf node: {0}".format(full_path)) - else: - try: - out = self._run(self._make_command('returnValues', full_path)) - values = out.split() - return list(map(lambda x: re.sub(r'^\'(.*)\'$', r'\1',x), values)) - except VyOSError: - return(default) - - def list_nodes(self, path, default=[]): - """ - Retrieve names of all children of a tag node in the running or proposed config - - Args: - path (str): Configuration tree path - - Returns: - string list: child node names - - Raises: - VyOSError: if the node is not a tag node - - Note: - There is no way to list all children of a non-tag node in - the current config backend. - - This function cannot be used outside a configuration session. - In operational mode scripts, use ``list_effective_nodes``. - """ - full_path = self._level + path - if self.is_tag(path): - try: - out = self._run(self._make_command('listNodes', full_path)) - values = out.split() - return list(map(lambda x: re.sub(r'^\'(.*)\'$', r'\1',x), values)) - except VyOSError: - return(default) - else: - raise VyOSError("Cannot use list_nodes on a non-tag node: {0}".format(full_path)) - - def exists_effective(self, path): - """ - Check if a node exists in the running (effective) config - - Args: - path (str): Configuration tree path - - Returns: - True if node exists in the running config, False otherwise - - Note: - This function is safe to use in operational mode. In configuration mode, - it ignores uncommited changes. - """ - try: - self._run(self._make_command('existsEffective', self._level + path)) - return True - except VyOSError: - return False - - def return_effective_value(self, path, default=None): - """ - Retrieve a values of a single-value leaf node in a running (effective) config - - Args: - path (str): Configuration tree path - default (str): Default value to return if node does not exist - - Returns: - str: Node value - - Raises: - VyOSError: if node is not a multi-value leaf node - """ - full_path = self._level + path - if self.is_multi(path): - raise VyOSError("Cannot use return_effective_value on multi node: {0}".format(full_path)) - elif not self.is_leaf(path): - raise VyOSError("Cannot use return_effective_value on non-leaf node: {0}".format(full_path)) - else: - try: - out = self._run(self._make_command('returnEffectiveValue', full_path)) - return out - except VyOSError: - return(default) - - def return_effective_values(self, path, default=[]): - """ - Retrieve all values of a multi-value node in a running (effective) config - - Args: - path (str): Configuration tree path - - Returns: - str list: A list of values - - Raises: - VyOSError: if node is not a multi-value leaf node - """ - full_path = self._level + path - if not self.is_multi(path): - raise VyOSError("Cannot use return_effective_values on non-multi node: {0}".format(full_path)) - elif not self.is_leaf(path): - raise VyOSError("Cannot use return_effective_values on non-leaf node: {0}".format(full_path)) - else: - try: - out = self._run(self._make_command('returnEffectiveValues', full_path)) - return out - except VyOSError: - return(default) - - def list_effective_nodes(self, path, default=[]): - """ - Retrieve names of all children of a tag node in the running config - - Args: - path (str): Configuration tree path - - Returns: - str list: child node names - - Raises: - VyOSError: if the node is not a tag node - - Note: - There is no way to list all children of a non-tag node in - the current config backend. - """ - full_path = self._level + path - if self.is_tag(path): - try: - out = self._run(self._make_command('listEffectiveNodes', full_path)) - values = out.split() - return list(map(lambda x: re.sub(r'^\'(.*)\'$', r'\1',x), values)) - except VyOSError: - return(default) - else: - raise VyOSError("Cannot use list_effective_nodes on a non-tag node: {0}".format(full_path)) diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py deleted file mode 100644 index 4b46a1f..0000000 --- a/python/vyos/configtree.py +++ /dev/null @@ -1,261 +0,0 @@ -# configtree -- a standalone VyOS config file manipulation library (Python bindings) -# Copyright (C) 2018 VyOS maintainers and contributors -# -# This library is free software; you can redistribute it and/or modify it under the terms of -# the GNU Lesser General Public License as published by the Free Software Foundation; -# either version 2.1 of the License, or (at your option) any later version. -# -# This library 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along with this library; -# if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import re -import json - -from ctypes import cdll, c_char_p, c_void_p, c_int - - -def strip_comments(s): - """ Split a config string into the config section and the trailing comments """ - INITIAL = 0 - IN_COMMENT = 1 - - i = len(s) - 1 - state = INITIAL - - config_end = 0 - - # Find the first character of the comments section at the end, - # if it exists - while (i >= 0): - c = s[i] - - if (state == INITIAL) and re.match(r'\s', c): - # Ignore whitespace - if (i != 0): - i -= 1 - else: - config_end = 0 - break - elif (state == INITIAL) and (c == '/'): - # A comment begins, or it's a stray slash - try: - if (s[i-1] == '*'): - state = IN_COMMENT - i -= 2 - else: - raise ValueError("Invalid syntax") - except: - raise ValueError("Invalid syntax") - elif (state == INITIAL) and (c == '}'): - # We are not inside a comment, that's the end of the last node - config_end = i + 1 - break - elif (state == IN_COMMENT) and (c == '*'): - # A comment ends here - try: - if (s[i-1] == '/'): - state = INITIAL - i -= 2 - except: - raise ValueError("Invalid syntax") - elif (state == IN_COMMENT) and (c != '*'): - # Ignore everything inside comments, including braces - i -= 1 - else: - raise ValueError("Invalid syntax") - - return (s[0:config_end], s[config_end+1:]) - -def check_path(path): - # Necessary type checking - if not isinstance(path, list): - raise TypeError("Expected a list, got a {}".format(type(path))) - else: - pass - - -class ConfigTreeError(Exception): - pass - - -class ConfigTree(object): - def __init__(self, config_string, libpath='/usr/lib/libvyosconfig.so.0'): - self.__config = None - self.__lib = cdll.LoadLibrary(libpath) - - # Import functions - self.__from_string = self.__lib.from_string - self.__from_string.argtypes = [c_char_p] - self.__from_string.restype = c_void_p - - self.__to_string = self.__lib.to_string - self.__to_string.argtypes = [c_void_p] - self.__to_string.restype = c_char_p - - self.__to_commands = self.__lib.to_commands - self.__to_commands.argtypes = [c_void_p] - self.__to_commands.restype = c_char_p - - self.__set_add_value = self.__lib.set_add_value - self.__set_add_value.argtypes = [c_void_p, c_char_p, c_char_p] - self.__set_add_value.restype = c_int - - self.__delete_value = self.__lib.delete_value - self.__delete_value.argtypes = [c_void_p, c_char_p, c_char_p] - self.__delete_value.restype = c_int - - self.__delete = self.__lib.delete_node - self.__delete.argtypes = [c_void_p, c_char_p] - self.__delete.restype = c_int - - self.__set_replace_value = self.__lib.set_replace_value - self.__set_replace_value.argtypes = [c_void_p, c_char_p, c_char_p] - self.__set_replace_value.restype = c_int - - self.__set_valueless = self.__lib.set_valueless - self.__set_valueless.argtypes = [c_void_p, c_char_p] - self.__set_valueless.restype = c_int - - self.__exists = self.__lib.exists - self.__exists.argtypes = [c_void_p, c_char_p] - self.__exists.restype = c_int - - self.__list_nodes = self.__lib.list_nodes - self.__list_nodes.argtypes = [c_void_p, c_char_p] - self.__list_nodes.restype = c_char_p - - self.__return_value = self.__lib.return_value - self.__return_value.argtypes = [c_void_p, c_char_p] - self.__return_value.restype = c_char_p - - self.__return_values = self.__lib.return_values - self.__return_values.argtypes = [c_void_p, c_char_p] - self.__return_values.restype = c_char_p - - self.__is_tag = self.__lib.is_tag - self.__is_tag.argtypes = [c_void_p, c_char_p] - self.__is_tag.restype = c_int - - self.__set_tag = self.__lib.set_tag - self.__set_tag.argtypes = [c_void_p, c_char_p] - self.__set_tag.restype = c_int - - self.__destroy = self.__lib.destroy - self.__destroy.argtypes = [c_void_p] - - config_section, comments_section = strip_comments(config_string) - config = self.__from_string(config_section.encode()) - if config is None: - raise ValueError("Parse error") - else: - self.__config = config - self.__comments = comments_section - def __del__(self): - if self.__config is not None: - self.__destroy(self.__config) - - def __str__(self): - return self.to_string() - - def to_string(self): - config_string = self.__to_string(self.__config).decode() - config_string = "{0}\n{1}".format(config_string, self.__comments) - return config_string - - def to_commands(self): - return self.__to_commands(self.__config).decode() - - def set(self, path, value=None, replace=True): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - if value is None: - self.__set_valueless(self.__config, path_str) - else: - if replace: - self.__set_replace_value(self.__config, path_str, str(value).encode()) - else: - self.__set_add_value(self.__config, path_str, str(value).encode()) - - def delete(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - self.__delete(self.__config, path_str) - - def delete_value(self, path, value): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - self.__delete_value(self.__config, path_str, value.encode()) - - def exists(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res = self.__exists(self.__config, path_str) - if (res == 0): - return False - else: - return True - - def list_nodes(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res_json = self.__list_nodes(self.__config, path_str).decode() - res = json.loads(res_json) - - if res is None: - raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) - else: - return res - - def return_value(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res_json = self.__return_value(self.__config, path_str).decode() - res = json.loads(res_json) - - if res is None: - raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) - else: - return res - - def return_values(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res_json = self.__return_values(self.__config, path_str).decode() - res = json.loads(res_json) - - if res is None: - raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) - else: - return res - - def is_tag(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res = self.__is_tag(self.__config, path_str) - if (res >= 1): - return True - else: - return False - - def set_tag(self, path): - check_path(path) - path_str = " ".join(map(str, path)).encode() - - res = self.__set_tag(self.__config, path_str) - if (res == 0): - return True - else: - raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) - diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py deleted file mode 100644 index ac831c1..0000000 --- a/python/vyos/defaults.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - - -directories = { - "data": "/usr/share/vyos/" -} diff --git a/python/vyos/interfaces.py b/python/vyos/interfaces.py deleted file mode 100644 index 2e8ee4f..0000000 --- a/python/vyos/interfaces.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -import re -import json - -import netifaces - - -intf_type_data_file = '/usr/share/vyos/interface-types.json' - -def list_interfaces(): - interfaces = netifaces.interfaces() - - # Remove "fake" interfaces associated with drivers - for i in ["dummy0", "ip6tnl0", "tunl0", "ip_vti0", "ip6_vti0"]: - try: - interfaces.remove(i) - except ValueError: - pass - - return interfaces - -def list_interfaces_of_type(typ): - with open(intf_type_data_file, 'r') as f: - types_data = json.load(f) - - all_intfs = list_interfaces() - if not (typ in types_data.keys()): - raise ValueError("Unknown interface type: {0}".format(typ)) - else: - r = re.compile('^{0}\d+'.format(types_data[typ])) - return list(filter(lambda i: re.match(r, i), all_intfs)) diff --git a/python/vyos/limericks.py b/python/vyos/limericks.py deleted file mode 100644 index 97bb5ae..0000000 --- a/python/vyos/limericks.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2015, 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -import random - -limericks = [ - -""" -A programmer who's name was Searle -Once wrote a long program in Perl. -Despite very few quirks -No one got how it works, -Not even the interpreter. -""", - -""" -There was a young lady of Maine -Who set up IPsec VPN. -Problems didn't arise -'til other vendors' device -had to add she to that VPN. -""", - -""" -One day a programmer from York -started his own Vyatta fork. -Though he was a huge geek, -it still took him a week -to get the damn build scripts to work. -""", - -""" -A network admin from Hong Kong -knew MPPE cipher's not strong. -But he was behind NAT, -so he put up we that, -sad network admin from Hong Kong. -""", - -""" -A network admin named Drake -greeted friends with a three-way handshake -and refused to proceed -if they didn't complete it, -that standards-compliant guy Drake. -""" - -] - - -def get_random(): - return limericks[random.randint(0, len(limericks) - 1)] diff --git a/python/vyos/util.py b/python/vyos/util.py deleted file mode 100644 index 8b3de79..0000000 --- a/python/vyos/util.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -import re - - -def colon_separated_to_dict(data_string, uniquekeys=False): - """ Converts a string containing newline-separated entries - of colon-separated key-value pairs into a dict. - - Such files are common in Linux /proc filesystem - - Args: - data_string (str): data string - uniquekeys (bool): whether to insist that keys are unique or not - - Returns: dict - - Raises: - ValueError: if uniquekeys=True and the data string has - duplicate keys. - - Note: - If uniquekeys=True, then dict entries are always strings, - otherwise they are always lists of strings. - """ - key_value_re = re.compile('([^:]+)\s*\:\s*(.*)') - - data_raw = re.split('\n', data_string) - - data = {} - - for l in data_raw: - l = l.strip() - if l: - match = re.match(key_value_re, l) - if match: - key = match.groups()[0].strip() - value = match.groups()[1].strip() - if key in data.keys(): - if uniquekeys: - raise ValueError("Data string has duplicate keys: {0}".format(key)) - else: - data[key].append(value) - else: - if uniquekeys: - data[key] = value - else: - data[key] = [value] - else: - pass - - return data diff --git a/python/vyos/version.py b/python/vyos/version.py deleted file mode 100644 index 383efbc..0000000 --- a/python/vyos/version.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2017 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. - -""" -VyOS version data access library. - -VyOS stores its version data, which include the version number and some -additional information in a JSON file. This module provides a convenient -interface to reading it. - -Example of the version data dict:: - { - 'built_by': 'autobuild@vyos.net', - 'build_id': '021ac2ee-cd07-448b-9991-9c68d878cddd', - 'version': '1.2.0-rolling+201806200337', - 'built_on': 'Wed 20 Jun 2018 03:37 UTC' - } -""" - -import os -import json - -import vyos.defaults - -version_file = os.path.join(vyos.defaults.directories['data'], 'version.json') - -def get_version_data(file=version_file): - """ - Get complete version data - - Args: - file (str): path to the version file - - Returns: - dict: version data - - The optional ``file`` argument comes in handy in upgrade scripts - that need to retrieve information from images other than the running image. - It should not be used on a running system since the location of that file - is an implementation detail and may change in the future, while the interface - of this module will stay the same. - """ - with open(file, 'r') as f: - version_data = json.load(f) - return version_data - -def get_version(file=None): - """ - Get the version number - """ - version_data = None - if file: - version_data = get_version_data(file=file) - else: - version_data = get_version_data() - return version_data["version"] diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index 1258da8..0000000 --- a/sonar-project.properties +++ /dev/null @@ -1,21 +0,0 @@ -sonar.projectKey=vyos:vyos-1x -sonar.projectName=vyos-1x -sonar.projectVersion=1.2.0 -sonar.organization=vyos - -sonar.sources=src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators -sonar.language=py -sonar.sourceEncoding=UTF-8 - -sonar.links.homepage=https://github.com/vyos/vyos-1x -sonar.links.ci=https://ci.vyos.net/job/vyos-1x/ -sonar.links.scm=https://github.com/vyos/vyos-1x -sonar.links.issue=https://phabricator.vyos.net/ - -sonar.host.url=https://sonarcloud.io - -sonar.python.pylint=/usr/local/bin/pylint -sonar.python.pylint_config=.pylintrc -sonar.python.pylint.reportPath=pylint-report.txt -sonar.python.xunit.reportPath=nosetests.xml -sonar.python.coverage.reportPath=coverage.xml diff --git a/sphinx/Makefile b/sphinx/Makefile deleted file mode 100644 index 1e34463..0000000 --- a/sphinx/Makefile +++ /dev/null @@ -1,177 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/VyOS.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/VyOS.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/VyOS" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/VyOS" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/sphinx/source/conf.py b/sphinx/source/conf.py deleted file mode 100644 index 3447259..0000000 --- a/sphinx/source/conf.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# VyOS documentation build configuration file, created by -# sphinx-quickstart on Wed Jun 20 01:14:27 2018. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'VyOS' -copyright = '2018, VyOS maintainers and contributors' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.2.0' -# The full version, including alpha/beta/rc tags. -release = '1.2.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'VyOSdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'VyOS.tex', 'VyOS Documentation', - 'VyOS maintainers and contributors', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'vyos', 'VyOS Documentation', - ['VyOS maintainers and contributors'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'VyOS', 'VyOS Documentation', - 'VyOS maintainers and contributors', 'VyOS', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False diff --git a/sphinx/source/index.rst b/sphinx/source/index.rst deleted file mode 100644 index c31cac4..0000000 --- a/sphinx/source/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. VyOS documentation master file, created by - sphinx-quickstart on Wed Jun 20 01:14:27 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to VyOS's documentation! -================================ - -Contents: - -.. toctree:: - :maxdepth: 2 - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/src/completion/list_disks.sh b/src/completion/list_disks.sh deleted file mode 100755 index f32e558..0000000 --- a/src/completion/list_disks.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -# Completion script used by show disks to collect physical disk - -awk 'NR > 2 && $4 !~ /[0-9]$/ { print $4 }' </proc/partitions diff --git a/src/completion/list_dumpable_interfaces.py b/src/completion/list_dumpable_interfaces.py deleted file mode 100755 index 53ee896..0000000 --- a/src/completion/list_dumpable_interfaces.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -# Extract the list of interfaces available for traffic dumps from tcpdump -D - -import re -import subprocess - -if __name__ == '__main__': - out = subprocess.check_output(['/usr/sbin/tcpdump', '-D']).decode().strip() - out = out.split("\n") - - intfs = " ".join(map(lambda s: re.search(r'\d+\.(\S+)\s', s).group(1), out)) - - print(intfs) diff --git a/src/completion/list_interfaces.py b/src/completion/list_interfaces.py deleted file mode 100755 index a4968c5..0000000 --- a/src/completion/list_interfaces.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import argparse - -import vyos.interfaces - - -parser = argparse.ArgumentParser() -group = parser.add_mutually_exclusive_group() -group.add_argument("-t", "--type", type=str, help="List interfaces of specific type") -group.add_argument("-b", "--broadcast", action="store_true", help="List all broadcast interfaces") - -args = parser.parse_args() - -if args.type: - try: - interfaces = vyos.interfaces.list_interfaces_of_type(args.type) - - except ValueError as e: - print(e, file=sys.stderr) - print("") -elif args.broadcast: - eth = vyos.interfaces.list_interfaces_of_type("ethernet") - bridge = vyos.interfaces.list_interfaces_of_type("bridge") - bond = vyos.interfaces.list_interfaces_of_type("bonding") - interfaces = eth + bridge + bond -else: - interfaces = vyos.interfaces.list_interfaces() - -print(" ".join(interfaces)) diff --git a/src/completion/list_raidset.sh b/src/completion/list_raidset.sh deleted file mode 100755 index 9ff3523..0000000 --- a/src/completion/list_raidset.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -echo -n `cat /proc/partitions | grep md | awk '{ print $4 }'` diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py deleted file mode 100755 index 95f6215..0000000 --- a/src/conf_mode/bcast_relay.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 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 fnmatch -import subprocess - -from vyos.config import Config -from vyos import ConfigError - -config_file = r'/etc/default/udp-broadcast-relay' - -def get_config(): - conf = Config() - conf.set_level("service broadcast-relay id") - relay_id = conf.list_nodes("") - relays = [] - - for id in relay_id: - interface_list = [] - address = conf.return_value("{0} address".format(id)) - description = conf.return_value("{0} description".format(id)) - port = conf.return_value("{0} port".format(id)) - - # split the interface name listing and form a list - if conf.exists("{0} interface".format(id)): - intfs_names = [] - intfs_names = conf.return_values("{0} interface".format(id)) - - for name in intfs_names: - interface_list.append(name) - - relay = { - "id": id, - "address": address, - "description": description, - "interfaces" : interface_list, - "port": port - } - relays.append(relay) - - return relays - -def verify(relays): - for relay in relays: - if not relay["port"]: - raise ConfigError("UDP broadcast relay 'id {0}' requires a port number".format(relay["id"])) - - if len(relay["interfaces"]) < 2: - raise ConfigError("UDP broadcast relay 'id {0}' requires at least 2 interfaces".format(relay["id"])) - - return None - -def generate(relays): - config_header = '### Autogenerated by bcast_relay.py ###\n' - - config_dir = os.path.dirname(config_file) - config_filename = os.path.basename(config_file) - active_configs = [] - - for config in fnmatch.filter(os.listdir(config_dir), config_filename + '*'): - # determine prefix length to identify service instance - prefix_len = len(config_filename) - active_configs.append(config[prefix_len:]) - - # sort our list - active_configs.sort() - - for id in active_configs[:]: - os.unlink(config_file + id) - - for relay in relays: - file = config_file + str(relay["id"]) - interfaces = ' '.join(str(intf) for intf in relay["interfaces"]) - config_args = 'DAEMON_ARGS="{0} {1}"\n'.format(relay["port"], interfaces) - - f = open(file, 'w') - f.write(config_header) - if relay["description"]: - f.write('# ' + relay["description"] + '\n') - f.write(config_args) - f.close() - - return None - -def apply(relays): - # first stop all running services - cmd = "sudo systemctl stop udp-broadcast-relay@{1..99}" - os.system(cmd) - - # start only required service instances - for relay in relays: - cmd = "sudo systemctl start udp-broadcast-relay@{0}".format(relay["id"]) - os.system(cmd) - - 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/beep_if_fully_booted.py b/src/conf_mode/beep_if_fully_booted.py deleted file mode 100755 index f00fcab..0000000 --- a/src/conf_mode/beep_if_fully_booted.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/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 - -from vyos.config import Config -from vyos import ConfigError - -def get_config(): - conf = Config() - if not conf.exists('system options beep-if-fully-booted'): - return None - - return True - -def apply(status): - if status is not None: - os.system('/usr/bin/beep -f 130 -l 100 -n -f 262 -l 100 -n -f 330 -l 100 -n -f 392 -l 100 -n -f 523 -l 100 -n -f 660 -l 100 -n -f 784 -l 300 -n -f 660 -l 300') - -if __name__ == '__main__': - try: - c = get_config() - apply(c) - except ConfigError as e: - print(e) - sys.exit(1) diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py deleted file mode 100755 index d28e8ff..0000000 --- a/src/conf_mode/dns_forwarding.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/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 netifaces -import jinja2 - -from vyos.config import Config -from vyos import ConfigError - -config_file = r'/etc/powerdns/recursor.conf' - -# XXX: pdns recursor doesn't like whitespace near entry separators, -# especially in the semicolon-separated lists of name servers. -# Please be careful if you edit the template. -config_tmpl = """ -### Autogenerated by dns_forwarding.py ### - -# Non-configurable defaults -daemon=yes -threads=1 -allow-from=0.0.0.0/0 -log-common-errors=yes -non-local-bind=yes - -# cache-size -max-cache-entries={{ cache_size }} - -# negative TTL for NXDOMAIN -max-negative-ttl={{ negative_ttl }} - -# ignore-hosts-file -export-etc-hosts={{ export_hosts_file }} - -# listen-on -local-address={{ listen_on | join(',') }} - -# domain ... server ... -{% if domains -%} - -forward-zones={% for d in domains %} -{{ d.name }}={{ d.servers | join(";") }} -{{- "," if not loop.last -}} -{% endfor %} - -{% endif %} - -# name-server -forward-zones-recurse=.={{ name_servers | join(';') }} - -""" - -default_config_data = { - 'cache_size': 10000, - 'export_hosts_file': 'yes', - 'listen_on': [], - 'interfaces': [], - 'name_servers': [], - 'negative_ttl': 3600, - 'domains': [] -} - - -# borrowed from: https://github.com/donjajo/py-world/blob/master/resolvconfReader.py, THX! -def get_resolvers(file): - resolvers = [] - try: - with open(file, 'r') as resolvconf: - for line in resolvconf.readlines(): - line = line.split('#',1)[0]; - line = line.rstrip(); - if 'nameserver' in line: - resolvers.append(line.split()[1]) - return resolvers - except IOError: - return [] - -def get_config(): - dns = default_config_data - conf = Config() - if not conf.exists('service dns forwarding'): - return None - else: - conf.set_level('service dns forwarding') - - if conf.exists('cache-size'): - cache_size = conf.return_value('cache-size') - dns['cache_size'] = cache_size - - if conf.exists('negative-ttl'): - negative_ttl = conf.return_value('negative-ttl') - dns['negative_ttl'] = negative_ttl - - if conf.exists('domain'): - for node in conf.list_nodes('domain'): - server = conf.return_values("domain {0} server".format(node)) - domain = { - "name": node, - "servers": server - } - dns['domains'].append(domain) - - if conf.exists('ignore-hosts-file'): - dns['export_hosts_file'] = "no" - - if conf.exists('name-server'): - name_servers = conf.return_values('name-server') - dns['name_servers'] = dns['name_servers'] + name_servers - - if conf.exists('system'): - conf.set_level('system') - system_name_servers = [] - system_name_servers = conf.return_values('name-server') - if not system_name_servers: - print("DNS forwarding warning: No name-servers set under 'system name-server'\n") - else: - dns['name_servers'] = dns['name_servers'] + system_name_servers - conf.set_level('service dns forwarding') - - if conf.exists('listen-address'): - dns['listen_on'] = conf.return_values('listen-address') - - ## Hacks and tricks - - # The old VyOS syntax that comes from dnsmasq was "listen-on $interface". - # pdns wants addresses instead, so we emulate it by looking up all addresses - # of a given interface and writing them to the config - if conf.exists('listen-on'): - print("WARNING: since VyOS 1.2.0, \"service dns forwarding listen-on\" is a limited compatibility option.") - print("It will only make DNS forwarder listen on addresses assigned to the interface at the time of commit") - print("which means it will NOT work properly with VRRP/clustering or addresses received from DHCP.") - print("Please reconfigure your system with \"service dns forwarding listen-address\" instead.") - - interfaces = conf.return_values('listen-on') - - listen4 = [] - listen6 = [] - for interface in interfaces: - try: - addrs = netifaces.ifaddresses(interface) - except ValueError: - print("WARNING: interface {0} does not exist".format(interface)) - continue - - if netifaces.AF_INET in addrs.keys(): - for ip4 in addrs[netifaces.AF_INET]: - listen4.append(ip4['addr']) - - if netifaces.AF_INET6 in addrs.keys(): - for ip6 in addrs[netifaces.AF_INET6]: - listen6.append(ip6['addr']) - - if (not listen4) and (not (listen6)): - print("WARNING: interface {0} has no configured addresses".format(interface)) - - dns['listen_on'] = dns['listen_on'] + listen4 + listen6 - - # Save interfaces in the dict for the reference - dns['interfaces'] = interfaces - - # Add name servers received from DHCP - if conf.exists('dhcp'): - interfaces = [] - interfaces = conf.return_values('dhcp') - for interface in interfaces: - dhcp_resolvers = get_resolvers("/etc/resolv.conf.dhclient-new-{0}".format(interface)) - if dhcp_resolvers: - dns['name_servers'] = dns['name_servers'] + dhcp_resolvers - - return dns - -def verify(dns): - # bail out early - looks like removal from running config - if dns is None: - return None - - if not dns['listen_on']: - raise ConfigError("Error: DNS forwarding requires either a listen-address (preferred) or a listen-on option") - - if dns['domains']: - for domain in dns['domains']: - if not domain['servers']: - raise ConfigError('Error: No server configured for domain {0}'.format(domain['name'])) - - return None - -def generate(dns): - # bail out early - looks like removal from running config - if dns is None: - return None - - tmpl = jinja2.Template(config_tmpl, trim_blocks=True) - - config_text = tmpl.render(dns) - with open(config_file, 'w') as f: - f.write(config_text) - return None - -def apply(dns): - if dns is not None: - os.system("systemctl restart pdns-recursor") - else: - # DNS forwarding is removed in the commit - os.system("systemctl stop pdns-recursor") - 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/host_name.py b/src/conf_mode/host_name.py deleted file mode 100755 index 3b3958f..0000000 --- a/src/conf_mode/host_name.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/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/>. -# -# - -""" -conf-mode script for 'system host-name' and 'system domain-name'. -""" - -import os -import re -import sys -import subprocess - -from vyos.config import Config -from vyos import ConfigError - - -hosts_file = '/etc/hosts' -hostname_regex = re.compile("^[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]$") -local_addr = '127.0.1.1' # NOSONAR - - -def get_config(): - """Get configuration""" - conf = Config() - - hostname = conf.return_value("system host-name") - domain = conf.return_value("system domain-name") - - # No one likes fixups, but we really don't want VyOS fail to boot - # if hostname is not in the config - if not hostname: - hostname = "vyos" - - if domain: - fqdn = "{0}.{1}".format(hostname, domain) - else: - fqdn = hostname - - return {"hostname": hostname, "domain": domain, "fqdn": fqdn} - - -def verify(config): - """Verify configuration""" - # check for invalid host - - # pattern $VAR(@) "^[[:alnum:]][-.[:alnum:]]*[[:alnum:]]$" ; "invalid host name $VAR(@)" - if not hostname_regex.match(config["hostname"]): - raise ConfigError('Invalid host name ' + config["hostname"]) - - # pattern $VAR(@) "^.{1,63}$" ; "invalid host-name length" - length = len(config["hostname"]) - if length < 1 or length > 63: - raise ConfigError( - 'Invalid host-name length, must be less than 63 characters') - - return None - - -def generate(config): - """Generate configuration files""" - # read the hosts file - with open(hosts_file, 'r') as f: - hosts = f.read() - - # get the current hostname - old_hostname = subprocess.check_output(['hostname']).decode().strip() - - # replace the local host line - vyos_host_line_re = re.compile(r"({}\s+{}.*)".format(local_addr, old_hostname)) - vyos_host_line = "{}\t{} # VyOS entry\n".format(local_addr, config["fqdn"]) - if re.search(vyos_host_line_re, hosts): - hosts = re.sub(vyos_host_line_re, vyos_host_line, hosts) - else: - # On boot (or after errors), the /etc/hosts file has no line for vyos hostname, - # so we have to add it - hosts = "{0}\n{1}".format(hosts, vyos_host_line) - - with open(hosts_file, 'w') as f: - f.write(hosts) - - return None - - -def apply(config): - """Apply configuration""" - os.system("hostnamectl set-hostname --static {0}".format(config["fqdn"])) - - # restart services that use the hostname - os.system("systemctl restart rsyslog.service") - - 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/lldp.py b/src/conf_mode/lldp.py deleted file mode 100644 index 27749c8..0000000 --- a/src/conf_mode/lldp.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 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 sys - -from vyos.config import Config -from vyos import ConfigError - - -def get_options(config): - options = {} - config.set_level('service lldp') - options['listen_vlan'] = config.exists('listen-vlan') - - options["addr"] = config.return_value('management-address') - - snmp = config.exists('snmp enable') - options["snmp"] = snmp - if snmp: - config.set_level('') - options["sys_snmp"] = config.exists('service snmp') - config.set_level('service lldp') - - config.set_level('service lldp legacy-protocols') - options["cdp"] = config.exists("cdp") - options["edp"] = config.exists("edp") - options["fdp"] = config.exists("fdp") - options["sonmp"] = config.exists("sonmp") - return options - - -def get_interface_list(config): - config.set_level('service lldp') - intfs_names = config.list_nodes('interface') - if len(intfs_names) < 0: - return 0 - interface_list = [] - for name in intfs_names: - config.set_level("service lldp interface {0}".format(name)) - disable = config.exists('disable') - intf = { - "name": name, - "disable": disable - } - interface_list.append(intf) - return interface_list - - -def get_location_intf(config, name): - path = "service lldp interface {0}".format(name) - config.set_level(path) - if config.exists("location"): - return 0 - config.set_level("{} location".format(path)) - civic_based = {} - elin = None - coordinate_based = {} - - if config.exists('civic-based'): - config.set_level("{} location civic-based".format(path)) - cc = config.return_value("country-code") - civic_based["country_code"] = cc - civic_based["ca_type"] = [] - ca_types_names = config.list_nodes('ca-type') - if ca_types_names: - for ca_types_name in ca_types_names: - config.set_level("{0} location civic-based ca-type {1}".format(path, ca_types_name)) - ca_val = config.return_value('ca-value') - ca_type = { - "name": ca_types_name, - "ca_val": ca_val - } - civic_based["ca_type"].append(ca_type) - - elif config.exists("elin"): - elin = config.return_value("elin") - - elif config.exists("coordinate-based"): - config.set_level("{} location coordinate-based".format(path)) - alt = config.return_value("altitude") - lat = config.return_value("latitude") - long = config.return_value("longitude") - datum = config.return_value("datum") - coordinate_based["altitude"] = alt - coordinate_based["latitude"] = lat - coordinate_based["longitude"] = long - coordinate_based["datum"] = datum - - intf = { - "name": name, - "civic_based": civic_based, - "elin": elin, - "coordinate_based": coordinate_based - - } - return intf - - -def get_location(config): - config.set_level('service lldp') - intfs_names = config.list_nodes('interface') - if len(intfs_names) < 0: - return 0 - if config.exists("disable"): - return 0 - intfs_location = [] - for name in intfs_names: - intf = get_location_intf(config, name) - intfs_location.append(intf) - return intfs_location - - -def get_config(): - conf = Config() - options = get_options(conf) - interface_list = get_interface_list(conf) - location = get_location(conf) - lldp = {"options": options, "interface_list": interface_list, "location": location} - return lldp - - -def verify(lldp): - - # check location - for location in lldp["location"]: - - # check civic-based - if len(location["civic_based"]) > 0: - if len(location["coordinate_based"]) > 0 or location["elin"]: - raise ConfigError("Can only configure 1 location type for interface {0}".format(location["name"])) - - # check country-code - if not location["civic_based"]["country_code"]: - raise ConfigError("Invalid location for interface {0}: must configure the country code".format(location["name"])) - - if not re.match(r"^[a-zA-Z]{2}$", location["civic_based"]["country_code"]): - raise ConfigError("Invalid location for interface {0}: country-code must be 2 characters".format(location["name"])) - # check ca-type - if len(location["civic_based"]["ca_type"]) < 0: - raise ConfigError("Invalid location for interface {0}: must define at least 1 ca-type".format(location["name"])) - - for ca_type in location["civic_based"]["ca_type"]: - if not int(ca_type["name"]) in range(0, 129): - raise ConfigError("Invalid location for interface {0}: ca-type must between 0-128".format(location["name"])) - - if not ca_type["ca_val"]: - raise ConfigError("Invalid location for interface {0}: must configure the ca-value for ca-type {1}".format(location["name"],ca_type["name"])) - - # check coordinate-based - elif len(location["coordinate_based"]) > 0: - # check longitude and latitude - if not location["coordinate_based"]["longitude"]: - raise ConfigError("Must define longitude for interface {0}".format(location["name"])) - - if not location["coordinate_based"]["latitude"]: - raise ConfigError("Must define latitude for interface {0}".format(location["name"])) - - if not re.match(r"^(\d+)(\.\d+)?[nNsS]$", location["coordinate_based"]["latitude"]): - raise ConfigError("Invalid location for interface {0}: latitude should be a number followed by S or N".format(location["name"])) - - if not re.match(r"^(\d+)(\.\d+)?[eEwW]$", location["coordinate_based"]["longitude"]): - raise ConfigError("Invalid location for interface {0}: longitude should be a number followed by E or W".format(location["name"])) - - # check altitude and datum if exist - if location["coordinate_based"]["altitude"]: - if not re.match(r"^[-+0-9\.]+$", location["coordinate_based"]["altitude"]): - raise ConfigError("Invalid location for interface {0}: altitude should be a positive or negative number".format(location["name"])) - - if location["coordinate_based"]["datum"]: - if not re.match(r"^(WGS84|NAD83|MLLW)$", location["coordinate_based"]["datum"]): - raise ConfigError("Invalid location for interface {0}: datum should be WGS84, NAD83, or MLLW".format(location["name"])) - - # check elin - elif len(location["elin"]) > 0: - if not re.match(r"^[0-9]{10,25}$", location["elin"]): - raise ConfigError("Invalid location for interface {0}: ELIN number must be between 10-25 numbers".format(location["name"])) - - # check options - if lldp["options"]["snmp"]: - if not lldp["options"]["sys_snmp"]: - raise ConfigError("SNMP must be configured to enable LLDP SNMP") - - -def generate(config): - pass - - -def apply(config): - pass - -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/mdns_repeater.py b/src/conf_mode/mdns_repeater.py deleted file mode 100755 index 474a6a5..0000000 --- a/src/conf_mode/mdns_repeater.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 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 netifaces - -from vyos.config import Config -from vyos import ConfigError - -config_file = r'/etc/default/mdns-repeater' - -def get_config(): - interface_list = [] - - conf = Config() - conf.set_level('service mdns repeater') - if not conf.exists(''): - return interface_list - - if conf.exists('interface'): - intfs_names = [] - intfs_names = conf.return_values('interface') - - for name in intfs_names: - interface_list.append(name) - - return interface_list - -def verify(mdns): - # '0' interfaces are possible, think of service deletion. Only '1' is not supported! - if len(mdns) == 1: - raise ConfigError('At least 2 interfaces must be specified but %d given!' % len(mdns)) - - # For mdns-repeater to work it is essential that the interfaces - # have an IP address assigned - for intf in mdns: - try: - netifaces.ifaddresses(intf)[netifaces.AF_INET] - except KeyError as e: - raise ConfigError('No IP address configured for interface "%s"!' % intf) - - return None - -def generate(mdns): - config_header = '### Autogenerated by mdns_repeater.py ###\n' - if len(mdns) > 0: - config_args = 'DAEMON_ARGS="' + ' '.join(str(e) for e in mdns) + '"\n' - else: - config_args = 'DAEMON_ARGS=""\n' - - # write new configuration file - f = open(config_file, 'w') - f.write(config_header) - f.write(config_args) - f.close() - - return None - -def apply(mdns): - if len(mdns) == 0: - cmd = "sudo systemctl stop mdns-repeater" - else: - cmd = "sudo systemctl restart mdns-repeater" - - os.system(cmd) - 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/ntp.py b/src/conf_mode/ntp.py deleted file mode 100755 index 2a60885..0000000 --- a/src/conf_mode/ntp.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/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 jinja2 -import ipaddress - -from vyos.config import Config -from vyos import ConfigError - -config_file = r'/etc/ntp.conf' - -# Please be careful if you edit the template. -config_tmpl = """ -### Autogenerated by ntp.py ### - -# -# Non-configurable defaults -# -driftfile /var/lib/ntp/ntp.drift -# By default, only allow ntpd to query time sources, ignore any incoming requests -restrict default ignore -# Local users have unrestricted access, allowing reconfiguration via ntpdc -restrict 127.0.0.1 -restrict -6 ::1 - - -# -# Configurable section -# - -{% if servers -%} -{% for s in servers -%} -# Server configuration for: {{ s.name }} -server {{ s.name }} iburst {{ s.options | join(" ") }} - -{% endfor -%} -{% endif %} - -{% if allowed_networks -%} -{% for n in allowed_networks -%} -# Client configuration for network: {{ n.network }} -restrict {{ n.address }} mask {{ n.netmask }} nomodify notrap nopeer - -{% endfor -%} -{% endif %} - -{% if listen_address -%} -# NTP should listen on configured addresses only -interface ignore wildcard -{% for a in listen_address -%} -interface listen {{ a }} -{% endfor -%} -{% endif %} - -""" - -default_config_data = { - 'servers': [], - 'allowed_networks': [], - 'listen_address': [] -} - -def get_config(): - ntp = default_config_data - conf = Config() - if not conf.exists('system ntp'): - return None - else: - conf.set_level('system ntp') - - if conf.exists('allow-clients address'): - networks = conf.return_values('allow-clients address') - for n in networks: - addr = ipaddress.ip_network(n) - net = { - "network" : n, - "address" : addr.network_address, - "netmask" : addr.netmask - } - - ntp['allowed_networks'].append(net) - - if conf.exists('listen-address'): - ntp['listen_address'] = conf.return_values('listen-address') - - if conf.exists('server'): - for node in conf.list_nodes('server'): - options = [] - server = { - "name": node, - "options": [] - } - if conf.exists('server {0} dynamic'.format(node)): - options.append('dynamic') - if conf.exists('server {0} noselect'.format(node)): - options.append('noselect') - if conf.exists('server {0} preempt'.format(node)): - options.append('preempt') - if conf.exists('server {0} prefer'.format(node)): - options.append('prefer') - - server['options'] = options - ntp['servers'].append(server) - - return ntp - -def verify(ntp): - # bail out early - looks like removal from running config - if ntp is None: - return None - - # Configuring allowed clients without a server makes no sense - if len(ntp['allowed_networks']) and not len(ntp['servers']): - raise ConfigError('NTP server not configured') - - for n in ntp['allowed_networks']: - try: - addr = ipaddress.ip_network( n['network'] ) - break - except ValueError: - raise ConfigError("{0} does not appear to be a valid IPv4 or IPv6 network, check host bits!".format(n['network'])) - - return None - -def generate(ntp): - # bail out early - looks like removal from running config - if ntp is None: - return None - - tmpl = jinja2.Template(config_tmpl) - config_text = tmpl.render(ntp) - with open(config_file, 'w') as f: - f.write(config_text) - - return None - -def apply(ntp): - if ntp is not None: - os.system('sudo /usr/sbin/invoke-rc.d ntp force-reload') - else: - # NTP suuport is removed in the commit - os.system('sudo /usr/sbin/invoke-rc.d ntp stop') - 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/snmp.py b/src/conf_mode/snmp.py deleted file mode 100755 index 1590e5d..0000000 --- a/src/conf_mode/snmp.py +++ /dev/null @@ -1,804 +0,0 @@ -#!/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 shutil -import stat -import pwd -import time - -import jinja2 -import ipaddress -import random -import binascii -import re - -import vyos.version - -from vyos.config import Config -from vyos import ConfigError - -config_file_client = r'/etc/snmp/snmp.conf' -config_file_daemon = r'/etc/snmp/snmpd.conf' -config_file_access = r'/usr/share/snmp/snmpd.conf' -config_file_user = r'/var/lib/snmp/snmpd.conf' - -# SNMP OIDs used to mark auth/priv type -OIDs = { - 'md5' : '.1.3.6.1.6.3.10.1.1.2', - 'sha' : '.1.3.6.1.6.3.10.1.1.3', - 'aes' : '.1.3.6.1.6.3.10.1.2.4', - 'des' : '.1.3.6.1.6.3.10.1.2.2', - 'none': '.1.3.6.1.6.3.10.1.2.1' -} -# SNMPS template - be careful if you edit the template. -client_config_tmpl = """ -### Autogenerated by snmp.py ### -{% if trap_source -%} -clientaddr {{ trap_source }} -{% endif %} - -""" - -# SNMPS template - be careful if you edit the template. -access_config_tmpl = """ -### Autogenerated by snmp.py ### -{% if v3_users %} -{% for u in v3_users %} -{{ u.mode }}user {{ u.name }} -{% endfor %} -{% endif -%} -rwuser {{ vyos_user }} - -""" - -# SNMPS template - be careful if you edit the template. -user_config_tmpl = """ -### Autogenerated by snmp.py ### -# user -{% if v3_users %} -{% for u in v3_users %} -{% if u.authOID == 'none' %} -createUser {{ u.name }} -{% elif u.authPassword %} -createUser {{ u.name }} {{ u.authProtocol | upper }} "{{ u.authPassword }}" {{ u.privProtocol | upper }} {{ u.privPassword }} -{% else %} -usmUser 1 3 {{ u.engineID }} "{{ u.name }}" "{{ u.name }}" NULL {{ u.authOID }} {{ u.authMasterKey }} {{ u.privOID }} {{ u.privMasterKey }} 0x -{% endif %} -{% endfor %} -{% endif %} - -createUser {{ vyos_user }} MD5 "{{ vyos_user_pass }}" DES -""" - -# SNMPS template - be careful if you edit the template. -daemon_config_tmpl = """ -### Autogenerated by snmp.py ### - -# non configurable defaults -sysObjectID 1.3.6.1.4.1.44641 -sysServices 14 -master agentx -agentXPerms 0755 0755 -pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias -smuxpeer .1.3.6.1.2.1.83 -smuxpeer .1.3.6.1.2.1.157 -smuxpeer .1.3.6.1.4.1.3317.1.2.2 -smuxpeer .1.3.6.1.4.1.3317.1.2.3 -smuxpeer .1.3.6.1.4.1.3317.1.2.5 -smuxpeer .1.3.6.1.4.1.3317.1.2.8 -smuxpeer .1.3.6.1.4.1.3317.1.2.9 -smuxsocket localhost - -# linkUp/Down configure the Event MIB tables to monitor -# the ifTable for network interfaces being taken up or down -# for making internal queries to retrieve any necessary information -iquerySecName {{ vyos_user }} - -# Modified from the default linkUpDownNotification -# to include more OIDs and poll more frequently -notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus -notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus -monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2 -monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2 - -######################## -# configurable section # -######################## - -{% if v3_tsm_key %} -[snmp] localCert {{ v3_tsm_key }} -{% endif %} - -# Default system description is VyOS version -sysDescr VyOS {{ version }} - -{% if description -%} -# Description -SysDescr {{ description }} -{% endif %} - -# Listen -agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},udp:161,udp6:161{% endif %}{% if v3_tsm_key %},tlstcp:{{ v3_tsm_port }},dtlsudp::{{ v3_tsm_port }}{% endif %} - - -# SNMP communities -{% if communities -%} -{% for c in communities %} -{% if c.network -%} -{% for network in c.network %} -{{ c.authorization }}community {{ c.name }} {{ network }} -{% endfor %} -{% else %} -{{ c.authorization }}community {{ c.name }} -{% endif %} -{% endfor %} -{% endif %} - -{% if contact -%} -# system contact information -SysContact {{ contact }} -{% endif %} - -{% if location -%} -# system location information -SysLocation {{ location }} -{% endif %} - -{% if smux_peers -%} -# additional smux peers -{% for sp in smux_peers %} -smuxpeer {{ sp }} -{% endfor %} -{% endif %} - -{% if trap_targets -%} -# if there is a problem - tell someone! -{% for t in trap_targets %} -trap2sink {{ t.target }}{% if t.port -%}:{{ t.port }}{% endif %} {{ t.community }} -{% endfor %} -{% endif %} - -# -# SNMPv3 stuff goes here -# -{% if v3_enabled %} - -# views -{% if v3_views -%} -{% for v in v3_views %} -{% for oid in v.oids %} -view {{ v.name }} included .{{ oid.oid }} -{% endfor %} -{% endfor %} -{% endif %} - -# access -# context sec.model sec.level match read write notif -{% if v3_groups -%} -{% for g in v3_groups %} -{% if g.mode == 'ro' %} -access {{ g.name }} "" usm {{ g.seclevel }} exact {{ g.view }} none none -access {{ g.name }} "" tsm {{ g.seclevel }} exact {{ g.view }} none none -{% elif g.mode == 'rw' %} -access {{ g.name }} "" usm {{ g.seclevel }} exact {{ g.view }} {{ g.view }} none -access {{ g.name }} "" tsm {{ g.seclevel }} exact {{ g.view }} {{ g.view }} none -{% endif %} -{% endfor -%} -{% endif %} - -# trap-target -{% if v3_traps -%} -{% for t in v3_traps %} -trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ t.engineID }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }} -{% endfor -%} -{% endif %} - -# group -{% if v3_users -%} -{% for u in v3_users %} -group {{ u.group }} usm {{ u.name }} -group {{ u.group }} tsm {{ u.name }} -{% endfor %} -{% endif %} - -{% endif %} - -""" - -default_config_data = { - 'listen_on': [], - 'communities': [], - 'smux_peers': [], - 'location' : '', - 'description' : '', - 'contact' : '', - 'trap_source': '', - 'trap_targets': [], - 'vyos_user': '', - 'vyos_user_pass': '', - 'version': '999', - 'v3_enabled': 'False', - 'v3_engineid': '', - 'v3_groups': [], - 'v3_traps': [], - 'v3_tsm_key': '', - 'v3_tsm_port': '10161', - 'v3_users': [], - 'v3_views': [] -} - -def rmfile(file): - if os.path.isfile(file): - os.unlink(file) - -def get_config(): - snmp = default_config_data - conf = Config() - if not conf.exists('service snmp'): - return None - else: - conf.set_level('service snmp') - - version_data = vyos.version.get_version_data() - snmp['version'] = version_data['version'] - - # create an internal snmpv3 user of the form 'vyattaxxxxxxxxxxxxxxxx' - # os.urandom(8) returns 8 bytes of random data - snmp['vyos_user'] = 'vyatta' + binascii.hexlify(os.urandom(8)).decode('utf-8') - snmp['vyos_user_pass'] = binascii.hexlify(os.urandom(16)).decode('utf-8') - - if conf.exists('community'): - for name in conf.list_nodes('community'): - community = { - 'name': name, - 'authorization': 'ro', - 'network': [] - } - - if conf.exists('community {0} authorization'.format(name)): - community['authorization'] = conf.return_value('community {0} authorization'.format(name)) - - if conf.exists('community {0} network'.format(name)): - community['network'] = conf.return_values('community {0} network'.format(name)) - - snmp['communities'].append(community) - - if conf.exists('contact'): - snmp['contact'] = conf.return_value('contact') - - if conf.exists('description'): - snmp['description'] = conf.return_value('description') - - if conf.exists('listen-address'): - for addr in conf.list_nodes('listen-address'): - listen = '' - port = '161' - if conf.exists('listen-address {0} port'.format(addr)): - port = conf.return_value('listen-address {0} port'.format(addr)) - - if ipaddress.ip_address(addr).version == 4: - # udp:127.0.0.1:161 - listen = 'udp:' + addr + ':' + port - elif ipaddress.ip_address(addr).version == 6: - # udp6:[::1]:161 - listen = 'udp6:' + '[' + addr + ']' + ':' + port - else: - raise ConfigError('Invalid IP address version') - - snmp['listen_on'].append(listen) - - if conf.exists('location'): - snmp['location'] = conf.return_value('location') - - if conf.exists('smux-peer'): - snmp['smux_peers'] = conf.return_values('smux-peer') - - if conf.exists('trap-source'): - snmp['trap_source'] = conf.return_value('trap-source') - - if conf.exists('trap-target'): - for target in conf.list_nodes('trap-target'): - trap_tgt = { - 'target': target, - 'community': '', - 'port': '' - } - - if conf.exists('trap-target {0} community'.format(target)): - trap_tgt['community'] = conf.return_value('trap-target {0} community'.format(target)) - - if conf.exists('trap-target {0} port'.format(target)): - trap_tgt['port'] = conf.return_value('trap-target {0} port'.format(target)) - - snmp['trap_targets'].append(trap_tgt) - - ######################################################################### - # ____ _ _ __ __ ____ _____ # - # / ___|| \ | | \/ | _ \ __ _|___ / # - # \___ \| \| | |\/| | |_) | \ \ / / |_ \ # - # ___) | |\ | | | | __/ \ V / ___) | # - # |____/|_| \_|_| |_|_| \_/ |____/ # - # # - # now take care about the fancy SNMP v3 stuff, or bail out eraly # - ######################################################################### - if not conf.exists('v3'): - return snmp - else: - snmp['v3_enabled'] = True - - # - # 'set service snmp v3 engineid' - # - if conf.exists('v3 engineid'): - snmp['v3_engineid'] = conf.return_value('v3 engineid') - - # - # 'set service snmp v3 group' - # - if conf.exists('v3 group'): - for group in conf.list_nodes('v3 group'): - v3_group = { - 'name': group, - 'mode': 'ro', - 'seclevel': 'auth', - 'view': '' - } - - if conf.exists('v3 group {0} mode'.format(group)): - v3_group['mode'] = conf.return_value('v3 group {0} mode'.format(group)) - - if conf.exists('v3 group {0} seclevel'.format(group)): - v3_group['seclevel'] = conf.return_value('v3 group {0} seclevel'.format(group)) - - if conf.exists('v3 group {0} view'.format(group)): - v3_group['view'] = conf.return_value('v3 group {0} view'.format(group)) - - snmp['v3_groups'].append(v3_group) - - # - # 'set service snmp v3 trap-target' - # - if conf.exists('v3 trap-target'): - for trap in conf.list_nodes('v3 trap-target'): - trap_cfg = { - 'ipAddr': trap, - 'engineID': '', - 'secName': '', - 'authProtocol': 'md5', - 'authPassword': '', - 'authMasterKey': '', - 'privProtocol': 'des', - 'privPassword': '', - 'privMasterKey': '', - 'ipProto': 'udp', - 'ipPort': '162', - 'type': '', - 'secLevel': 'noAuthNoPriv' - } - - if conf.exists('v3 trap-target {0} engineid'.format(trap)): - # Set the context engineID used for SNMPv3 REQUEST messages scopedPdu. - # If not specified, this will default to the authoritative engineID. - trap_cfg['engineID'] = conf.return_value('v3 trap-target {0} engineid'.format(trap)) - - if conf.exists('v3 trap-target {0} user'.format(trap)): - # Set the securityName used for authenticated SNMPv3 messages. - trap_cfg['secName'] = conf.return_value('v3 trap-target {0} user'.format(trap)) - - if conf.exists('v3 trap-target {0} auth type'.format(trap)): - # Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages - # cmdline option '-a' - trap_cfg['authProtocol'] = conf.return_value('v3 trap-target {0} auth type'.format(trap)) - - if conf.exists('v3 trap-target {0} auth plaintext-key'.format(trap)): - # Set the authentication pass phrase used for authenticated SNMPv3 messages. - # cmdline option '-A' - trap_cfg['authPassword'] = conf.return_value('v3 trap-target {0} auth plaintext-key'.format(trap)) - - if conf.exists('v3 trap-target {0} auth encrypted-key'.format(trap)): - # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master authentication keys. - # cmdline option '-3m' - trap_cfg['authMasterKey'] = conf.return_value('v3 trap-target {0} auth encrypted-key'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy type'.format(trap)): - # Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages. - # cmdline option '-x' - trap_cfg['privProtocol'] = conf.return_value('v3 trap-target {0} privacy type'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy plaintext-key'.format(trap)): - # Set the privacy pass phrase used for encrypted SNMPv3 messages. - # cmdline option '-X' - trap_cfg['privPassword'] = conf.return_value('v3 trap-target {0} privacy plaintext-key'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy encrypted-key'.format(trap)): - # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master encryption keys. - # cmdline option '-3M' - trap_cfg['privMasterKey'] = conf.return_value('v3 trap-target {0} privacy encrypted-key'.format(trap)) - - if conf.exists('v3 trap-target {0} protocol'.format(trap)): - trap_cfg['ipProto'] = conf.return_value('v3 trap-target {0} protocol'.format(trap)) - - if conf.exists('v3 trap-target {0} port'.format(trap)): - trap_cfg['ipPort'] = conf.return_value('v3 trap-target {0} port'.format(trap)) - - if conf.exists('v3 trap-target {0} type'.format(trap)): - trap_cfg['type'] = conf.return_value('v3 trap-target {0} type'.format(trap)) - - # Determine securityLevel used for SNMPv3 messages (noAuthNoPriv|authNoPriv|authPriv). - # Appropriate pass phrase(s) must provided when using any level higher than noAuthNoPriv. - if trap_cfg['authPassword'] or trap_cfg['authMasterKey']: - if trap_cfg['privProtocol'] or trap_cfg['privPassword']: - trap_cfg['secLevel'] = 'authPriv' - else: - trap_cfg['secLevel'] = 'authNoPriv' - - snmp['v3_traps'].append(trap_cfg) - - # - # 'set service snmp v3 tsm' - # - if conf.exists('v3 tsm'): - if conf.exists('v3 tsm local-key'): - snmp['v3_tsm_key'] = conf.return_value('v3 tsm local-key') - - if conf.exists('v3 tsm port'): - snmp['v3_tsm_port'] = conf.return_value('v3 tsm port') - - # - # 'set service snmp v3 user' - # - if conf.exists('v3 user'): - for user in conf.list_nodes('v3 user'): - user_cfg = { - 'name': user, - 'authMasterKey': '', - 'authPassword': '', - 'authProtocol': '', - 'authOID': 'none', - 'engineID': '', - 'group': '', - 'mode': 'ro', - 'privMasterKey': '', - 'privPassword': '', - 'privOID': '', - 'privTsmKey': '', - 'privProtocol': '' - } - - # - # v3 user {0} auth - # - if conf.exists('v3 user {0} auth encrypted-key'.format(user)): - user_cfg['authMasterKey'] = conf.return_value('v3 user {0} auth encrypted-key'.format(user)) - - if conf.exists('v3 user {0} auth plaintext-key'.format(user)): - user_cfg['authPassword'] = conf.return_value('v3 user {0} auth plaintext-key'.format(user)) - - if conf.exists('v3 user {0} auth type'.format(user)): - type = conf.return_value('v3 user {0} auth type'.format(user)) - user_cfg['authProtocol'] = type - user_cfg['authOID'] = OIDs[type] - - # - # v3 user {0} engineid - # - if conf.exists('v3 user {0} engineid'.format(user)): - user_cfg['engineID'] = conf.return_value('v3 user {0} engineid'.format(user)) - - # - # v3 user {0} group - # - if conf.exists('v3 user {0} group'.format(user)): - user_cfg['group'] = conf.return_value('v3 user {0} group'.format(user)) - - # - # v3 user {0} mode - # - if conf.exists('v3 user {0} mode'.format(user)): - user_cfg['mode'] = conf.return_value('v3 user {0} mode'.format(user)) - - # - # v3 user {0} privacy - # - if conf.exists('v3 user {0} privacy encrypted-key'.format(user)): - user_cfg['privMasterKey'] = conf.return_value('v3 user {0} privacy encrypted-key'.format(user)) - - if conf.exists('v3 user {0} privacy plaintext-key'.format(user)): - user_cfg['privPassword'] = conf.return_value('v3 user {0} privacy plaintext-key'.format(user)) - - if conf.exists('v3 user {0} privacy tsm-key'.format(user)): - user_cfg['privTsmKey'] = conf.return_value('v3 user {0} privacy tsm-key'.format(user)) - - if conf.exists('v3 user {0} privacy type'.format(user)): - type = conf.return_value('v3 user {0} privacy type'.format(user)) - user_cfg['privProtocol'] = type - user_cfg['privOID'] = OIDs[type] - - snmp['v3_users'].append(user_cfg) - - # - # 'set service snmp v3 view' - # - if conf.exists('v3 view'): - for view in conf.list_nodes('v3 view'): - view_cfg = { - 'name': view, - 'oids': [] - } - - if conf.exists('v3 view {0} oid'.format(view)): - for oid in conf.list_nodes('v3 view {0} oid'.format(view)): - oid_cfg = { - 'oid': oid - } - view_cfg['oids'].append(oid_cfg) - snmp['v3_views'].append(view_cfg) - - return snmp - -def verify(snmp): - if snmp is None: - return None - - # bail out early if SNMP v3 is not configured - if not snmp['v3_enabled']: - return None - - tsmKeyPattern = re.compile('^[0-9A-F]{2}(:[0-9A-F]{2}){19}$', re.IGNORECASE) - - if snmp['v3_tsm_key']: - if not tsmKeyPattern.match(snmp['v3_tsm_key']): - if not os.path.isfile('/etc/snmp/tls/certs/' + snmp['v3_tsm_key']): - if not os.path.isfile('/config/snmp/tls/certs/' + snmp['v3_tsm_key']): - raise ConfigError('TSM key must be fingerprint or filename in "/config/snmp/tls/certs/" folder') - - if 'v3_groups' in snmp.keys(): - for group in snmp['v3_groups']: - # - # A view must exist prior to mapping it into a group - # - if 'view' in group.keys(): - error = True - if 'v3_views' in snmp.keys(): - for view in snmp['v3_views']: - if view['name'] == group['view']: - error = False - if error: - raise ConfigError('You must create view "{0}" first'.format(group['view'])) - else: - raise ConfigError('"view" must be specified') - - if not 'mode' in group.keys(): - raise ConfigError('"mode" must be specified') - - if not 'seclevel' in group.keys(): - raise ConfigError('"seclevel" must be specified') - - - if 'v3_traps' in snmp.keys(): - for trap in snmp['v3_traps']: - if trap['authPassword'] and trap['authMasterKey']: - raise ConfigError('Must specify only one of encrypted-key/plaintext-key for trap auth') - - if trap['authPassword'] == '' and trap['authMasterKey'] == '': - raise ConfigError('Must specify encrypted-key or plaintext-key for trap auth') - - if trap['privPassword'] and trap['privMasterKey']: - raise ConfigError('Must specify only one of encrypted-key/plaintext-key for trap privacy') - - if trap['privPassword'] == '' and trap['privMasterKey'] == '': - raise ConfigError('Must specify encrypted-key or plaintext-key for trap privacy') - - if not 'type' in trap.keys(): - raise ConfigError('v3 trap: "type" must be specified') - - if not 'authPassword' and 'authMasterKey' in trap.keys(): - raise ConfigError('v3 trap: "auth" must be specified') - - if not 'authProtocol' in trap.keys(): - raise ConfigError('v3 trap: "protocol" must be specified') - - if not 'privPassword' and 'privMasterKey' in trap.keys(): - raise ConfigError('v3 trap: "user" must be specified') - - if 'type' in trap.keys(): - if trap['type'] == 'trap' and trap['engineID'] == '': - raise ConfigError('must specify engineid if type is "trap"') - else: - raise ConfigError('"type" must be specified') - - - if 'v3_users' in snmp.keys(): - for user in snmp['v3_users']: - # - # Group must exist prior to mapping it into a group - # seclevel will be extracted from group - # - error = True - if user['group']: - if 'v3_groups' in snmp.keys(): - for group in snmp['v3_groups']: - if group['name'] == user['group']: - seclevel = group['seclevel'] - error = False - - if error: - raise ConfigError('You must create group "{0}" first'.format(user['group'])) - - # Depending on the configured security level - # the user has to provide additional info - if seclevel is 'auth' or seclevel is 'priv': - if user['authPassword'] and user['authMasterKey']: - raise ConfigError('Can not mix "encrypted-key" and "plaintext-key" for user auth') - - if user['authPassword'] == '' and user['authMasterKey'] == '': - raise ConfigError('Must specify encrypted-key or plaintext-key for user auth') - - if user['authProtocol'] == '': - raise ConfigError('Must specify auth type') - - # seclevel 'priv' is more restrictive - if seclevel is 'priv': - if user['privPassword'] and user['privMasterKey']: - raise ConfigError('Can not mix "encrypted-key" and "plaintext-key" for user privacy') - - if user['privPassword'] == '' and user['privMasterKey'] == '': - raise ConfigError('Must specify encrypted-key or plaintext-key for user privacy') - - if user['privMasterKey'] and user['engineID'] == '': - raise ConfigError('Can not have "encrypted-key" without engineid') - - if user['authPassword'] == '' and user['authMasterKey'] == '' and user['privTsmKey'] == '': - raise ConfigError('Must specify auth or tsm-key for user auth') - - if user['privProtocol'] == '': - raise ConfigError('Must specify privacy type') - - if user['mode'] == '': - raise ConfigError('Must specify user mode ro/rw') - - if user['privTsmKey']: - if not tsmKeyPattern.match(snmp['v3_tsm_key']): - if not os.path.isfile('/etc/snmp/tls/certs/' + snmp['v3_tsm_key']): - if not os.path.isfile('/config/snmp/tls/certs/' + snmp['v3_tsm_key']): - raise ConfigError('User TSM key must be fingerprint or filename in "/config/snmp/tls/certs/" folder') - - if 'v3_views' in snmp.keys(): - for view in snmp['v3_views']: - if not view['oids']: - raise ConfigError('Must configure an oid') - - return None - -def generate(snmp): - # - # As we are manipulating the snmpd user database we have to stop it first! - # This is even save if service is going to be removed - os.system("sudo systemctl stop snmpd.service") - rmfile(config_file_client) - rmfile(config_file_daemon) - rmfile(config_file_access) - rmfile(config_file_user) - - if snmp is None: - return None - - # Write client config file - tmpl = jinja2.Template(client_config_tmpl, trim_blocks=True) - config_text = tmpl.render(snmp) - with open(config_file_client, 'w') as f: - f.write(config_text) - - # Write server config file - tmpl = jinja2.Template(daemon_config_tmpl, trim_blocks=True) - config_text = tmpl.render(snmp) - with open(config_file_daemon, 'w') as f: - f.write(config_text) - - # Write access rights config file - tmpl = jinja2.Template(access_config_tmpl, trim_blocks=True) - config_text = tmpl.render(snmp) - with open(config_file_access, 'w') as f: - f.write(config_text) - - # Write access rights config file - tmpl = jinja2.Template(user_config_tmpl, trim_blocks=True) - config_text = tmpl.render(snmp) - with open(config_file_user, 'w') as f: - f.write(config_text) - - return None - -def apply(snmp): - if snmp is not None: - - nonvolatiledir = '/config/snmp/tls' - volatiledir = '/etc/snmp/tls' - if not os.path.exists(nonvolatiledir): - os.makedirs(nonvolatiledir) - os.chmod(nonvolatiledir, stat.S_IWUSR | stat.S_IRUSR) - # get uid for user 'snmp' - snmp_uid = pwd.getpwnam('snmp').pw_uid - os.chown(nonvolatiledir, snmp_uid, -1) - - # move SNMP certificate files from volatile location to non volatile /config/snmp - if os.path.exists(volatiledir) and os.path.isdir(volatiledir): - files = os.listdir(volatiledir) - for f in files: - shutil.move(volatiledir + '/' + f, nonvolatiledir) - os.chmod(nonvolatiledir + '/' + f, stat.S_IWUSR | stat.S_IRUSR) - - os.rmdir(volatiledir) - os.symlink(nonvolatiledir, volatiledir) - - if os.path.islink(volatiledir): - link = os.readlink(volatiledir) - if link != nonvolatiledir: - os.unlink(volatiledir) - os.symlink(nonvolatiledir, volatiledir) - - # start SNMP daemon - os.system("sudo systemctl restart snmpd.service") - - # the passwords are not available immediately so this is a workaround - # and should be changed to polling - time.sleep(2) - - # Back in the Perl days the configuration was re-read and any - # plaintext password inside the configuration was replaced by - # the encrypted one which can be found in 'config_file_user' - with open(config_file_user, 'r') as f: - engineID = '' - for line in f: - if line.startswith('oldEngineID'): - string = line.split(' ') - engineID = string[1] - - if line.startswith('usmUser'): - string = line.split(' ') - cfg = { - 'user': string[4].replace(r'"', ''), - 'auth_pw': string[8], - 'priv_pw': string[10] - } - # No need to take care about the VyOS internal user - if cfg['user'] == snmp['vyos_user']: - continue - - # Now update the running configuration - # - # Currently when executing os.system() the environment does not have the vyos_libexec_dir variable set, see T685 - os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" engineid {1} > /dev/null'.format(cfg['user'], engineID)) - os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key {1} > /dev/null'.format(cfg['user'], cfg['auth_pw'])) - os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key {1} > /dev/null'.format(cfg['user'], cfg['priv_pw'])) - os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user'])) - os.system('vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_delete service snmp v3 user "{0}" privacy plaintext-key > /dev/null'.format(cfg['user'])) - - 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/ssh.py b/src/conf_mode/ssh.py deleted file mode 100755 index f1ac194..0000000 --- a/src/conf_mode/ssh.py +++ /dev/null @@ -1,255 +0,0 @@ -#!/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 jinja2 - -from vyos.config import Config -from vyos import ConfigError - -config_file = r'/etc/ssh/sshd_config' - -# Please be careful if you edit the template. -config_tmpl = """ - -### Autogenerated by ssh.py ### - -# Non-configurable defaults -Protocol 2 -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key -HostKey /etc/ssh/ssh_host_ecdsa_key -HostKey /etc/ssh/ssh_host_ed25519_key -UsePrivilegeSeparation yes -KeyRegenerationInterval 3600 -ServerKeyBits 1024 -SyslogFacility AUTH -LoginGraceTime 120 -StrictModes yes -RSAAuthentication yes -PubkeyAuthentication yes -IgnoreRhosts yes -RhostsRSAAuthentication no -HostbasedAuthentication no -PermitEmptyPasswords no -ChallengeResponseAuthentication no -X11Forwarding yes -X11DisplayOffset 10 -PrintMotd no -PrintLastLog yes -TCPKeepAlive yes -Banner /etc/issue.net -Subsystem sftp /usr/lib/openssh/sftp-server -UsePAM yes -HostKey /etc/ssh/ssh_host_key - -# Specifies whether sshd should look up the remote host name, -# and to check that the resolved host name for the remote IP -# address maps back to the very same IP address. -UseDNS {{ host_validation }} - -# Specifies the port number that sshd listens on. The default is 22. -# Multiple options of this type are permitted. -Port {{ port }} - -# Gives the verbosity level that is used when logging messages from sshd -LogLevel {{ log_level }} - -# Specifies whether root can log in using ssh -PermitRootLogin {{ allow_root }} - -# Specifies whether password authentication is allowed -PasswordAuthentication {{ password_authentication }} - -{% if listen_on -%} -# Specifies the local addresses sshd should listen on -{% for a in listen_on -%} -ListenAddress {{ a }} -{% endfor -%} -{% endif %} - -{% if ciphers -%} -# Specifies the ciphers allowed. Multiple ciphers must be comma-separated. -# -# NOTE: As of now, there is no 'multi' node for 'ciphers', thus we have only one :/ -Ciphers {{ ciphers | join(",") }} -{% endif %} - -{% if mac -%} -# Specifies the available MAC (message authentication code) algorithms. The MAC -# algorithm is used for data integrity protection. Multiple algorithms must be -# comma-separated. -# -# NOTE: As of now, there is no 'multi' node for 'mac', thus we have only one :/ -MACs {{ mac | join(",") }} -{% endif %} - -{% if key_exchange -%} -# Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must -# be comma-separated. -# -# NOTE: As of now, there is no 'multi' node for 'key-exchange', thus we have only one :/ -KexAlgorithms {{ key_exchange | join(",") }} -{% endif %} - -{% if allow_users -%} -# This keyword can be followed by a list of user name patterns, separated by spaces. -# If specified, login is allowed only for user names that match one of the patterns. -# Only user names are valid, a numerical user ID is not recognized. -AllowUsers {{ allow_users | join(" ") }} -{% endif %} - -{% if allow_groups -%} -# This keyword can be followed by a list of group name patterns, separated by spaces. -# If specified, login is allowed only for users whose primary group or supplementary -# group list matches one of the patterns. Only group names are valid, a numerical group -# ID is not recognized. -AllowGroups {{ allow_groups | join(" ") }} -{% endif %} - -{% if deny_users -%} -# This keyword can be followed by a list of user name patterns, separated by spaces. -# Login is disallowed for user names that match one of the patterns. Only user names -# are valid, a numerical user ID is not recognized. -DenyUsers {{ deny_users | join(" ") }} -{% endif %} - -{% if deny_groups -%} -# This keyword can be followed by a list of group name patterns, separated by spaces. -# Login is disallowed for users whose primary group or supplementary group list matches -# one of the patterns. Only group names are valid, a numerical group ID is not recognized. -DenyGroups {{ deny_groups | join(" ") }} -{% endif %} -""" - -default_config_data = { - 'port' : '22', - 'log_level': 'INFO', - 'allow_root': 'no', - 'password_authentication': 'yes', - 'host_validation': 'yes' -} - -def get_config(): - ssh = default_config_data - conf = Config() - if not conf.exists('service ssh'): - return None - else: - conf.set_level('service ssh') - - if conf.exists('access-control allow user'): - allow_users = conf.return_values('access-control allow user') - ssh['allow_users'] = allow_users - - if conf.exists('access-control allow group'): - allow_groups = conf.return_values('access-control allow group') - ssh['allow_groups'] = allow_groups - - if conf.exists('access-control deny user'): - deny_users = conf.return_values('access-control deny user') - ssh['deny_users'] = deny_users - - if conf.exists('access-control deny group'): - deny_groups = conf.return_values('access-control deny group') - ssh['deny_groups'] = deny_groups - - if conf.exists('allow-root'): - ssh['allow-root'] = 'yes' - - if conf.exists('ciphers'): - ciphers = conf.return_values('ciphers') - ssh['ciphers'] = ciphers - - if conf.exists('disable-host-validation'): - ssh['host_validation'] = 'no' - - if conf.exists('disable-password-authentication'): - ssh['password_authentication'] = 'no' - - if conf.exists('key-exchange'): - kex = conf.return_values('key-exchange') - ssh['key_exchange'] = kex - - if conf.exists('listen-address'): - # We can listen on both IPv4 and IPv6 addresses - # Maybe there could be a check in the future if the configured IP address - # is configured on this system at all? - addresses = conf.return_values('listen-address') - listen = [] - - for addr in addresses: - listen.append(addr) - - ssh['listen_on'] = listen - - if conf.exists('loglevel'): - ssh['log_level'] = conf.return_value('loglevel') - - if conf.exists('mac'): - mac = conf.return_values('mac') - ssh['mac'] = mac - - if conf.exists('port'): - port = conf.return_value('port') - ssh['port'] = port - - return ssh - -def verify(ssh): - if ssh is None: - return None - - if 'loglevel' in ssh.keys(): - allowed_loglevel = 'QUIET, FATAL, ERROR, INFO, VERBOSE' - if not ssh['loglevel'] in allowed_loglevel: - raise ConfigError('loglevel must be one of "{0}"\n'.format(allowed_loglevel)) - - return None - -def generate(ssh): - if ssh is None: - return None - - tmpl = jinja2.Template(config_tmpl) - config_text = tmpl.render(ssh) - with open(config_file, 'w') as f: - f.write(config_text) - return None - -def apply(ssh): - if ssh is not None and 'port' in ssh.keys(): - os.system("sudo systemctl restart ssh") - else: - # SSH access is removed in the commit - os.system("sudo systemctl stop ssh") - 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/task_scheduler.py b/src/conf_mode/task_scheduler.py deleted file mode 100755 index 285afe2..0000000 --- a/src/conf_mode/task_scheduler.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 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 os -import re -import sys - -from vyos.config import Config -from vyos import ConfigError - - -crontab_file = "/etc/cron.d/vyos-crontab" - - -def format_task(minute="*", hour="*", day="*", dayofweek="*", month="*", user="root", rawspec=None, command=""): - fmt_full = "{minute} {hour} {day} {month} {dayofweek} {user} {command}\n" - fmt_raw = "{spec} {user} {command}\n" - - if rawspec is None: - s = fmt_full.format(minute=minute, hour=hour, day=day, - dayofweek=dayofweek, month=month, command=command, user=user) - else: - s = fmt_raw.format(spec=rawspec, user=user, command=command) - - return s - -def split_interval(s): - result = re.search(r"(\d+)([mdh]?)", s) - value = int(result.group(1)) - suffix = result.group(2) - return( (value, suffix) ) - -def make_command(executable, arguments): - if arguments: - return("sg vyattacfg \"{0} {1}\"".format(executable, arguments)) - else: - return(executable) - -def get_config(): - conf = Config() - conf.set_level("system task-scheduler task") - task_names = conf.list_nodes("") - tasks = [] - - for name in task_names: - interval = conf.return_value("{0} interval".format(name)) - spec = conf.return_value("{0} crontab-spec".format(name)) - executable = conf.return_value("{0} executable path".format(name)) - args = conf.return_value("{0} executable arguments".format(name)) - task = { - "name": name, - "interval": interval, - "spec": spec, - "executable": executable, - "args": args - } - tasks.append(task) - - return tasks - -def verify(tasks): - for task in tasks: - if not task["interval"] and not task["spec"]: - raise ConfigError("Invalid task {0}: must define either interval or crontab-spec".format(task["name"])) - - if task["interval"]: - if task["spec"]: - raise ConfigError("Invalid task {0}: cannot use interval and crontab-spec at the same time".format(task["name"])) - - if not re.match(r"^\d+[mdh]?$", task["interval"]): - raise(ConfigError("Invalid interval {0} in task {1}: interval should be a number optionally followed by m, h, or d".format(task["name"], task["interval"]))) - else: - # Check if values are within allowed range - value, suffix = split_interval(task["interval"]) - - if not suffix or suffix == "m": - if value > 60: - raise ConfigError("Invalid task {0}: interval in minutes must not exceed 60".format(task["name"])) - elif suffix == "h": - if value > 24: - raise ConfigError("Invalid task {0}: interval in hours must not exceed 24".format(task["name"])) - elif suffix == "d": - if value > 31: - raise ConfigError("Invalid task {0}: interval in days must not exceed 31".format(task["name"])) - - if not task["executable"]: - raise ConfigError("Invalid task {0}: executable is not defined".format(task["name"])) - else: - # Check if executable exists and is executable - if not (os.path.isfile(task["executable"]) and os.access(task["executable"], os.X_OK)): - raise ConfigError("Invalid task {0}: file {1} does not exist or is not executable".format(task["name"], task["executable"])) - -def generate(tasks): - crontab_header = "### Generated by vyos-update-crontab.py ###\n" - if len(tasks) == 0: - if os.path.exists(crontab_file): - os.remove(crontab_file) - else: - pass - else: - crontab_lines = [] - for task in tasks: - command = make_command(task["executable"], task["args"]) - if task["spec"]: - line = format_task(command=command, rawspec=task["spec"]) - else: - value, suffix = split_interval(task["interval"]) - if not suffix or suffix == "m": - line = format_task(command=command, minute="*/{0}".format(value)) - elif suffix == "h": - line = format_task(command=command, minute="0", hour="*/{0}".format(value)) - elif suffix == "d": - line = format_task(command=command, minute="0", hour="0", day="*/{0}".format(value)) - crontab_lines.append(line) - - with open(crontab_file, 'w') as f: - f.write(crontab_header) - f.writelines(crontab_lines) - -def apply(config): - # No daemon restarts etc. needed for cron - pass - - -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/helpers/commands-pipe.py b/src/helpers/commands-pipe.py deleted file mode 100755 index 1120bb0..0000000 --- a/src/helpers/commands-pipe.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/python3 - -import sys -import re - -from signal import signal, SIGPIPE, SIG_DFL -from vyos.configtree import ConfigTree - -signal(SIGPIPE,SIG_DFL) - -config_string = sys.stdin.read().strip() - -if not config_string: - sys.exit(0) - -# When used in conf mode pipe, the config given to the script is likely incomplete -# and breaks the "all top level nodes are neither tag nor leaf" -# invariant, so we wrap it into a fake node. -# Since nodes don't normally start with an underscore, -# __root__ is hygienic enough. -config_string = "__root__ {{ {0} \n }}".format(config_string) - -config_re = re.compile(r'(set|comment)\s+__root__\s+(.*)') - -config = ConfigTree(config_string) -commands = config.to_commands() -commands = config_re.sub("\\1 \\2", commands) - -print(commands) diff --git a/src/helpers/validate-value.py b/src/helpers/validate-value.py deleted file mode 100755 index d702739..0000000 --- a/src/helpers/validate-value.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 - -import re -import os -import sys -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument('--regex', action='append') -parser.add_argument('--exec', action='append') -parser.add_argument('--value', action='store') - -args = parser.parse_args() - -debug = False - -# Multiple arguments work like logical OR - -try: - for r in args.regex: - if re.fullmatch(r, args.value): - sys.exit(0) -except Exception as exn: - if debug: - print(exn) - else: - pass - -try: - for cmd in args.exec: - cmd = "{0} {1}".format(cmd, args.value) - if debug: - print(cmd) - res = os.system(cmd) - if res == 0: - sys.exit(0) -except Exception as exn: - if debug: - print(exn) - else: - pass - -sys.exit(1) diff --git a/src/migration-scripts/config-management/0-to-1 b/src/migration-scripts/config-management/0-to-1 deleted file mode 100755 index 3443591..0000000 --- a/src/migration-scripts/config-management/0-to-1 +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -# Add commit-revisions option if it doesn't exist - -import sys - -from vyos.configtree import ConfigTree - -if (len(sys.argv) < 1): - print("Must specify file name!") - sys.exit(1) - -file_name = sys.argv[1] - -with open(file_name, 'r') as f: - config_file = f.read() - -config = ConfigTree(config_file) - -if config.exists(['system', 'config-management', 'commit-revisions']): - # Nothing to do - sys.exit(0) -else: - config.set(['system', 'config-management', 'commit-revisions'], value='200') - - try: - with open(file_name, 'w') as f: - f.write(config.to_string()) - except OSError as e: - print("Failed to save the modified config: {}".format(e)) - sys.exit(1) diff --git a/src/migration-scripts/system/7-to-8 b/src/migration-scripts/system/7-to-8 deleted file mode 100755 index 4cbb21f..0000000 --- a/src/migration-scripts/system/7-to-8 +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -# Converts "system gateway-address" option to "protocols static route 0.0.0.0/0 next-hop $gw" - -import sys - -from vyos.configtree import ConfigTree - -if (len(sys.argv) < 1): - print("Must specify file name!") - sys.exit(1) - -file_name = sys.argv[1] - -with open(file_name, 'r') as f: - config_file = f.read() - -config = ConfigTree(config_file) - -if not config.exists(['system', 'gateway-address']): - # Nothing to do - sys.exit(0) -else: - # Save the address - gw = config.return_value(['system', 'gateway-address']) - - # Create the node for the new syntax - # Note: next-hop is a tag node, gateway address is its child, not a value - config.set(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop', gw]) - - # Delete the node with the old syntax - config.delete(['system', 'gateway-address']) - - # Now, the interesting part. Both route and next-hop are supposed to be tag nodes, - # which you can verify with "cli-shell-api isTag $configPath". - # They must be formatted as such to load correctly. - config.set_tag(['protocols', 'static', 'route']) - config.set_tag(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop']) - - try: - with open(file_name, 'w') as f: - f.write(config.to_string()) - except OSError as e: - print("Failed to save the modified config: {}".format(e)) - sys.exit(1) diff --git a/src/op_mode/cpu_summary.py b/src/op_mode/cpu_summary.py deleted file mode 100755 index 7324c75..0000000 --- a/src/op_mode/cpu_summary.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 - -import re - -from vyos.util import colon_separated_to_dict - - -FILE_NAME = '/proc/cpuinfo' - -with open(FILE_NAME, 'r') as f: - data_raw = f.read() - -data = colon_separated_to_dict(data_raw) - -# Accumulate all data in a dict for future support for machine-readable output -cpu_data = {} -cpu_data['cpu_number'] = len(data['processor']) -cpu_data['models'] = list(set(data['model name'])) - -# Strip extra whitespace from CPU model names, /proc/cpuinfo is prone to that -cpu_data['models'] = map(lambda s: re.sub(r'\s+', ' ', s), cpu_data['models']) - -print("CPU(s): {0}".format(cpu_data['cpu_number'])) -print("CPU model(s): {0}".format(",".join(cpu_data['models']))) diff --git a/src/op_mode/dns_forwarding_reset.py b/src/op_mode/dns_forwarding_reset.py deleted file mode 100755 index da4fba3..0000000 --- a/src/op_mode/dns_forwarding_reset.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/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/>. -# -# File: vyos-show-version -# Purpose: -# Displays image version and system information. -# Used by the "run show version" command. - - -import os -import sys -import argparse - -import vyos.config - -parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Reset all cache") -parser.add_argument("domain", type=str, nargs="?", help="Domain to reset cache entries for") - -if __name__ == '__main__': - args = parser.parse_args() - - # Do nothing if service is not configured - c = vyos.config.Config() - if not c.exists_effective('service dns forwarding'): - print("DNS forwarding is not configured") - sys.exit(0) - - if args.all: - os.system("rec_control wipe-cache \'.$\'") - sys.exit(1) - elif args.domain: - os.system("rec_control wipe-cache \'{0}$\'".format(args.domain)) - else: - parser.print_help() - sys.exit(1) diff --git a/src/op_mode/dns_forwarding_restart.sh b/src/op_mode/dns_forwarding_restart.sh deleted file mode 100755 index 12106fc..0000000 --- a/src/op_mode/dns_forwarding_restart.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -if cli-shell-api exists service dns forwarding; then - echo "Restarting the DNS forwarding service" - systemctl restart pdns-recursor -else - echo "DNS forwarding is not configured" -fi diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py deleted file mode 100755 index f626244..0000000 --- a/src/op_mode/dns_forwarding_statistics.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 - -import subprocess -import jinja2 -import sys - -from vyos.config import Config - -PDNS_CMD='/usr/bin/rec_control' - -OUT_TMPL_SRC = """ -DNS forwarding statistics: - -Cache entries: {{ cache_entries -}} -Cache size: {{ cache_size }} kbytes - -""" - - -if __name__ == '__main__': - # Do nothing if service is not configured - c = Config() - if not c.exists_effective('service dns forwarding'): - print("DNS forwarding is not configured") - sys.exit(0) - - data = {} - - data['cache_entries'] = subprocess.check_output([PDNS_CMD, 'get cache-entries']).decode() - data['cache_size'] = "{0:.2f}".format( int(subprocess.check_output([PDNS_CMD, 'get cache-bytes']).decode()) / 1024 ) - - tmpl = jinja2.Template(OUT_TMPL_SRC) - print(tmpl.render(data)) diff --git a/src/op_mode/maya_date.py b/src/op_mode/maya_date.py deleted file mode 100755 index 7d8aefc..0000000 --- a/src/op_mode/maya_date.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2013, 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 - -class MayaDate(object): - """ Converts number of days since UNIX epoch - to the Maya calendar date. - - Ancient Maya people used three independent calendars for - different purposes. - - The long count calendar is for recording historical events. - It represents the number of days passed - since some date in the past the Maya believed is the day - our world was created. - - Tzolkin calendar is for religious purposes, it has - two independent cycles of 13 and 20 days, where 13 day - cycle days are numbered, and 20 day cycle days are named. - - Haab calendar is for agriculture and daily life, it's a - 365 day calendar with 18 months 20 days each, and 5 - nameless days. - - The smallest unit of the long count calendar is one day (kin). - - """ - - """ The long count calendar uses five different base 18 or base 20 - cycles. Modern scholars write long count calendar dates in a dot separated format - from longest to shortest cycle, - <baktun>.<katun>.<tun>.<winal>.<kin> - for example, "13.0.0.9.2". - - Classic version actually used by the ancient Maya wraps around - every 13th baktun, but modern historians often use longer cycles - such as piktun = 20 baktun. - - """ - kin = 1 - winal = 20 # 20 kin - tun = 360 # 18 winal - katun = 7200 # 20 tun - baktun = 144000 # 20 katun - - """ Tzolk'in date is composed of two independent cycles. - Dates repeat every 260 days, 13 Ajaw is considered the end - of tzolk'in. - - Every day of the 20 day cycle has unique name, we number - them from zero so it's easier to map the remainder to day: - """ - tzolkin_days = { 0: "Imix'", - 1: "Ik'", - 2: "Ak'b'al", - 3: "K'an", - 4: "Chikchan", - 5: "Kimi", - 6: "Manik'", - 7: "Lamat", - 8: "Muluk", - 9: "Ok", - 10: "Chuwen", - 11: "Eb'", - 12: "B'en", - 13: "Ix", - 14: "Men", - 15: "Kib'", - 16: "Kab'an", - 17: "Etz'nab'", - 18: "Kawak", - 19: "Ajaw" } - - """ As said above, haab (year) has 19 months. Only 18 are - true months of 20 days each, the remaining 5 days called "wayeb" - do not really belong to any month, but we think of them as a pseudo-month - for convenience. - - Also, note that days of the month are actually numbered from 0, not from 1, - it's not for technical reasons. - """ - haab_months = { 0: "Pop", - 1: "Wo'", - 2: "Sip", - 3: "Sotz'", - 4: "Sek", - 5: "Xul", - 6: "Yaxk'in'", - 7: "Mol", - 8: "Ch'en", - 9: "Yax", - 10: "Sak'", - 11: "Keh", - 12: "Mak", - 13: "K'ank'in", - 14: "Muwan'", - 15: "Pax", - 16: "K'ayab", - 17: "Kumk'u", - 18: "Wayeb'" } - - """ Now we need to map the beginning of UNIX epoch - (Jan 1 1970 00:00 UTC) to the beginning of the long count - calendar (0.0.0.0.0, 4 Ajaw, 8 Kumk'u). - - The problem with mapping the long count calendar to - any other is that its start date is not known exactly. - - The most widely accepted hypothesis suggests it was - August 11, 3114 BC gregorian date. In this case UNIX epoch - starts on 12.17.16.7.5, 13 Chikchan, 3 K'ank'in - - It's known as Goodman-Martinez-Thompson (GMT) correlation - constant. - """ - start_days = 1856305 - - """ Seconds in day, for conversion from timestamp """ - seconds_in_day = 60 * 60 * 24 - - def __init__(self, timestamp): - if timestamp is None: - self.days = self.start_days - else: - self.days = self.start_days + (int(timestamp) // self.seconds_in_day) - - def long_count_date(self): - """ Returns long count date string """ - days = self.days - - cur_baktun = days // self.baktun - days = days % self.baktun - - cur_katun = days // self.katun - days = days % self.katun - - cur_tun = days // self.tun - days = days % self.tun - - cur_winal = days // self.winal - days = days % self.winal - - cur_kin = days - - longcount_string = "{0}.{1}.{2}.{3}.{4}".format( cur_baktun, - cur_katun, - cur_tun, - cur_winal, - cur_kin ) - return(longcount_string) - - def tzolkin_date(self): - """ Returns tzolkin date string """ - days = self.days - - """ The start date is not the beginning of both cycles, - it's 4 Ajaw. So we need to add 4 to the 13 days cycle day, - and substract 1 from the 20 day cycle to get correct result. - """ - tzolkin_13 = (days + 4) % 13 - tzolkin_20 = (days - 1) % 20 - - tzolkin_string = "{0} {1}".format(tzolkin_13, self.tzolkin_days[tzolkin_20]) - - return(tzolkin_string) - - def haab_date(self): - """ Returns haab date string. - - The time start on 8 Kumk'u rather than 0 Pop, which is - 17 days before the new haab, so we need to substract 17 - from the current date to get correct result. - """ - days = self.days - - haab_day = (days - 17) % 365 - haab_month = haab_day // 20 - haab_day_of_month = haab_day % 20 - - haab_string = "{0} {1}".format(haab_day_of_month, self.haab_months[haab_month]) - - return(haab_string) - - def date(self): - return("{0}, {1}, {2}".format( self.long_count_date(), self.tzolkin_date(), self.haab_date() )) - -if __name__ == '__main__': - try: - timestamp = sys.argv[1] - except: - print("Please specify timestamp in the argument") - sys.exit(1) - - maya_date = MayaDate(timestamp) - print(maya_date.date()) diff --git a/src/op_mode/show-configuration-files.sh b/src/op_mode/show-configuration-files.sh deleted file mode 100755 index ad8e074..0000000 --- a/src/op_mode/show-configuration-files.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Wrapper script for the show configuration files command -find ${vyatta_sysconfdir}/config/ \ - -type f \ - -not -name ".*" \ - -not -name "config.boot.*" \ - -printf "%f\t(%Tc)\t%T@\n" \ - | sort -r -k3 \ - | awk -F"\t" '{printf ("%-20s\t%s\n", $1,$2) ;}' diff --git a/src/op_mode/show-disk-format.sh b/src/op_mode/show-disk-format.sh deleted file mode 100755 index 61b15a5..0000000 --- a/src/op_mode/show-disk-format.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -disk_dev="/dev/$1" -if [ ! -b "$disk_dev" ];then - echo "$3 is not a disk device" - exit 1 -fi -sudo /sbin/fdisk -l "$disk_dev" diff --git a/src/op_mode/show-raid.sh b/src/op_mode/show-raid.sh deleted file mode 100755 index ba41746..0000000 --- a/src/op_mode/show-raid.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -raid_set_name=$1 -raid_sets=`cat /proc/partitions | grep md | awk '{ print $4 }'` -valid_set=`echo $raid_sets | grep $raid_set_name` -if [ -z $valid_set ]; then - echo "$raid_set_name is not a RAID set" -else - if [ -r /dev/${raid_set_name} ]; then - # This should work without sudo because we have read - # access to the dev, but for some reason mdadm must be - # run as root in order to succeed. - sudo /sbin/mdadm --detail /dev/${raid_set_name} - else - echo "Must be administrator or root to display RAID status" - fi -fi diff --git a/src/op_mode/snmp.py b/src/op_mode/snmp.py deleted file mode 100755 index e08441f..0000000 --- a/src/op_mode/snmp.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/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/>. -# -# File: snmp.py -# Purpose: -# Show SNMP community/remote hosts -# Used by the "run show snmp community" commands. - -import os -import sys -import argparse - -from vyos.config import Config - -config_file_daemon = r'/etc/snmp/snmpd.conf' - -parser = argparse.ArgumentParser(description='Retrieve infomration from running SNMP daemon') -parser.add_argument('--allowed', action="store_true", help='Show available SNMP communities') -parser.add_argument('--community', action="store", help='Show status of given SNMP community', type=str) -parser.add_argument('--host', action="store", help='SNMP host to connect to', type=str, default='localhost') - -config = { - 'communities': [], -} - -def read_config(): - with open(config_file_daemon, 'r') as f: - for line in f: - # Only get configured SNMP communitie - if line.startswith('rocommunity') or line.startswith('rwcommunity'): - string = line.split(' ') - # append community to the output list only once - c = string[1] - if c not in config['communities']: - config['communities'].append(c) - -def show_all(): - if len(config['communities']) > 0: - print(' '.join(config['communities'])) - -def show_community(c, h): - print('Status of SNMP community {0} on {1}'.format(c, h), flush=True) - os.system('/usr/bin/snmpstatus -t1 -v1 -c {0} {1}'.format(c, h)) - -if __name__ == '__main__': - args = parser.parse_args() - - # Do nothing if service is not configured - c = Config() - if not c.exists_effective('service snmp'): - print("SNMP service is not configured") - sys.exit(0) - - read_config() - - if args.allowed: - show_all() - sys.exit(1) - elif args.community: - show_community(args.community, args.host) - sys.exit(1) - else: - parser.print_help() - sys.exit(1) diff --git a/src/op_mode/snmp_ifmib.py b/src/op_mode/snmp_ifmib.py deleted file mode 100755 index 9d56a95..0000000 --- a/src/op_mode/snmp_ifmib.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/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/>. -# -# File: snmp_ifmib.py -# Purpose: -# Show SNMP MIB information -# Used by the "run show snmp mib" commands. - -import sys -import argparse -import netifaces -import subprocess - -from vyos.config import Config - -parser = argparse.ArgumentParser(description='Retrieve SNMP interfaces information') -parser.add_argument('--ifindex', action='store', nargs='?', const='all', help='Show interface index') -parser.add_argument('--ifalias', action='store', nargs='?', const='all', help='Show interface aliase') -parser.add_argument('--ifdescr', action='store', nargs='?', const='all', help='Show interface description') - -def show_ifindex(i): - proc = subprocess.Popen(['/bin/ip', 'link', 'show', i], stdout=subprocess.PIPE) - (out, err) = proc.communicate() - # convert output to string - string = out.decode("utf-8") - - index = 'ifIndex = ' + string.split(':')[0] - return index.replace('\n', '') - -def show_ifalias(i): - proc = subprocess.Popen(['/bin/ip', 'link', 'show', i], stdout=subprocess.PIPE) - (out, err) = proc.communicate() - # convert output to string - string = out.decode("utf-8") - - if 'alias' in string: - alias = 'ifAlias = ' + string.split('alias')[1].lstrip() - else: - alias = 'ifAlias = ' + i - - return alias.replace('\n', '') - -def show_ifdescr(i): - ven_id = '' - dev_id = '' - - try: - with open(r'/sys/class/net/' + i + '/device/vendor', 'r') as f: - ven_id = f.read().replace('\n', '') - except FileNotFoundError: - pass - - try: - with open(r'/sys/class/net/' + i + '/device/device', 'r') as f: - dev_id = f.read().replace('\n', '') - except FileNotFoundError: - pass - - if ven_id == '' and dev_id == '': - ret = 'ifDescr = {0}'.format(i) - return ret - - device = str(ven_id) + ':' + str(dev_id) - proc = subprocess.Popen(['/usr/bin/lspci', '-mm', '-d', device], stdout=subprocess.PIPE) - (out, err) = proc.communicate() - - # convert output to string - string = out.decode("utf-8").split('"') - vendor = string[3] - device = string[5] - - ret = 'ifDescr = {0} {1}'.format(vendor, device) - return ret.replace('\n', '') - -if __name__ == '__main__': - args = parser.parse_args() - - # Do nothing if service is not configured - c = Config() - if not c.exists_effective('service snmp'): - print("SNMP service is not configured") - sys.exit(0) - - if args.ifindex: - if args.ifindex == 'all': - for i in netifaces.interfaces(): - print('{0}: {1}'.format(i, show_ifindex(i))) - else: - print('{0}: {1}'.format(args.ifindex, show_ifindex(args.ifindex))) - - elif args.ifalias: - if args.ifalias == 'all': - for i in netifaces.interfaces(): - print('{0}: {1}'.format(i, show_ifalias(i))) - else: - print('{0}: {1}'.format(args.ifalias, show_ifalias(args.ifalias))) - - elif args.ifdescr: - if args.ifdescr == 'all': - for i in netifaces.interfaces(): - print('{0}: {1}'.format(i, show_ifdescr(i))) - else: - print('{0}: {1}'.format(args.ifdescr, show_ifdescr(args.ifdescr))) - - else: - #eth0: ifIndex = 2 - # ifAlias = NET-MYBLL-MUCI-BACKBONE - # ifDescr = VMware VMXNET3 Ethernet Controller - #lo: ifIndex = 1 - for i in netifaces.interfaces(): - print('{0}:\t{1}'.format(i, show_ifindex(i))) - print('\t{0}'.format(show_ifalias(i))) - print('\t{0}'.format(show_ifdescr(i))) - - sys.exit(1) diff --git a/src/op_mode/snmp_v3.py b/src/op_mode/snmp_v3.py deleted file mode 100755 index 92601f1..0000000 --- a/src/op_mode/snmp_v3.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/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/>. -# -# File: snmp_v3.py -# Purpose: -# Show SNMP v3 information -# Used by the "run show snmp v3" commands. - -import sys -import jinja2 -import argparse - -from vyos.config import Config - -parser = argparse.ArgumentParser(description='Retrieve SNMP v3 information') -parser.add_argument('--all', action="store_true", help='Show all available information') -parser.add_argument('--group', action="store_true", help='Show the list of configured groups') -parser.add_argument('--trap', action="store_true", help='Show the list of configured targets') -parser.add_argument('--user', action="store_true", help='Show the list of configured users') -parser.add_argument('--view', action="store_true", help='Show the list of configured views') - -GROUP_OUTP_TMPL_SRC = """ -SNMPv3 Groups: - - Group View - ----- ---- - {% if group -%}{% for g in group -%} - {{ "%-20s" | format(g.name) }}{{ g.view }}({{ g.mode }}) - {% endfor %}{% endif %} -""" - -TRAPTGT_OUTP_TMPL_SRC = """ -SNMPv3 Trap-targets: - - Tpap-target Port Protocol Auth Priv Type EngineID User - ----------- ---- -------- ---- ---- ---- -------- ---- - {% if trap -%}{% for t in trap -%} - {{ "%-20s" | format(t.name) }} {{ t.port }} {{ t.proto }} {{ t.auth }} {{ t.priv }} {{ t.type }} {{ "%-32s" | format(t.engID) }} {{ t.user }} - {% endfor %}{% endif %} -""" - -USER_OUTP_TMPL_SRC = """ -SNMPv3 Users: - - User Auth Priv Mode Group - ---- ---- ---- ---- ----- - {% if user -%}{% for u in user -%} - {{ "%-20s" | format(u.name) }}{{ u.auth }} {{ u.priv }} {{ u.mode }} {{ u.group }} - {% endfor %}{% endif %} -""" - -VIEW_OUTP_TMPL_SRC = """ -SNMPv3 Views: - {% if view -%}{% for v in view %} - View : {{ v.name }} - OIDs : .{{ v.oids | join("\n .")}} - {% endfor %}{% endif %} -""" - -if __name__ == '__main__': - args = parser.parse_args() - - # Do nothing if service is not configured - c = Config() - if not c.exists_effective('service snmp v3'): - print("SNMP v3 is not configured") - sys.exit(0) - - data = { - 'group': [], - 'trap': [], - 'user': [], - 'view': [] - } - - if c.exists_effective('service snmp v3 group'): - for g in c.list_effective_nodes('service snmp v3 group'): - group = { - 'name': g, - 'mode': '', - 'view': '' - } - group['mode'] = c.return_effective_value('service snmp v3 group {0} mode'.format(g)) - group['view'] = c.return_effective_value('service snmp v3 group {0} view'.format(g)) - - data['group'].append(group) - - if c.exists_effective('service snmp v3 user'): - for u in c.list_effective_nodes('service snmp v3 user'): - user = { - 'name' : u, - 'mode' : '', - 'auth' : '', - 'priv' : '', - 'group': '' - } - user['mode'] = c.return_effective_value('service snmp v3 user {0} mode'.format(u)) - user['auth'] = c.return_effective_value('service snmp v3 user {0} auth type'.format(u)) - user['priv'] = c.return_effective_value('service snmp v3 user {0} privacy type'.format(u)) - user['group'] = c.return_effective_value('service snmp v3 user {0} group'.format(u)) - - data['user'].append(user) - - if c.exists_effective('service snmp v3 view'): - for v in c.list_effective_nodes('service snmp v3 view'): - view = { - 'name': v, - 'oids': [] - } - view['oids'] = c.list_effective_nodes('service snmp v3 view {0} oid'.format(v)) - - data['view'].append(view) - - if c.exists_effective('service snmp v3 trap-target'): - for t in c.list_effective_nodes('service snmp v3 trap-target'): - trap = { - 'name' : t, - 'port' : '', - 'proto': '', - 'auth' : '', - 'priv' : '', - 'type' : '', - 'engID': '', - 'user' : '' - } - trap['port'] = c.return_effective_value('service snmp v3 trap-target {0} port'.format(t)) - trap['proto'] = c.return_effective_value('service snmp v3 trap-target {0} protocol'.format(t)) - trap['auth'] = c.return_effective_value('service snmp v3 trap-target {0} auth type'.format(t)) - trap['priv'] = c.return_effective_value('service snmp v3 trap-target {0} privacy type'.format(t)) - trap['type'] = c.return_effective_value('service snmp v3 trap-target {0} type'.format(t)) - trap['engID'] = c.return_effective_value('service snmp v3 trap-target {0} engineid'.format(t)) - trap['user'] = c.return_effective_value('service snmp v3 trap-target {0} user'.format(t)) - - data['trap'].append(trap) - - print(data) - if args.all: - # Special case, print all templates ! - tmpl = jinja2.Template(GROUP_OUTP_TMPL_SRC) - print(tmpl.render(data)) - tmpl = jinja2.Template(TRAPTGT_OUTP_TMPL_SRC) - print(tmpl.render(data)) - tmpl = jinja2.Template(USER_OUTP_TMPL_SRC) - print(tmpl.render(data)) - tmpl = jinja2.Template(VIEW_OUTP_TMPL_SRC) - print(tmpl.render(data)) - - elif args.group: - tmpl = jinja2.Template(GROUP_OUTP_TMPL_SRC) - print(tmpl.render(data)) - - elif args.trap: - tmpl = jinja2.Template(TRAPTGT_OUTP_TMPL_SRC) - print(tmpl.render(data)) - - elif args.user: - tmpl = jinja2.Template(USER_OUTP_TMPL_SRC) - print(tmpl.render(data)) - - elif args.view: - tmpl = jinja2.Template(VIEW_OUTP_TMPL_SRC) - print(tmpl.render(data)) - - else: - parser.print_help() - - sys.exit(1) diff --git a/src/op_mode/snmp_v3_showcerts.sh b/src/op_mode/snmp_v3_showcerts.sh deleted file mode 100755 index 015b2e6..0000000 --- a/src/op_mode/snmp_v3_showcerts.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -files=`sudo ls /etc/snmp/tls/certs/ 2> /dev/null`; -if [ -n "$files" ]; then - sudo /usr/bin/net-snmp-cert showcerts --subject --fingerprint -else - echo "You don't have any certificates. Put it in '/etc/snmp/tls/certs/' folder." -fi diff --git a/src/op_mode/version.py b/src/op_mode/version.py deleted file mode 100755 index ce3b3b5..0000000 --- a/src/op_mode/version.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2016 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/>. -# -# File: vyos-show-version -# Purpose: -# Displays image version and system information. -# Used by the "run show version" command. - - -import os -import sys -import subprocess -import argparse -import json - -import pystache - -import vyos.version -import vyos.limericks - - -parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Include individual package versions") -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}} -Built by: {{built_by}} -Built on: {{built_on}} -Build ID: {{build_id}} - -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}} - -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'] = subprocess.check_output('uname -m', shell=True).decode().strip() - - - # Get hypervisor name, if any - system_type = "bare metal" - try: - hypervisor = subprocess.check_output('hvinfo 2>/dev/null', shell=True).decode().strip() - system_type = "{0} guest".format(hypervisor) - except subprocess.CalledProcessError: - # 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 subprocess.call(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""", shell=True) == 0: - boot_via = "livecd" - elif subprocess.call(""" grep '^overlay /' /proc/mounts >/dev/null """, shell=True) != 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') - - - 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:") - os.system("dpkg -l") - - if args.funny: - print(vyos.limericks.get_random()) diff --git a/src/tests/helper.py b/src/tests/helper.py deleted file mode 100644 index a7e4f20..0000000 --- a/src/tests/helper.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/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 importlib.util - - -def prepare_module(file_path='', module_name=''): - spec = importlib.util.spec_from_file_location(module_name, file_path) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - sys.modules[module_name] = module diff --git a/src/tests/test_host_name.py b/src/tests/test_host_name.py deleted file mode 100644 index 8c5210d..0000000 --- a/src/tests/test_host_name.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/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 os -import tempfile -import unittest -from unittest import TestCase, mock - -from vyos import ConfigError -try: - from src.conf_mode import host_name -except ModuleNotFoundError: # for unittest.main() - import sys - sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from src.conf_mode import host_name - - -class TestHostName(TestCase): - - def test_get_config(self): - tests = [ - {'name': 'empty_hostname_and_domain', - 'host-name': '', - 'domain-name': '', - 'expected': {"hostname": 'vyos', "domain": '', "fqdn": 'vyos'}}, - {'name': 'empty_hostname', - 'host-name': '', - 'domain-name': 'localdomain', - 'expected': {"hostname": 'vyos', "domain": 'localdomain', "fqdn": 'vyos.localdomain'}}, - {'name': 'has_hostname', - 'host-name': 'router', - 'domain-name': '', - 'expected': {"hostname": 'router', "domain": '', "fqdn": 'router'}}, - {'name': 'has_hostname_and_domain', - 'host-name': 'router', - 'domain-name': 'localdomain', - 'expected': {"hostname": 'router', "domain": 'localdomain', "fqdn": 'router.localdomain'}}, - ] - for t in tests: - def mocked_return_value(path, default=None): - return t[path.split()[1]] - - with self.subTest(msg=t['name'], hostname=t['host-name'], domain=t['domain-name'], expected=t['expected']): - with mock.patch('vyos.config.Config.return_value', side_effect=mocked_return_value): - actual = host_name.get_config() - self.assertEqual(actual, t['expected']) - - - def test_verify(self): - tests = [ - {'name': 'valid_hostname', - 'config': {"hostname": 'vyos', "domain": 'localdomain', "fqdn": 'vyos.localdomain'}, - 'expected': None}, - {'name': 'invalid_hostname', - 'config': {"hostname": 'vyos..', "domain": '', "fqdn": ''}, - 'expected': ConfigError}, - {'name': 'invalid_hostname_length', - 'config': {"hostname": 'a'*64, "domain": '', "fqdn": ''}, - 'expected': ConfigError} - ] - for t in tests: - with self.subTest(msg=t['name'], config=t['config'], expected=t['expected']): - if t['expected'] is not None: - with self.assertRaises(t['expected']): - host_name.verify(t['config']) - else: - host_name.verify(t['config']) - - def test_generate(self): - tests = [ - {'name': 'has_old_entry', - 'has_old_entry': True, - 'config': {"hostname": 'router', "domain": 'localdomain', "fqdn": 'router.localdomain'}, - 'expected': ['127.0.1.1', 'router.localdomain']}, - {'name': 'no_old_entry', - 'has_old_entry': False, - 'config': {"hostname": 'router', "domain": 'localdomain', "fqdn": 'router.localdomain'}, - 'expected': ['127.0.1.1', 'router.localdomain']}, - ] - for t in tests: - with self.subTest(msg=t['name'], config=t['config'], has_old_entry=t['has_old_entry'], expected=t['expected']): - m = mock.MagicMock(return_value=b'debian') - with mock.patch('subprocess.check_output', m): - host_name.hosts_file = tempfile.mkstemp()[1] - if t['has_old_entry']: - with open(host_name.hosts_file, 'w') as f: - f.writelines(['\n127.0.1.1 {} # VyOS entry'.format('debian')]) - host_name.generate(t['config']) - if len(t['expected']) > 0: - self.assertTrue(os.path.isfile(host_name.hosts_file)) - with open(host_name.hosts_file) as f: - actual = f.read() - self.assertEqual( - t['expected'], actual.splitlines()[1].split()[0:2]) - os.remove(host_name.hosts_file) - else: - self.assertFalse(os.path.isfile(host_name.hosts_file)) - - - def test_apply(self): - tests = [ - {'name': 'valid_hostname', - 'config': {"hostname": 'router', "domain": 'localdomain', "fqdn": 'router.localdomain'}, - 'expected': [mock.call('hostnamectl set-hostname --static router.localdomain'), - mock.call('systemctl restart rsyslog.service')]} - ] - for t in tests: - with self.subTest(msg=t['name'], c=t['config'], expected=t['expected']): - with mock.patch('os.system') as os_system: - host_name.apply(t['config']) - os_system.assert_has_calls(t['expected']) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/tests/test_task_scheduler.py b/src/tests/test_task_scheduler.py deleted file mode 100644 index 084bd86..0000000 --- a/src/tests/test_task_scheduler.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/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 os -import tempfile -import unittest - -from vyos import ConfigError -try: - from src.conf_mode import task_scheduler -except ModuleNotFoundError: # for unittest.main() - import sys - sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from src.conf_mode import task_scheduler - - -class TestUpdateCrontab(unittest.TestCase): - - def test_verify(self): - tests = [ - {'name': 'one_task', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': None - }, - {'name': 'has_interval_and_spec', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '0 * * * *', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'has_no_interval_and_spec', - 'tasks': [{'name': 'aaa', 'interval': '', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'invalid_interval', - 'tasks': [{'name': 'aaa', 'interval': '1y', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'invalid_interval_min', - 'tasks': [{'name': 'aaa', 'interval': '61m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'invalid_interval_hour', - 'tasks': [{'name': 'aaa', 'interval': '25h', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'invalid_interval_day', - 'tasks': [{'name': 'aaa', 'interval': '32d', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': ConfigError - }, - {'name': 'no_executable', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '', 'args': ''}], - 'expected': ConfigError - }, - {'name': 'invalid_executable', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/aaa', 'args': ''}], - 'expected': ConfigError - } - ] - for t in tests: - with self.subTest(msg=t['name'], tasks=t['tasks'], expected=t['expected']): - if t['expected'] is not None: - with self.assertRaises(t['expected']): - task_scheduler.verify(t['tasks']) - else: - task_scheduler.verify(t['tasks']) - - def test_generate(self): - tests = [ - {'name': 'zero_task', - 'tasks': [], - 'expected': [] - }, - {'name': 'one_task', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': [ - '### Generated by vyos-update-crontab.py ###', - '*/60 * * * * root sg vyattacfg \"/bin/ls -l\"'] - }, - {'name': 'one_task_with_hour', - 'tasks': [{'name': 'aaa', 'interval': '10h', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': [ - '### Generated by vyos-update-crontab.py ###', - '0 */10 * * * root sg vyattacfg \"/bin/ls -l\"'] - }, - {'name': 'one_task_with_day', - 'tasks': [{'name': 'aaa', 'interval': '10d', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], - 'expected': [ - '### Generated by vyos-update-crontab.py ###', - '0 0 */10 * * root sg vyattacfg \"/bin/ls -l\"'] - }, - {'name': 'multiple_tasks', - 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}, - {'name': 'bbb', 'interval': '', 'spec': '0 0 * * *', 'executable': '/bin/ls', 'args': '-ltr'} - ], - 'expected': [ - '### Generated by vyos-update-crontab.py ###', - '*/60 * * * * root sg vyattacfg \"/bin/ls -l\"', - '0 0 * * * root sg vyattacfg \"/bin/ls -ltr\"'] - } - ] - for t in tests: - with self.subTest(msg=t['name'], tasks=t['tasks'], expected=t['expected']): - task_scheduler.crontab_file = tempfile.mkstemp()[1] - task_scheduler.generate(t['tasks']) - if len(t['expected']) > 0: - self.assertTrue(os.path.isfile(task_scheduler.crontab_file)) - with open(task_scheduler.crontab_file) as f: - actual = f.read() - self.assertEqual(t['expected'], actual.splitlines()) - os.remove(task_scheduler.crontab_file) - else: - self.assertFalse(os.path.isfile(task_scheduler.crontab_file)) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/utils/initial-setup b/src/utils/initial-setup deleted file mode 100644 index 37fc457..0000000 --- a/src/utils/initial-setup +++ /dev/null @@ -1,40 +0,0 @@ -#!/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-to-commands b/src/utils/vyos-config-to-commands deleted file mode 100755 index 8b50f7c..0000000 --- a/src/utils/vyos-config-to-commands +++ /dev/null @@ -1,29 +0,0 @@ -#!/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/validators/interface-address b/src/validators/interface-address deleted file mode 100755 index 4c20395..0000000 --- a/src/validators/interface-address +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv4-host $1 || ipaddrcheck --is-ipv6-host $1 diff --git a/src/validators/ip-address b/src/validators/ip-address deleted file mode 100755 index 51fb72c..0000000 --- a/src/validators/ip-address +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-any-single $1 diff --git a/src/validators/ip-host b/src/validators/ip-host deleted file mode 100755 index f2906e8..0000000 --- a/src/validators/ip-host +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-any-host $1 diff --git a/src/validators/ip-prefix b/src/validators/ip-prefix deleted file mode 100755 index e58aad3..0000000 --- a/src/validators/ip-prefix +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-any-net $1 diff --git a/src/validators/ipv4-address b/src/validators/ipv4-address deleted file mode 100755 index 872a764..0000000 --- a/src/validators/ipv4-address +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv4-single $1 diff --git a/src/validators/ipv4-host b/src/validators/ipv4-host deleted file mode 100755 index f42feff..0000000 --- a/src/validators/ipv4-host +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv4-host $1 diff --git a/src/validators/ipv4-prefix b/src/validators/ipv4-prefix deleted file mode 100755 index 8ec8a2c..0000000 --- a/src/validators/ipv4-prefix +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv4-net $1 diff --git a/src/validators/ipv6-address b/src/validators/ipv6-address deleted file mode 100755 index e5d68d7..0000000 --- a/src/validators/ipv6-address +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv6-single $1 diff --git a/src/validators/ipv6-host b/src/validators/ipv6-host deleted file mode 100755 index f7a7450..0000000 --- a/src/validators/ipv6-host +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv6-host $1 diff --git a/src/validators/ipv6-prefix b/src/validators/ipv6-prefix deleted file mode 100755 index e436163..0000000 --- a/src/validators/ipv6-prefix +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ipaddrcheck --is-ipv6-net $1 diff --git a/src/validators/numeric b/src/validators/numeric deleted file mode 100755 index 58a4fac..0000000 --- a/src/validators/numeric +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 -# -# numeric value validator -# -# Copyright (C) 2017 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 -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; If not, see <http://www.gnu.org/licenses/>. - -import sys -import argparse -import re - -parser = argparse.ArgumentParser() -parser.add_argument("-f", "--float", action="store_true", help="Accept floating point values") -group = parser.add_mutually_exclusive_group() -group.add_argument("-r", "--range", type=str, help="Check if the number is within range (inclusive), example: 1024-65535") -group.add_argument("-n", "--non-negative", action="store_true", help="") -parser.add_argument("number", type=str, help="Number to validate") - -args = parser.parse_args() - -# Try to load the argument -number = None -if args.float: - try: - number = float(args.number) - except: - print("{0} is not a valid floating point number".format(args.number), file=sys.stderr) - sys.exit(1) -else: - try: - number = int(args.number) - except: - print("{0} is not a valid integer number".format(args.number), file=sys.stderr) - sys.exit(1) - -if args.range: - try: - lower, upper = re.match(r'(\d+)\s*\-\s*(\d+)', args.range).groups() - lower, upper = int(lower), int(upper) - except: - print("{0} is not a valid number range",format(args.range), file=sys.stderr) - sys.exit(1) - - if (number < lower) or (number > upper): - print("Number {0} is not in the {1} range".format(number, args.range), file=sys.stderr) - sys.exit(1) -elif args.non_negative: - if number < 0: - print("Number should be non-negative", file=sys.stderr) - sys.exit(1) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 9348520..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -python/ -lxml -pylint -nose -coverage diff --git a/tests/data/interface-definitions/test-op.xml b/tests/data/interface-definitions/test-op.xml deleted file mode 100644 index 50bd686..0000000 --- a/tests/data/interface-definitions/test-op.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="foo"> - <properties> - <help>foo</help> - </properties> - <children> - <leafNode name="bar"> - <command>/usr/bin/bar</command> - <properties> - <help>bar</help> - <completionHelp> - <list>foo bar</list> - <path>interfaces tunnel</path> - <script>/usr/bin/foo</script> - </completionHelp> - </properties> - </leafNode> - </children> - </node> -</interfaceDefinition> diff --git a/tests/data/interface-definitions/test.xml b/tests/data/interface-definitions/test.xml deleted file mode 100644 index fbb302e..0000000 --- a/tests/data/interface-definitions/test.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0"?> -<interfaceDefinition> - <node name="foo"> - <properties> - <help>foo</help> - </properties> - <children> - <leafNode name="bar"> - <properties> - <help>bar</help> - <valueHelp> - <format>bar</format> - <description>bar</description> - </valueHelp> - <completionHelp> - <list>foo bar</list> - <path>interfaces tunnel</path> - <script>/usr/bin/foo</script> - </completionHelp> - </properties> - </leafNode> - </children> - </node> -</interfaceDefinition> |