Alessandro Pilotti 10 лет назад
Родитель
Сommit
41a823bdac

+ 1 - 1
coriolis/osmorphing/base.py

@@ -71,7 +71,7 @@ class BaseOSMorphingTools(object):
         return add, remove
 
     @abc.abstractmethod
-    def set_dhcp(self):
+    def set_net_config(self, nics_info, dhcp):
         pass
 
     def pre_packages_install(self):

+ 7 - 6
coriolis/osmorphing/debian.py

@@ -25,12 +25,13 @@ class DebianMorphingTools(base.BaseOSMorphingTools):
             release = self._read_file(debian_version_path).decode()
             return ('Debian', release)
 
-    def set_dhcp(self):
-        # NOTE: doesn't work with chroot
-        interfaces_path = os.path.join(
-            self._os_root_dir, "etc/network/interfaces")
-        self._exec_cmd('sudo sed -i.bak "s/static/dhcp/g" %s' %
-                       interfaces_path)
+    def set_net_config(self, nics_info, dhcp):
+        if dhcp:
+            # NOTE: doesn't work with chroot
+            interfaces_path = os.path.join(
+                self._os_root_dir, "etc/network/interfaces")
+            self._exec_cmd('sudo sed -i.bak "s/static/dhcp/g" %s' %
+                           interfaces_path)
 
     def pre_packages_install(self):
         apt_get_cmd = 'apt-get update -y'

+ 2 - 2
coriolis/osmorphing/manager.py

