3 # Copyright (c) 2007 Red Hat, Inc.
4 # Copyright (c) 2009, 2010, 2011 Intel, Inc.
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the Free
8 # Software Foundation; version 2 of the License
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc., 59
17 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 import pykickstart.sections as kssections
26 import pykickstart.commands as kscommands
27 import pykickstart.constants as ksconstants
28 import pykickstart.errors as kserrors
29 import pykickstart.parser as ksparser
30 import pykickstart.version as ksversion
31 from pykickstart.handlers.control import commandMap
32 from pykickstart.handlers.control import dataMap
35 from mic.utils import errors, misc, runner, fs_related as fs
36 from .custom_commands import desktop, micrepo, micboot, partition, installerfw
37 from mic.utils.safeurl import SafeURL
39 AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
42 class PrepackageSection(kssections.Section):
43 sectionOpen = "%prepackages"
45 def handleLine(self, line):
49 (h, s, t) = line.partition('#')
52 self.handler.prepackages.add([line])
54 def handleHeader(self, lineno, args):
55 kssections.Section.handleHeader(self, lineno, args)
57 class AttachmentSection(kssections.Section):
58 sectionOpen = "%attachment"
60 def handleLine(self, line):
64 (h, s, t) = line.partition('#')
67 self.handler.attachment.add([line])
69 def handleHeader(self, lineno, args):
70 kssections.Section.handleHeader(self, lineno, args)
72 class EnvSection(kssections.Section):
75 def handleLine(self, line):
79 (h, s, t) = line.partition('#')
81 (n, s, v) = line.partition('=')
82 self.handler.env.append((n, v))
84 def handleHeader(self, lineno, args):
86 kssections.Section.handleHeader(self, lineno, args)
88 def apply_wrapper(func):
89 def wrapper(*kargs, **kwargs):
91 func(*kargs, **kwargs)
92 except (OSError, IOError, errors.KsError) as err:
93 cfgcls = kargs[0].__class__.__name__
94 if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
95 msger.warning("%s" % err)
98 # just throw out the exception
102 def read_kickstart(path):
103 """Parse a kickstart file and return a KickstartParser instance.
105 This is a simple utility function which takes a path to a kickstart file,
106 parses it and returns a pykickstart KickstartParser instance which can
107 be then passed to an ImageCreator constructor.
109 If an error occurs, a CreatorError exception is thrown.
112 #version = ksversion.makeVersion()
113 #ks = ksparser.KickstartParser(version)
115 using_version = ksversion.DEVEL
116 commandMap[using_version]["desktop"] = desktop.Mic_Desktop
117 commandMap[using_version]["repo"] = micrepo.Mic_Repo
118 commandMap[using_version]["tpk_repo"] = micrepo.Mic_Tpk_Repo
119 commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
120 commandMap[using_version]["part"] = partition.Mic_Partition
121 commandMap[using_version]["partition"] = partition.Mic_Partition
122 commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
123 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
124 dataMap[using_version]["Tpk_RepoData"] = micrepo.Mic_Tpk_RepoData
125 dataMap[using_version]["PartData"] = partition.Mic_PartData
126 superclass = ksversion.returnClassForVersion(version=using_version)
128 class KSHandlers(superclass):
130 superclass.__init__(self, mapping=commandMap[using_version])
131 self.prepackages = ksparser.Packages()
132 self.attachment = ksparser.Packages()
134 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
135 ks.registerSection(PrepackageSection(ks.handler))
136 ks.registerSection(AttachmentSection(ks.handler))
137 ks.registerSection(EnvSection(ks.handler))
140 ks.readKickstart(path)
141 except (kserrors.KickstartParseError, kserrors.KickstartError) as err:
142 if msger.ask("Errors occured on kickstart file, skip and continue?"):
143 msger.warning("%s" % err)
146 raise errors.KsError("%s" % err)
150 class KickstartConfig(object):
151 """A base class for applying kickstart configurations to a system."""
152 def __init__(self, instroot):
153 self.instroot = instroot
155 def path(self, subpath):
156 return self.instroot + subpath
158 def _check_sysconfig(self):
159 if not os.path.exists(self.path("/etc/sysconfig")):
160 fs.makedirs(self.path("/etc/sysconfig"))
163 os.chroot(self.instroot)
166 def call(self, args):
167 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
168 raise errors.KsError("Can't find %s in chroot" % args[0])
169 subprocess.call(args, preexec_fn = self.chroot)
174 class LanguageConfig(KickstartConfig):
175 """A class to apply a kickstart language configuration to a system."""
177 def apply(self, kslang):
178 self._check_sysconfig()
180 f = open(self.path("/etc/sysconfig/i18n"), "w+")
181 f.write("LANG=\"" + kslang.lang + "\"\n")
184 f = open(self.path("/etc/locale.conf"), "w+")
185 f.write("LANG=\"" + kslang.lang + "\"\n")
188 #cp ks lang setting to other file, then can access the file in %post section
189 fs.makedirs(self.path("/etc/config"))
190 f = open(self.path("/etc/config/mic_language"), "w+")
191 f.write("LANG=\"" + kslang.lang + "\"\n")
194 class KeyboardConfig(KickstartConfig):
195 """A class to apply a kickstart keyboard configuration to a system."""
197 def apply(self, kskeyboard):
200 # should this impact the X keyboard config too?
201 # or do we want to make X be able to do this mapping?
203 #k = rhpl.keyboard.Keyboard()
204 #if kskeyboard.keyboard:
205 # k.set(kskeyboard.keyboard)
206 #k.write(self.instroot)
209 class TimezoneConfig(KickstartConfig):
210 """A class to apply a kickstart timezone configuration to a system."""
212 def apply(self, kstimezone):
213 self._check_sysconfig()
214 tz = kstimezone.timezone or "America/New_York"
215 utc = str(kstimezone.isUtc)
217 f = open(self.path("/etc/sysconfig/clock"), "w+")
218 f.write("ZONE=\"" + tz + "\"\n")
219 f.write("UTC=" + utc + "\n")
221 if not os.path.exists("/opt/etc"):
222 fs.makedirs("/opt/etc")
223 tz_source = "/usr/share/zoneinfo/%s" % (tz)
224 tz_midst = "/opt/etc/localtime"
225 tz_dest = "/etc/localtime"
227 lncmd = fs.find_binary_inchroot('ln', self.instroot)
229 self.call([lncmd, "-s", tz_source, tz_midst])
230 self.call([lncmd, "-s", tz_midst, tz_dest])
232 lncmd = fs.find_binary_path('ln')
233 subprocess.call([lncmd, "-s",
234 self.path(tz_source),
235 self.path(tz_midst)])
236 subprocess.call([lncmd, "-s",
239 except (IOError, OSError) as msg:
240 raise errors.KsError("Timezone setting error: %s" % msg)
242 class AuthConfig(KickstartConfig):
243 """A class to apply a kickstart authconfig configuration to a system."""
245 def apply(self, ksauthconfig):
246 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
247 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
248 self.call(args + auth.split())
250 class FirewallConfig(KickstartConfig):
251 """A class to apply a kickstart firewall configuration to a system."""
253 def apply(self, ksfirewall):
255 # FIXME: should handle the rest of the options
257 if not os.path.exists(self.path("/usr/sbin/lokkit")):
259 if ksfirewall.enabled:
262 status = "--disabled"
264 self.call(["/usr/sbin/lokkit",
265 "-f", "--quiet", "--nostart", status])
267 class RootPasswordConfig(KickstartConfig):
268 """A class to apply a kickstart root password configuration to a system."""
270 self.call(["/usr/bin/passwd", "-d", "root"])
272 def set_encrypted(self, password):
273 self.call(["/usr/sbin/usermod", "-p", password, "root"])
275 def set_unencrypted(self, password):
276 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
277 if not os.path.exists("%s/%s" %(self.instroot, p)):
278 raise errors.KsError("Unable to set unencrypted password due "
281 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
282 stdout = subprocess.PIPE,
283 preexec_fn = self.chroot)
284 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-c","SHA512"],
286 stdout = subprocess.PIPE,
287 preexec_fn = self.chroot)
291 def apply(self, ksrootpw):
292 if ksrootpw.isCrypted:
293 self.set_encrypted(ksrootpw.password)
294 elif ksrootpw.password != "":
295 self.set_unencrypted(ksrootpw.password)
299 class UserConfig(KickstartConfig):
300 def set_empty_passwd(self, user):
301 self.call(["/usr/bin/passwd", "-d", user])
303 def set_encrypted_passwd(self, user, password):
304 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
306 def set_unencrypted_passwd(self, user, password):
307 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
308 if not os.path.exists("%s/%s" %(self.instroot, p)):
309 raise errors.KsError("Unable to set unencrypted password due "
312 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
313 stdout = subprocess.PIPE,
314 preexec_fn = self.chroot)
315 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-c","SHA512"],
317 stdout = subprocess.PIPE,
318 preexec_fn = self.chroot)
321 def addUser(self, userconfig):
322 args = [ "/usr/sbin/useradd" ]
323 if userconfig.groups:
324 args += [ "--groups", ",".join(userconfig.groups) ]
327 args += [ "-d", "/home/%s" % userconfig.name ]
328 args.append(userconfig.name)
330 dev_null = os.open("/dev/null", os.O_WRONLY)
331 msger.debug('adding user with %s' % args)
332 subprocess.call(args,
335 preexec_fn = self.chroot)
338 msger.warning('Cannot add user using "useradd"')
340 if userconfig.password not in (None, ""):
341 if userconfig.isCrypted:
342 self.set_encrypted_passwd(userconfig.name,
345 self.set_unencrypted_passwd(userconfig.name,
348 self.set_empty_passwd(userconfig.name)
350 raise errors.KsError("Invalid kickstart command: %s" \
351 % userconfig.__str__())
354 def apply(self, user):
355 for userconfig in user.userList:
356 #There exist root user already.
357 if userconfig.name == "root":
358 msger.debug("root user, just set root user groups attribution")
359 if userconfig.groups:
360 self.call(["/usr/sbin/usermod", "-a", "-G", "%s" % ",".join(userconfig.groups), "root"])
362 self.addUser(userconfig)
364 class ServicesConfig(KickstartConfig):
365 """A class to apply a kickstart services configuration to a system."""
367 def apply(self, ksservices):
368 if not os.path.exists(self.path("/sbin/chkconfig")):
370 for s in ksservices.enabled:
371 self.call(["/sbin/chkconfig", s, "on"])
372 for s in ksservices.disabled:
373 self.call(["/sbin/chkconfig", s, "off"])
375 class XConfig(KickstartConfig):
376 """A class to apply a kickstart X configuration to a system."""
378 def apply(self, ksxconfig):
379 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
380 f = open(self.path("/etc/inittab"), "r+")
382 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
386 if ksxconfig.defaultdesktop:
387 self._check_sysconfig()
388 f = open(self.path("/etc/sysconfig/desktop"), "w")
389 f.write("DESKTOP=" + str(ksxconfig.defaultdesktop) + "\n")
392 class DesktopConfig(KickstartConfig):
393 """A class to apply a kickstart desktop configuration to a system."""
395 def apply(self, ksdesktop):
396 if ksdesktop.defaultdesktop:
397 self._check_sysconfig()
398 f = open(self.path("/etc/sysconfig/desktop"), "w")
399 f.write("DESKTOP=" + str(ksdesktop.defaultdesktop) + "\n")
401 if os.path.exists(self.path("/etc/gdm/custom.conf")):
402 f = open(self.path("/etc/skel/.dmrc"), "w")
403 f.write("[Desktop]\n")
404 f.write("Session=" + str(ksdesktop.defaultdesktop.lower()) + "\n")
406 if ksdesktop.session:
407 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
408 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
409 f.write("session=" + str(ksdesktop.session.lower()) + "\n")
411 if ksdesktop.autologinuser:
412 self._check_sysconfig()
413 f = open(self.path("/etc/sysconfig/desktop"), "a+")
414 f.write("AUTOLOGIN_USER=" + str(ksdesktop.autologinuser) + "\n")
416 if os.path.exists(self.path("/etc/gdm/custom.conf")):
417 f = open(self.path("/etc/gdm/custom.conf"), "w")
418 f.write("[daemon]\n")
419 f.write("AutomaticLoginEnable=true\n")
420 f.write("AutomaticLogin=" + str(ksdesktop.autologinuser) + "\n")
423 class MoblinRepoConfig(KickstartConfig):
424 """A class to apply a kickstart desktop configuration to a system."""
425 def __create_repo_section(self, repo, type, fd):
428 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
429 reponame = repo.name + reposuffix[type]
432 baseurl = repo.baseurl
434 mirrorlist = repo.mirrorlist
436 elif type == "debuginfo":
438 if repo.baseurl.endswith("/"):
439 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
441 baseurl = os.path.dirname(repo.baseurl)
445 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
446 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
447 mirrorlist += "debug" + "-" + variant
449 elif type == "source":
451 if repo.baseurl.endswith("/"):
452 baseurl = os.path.dirname(
454 os.path.dirname(repo.baseurl)))
456 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
460 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
461 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
462 mirrorlist += "source" + "-" + variant
464 fd.write("[" + reponame + "]\n")
465 fd.write("name=" + reponame + "\n")
466 fd.write("failovermethod=priority\n")
468 auth_url = re.compile(AUTH_URL_PTN)
469 m = auth_url.match(baseurl)
471 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
472 fd.write("baseurl=" + baseurl + "\n")
474 fd.write("mirrorlist=" + mirrorlist + "\n")
475 """ Skip saving proxy settings """
477 # fd.write("proxy=" + repo.proxy + "\n")
478 #if repo.proxy_username:
479 # fd.write("proxy_username=" + repo.proxy_username + "\n")
480 #if repo.proxy_password:
481 # fd.write("proxy_password=" + repo.proxy_password + "\n")
483 fd.write("gpgkey=" + repo.gpgkey + "\n")
484 fd.write("gpgcheck=1\n")
486 fd.write("gpgcheck=0\n")
487 if type == "source" or type == "debuginfo" or repo.disable:
488 fd.write("enabled=0\n")
490 fd.write("enabled=1\n")
493 def __create_repo_file(self, repo, repodir):
494 fs.makedirs(self.path(repodir))
495 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
496 self.__create_repo_section(repo, "base", f)
498 self.__create_repo_section(repo, "debuginfo", f)
500 self.__create_repo_section(repo, "source", f)
504 def apply(self, ksrepo, repodata, repourl):
505 for repo in ksrepo.repoList:
506 if repo.name in repourl:
507 repo.baseurl = repourl[repo.name]
509 #self.__create_repo_file(repo, "/etc/yum.repos.d")
510 self.__create_repo_file(repo, "/etc/zypp/repos.d")
511 """ Import repo gpg keys """
513 for repo in repodata:
516 "--root=%s" % self.instroot,
520 class RPMMacroConfig(KickstartConfig):
521 """A class to apply the specified rpm macros to the filesystem"""
526 if not os.path.exists(self.path("/etc/rpm")):
527 os.mkdir(self.path("/etc/rpm"))
528 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
530 f.write("%_excludedocs 1\n")
531 f.write("%__file_context_path %{nil}\n")
532 if inst_langs(ks) != None:
533 f.write("%_install_langs ")
534 f.write(inst_langs(ks))
538 class NetworkConfig(KickstartConfig):
539 """A class to apply a kickstart network configuration to a system."""
540 def write_ifcfg(self, network):
541 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
546 f.write("DEVICE=%s\n" % network.device)
547 f.write("BOOTPROTO=%s\n" % network.bootProto)
549 if network.bootProto.lower() == "static":
551 f.write("IPADDR=%s\n" % network.ip)
553 f.write("NETMASK=%s\n" % network.netmask)
556 f.write("ONBOOT=on\n")
558 f.write("ONBOOT=off\n")
561 f.write("ESSID=%s\n" % network.essid)
564 if network.ethtool.find("autoneg") == -1:
565 network.ethtool = "autoneg off " + network.ethtool
566 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
568 if network.bootProto.lower() == "dhcp":
570 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
571 if network.dhcpclass:
572 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
575 f.write("MTU=%s\n" % network.mtu)
579 def write_wepkey(self, network):
580 if not network.wepkey:
583 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
586 f.write("KEY=%s\n" % network.wepkey)
589 def write_sysconfig(self, useipv6, hostname, gateway):
590 path = self.path("/etc/sysconfig/network")
592 os.chmod(path, 0o644)
594 f.write("NETWORKING=yes\n")
597 f.write("NETWORKING_IPV6=yes\n")
599 f.write("NETWORKING_IPV6=no\n")
602 f.write("HOSTNAME=%s\n" % hostname)
604 f.write("HOSTNAME=localhost.localdomain\n")
607 f.write("GATEWAY=%s\n" % gateway)
611 def write_hosts(self, hostname):
613 if hostname and hostname != "localhost.localdomain":
614 localline += hostname + " "
615 l = hostname.split(".")
617 localline += l[0] + " "
618 localline += "localhost.localdomain localhost"
620 path = self.path("/etc/hosts")
622 os.chmod(path, 0o644)
623 f.write("127.0.0.1\t\t%s\n" % localline)
624 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
627 def write_resolv(self, nodns, nameservers):
628 if nodns or not nameservers:
631 path = self.path("/etc/resolv.conf")
633 os.chmod(path, 0o644)
635 for ns in (nameservers):
637 f.write("nameserver %s\n" % ns)
642 def apply(self, ksnet):
643 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
651 for network in ksnet.network:
652 if not network.device:
653 raise errors.KsError("No --device specified with "
654 "network kickstart command")
656 if (network.onboot and network.bootProto.lower() != "dhcp" and
657 not (network.ip and network.netmask)):
658 raise errors.KsError("No IP address and/or netmask "
659 "specified with static "
660 "configuration for '%s'" %
663 self.write_ifcfg(network)
664 self.write_wepkey(network)
672 hostname = network.hostname
674 gateway = network.gateway
676 if network.nameserver:
677 nameservers = network.nameserver.split(",")
679 self.write_sysconfig(useipv6, hostname, gateway)
681 #to avoid import error because of import each other
682 from mic.conf import configmgr
683 path=self.path("/etc/hosts")
684 if configmgr.create['skip_set_hosts'] == False and os.path.exists(path) == False:
685 self.write_hosts(hostname)
686 self.write_resolv(nodns, nameservers)
688 def use_installerfw(ks, feature):
689 """ Check if the installer framework has to be used for a feature
692 features = ks.handler.installerfw.features
694 if feature in features or "all" in features:
698 def get_image_size(ks, default = None):
700 for p in ks.handler.partition.partitions:
701 if p.mountpoint == "/" and p.size:
704 return int(__size) * 1024 * 1024
708 def get_image_fstype(ks, default = None):
709 for p in ks.handler.partition.partitions:
710 if p.mountpoint == "/" and p.fstype:
714 def get_image_fsopts(ks, default = None):
715 for p in ks.handler.partition.partitions:
716 if p.mountpoint == "/" and p.fsopts:
722 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
723 devices.append(ks.handler.device)
725 devices.extend(ks.handler.device.deviceList)
728 for device in devices:
729 if not device.moduleName:
731 modules.extend(device.moduleName.split(":"))
735 def get_timeout(ks, default = None):
736 if not hasattr(ks.handler.bootloader, "timeout"):
738 if ks.handler.bootloader.timeout is None:
740 return int(ks.handler.bootloader.timeout)
742 def get_kernel_args(ks, default = "ro rd.live.image"):
743 if not hasattr(ks.handler.bootloader, "appendLine"):
745 if ks.handler.bootloader.appendLine is None:
747 return "%s %s" %(default, ks.handler.bootloader.appendLine)
749 def get_menu_args(ks, default = ""):
750 if not hasattr(ks.handler.bootloader, "menus"):
752 if ks.handler.bootloader.menus in (None, ""):
754 return "%s" % ks.handler.bootloader.menus
756 def get_default_kernel(ks, default = None):
757 if not hasattr(ks.handler.bootloader, "default"):
759 if not ks.handler.bootloader.default:
761 return ks.handler.bootloader.default
763 RepoType = collections.namedtuple("Repo",
764 "name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy, \
765 proxy_username, proxy_password, debuginfo, \
766 source, gpgkey, disable, ssl_verify, nocache, \
769 def Repo(name, baseurl, mirrorlist=None, includepkgs=[], excludepkgs=[], proxy=None,
770 proxy_username=None, proxy_password=None, debuginfo=None,
771 source=None, gpgkey=None, disable=None, ssl_verify=None,
772 nocache=False, cost=None, priority=None):
773 return RepoType(name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy,
774 proxy_username, proxy_password, debuginfo,
775 source, gpgkey, disable, ssl_verify, nocache,
779 def get_repos(ks, repo_urls=None, ignore_ksrepo=False):
781 for repodata in ks.handler.repo.repoList:
783 for field in RepoType._fields:
784 if hasattr(repodata, field) and getattr(repodata, field):
785 repo[field] = getattr(repodata, field)
787 if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'):
788 repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'),
789 getattr(repodata, 'user', None),
790 getattr(repodata, 'passwd', None))
793 repos[repo['name']] = Repo(**repo)
798 for name, repo in list(repo_urls.items()):
799 if 'baseurl' in repo:
800 repo['baseurl'] = SafeURL(repo.get('baseurl'),
801 repo.get('user', None),
802 repo.get('passwd', None))
803 repos[name] = Repo(**repo)
804 return list(repos.values())
806 TpkRepoType = collections.namedtuple("TpkRepo",
807 "name, baseurl,proxy,proxy_username,proxy_password,ssl_verify")
809 def TpkRepo(name, baseurl, proxy=None,proxy_username=None, proxy_password=None,ssl_verify=None):
810 return TpkRepoType(name, baseurl,proxy,proxy_username,proxy_password,ssl_verify)
813 def get_tpkrepos(ks):
815 for tpkrepodata in ks.handler.tpk_repo.tpkRepoList:
817 for field in TpkRepoType._fields:
818 if hasattr(tpkrepodata, field) and getattr(tpkrepodata, field):
819 tpkrepo[field] = getattr(tpkrepodata, field)
821 if hasattr(tpkrepodata, 'baseurl') and getattr(tpkrepodata, 'baseurl'):
822 tpkrepo['baseurl'] = SafeURL(getattr(tpkrepodata, 'baseurl'),getattr(tpkrepodata, 'user',None),getattr(tpkrepodata, 'passwd',None))
824 if 'name' in tpkrepo:
825 tpkrepos[tpkrepo['name']] = TpkRepo(**tpkrepo)
827 return list(tpkrepos.values())
830 def convert_method_to_repo(ks):
832 ks.handler.repo.methodToRepo()
833 except (AttributeError, kserrors.KickstartError):
836 def get_attachment(ks, required=()):
837 return ks.handler.attachment.packageList + list(required)
839 def get_env(ks, required=()):
840 return ks.handler.env
842 def get_pre_packages(ks, required=()):
843 return ks.handler.prepackages.packageList + list(required)
845 def get_packages(ks, required=()):
846 return ks.handler.packages.packageList + list(required)
848 def get_tpkpackages(ks):
849 return ks.handler.tpk_packages.tpk_packageList
851 def get_groups(ks, required=()):
852 return ks.handler.packages.groupList + list(required)
854 def get_excluded(ks, required=()):
855 return ks.handler.packages.excludedList + list(required)
857 def get_partitions(ks):
858 return ks.handler.partition.partitions
860 def ignore_missing(ks):
861 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
863 def exclude_docs(ks):
864 return ks.handler.packages.excludeDocs
867 if hasattr(ks.handler.packages, "instLange"):
868 return ks.handler.packages.instLange
869 elif hasattr(ks.handler.packages, "instLangs"):
870 return ks.handler.packages.instLangs
873 def get_post_scripts(ks):
875 for s in ks.handler.scripts:
876 if s.type != ksparser.constants.KS_SCRIPT_POST:
881 def get_sign_scripts(ks):
883 for s in ks.handler.scripts:
884 if (s.type == ksparser.constants.KS_SCRIPT_RUN or \
885 s.type == ksparser.constants.KS_SCRIPT_UMOUNT):
889 def add_repo(ks, repostr):
890 args = repostr.split()
891 repoobj = ks.handler.repo.parse(args[1:])
892 if repoobj and repoobj not in ks.handler.repo.repoList:
893 ks.handler.repo.repoList.append(repoobj)
895 def remove_all_repos(ks):
896 while len(ks.handler.repo.repoList) != 0:
897 del ks.handler.repo.repoList[0]
899 def remove_duplicate_repos(ks):
903 if len(ks.handler.repo.repoList) < 2:
905 if i >= len(ks.handler.repo.repoList) - 1:
907 name = ks.handler.repo.repoList[i].name
908 baseurl = ks.handler.repo.repoList[i].baseurl
909 if j < len(ks.handler.repo.repoList):
910 if (ks.handler.repo.repoList[j].name == name or \
911 ks.handler.repo.repoList[j].baseurl == baseurl):
912 del ks.handler.repo.repoList[j]
915 if j >= len(ks.handler.repo.repoList):
922 def resolve_groups(creatoropts, repometadata):
924 if 'zypp' == creatoropts['pkgmgr']:
926 ks = creatoropts['ks']
928 for repo in repometadata:
929 """ Mustn't replace group with package list if repo is ready for the
930 corresponding package manager.
933 if iszypp and repo["patterns"]:
935 if not iszypp and repo["comps"]:
938 # But we also must handle such cases, use zypp but repo only has comps,
939 # use yum but repo only has patterns, use zypp but use_comps is true,
940 # use yum but use_comps is false.
942 if iszypp and repo["comps"]:
943 groupfile = repo["comps"]
944 get_pkglist_handler = misc.get_pkglist_in_comps
945 if not iszypp and repo["patterns"]:
946 groupfile = repo["patterns"]
947 get_pkglist_handler = misc.get_pkglist_in_patterns
952 if i >= len(ks.handler.packages.groupList):
954 pkglist = get_pkglist_handler(
955 ks.handler.packages.groupList[i].name,
958 del ks.handler.packages.groupList[i]
960 if pkg not in ks.handler.packages.packageList:
961 ks.handler.packages.packageList.append(pkg)