diff --git a/coriolis/osmorphing/base.py b/coriolis/osmorphing/base.py
index fbf7445e..85890f30 100644
--- a/coriolis/osmorphing/base.py
+++ b/coriolis/osmorphing/base.py
@@ -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
@@ -189,6 +193,17 @@ def _version_supported_util(cls, version, minimum, maximum=None):
 
         return True
 
+    def check_installed_packages(self, package_names):
+        installed_packages = self.get_installed_packages()
+        LOG.info("Packages installed: %s" % str(installed_packages))
+
+        packages = [
+            pkg for pkg in package_names if not any(
+                pkg in installed_pkg for installed_pkg in installed_packages)]
+        LOG.info("Packages already installed: %s" %
+                 str(set(package_names) - set(packages)))
+        return packages
+
     def get_packages(self):
         k_add = [h for h in self._packages.keys() if
                  h is None or h == self._hypervisor]
diff --git a/coriolis/osmorphing/coreos.py b/coriolis/osmorphing/coreos.py
index 4cc3628c..013e8208 100644
--- a/coriolis/osmorphing/coreos.py
+++ b/coriolis/osmorphing/coreos.py
@@ -14,6 +14,9 @@ def check_os_supported(cls, detected_os_info):
             return True
         return False
 
+    def get_installed_package(self):
+        return []
+
     def disable_predictable_nic_names(self):
         pass
 
diff --git a/coriolis/osmorphing/debian.py b/coriolis/osmorphing/debian.py
index 6f87c1ef..68ee1a40 100644
--- a/coriolis/osmorphing/debian.py
+++ b/coriolis/osmorphing/debian.py
@@ -122,6 +122,13 @@ 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 = 'apt list --installed'
+        try:
+            return self._exec_cmd_chroot(cmd).splitlines()
+        except exception.CoriolisException:
+            return []
+
     def pre_packages_install(self, package_names):
         super(BaseDebianMorphingTools, self).pre_packages_install(
             package_names)
diff --git a/coriolis/osmorphing/manager.py b/coriolis/osmorphing/manager.py
index bf900d03..f73a45b9 100644
--- a/coriolis/osmorphing/manager.py
+++ b/coriolis/osmorphing/manager.py
@@ -239,6 +239,10 @@ 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")
+    packages_add = import_os_morphing_tools.check_installed_packages(
+        packages_add)
+
     LOG.info("Pre packages install")
     import_os_morphing_tools.pre_packages_install(packages_add)
 
diff --git a/coriolis/osmorphing/openwrt.py b/coriolis/osmorphing/openwrt.py
index 63acbbf0..81586780 100644
--- a/coriolis/osmorphing/openwrt.py
+++ b/coriolis/osmorphing/openwrt.py
@@ -17,6 +17,9 @@ def check_os_supported(cls, detected_os_info):
             return True
         return False
 
+    def get_installed_package(self):
+        return []
+
     def disable_predictable_nic_names(self):
         pass
 
diff --git a/coriolis/osmorphing/redhat.py b/coriolis/osmorphing/redhat.py
index 7d0fa93f..67ec2d38 100644
--- a/coriolis/osmorphing/redhat.py
+++ b/coriolis/osmorphing/redhat.py
@@ -209,16 +209,25 @@ 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 check_installed_package(self, package_name):
+        cmd = 'rpm -q %s' % package_name
         try:
-            self._exec_cmd_chroot(cmd)
+            self._exec_cmd_chroot(cmd).splitlines()
             return True
         except exception.CoriolisException:
             LOG.warning(f"Package ${package_name} is not installed")
             LOG.trace(utils.get_exception_details())
             return False
 
+    def get_installed_packages(self):
+        cmd = 'rpm -qa'
+        try:
+            return self._exec_cmd_chroot(cmd)
+        except exception.CoriolisException:
+            LOG.warning("Failed to get installed packages")
+            LOG.trace(utils.get_exception_details())
+            return []
+
     def _yum_install(self, package_names, enable_repos=[]):
         try:
             yum_cmd = 'yum install %s -y%s' % (
@@ -295,7 +304,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 not self.check_installed_package('grubby'):
             self._yum_install(['grubby'])
         else:
             LOG.debug("Skipping package 'grubby' as it's already installed")
diff --git a/coriolis/osmorphing/suse.py b/coriolis/osmorphing/suse.py
index 5ef6bda0..372af974 100644
--- a/coriolis/osmorphing/suse.py
+++ b/coriolis/osmorphing/suse.py
@@ -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'
+        try:
+            return self._exec_cmd_chroot(cmd).splitlines()
+        except exception.CoriolisException:
+            LOG.warning("Failed to get installed packages")
+            LOG.trace(utils.get_exception_details())
+            return []
+
     def get_update_grub2_command(self):
         location = self._get_grub2_cfg_location()
         return "grub2-mkconfig -o %s" % location