From 381e04b37759302431eceff7d098c33ec4cdb120 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Thu, 8 Feb 2024 20:40:08 +0100 Subject: [PATCH] Add is_installed function in updater.py Signed-off-by: Ronan Abhamon --- README.md | 7 +++ SOURCES/etc/xapi.d/plugins/updater.py | 28 ++++++++++++ tests/test_updater.py | 63 ++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a8e8385..0c154b1 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,13 @@ Update the host. $ xe host-call-plugin host-uuid= plugin=updater.py fn=update ``` +#### `is_installed`: +Test if one or many packages are installed. +``` +$ xe host-call-plugin host-uuid= plugin=updater.py fn=is_installed args:packages=sm,sm-rawhba,invalid +{"sm-rawhba": "sm-rawhba-2.30.8-2.3.0.linstor.1.xcpng8.2.x86_64", "invalid": "", "sm": "sm-2.30.8-10.1.0.linstor.1.xcpng8.2.x86_64"} +``` + ### Proxy configuration #### `get_proxies()`: diff --git a/SOURCES/etc/xapi.d/plugins/updater.py b/SOURCES/etc/xapi.d/plugins/updater.py index 56376d6..e4111c6 100755 --- a/SOURCES/etc/xapi.d/plugins/updater.py +++ b/SOURCES/etc/xapi.d/plugins/updater.py @@ -181,6 +181,33 @@ def check_update(session, args): def update(session, args): return install_helper(session, args, 'update') +@error_wrapped +def is_installed(session, args): + packages = args.get('packages') + if not packages: + return '{}' + + import re + packages = re.sub(r'\s+', ' ', packages).replace(',', ' ').split(' ') + packages = filter(lambda package: package, packages) + if not packages: + return '{}' + + package_map = dict.fromkeys(packages, '') + packages = list(package_map) + + command = ['rpm', '-q'] + packages + result = run_command(command, check=False) + package_info = result['stdout'].rstrip().split('\n') + assert len(packages) == len(package_info), 'ill-formed result' + + for i, package in enumerate(packages): + info = package_info[i] + if not info.endswith('is not installed'): + package_map[package] = info + + return json.dumps(package_map) + def check_upgrade(session, args): # TODO: # check new version exists @@ -265,6 +292,7 @@ def set_proxies(session, args): 'install': install, 'check_update': check_update, 'update': update, + 'is_installed': is_installed, 'get_proxies': get_proxies, 'set_proxies': set_proxies }) diff --git a/tests/test_updater.py b/tests/test_updater.py index 9379a3a..46a623a 100644 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -7,7 +7,14 @@ import time import XenAPIPlugin -from updater import install, check_update, get_proxies, set_proxies, update, DEFAULT_REPOS +from updater import \ + install, \ + check_update, \ + get_proxies, \ + set_proxies, \ + update, \ + is_installed, \ + DEFAULT_REPOS # ============================================================================== # Install/Update. @@ -108,6 +115,60 @@ def test_update_with_additional_repos_and_packages(self, run_command, fs): ['yum', 'update', '--disablerepo=*', '--enablerepo=' + ','.join(repos), '-y', packages] ) +@mock.patch('updater.run_command', autospec=True) +class TestIsInstalled: + def test_without_package(self, run_command): + result = is_installed(mock.MagicMock(), {}) + assert result == '{}' + + def test_one_package_installed(self, run_command): + run_command.return_value = { + 'stdout': 'test.rpm', + 'stderr': '', + 'returncode': 0 + } + + package = 'test' + result = is_installed(mock.MagicMock(), {'packages': package}) + run_command.assert_called_once_with( + ['rpm', '-q', package], False + ) + + assert json.loads(result) == {'test': 'test.rpm'} + + def test_no_package_installed(self, run_command): + run_command.return_value = { + 'stdout': 'test is not installed', + 'stderr': '', + 'returncode': 1 + } + + package = 'test' + result = is_installed(mock.MagicMock(), {'packages': package}) + run_command.assert_called_once_with( + ['rpm', '-q', package], False + ) + + assert json.loads(result) == {'test': ''} + + def test_with_many_packages(self, run_command, fs): + run_command.return_value = { + 'stdout': + 'toto.rpm\n' + 'package tata is not installed\n' + 'titi.rpm\n', + 'stderr': '', + 'returncode': 0 + } + + packages = 'toto,tata,titi' + result = is_installed(mock.MagicMock(), {'packages': packages}) + run_command.assert_called_once_with( + ['rpm', '-q'] + packages.split(','), False + ) + + assert json.loads(result) == {'toto': 'toto.rpm', 'tata': '', 'titi': 'titi.rpm'} + # ============================================================================== # Lock: Try to execute a command with a lock already locked. # ==============================================================================