summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/configd-include.json1
-rw-r--r--data/templates/frr/isis.frr.tmpl121
-rw-r--r--data/templates/openvpn/client.conf.tmpl2
-rw-r--r--data/templates/openvpn/server.conf.tmpl14
-rw-r--r--interface-definitions/include/isis-redistribute-ipv4.xml.i36
-rw-r--r--python/vyos/configdict.py2
-rw-r--r--python/vyos/configverify.py4
-rw-r--r--python/vyos/ifconfig/interface.py4
-rw-r--r--python/vyos/ifconfig/tunnel.py40
-rw-r--r--python/vyos/ifconfig/wireguard.py24
-rw-r--r--python/vyos/template.py23
-rw-r--r--python/vyos/validate.py16
-rw-r--r--smoketest/scripts/cli/base_accel_ppp_test.py2
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py3
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_openvpn.py26
-rwxr-xr-xsmoketest/scripts/cli/test_service_snmp.py2
-rwxr-xr-xsmoketest/scripts/cli/test_service_tftp-server.py2
-rwxr-xr-xsmoketest/scripts/cli/test_system_ntp.py8
-rwxr-xr-xsrc/conf_mode/dhcpv6_server.py5
-rwxr-xr-xsrc/conf_mode/dns_forwarding.py4
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py6
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py8
-rwxr-xr-xsrc/conf_mode/protocols_bfd.py8
-rwxr-xr-xsrc/conf_mode/protocols_isis.py152
-rwxr-xr-xsrc/conf_mode/service_ipoe-server.py3
-rwxr-xr-xsrc/conf_mode/snmp.py3
-rwxr-xr-xsrc/conf_mode/tftp_server.py2
-rwxr-xr-xsrc/conf_mode/vpn_l2tp.py4
-rwxr-xr-xsrc/op_mode/powerctrl.py6
-rw-r--r--src/tests/test_jinja_filters.py72
-rw-r--r--src/tests/test_template.py46
-rw-r--r--src/tests/test_validate.py23
32 files changed, 506 insertions, 166 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
index da6fb915f..2e44405ee 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -30,6 +30,7 @@
"nat.py",
"ntp.py",
"protocols_igmp.py",
+"protocols_isis.py",
"protocols_mpls.py",
"protocols_pim.py",
"protocols_rip.py",
diff --git a/data/templates/frr/isis.frr.tmpl b/data/templates/frr/isis.frr.tmpl
new file mode 100644
index 000000000..929f5bdb2
--- /dev/null
+++ b/data/templates/frr/isis.frr.tmpl
@@ -0,0 +1,121 @@
+!
+router isis {{ process }}
+ net {{ net }}
+{% if dynamic_hostname is defined %}
+ hostname dynamic
+{% endif %}
+{% if purge_originator is defined %}
+ purge-originator
+{% endif %}
+{% if set_attached_bit is defined %}
+ set-attached-bit
+{% endif %}
+{% if set_overload_bit is defined %}
+ set-overload-bit
+{% endif %}
+{% if domain_password is defined and domain_password.plaintext_password is defined and domain_password.plaintext_password is not none %}
+ domain-password clear {{ domain_password.plaintext_password }}
+{% endif %}
+{% if lsp_gen_interval is defined and lsp_gen_interval is not none %}
+ lsp-gen-interval {{ lsp_gen_interval }}
+{% endif %}
+{% if lsp_mtu is defined and lsp_mtu is not none %}
+ lsp-mtu {{ lsp_mtu }}
+{% endif %}
+{% if lsp_refresh_interval is defined and lsp_refresh_interval is not none %}
+ lsp-refresh-interval {{ lsp_refresh_interval }}
+{% endif %}
+{% if max_lsp_lifetime is defined and max_lsp_lifetime is not none %}
+ max-lsp-lifetime {{ max_lsp_lifetime }}
+{% endif %}
+{% if spf_interval is defined and spf_interval is not none %}
+ spf-interval {{ spf_interval }}
+{% endif %}
+{% if spf_delay_ietf is defined and spf_delay_ietf.init_delay is defined and spf_delay_ietf.init_delay is not none %}
+ spf-delay-ietf init-delay {{ spf_delay_ietf.init_delay }}
+{% endif %}
+{% if area_password is defined and area_password.md5 is defined and area_password.md5 is not none %}
+ area-password md5 {{ area_password.md5 }}
+{% elif area_password is defined and area_password.plaintext_password is defined and area_password.plaintext_password is not none %}
+ area-password clear {{ area_password.plaintext_password }}
+{% endif %}
+{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %}
+{% for level in default_information.originate.ipv4 if default_information.originate.ipv4 is defined %}
+ default-information originate ipv4 {{ level | replace('_', '-') }}
+{% endfor %}
+{% for level in default_information.originate.ipv6 if default_information.originate.ipv6 is defined %}
+ default-information originate ipv6 {{ level | replace('_', '-') }} always
+{% endfor %}
+{% endif %}
+{% if redistribute is defined and redistribute.ipv4 is defined and redistribute.ipv4 is not none %}
+{% for protocol in redistribute.ipv4 %}
+{% for level, level_config in redistribute.ipv4[protocol].items() %}
+{% if level_config.metric is defined and level_config.metric is not none %}
+ redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }}
+{% elif level_config.route_map is defined and level_config.route_map is not none %}
+ redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }}
+{% else %}
+ redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }}
+{% endif %}
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% if level is defined and level is not none %}
+{% if level == 'level-1' %}
+ is-type level-1
+{% elif level == 'level-2' %}
+ is-type level-2-only
+{% elif level == 'level-1-2' %}
+ is-type level-1-2
+{% endif %}
+{% endif %}
+!
+{% if interface_remove is defined and interface_remove is not none %}
+{% for iface in interface_remove %}
+interface {{ iface }}
+ no ip router isis
+{% endfor %}
+{% endif %}
+!
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+ ip router isis {{ process }}
+{% if iface_config.bfd is defined %}
+ isis bfd
+{% endif %}
+{% if iface_config.network is defined and iface_config.network.point_to_point is defined %}
+ isis network point-to-point
+{% endif %}
+{% if iface_config.circuit_type is defined %}
+ isis circuit-type {{ iface_config.circuit_type }}
+{% endif %}
+{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %}
+ isis hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.hello_multiplier is defined and iface_config.hello_multiplier is not none %}
+ isis hello-multiplier {{ iface_config.hello_multiplier }}
+{% endif %}
+{% if iface_config.hello_padding is defined %}
+ isis hello padding
+{% endif %}
+{% if iface_config.metric is defined and iface_config.metric is not none %}
+ isis metric {{ iface_config.metric }}
+{% endif %}
+{% if iface_config.passive is defined %}
+ isis passive
+{% endif %}
+{% if iface_config.password is defined and iface_config.password.plaintext_password is defined and iface_config.password.plaintext_password is not none %}
+ isis password clear {{ iface_config.password.plaintext_password }}
+{% endif %}
+{% if iface_config.priority is defined and iface_config.priority is not none %}
+ isis priority {{ iface_config.priority }}
+{% endif %}
+{% if iface_config.psnp_interval is defined and iface_config.psnp_interval is not none %}
+ isis psnp-interval {{ iface_config.psnp_interval }}
+{% endif %}
+{% if iface_config.three_way_handshake is defined %}
+ isis three-way-handshake
+{% endif %}
+{% endfor %}
+{% endif %}
diff --git a/data/templates/openvpn/client.conf.tmpl b/data/templates/openvpn/client.conf.tmpl
index fd3d3e68d..62387ef7c 100644
--- a/data/templates/openvpn/client.conf.tmpl
+++ b/data/templates/openvpn/client.conf.tmpl
@@ -13,7 +13,6 @@ push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }}"
iroute {{ network | address_from_cidr }} {{ network | netmask_from_cidr }}
{% endfor %}
{% endif %}
-
{# ipv6_remote is only set when IPv6 server is enabled #}
{% if ipv6_remote %}
# IPv6
@@ -27,7 +26,6 @@ push "route-ipv6 {{ route6 }}"
iroute {{ net6 }}
{% endfor %}
{% endif %}
-
{% if disable is defined %}
disable
{% endif %}
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index e8f7c3ab8..a510c3a84 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -13,7 +13,13 @@ dev-type {{ device_type }}
dev {{ ifname }}
persist-key
iproute /usr/libexec/vyos/system/unpriv-ip
-proto {{ protocol }}
+{% if protocol == 'tcp-active' %}
+proto tcp6-client
+{% elif protocol == 'tcp-passive' %}
+proto tcp6-server
+{% else %}
+proto udp6
+{% endif %}
{% if local_host is defined and local_host is not none %}
local {{ local_host }}
{% endif %}
@@ -65,7 +71,7 @@ topology p2p
{% elif server.topology is defined and server.topology is not none %}
topology {{ server.topology }}
{% endif %}
-{% for subnet in server.subnet if subnet | ipv4 %}
+{% for subnet in server.subnet if subnet | is_ipv4 %}
server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool
{# OpenVPN assigns the first IP address to its local interface so the pool used #}
{# in net30 topology - where each client receives a /30 must start from the second subnet #}
@@ -130,12 +136,12 @@ push "dhcp-option DNS6 {{ ns6 }}"
ping {{ keep_alive.interval }}
ping-restart {{ keep_alive.failure_count }}
-{% for laddr, laddr_conf in local_address.items() if laddr | ipv4 %}
+{% for laddr, laddr_conf in local_address.items() if laddr | is_ipv4 %}
{% if laddr_conf is defined and laddr_conf.subnet_mask is defined and laddr_conf.subnet_mask is not none %}
ifconfig {{ laddr }} {{ laddr_conf.subnet_mask }}
{% else %}
{% for raddr in remote_address %}
-{% if raddr | ipv4 %}
+{% if raddr | is_ipv4 %}
ifconfig {{ laddr }} {{ raddr }}
{% else %}
ifconfig-ipv6 {{ laddr }} {{ raddr }}
diff --git a/interface-definitions/include/isis-redistribute-ipv4.xml.i b/interface-definitions/include/isis-redistribute-ipv4.xml.i
index a40d8dfc2..fd5e75918 100644
--- a/interface-definitions/include/isis-redistribute-ipv4.xml.i
+++ b/interface-definitions/include/isis-redistribute-ipv4.xml.i
@@ -16,28 +16,14 @@
</constraint>
</properties>
</leafNode>
- <tagNode name="route-map">
+ <leafNode name="route-map">
<properties>
<help>Route map reference</help>
<completionHelp>
<path>policy route-map</path>
</completionHelp>
</properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>&lt;0-16777215&gt;</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
+ </leafNode>
</children>
</node>
<node name="level-2">
@@ -57,28 +43,14 @@
</constraint>
</properties>
</leafNode>
- <tagNode name="route-map">
+ <leafNode name="route-map">
<properties>
<help>Route map reference</help>
<completionHelp>
<path>policy route-map</path>
</completionHelp>
</properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>&lt;0-16777215&gt;</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
+ </leafNode>
</children>
</node>
<!-- included end -->
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py
index 0b03dfc7d..b14f96364 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -431,7 +431,7 @@ def get_accel_dict(config, base, chap_secrets):
Return a dictionary with the necessary interface config keys.
"""
from vyos.util import get_half_cpus
- from vyos.validate import is_ipv4
+ from vyos.template import is_ipv4
dict = config.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index babb0feb7..675dac5b1 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -51,7 +51,7 @@ def verify_mtu_ipv6(config):
recurring validation if the specified MTU can be used when IPv6 is
configured on the interface. IPv6 requires a 1280 bytes MTU.
"""
- from vyos.validate import is_ipv6
+ from vyos.template import is_ipv6
if 'mtu' in config:
# IPv6 minimum required link mtu
min_mtu = 1280
@@ -278,7 +278,7 @@ def verify_diffie_hellman_length(file, min_keysize):
prog = re.compile('\d+\s+bit')
if prog.search(out):
bits = prog.search(out)[0].split()[0]
- if int(min_keysize) >= int(bits):
+ if int(bits) >= int(min_keysize):
return True
return False
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 894410871..893623284 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -35,8 +35,8 @@ from vyos.configdict import dict_merge
from vyos.template import render
from vyos.util import mac2eui64
from vyos.util import dict_search
-from vyos.validate import is_ipv4
-from vyos.validate import is_ipv6
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
from vyos.validate import is_intf_addr_assigned
from vyos.validate import assert_boolean
from vyos.validate import assert_list
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 4122d1a2f..926d66c18 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -22,6 +22,10 @@ from vyos.ifconfig.interface import Interface
from vyos.ifconfig.afi import IP4, IP6
from vyos.validate import assert_list
+import random
+from random import seed, getrandbits
+from ipaddress import IPv6Network, IPv6Address
+
def enable_to_on(value):
if value == 'enable':
return 'on'
@@ -122,6 +126,16 @@ class _Tunnel(Interface):
@classmethod
def get_config(cls):
return dict(zip(cls.options, ['']*len(cls.options)))
+
+ def generate_link_local():
+ # Linux Kernel does not generate IPv6 Link Local address do to missing MAC
+ # We have to generate address manually and assign to interface
+ net = IPv6Network("FE80::/16")
+ rand_net = IPv6Network((net.network_address + (random.getrandbits(64 - net.prefixlen) << 64 ),64))
+ network = IPv6Network(rand_net)
+ address = str(IPv6Address(network.network_address + getrandbits(network.max_prefixlen - network.prefixlen)))+'/'+str(network.prefixlen)
+
+ return address
class GREIf(_Tunnel):
@@ -154,6 +168,12 @@ class GREIf(_Tunnel):
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname}'
delete = 'ip tunnel del {ifname}'
+
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
# GreTap also called GRE Bridge
@@ -219,6 +239,11 @@ class IP6GREIf(_Tunnel):
# sudo ip tunnel cha tun100 local: : 2
# Error: an IP address is expected rather than "::2"
# works if mode is explicit
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
class IPIPIf(_Tunnel):
@@ -270,6 +295,11 @@ class IPIP6If(_Tunnel):
create = 'ip -6 tunnel add {ifname} mode {type}'
change = 'ip -6 tunnel cha {ifname}'
delete = 'ip -6 tunnel del {ifname}'
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
class IP6IP6If(IPIP6If):
@@ -283,6 +313,11 @@ class IP6IP6If(IPIP6If):
ip = [IP6,]
default = {'type': 'ip6ip6'}
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
class SitIf(_Tunnel):
@@ -306,6 +341,11 @@ class SitIf(_Tunnel):
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname}'
delete = 'ip tunnel del {ifname}'
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
class Sit6RDIf(SitIf):
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index d8e89229d..5e9173349 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -24,7 +24,11 @@ from hurry.filesize import alternative
from vyos.config import Config
from vyos.ifconfig import Interface
from vyos.ifconfig import Operational
-from vyos.validate import is_ipv6
+from vyos.template import is_ipv6
+
+import random
+from random import seed, getrandbits
+from ipaddress import IPv6Network, IPv6Address
class WireGuardOperational(Operational):
def _dump(self):
@@ -168,7 +172,23 @@ class WireGuardIf(Interface):
options = Interface.options + \
['port', 'private_key', 'pubkey', 'psk',
'allowed_ips', 'fwmark', 'endpoint', 'keepalive']
-
+
+
+ def generate_link_local():
+ # Linux Kernel does not generate IPv6 Link Local address do to missing MAC
+ # We have to generate address manually and assign to interface
+ net = IPv6Network("FE80::/16")
+ rand_net = IPv6Network((net.network_address + (random.getrandbits(64 - net.prefixlen) << 64 ),64))
+ network = IPv6Network(rand_net)
+ address = str(IPv6Address(network.network_address + getrandbits(network.max_prefixlen - network.prefixlen)))+'/'+str(network.prefixlen)
+
+ return address
+
+ def _create(self):
+ super()._create(self)
+ # Assign generated IPv6 Link Local address to the interface
+ self.add_addr(self.generate_link_local())
+
def update(self, config):
""" General helper function which works on a dictionary retrived by
get_config_dict(). It's main intention is to consolidate the scattered
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 53e1dc1b5..58ba75972 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -124,7 +124,7 @@ def render(
##################################
@register_filter('address_from_cidr')
-def vyos_address_from_cidr(text):
+def address_from_cidr(text):
""" Take an IPv4/IPv6 CIDR prefix and convert the network to an "address".
Example:
192.0.2.0/24 -> 192.0.2.0, 2001:db8::/48 -> 2001:db8::
@@ -133,7 +133,7 @@ def vyos_address_from_cidr(text):
return str(ip_network(text).network_address)
@register_filter('netmask_from_cidr')
-def vyos_netmask_from_cidr(text):
+def netmask_from_cidr(text):
""" Take CIDR prefix and convert the prefix length to a "subnet mask".
Example:
- 192.0.2.0/24 -> 255.255.255.0
@@ -142,22 +142,27 @@ def vyos_netmask_from_cidr(text):
from ipaddress import ip_network
return str(ip_network(text).netmask)
-@register_filter('ipv4')
-def vyos_ipv4(text):
+@register_filter('is_ip')
+def is_ip(addr):
+ """ Check addr if it is an IPv4 or IPv6 address """
+ return is_ipv4(addr) or is_ipv6(addr)
+
+@register_filter('is_ipv4')
+def is_ipv4(text):
""" Filter IP address, return True on IPv4 address, False otherwise """
from ipaddress import ip_interface
try: return ip_interface(text).version == 4
except: return False
@register_filter('ipv6')
-def vyos_ipv6(text):
+def is_ipv6(text):
""" Filter IP address, return True on IPv6 address, False otherwise """
from ipaddress import ip_interface
try: return ip_interface(text).version == 6
except: return False
@register_filter('first_host_address')
-def vyos_first_host_address(text):
+def first_host_address(text):
""" Return first usable (host) IP address from given prefix.
Example:
- 10.0.0.0/24 -> 10.0.0.1
@@ -173,7 +178,7 @@ def vyos_first_host_address(text):
return str(addr.ip)
@register_filter('last_host_address')
-def vyos_last_host_address(text):
+def last_host_address(text):
""" Return first usable IP address from given prefix.
Example:
- 10.0.0.0/24 -> 10.0.0.254
@@ -190,7 +195,7 @@ def vyos_last_host_address(text):
return str(IPv6Network(addr).broadcast_address)
@register_filter('inc_ip')
-def vyos_inc_ip(address, increment):
+def inc_ip(address, increment):
""" Increment given IP address by 'increment'
Example (inc by 2):
@@ -201,7 +206,7 @@ def vyos_inc_ip(address, increment):
return str(ip_interface(address).ip + int(increment))
@register_filter('dec_ip')
-def vyos_dec_ip(address, decrement):
+def dec_ip(address, decrement):
""" Decrement given IP address by 'decrement'
Example (inc by 2):
diff --git a/python/vyos/validate.py b/python/vyos/validate.py
index 74b8adcfc..84a7bc2de 100644
--- a/python/vyos/validate.py
+++ b/python/vyos/validate.py
@@ -25,21 +25,10 @@ from vyos.util import cmd
# parameters with default will be left unset
# all other paramters will receive the value to check
-def is_ip(addr):
- """ Check addr if it is an IPv4 or IPv6 address """
- return is_ipv4(addr) or is_ipv6(addr)
-
-def is_ipv4(addr):
- from vyos.template import vyos_ipv4
- return vyos_ipv4(addr)
-
-def is_ipv6(addr):
- from vyos.template import vyos_ipv6
- return vyos_ipv6(addr)
-
def is_ipv6_link_local(addr):
""" Check if addrsss is an IPv6 link-local address. Returns True/False """
from ipaddress import IPv6Address
+ from vyos.template import is_ipv6
addr = addr.split('%')[0]
if is_ipv6(addr):
if IPv6Address(addr).is_link_local:
@@ -51,6 +40,7 @@ def _are_same_ip(one, two):
from socket import AF_INET
from socket import AF_INET6
from socket import inet_pton
+ from vyos.template import is_ipv4
# compare the binary representation of the IP
f_one = AF_INET if is_ipv4(one) else AF_INET6
s_two = AF_INET if is_ipv4(two) else AF_INET6
@@ -68,6 +58,7 @@ def _is_intf_addr_assigned(intf, address, netmask=''):
It can check both a single IP address (e.g. 192.0.2.1 or a assigned CIDR
address 192.0.2.1/24.
"""
+ from vyos.template import is_ipv4
# check if the requested address type is configured at all
# {
@@ -138,6 +129,7 @@ def is_subnet_connected(subnet, primary=False):
"""
from ipaddress import ip_address
from ipaddress import ip_network
+ from vyos.template import is_ipv6
# determine IP version (AF_INET or AF_INET6) depending on passed address
addr_type = netifaces.AF_INET
diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py
index e3e5071c1..e46a16137 100644
--- a/smoketest/scripts/cli/base_accel_ppp_test.py
+++ b/smoketest/scripts/cli/base_accel_ppp_test.py
@@ -20,10 +20,10 @@ from configparser import ConfigParser
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
+from vyos.template import is_ipv4
from vyos.util import cmd
from vyos.util import get_half_cpus
from vyos.util import process_named_running
-from vyos.validate import is_ipv4
class BasicAccelPPPTest:
class BaseTest(unittest.TestCase):
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 653cc91f9..e02424073 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -23,7 +23,8 @@ from vyos.ifconfig import Interface
from vyos.util import read_file
from vyos.util import cmd
from vyos.util import dict_search
-from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local
+from vyos.validate import is_intf_addr_assigned
+from vyos.validate import is_ipv6_link_local
class BasicInterfaceTest:
class BaseTest(unittest.TestCase):
diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py
index 63deef5c2..41e48c2f8 100755
--- a/smoketest/scripts/cli/test_interfaces_openvpn.py
+++ b/smoketest/scripts/cli/test_interfaces_openvpn.py
@@ -26,11 +26,11 @@ from vyos.configsession import ConfigSessionError
from vyos.util import cmd
from vyos.util import process_named_running
from vyos.util import read_file
-from vyos.template import vyos_inc_ip
-from vyos.template import vyos_address_from_cidr
-from vyos.template import vyos_netmask_from_cidr
-from vyos.template import vyos_last_host_address
-from vyos.template import vyos_inc_ip
+from vyos.template import address_from_cidr
+from vyos.template import dec_ip
+from vyos.template import inc_ip
+from vyos.template import last_host_address
+from vyos.template import netmask_from_cidr
PROCESS_NAME = 'openvpn'
@@ -319,7 +319,7 @@ class TestInterfacesOpenVPN(unittest.TestCase):
for ii in num_range:
interface = f'vtun{ii}'
subnet = f'192.0.{ii}.0/24'
- client_ip = vyos_inc_ip(subnet, '5')
+ client_ip = inc_ip(subnet, '5')
path = base_path + [interface]
port = str(2000 + ii)
@@ -349,11 +349,11 @@ class TestInterfacesOpenVPN(unittest.TestCase):
interface = f'vtun{ii}'
subnet = f'192.0.{ii}.0/24'
- start_addr = vyos_inc_ip(subnet, '2')
- stop_addr = vyos_last_host_address(subnet)
+ start_addr = inc_ip(subnet, '2')
+ stop_addr = last_host_address(subnet)
- client_ip = vyos_inc_ip(subnet, '5')
- client_netmask = vyos_netmask_from_cidr(subnet)
+ client_ip = inc_ip(subnet, '5')
+ client_netmask = netmask_from_cidr(subnet)
port = str(2000 + ii)
@@ -387,7 +387,7 @@ class TestInterfacesOpenVPN(unittest.TestCase):
self.assertIn(f'ifconfig-push {client_ip} {client_netmask}', client_config)
for route in client1_routes:
- self.assertIn('iroute {} {}'.format(vyos_address_from_cidr(route), vyos_netmask_from_cidr(route)), client_config)
+ self.assertIn('iroute {} {}'.format(address_from_cidr(route), netmask_from_cidr(route)), client_config)
self.assertTrue(process_named_running(PROCESS_NAME))
self.assertEqual(get_vrf(interface), vrf_name)
@@ -434,8 +434,8 @@ class TestInterfacesOpenVPN(unittest.TestCase):
for ii in num_range:
interface = f'vtun{ii}'
subnet = f'192.0.{ii}.0/24'
- start_addr = vyos_inc_ip(subnet, '4')
- stop_addr = vyos_last_host_address(subnet)
+ start_addr = inc_ip(subnet, '4')
+ stop_addr = dec_ip(last_host_address(subnet), '1')
port = str(2000 + ii)
config_file = f'/run/openvpn/{interface}.conf'
diff --git a/smoketest/scripts/cli/test_service_snmp.py b/smoketest/scripts/cli/test_service_snmp.py
index 067a3c76b..2c2e2181b 100755
--- a/smoketest/scripts/cli/test_service_snmp.py
+++ b/smoketest/scripts/cli/test_service_snmp.py
@@ -18,10 +18,10 @@ import os
import re
import unittest
-from vyos.validate import is_ipv4
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
+from vyos.template import is_ipv4
from vyos.util import read_file
from vyos.util import process_named_running
diff --git a/smoketest/scripts/cli/test_service_tftp-server.py b/smoketest/scripts/cli/test_service_tftp-server.py
index 92333392a..3210e622f 100755
--- a/smoketest/scripts/cli/test_service_tftp-server.py
+++ b/smoketest/scripts/cli/test_service_tftp-server.py
@@ -24,7 +24,7 @@ from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos.util import read_file
from vyos.util import process_named_running
-from vyos.validate import is_ipv6
+from vyos.template import is_ipv6
PROCESS_NAME = 'in.tftpd'
base_path = ['service', 'tftp-server']
diff --git a/smoketest/scripts/cli/test_system_ntp.py b/smoketest/scripts/cli/test_system_ntp.py
index 4f62b62d5..822a9aff2 100755
--- a/smoketest/scripts/cli/test_system_ntp.py
+++ b/smoketest/scripts/cli/test_system_ntp.py
@@ -20,8 +20,8 @@ import unittest
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
-from vyos.template import vyos_address_from_cidr
-from vyos.template import vyos_netmask_from_cidr
+from vyos.template import address_from_cidr
+from vyos.template import netmask_from_cidr
from vyos.util import read_file
from vyos.util import process_named_running
@@ -86,8 +86,8 @@ class TestSystemNTP(unittest.TestCase):
# Check generated client address configuration
for network in networks:
- network_address = vyos_address_from_cidr(network)
- network_netmask = vyos_netmask_from_cidr(network)
+ network_address = address_from_cidr(network)
+ network_netmask = netmask_from_cidr(network)
tmp = get_config_value(f'restrict {network_address}')[0]
test = f'mask {network_netmask} nomodify notrap nopeer'
diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py
index 1777d4db7..c2868e078 100755
--- a/src/conf_mode/dhcpv6_server.py
+++ b/src/conf_mode/dhcpv6_server.py
@@ -22,10 +22,11 @@ from copy import deepcopy
from vyos.config import Config
from vyos.template import render
+from vyos.template import is_ipv6
from vyos.util import call
-from vyos.validate import is_subnet_connected, is_ipv6
-from vyos import ConfigError
+from vyos.validate import is_subnet_connected
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py
index d0c2dd252..ef52cbfd3 100755
--- a/src/conf_mode/dns_forwarding.py
+++ b/src/conf_mode/dns_forwarding.py
@@ -21,12 +21,12 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.hostsd_client import Client as hostsd_client
+from vyos.template import render
+from vyos.template import is_ipv6
from vyos.util import call
from vyos.util import chown
from vyos.util import dict_search
-from vyos.template import render
from vyos.xml import defaults
-from vyos.validate import is_ipv6
from vyos import ConfigError
from vyos import airbag
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index b507afcc0..c23e79948 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -33,13 +33,13 @@ from vyos.configverify import verify_bridge_delete
from vyos.configverify import verify_diffie_hellman_length
from vyos.ifconfig import VTunIf
from vyos.template import render
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
from vyos.util import call
from vyos.util import chown
from vyos.util import chmod_600
from vyos.util import dict_search
from vyos.validate import is_addr_assigned
-from vyos.validate import is_ipv4
-from vyos.validate import is_ipv6
from vyos import ConfigError
from vyos import airbag
@@ -320,7 +320,7 @@ def verify(openvpn):
if 'local_port' in openvpn:
raise ConfigError('Cannot specify "local-port" with "tcp-active"')
- if 'remote_host' in openvpn:
+ if 'remote_host' not in openvpn:
raise ConfigError('Must specify "remote-host" with "tcp-active"')
# shared secret and TLS
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index 5561514bd..f1217b62d 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -23,12 +23,14 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import is_member
+from vyos.configdict import list_diff
+from vyos.dicts import FixedDict
from vyos.ifconfig import Interface, GREIf, GRETapIf, IPIPIf, IP6GREIf, IPIP6If, IP6IP6If, SitIf, Sit6RDIf
from vyos.ifconfig.afi import IP4, IP6
-from vyos.configdict import list_diff
-from vyos.validate import is_ipv4, is_ipv6
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
from vyos import ConfigError
-from vyos.dicts import FixedDict
+
from vyos import airbag
airbag.enable()
diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py
index c8e791c78..d1e551cad 100755
--- a/src/conf_mode/protocols_bfd.py
+++ b/src/conf_mode/protocols_bfd.py
@@ -20,11 +20,11 @@ from sys import exit
from copy import deepcopy
from vyos.config import Config
-from vyos.validate import is_ipv6_link_local, is_ipv6
-from vyos import ConfigError
-from vyos.util import call
+from vyos.template import is_ipv6
from vyos.template import render
-
+from vyos.util import call
+from vyos.validate import is_ipv6_link_local
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
new file mode 100755
index 000000000..d5e5b64fb
--- /dev/null
+++ b/src/conf_mode/protocols_isis.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2017-2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# 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
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.configdict import node_changed
+from vyos import ConfigError
+from vyos.util import call
+from vyos.template import render
+from vyos.template import render_to_string
+from vyos import frr
+from vyos import airbag
+airbag.enable()
+
+config_file = r'/tmp/isis.frr'
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['protocols', 'isis']
+
+ isis = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+
+ # determine which members have been removed
+ for instance in isis:
+ conf.set_level(base + [instance])
+ tmp = node_changed(conf, ['interface'])
+ if tmp:
+ isis[instance].update({'interface_remove': tmp})
+
+ return isis
+
+def verify(isis):
+ # bail out early - looks like removal from running config
+ if not isis:
+ return None
+
+ for process, isis_config in isis.items():
+ # If more then one isis process is defined (Frr only supports one)
+ # http://docs.frrouting.org/en/latest/isisd.html#isis-router
+ if len(isis) > 1:
+ raise ConfigError('Only one isis process can be definded')
+
+ # If network entity title (net) not defined
+ if 'net' not in isis_config:
+ raise ConfigError('ISIS net format iso is mandatory!')
+
+ # If interface not set
+ if 'interface' not in isis_config:
+ raise ConfigError('ISIS interface is mandatory!')
+
+ # If md5 and plaintext-password set at the same time
+ if 'area_password' in isis_config:
+ if {'md5', 'plaintext_password'} <= set(isis_config['encryption']):
+ raise ConfigError('Can not use both md5 and plaintext-password for ISIS area-password!')
+
+ # If one param from deley set, but not set others
+ if 'spf_delay_ietf' in isis_config:
+ required_timers = ['holddown', 'init_delay', 'long_delay', 'short_delay', 'time_to_learn']
+ exist_timers = []
+ for elm_timer in required_timers:
+ if elm_timer in isis_config['spf_delay_ietf']:
+ exist_timers.append(elm_timer)
+
+ exist_timers = set(required_timers).difference(set(exist_timers))
+ if len(exist_timers) > 0:
+ raise ConfigError('All types of delay must be specified: ' + ', '.join(exist_timers).replace('_', '-'))
+
+ # If Redistribute set, but level don't set
+ if 'redistribute' in isis_config:
+ proc_level = isis_config.get('level','').replace('-','_')
+ for proto, proto_config in isis_config.get('redistribute', {}).get('ipv4', {}).items():
+ if 'level_1' not in proto_config and 'level_2' not in proto_config:
+ raise ConfigError('Redistribute level-1 or level-2 should be specified in \"protocols isis {} redistribute ipv4 {}\"'.format(process, proto))
+ for redistribute_level in proto_config.keys():
+ if proc_level and proc_level != 'level_1_2' and proc_level != redistribute_level:
+ raise ConfigError('\"protocols isis {0} redistribute ipv4 {2} {3}\" cannot be used with \"protocols isis {0} level {1}\"'.format(process, proc_level, proto, redistribute_level))
+
+ return None
+
+def generate(isis):
+ if not isis:
+ isis['new_frr_config'] = ''
+ return None
+
+ # only one ISIS process is supported, so we can directly send the first key
+ # of the config dict
+ process = list(isis.keys())[0]
+ isis[process]['process'] = process
+
+ import pprint
+ pprint.pprint(isis[process])
+
+ # render(config) not needed, its only for debug
+ render(config_file, 'frr/isis.frr.tmpl', isis[process], trim_blocks=True)
+
+ isis['new_frr_config'] = render_to_string('frr/isis.frr.tmpl',
+ isis[process], trim_blocks=True)
+
+ return None
+
+def apply(isis):
+
+ # Save original configration prior to starting any commit actions
+ frr_cfg = {}
+ frr_cfg['original_config'] = frr.get_configuration(daemon='isisd')
+ frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], isis['new_frr_config'], from_re='router isis .*')
+
+ # Debugging
+ print('')
+ print('--------- DEBUGGING ----------')
+ print(f'Existing config:\n{frr_cfg["original_config"]}\n\n')
+ print(f'Replacement config:\n{isis["new_frr_config"]}\n\n')
+ print(f'Modified config:\n{frr_cfg["modified_config"]}\n\n')
+
+ # FRR mark configuration will test for syntax errors and throws an
+ # exception if any syntax errors is detected
+ frr.mark_configuration(frr_cfg['modified_config'])
+
+ # Commit resulting configuration to FRR, this will throw CommitError
+ # on failure
+ frr.reload_configuration(frr_cfg['modified_config'], daemon='isisd')
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py
index 87c7754f3..68c554360 100755
--- a/src/conf_mode/service_ipoe-server.py
+++ b/src/conf_mode/service_ipoe-server.py
@@ -23,8 +23,9 @@ from sys import exit
from vyos.config import Config
from vyos.template import render
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
from vyos.util import call, get_half_cpus
-from vyos.validate import is_ipv4
from vyos import ConfigError
from vyos import airbag
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index 117bf0274..3990e5735 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -22,8 +22,9 @@ from vyos.config import Config
from vyos.configverify import verify_vrf
from vyos.snmpv3_hashgen import plaintext_to_md5, plaintext_to_sha1, random
from vyos.template import render
+from vyos.template import is_ipv4
from vyos.util import call, chmod_755
-from vyos.validate import is_ipv4, is_addr_assigned
+from vyos.validate import is_addr_assigned
from vyos.version import get_version_data
from vyos import ConfigError, airbag
airbag.enable()
diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py
index cac95afe2..56e195b6a 100755
--- a/src/conf_mode/tftp_server.py
+++ b/src/conf_mode/tftp_server.py
@@ -25,9 +25,9 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.template import render
+from vyos.template import is_ipv4
from vyos.util import call
from vyos.util import chmod_755
-from vyos.validate import is_ipv4
from vyos.validate import is_addr_assigned
from vyos.xml import defaults
from vyos import ConfigError
diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index 465986d5b..80eb8daf2 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -25,10 +25,10 @@ from time import sleep
from ipaddress import ip_network
from vyos.config import Config
+from vyos.template import is_ipv4
+from vyos.template import render
from vyos.util import call, get_half_cpus
-from vyos.validate import is_ipv4
from vyos import ConfigError
-from vyos.template import render
from vyos import airbag
airbag.enable()
diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py
index 69af427ec..c000d7d06 100755
--- a/src/op_mode/powerctrl.py
+++ b/src/op_mode/powerctrl.py
@@ -34,7 +34,11 @@ def utc2local(datetime):
def parse_time(s):
try:
if re.match(r'^\d{1,2}$', s):
- return datetime.strptime(s, "%M").time()
+ if (int(s) > 59):
+ s = str(int(s)//60) + ":" + str(int(s)%60)
+ return datetime.strptime(s, "%H:%M").time()
+ else:
+ return datetime.strptime(s, "%M").time()
else:
return datetime.strptime(s, "%H:%M").time()
except ValueError:
diff --git a/src/tests/test_jinja_filters.py b/src/tests/test_jinja_filters.py
index acd7a5952..8a7241fe3 100644
--- a/src/tests/test_jinja_filters.py
+++ b/src/tests/test_jinja_filters.py
@@ -17,13 +17,13 @@
from unittest import TestCase
from ipaddress import ip_network
-from vyos.template import vyos_address_from_cidr
-from vyos.template import vyos_netmask_from_cidr
-from vyos.template import vyos_ipv4
-from vyos.template import vyos_ipv6
-from vyos.template import vyos_first_host_address
-from vyos.template import vyos_last_host_address
-from vyos.template import vyos_inc_ip
+from vyos.template import address_from_cidr
+from vyos.template import netmask_from_cidr
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
+from vyos.template import first_host_address
+from vyos.template import last_host_address
+from vyos.template import inc_ip
class TestTeamplteHelpers(TestCase):
def setUp(self):
@@ -31,39 +31,39 @@ class TestTeamplteHelpers(TestCase):
def test_helpers_from_cidr(self):
network_v4 = '192.0.2.0/26'
- self.assertEqual(vyos_address_from_cidr(network_v4), str(ip_network(network_v4).network_address))
- self.assertEqual(vyos_netmask_from_cidr(network_v4), str(ip_network(network_v4).netmask))
+ self.assertEqual(address_from_cidr(network_v4), str(ip_network(network_v4).network_address))
+ self.assertEqual(netmask_from_cidr(network_v4), str(ip_network(network_v4).netmask))
def test_helpers_ipv4(self):
- self.assertTrue(vyos_ipv4('192.0.2.1'))
- self.assertTrue(vyos_ipv4('192.0.2.0/24'))
- self.assertTrue(vyos_ipv4('192.0.2.1/32'))
- self.assertTrue(vyos_ipv4('10.255.1.2'))
- self.assertTrue(vyos_ipv4('10.255.1.0/24'))
- self.assertTrue(vyos_ipv4('10.255.1.2/32'))
- self.assertFalse(vyos_ipv4('2001:db8::'))
- self.assertFalse(vyos_ipv4('2001:db8::1'))
- self.assertFalse(vyos_ipv4('2001:db8::/64'))
+ self.assertTrue(is_ipv4('192.0.2.1'))
+ self.assertTrue(is_ipv4('192.0.2.0/24'))
+ self.assertTrue(is_ipv4('192.0.2.1/32'))
+ self.assertTrue(is_ipv4('10.255.1.2'))
+ self.assertTrue(is_ipv4('10.255.1.0/24'))
+ self.assertTrue(is_ipv4('10.255.1.2/32'))
+ self.assertFalse(is_ipv4('2001:db8::'))
+ self.assertFalse(is_ipv4('2001:db8::1'))
+ self.assertFalse(is_ipv4('2001:db8::/64'))
def test_helpers_ipv6(self):
- self.assertFalse(vyos_ipv6('192.0.2.1'))
- self.assertFalse(vyos_ipv6('192.0.2.0/24'))
- self.assertFalse(vyos_ipv6('192.0.2.1/32'))
- self.assertFalse(vyos_ipv6('10.255.1.2'))
- self.assertFalse(vyos_ipv6('10.255.1.0/24'))
- self.assertFalse(vyos_ipv6('10.255.1.2/32'))
- self.assertTrue(vyos_ipv6('2001:db8::'))
- self.assertTrue(vyos_ipv6('2001:db8::1'))
- self.assertTrue(vyos_ipv6('2001:db8::1/64'))
- self.assertTrue(vyos_ipv6('2001:db8::/32'))
- self.assertTrue(vyos_ipv6('2001:db8::/64'))
+ self.assertFalse(is_ipv6('192.0.2.1'))
+ self.assertFalse(is_ipv6('192.0.2.0/24'))
+ self.assertFalse(is_ipv6('192.0.2.1/32'))
+ self.assertFalse(is_ipv6('10.255.1.2'))
+ self.assertFalse(is_ipv6('10.255.1.0/24'))
+ self.assertFalse(is_ipv6('10.255.1.2/32'))
+ self.assertTrue(is_ipv6('2001:db8::'))
+ self.assertTrue(is_ipv6('2001:db8::1'))
+ self.assertTrue(is_ipv6('2001:db8::1/64'))
+ self.assertTrue(is_ipv6('2001:db8::/32'))
+ self.assertTrue(is_ipv6('2001:db8::/64'))
def test_helpers_first_host_address(self):
- self.assertEqual(vyos_first_host_address('10.0.0.0/24'), '10.0.0.1')
- self.assertEqual(vyos_first_host_address('10.0.0.128/25'), '10.0.0.129')
- self.assertEqual(vyos_first_host_address('10.0.0.200/29'), '10.0.0.201')
+ self.assertEqual(first_host_address('10.0.0.0/24'), '10.0.0.1')
+ self.assertEqual(first_host_address('10.0.0.128/25'), '10.0.0.129')
+ self.assertEqual(first_host_address('10.0.0.200/29'), '10.0.0.201')
- self.assertEqual(vyos_first_host_address('2001:db8::/64'), '2001:db8::')
- self.assertEqual(vyos_first_host_address('2001:db8::/112'), '2001:db8::')
- self.assertEqual(vyos_first_host_address('2001:db8::10/112'), '2001:db8::10')
- self.assertEqual(vyos_first_host_address('2001:db8::100/112'), '2001:db8::100')
+ self.assertEqual(first_host_address('2001:db8::/64'), '2001:db8::')
+ self.assertEqual(first_host_address('2001:db8::/112'), '2001:db8::')
+ self.assertEqual(first_host_address('2001:db8::10/112'), '2001:db8::10')
+ self.assertEqual(first_host_address('2001:db8::100/112'), '2001:db8::100')
diff --git a/src/tests/test_template.py b/src/tests/test_template.py
new file mode 100644
index 000000000..6dc2f075e
--- /dev/null
+++ b/src/tests/test_template.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# 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 vyos.template
+from unittest import TestCase
+
+class TestVyOSTemplate(TestCase):
+ def setUp(self):
+ pass
+
+ def test_is_ip(self):
+ self.assertTrue(vyos.template.is_ip('192.0.2.1'))
+ self.assertTrue(vyos.template.is_ip('2001:db8::1'))
+ self.assertFalse(vyos.template.is_ip('VyOS'))
+
+ def test_is_ipv4(self):
+ self.assertTrue(vyos.template.is_ipv4('192.0.2.1'))
+ self.assertTrue(vyos.template.is_ipv4('192.0.2.0/24'))
+ self.assertTrue(vyos.template.is_ipv4('192.0.2.1/32'))
+
+ self.assertFalse(vyos.template.is_ipv4('2001:db8::1'))
+ self.assertFalse(vyos.template.is_ipv4('2001:db8::/64'))
+ self.assertFalse(vyos.template.is_ipv4('VyOS'))
+
+ def test_is_ipv6(self):
+ self.assertTrue(vyos.template.is_ipv6('2001:db8::1'))
+ self.assertTrue(vyos.template.is_ipv6('2001:db8::/64'))
+ self.assertTrue(vyos.template.is_ipv6('2001:db8::1/64'))
+
+ self.assertFalse(vyos.template.is_ipv6('192.0.2.1'))
+ self.assertFalse(vyos.template.is_ipv6('192.0.2.0/24'))
+ self.assertFalse(vyos.template.is_ipv6('192.0.2.1/32'))
+ self.assertFalse(vyos.template.is_ipv6('VyOS'))
diff --git a/src/tests/test_validate.py b/src/tests/test_validate.py
index e9fe185ed..226e856a3 100644
--- a/src/tests/test_validate.py
+++ b/src/tests/test_validate.py
@@ -21,29 +21,6 @@ class TestVyOSValidate(TestCase):
def setUp(self):
pass
- def test_is_ip(self):
- self.assertTrue(vyos.validate.is_ip('192.0.2.1'))
- self.assertTrue(vyos.validate.is_ip('2001:db8::1'))
- self.assertFalse(vyos.validate.is_ip('VyOS'))
-
- def test_is_ipv4(self):
- self.assertTrue(vyos.validate.is_ipv4('192.0.2.1'))
- self.assertTrue(vyos.validate.is_ipv4('192.0.2.0/24'))
- self.assertTrue(vyos.validate.is_ipv4('192.0.2.1/32'))
-
- self.assertFalse(vyos.validate.is_ipv4('2001:db8::1'))
- self.assertFalse(vyos.validate.is_ipv4('2001:db8::/64'))
- self.assertFalse(vyos.validate.is_ipv4('VyOS'))
-
- def test_is_ipv6(self):
- self.assertFalse(vyos.validate.is_ipv6('192.0.2.1'))
- self.assertFalse(vyos.validate.is_ipv6('192.0.2.0/24'))
- self.assertFalse(vyos.validate.is_ipv6('192.0.2.1/32'))
- self.assertTrue(vyos.validate.is_ipv6('2001:db8::1'))
- self.assertTrue(vyos.validate.is_ipv6('2001:db8::/64'))
- self.assertTrue(vyos.validate.is_ipv6('2001:db8::1/64'))
- self.assertFalse(vyos.validate.is_ipv6('VyOS'))
-
def test_is_ipv6_link_local(self):
self.assertFalse(vyos.validate.is_ipv6_link_local('169.254.0.1'))
self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::'))