mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-03 13:47:18 +03:00
unattended: Split out make_installconfig
The building process here is mostly independent of the InstallScript object. Moving it to its own function makes that more clear, makes InstallScript smaller, and the code is indented less
This commit is contained in:
parent
e87e3a71fe
commit
1f6879c811
@ -175,9 +175,9 @@ class InstallerTreeMedia(object):
|
||||
def prepare(self, guest, meter):
|
||||
cmdline = None
|
||||
if self._unattended_data:
|
||||
script, config = unattended.prepare_install_script(
|
||||
script = unattended.prepare_install_script(
|
||||
guest, self._unattended_data)
|
||||
path, cmdline = unattended.generate_install_script(script, config)
|
||||
path, cmdline = unattended.generate_install_script(script)
|
||||
|
||||
self.initrd_injections.append(path)
|
||||
self._tmpfiles.append(path)
|
||||
|
@ -18,6 +18,114 @@ from gi.repository import GLib
|
||||
from . import util
|
||||
|
||||
|
||||
def _make_installconfig(script, osobj, unattended_data, arch, hostname):
|
||||
"""
|
||||
Build a Libosinfo.InstallConfig instance
|
||||
"""
|
||||
def get_timezone():
|
||||
TZ_FILE = "/etc/localtime"
|
||||
localtime = Gio.File.new_for_path(TZ_FILE)
|
||||
if not localtime.query_exists():
|
||||
return None
|
||||
info = localtime.query_info(
|
||||
Gio.FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
|
||||
if not info:
|
||||
return None
|
||||
target = info.get_symlink_target()
|
||||
if not target:
|
||||
return None
|
||||
tokens = target.split("zoneinfo/")
|
||||
if not tokens or len(tokens) < 2:
|
||||
return None
|
||||
return tokens[1]
|
||||
|
||||
def get_language():
|
||||
names = GLib.get_language_names()
|
||||
if not names or len(names) < 2:
|
||||
return None
|
||||
return names[1]
|
||||
|
||||
config = Libosinfo.InstallConfig()
|
||||
|
||||
# Set user login and name based on the one from the system
|
||||
config.set_user_login(GLib.get_user_name())
|
||||
config.set_user_realname(GLib.get_real_name())
|
||||
|
||||
# Set user-password.
|
||||
# In case it's required and not passed, just raise a RuntimeError.
|
||||
if script.requires_user_password() and not unattended_data.user_password:
|
||||
raise RuntimeError(
|
||||
_("%s requires the user-password to be set.") %
|
||||
osobj.name)
|
||||
config.set_user_password(
|
||||
unattended_data.user_password if unattended_data.user_password
|
||||
else "")
|
||||
|
||||
# Set the admin-password:
|
||||
# In case it's required and not passed, just raise a RuntimeError.
|
||||
if script.requires_admin_password() and not unattended_data.admin_password:
|
||||
raise RuntimeError(
|
||||
_("%s requires the admin-password to be set.") %
|
||||
osobj.name)
|
||||
config.set_admin_password(
|
||||
unattended_data.admin_password if unattended_data.admin_password
|
||||
else "")
|
||||
|
||||
# Set the target disk.
|
||||
# virtiodisk is the preferred way, in case it's supported, otherwise
|
||||
# just fallback to scsi.
|
||||
#
|
||||
# Note: this is linux specific and will require some changes whenever
|
||||
# support for Windows will be added.
|
||||
tgt = "/dev/vda" if osobj.supports_virtiodisk() else "/dev/sda"
|
||||
config.set_target_disk(tgt)
|
||||
|
||||
# Set hardware architecture and hostname
|
||||
config.set_hardware_arch(arch)
|
||||
config.set_hostname(hostname)
|
||||
|
||||
# Try to guess the timezone from '/etc/localtime', in case it's not
|
||||
# possible 'America/New_York' will be used.
|
||||
timezone = get_timezone()
|
||||
if timezone:
|
||||
config.set_l10n_timezone(timezone)
|
||||
else:
|
||||
logging.warning(
|
||||
_("'America/New_York' timezone will be used for this "
|
||||
"unattended installation."))
|
||||
|
||||
# Try to guess to language and keyboard layout from the system's
|
||||
# language.
|
||||
#
|
||||
# This method has flows as it's quite common to have language and
|
||||
# keyboard layout not matching. Otherwise, there's no easy way to guess
|
||||
# the keyboard layout without relying on a set of APIs of an specific
|
||||
# Desktop Environment.
|
||||
language = get_language()
|
||||
if language:
|
||||
config.set_l10n_language(language)
|
||||
config.set_l10n_keyboard(language)
|
||||
else:
|
||||
logging.warning(
|
||||
_("'en_US' will be used as both language and keyboard layout "
|
||||
"for unattended installation."))
|
||||
|
||||
logging.debug("InstallScriptConfig created with the following params:")
|
||||
logging.debug("username: %s", config.get_user_login())
|
||||
logging.debug("realname: %s", config.get_user_realname())
|
||||
logging.debug("user password: %s", config.get_user_password())
|
||||
logging.debug("admin password: %s", config.get_admin_password())
|
||||
logging.debug("target disk: %s", config.get_target_disk())
|
||||
logging.debug("hardware arch: %s", config.get_hardware_arch())
|
||||
logging.debug("hostname: %s", config.get_hostname())
|
||||
logging.debug("timezone: %s", config.get_l10n_timezone())
|
||||
logging.debug("language: %s", config.get_l10n_language())
|
||||
logging.debug("keyboard: %s", config.get_l10n_keyboard())
|
||||
|
||||
return config
|
||||
|
||||
|
||||
class OSInstallScript:
|
||||
"""
|
||||
Wrapper for Libosinfo.InstallScript interactions
|
||||
@ -29,6 +137,7 @@ class OSInstallScript:
|
||||
def __init__(self, script, osobj):
|
||||
self._script = script
|
||||
self._osobj = osobj
|
||||
self._config = None
|
||||
|
||||
if not OSInstallScript.have_new_libosinfo():
|
||||
raise RuntimeError(_("libosinfo is too old to support unattended "
|
||||
@ -86,131 +195,27 @@ class OSInstallScript:
|
||||
logging.debug("Using '%s' installation source", source)
|
||||
self._script.set_installation_source(installation_source)
|
||||
|
||||
def get_config(self, unattended_data, arch, hostname):
|
||||
def requires_param(config_param):
|
||||
param = self._script.get_config_param(config_param)
|
||||
def _requires_param(self, config_param):
|
||||
param = self._script.get_config_param(config_param)
|
||||
return bool(param and not param.is_optional())
|
||||
|
||||
if not param or param.is_optional():
|
||||
return False
|
||||
def requires_user_password(self):
|
||||
return self._requires_param(
|
||||
Libosinfo.INSTALL_CONFIG_PROP_USER_PASSWORD)
|
||||
def requires_admin_password(self):
|
||||
return self._requires_param(
|
||||
Libosinfo.INSTALL_CONFIG_PROP_ADMIN_PASSWORD)
|
||||
|
||||
return True
|
||||
def set_config(self, config):
|
||||
self._config = config
|
||||
|
||||
def requires_user_password():
|
||||
return requires_param(Libosinfo.INSTALL_CONFIG_PROP_USER_PASSWORD)
|
||||
|
||||
def requires_admin_password():
|
||||
return requires_param(Libosinfo.INSTALL_CONFIG_PROP_ADMIN_PASSWORD)
|
||||
|
||||
def get_timezone():
|
||||
TZ_FILE = "/etc/localtime"
|
||||
localtime = Gio.File.new_for_path(TZ_FILE)
|
||||
if not localtime.query_exists():
|
||||
return None
|
||||
info = localtime.query_info(
|
||||
Gio.FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
|
||||
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
|
||||
if not info:
|
||||
return None
|
||||
target = info.get_symlink_target()
|
||||
if not target:
|
||||
return None
|
||||
tokens = target.split("zoneinfo/")
|
||||
if not tokens or len(tokens) < 2:
|
||||
return None
|
||||
return tokens[1]
|
||||
|
||||
def get_language():
|
||||
names = GLib.get_language_names()
|
||||
if not names or len(names) < 2:
|
||||
return None
|
||||
return names[1]
|
||||
|
||||
config = Libosinfo.InstallConfig()
|
||||
|
||||
# Set user login and name based on the one from the system
|
||||
config.set_user_login(GLib.get_user_name())
|
||||
config.set_user_realname(GLib.get_real_name())
|
||||
|
||||
# Set user-password.
|
||||
# In case it's required and not passed, just raise a RuntimeError.
|
||||
if requires_user_password() and not unattended_data.user_password:
|
||||
raise RuntimeError(
|
||||
_("%s requires the user-password to be set.") %
|
||||
self._osobj.name)
|
||||
config.set_user_password(
|
||||
unattended_data.user_password if unattended_data.user_password
|
||||
else "")
|
||||
|
||||
# Set the admin-password:
|
||||
# In case it's required and not passed, just raise a RuntimeError.
|
||||
if requires_admin_password() and not unattended_data.admin_password:
|
||||
raise RuntimeError(
|
||||
_("%s requires the admin-password to be set.") %
|
||||
self._osobj.name)
|
||||
config.set_admin_password(
|
||||
unattended_data.admin_password if unattended_data.admin_password
|
||||
else "")
|
||||
|
||||
# Set the target disk.
|
||||
# virtiodisk is the preferred way, in case it's supported, otherwise
|
||||
# just fallback to scsi.
|
||||
#
|
||||
# Note: this is linux specific and will require some changes whenever
|
||||
# support for Windows will be added.
|
||||
tgt = "/dev/vda" if self._osobj.supports_virtiodisk() else "/dev/sda"
|
||||
config.set_target_disk(tgt)
|
||||
|
||||
# Set hardware architecture and hostname
|
||||
config.set_hardware_arch(arch)
|
||||
config.set_hostname(hostname)
|
||||
|
||||
# Try to guess the timezone from '/etc/localtime', in case it's not
|
||||
# possible 'America/New_York' will be used.
|
||||
timezone = get_timezone()
|
||||
if timezone:
|
||||
config.set_l10n_timezone(timezone)
|
||||
else:
|
||||
logging.warning(
|
||||
_("'America/New_York' timezone will be used for this "
|
||||
"unattended installation."))
|
||||
|
||||
# Try to guess to language and keyboard layout from the system's
|
||||
# language.
|
||||
#
|
||||
# This method has flows as it's quite common to have language and
|
||||
# keyboard layout not matching. Otherwise, there's no easy way to guess
|
||||
# the keyboard layout without relying on a set of APIs of an specific
|
||||
# Desktop Environment.
|
||||
language = get_language()
|
||||
if language:
|
||||
config.set_l10n_language(language)
|
||||
config.set_l10n_keyboard(language)
|
||||
else:
|
||||
logging.warning(
|
||||
_("'en_US' will be used as both language and keyboard layout "
|
||||
"for unattended installation."))
|
||||
|
||||
logging.debug("InstallScriptConfig created with the following params:")
|
||||
logging.debug("username: %s", config.get_user_login())
|
||||
logging.debug("realname: %s", config.get_user_realname())
|
||||
logging.debug("user password: %s", config.get_user_password())
|
||||
logging.debug("admin password: %s", config.get_admin_password())
|
||||
logging.debug("target disk: %s", config.get_target_disk())
|
||||
logging.debug("hardware arch: %s", config.get_hardware_arch())
|
||||
logging.debug("hostname: %s", config.get_hostname())
|
||||
logging.debug("timezone: %s", config.get_l10n_timezone())
|
||||
logging.debug("language: %s", config.get_l10n_language())
|
||||
logging.debug("keyboard: %s", config.get_l10n_keyboard())
|
||||
|
||||
return config
|
||||
|
||||
def generate_output(self, config, output_dir):
|
||||
def generate_output(self, output_dir):
|
||||
self._script.generate_output(
|
||||
self._osobj.get_handle(), config, output_dir)
|
||||
self._osobj.get_handle(), self._config, output_dir)
|
||||
|
||||
def generate_cmdline(self, config):
|
||||
def generate_cmdline(self):
|
||||
return self._script.generate_command_line(
|
||||
self._osobj.get_handle(), config)
|
||||
self._osobj.get_handle(), self._config)
|
||||
|
||||
|
||||
class UnattendedData():
|
||||
@ -228,17 +233,19 @@ def prepare_install_script(guest, unattended_data):
|
||||
script.set_preferred_injection_method("initrd")
|
||||
script.set_installation_source("network")
|
||||
|
||||
config = script.get_config(unattended_data, guest.os.arch, guest.name)
|
||||
return script, config
|
||||
config = _make_installconfig(script, guest.osinfo, unattended_data,
|
||||
guest.os.arch, guest.name)
|
||||
script.set_config(config)
|
||||
return script
|
||||
|
||||
|
||||
def generate_install_script(script, config):
|
||||
def generate_install_script(script):
|
||||
scratch = os.path.join(util.get_cache_dir(), "unattended")
|
||||
if not os.path.exists(scratch):
|
||||
os.makedirs(scratch, 0o751)
|
||||
|
||||
script.generate_output(config, Gio.File.new_for_path(scratch))
|
||||
script.generate_output(Gio.File.new_for_path(scratch))
|
||||
path = os.path.join(scratch, script.get_expected_filename())
|
||||
cmdline = script.generate_cmdline(config)
|
||||
cmdline = script.generate_cmdline()
|
||||
|
||||
return path, cmdline
|
||||
|
Loading…
x
Reference in New Issue
Block a user