diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/configsession.py | 4 | ||||
-rw-r--r-- | python/vyos/cpu.py | 102 | ||||
-rw-r--r-- | python/vyos/frr.py | 2 | ||||
-rw-r--r-- | python/vyos/migrator.py | 5 | ||||
-rw-r--r-- | python/vyos/pki.py | 2 | ||||
-rw-r--r-- | python/vyos/util.py | 17 |
6 files changed, 124 insertions, 8 deletions
diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py index f28ad09c5..3a60f6d92 100644 --- a/python/vyos/configsession.py +++ b/python/vyos/configsession.py @@ -33,6 +33,7 @@ INSTALL_IMAGE = ['/opt/vyatta/sbin/install-image', '--url'] REMOVE_IMAGE = ['/opt/vyatta/bin/vyatta-boot-image.pl', '--del'] GENERATE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'generate'] SHOW = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'show'] +RESET = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'reset'] # Default "commit via" string APP = "vyos-http-api" @@ -200,3 +201,6 @@ class ConfigSession(object): out = self.__run_command(SHOW + path) return out + def reset(self, path): + out = self.__run_command(RESET + path) + return out diff --git a/python/vyos/cpu.py b/python/vyos/cpu.py new file mode 100644 index 000000000..a0ef864be --- /dev/null +++ b/python/vyos/cpu.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# 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/>. + +""" +Retrieves (or at least attempts to retrieve) the total number of real CPU cores +installed in a Linux system. + +The issue of core count is complicated by existence of SMT, e.g. Intel's Hyper Threading. +GNU nproc returns the number of LOGICAL cores, +which is 2x of the real cores if SMT is enabled. + +The idea is to find all physical CPUs and add up their core counts. +It has special cases for x86_64 and MAY work correctly on other architectures, +but nothing is certain. +""" + +import re + + +def _read_cpuinfo(): + with open('/proc/cpuinfo', 'r') as f: + return f.readlines() + +def _split_line(l): + l = l.strip() + parts = re.split(r'\s*:\s*', l) + return (parts[0], ":".join(parts[1:])) + +def _find_cpus(cpuinfo_lines): + # Make a dict because it's more convenient to work with later, + # when we need to find physicall distinct CPUs there. + cpus = {} + + cpu_number = 0 + + for l in cpuinfo_lines: + key, value = _split_line(l) + if key == 'processor': + cpu_number = value + cpus[cpu_number] = {} + else: + cpus[cpu_number][key] = value + + return cpus + +def _find_physical_cpus(): + cpus = _find_cpus(_read_cpuinfo()) + + phys_cpus = {} + + for num in cpus: + if 'physical id' in cpus[num]: + # On at least some architectures, CPUs in different sockets + # have different 'physical id' field, e.g. on x86_64. + phys_id = cpus[num]['physical id'] + if phys_id not in phys_cpus: + phys_cpus[phys_id] = cpus[num] + else: + # On other architectures, e.g. on ARM, there's no such field. + # We just assume they are different CPUs, + # whether single core ones or cores of physical CPUs. + phys_cpus[num] = cpu[num] + + return phys_cpus + +def get_cpus(): + """ Returns a list of /proc/cpuinfo entries that belong to different CPUs. + """ + cpus_dict = _find_physical_cpus() + return list(cpus_dict.values()) + +def get_core_count(): + """ Returns the total number of physical CPU cores + (even if Hyper-Threading or another SMT is enabled and has inflated + the number of cores in /proc/cpuinfo) + """ + physical_cpus = _find_physical_cpus() + + core_count = 0 + + for num in physical_cpus: + # Some architectures, e.g. x86_64, include a field for core count. + # Since we found unique physical CPU entries, we can sum their core counts. + if 'cpu cores' in physical_cpus[num]: + core_count += int(physical_cpus[num]['cpu cores']) + else: + core_count += 1 + + return core_count diff --git a/python/vyos/frr.py b/python/vyos/frr.py index cbba19ab7..0ffd5cba9 100644 --- a/python/vyos/frr.py +++ b/python/vyos/frr.py @@ -85,7 +85,7 @@ LOG.addHandler(ch2) _frr_daemons = ['zebra', 'bgpd', 'fabricd', 'isisd', 'ospf6d', 'ospfd', 'pbrd', 'pimd', 'ripd', 'ripngd', 'sharpd', 'staticd', 'vrrpd', 'ldpd', - 'bfdd'] + 'bfdd', 'eigrpd'] path_vtysh = '/usr/bin/vtysh' path_frr_reload = '/usr/lib/frr/frr-reload.py' diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py index a2e0daabd..c6e3435ca 100644 --- a/python/vyos/migrator.py +++ b/python/vyos/migrator.py @@ -105,6 +105,11 @@ class Migrator(object): sys_keys = list(sys_versions.keys()) sys_keys.sort() + # XXX 'bgp' needs to follow 'quagga': + if 'bgp' in sys_keys and 'quagga' in sys_keys: + sys_keys.insert(sys_keys.index('quagga'), + sys_keys.pop(sys_keys.index('bgp'))) + rev_versions = {} for key in sys_keys: diff --git a/python/vyos/pki.py b/python/vyos/pki.py index 0b916eaae..fd91fc9bf 100644 --- a/python/vyos/pki.py +++ b/python/vyos/pki.py @@ -247,7 +247,7 @@ def load_private_key(raw_data, passphrase=None, wrap_tags=True): if wrap_tags: raw_data = wrap_private_key(raw_data, passphrase) - if passphrase: + if passphrase is not None: passphrase = bytes(passphrase, 'utf-8') try: diff --git a/python/vyos/util.py b/python/vyos/util.py index de55e108b..0d62fbfe9 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -757,21 +757,26 @@ def dict_search_args(dict_object, *path): dict_object = dict_object[item] return dict_object -def dict_search_recursive(dict_object, key): +def dict_search_recursive(dict_object, key, path=[]): """ Traverse a dictionary recurisvely and return the value of the key we are looking for. Thankfully copied from https://stackoverflow.com/a/19871956 + + Modified to yield optional path to found keys """ if isinstance(dict_object, list): for i in dict_object: - for x in dict_search_recursive(i, key): - yield x + new_path = path + [i] + for x in dict_search_recursive(i, key, new_path): + yield x elif isinstance(dict_object, dict): if key in dict_object: - yield dict_object[key] - for j in dict_object.values(): - for x in dict_search_recursive(j, key): + new_path = path + [key] + yield dict_object[key], new_path + for k, j in dict_object.items(): + new_path = path + [k] + for x in dict_search_recursive(j, key, new_path): yield x def get_bridge_fdb(interface): |