Skip to content
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
101 changes: 71 additions & 30 deletions coriolis/osmorphing/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
REQUIRED_DETECTED_OS_FIELDS = [
"os_type", "distribution_name", "release_version",
"friendly_release_name"]
DEFAULT_CLOUD_USER = "cloud-user"


class BaseOSMorphingTools(object, with_metaclass(abc.ABCMeta)):
Expand Down Expand Up @@ -393,39 +394,79 @@ def _set_selinux_autorelabel(self):
except Exception as err:
LOG.warning("Failed to set autorelabel: %r" % err)

def _configure_cloud_init_user_retention(self):
cloud_cfg_paths = ["/etc/cloud/cloud.cfg"]
def _write_cloud_init_mods_config(self, cloud_cfg):
cloud_cfgs_dir = "/etc/cloud/cloud.cfg.d"
if self._test_path(cloud_cfgs_dir):
for path in self._exec_cmd_chroot(
'ls -1 %s' % cloud_cfgs_dir).decode().splitlines():
if path.endswith('.cfg'):
cloud_cfg_paths.append("%s/%s" % (cloud_cfgs_dir, path))

cloud_config_path = f"{cloud_cfgs_dir}/99_coriolis.cfg"
if not self._test_path(cloud_cfgs_dir):
self._exec_cmd_chroot("mkdir -p %s" % cloud_cfgs_dir)
self._event_manager.progress_update(
"Reconfiguring cloud-init to retain original user credentials")
for cloud_cfg_path in cloud_cfg_paths:
if not self._test_path(cloud_cfg_path):
LOG.warn("Could not find %s. Skipping reconfiguration." % (
cloud_cfg_path))
continue
"Customizing cloud-init configuration")
new_cloud_cfg = yaml.dump(cloud_cfg, Dumper=yaml.SafeDumper)
self._write_file_sudo(cloud_config_path, new_cloud_cfg)

def _disable_installer_cloud_config(self):
installer_config_path = "/etc/cloud/cloud.cfg.d/99-installer.cfg"
if self._test_path(installer_config_path):
self._event_manager.progress_update(
"Disabling installer-generated cloud-config")
self._exec_cmd_chroot(
f"mv {installer_config_path} {installer_config_path}.bak")

def _ensure_cloud_init_not_disabled(self):
disabler_file = "/etc/cloud/cloud-init.disabled"
system_conf_disabler = "/etc/systemd/system.conf"
grub_conf_disabler = "/etc/default/grub"
if self._test_path(disabler_file):
self._exec_cmd_chroot(f"rm {disabler_file}")
if self._test_path(system_conf_disabler):
self._exec_cmd_chroot(
"sed -i '/cloud-init=disabled/d' %s" % system_conf_disabler)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this will work as you expect it, it could just leave an empty variable and maybe even bork the system.conf file. If you haven't already, please do a test and see if it gets enabled and systemd doesn't just fall on its head.
Let me know if you already tested this and it works.

if self._test_path(grub_conf_disabler):
self._exec_cmd_chroot(
"sed -i '/cloud-init=disabled/d' %s" % grub_conf_disabler)
self._execute_update_grub()

def _reset_cloud_init_run(self):
self._exec_cmd_chroot("cloud-init clean --logs")

def _get_default_cloud_user(self):
cloud_cfg_path = 'etc/cloud/cloud.cfg'
if not self._test_path(cloud_cfg_path):
return DEFAULT_CLOUD_USER
cloud_cfg_content = self._read_file_sudo(cloud_cfg_path)
cloud_cfg = yaml.load(cloud_cfg_content, Loader=yaml.SafeLoader)
return cloud_cfg.get('system_info', {}).get('default_user', {}).get(
'name', DEFAULT_CLOUD_USER)

def _create_cloudinit_user(self):
cloud_user = self._get_default_cloud_user()
if not self._check_user_exists(cloud_user):
self._exec_cmd_chroot("useradd %s" % cloud_user)

def _configure_cloud_init(self):
cloud_cfg_mods = {}
if "cloud-init" not in self.get_packages()[0]:
return

self._disable_installer_cloud_config()
self._ensure_cloud_init_not_disabled()
self._reset_cloud_init_run()

