Procházet zdrojové kódy

Adds SLES and openSUSE support

Alessandro Pilotti před 10 roky
rodič
revize
c1b33d4776

+ 23 - 0
coriolis/osmorphing/base.py

@@ -1,6 +1,7 @@
 import abc
 import abc
 import itertools
 import itertools
 import os
 import os
+import re
 import uuid
 import uuid
 
 
 from coriolis import utils
 from coriolis import utils
@@ -110,3 +111,25 @@ class BaseLinuxOSMorphingTools(BaseOSMorphingTools):
         self._write_file(tmp_file, content)
         self._write_file(tmp_file, content)
         self._exec_cmd_chroot("cp /%s /%s" % (tmp_file, chroot_path))
         self._exec_cmd_chroot("cp /%s /%s" % (tmp_file, chroot_path))
         self._exec_cmd_chroot("rm /%s" % tmp_file)
         self._exec_cmd_chroot("rm /%s" % tmp_file)
+
+    def _enable_systemd_service(self, service_name):
+        self._exec_cmd_chroot("systemctl enable %s.service" % service_name)
+
+    def _get_os_release(self):
+        return self._read_config_file("etc/os-release", check_exists=True)
+
+    def _read_config_file(self, chroot_path, check_exists=False):
+        if not check_exists or self._test_path(chroot_path):
+            content = self._read_file(chroot_path).decode()
+            return self._get_config(content)
+        else:
+            return {}
+
+    def _get_config(self, config_content):
+        config = {}
+        for config_line in config_content.split('\n'):
+            m = re.match('(.*)="?([^"]*)"?', config_line)
+            if m:
+                name, value = m.groups()
+                config[name] = value
+        return config

+ 3 - 1
coriolis/osmorphing/factory.py

@@ -6,6 +6,7 @@ from coriolis import constants
 from coriolis import exception
 from coriolis import exception
 from coriolis.osmorphing import debian
 from coriolis.osmorphing import debian
 from coriolis.osmorphing import redhat
 from coriolis.osmorphing import redhat
+from coriolis.osmorphing import suse
 from coriolis.osmorphing import ubuntu
 from coriolis.osmorphing import ubuntu
 from coriolis.osmorphing import windows
 from coriolis.osmorphing import windows
 
 
@@ -17,7 +18,8 @@ def get_os_morphing_tools(conn, os_type, os_root_dir, target_hypervisor,
     os_morphing_tools_clss = {
     os_morphing_tools_clss = {
         constants.OS_TYPE_LINUX: [debian.DebianMorphingTools,
         constants.OS_TYPE_LINUX: [debian.DebianMorphingTools,
                                   ubuntu.UbuntuMorphingTools,
                                   ubuntu.UbuntuMorphingTools,
-                                  redhat.RedHatMorphingTools],
+                                  redhat.RedHatMorphingTools,
+                                  suse.SUSEMorphingTools],
         constants.OS_TYPE_WINDOWS: [windows.WindowsMorphingTools],
         constants.OS_TYPE_WINDOWS: [windows.WindowsMorphingTools],
         }
         }
 
 

+ 1 - 1
coriolis/osmorphing/osmount/ubuntu.py

@@ -62,7 +62,7 @@ class UbuntuOSMountTools(base.BaseSSHOSMountTools):
                 "sudo ls /dev/%s/*" % vg_name).decode().split('\n')[:-1]
                 "sudo ls /dev/%s/*" % vg_name).decode().split('\n')[:-1]
             dev_paths += lvm_dev_paths
             dev_paths += lvm_dev_paths
 
 
-        valid_filesystems = ['ext2', 'ext3', 'ext4', 'xfs']
+        valid_filesystems = ['ext2', 'ext3', 'ext4', 'xfs', 'btrfs']
 
 
         dev_paths_to_mount = []
         dev_paths_to_mount = []
         for dev_path in dev_paths:
         for dev_path in dev_paths:

+ 0 - 19
coriolis/osmorphing/redhat.py

@@ -79,9 +79,6 @@ class RedHatMorphingTools(base.BaseLinuxOSMorphingTools):
         except:
         except:
             return False
             return False
 
 
-    def _enable_systemd_service(self, service_name):
-        self._exec_cmd_chroot("systemctl enable %s.service" % service_name)
-
     def _set_dhcp_net_config(self, ifcfgs_ethernet):
     def _set_dhcp_net_config(self, ifcfgs_ethernet):
         for ifcfg_file, ifcfg in ifcfgs_ethernet:
         for ifcfg_file, ifcfg in ifcfgs_ethernet:
             if ifcfg.get("BOOTPROTO") == "none":
             if ifcfg.get("BOOTPROTO") == "none":
@@ -181,13 +178,6 @@ class RedHatMorphingTools(base.BaseLinuxOSMorphingTools):
                 not self._test_path(udev_file)):
                 not self._test_path(udev_file)):
             self._write_file_sudo(udev_file, content)
             self._write_file_sudo(udev_file, content)
 
 
-    def _read_config_file(self, chroot_path, check_exists=False):
-        if not check_exists or self._test_path(chroot_path):
-            content = self._read_file(chroot_path).decode()
-            return self._get_config(content)
-        else:
-            return {}
-
     def _write_config_file(self, chroot_path, config_data):
     def _write_config_file(self, chroot_path, config_data):
         content = self._get_config_file_content(config_data)
         content = self._get_config_file_content(config_data)
         self._write_file_sudo(chroot_path, content)
         self._write_file_sudo(chroot_path, content)
