summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/vyos/component_version.py174
-rw-r--r--python/vyos/component_versions.py57
-rw-r--r--python/vyos/formatversions.py109
-rw-r--r--python/vyos/migrator.py26
-rw-r--r--python/vyos/systemversions.py46
5 files changed, 230 insertions, 182 deletions
diff --git a/python/vyos/component_version.py b/python/vyos/component_version.py
deleted file mode 100644
index b1554828d..000000000
--- a/python/vyos/component_version.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# Copyright 2022 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/>.
-
-"""
-Functions for reading/writing component versions.
-
-The config file version string has the following form:
-
-VyOS 1.3/1.4:
-
-// Warning: Do not remove the following line.
-// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
-// Release version: 1.3.0
-
-VyOS 1.2:
-
-/* Warning: Do not remove the following line. */
-/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pppoe-server@2:pptp@1:qos@1:quagga@7:snmp@1:ssh@1:system@10:vrrp@2:wanloadbalance@3:webgui@1:webproxy@2:zone-policy@1" === */
-/* Release version: 1.2.8 */
-
-"""
-
-import os
-import re
-import sys
-import fileinput
-from vyos.xml import component_version
-from vyos.version import get_version
-
-def from_string(string_line, vintage='vyos'):
- """
- Get component version dictionary from string.
- Return empty dictionary if string contains no config information
- or raise error if component version string malformed.
- """
- version_dict = {}
-
- if vintage == 'vyos':
- if re.match(r'// vyos-config-version:.+', string_line):
- if not re.match(r'// vyos-config-version:\s+"([\w,-]+@\d+:)+([\w,-]+@\d+)"\s*', string_line):
- raise ValueError(f"malformed configuration string: {string_line}")
-
- for pair in re.findall(r'([\w,-]+)@(\d+)', string_line):
- version_dict[pair[0]] = int(pair[1])
-
- elif vintage == 'vyatta':
- if re.match(r'/\* === vyatta-config-version:.+=== \*/$', string_line):
- if not re.match(r'/\* === vyatta-config-version:\s+"([\w,-]+@\d+:)+([\w,-]+@\d+)"\s+=== \*/$', string_line):
- raise ValueError(f"malformed configuration string: {string_line}")
-
- for pair in re.findall(r'([\w,-]+)@(\d+)', string_line):
- version_dict[pair[0]] = int(pair[1])
- else:
- raise ValueError("Unknown config string vintage")
-
- return version_dict
-
-def from_file(config_file_name='/opt/vyatta/etc/config/config.boot',
- vintage='vyos'):
- """
- Get component version dictionary parsing config file line by line
- """
- f = open(config_file_name, 'r')
- for line_in_config in f:
- version_dict = from_string(line_in_config, vintage=vintage)
- if version_dict:
- return version_dict
-
- # no version information
- return {}
-
-def from_system():
- """
- Get system component version dict.
- """
- return component_version()
-
-def legacy_from_system():
- """
- legacy function; imported as-is.
-
- Get component versions from running system; critical failure if
- unable to read migration directory.
- """
- import vyos.defaults
-
- system_versions = {}
-
- try:
- version_info = os.listdir(vyos.defaults.directories['current'])
- except OSError as err:
- print("OS error: {}".format(err))
- sys.exit(1)
-
- for info in version_info:
- if re.match(r'[\w,-]+@\d+', info):
- pair = info.split('@')
- system_versions[pair[0]] = int(pair[1])
-
- return system_versions
-
-def format_string(ver: dict) -> str:
- """
- Version dict to string.
- """
- keys = list(ver)
- keys.sort()
- l = []
- for k in keys:
- v = ver[k]
- l.append(f'{k}@{v}')
- sep = ':'
- return sep.join(l)
-
-def system_footer(vintage='vyos') -> str:
- """
- Version footer as string.
- """
- ver_str = format_string(from_system())
- release = get_version()
- if vintage == 'vyos':
- ret_str = (f'// Warning: Do not remove the following line.\n'
- + f'// vyos-config-version: "{ver_str}"\n'
- + f'// Release version: {release}\n')
- elif vintage == 'vyatta':
- ret_str = (f'/* Warning: Do not remove the following line. */\n'
- + f'/* === vyatta-config-version: "{ver_str}" === */\n'
- + f'/* Release version: {release} */\n')
- else:
- raise ValueError("Unknown config string vintage")
-
- return ret_str
-
-def write_footer(file_name, vintage='vyos'):
- """
- Write version footer to file.
- """
- footer = system_footer(vintage=vintage)
- if file_name:
- with open(file_name, 'a') as f:
- f.write(footer)
- else:
- sys.stdout.write(footer)
-
-def remove_footer(file_name):
- """
- Remove old version footer.
- """
- for line in fileinput.input(file_name, inplace=True):
- if re.match(r'/\* Warning:.+ \*/$', line):
- continue
- if re.match(r'/\* === vyatta-config-version:.+=== \*/$', line):
- continue
- if re.match(r'/\* Release version:.+ \*/$', line):
- continue
- if re.match('// vyos-config-version:.+', line):
- continue
- if re.match('// Warning:.+', line):
- continue
- if re.match('// Release version:.+', line):
- continue
- sys.stdout.write(line)
diff --git a/python/vyos/component_versions.py b/python/vyos/component_versions.py
new file mode 100644
index 000000000..90b458aae
--- /dev/null
+++ b/python/vyos/component_versions.py
@@ -0,0 +1,57 @@
+# 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/>.
+
+"""
+The version data looks like:
+
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version:
+"cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@1:dhcp-server@4:firewall@5:ipsec@4:nat@4:qos@1:quagga@2:system@8:vrrp@1:wanloadbalance@3:webgui@1:webproxy@1:zone-policy@1"
+=== */
+/* Release version: 1.2.0-rolling+201806131737 */
+"""
+
+import re
+
+def get_component_version(string_line):
+ """
+ Get component version dictionary from string
+ return empty dictionary if string contains no config information
+ or raise error if component version string malformed
+ """
+ return_value = {}
+ if re.match(r'/\* === vyatta-config-version:.+=== \*/$', string_line):
+
+ if not re.match(r'/\* === vyatta-config-version:\s+"([\w,-]+@\d+:)+([\w,-]+@\d+)"\s+=== \*/$', string_line):
+ raise ValueError("malformed configuration string: " + str(string_line))
+
+ for pair in re.findall(r'([\w,-]+)@(\d+)', string_line):
+ if pair[0] in return_value.keys():
+ raise ValueError("duplicate unit name: \"" + str(pair[0]) + "\" in string: \"" + string_line + "\"")
+ return_value[pair[0]] = int(pair[1])
+
+ return return_value
+
+
+def get_component_versions_from_file(config_file_name='/opt/vyatta/etc/config/config.boot'):
+ """
+ Get component version dictionary parsing config file line by line
+ """
+ f = open(config_file_name, 'r')
+ for line_in_config in f:
+ component_version = get_component_version(line_in_config)
+ if component_version:
+ return component_version
+ raise ValueError("no config string in file:", config_file_name)
diff --git a/python/vyos/formatversions.py b/python/vyos/formatversions.py
new file mode 100644
index 000000000..29117a5d3
--- /dev/null
+++ b/python/vyos/formatversions.py
@@ -0,0 +1,109 @@
+# Copyright 2019 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 sys
+import os
+import re
+import fileinput
+
+def read_vyatta_versions(config_file):
+ config_file_versions = {}
+
+ with open(config_file, 'r') as config_file_handle:
+ for config_line in config_file_handle:
+ if re.match(r'/\* === vyatta-config-version:.+=== \*/$', config_line):
+ if not re.match(r'/\* === vyatta-config-version:\s+"([\w,-]+@\d+:)+([\w,-]+@\d+)"\s+=== \*/$', config_line):
+ raise ValueError("malformed configuration string: "
+ "{}".format(config_line))
+
+ for pair in re.findall(r'([\w,-]+)@(\d+)', config_line):
+ config_file_versions[pair[0]] = int(pair[1])
+
+
+ return config_file_versions
+
+def read_vyos_versions(config_file):
+ config_file_versions = {}
+
+ with open(config_file, 'r') as config_file_handle:
+ for config_line in config_file_handle:
+ if re.match(r'// vyos-config-version:.+', config_line):
+ if not re.match(r'// vyos-config-version:\s+"([\w,-]+@\d+:)+([\w,-]+@\d+)"\s*', config_line):
+ raise ValueError("malformed configuration string: "
+ "{}".format(config_line))
+
+ for pair in re.findall(r'([\w,-]+)@(\d+)', config_line):
+ config_file_versions[pair[0]] = int(pair[1])
+
+ return config_file_versions
+
+def remove_versions(config_file):
+ """
+ Remove old version string.
+ """
+ for line in fileinput.input(config_file, inplace=True):
+ if re.match(r'/\* Warning:.+ \*/$', line):
+ continue
+ if re.match(r'/\* === vyatta-config-version:.+=== \*/$', line):
+ continue
+ if re.match(r'/\* Release version:.+ \*/$', line):
+ continue
+ if re.match('// vyos-config-version:.+', line):
+ continue
+ if re.match('// Warning:.+', line):
+ continue
+ if re.match('// Release version:.+', line):
+ continue
+ sys.stdout.write(line)
+
+def format_versions_string(config_versions):
+ cfg_keys = list(config_versions.keys())
+ cfg_keys.sort()
+
+ component_version_strings = []
+
+ for key in cfg_keys:
+ cfg_vers = config_versions[key]
+ component_version_strings.append('{}@{}'.format(key, cfg_vers))
+
+ separator = ":"
+ component_version_string = separator.join(component_version_strings)
+
+ return component_version_string
+
+def write_vyatta_versions_foot(config_file, component_version_string,
+ os_version_string):
+ if config_file:
+ with open(config_file, 'a') as config_file_handle:
+ config_file_handle.write('/* Warning: Do not remove the following line. */\n')
+ config_file_handle.write('/* === vyatta-config-version: "{}" === */\n'.format(component_version_string))
+ config_file_handle.write('/* Release version: {} */\n'.format(os_version_string))
+ else:
+ sys.stdout.write('/* Warning: Do not remove the following line. */\n')
+ sys.stdout.write('/* === vyatta-config-version: "{}" === */\n'.format(component_version_string))
+ sys.stdout.write('/* Release version: {} */\n'.format(os_version_string))
+
+def write_vyos_versions_foot(config_file, component_version_string,
+ os_version_string):
+ if config_file:
+ with open(config_file, 'a') as config_file_handle:
+ config_file_handle.write('// Warning: Do not remove the following line.\n')
+ config_file_handle.write('// vyos-config-version: "{}"\n'.format(component_version_string))
+ config_file_handle.write('// Release version: {}\n'.format(os_version_string))
+ else:
+ sys.stdout.write('// Warning: Do not remove the following line.\n')
+ sys.stdout.write('// vyos-config-version: "{}"\n'.format(component_version_string))
+ sys.stdout.write('// Release version: {}\n'.format(os_version_string))
+
diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py
index 266a2e58e..a2e0daabd 100644
--- a/python/vyos/migrator.py
+++ b/python/vyos/migrator.py
@@ -17,8 +17,10 @@ import sys
import os
import json
import subprocess
+import vyos.version
import vyos.defaults
-import vyos.component_version as component_version
+import vyos.systemversions as systemversions
+import vyos.formatversions as formatversions
class MigratorError(Exception):
pass
@@ -40,13 +42,13 @@ class Migrator(object):
cfg_file = self._config_file
component_versions = {}
- cfg_versions = component_version.from_file(cfg_file, vintage='vyatta')
+ cfg_versions = formatversions.read_vyatta_versions(cfg_file)
if cfg_versions:
self._config_file_vintage = 'vyatta'
component_versions = cfg_versions
- cfg_versions = component_version.from_file(cfg_file, vintage='vyos')
+ cfg_versions = formatversions.read_vyos_versions(cfg_file)
if cfg_versions:
self._config_file_vintage = 'vyos'
@@ -150,11 +152,19 @@ class Migrator(object):
"""
Write new versions string.
"""
+ versions_string = formatversions.format_versions_string(cfg_versions)
+
+ os_version_string = vyos.version.get_version()
+
if self._config_file_vintage == 'vyatta':
- component_version.write_footer(self._config_file, vintage='vyatta')
+ formatversions.write_vyatta_versions_foot(self._config_file,
+ versions_string,
+ os_version_string)
if self._config_file_vintage == 'vyos':
- component_version.write_footer(self._config_file, vintage='vyos')
+ formatversions.write_vyos_versions_foot(self._config_file,
+ versions_string,
+ os_version_string)
def save_json_record(self, component_versions: dict):
"""
@@ -185,7 +195,7 @@ class Migrator(object):
# This will force calling all migration scripts:
cfg_versions = {}
- sys_versions = component_version.from_system()
+ sys_versions = systemversions.get_system_component_version()
# save system component versions in json file for easy reference
self.save_json_record(sys_versions)
@@ -201,7 +211,7 @@ class Migrator(object):
if not self._changed:
return
- component_version.remove_footer(cfg_file)
+ formatversions.remove_versions(cfg_file)
self.write_config_file_versions(rev_versions)
@@ -222,7 +232,7 @@ class VirtualMigrator(Migrator):
if not self._changed:
return
- component_version.remove_footer(cfg_file)
+ formatversions.remove_versions(cfg_file)
self.write_config_file_versions(cfg_versions)
diff --git a/python/vyos/systemversions.py b/python/vyos/systemversions.py
new file mode 100644
index 000000000..f2da76d4f
--- /dev/null
+++ b/python/vyos/systemversions.py
@@ -0,0 +1,46 @@
+# Copyright 2019 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 os
+import re
+import sys
+import vyos.defaults
+from vyos.xml import component_version
+
+# legacy version, reading from the file names in
+# /opt/vyatta/etc/config-migrate/current
+def get_system_versions():
+ """
+ Get component versions from running system; critical failure if
+ unable to read migration directory.
+ """
+ system_versions = {}
+
+ try:
+ version_info = os.listdir(vyos.defaults.directories['current'])
+ except OSError as err:
+ print("OS error: {}".format(err))
+ sys.exit(1)
+
+ for info in version_info:
+ if re.match(r'[\w,-]+@\d+', info):
+ pair = info.split('@')
+ system_versions[pair[0]] = int(pair[1])
+
+ return system_versions
+
+# read from xml cache
+def get_system_component_version():
+ return component_version()