summaryrefslogtreecommitdiff
path: root/src/migration-scripts/interfaces
diff options
context:
space:
mode:
Diffstat (limited to 'src/migration-scripts/interfaces')
-rwxr-xr-xsrc/migration-scripts/interfaces/0-to-1118
-rwxr-xr-xsrc/migration-scripts/interfaces/1-to-263
-rwxr-xr-xsrc/migration-scripts/interfaces/10-to-1155
-rwxr-xr-xsrc/migration-scripts/interfaces/11-to-1258
-rwxr-xr-xsrc/migration-scripts/interfaces/2-to-343
-rwxr-xr-xsrc/migration-scripts/interfaces/3-to-497
-rwxr-xr-xsrc/migration-scripts/interfaces/4-to-5112
-rwxr-xr-xsrc/migration-scripts/interfaces/5-to-6123
-rwxr-xr-xsrc/migration-scripts/interfaces/6-to-763
-rwxr-xr-xsrc/migration-scripts/interfaces/7-to-876
-rwxr-xr-xsrc/migration-scripts/interfaces/8-to-952
-rwxr-xr-xsrc/migration-scripts/interfaces/9-to-1064
12 files changed, 924 insertions, 0 deletions
diff --git a/src/migration-scripts/interfaces/0-to-1 b/src/migration-scripts/interfaces/0-to-1
new file mode 100755
index 000000000..ee4d6b82c
--- /dev/null
+++ b/src/migration-scripts/interfaces/0-to-1
@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+
+# Change syntax of bridge interface
+# - move interface based bridge-group to actual bridge (de-nest)
+# - make stp and igmp-snooping nodes valueless
+# https://phabricator.vyos.net/T1556
+
+import sys
+from vyos.configtree import ConfigTree
+
+def migrate_bridge(config, tree, intf):
+ # check if bridge-group exists
+ tree_bridge = tree + ['bridge-group']
+ if config.exists(tree_bridge):
+ bridge = config.return_value(tree_bridge + ['bridge'])
+ # create new bridge member interface
+ config.set(base + [bridge, 'member', 'interface', intf])
+ # format as tag node to avoid loading problems
+ config.set_tag(base + [bridge, 'member', 'interface'])
+
+ # cost: migrate if configured
+ tree_cost = tree + ['bridge-group', 'cost']
+ if config.exists(tree_cost):
+ cost = config.return_value(tree_cost)
+ # set new node
+ config.set(base + [bridge, 'member', 'interface', intf, 'cost'], value=cost)
+
+ # priority: migrate if configured
+ tree_priority = tree + ['bridge-group', 'priority']
+ if config.exists(tree_priority):
+ priority = config.return_value(tree_priority)
+ # set new node
+ config.set(base + [bridge, 'member', 'interface', intf, 'priority'], value=priority)
+
+ # Delete the old bridge-group assigned to an interface
+ config.delete(tree_bridge)
+
+
+if __name__ == '__main__':
+ 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)
+ base = ['interfaces', 'bridge']
+
+ if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+ else:
+ #
+ # make stp and igmp-snooping nodes valueless
+ #
+ for br in config.list_nodes(base):
+ # STP: check if enabled
+ if config.exists(base + [br, 'stp']):
+ stp_val = config.return_value(base + [br, 'stp'])
+ # STP: delete node with old syntax
+ config.delete(base + [br, 'stp'])
+ # STP: set new node - if enabled
+ if stp_val == "true":
+ config.set(base + [br, 'stp'], value=None)
+
+ # igmp-snooping: check if enabled
+ if config.exists(base + [br, 'igmp-snooping', 'querier']):
+ igmp_val = config.return_value(base + [br, 'igmp-snooping', 'querier'])
+ # igmp-snooping: delete node with old syntax
+ config.delete(base + [br, 'igmp-snooping', 'querier'])
+ # igmp-snooping: set new node - if enabled
+ if igmp_val == "enable":
+ config.set(base + [br, 'igmp', 'querier'], value=None)
+
+ #
+ # move interface based bridge-group to actual bridge (de-nest)
+ #
+ bridge_types = ['bonding', 'ethernet', 'l2tpv3', 'openvpn', 'vxlan', 'wireless']
+ for type in bridge_types:
+ if not config.exists(['interfaces', type]):
+ continue
+
+ for interface in config.list_nodes(['interfaces', type]):
+ # check if bridge-group exists
+ bridge_group = ['interfaces', type, interface]
+ if config.exists(bridge_group + ['bridge-group']):
+ migrate_bridge(config, bridge_group, interface)
+
+ # We also need to migrate VLAN interfaces
+ vlan_base = ['interfaces', type, interface, 'vif']
+ if config.exists(vlan_base):
+ for vlan in config.list_nodes(vlan_base):
+ intf = "{}.{}".format(interface, vlan)
+ migrate_bridge(config, vlan_base + [vlan], intf)
+
+ # And then we have service VLANs (vif-s) interfaces
+ vlan_base = ['interfaces', type, interface, 'vif-s']
+ if config.exists(vlan_base):
+ for vif_s in config.list_nodes(vlan_base):
+ intf = "{}.{}".format(interface, vif_s)
+ migrate_bridge(config, vlan_base + [vif_s], intf)
+
+ # Every service VLAN can have multiple customer VLANs (vif-c)
+ vlan_c = ['interfaces', type, interface, 'vif-s', vif_s, 'vif-c']
+ if config.exists(vlan_c):
+ for vif_c in config.list_nodes(vlan_c):
+ intf = "{}.{}.{}".format(interface, vif_s, vif_c)
+ migrate_bridge(config, vlan_c + [vif_c], intf)
+
+ 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/interfaces/1-to-2 b/src/migration-scripts/interfaces/1-to-2
new file mode 100755
index 000000000..050137318
--- /dev/null
+++ b/src/migration-scripts/interfaces/1-to-2
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+
+# Change syntax of bond interface
+# - move interface based bond-group to actual bond (de-nest)
+# https://phabricator.vyos.net/T1614
+
+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)
+base = ['interfaces', 'bonding']
+
+if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+else:
+ #
+ # move interface based bond-group to actual bond (de-nest)
+ #
+ for intf in config.list_nodes(['interfaces', 'ethernet']):
+ # check if bond-group exists
+ if config.exists(['interfaces', 'ethernet', intf, 'bond-group']):
+ # get configured bond interface
+ bond = config.return_value(['interfaces', 'ethernet', intf, 'bond-group'])
+ # delete old interface asigned (nested) bond group
+ config.delete(['interfaces', 'ethernet', intf, 'bond-group'])
+ # create new bond member interface
+ config.set(base + [bond, 'member', 'interface'], value=intf, replace=False)
+
+ #
+ # some combinations were allowed in the past from a CLI perspective
+ # but the kernel overwrote them - remove from CLI to not confuse the users.
+ # In addition new consitency checks are in place so users can't repeat the
+ # mistake. One of those nice issues is https://phabricator.vyos.net/T532
+ for bond in config.list_nodes(base):
+ if config.exists(base + [bond, 'arp-monitor', 'interval']) and config.exists(base + [bond, 'mode']):
+ mode = config.return_value(base + [bond, 'mode'])
+ if mode in ['802.3ad', 'transmit-load-balance', 'adaptive-load-balance']:
+ intvl = int(config.return_value(base + [bond, 'arp-monitor', 'interval']))
+ if intvl > 0:
+ # this is not allowed and the linux kernel replies with:
+ # option arp_interval: mode dependency failed, not supported in mode 802.3ad(4)
+ # option arp_interval: mode dependency failed, not supported in mode balance-alb(6)
+ # option arp_interval: mode dependency failed, not supported in mode balance-tlb(5)
+ #
+ # so we simply disable arp_interval by setting it to 0 and miimon will take care about the link
+ config.set(base + [bond, 'arp-monitor', 'interval'], value='0')
+
+ 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/interfaces/10-to-11 b/src/migration-scripts/interfaces/10-to-11
new file mode 100755
index 000000000..6b8e49ed9
--- /dev/null
+++ b/src/migration-scripts/interfaces/10-to-11
@@ -0,0 +1,55 @@
+#!/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/>.
+
+# rename WWAN (wirelessmodem) serial interface from non persistent ttyUSB2 to
+# a bus like name, e.g. "usb0b1.3p1.3"
+
+import os
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ base = ['interfaces', 'wirelessmodem']
+ if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+ for wwan in config.list_nodes(base):
+ if config.exists(base + [wwan, 'device']):
+ device = config.return_value(base + [wwan, 'device'])
+
+ for root, dirs, files in os.walk('/dev/serial/by-bus'):
+ for file in files:
+ device_file = os.path.realpath(os.path.join(root, file))
+ if os.path.basename(device_file) == device:
+ config.set(base + [wwan, 'device'], value=file, replace=True)
+
+ 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))
+ exit(1)
diff --git a/src/migration-scripts/interfaces/11-to-12 b/src/migration-scripts/interfaces/11-to-12
new file mode 100755
index 000000000..0dad24642
--- /dev/null
+++ b/src/migration-scripts/interfaces/11-to-12
@@ -0,0 +1,58 @@
+#!/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/>.
+
+# - rename 'dhcpv6-options prefix-delegation' from single node to a new tag node
+# 'dhcpv6-options pd 0'
+# - delete 'sla-len' from CLI - value is calculated on demand
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ for type in config.list_nodes(['interfaces']):
+ for interface in config.list_nodes(['interfaces', type]):
+ # cache current config tree
+ base_path = ['interfaces', type, interface, 'dhcpv6-options']
+ old_base = base_path + ['prefix-delegation']
+ new_base = base_path + ['pd']
+ if config.exists(old_base):
+ config.set(new_base)
+ config.set_tag(new_base)
+ config.copy(old_base, new_base + ['0'])
+ config.delete(old_base)
+
+ for pd in config.list_nodes(new_base):
+ for tmp in config.list_nodes(new_base + [pd, 'interface']):
+ sla_config = new_base + [pd, 'interface', tmp, 'sla-len']
+ if config.exists(sla_config):
+ config.delete(sla_config)
+
+ 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))
+ exit(1)
diff --git a/src/migration-scripts/interfaces/2-to-3 b/src/migration-scripts/interfaces/2-to-3
new file mode 100755
index 000000000..a63a54cdf
--- /dev/null
+++ b/src/migration-scripts/interfaces/2-to-3
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+# Change syntax of openvpn encryption settings
+# - move cipher from encryption to encryption cipher
+# https://phabricator.vyos.net/T1704
+
+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)
+base = ['interfaces', 'openvpn']
+
+if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+else:
+ #
+ # move cipher from "encryption" to "encryption cipher"
+ #
+ for intf in config.list_nodes(['interfaces', 'openvpn']):
+ # Check if encryption is set
+ if config.exists(['interfaces', 'openvpn', intf, 'encryption']):
+ # Get cipher used
+ cipher = config.return_value(['interfaces', 'openvpn', intf, 'encryption'])
+ # Delete old syntax
+ config.delete(['interfaces', 'openvpn', intf, 'encryption'])
+ # Add new syntax to config
+ config.set(['interfaces', 'openvpn', intf, 'encryption', 'cipher'], value=cipher)
+ 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/interfaces/3-to-4 b/src/migration-scripts/interfaces/3-to-4
new file mode 100755
index 000000000..e3bd25a68
--- /dev/null
+++ b/src/migration-scripts/interfaces/3-to-4
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+
+# Change syntax of wireless interfaces
+# Migrate boolean nodes to valueless
+
+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)
+base = ['interfaces', 'wireless']
+
+if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+else:
+ for wifi in config.list_nodes(base):
+ # as converting a node to bool is always the same, we can script it
+ to_bool_nodes = ['capabilities ht 40MHz-incapable',
+ 'capabilities ht auto-powersave',
+ 'capabilities ht delayed-block-ack',
+ 'capabilities ht dsss-cck-40',
+ 'capabilities ht greenfield',
+ 'capabilities ht ldpc',
+ 'capabilities ht lsig-protection',
+ 'capabilities ht stbc tx',
+ 'capabilities require-ht',
+ 'capabilities require-vht',
+ 'capabilities vht antenna-pattern-fixed',
+ 'capabilities vht ldpc',
+ 'capabilities vht stbc tx',
+ 'capabilities vht tx-powersave',
+ 'capabilities vht vht-cf',
+ 'expunge-failing-stations',
+ 'isolate-stations']
+
+ for node in to_bool_nodes:
+ if config.exists(base + [wifi, node]):
+ tmp = config.return_value(base + [wifi, node])
+ # delete old node
+ config.delete(base + [wifi, node])
+ # set new node if it was enabled
+ if tmp == 'true':
+ # OLD CLI used camel casing in 40MHz-incapable which is
+ # not supported in the new backend. Convert all to lower-case
+ config.set(base + [wifi, node.lower()])
+
+ # Remove debug node
+ if config.exists(base + [wifi, 'debug']):
+ config.delete(base + [wifi, 'debug'])
+
+ # RADIUS servers
+ if config.exists(base + [wifi, 'security', 'wpa', 'radius-server']):
+ for server in config.list_nodes(base + [wifi, 'security', 'wpa', 'radius-server']):
+ base_server = base + [wifi, 'security', 'wpa', 'radius-server', server]
+
+ # Migrate RADIUS shared secret
+ if config.exists(base_server + ['secret']):
+ key = config.return_value(base_server + ['secret'])
+ # write new configuration node
+ config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'key'], value=key)
+ # format as tag node
+ config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server'])
+
+ # Migrate RADIUS port
+ if config.exists(base_server + ['port']):
+ port = config.return_value(base_server + ['port'])
+ # write new configuration node
+ config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'port'], value=port)
+ # format as tag node
+ config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server'])
+
+ # Migrate RADIUS accounting
+ if config.exists(base_server + ['accounting']):
+ port = config.return_value(base_server + ['accounting'])
+ # write new configuration node
+ config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'accounting'])
+ # format as tag node
+ config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server'])
+
+ # delete old radius-server nodes
+ config.delete(base + [wifi, 'security', 'wpa', 'radius-server'])
+
+ 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/interfaces/4-to-5 b/src/migration-scripts/interfaces/4-to-5
new file mode 100755
index 000000000..2a42c60ff
--- /dev/null
+++ b/src/migration-scripts/interfaces/4-to-5
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+
+# De-nest PPPoE interfaces
+# Migrate boolean nodes to valueless
+
+import sys
+from vyos.configtree import ConfigTree
+
+def migrate_dialer(config, tree, intf):
+ for pppoe in config.list_nodes(tree):
+ # assemble string, 0 -> pppoe0
+ new_base = ['interfaces', 'pppoe']
+ pppoe_base = new_base + ['pppoe' + pppoe]
+ config.set(new_base)
+ # format as tag node to avoid loading problems
+ config.set_tag(new_base)
+
+ # Copy the entire old node to the new one before migrating individual
+ # parts
+ config.copy(tree + [pppoe], pppoe_base)
+
+ # Instead of letting the user choose between auto and none
+ # where auto is default, it makes more sesne to just offer
+ # an option to disable the default behavior (declutter CLI)
+ if config.exists(pppoe_base + ['name-server']):
+ tmp = config.return_value(pppoe_base + ['name-server'])
+ if tmp == "none":
+ config.set(pppoe_base + ['no-peer-dns'])
+ config.delete(pppoe_base + ['name-server'])
+
+ # Migrate user-id and password nodes under an 'authentication'
+ # node
+ if config.exists(pppoe_base + ['user-id']):
+ user = config.return_value(pppoe_base + ['user-id'])
+ config.set(pppoe_base + ['authentication', 'user'], value=user)
+ config.delete(pppoe_base + ['user-id'])
+
+ if config.exists(pppoe_base + ['password']):
+ pwd = config.return_value(pppoe_base + ['password'])
+ config.set(pppoe_base + ['authentication', 'password'], value=pwd)
+ config.delete(pppoe_base + ['password'])
+
+ # remove enable-ipv6 node and rather place it under ipv6 node
+ if config.exists(pppoe_base + ['enable-ipv6']):
+ config.set(pppoe_base + ['ipv6', 'enable'])
+ config.delete(pppoe_base + ['enable-ipv6'])
+
+ # Source interface migration
+ config.set(pppoe_base + ['source-interface'], value=intf)
+
+ # Remove IPv6 router-advert nodes as this makes no sense on a
+ # client diale rinterface to send RAs back into the network
+ # https://phabricator.vyos.net/T2055
+ ipv6_ra = pppoe_base + ['ipv6', 'router-advert']
+ if config.exists(ipv6_ra):
+ config.delete(ipv6_ra)
+
+
+if __name__ == '__main__':
+ if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = sys.argv[1]
+
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ pppoe_links = ['bonding', 'ethernet']
+
+ for link_type in pppoe_links:
+ if not config.exists(['interfaces', link_type]):
+ continue
+
+ for interface in config.list_nodes(['interfaces', link_type]):
+ # check if PPPoE exists
+ base_if = ['interfaces', link_type, interface]
+ pppoe_if = base_if + ['pppoe']
+ if config.exists(pppoe_if):
+ for dialer in config.list_nodes(pppoe_if):
+ migrate_dialer(config, pppoe_if, interface)
+
+ # Delete old PPPoE interface
+ config.delete(pppoe_if)
+
+ # bail out early if there are no VLAN interfaces to migrate
+ if not config.exists(base_if + ['vif']):
+ continue
+
+ # Migrate PPPoE interfaces attached to a VLAN
+ for vlan in config.list_nodes(base_if + ['vif']):
+ vlan_if = base_if + ['vif', vlan]
+ pppoe_if = vlan_if + ['pppoe']
+ if config.exists(pppoe_if):
+ for dialer in config.list_nodes(pppoe_if):
+ intf = "{}.{}".format(interface, vlan)
+ migrate_dialer(config, pppoe_if, intf)
+
+ # Delete old PPPoE interface
+ config.delete(pppoe_if)
+
+ # Add interface description that this is required for PPPoE
+ if not config.exists(vlan_if + ['description']):
+ config.set(vlan_if + ['description'], value='PPPoE link interface')
+
+ 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/interfaces/5-to-6 b/src/migration-scripts/interfaces/5-to-6
new file mode 100755
index 000000000..1291751d8
--- /dev/null
+++ b/src/migration-scripts/interfaces/5-to-6
@@ -0,0 +1,123 @@
+#!/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/>.
+
+# Migrate IPv6 router advertisments from a nested interface configuration to
+# a denested "service router-advert"
+
+import sys
+from vyos.configtree import ConfigTree
+
+def copy_rtradv(c, old_base, interface):
+ base = ['service', 'router-advert', 'interface']
+
+ if c.exists(old_base):
+ if not c.exists(base):
+ c.set(base)
+ c.set_tag(base)
+
+ # take the old node as a whole and copy it to new new path,
+ # additional migrations will be done afterwards
+ new_base = base + [interface]
+ c.copy(old_base, new_base)
+ c.delete(old_base)
+
+ # cur-hop-limit has been renamed to hop-limit
+ if c.exists(new_base + ['cur-hop-limit']):
+ c.rename(new_base + ['cur-hop-limit'], 'hop-limit')
+
+ bool_cleanup = ['managed-flag', 'other-config-flag']
+ for bool in bool_cleanup:
+ if c.exists(new_base + [bool]):
+ tmp = c.return_value(new_base + [bool])
+ c.delete(new_base + [bool])
+ if tmp == 'true':
+ c.set(new_base + [bool])
+
+ # max/min interval moved to subnode
+ intervals = ['max-interval', 'min-interval']
+ for interval in intervals:
+ if c.exists(new_base + [interval]):
+ tmp = c.return_value(new_base + [interval])
+ c.delete(new_base + [interval])
+ min_max = interval.split('-')[0]
+ c.set(new_base + ['interval', min_max], value=tmp)
+
+ # cleanup boolean nodes in individual prefix
+ prefix_base = new_base + ['prefix']
+ if c.exists(prefix_base):
+ for prefix in config.list_nodes(prefix_base):
+ if c.exists(prefix_base + [prefix, 'autonomous-flag']):
+ tmp = c.return_value(prefix_base + [prefix, 'autonomous-flag'])
+ c.delete(prefix_base + [prefix, 'autonomous-flag'])
+ if tmp == 'false':
+ c.set(prefix_base + [prefix, 'no-autonomous-flag'])
+
+ if c.exists(prefix_base + [prefix, 'on-link-flag']):
+ tmp = c.return_value(prefix_base + [prefix, 'on-link-flag'])
+ c.delete(prefix_base + [prefix, 'on-link-flag'])
+ if tmp == 'true':
+ c.set(prefix_base + [prefix, 'on-link-flag'])
+
+ # router advertisement can be individually disabled per interface
+ # the node has been renamed from send-advert {true | false} to no-send-advert
+ if c.exists(new_base + ['send-advert']):
+ tmp = c.return_value(new_base + ['send-advert'])
+ c.delete(new_base + ['send-advert'])
+ if tmp == 'false':
+ c.set(new_base + ['no-send-advert'])
+
+ # link-mtu advertisement was formerly disabled by setting its value to 0
+ # ... this makes less sense - if it should not be send, just do not
+ # configure it
+ if c.exists(new_base + ['link-mtu']):
+ tmp = c.return_value(new_base + ['link-mtu'])
+ if tmp == '0':
+ c.delete(new_base + ['link-mtu'])
+
+if __name__ == '__main__':
+ if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = sys.argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ # list all individual interface types like dummy, ethernet and so on
+ for if_type in config.list_nodes(['interfaces']):
+ base_if_type = ['interfaces', if_type]
+
+ # for every individual interface we need to check if there is an
+ # ipv6 ra configured ... and also for every VIF (VLAN) interface
+ for intf in config.list_nodes(base_if_type):
+ old_base = base_if_type + [intf, 'ipv6', 'router-advert']
+ copy_rtradv(config, old_base, intf)
+
+ vif_base = base_if_type + [intf, 'vif']
+ if config.exists(vif_base):
+ for vif in config.list_nodes(vif_base):
+ old_base = vif_base + [vif, 'ipv6', 'router-advert']
+ vlan_name = f'{intf}.{vif}'
+ copy_rtradv(config, old_base, vlan_name)
+
+ 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/interfaces/6-to-7 b/src/migration-scripts/interfaces/6-to-7
new file mode 100755
index 000000000..220c7e601
--- /dev/null
+++ b/src/migration-scripts/interfaces/6-to-7
@@ -0,0 +1,63 @@
+#!/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/>.
+
+# Remove network provider name from CLI and rather use provider APN from CLI
+
+import sys
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = sys.argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ base = ['interfaces', 'wirelessmodem']
+
+ if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+
+ # list all individual wwan/wireless modem interfaces
+ for i in config.list_nodes(base):
+ iface = base + [i]
+
+ # only three carries have been supported in the past, thus
+ # this will be fairly simple \o/ - and only one (AT&T) did
+ # configure an APN
+ if config.exists(iface + ['network']):
+ network = config.return_value(iface + ['network'])
+ if network == "att":
+ apn = 'isp.cingular'
+ config.set(iface + ['apn'], value=apn)
+
+ config.delete(iface + ['network'])
+
+ # synchronize DNS configuration with PPPoE interfaces to have a
+ # uniform CLI experience
+ if config.exists(iface + ['no-dns']):
+ config.rename(iface + ['no-dns'], 'no-peer-dns')
+
+ 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/interfaces/7-to-8 b/src/migration-scripts/interfaces/7-to-8
new file mode 100755
index 000000000..a4051301f
--- /dev/null
+++ b/src/migration-scripts/interfaces/7-to-8
@@ -0,0 +1,76 @@
+#!/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/>.
+
+# Split WireGuard endpoint into address / port nodes to make use of common
+# validators
+
+import os
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+from vyos.util import chown, chmod_750
+
+def migrate_default_keys():
+ kdir = r'/config/auth/wireguard'
+ if os.path.exists(f'{kdir}/private.key') and not os.path.exists(f'{kdir}/default/private.key'):
+ location = f'{kdir}/default'
+ if not os.path.exists(location):
+ os.makedirs(location)
+
+ chown(location, 'root', 'vyattacfg')
+ chmod_750(location)
+ os.rename(f'{kdir}/private.key', f'{location}/private.key')
+ os.rename(f'{kdir}/public.key', f'{location}/public.key')
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ base = ['interfaces', 'wireguard']
+
+ migrate_default_keys()
+
+ if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+ # list all individual wireguard interface isntance
+ for i in config.list_nodes(base):
+ iface = base + [i]
+ for peer in config.list_nodes(iface + ['peer']):
+ base_peer = iface + ['peer', peer]
+ if config.exists(base_peer + ['endpoint']):
+ endpoint = config.return_value(base_peer + ['endpoint'])
+ address = endpoint.split(':')[0]
+ port = endpoint.split(':')[1]
+ # delete old node
+ config.delete(base_peer + ['endpoint'])
+ # setup new nodes
+ config.set(base_peer + ['address'], value=address)
+ config.set(base_peer + ['port'], value=port)
+
+ 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))
+ exit(1)
diff --git a/src/migration-scripts/interfaces/8-to-9 b/src/migration-scripts/interfaces/8-to-9
new file mode 100755
index 000000000..2d1efd418
--- /dev/null
+++ b/src/migration-scripts/interfaces/8-to-9
@@ -0,0 +1,52 @@
+#!/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/>.
+
+# Rename link nodes to source-interface for the following interface types:
+# - vxlan
+# - pseudo-ethernet
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ for if_type in ['vxlan', 'pseudo-ethernet']:
+ base = ['interfaces', if_type]
+ if not config.exists(base):
+ # Nothing to do
+ continue
+
+ # list all individual interface isntance
+ for i in config.list_nodes(base):
+ iface = base + [i]
+ if config.exists(iface + ['link']):
+ config.rename(iface + ['link'], 'source-interface')
+
+ 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))
+ exit(1)
diff --git a/src/migration-scripts/interfaces/9-to-10 b/src/migration-scripts/interfaces/9-to-10
new file mode 100755
index 000000000..4aa2c42b5
--- /dev/null
+++ b/src/migration-scripts/interfaces/9-to-10
@@ -0,0 +1,64 @@
+#!/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/>.
+
+# - rename CLI node 'dhcpv6-options delgate' to 'dhcpv6-options prefix-delegation
+# interface'
+# - rename CLI node 'interface-id' for prefix-delegation to 'address' as it
+# represents the local interface IPv6 address assigned by DHCPv6-PD
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ for intf_type in config.list_nodes(['interfaces']):
+ for intf in config.list_nodes(['interfaces', intf_type]):
+ # cache current config tree
+ base_path = ['interfaces', intf_type, intf, 'dhcpv6-options',
+ 'delegate']
+
+ if config.exists(base_path):
+ # cache new config tree
+ new_path = ['interfaces', intf_type, intf, 'dhcpv6-options',
+ 'prefix-delegation']
+ if not config.exists(new_path):
+ config.set(new_path)
+
+ # copy to new node
+ config.copy(base_path, new_path + ['interface'])
+
+ # rename interface-id to address
+ for interface in config.list_nodes(new_path + ['interface']):
+ config.rename(new_path + ['interface', interface, 'interface-id'], 'address')
+
+ # delete old noe
+ config.delete(base_path)
+
+ 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))
+ exit(1)