if self._osmorphing_parameters.get('retain_user_credentials', False):
cloud_cfg_user_retention = {
'disable_root': False,
'ssh_pwauth': True,
'users': None
}
cloud_cfg_mods.update(cloud_cfg_user_retention)
else:
self._create_cloudinit_user()

if not self._osmorphing_parameters.get('set_dhcp', True):
disabled_network_config = {"network": {"config": "disabled"}}
cloud_cfg_mods.update(disabled_network_config)

try:
self._exec_cmd_chroot(
"cp %s %s.bak" % (cloud_cfg_path, cloud_cfg_path))

cloud_cfg = yaml.load(self._read_file(cloud_cfg_path),
Loader=yaml.SafeLoader)

cloud_cfg['disable_root'] = False
cloud_cfg['ssh_pwauth'] = True
cloud_cfg['users'] = None
new_cloud_cfg = yaml.dump(cloud_cfg)
self._write_file_sudo(cloud_cfg_path, new_cloud_cfg)
except Exception as err:
raise exception.CoriolisException(
"Failed to reconfigure cloud-init to retain user "
"credentials. Error was: %s" % str(err)) from err
self._write_cloud_init_mods_config(cloud_cfg_mods)

def _test_path_chroot(self, path):
# This method uses _exec_cmd_chroot() instead of SFTP stat()
Expand Down
13 changes: 13 additions & 0 deletions coriolis/osmorphing/debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ def _compose_netplan_cfg(self, nics_info):
}
return yaml.dump(cfg, default_flow_style=False)

def _has_systemd_chroot(self):
return self._test_path("/lib/systemd/system")

def set_net_config(self, nics_info, dhcp):
if not dhcp:
LOG.info("Setting static IP configuration")
Expand Down Expand Up @@ -124,6 +127,11 @@ def set_net_config(self, nics_info, dhcp):
cfg_name = "%s/coriolis_netplan.yaml" % self.netplan_base
self._write_file_sudo(cfg_name, new_cfg)

def _configure_cloud_init(self):
super(BaseDebianMorphingTools, self)._configure_cloud_init()
if self._has_systemd_chroot():
self._enable_systemd_service("cloud-init")

def get_installed_packages(self):
cmd = "dpkg-query -f '${binary:Package}\\n' -W"
try:
Expand Down Expand Up @@ -155,6 +163,11 @@ def pre_packages_install(self, package_names):
"OSMorphing minion machine on the target platform. Original "
"error was: %s" % str(err)) from err

def post_packages_install(self, package_names):
self._configure_cloud_init()
super(BaseDebianMorphingTools, self).post_packages_install(
package_names)

def install_packages(self, package_names):
try:
# NOTE(aznashwan): in the rare event that a replica sync occurs
Expand Down
11 changes: 11 additions & 0 deletions coriolis/osmorphing/redhat.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ def pre_packages_install(self, package_names):
else:
LOG.debug("Skipping package 'grubby' as it's already installed")

def post_packages_install(self, package_names):
self._configure_cloud_init()
self._run_dracut()
super(BaseRedHatMorphingTools, self).post_packages_install(
package_names)

def install_packages(self, package_names):
enable_repos = self._get_repos_to_enable()
self._yum_install(package_names, enable_repos)
Expand All @@ -282,6 +288,11 @@ def _set_network_nozeroconf_config(self):
network_cfg["NOZEROCONF"] = "yes"
self._write_config_file(network_cfg_file, network_cfg)

def _configure_cloud_init(self):
super(BaseRedHatMorphingTools, self)._configure_cloud_init()
if self._has_systemd():
self._enable_systemd_service("cloud-init")

def _write_config_file(self, chroot_path, config_data):
content = self._get_config_file_content(config_data)
self._write_file_sudo(chroot_path, content)
Expand Down
10 changes: 10 additions & 0 deletions coriolis/osmorphing/suse.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ def _has_systemd(self):
except Exception:
return False

def _configure_cloud_init(self):
super(BaseSUSEMorphingTools, self)._configure_cloud_init()
if self._has_systemd():
self._enable_systemd_service("cloud-init")

def post_packages_install(self, package_names):
self._configure_cloud_init()
self._run_dracut()
super(BaseSUSEMorphingTools, self).post_packages_install(package_names)

def _enable_sles_module(self, module):
available_modules = self._exec_cmd_chroot(
"SUSEConnect --list-extensions").decode()
Expand Down
Loading