@@ -196,15 +186,6 @@ class RedHatMorphingTools(base.BaseLinuxOSMorphingTools):
         return "%s\n" % "\n".join(
         return "%s\n" % "\n".join(
             ['%s="%s"' % (k, v) for k, v in config.items()])
             ['%s="%s"' % (k, v) for k, v in config.items()])
 
 
-    def _get_config(self, config_content):
-        config = {}
-        for config_line in config_content.split('\n'):
-            m = re.match('(.*)="?([^"]*)"?', config_line)
-            if m:
-                name, value = m.groups()
-                config[name] = value
-        return config
-
     def _get_net_config_files(self):
     def _get_net_config_files(self):
         dir_content = self._list_dir(self._NETWORK_SCRIPTS_PATH)
         dir_content = self._list_dir(self._NETWORK_SCRIPTS_PATH)
         return [os.path.join(self._NETWORK_SCRIPTS_PATH, f) for f in
         return [os.path.join(self._NETWORK_SCRIPTS_PATH, f) for f in

+ 105 - 0
coriolis/osmorphing/suse.py

@@ -0,0 +1,105 @@
+import os
+import re
+
+from coriolis import constants
+from coriolis.osmorphing import base
+
+
+class SUSEMorphingTools(base.BaseLinuxOSMorphingTools):
+    _packages = {
+        (constants.HYPERVISOR_VMWARE, None): [("open-vm-tools", True)],
+        (None, constants.PLATFORM_OPENSTACK): [("cloud-init", True)],
+    }
+
+    def _check_os(self):
+        os_release = self._get_os_release()
+        name = os_release.get("NAME")
+        if name == "SLES" or name.startswith("openSUSE"):
+            pretty_name = os_release.get("PRETTY_NAME")
+            if name == "openSUSE Tumbleweed":
+                self._version_id = None
+            else:
+                self._version_id = os_release.get("VERSION_ID")
+            return (name, pretty_name)
+
+        suse_release_path = "etc/SuSE-release"
+        if self._test_path(suse_release_path):
+            out = self._read_file(suse_release_path).decode()
+            release = out.split('\n')[0]
+            version_id = re.findall('^VERSION = (.*)$', out, re.MULTILINE)[0]
+            patch_level = re.findall('^PATCHLEVEL = (.*)$', out, re.MULTILINE)
+            if patch_level:
+                version_id = "%s.%s" % (version_id, patch_level[1])
+            self._version_id = version_id
+            return ('SUSE', release)
+
+    def set_net_config(self, nics_info, dhcp):
+        # TODO: add networking support
+        pass
+
+    def _copy_resolv_conf(self):
+        resolv_conf_path = os.path.join(self._os_root_dir, "etc/resolv.conf")
+        self._exec_cmd("sudo cp -f /etc/resolv.conf %s" % resolv_conf_path)
+
+    def pre_packages_install(self):
+        self._copy_resolv_conf()
+
+        if self._platform == constants.PLATFORM_OPENSTACK:
+            # TODO: use OS version to choose the right repo
+            repo_version_map = {("SLES", "11.4"): "SLE_11_SP4",
+                                ("SLES", "11.3"): "SLE_11_SP3",
+                                ("SLES", "11.2"): "SLE_11_SP2",
+                                ("SLES", "12.1"): "SLE_12_SP1",
+                                ("SLES", "12"): "SLE_12",
+                                ("openSUSE", "13.2"): "openSUSE_13.2",
+                                ("openSUSE Leap", "42.1"):
+                                "openSUSE_Leap_42.1",
+                                ("openSUSE Tumbleweed", None):
+                                "openSUSE_Tumbleweed"}
+
+            repo_version = repo_version_map.get(
+                (self._distro, self._version_id), "SLE_12_SP1")
+
+            repo = "obs://Cloud:Tools/%s" % repo_version
+            self._event_manager.progress_update("Adding repository: %s" % repo)
+            self._exec_cmd_chroot("zypper --non-interactive addrepo -f %s "
+                                  "Cloud-Tools" % repo)
+        self._exec_cmd_chroot(
+            "zypper --non-interactive --no-gpg-checks refresh")
+
+    def _run_dracut(self):
+        package_names = self._exec_cmd_chroot(
+            'rpm -q kernel-default').decode().split('\n')[:-1]
+        for package_name in package_names:
+            m = re.match(r'^kernel-default-(.*)\.\d\..*$', package_name)
+            if m:
+                kernel_version = "%s-default" % m.groups()[0]
+                self._event_manager.progress_update(
+                    "Generating initrd for kernel: %s" % kernel_version)
+                self._exec_cmd_chroot(
+                    "dracut -f /boot/initrd-%(version)s %(version)s" %
+                    {"version": kernel_version})
+
+    def _has_systemd(self):
+        try:
+            self._exec_cmd_chroot("rpm -q systemd")
+            return True
+        except:
+            return False
+
+    def _configure_cloud_init(self):
+        if "cloud-init" in self.get_packages()[0]:
+            if self._has_systemd():
+                self._enable_systemd_service("cloud-init")
+
+    def install_packages(self, package_names):
+        self._exec_cmd_chroot(
+            'zypper --non-interactive install %s' % " ".join(package_names))
+
+    def uninstall_packages(self, package_names):
+        self._exec_cmd_chroot(
+            'zypper --non-interactive remove %s' % " ".join(package_names))
+
+    def post_packages_install(self):
+        self._run_dracut()
+        self._configure_cloud_init()