diff --git a/LibreNMS/Util/Version.php b/LibreNMS/Util/Version.php index fa9d850351..4b7f3a9335 100644 --- a/LibreNMS/Util/Version.php +++ b/LibreNMS/Util/Version.php @@ -26,6 +26,7 @@ namespace LibreNMS\Util; use LibreNMS\DB\Eloquent; +use Symfony\Component\Process\Process; class Version { @@ -88,4 +89,16 @@ class Version ? rtrim(shell_exec("git show --pretty='%ct' -s HEAD")) : ''; } + + public static function python() + { + $proc = new Process(['python3', '--version']); + $proc->run(); + + if ($proc->getExitCode() !== 0) { + return null; + } + + return explode(' ', rtrim($proc->getOutput()), 2)[1] ?? null; + } } diff --git a/LibreNMS/Validations/Python.php b/LibreNMS/Validations/Python.php new file mode 100644 index 0000000000..1d8e783dbb --- /dev/null +++ b/LibreNMS/Validations/Python.php @@ -0,0 +1,71 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2020 Thomas Berberich + * @author Thomas Berberich + */ + +namespace LibreNMS\Validations; + +use LibreNMS\Config; +use LibreNMS\Util\Version; +use LibreNMS\Validator; + +class Python extends BaseValidation +{ + const PYTHON_MIN_VERSION = '3.4.0'; + + /** + * Validate this module. + * To return ValidationResults, call ok, warn, fail, or result methods on the $validator + * + * @param Validator $validator + */ + public function validate(Validator $validator) + { + $version = Version::python(); + + if (empty($version)) { + $validator->fail('python3 not found'); + return; // no need to check anything else + } + + $this->checkVersion($validator, $version); + $this->checkExtensions($validator); + } + + private function checkVersion(Validator $validator, $version) + { + if (version_compare($version, self::PYTHON_MIN_VERSION, '<')) { + $validator->warn('Python version ' . self::PYTHON_MIN_VERSION . ' is the minimum supported version. We recommend you update Python to a supported version.'); + } + } + + private function checkExtensions(Validator $validator) + { + $pythonExtensions = 'scripts/check_requirements.py'; + exec(Config::get('install_dir') . '/' . $pythonExtensions . ' -v', $output, $returnval); + + if ($returnval !== 0) { + $validator->fail("Python3 module issue found: '" . ($output[0] ?? '') . "'"); + } + } +} diff --git a/app/Http/Controllers/AboutController.php b/app/Http/Controllers/AboutController.php index 9adbaaa873..4c8e332a41 100644 --- a/app/Http/Controllers/AboutController.php +++ b/app/Http/Controllers/AboutController.php @@ -72,6 +72,7 @@ class AboutController extends Controller 'version_local' => $version->local(), 'version_mysql' => current(DB::selectOne('select version()')), 'version_php' => phpversion(), + 'version_python' => Version::python(), 'version_webserver' => $request->server('SERVER_SOFTWARE'), 'version_rrdtool' => str_replace('1.7.01.7.0', '1.7.0', implode(' ', array_slice(explode(' ', shell_exec( Config::get('rrdtool', 'rrdtool') . ' --version | head -n1' diff --git a/includes/common.php b/includes/common.php index b331be497f..49867a4938 100644 --- a/includes/common.php +++ b/includes/common.php @@ -1007,6 +1007,7 @@ function version_info($remote = false) } $output['db_schema'] = vsprintf('%s (%s)', $version->database()); $output['php_ver'] = phpversion(); + $output['python_ver'] = \LibreNMS\Util\Version::python(); $output['mysql_ver'] = dbIsConnected() ? dbFetchCell('SELECT version()') : '?'; $output['rrdtool_ver'] = str_replace('1.7.01.7.0', '1.7.0', implode(' ', array_slice(explode(' ', shell_exec( Config::get('rrdtool', 'rrdtool') . ' --version |head -n1' diff --git a/resources/views/about/index.blade.php b/resources/views/about/index.blade.php index 72ac1530fb..7ca552cd41 100644 --- a/resources/views/about/index.blade.php +++ b/resources/views/about/index.blade.php @@ -42,6 +42,10 @@ @lang('PHP') {{ $version_php }} + + @lang('Python') + {{ $version_python }} + @lang('MySQL') {{ $version_mysql }} diff --git a/scripts/check_requirements.py b/scripts/check_requirements.py index fce327bb5c..6cfdbdff6e 100755 --- a/scripts/check_requirements.py +++ b/scripts/check_requirements.py @@ -1,17 +1,27 @@ #! /usr/bin/env python3 import os +import sys import pkg_resources from pkg_resources import DistributionNotFound, VersionConflict +args = sys.argv + +# verbose flag +verbose = '-v' in args + target = os.path.realpath(os.path.dirname(__file__) + '/../requirements.txt') with open(target, 'r') as file: requirements = file.read().rstrip().split("\n") try: pkg_resources.require(requirements) - except DistributionNotFound: + except DistributionNotFound as req: + if verbose: + print(req) exit(1) - except VersionConflict: + except VersionConflict as req: + if verbose: + print(req) exit(2) exit(0) diff --git a/validate.php b/validate.php index 91094d7f27..a46f6a5d68 100755 --- a/validate.php +++ b/validate.php @@ -47,6 +47,7 @@ if (isset($options['h'])) { - php: check that various PHP modules and functions exist - poller: check that the poller and discovery are running properly - programs: check that external programs exist and are executable + - python: check that various Python modules and functions exist - updates: checks the status of git and updates - user: check that the LibreNMS user is set properly @@ -159,6 +160,7 @@ Component | Version LibreNMS | ${versions['local_ver']} DB Schema | ${versions['db_schema']} PHP | ${versions['php_ver']} +Python | ${versions['python_ver']} MySQL | ${versions['mysql_ver']} RRDTool | ${versions['rrdtool_ver']} SNMP | ${versions['netsnmp_ver']}