@@ -9,7 +9,7 @@ LOG = logging.getLogger(__name__)
 
 
 def morph_image(connection_info, target_hypervisor, target_platform,
-                volume_devs):
+                volume_devs, nics_info):
     (ip, port, username, pkey) = connection_info
 
     LOG.info("Waiting for connectivity on host: %(ip)s:%(port)s",
@@ -29,7 +29,7 @@ def morph_image(connection_info, target_hypervisor, target_platform,
 
     LOG.info('OS being migrated: %s', str(os_info))
 
-    os_morphing_tools.set_dhcp()
+    os_morphing_tools.set_net_config(nics_info, dhcp=True)
     LOG.info("Pre packages")
     os_morphing_tools.pre_packages_install()
 

+ 82 - 39
coriolis/osmorphing/redhat.py

@@ -3,6 +3,7 @@ import re
 import uuid
 
 from oslo_log import log as logging
+import yaml
 
 from coriolis import constants
 from coriolis.osmorphing import base
@@ -14,6 +15,8 @@ RELEASE_RHEL = "Red Hat Enterprise Linux Server"
 RELEASE_CENTOS = "CentOS Linux"
 RELEASE_FEDORA = "Fedora"
 
+DEFAULT_CLOUD_USER = "cloud-user"
+
 
 class RedHatMorphingTools(base.BaseOSMorphingTools):
     _packages = {
@@ -24,7 +27,6 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
             ("cloud-init", True),
             ("cloud-utils-growpart", False)],
     }
-    _CLOUD_INIT_USER = 'centos'
     _NETWORK_SCRIPTS_PATH = "etc/sysconfig/network-scripts"
 
     def check_os(self):
@@ -37,12 +39,37 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
                 distro, version, codename = m.groups()
                 return (distro, version)
 
-    def set_dhcp(self):
-        for ifcfg_file in self._get_net_config_files():
-            ifcfg_content = self._read_file(ifcfg_file).decode()
-            ifcfg = self._get_config(ifcfg_content)
-            if (ifcfg.get("TYPE") == "Ethernet" and
-                    ifcfg.get("BOOTPROTO") == "none"):
+    def _get_net_ifaces_info(self, ifcfgs_ethernet, mac_addresses):
+        net_ifaces_info = []
+
+        for ifcfg_file, ifcfg in ifcfgs_ethernet:
+            mac_address = ifcfg.get("HWADDR")
+            if not mac_address:
+                if len(ifcfgs_ethernet) == 1 and len(mac_addresses) == 1:
+                    mac_address = mac_addresses[0]
+                    LOG.info("HWADDR not defined in: %s, using migration "
+                             "configuration mac_address: %s",
+                             ifcfg_file, mac_address)
+            if not mac_address:
+                LOG.warn("HWADDR not defined, skipping: %s", ifcfg_file)
+                continue
+            name = ifcfg.get("NAME")
+            if not name:
+                # Get the name from the config file
+                name = re.match("^.*/ifcfg-(.*)", ifcfg_file).groups()[0]
+            net_ifaces_info.append((name, mac_address))
+        return net_ifaces_info
+
+    def _add_net_udev_rules(self, net_ifaces_info):
+        udev_file = "etc/udev/rules.d/70-persistent-net.rules"
+        if not self._test_path(udev_file):
+            if net_ifaces_info:
+                content = utils.get_udev_net_rules(net_ifaces_info)
+                self._write_file_sudo(udev_file, content)
+
+    def _set_dhcp_net_config(self, ifcfgs_ethernet):
+        for ifcfg_file, ifcfg in ifcfgs_ethernet:
+            if ifcfg.get("BOOTPROTO") == "none":
                 ifcfg["BOOTPROTO"] = "dhcp"
                 ifcfg["UUID"] = str(uuid.uuid4())
 
@@ -58,14 +85,34 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
                 ifcfg_updated_content = self._get_config_file_content(ifcfg)
                 self._write_file_sudo(ifcfg_file, ifcfg_updated_content)
 
+    def _get_ifcfgs_by_type(self, ifcfg_type):
+        ifcfgs = []
+        for ifcfg_file in self._get_net_config_files():
+            ifcfg_content = self._read_file(ifcfg_file).decode()
+            ifcfg = self._get_config(ifcfg_content)
+            if ifcfg.get("TYPE") == ifcfg_type:
+                ifcfgs.append((ifcfg_file, ifcfg))
+        return ifcfgs
+
+    def set_net_config(self, nics_info, dhcp):
+        ifcfgs_ethernet = self._get_ifcfgs_by_type(self, "Ethernet")
+
+        if dhcp:
+            self._set_dhcp_net_config(ifcfgs_ethernet)
+
+        mac_addresses = [ni.get("mac_address") for ni in nics_info]
+        net_ifaces_info = self._get_net_ifaces_info(ifcfgs_ethernet,
+                                                    mac_addresses)
+        self._add_net_udev_rules(net_ifaces_info)
+
     def install_packages(self, package_names):
-        apt_get_cmd = 'yum install %s -y' % " ".join(package_names)
-        self._exec_cmd_chroot(apt_get_cmd)
+        yum_cmd = 'yum install %s -y' % " ".join(package_names)
+        self._exec_cmd_chroot(yum_cmd)
 
     def uninstall_packages(self, package_names):
         for package_name in package_names:
-            apt_get_cmd = 'yum remove %s -y' % package_name
-            self._exec_cmd_chroot(apt_get_cmd)
+            yum_cmd = 'yum remove %s -y' % package_name
+            self._exec_cmd_chroot(yum_cmd)
 
     def _run_dracut(self):
         package_names = self._exec_cmd_chroot(
@@ -77,10 +124,21 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
                 LOG.info("Generating initrd for kernel: %s", kernel_version)
                 self._exec_cmd_chroot("dracut -f --kver %s" % kernel_version)
 
+    def _get_default_cloud_user(self):
+        cloud_cfg_path = os.path.join(self._os_root_dir, 'etc/cloud/cloud.cfg')
+        if not self._test_path(cloud_cfg_path):
+            raise Exception("cloud-init config file not found: %s" %
+                            cloud_cfg_path)
+        cloud_cfg_content = self._read_file(cloud_cfg_path)
+        cloud_cfg = yaml.load(cloud_cfg_content)
+        return cloud_cfg.get('system_info', {}).get('default_user', {}).get(
+            'name', DEFAULT_CLOUD_USER)
+
     def _add_cloud_init_user(self):
-        if ("cloud-init" in self.get_packages()[0] and not
-                self._check_user_exists(self._CLOUD_INIT_USER)):
-            self._exec_cmd_chroot("useradd %s" % self._CLOUD_INIT_USER)
+        if "cloud-init" in self.get_packages()[0]:
+            cloud_user = self._get_default_cloud_user()
+            if not self._check_user_exists(cloud_user):
+                self._exec_cmd_chroot("useradd %s" % cloud_user)
 
     def _add_hyperv_ballooning_udev_rules(self):
         udev_file = "etc/udev/rules.d/100-balloon.rules"
@@ -90,13 +148,6 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
                 not self._test_path(udev_file)):
             self._write_file_sudo(udev_file, content)
 
-    def _add_net_udev_rules(self):
-        udev_file = "etc/udev/rules.d/70-persistent-net.rules"
-        if not self._test_path(udev_file):
-            net_ifaces_info = self._get_net_ifaces_info()
-            content = utils.get_udev_net_rules(net_ifaces_info)
-            self._write_file_sudo(udev_file, content)
-
     def _get_config_file_content(self, config):
         return "%s\n" % "\n".join(
             ['%s="%s"' % (k, v) for k, v in config.items()])
@@ -115,28 +166,20 @@ class RedHatMorphingTools(base.BaseOSMorphingTools):
         return [os.path.join(self._NETWORK_SCRIPTS_PATH, f) for f in
                 dir_content if re.match("^ifcfg-(.*)", f)]
 
-    def _get_net_ifaces_info(self):
-        net_ifaces_info = []
-        for ifcfg_file in self._get_net_config_files():
-            ifcfg_content = self._read_file(ifcfg_file).decode()
-            ifcfg = self._get_config(ifcfg_content)
-            if ifcfg.get("TYPE") == "Ethernet":
-                mac_address = ifcfg.get("HWADDR")
-                if not mac_address:
-                    LOG.warn("HWADDR not defined in: %s", ifcfg_file)
-                    continue
-                name = ifcfg.get("NAME")
-                if not name:
-                    # Get the name from the config file
-                    name = re.match("^.*/ifcfg-(.*)", ifcfg_file).groups()[0]
-                net_ifaces_info.append((name, mac_address))
-        return net_ifaces_info
-
     def _set_selinux_autorelabel(self):
         self._exec_cmd_chroot("touch /.autorelabel")
 
+    def pre_packages_install(self):
+        distro, version = self.check_os()
+        if distro == RELEASE_RHEL and "cloud-init" in self.get_packages()[0]:
+            major_version = version.split(".")[0]
+            repo_name = "rhel-%s-server-rh-common-rpms" % major_version
+            # This is necessary for cloud-init
+            LOG.info("Enabling repository: %s" % repo_name)
+            self._exec_cmd_chroot(
+                "subscription-manager repos --enable %s" % repo_name)
+
     def post_packages_install(self):
-        self._add_net_udev_rules()
         self._add_hyperv_ballooning_udev_rules()
         self._run_dracut()
         self._add_cloud_init_user()

+ 7 - 5
coriolis/providers/openstack/__init__.py

@@ -332,6 +332,8 @@ class ImportProvider(base.BaseExportProvider):
             nova, glance, neutron, migr_image_name, migr_flavor_name,
             migr_network_name, migr_fip_pool_name)
 
