Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OSMorphing] Check installed packages before installing packages #337

Merged
merged 2 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions coriolis/osmorphing/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ def check_os_supported(cls, detected_os_info):
"OS compatibility check not implemented for tools class %s" % (
cls.__name__))

@abc.abstractmethod
def get_installed_packages(self, package_name):
pass

@abc.abstractmethod
def set_net_config(self, nics_info, dhcp):
pass
Expand Down Expand Up @@ -121,6 +125,7 @@ def set_environment(self, environment):
class BaseLinuxOSMorphingTools(BaseOSMorphingTools):

_packages = {}
installed_packages = []

def __init__(self, conn, os_root_dir, os_root_dev, hypervisor,
event_manager, detected_os_info, osmorphing_parameters,
Expand Down
3 changes: 3 additions & 0 deletions coriolis/osmorphing/coreos.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def check_os_supported(cls, detected_os_info):
return True
return False

def get_installed_package(self):
pass

def disable_predictable_nic_names(self):
pass

Expand Down
8 changes: 8 additions & 0 deletions coriolis/osmorphing/debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ def set_net_config(self, nics_info, dhcp):
cfg_name = "%s/coriolis_netplan.yaml" % netplan_base
self._write_file_sudo(cfg_name, new_cfg)

def get_installed_packages(self):
cmd = "dpkg-query -f '${binary:Package}\\n' -W"
try:
self.installed_packages = self._exec_cmd_chroot(
cmd).decode('utf-8').splitlines()
except exception.CoriolisException:
pass

def pre_packages_install(self, package_names):
super(BaseDebianMorphingTools, self).pre_packages_install(
package_names)
Expand Down
5 changes: 5 additions & 0 deletions coriolis/osmorphing/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ def morph_image(origin_provider, destination_provider, connection_info,
LOG.info("Post packages uninstall")
export_os_morphing_tools.post_packages_uninstall(packages_remove)

LOG.info("Checking for packages already installed")
import_os_morphing_tools.get_installed_packages()
packages_add = list(
set(packages_add) - set(import_os_morphing_tools.installed_packages))

LOG.info("Pre packages install")
import_os_morphing_tools.pre_packages_install(packages_add)

Expand Down
3 changes: 3 additions & 0 deletions coriolis/osmorphing/openwrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ def check_os_supported(cls, detected_os_info):
return True
return False

def get_installed_package(self):
pass

def disable_predictable_nic_names(self):
pass

Expand Down
13 changes: 6 additions & 7 deletions coriolis/osmorphing/redhat.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,14 @@ def set_net_config(self, nics_info, dhcp):
mac_addresses)
self._add_net_udev_rules(net_ifaces_info)

def _has_package_installed(self, package_name):
cmd = 'rpm -q %s' % ("".join(package_name))
def get_installed_packages(self):
cmd = 'rpm -qa --qf "%{NAME}\\n"'
try:
self._exec_cmd_chroot(cmd)
return True
self.installed_packages = self._exec_cmd_chroot(
cmd).decode('utf-8').splitlines()
except exception.CoriolisException:
LOG.warning(f"Package ${package_name} is not installed")
LOG.warning("Failed to get installed packages")
LOG.trace(utils.get_exception_details())
return False

def _yum_install(self, package_names, enable_repos=[]):
try:
Expand Down Expand Up @@ -295,7 +294,7 @@ def pre_packages_install(self, package_names):
super(BaseRedHatMorphingTools, self).pre_packages_install(
package_names)
self._yum_clean_all()
if not self._has_package_installed('grubby'):
if 'grubby' not in self.installed_packages:
self._yum_install(['grubby'])
else:
LOG.debug("Skipping package 'grubby' as it's already installed")
Expand Down
9 changes: 9 additions & 0 deletions coriolis/osmorphing/suse.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ def set_net_config(self, nics_info, dhcp):
# TODO(alexpilotti): add networking support
pass

def get_installed_packages(self):
cmd = 'rpm -qa --qf "%{NAME}\\n"'
try:
self.installed_packages = self._exec_cmd_chroot(
cmd).decode('utf-8').splitlines()
except exception.CoriolisException:
LOG.warning("Failed to get installed packages")
LOG.trace(utils.get_exception_details())

def get_update_grub2_command(self):
location = self._get_grub2_cfg_location()
return "grub2-mkconfig -o %s" % location
Expand Down
3 changes: 3 additions & 0 deletions coriolis/osmorphing/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,9 @@ def set_net_config(self, nics_info, dhcp):
def get_packages(self):
return [], []

def get_installed_packages(self):
pass

def pre_packages_install(self, package_names):
pass

Expand Down
3 changes: 3 additions & 0 deletions coriolis/tests/osmorphing/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class TestLinuxOSMorphingTools(base.BaseLinuxOSMorphingTools):
def check_os_supported(self):
pass

def get_installed_packages(self):
pass

def install_packages(self):
pass

Expand Down
27 changes: 27 additions & 0 deletions coriolis/tests/osmorphing/test_debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,33 @@ def test_set_net_config_no_dhcp(
mock_write_file_sudo.assert_not_called()
mock_exec_cmd_chroot.assert_not_called()

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_get_installed_packages(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.return_value = \
"package1\npackage2".encode('utf-8')

self.morpher.get_installed_packages()

self.assertEqual(
self.morpher.installed_packages,
['package1', 'package2']
)
mock_exec_cmd_chroot.assert_called_once_with(
"dpkg-query -f '${binary:Package}\\n' -W")

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_get_installed_packages_none(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.side_effect = exception.CoriolisException()

self.morpher.get_installed_packages()

self.assertEqual(
self.morpher.installed_packages,
[]
)
mock_exec_cmd_chroot.assert_called_once_with(
"dpkg-query -f '${binary:Package}\\n' -W")

@mock.patch.object(base.BaseLinuxOSMorphingTools, 'pre_packages_install')
@mock.patch.object(debian.BaseDebianMorphingTools, '_exec_cmd_chroot')
def test_pre_packages_install(self, mock_exec_cmd_chroot,
Expand Down
5 changes: 5 additions & 0 deletions coriolis/tests/osmorphing/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ def check_os_supported(cls, detected_os_info):
self.assertIsNone(result)

class MockOSMorphingToolsClass:
installed_packages = []

def __init__(self, *args, **kwargs):
pass

Expand All @@ -174,6 +176,9 @@ def post_packages_uninstall(self, packages_remove):
def pre_packages_install(self, packages_add):
pass

def get_installed_packages(self):
pass

def set_net_config(self, nics_info, dhcp):
pass

Expand Down
3 changes: 3 additions & 0 deletions coriolis/tests/osmorphing/test_openwrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class MockOpenWRTMorphingTools(openwrt.BaseOpenWRTMorphingTools):
def __init__(self):
pass

def get_installed_packages(self):
pass

def install_packages(self, packages):
pass

Expand Down
40 changes: 20 additions & 20 deletions coriolis/tests/osmorphing/test_redhat.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,27 +364,33 @@ def test_set_net_config_no_dhcp(
mock_get_net_ifaces_info.return_value)

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_has_package_installed(self, mock_exec_cmd_chroot):
result = self.morphing_tools._has_package_installed("mock_package")
def test_get_installed_packages(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.return_value = \
"package1\npackage2".encode('utf-8')

self.morphing_tools.get_installed_packages()

self.assertEqual(
True,
result
self.morphing_tools.installed_packages,
['package1', 'package2']
)
mock_exec_cmd_chroot.assert_called_once_with("rpm -q mock_package")
mock_exec_cmd_chroot.assert_called_once_with(
'rpm -qa --qf "%{NAME}\\n"')

mock_exec_cmd_chroot.reset_mock()
@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_get_installed_packages_none(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.side_effect = exception.CoriolisException()

with self.assertLogs(
'coriolis.osmorphing.redhat', level=logging.DEBUG):
result = self.morphing_tools._has_package_installed("mock_package")
self.morphing_tools.get_installed_packages()

self.assertEqual(
False,
result
self.morphing_tools.installed_packages,
[]
)
mock_exec_cmd_chroot.assert_called_once_with("rpm -q mock_package")
mock_exec_cmd_chroot.assert_called_once_with(
'rpm -qa --qf "%{NAME}\\n"')

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test__yum_install(self, mock_exec_cmd_chroot):
Expand Down Expand Up @@ -472,31 +478,25 @@ def test__find_yum_repos_not_found(self, mock_read_file, mock_list_dir):
with self.assertLogs('coriolis.osmorphing.redhat', level=logging.WARN):
self.morphing_tools._find_yum_repos(repos_to_enable)

@mock.patch.object(redhat.BaseRedHatMorphingTools,
'_has_package_installed')
@mock.patch.object(redhat.BaseRedHatMorphingTools, '_yum_install')
@mock.patch.object(redhat.BaseRedHatMorphingTools, '_yum_clean_all')
@mock.patch.object(base.BaseLinuxOSMorphingTools, 'pre_packages_install')
def test_pre_packages_install(self, mock_pre_packages_install,
mock_yum_clean_all, mock_yum_install,
mock_has_package_installed):
mock_has_package_installed.return_value = False
mock_yum_clean_all, mock_yum_install):
self.morphing_tools.installed_packages = []

self.morphing_tools.pre_packages_install(self.package_names)

mock_pre_packages_install.assert_called_once_with(self.package_names)
mock_yum_clean_all.assert_called_once()
mock_yum_install.assert_called_once_with(['grubby'])

@mock.patch.object(redhat.BaseRedHatMorphingTools,
'_has_package_installed')
@mock.patch.object(redhat.BaseRedHatMorphingTools, '_yum_install')
@mock.patch.object(redhat.BaseRedHatMorphingTools, '_yum_clean_all')
@mock.patch.object(base.BaseLinuxOSMorphingTools, 'pre_packages_install')
def test_pre_packages_install_has_grubby(
self, mock_pre_packages_install, mock_yum_clean_all, mock_yum_install,
mock_has_package_installed):
mock_has_package_installed.return_value = True
self, mock_pre_packages_install, mock_yum_clean_all, mock_yum_install):
self.morphing_tools.installed_packages = ['grubby']

self.morphing_tools.pre_packages_install(self.package_names)

Expand Down
29 changes: 29 additions & 0 deletions coriolis/tests/osmorphing/test_suse.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,35 @@ def test_check_os_not_supported(self):

self.assertFalse(result)

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_get_installed_packages(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.return_value = \
"package1\npackage2".encode('utf-8')

self.morphing_tools.get_installed_packages()

self.assertEqual(
self.morphing_tools.installed_packages,
['package1', 'package2']
)
mock_exec_cmd_chroot.assert_called_once_with(
'rpm -qa --qf "%{NAME}\\n"')

@mock.patch.object(base.BaseLinuxOSMorphingTools, '_exec_cmd_chroot')
def test_get_installed_packages_none(self, mock_exec_cmd_chroot):
mock_exec_cmd_chroot.side_effect = exception.CoriolisException()

with self.assertLogs(
'coriolis.osmorphing.suse', level=logging.DEBUG):
self.morphing_tools.get_installed_packages()

self.assertEqual(
self.morphing_tools.installed_packages,
[]
)
mock_exec_cmd_chroot.assert_called_once_with(
'rpm -qa --qf "%{NAME}\\n"')

@mock.patch.object(
suse.BaseSUSEMorphingTools, '_get_grub2_cfg_location'
)
Expand Down
Loading