893 lines
31 KiB
Python
893 lines
31 KiB
Python
#!/usr/bin/python -tt
|
|
#
|
|
# Copyright (c) 2007 Red Hat, Inc.
|
|
# Copyright (c) 2009, 2010, 2011 Intel, Inc.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by the Free
|
|
# Software Foundation; version 2 of the License
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
# for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along
|
|
# with this program; if not, write to the Free Software Foundation, Inc., 59
|
|
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
import os, sys, re
|
|
import shutil
|
|
import subprocess
|
|
import string
|
|
|
|
import pykickstart.sections as kssections
|
|
import pykickstart.commands as kscommands
|
|
import pykickstart.constants as ksconstants
|
|
import pykickstart.errors as kserrors
|
|
import pykickstart.parser as ksparser
|
|
import pykickstart.version as ksversion
|
|
from pykickstart.handlers.control import commandMap
|
|
from pykickstart.handlers.control import dataMap
|
|
|
|
from mic import msger
|
|
from mic.utils import errors, misc, runner, fs_related as fs
|
|
from custom_commands import desktop, micrepo, micboot, partition, installerfw
|
|
|
|
|
|
AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
|
|
|
|
|
|
class PrepackageSection(kssections.Section):
|
|
sectionOpen = "%prepackages"
|
|
|
|
def handleLine(self, line):
|
|
if not self.handler:
|
|
return
|
|
|
|
(h, s, t) = line.partition('#')
|
|
line = h.rstrip()
|
|
|
|
self.handler.prepackages.add([line])
|
|
|
|
def handleHeader(self, lineno, args):
|
|
kssections.Section.handleHeader(self, lineno, args)
|
|
|
|
class AttachmentSection(kssections.Section):
|
|
sectionOpen = "%attachment"
|
|
|
|
def handleLine(self, line):
|
|
if not self.handler:
|
|
return
|
|
|
|
(h, s, t) = line.partition('#')
|
|
line = h.rstrip()
|
|
|
|
self.handler.attachment.add([line])
|
|
|
|
def handleHeader(self, lineno, args):
|
|
kssections.Section.handleHeader(self, lineno, args)
|
|
|
|
def apply_wrapper(func):
|
|
def wrapper(*kargs, **kwargs):
|
|
try:
|
|
func(*kargs, **kwargs)
|
|
except (OSError, IOError, errors.KsError), err:
|
|
cfgcls = kargs[0].__class__.__name__
|
|
if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
|
|
msger.warning("%s" % err)
|
|
pass
|
|
else:
|
|
# just throw out the exception
|
|
raise
|
|
return wrapper
|
|
|
|
def read_kickstart(path):
|
|
"""Parse a kickstart file and return a KickstartParser instance.
|
|
|
|
This is a simple utility function which takes a path to a kickstart file,
|
|
parses it and returns a pykickstart KickstartParser instance which can
|
|
be then passed to an ImageCreator constructor.
|
|
|
|
If an error occurs, a CreatorError exception is thrown.
|
|
"""
|
|
|
|
#version = ksversion.makeVersion()
|
|
#ks = ksparser.KickstartParser(version)
|
|
|
|
using_version = ksversion.DEVEL
|
|
commandMap[using_version]["desktop"] = desktop.Mic_Desktop
|
|
commandMap[using_version]["repo"] = micrepo.Mic_Repo
|
|
commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
|
|
commandMap[using_version]["part"] = partition.Wic_Partition
|
|
commandMap[using_version]["partition"] = partition.Wic_Partition
|
|
commandMap[using_version]["installerfw"] = installerfw.Mic_installerfw
|
|
dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
|
|
dataMap[using_version]["PartData"] = partition.Wic_PartData
|
|
superclass = ksversion.returnClassForVersion(version=using_version)
|
|
|
|
class KSHandlers(superclass):
|
|
def __init__(self):
|
|
superclass.__init__(self, mapping=commandMap[using_version])
|
|
self.prepackages = ksparser.Packages()
|
|
self.attachment = ksparser.Packages()
|
|
|
|
ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
|
|
ks.registerSection(PrepackageSection(ks.handler))
|
|
ks.registerSection(AttachmentSection(ks.handler))
|
|
|
|
try:
|
|
ks.readKickstart(path)
|
|
except (kserrors.KickstartParseError, kserrors.KickstartError), err:
|
|
if msger.ask("Errors occured on kickstart file, skip and continue?"):
|
|
msger.warning("%s" % err)
|
|
pass
|
|
else:
|
|
raise errors.KsError("%s" % err)
|
|
|
|
return ks
|
|
|
|
class KickstartConfig(object):
|
|
"""A base class for applying kickstart configurations to a system."""
|
|
def __init__(self, instroot):
|
|
self.instroot = instroot
|
|
|
|
def path(self, subpath):
|
|
return self.instroot + subpath
|
|
|
|
def _check_sysconfig(self):
|
|
if not os.path.exists(self.path("/etc/sysconfig")):
|
|
fs.makedirs(self.path("/etc/sysconfig"))
|
|
|
|
def chroot(self):
|
|
os.chroot(self.instroot)
|
|
os.chdir("/")
|
|
|
|
def call(self, args):
|
|
if not os.path.exists("%s/%s" %(self.instroot, args[0])):
|
|
raise errors.KsError("Can't find %s in chroot" % args[0])
|
|
subprocess.call(args, preexec_fn = self.chroot)
|
|
|
|
def apply(self):
|
|
pass
|
|
|
|
class LanguageConfig(KickstartConfig):
|
|
"""A class to apply a kickstart language configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, kslang):
|
|
self._check_sysconfig()
|
|
if kslang.lang:
|
|
f = open(self.path("/etc/sysconfig/i18n"), "w+")
|
|
f.write("LANG=\"" + kslang.lang + "\"\n")
|
|
f.close()
|
|
|
|
class KeyboardConfig(KickstartConfig):
|
|
"""A class to apply a kickstart keyboard configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, kskeyboard):
|
|
#
|
|
# FIXME:
|
|
# should this impact the X keyboard config too?
|
|
# or do we want to make X be able to do this mapping?
|
|
#
|
|
#k = rhpl.keyboard.Keyboard()
|
|
#if kskeyboard.keyboard:
|
|
# k.set(kskeyboard.keyboard)
|
|
#k.write(self.instroot)
|
|
pass
|
|
|
|
class TimezoneConfig(KickstartConfig):
|
|
"""A class to apply a kickstart timezone configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, kstimezone):
|
|
self._check_sysconfig()
|
|
tz = kstimezone.timezone or "America/New_York"
|
|
utc = str(kstimezone.isUtc)
|
|
|
|
f = open(self.path("/etc/sysconfig/clock"), "w+")
|
|
f.write("ZONE=\"" + tz + "\"\n")
|
|
f.write("UTC=" + utc + "\n")
|
|
f.close()
|
|
tz_source = "/usr/share/zoneinfo/%s" % (tz)
|
|
tz_dest = "/etc/localtime"
|
|
try:
|
|
cpcmd = fs.find_binary_inchroot('cp', self.instroot)
|
|
if cpcmd:
|
|
self.call([cpcmd, "-f", tz_source, tz_dest])
|
|
else:
|
|
cpcmd = fs.find_binary_path('cp')
|
|
subprocess.call([cpcmd, "-f",
|
|
self.path(tz_source),
|
|
self.path(tz_dest)])
|
|
except (IOError, OSError), (errno, msg):
|
|
raise errors.KsError("Timezone setting error: %s" % msg)
|
|
|
|
class AuthConfig(KickstartConfig):
|
|
"""A class to apply a kickstart authconfig configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, ksauthconfig):
|
|
auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
|
|
args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
|
|
self.call(args + auth.split())
|
|
|
|
class FirewallConfig(KickstartConfig):
|
|
"""A class to apply a kickstart firewall configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, ksfirewall):
|
|
#
|
|
# FIXME: should handle the rest of the options
|
|
#
|
|
if not os.path.exists(self.path("/usr/sbin/lokkit")):
|
|
return
|
|
if ksfirewall.enabled:
|
|
status = "--enabled"
|
|
else:
|
|
status = "--disabled"
|
|
|
|
self.call(["/usr/sbin/lokkit",
|
|
"-f", "--quiet", "--nostart", status])
|
|
|
|
class RootPasswordConfig(KickstartConfig):
|
|
"""A class to apply a kickstart root password configuration to a system."""
|
|
def unset(self):
|
|
self.call(["/usr/bin/passwd", "-d", "root"])
|
|
|
|
def set_encrypted(self, password):
|
|
self.call(["/usr/sbin/usermod", "-p", password, "root"])
|
|
|
|
def set_unencrypted(self, password):
|
|
for p in ("/bin/echo", "/usr/sbin/chpasswd"):
|
|
if not os.path.exists("%s/%s" %(self.instroot, p)):
|
|
raise errors.KsError("Unable to set unencrypted password due "
|
|
"to lack of %s" % p)
|
|
|
|
p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
|
|
stdout = subprocess.PIPE,
|
|
preexec_fn = self.chroot)
|
|
p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
|
|
stdin = p1.stdout,
|
|
stdout = subprocess.PIPE,
|
|
preexec_fn = self.chroot)
|
|
p2.communicate()
|
|
|
|
@apply_wrapper
|
|
def apply(self, ksrootpw):
|
|
if ksrootpw.isCrypted:
|
|
self.set_encrypted(ksrootpw.password)
|
|
elif ksrootpw.password != "":
|
|
self.set_unencrypted(ksrootpw.password)
|
|
else:
|
|
self.unset()
|
|
|
|
class UserConfig(KickstartConfig):
|
|
def set_empty_passwd(self, user):
|
|
self.call(["/usr/bin/passwd", "-d", user])
|
|
|
|
def set_encrypted_passwd(self, user, password):
|
|
self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
|
|
|
|
def set_unencrypted_passwd(self, user, password):
|
|
for p in ("/bin/echo", "/usr/sbin/chpasswd"):
|
|
if not os.path.exists("%s/%s" %(self.instroot, p)):
|
|
raise errors.KsError("Unable to set unencrypted password due "
|
|
"to lack of %s" % p)
|
|
|
|
p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
|
|
stdout = subprocess.PIPE,
|
|
preexec_fn = self.chroot)
|
|
p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
|
|
stdin = p1.stdout,
|
|
stdout = subprocess.PIPE,
|
|
preexec_fn = self.chroot)
|
|
p2.communicate()
|
|
|
|
def addUser(self, userconfig):
|
|
args = [ "/usr/sbin/useradd" ]
|
|
if userconfig.groups:
|
|
args += [ "--groups", string.join(userconfig.groups, ",") ]
|
|
if userconfig.name:
|
|
args += [ "-m"]
|
|
args += [ "-d", "/home/%s" % userconfig.name ]
|
|
args.append(userconfig.name)
|
|
try:
|
|
dev_null = os.open("/dev/null", os.O_WRONLY)
|
|
msger.debug('adding user with %s' % args)
|
|
subprocess.call(args,
|
|
stdout = dev_null,
|
|
stderr = dev_null,
|
|
preexec_fn = self.chroot)
|
|
os.close(dev_null)
|
|
except:
|
|
msger.warning('Cannot add user using "useradd"')
|
|
|
|
if userconfig.password not in (None, ""):
|
|
if userconfig.isCrypted:
|
|
self.set_encrypted_passwd(userconfig.name,
|
|
userconfig.password)
|
|
else:
|
|
self.set_unencrypted_passwd(userconfig.name,
|
|
userconfig.password)
|
|
else:
|
|
self.set_empty_passwd(userconfig.name)
|
|
else:
|
|
raise errors.KsError("Invalid kickstart command: %s" \
|
|
% userconfig.__str__())
|
|
|
|
@apply_wrapper
|
|
def apply(self, user):
|
|
for userconfig in user.userList:
|
|
self.addUser(userconfig)
|
|
|
|
class ServicesConfig(KickstartConfig):
|
|
"""A class to apply a kickstart services configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, ksservices):
|
|
if not os.path.exists(self.path("/sbin/chkconfig")):
|
|
return
|
|
for s in ksservices.enabled:
|
|
self.call(["/sbin/chkconfig", s, "on"])
|
|
for s in ksservices.disabled:
|
|
self.call(["/sbin/chkconfig", s, "off"])
|
|
|
|
class XConfig(KickstartConfig):
|
|
"""A class to apply a kickstart X configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, ksxconfig):
|
|
if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
|
|
f = open(self.path("/etc/inittab"), "rw+")
|
|
buf = f.read()
|
|
buf = buf.replace("id:3:initdefault", "id:5:initdefault")
|
|
f.seek(0)
|
|
f.write(buf)
|
|
f.close()
|
|
if ksxconfig.defaultdesktop:
|
|
self._check_sysconfig()
|
|
f = open(self.path("/etc/sysconfig/desktop"), "w")
|
|
f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
|
|
f.close()
|
|
|
|
class DesktopConfig(KickstartConfig):
|
|
"""A class to apply a kickstart desktop configuration to a system."""
|
|
@apply_wrapper
|
|
def apply(self, ksdesktop):
|
|
if ksdesktop.defaultdesktop:
|
|
self._check_sysconfig()
|
|
f = open(self.path("/etc/sysconfig/desktop"), "w")
|
|
f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
|
|
f.close()
|
|
if os.path.exists(self.path("/etc/gdm/custom.conf")):
|
|
f = open(self.path("/etc/skel/.dmrc"), "w")
|
|
f.write("[Desktop]\n")
|
|
f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
|
|
f.close()
|
|
if ksdesktop.session:
|
|
if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
|
|
f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
|
|
f.write("session="+ksdesktop.session.lower()+"\n")
|
|
f.close()
|
|
if ksdesktop.autologinuser:
|
|
self._check_sysconfig()
|
|
f = open(self.path("/etc/sysconfig/desktop"), "a+")
|
|
f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
|
|
f.close()
|
|
if os.path.exists(self.path("/etc/gdm/custom.conf")):
|
|
f = open(self.path("/etc/gdm/custom.conf"), "w")
|
|
f.write("[daemon]\n")
|
|
f.write("AutomaticLoginEnable=true\n")
|
|
f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
|
|
f.close()
|
|
|
|
class MoblinRepoConfig(KickstartConfig):
|
|
"""A class to apply a kickstart desktop configuration to a system."""
|
|
def __create_repo_section(self, repo, type, fd):
|
|
baseurl = None
|
|
mirrorlist = None
|
|
reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
|
|
reponame = repo.name + reposuffix[type]
|
|
if type == "base":
|
|
if repo.baseurl:
|
|
baseurl = repo.baseurl
|
|
if repo.mirrorlist:
|
|
mirrorlist = repo.mirrorlist
|
|
|
|
elif type == "debuginfo":
|
|
if repo.baseurl:
|
|
if repo.baseurl.endswith("/"):
|
|
baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
|
|
else:
|
|
baseurl = os.path.dirname(repo.baseurl)
|
|
baseurl += "/debug"
|
|
|
|
if repo.mirrorlist:
|
|
variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
|
|
mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
|
|
mirrorlist += "debug" + "-" + variant
|
|
|
|
elif type == "source":
|
|
if repo.baseurl:
|
|
if repo.baseurl.endswith("/"):
|
|
baseurl = os.path.dirname(
|
|
os.path.dirname(
|
|
os.path.dirname(repo.baseurl)))
|
|
else:
|
|
baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
|
|
baseurl += "/source"
|
|
|
|
if repo.mirrorlist:
|
|
variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
|
|
mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
|
|
mirrorlist += "source" + "-" + variant
|
|
|
|
fd.write("[" + reponame + "]\n")
|
|
fd.write("name=" + reponame + "\n")
|
|
fd.write("failovermethod=priority\n")
|
|
if baseurl:
|
|
auth_url = re.compile(AUTH_URL_PTN)
|
|
m = auth_url.match(baseurl)
|
|
if m:
|
|
baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
|
|
fd.write("baseurl=" + baseurl + "\n")
|
|
if mirrorlist:
|
|
fd.write("mirrorlist=" + mirrorlist + "\n")
|
|
""" Skip saving proxy settings """
|
|
#if repo.proxy:
|
|
# fd.write("proxy=" + repo.proxy + "\n")
|
|
#if repo.proxy_username:
|
|
# fd.write("proxy_username=" + repo.proxy_username + "\n")
|
|
#if repo.proxy_password:
|
|
# fd.write("proxy_password=" + repo.proxy_password + "\n")
|
|
if repo.gpgkey:
|
|
fd.write("gpgkey=" + repo.gpgkey + "\n")
|
|
fd.write("gpgcheck=1\n")
|
|
else:
|
|
fd.write("gpgcheck=0\n")
|
|
if type == "source" or type == "debuginfo" or repo.disable:
|
|
fd.write("enabled=0\n")
|
|
else:
|
|
fd.write("enabled=1\n")
|
|
fd.write("\n")
|
|
|
|
def __create_repo_file(self, repo, repodir):
|
|
fs.makedirs(self.path(repodir))
|
|
f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
|
|
self.__create_repo_section(repo, "base", f)
|
|
if repo.debuginfo:
|
|
self.__create_repo_section(repo, "debuginfo", f)
|
|
if repo.source:
|
|
self.__create_repo_section(repo, "source", f)
|
|
f.close()
|
|
|
|
@apply_wrapper
|
|
def apply(self, ksrepo, repodata, repourl):
|
|
for repo in ksrepo.repoList:
|
|
if repo.name in repourl:
|
|
repo.baseurl = repourl[repo.name]
|
|
if repo.save:
|
|
#self.__create_repo_file(repo, "/etc/yum.repos.d")
|
|
self.__create_repo_file(repo, "/etc/zypp/repos.d")
|
|
""" Import repo gpg keys """
|
|
if repodata:
|
|
for repo in repodata:
|
|
if repo['repokey']:
|
|
runner.quiet(['rpm',
|
|
"--root=%s" % self.instroot,
|
|
"--import",
|
|
repo['repokey']])
|
|
|
|
class RPMMacroConfig(KickstartConfig):
|
|
"""A class to apply the specified rpm macros to the filesystem"""
|
|
@apply_wrapper
|
|
def apply(self, ks):
|
|
if not ks:
|
|
return
|
|
if not os.path.exists(self.path("/etc/rpm")):
|
|
os.mkdir(self.path("/etc/rpm"))
|
|
f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
|
|
if exclude_docs(ks):
|
|
f.write("%_excludedocs 1\n")
|
|
f.write("%__file_context_path %{nil}\n")
|
|
if inst_langs(ks) != None:
|
|
f.write("%_install_langs ")
|
|
f.write(inst_langs(ks))
|
|
f.write("\n")
|
|
f.close()
|
|
|
|
class NetworkConfig(KickstartConfig):
|
|
"""A class to apply a kickstart network configuration to a system."""
|
|
def write_ifcfg(self, network):
|
|
p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
|
|
|
|
f = file(p, "w+")
|
|
os.chmod(p, 0644)
|
|
|
|
f.write("DEVICE=%s\n" % network.device)
|
|
f.write("BOOTPROTO=%s\n" % network.bootProto)
|
|
|
|
if network.bootProto.lower() == "static":
|
|
if network.ip:
|
|
f.write("IPADDR=%s\n" % network.ip)
|
|
if network.netmask:
|
|
f.write("NETMASK=%s\n" % network.netmask)
|
|
|
|
if network.onboot:
|
|
f.write("ONBOOT=on\n")
|
|
else:
|
|
f.write("ONBOOT=off\n")
|
|
|
|
if network.essid:
|
|
f.write("ESSID=%s\n" % network.essid)
|
|
|
|
if network.ethtool:
|
|
if network.ethtool.find("autoneg") == -1:
|
|
network.ethtool = "autoneg off " + network.ethtool
|
|
f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
|
|
|
|
if network.bootProto.lower() == "dhcp":
|
|
if network.hostname:
|
|
f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
|
|
if network.dhcpclass:
|
|
f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
|
|
|
|
if network.mtu:
|
|
f.write("MTU=%s\n" % network.mtu)
|
|
|
|
f.close()
|
|
|
|
def write_wepkey(self, network):
|
|
if not network.wepkey:
|
|
return
|
|
|
|
p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
|
|
f = file(p, "w+")
|
|
os.chmod(p, 0600)
|
|
f.write("KEY=%s\n" % network.wepkey)
|
|
f.close()
|
|
|
|
def write_sysconfig(self, useipv6, hostname, gateway):
|
|
path = self.path("/etc/sysconfig/network")
|
|
f = file(path, "w+")
|
|
os.chmod(path, 0644)
|
|
|
|
f.write("NETWORKING=yes\n")
|
|
|
|
if useipv6:
|
|
f.write("NETWORKING_IPV6=yes\n")
|
|
else:
|
|
f.write("NETWORKING_IPV6=no\n")
|
|
|
|
if hostname:
|
|
f.write("HOSTNAME=%s\n" % hostname)
|
|
else:
|
|
f.write("HOSTNAME=localhost.localdomain\n")
|
|
|
|
if gateway:
|
|
f.write("GATEWAY=%s\n" % gateway)
|
|
|
|
f.close()
|
|
|
|
def write_hosts(self, hostname):
|
|
localline = ""
|
|
if hostname and hostname != "localhost.localdomain":
|
|
localline += hostname + " "
|
|
l = hostname.split(".")
|
|
if len(l) > 1:
|
|
localline += l[0] + " "
|
|
localline += "localhost.localdomain localhost"
|
|
|
|
path = self.path("/etc/hosts")
|
|
f = file(path, "w+")
|
|
os.chmod(path, 0644)
|
|
f.write("127.0.0.1\t\t%s\n" % localline)
|
|
f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
|
|
f.close()
|
|
|
|
def write_resolv(self, nodns, nameservers):
|
|
if nodns or not nameservers:
|
|
return
|
|
|
|
path = self.path("/etc/resolv.conf")
|
|
f = file(path, "w+")
|
|
os.chmod(path, 0644)
|
|
|
|
for ns in (nameservers):
|
|
if ns:
|
|
f.write("nameserver %s\n" % ns)
|
|
|
|
f.close()
|
|
|
|
@apply_wrapper
|
|
def apply(self, ksnet):
|
|
fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
|
|
|
|
useipv6 = False
|
|
nodns = False
|
|
hostname = None
|
|
gateway = None
|
|
nameservers = None
|
|
|
|
for network in ksnet.network:
|
|
if not network.device:
|
|
raise errors.KsError("No --device specified with "
|
|
"network kickstart command")
|
|
|
|
if (network.onboot and network.bootProto.lower() != "dhcp" and
|
|
not (network.ip and network.netmask)):
|
|
raise errors.KsError("No IP address and/or netmask "
|
|
"specified with static "
|
|
"configuration for '%s'" %
|
|
network.device)
|
|
|
|
self.write_ifcfg(network)
|
|
self.write_wepkey(network)
|
|
|
|
if network.ipv6:
|
|
useipv6 = True
|
|
if network.nodns:
|
|
nodns = True
|
|
|
|
if network.hostname:
|
|
hostname = network.hostname
|
|
if network.gateway:
|
|
gateway = network.gateway
|
|
|
|
if network.nameserver:
|
|
nameservers = network.nameserver.split(",")
|
|
|
|
self.write_sysconfig(useipv6, hostname, gateway)
|
|
self.write_hosts(hostname)
|
|
self.write_resolv(nodns, nameservers)
|
|
|
|
def use_installerfw(ks, feature):
|
|
""" Check if the installer framework has to be used for a feature
|
|
"feature". """
|
|
|
|
features = ks.handler.installerfw.features
|
|
if features:
|
|
if feature in features or "all" in features:
|
|
return True
|
|
return False
|
|
|
|
def get_image_size(ks, default = None):
|
|
__size = 0
|
|
for p in ks.handler.partition.partitions:
|
|
if p.mountpoint == "/" and p.size:
|
|
__size = p.size
|
|
if __size > 0:
|
|
return int(__size) * 1024L * 1024L
|
|
else:
|
|
return default
|
|
|
|
def get_image_fstype(ks, default = None):
|
|
for p in ks.handler.partition.partitions:
|
|
if p.mountpoint == "/" and p.fstype:
|
|
return p.fstype
|
|
return default
|
|
|
|
def get_image_fsopts(ks, default = None):
|
|
for p in ks.handler.partition.partitions:
|
|
if p.mountpoint == "/" and p.fsopts:
|
|
return p.fsopts
|
|
return default
|
|
|
|
def get_modules(ks):
|
|
devices = []
|
|
if isinstance(ks.handler.device, kscommands.device.FC3_Device):
|
|
devices.append(ks.handler.device)
|
|
else:
|
|
devices.extend(ks.handler.device.deviceList)
|
|
|
|
modules = []
|
|
for device in devices:
|
|
if not device.moduleName:
|
|
continue
|
|
modules.extend(device.moduleName.split(":"))
|
|
|
|
return modules
|
|
|
|
def get_timeout(ks, default = None):
|
|
if not hasattr(ks.handler.bootloader, "timeout"):
|
|
return default
|
|
if ks.handler.bootloader.timeout is None:
|
|
return default
|
|
return int(ks.handler.bootloader.timeout)
|
|
|
|
def get_kernel_args(ks, default = "ro rd.live.image"):
|
|
if not hasattr(ks.handler.bootloader, "appendLine"):
|
|
return default
|
|
if ks.handler.bootloader.appendLine is None:
|
|
return default
|
|
return "%s %s" %(default, ks.handler.bootloader.appendLine)
|
|
|
|
def get_menu_args(ks, default = ""):
|
|
if not hasattr(ks.handler.bootloader, "menus"):
|
|
return default
|
|
if ks.handler.bootloader.menus in (None, ""):
|
|
return default
|
|
return "%s" % ks.handler.bootloader.menus
|
|
|
|
def get_default_kernel(ks, default = None):
|
|
if not hasattr(ks.handler.bootloader, "default"):
|
|
return default
|
|
if not ks.handler.bootloader.default:
|
|
return default
|
|
return ks.handler.bootloader.default
|
|
|
|
def get_repos(ks, repo_urls=None):
|
|
repos = {}
|
|
for repo in ks.handler.repo.repoList:
|
|
inc = []
|
|
if hasattr(repo, "includepkgs"):
|
|
inc.extend(repo.includepkgs)
|
|
|
|
exc = []
|
|
if hasattr(repo, "excludepkgs"):
|
|
exc.extend(repo.excludepkgs)
|
|
|
|
baseurl = repo.baseurl
|
|
mirrorlist = repo.mirrorlist
|
|
|
|
if repo_urls and repo.name in repo_urls:
|
|
baseurl = repo_urls[repo.name]
|
|
mirrorlist = None
|
|
|
|
if repos.has_key(repo.name):
|
|
msger.warning("Overriding already specified repo %s" %(repo.name,))
|
|
|
|
proxy = None
|
|
if hasattr(repo, "proxy"):
|
|
proxy = repo.proxy
|
|
proxy_username = None
|
|
if hasattr(repo, "proxy_username"):
|
|
proxy_username = repo.proxy_username
|
|
proxy_password = None
|
|
if hasattr(repo, "proxy_password"):
|
|
proxy_password = repo.proxy_password
|
|
if hasattr(repo, "debuginfo"):
|
|
debuginfo = repo.debuginfo
|
|
if hasattr(repo, "source"):
|
|
source = repo.source
|
|
if hasattr(repo, "gpgkey"):
|
|
gpgkey = repo.gpgkey
|
|
if hasattr(repo, "disable"):
|
|
disable = repo.disable
|
|
ssl_verify = True
|
|
if hasattr(repo, "ssl_verify"):
|
|
ssl_verify = repo.ssl_verify == "yes"
|
|
nocache = False
|
|
if hasattr(repo, "nocache"):
|
|
nocache = repo.nocache
|
|
cost = None
|
|
if hasattr(repo, "cost"):
|
|
cost = repo.cost
|
|
priority = None
|
|
if hasattr(repo, "priority"):
|
|
priority = repo.priority
|
|
|
|
repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
|
|
proxy, proxy_username, proxy_password, debuginfo,
|
|
source, gpgkey, disable, ssl_verify, nocache,
|
|
cost, priority)
|
|
|
|
return repos.values()
|
|
|
|
def convert_method_to_repo(ks):
|
|
try:
|
|
ks.handler.repo.methodToRepo()
|
|
except (AttributeError, kserrors.KickstartError):
|
|
pass
|
|
|
|
def get_attachment(ks, required=()):
|
|
return ks.handler.attachment.packageList + list(required)
|
|
|
|
def get_pre_packages(ks, required=()):
|
|
return ks.handler.prepackages.packageList + list(required)
|
|
|
|
def get_packages(ks, required=()):
|
|
return ks.handler.packages.packageList + list(required)
|
|
|
|
def get_groups(ks, required=()):
|
|
return ks.handler.packages.groupList + list(required)
|
|
|
|
def get_excluded(ks, required=()):
|
|
return ks.handler.packages.excludedList + list(required)
|
|
|
|
def get_partitions(ks):
|
|
return ks.handler.partition.partitions
|
|
|
|
def ignore_missing(ks):
|
|
return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
|
|
|
|
def exclude_docs(ks):
|
|
return ks.handler.packages.excludeDocs
|
|
|
|
def inst_langs(ks):
|
|
if hasattr(ks.handler.packages, "instLange"):
|
|
return ks.handler.packages.instLange
|
|
elif hasattr(ks.handler.packages, "instLangs"):
|
|
return ks.handler.packages.instLangs
|
|
return ""
|
|
|
|
def get_post_scripts(ks):
|
|
scripts = []
|
|
for s in ks.handler.scripts:
|
|
if s.type != ksparser.KS_SCRIPT_POST:
|
|
continue
|
|
scripts.append(s)
|
|
return scripts
|
|
|
|
def add_repo(ks, repostr):
|
|
args = repostr.split()
|
|
repoobj = ks.handler.repo.parse(args[1:])
|
|
if repoobj and repoobj not in ks.handler.repo.repoList:
|
|
ks.handler.repo.repoList.append(repoobj)
|
|
|
|
def remove_all_repos(ks):
|
|
while len(ks.handler.repo.repoList) != 0:
|
|
del ks.handler.repo.repoList[0]
|
|
|
|
def remove_duplicate_repos(ks):
|
|
i = 0
|
|
j = i + 1
|
|
while True:
|
|
if len(ks.handler.repo.repoList) < 2:
|
|
break
|
|
if i >= len(ks.handler.repo.repoList) - 1:
|
|
break
|
|
name = ks.handler.repo.repoList[i].name
|
|
baseurl = ks.handler.repo.repoList[i].baseurl
|
|
if j < len(ks.handler.repo.repoList):
|
|
if (ks.handler.repo.repoList[j].name == name or \
|
|
ks.handler.repo.repoList[j].baseurl == baseurl):
|
|
del ks.handler.repo.repoList[j]
|
|
else:
|
|
j += 1
|
|
if j >= len(ks.handler.repo.repoList):
|
|
i += 1
|
|
j = i + 1
|
|
else:
|
|
i += 1
|
|
j = i + 1
|
|
|
|
def resolve_groups(creatoropts, repometadata):
|
|
iszypp = False
|
|
if 'zypp' == creatoropts['pkgmgr']:
|
|
iszypp = True
|
|
ks = creatoropts['ks']
|
|
|
|
for repo in repometadata:
|
|
""" Mustn't replace group with package list if repo is ready for the
|
|
corresponding package manager.
|
|
"""
|
|
|
|
if iszypp and repo["patterns"]:
|
|
continue
|
|
if not iszypp and repo["comps"]:
|
|
continue
|
|
|
|
# But we also must handle such cases, use zypp but repo only has comps,
|
|
# use yum but repo only has patterns, use zypp but use_comps is true,
|
|
# use yum but use_comps is false.
|
|
groupfile = None
|
|
if iszypp and repo["comps"]:
|
|
groupfile = repo["comps"]
|
|
get_pkglist_handler = misc.get_pkglist_in_comps
|
|
if not iszypp and repo["patterns"]:
|
|
groupfile = repo["patterns"]
|
|
get_pkglist_handler = misc.get_pkglist_in_patterns
|
|
|
|
if groupfile:
|
|
i = 0
|
|
while True:
|
|
if i >= len(ks.handler.packages.groupList):
|
|
break
|
|
pkglist = get_pkglist_handler(
|
|
ks.handler.packages.groupList[i].name,
|
|
groupfile)
|
|
if pkglist:
|
|
del ks.handler.packages.groupList[i]
|
|
for pkg in pkglist:
|
|
if pkg not in ks.handler.packages.packageList:
|
|
ks.handler.packages.packageList.append(pkg)
|
|
else:
|
|
i = i + 1
|