+        nics_info = export_info["devices"].get("nics", [])
+
         try:
             for i, volume in enumerate(volumes):
                 self._wait_for_volume(nova, volume, 'available')
@@ -345,15 +347,15 @@ class ImportProvider(base.BaseExportProvider):
 
                 guest_conn_info = migr_resources.get_guest_connection_info()
 
-                osmorphing_manager.morph_image(guest_conn_info,
-                                               hypervisor_type,
-                                               constants.PLATFORM_OPENSTACK,
-                                               volume_devs)
+            osmorphing_manager.morph_image(guest_conn_info,
+                                           hypervisor_type,
+                                           constants.PLATFORM_OPENSTACK,
+                                           volume_devs,
+                                           nics_info)
         finally:
             migr_resources.delete()
 
         ports = []
-        nics_info = export_info["devices"].get("nics", [])
         for nic_info in nics_info:
             ports.append(self._create_neutron_port(
                 neutron, network_name, nic_info.get("mac_address")))

+ 1 - 0
coriolis/utils.py

@@ -91,6 +91,7 @@ def list_ssh_dir(ssh, remote_path):
 
 @retry_on_error()
 def exec_ssh_cmd(ssh, cmd):
+    LOG.debug("Executing SSH command: %s", cmd)
     stdin, stdout, stderr = ssh.exec_command(cmd)
     exit_code = stdout.channel.recv_exit_status()
     std_out = stdout.read()