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.
26 from mic.utils import errors, misc, runner, fs_related as fs
28 import pykickstart.sections as kssections
29 import pykickstart.commands as kscommands
30 import pykickstart.constants as ksconstants
31 import pykickstart.errors as kserrors
32 import pykickstart.parser as ksparser
33 import pykickstart.version as ksversion
34 from pykickstart.handlers.control import commandMap
35 from pykickstart.handlers.control import dataMap
37 import custom_commands.desktop as desktop
38 import custom_commands.moblinrepo as moblinrepo
39 import custom_commands.micboot as micboot
40 import custom_commands.partition as partition
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 def read_kickstart(path):
58 """Parse a kickstart file and return a KickstartParser instance.
60 This is a simple utility function which takes a path to a kickstart file,
61 parses it and returns a pykickstart KickstartParser instance which can
62 be then passed to an ImageCreator constructor.
64 If an error occurs, a CreatorError exception is thrown.
67 #version = ksversion.makeVersion()
68 #ks = ksparser.KickstartParser(version)
70 using_version = ksversion.DEVEL
71 commandMap[using_version]["desktop"] = desktop.Moblin_Desktop
72 commandMap[using_version]["repo"] = moblinrepo.Moblin_Repo
73 commandMap[using_version]["bootloader"] = micboot.Moblin_Bootloader
74 commandMap[using_version]["part"] = partition.MeeGo_Partition
75 commandMap[using_version]["partition"] = partition.MeeGo_Partition
76 dataMap[using_version]["RepoData"] = moblinrepo.Moblin_RepoData
77 dataMap[using_version]["PartData"] = partition.MeeGo_PartData
78 superclass = ksversion.returnClassForVersion(version=using_version)
80 class KSHandlers(superclass):
81 def __init__(self, mapping={}):
82 superclass.__init__(self, mapping=commandMap[using_version])
83 self.prepackages = ksparser.Packages()
85 ks = ksparser.KickstartParser(KSHandlers())
86 ks.registerSection(PrepackageSection(ks.handler))
89 ks.readKickstart(path)
90 except kserrors.KickstartParseError, e:
91 msgptn = re.compile("^\D*(\d+).*(Section does not end with.*)$", re.S)
92 m = msgptn.match(str(e))
96 msger.warning("'%s:%s': %s" % (path, lineno, wrnmsg))
98 raise errors.KsError("'%s': %s" % (path, str(e)))
99 except kserrors.KickstartError, e:
100 raise errors.KsError("'%s': %s" % (path, str(e)))
103 def build_name(kscfg, prefix = None, suffix = None, maxlen = None):
104 """Construct and return an image name string.
106 This is a utility function to help create sensible name and fslabel
107 strings. The name is constructed using the sans-prefix-and-extension
108 kickstart filename and the supplied prefix and suffix.
110 If the name exceeds the maxlen length supplied, the prefix is first dropped
111 and then the kickstart filename portion is reduced until it fits. In other
112 words, the suffix takes precedence over the kickstart portion and the
113 kickstart portion takes precedence over the prefix.
115 kscfg -- a path to a kickstart file
116 prefix -- a prefix to prepend to the name; defaults to None, which causes
118 suffix -- a suffix to append to the name; defaults to None, which causes
119 a YYYYMMDDHHMM suffix to be used
120 maxlen -- the maximum length for the returned string; defaults to None,
121 which means there is no restriction on the name length
123 Note, if maxlen is less then the len(suffix), you get to keep both pieces.
126 name = os.path.basename(kscfg)
127 idx = name.rfind('.')
134 suffix = time.strftime("%Y%m%d%H%M")
136 if name.startswith(prefix):
137 name = name[len(prefix):]
139 ret = prefix + name + "-" + suffix
140 if not maxlen is None and len(ret) > maxlen:
141 ret = name[:maxlen - len(suffix) - 1] + "-" + suffix
145 class KickstartConfig(object):
146 """A base class for applying kickstart configurations to a system."""
147 def __init__(self, instroot):
148 self.instroot = instroot
150 def path(self, subpath):
151 return self.instroot + subpath
153 def _check_sysconfig(self):
154 if not os.path.exists(self.path("/etc/sysconfig")):
155 fs.makedirs(self.path("/etc/sysconfig"))
158 os.chroot(self.instroot)
161 def call(self, args):
162 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
163 msger.warning("%s/%s" %(self.instroot, args[0]))
164 raise errors.KsError("Unable to run %s!" %(args))
165 subprocess.call(args, preexec_fn = self.chroot)
170 class LanguageConfig(KickstartConfig):
171 """A class to apply a kickstart language configuration to a system."""
172 def apply(self, kslang):
173 self._check_sysconfig()
175 f = open(self.path("/etc/sysconfig/i18n"), "w+")
176 f.write("LANG=\"" + kslang.lang + "\"\n")
179 class KeyboardConfig(KickstartConfig):
180 """A class to apply a kickstart keyboard configuration to a system."""
181 def apply(self, kskeyboard):
184 # should this impact the X keyboard config too?
185 # or do we want to make X be able to do this mapping?
187 #k = rhpl.keyboard.Keyboard()
188 #if kskeyboard.keyboard:
189 # k.set(kskeyboard.keyboard)
190 #k.write(self.instroot)
193 class TimezoneConfig(KickstartConfig):
194 """A class to apply a kickstart timezone configuration to a system."""
195 def apply(self, kstimezone):
196 self._check_sysconfig()
197 tz = kstimezone.timezone or "America/New_York"
198 utc = str(kstimezone.isUtc)
200 f = open(self.path("/etc/sysconfig/clock"), "w+")
201 f.write("ZONE=\"" + tz + "\"\n")
202 f.write("UTC=" + utc + "\n")
204 tz_source = self.path("/usr/share/zoneinfo/%s" % (tz))
205 tz_dest = self.path("/etc/localtime")
207 shutil.copyfile(tz_source, tz_dest)
208 except (IOError, OSError), (errno, msg):
209 raise errors.KsError("Error copying timezone info from "
211 % (tz_source, tz_dest, msg))
214 class AuthConfig(KickstartConfig):
215 """A class to apply a kickstart authconfig configuration to a system."""
216 def apply(self, ksauthconfig):
217 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
218 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
219 self.call(args + auth.split())
221 class FirewallConfig(KickstartConfig):
222 """A class to apply a kickstart firewall configuration to a system."""
223 def apply(self, ksfirewall):
225 # FIXME: should handle the rest of the options
227 if not os.path.exists(self.path("/usr/sbin/lokkit")):
229 if ksfirewall.enabled:
232 status = "--disabled"
234 self.call(["/usr/sbin/lokkit",
235 "-f", "--quiet", "--nostart", status])
237 class RootPasswordConfig(KickstartConfig):
238 """A class to apply a kickstart root password configuration to a system."""
240 self.call(["/usr/bin/passwd", "-d", "root"])
242 def set_encrypted(self, password):
243 self.call(["/usr/sbin/usermod", "-p", password, "root"])
245 def set_unencrypted(self, password):
246 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
247 if not os.path.exists("%s/%s" %(self.instroot, p)):
248 raise errors.KsError("Unable to set unencrypted password due "
251 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
252 stdout = subprocess.PIPE,
253 preexec_fn = self.chroot)
254 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
256 stdout = subprocess.PIPE,
257 preexec_fn = self.chroot)
260 def apply(self, ksrootpw):
261 if ksrootpw.isCrypted:
262 self.set_encrypted(ksrootpw.password)
263 elif ksrootpw.password != "":
264 self.set_unencrypted(ksrootpw.password)
268 class UserConfig(KickstartConfig):
269 def set_empty_passwd(self, user):
270 self.call(["/usr/bin/passwd", "-d", user])
272 def set_encrypted_passwd(self, user, password):
273 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
275 def set_unencrypted_passwd(self, user, 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", "%s:%s" %(user, password)],
282 stdout = subprocess.PIPE,
283 preexec_fn = self.chroot)
284 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
286 stdout = subprocess.PIPE,
287 preexec_fn = self.chroot)
290 def addUser(self, userconfig):
291 args = [ "/usr/sbin/useradd" ]
292 if userconfig.groups:
293 args += [ "--groups", string.join(userconfig.groups, ",") ]
295 args.append(userconfig.name)
296 dev_null = os.open("/dev/null", os.O_WRONLY)
297 subprocess.call(args,
300 preexec_fn = self.chroot)
302 if userconfig.password not in (None, ""):
303 if userconfig.isCrypted:
304 self.set_encrypted_passwd(userconfig.name,
307 self.set_unencrypted_passwd(userconfig.name,
310 self.set_empty_passwd(userconfig.name)
312 raise errors.KsError("Invalid kickstart command: %s" \
313 % userconfig.__str__())
315 def apply(self, user):
316 for userconfig in user.userList:
318 self.addUser(userconfig)
322 class ServicesConfig(KickstartConfig):
323 """A class to apply a kickstart services configuration to a system."""
324 def apply(self, ksservices):
325 if not os.path.exists(self.path("/sbin/chkconfig")):
327 for s in ksservices.enabled:
328 self.call(["/sbin/chkconfig", s, "on"])
329 for s in ksservices.disabled:
330 self.call(["/sbin/chkconfig", s, "off"])
332 class XConfig(KickstartConfig):
333 """A class to apply a kickstart X configuration to a system."""
334 def apply(self, ksxconfig):
335 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
336 f = open(self.path("/etc/inittab"), "rw+")
338 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
342 if ksxconfig.defaultdesktop:
343 self._check_sysconfig()
344 f = open(self.path("/etc/sysconfig/desktop"), "w")
345 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
348 class DesktopConfig(KickstartConfig):
349 """A class to apply a kickstart desktop configuration to a system."""
350 def apply(self, ksdesktop):
351 if ksdesktop.defaultdesktop:
352 self._check_sysconfig()
353 f = open(self.path("/etc/sysconfig/desktop"), "w")
354 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
356 if os.path.exists(self.path("/etc/gdm/custom.conf")):
357 f = open(self.path("/etc/skel/.dmrc"), "w")
358 f.write("[Desktop]\n")
359 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
361 if ksdesktop.session:
362 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
363 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
364 f.write("session="+ksdesktop.session.lower()+"\n")
366 if ksdesktop.autologinuser:
367 self._check_sysconfig()
368 f = open(self.path("/etc/sysconfig/desktop"), "a+")
369 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
371 if os.path.exists(self.path("/etc/gdm/custom.conf")):
372 f = open(self.path("/etc/gdm/custom.conf"), "w")
373 f.write("[daemon]\n")
374 f.write("AutomaticLoginEnable=true\n")
375 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
378 class MoblinRepoConfig(KickstartConfig):
379 """A class to apply a kickstart desktop configuration to a system."""
380 def __create_repo_section(self, repo, type, fd):
383 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
384 reponame = repo.name + reposuffix[type]
387 baseurl = repo.baseurl
389 mirrorlist = repo.mirrorlist
391 elif type == "debuginfo":
393 if repo.baseurl.endswith("/"):
394 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
396 baseurl = os.path.dirname(repo.baseurl)
400 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
401 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
402 mirrorlist += "debug" + "-" + variant
404 elif type == "source":
406 if repo.baseurl.endswith("/"):
407 baseurl = os.path.dirname(
409 os.path.dirname(repo.baseurl)))
411 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
415 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
416 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
417 mirrorlist += "source" + "-" + variant
419 fd.write("[" + reponame + "]\n")
420 fd.write("name=" + reponame + "\n")
421 fd.write("failovermethod=priority\n")
423 fd.write("baseurl=" + baseurl + "\n")
425 fd.write("mirrorlist=" + mirrorlist + "\n")
426 """ Skip saving proxy settings """
428 # fd.write("proxy=" + repo.proxy + "\n")
429 #if repo.proxy_username:
430 # fd.write("proxy_username=" + repo.proxy_username + "\n")
431 #if repo.proxy_password:
432 # fd.write("proxy_password=" + repo.proxy_password + "\n")
434 fd.write("gpgkey=" + repo.gpgkey + "\n")
435 fd.write("gpgcheck=1\n")
437 fd.write("gpgcheck=0\n")
438 if type == "source" or type == "debuginfo" or repo.disable:
439 fd.write("enabled=0\n")
441 fd.write("enabled=1\n")
444 def __create_repo_file(self, repo, repodir):
445 fs.makedirs(self.path(repodir))
446 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
447 self.__create_repo_section(repo, "base", f)
449 self.__create_repo_section(repo, "debuginfo", f)
451 self.__create_repo_section(repo, "source", f)
454 def apply(self, ksrepo, repodata):
455 for repo in ksrepo.repoList:
457 #self.__create_repo_file(repo, "/etc/yum.repos.d")
458 self.__create_repo_file(repo, "/etc/zypp/repos.d")
459 """ Import repo gpg keys """
461 for repo in repodata:
464 "--root=%s" % self.instroot,
468 class RPMMacroConfig(KickstartConfig):
469 """A class to apply the specified rpm macros to the filesystem"""
473 if not os.path.exists(self.path("/etc/rpm")):
474 os.mkdir(self.path("/etc/rpm"))
475 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
477 f.write("%_excludedocs 1\n")
478 f.write("%__file_context_path %{nil}\n")
479 if inst_langs(ks) != None:
480 f.write("%_install_langs ")
481 f.write(inst_langs(ks))
485 class NetworkConfig(KickstartConfig):
486 """A class to apply a kickstart network configuration to a system."""
487 def write_ifcfg(self, network):
488 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
493 f.write("DEVICE=%s\n" % network.device)
494 f.write("BOOTPROTO=%s\n" % network.bootProto)
496 if network.bootProto.lower() == "static":
498 f.write("IPADDR=%s\n" % network.ip)
500 f.write("NETMASK=%s\n" % network.netmask)
503 f.write("ONBOOT=on\n")
505 f.write("ONBOOT=off\n")
508 f.write("ESSID=%s\n" % network.essid)
511 if network.ethtool.find("autoneg") == -1:
512 network.ethtool = "autoneg off " + network.ethtool
513 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
515 if network.bootProto.lower() == "dhcp":
517 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
518 if network.dhcpclass:
519 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
522 f.write("MTU=%s\n" % network.mtu)
526 def write_wepkey(self, network):
527 if not network.wepkey:
530 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
533 f.write("KEY=%s\n" % network.wepkey)
536 def write_sysconfig(self, useipv6, hostname, gateway):
537 path = self.path("/etc/sysconfig/network")
541 f.write("NETWORKING=yes\n")
544 f.write("NETWORKING_IPV6=yes\n")
546 f.write("NETWORKING_IPV6=no\n")
549 f.write("HOSTNAME=%s\n" % hostname)
551 f.write("HOSTNAME=localhost.localdomain\n")
554 f.write("GATEWAY=%s\n" % gateway)
558 def write_hosts(self, hostname):
560 if hostname and hostname != "localhost.localdomain":
561 localline += hostname + " "
562 l = hostname.split(".")
564 localline += l[0] + " "
565 localline += "localhost.localdomain localhost"
567 path = self.path("/etc/hosts")
570 f.write("127.0.0.1\t\t%s\n" % localline)
571 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
574 def write_resolv(self, nodns, nameservers):
575 if nodns or not nameservers:
578 path = self.path("/etc/resolv.conf")
582 for ns in (nameservers):
584 f.write("nameserver %s\n" % ns)
588 def apply(self, ksnet):
589 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
597 for network in ksnet.network:
598 if not network.device:
599 raise errors.KsError("No --device specified with "
600 "network kickstart command")
602 if (network.onboot and network.bootProto.lower() != "dhcp" and
603 not (network.ip and network.netmask)):
604 raise errors.KsError("No IP address and/or netmask "
605 "specified with static "
606 "configuration for '%s'" %
609 self.write_ifcfg(network)
610 self.write_wepkey(network)
618 hostname = network.hostname
620 gateway = network.gateway
622 if network.nameserver:
623 nameservers = network.nameserver.split(",")
625 self.write_sysconfig(useipv6, hostname, gateway)
626 self.write_hosts(hostname)
627 self.write_resolv(nodns, nameservers)
630 def get_image_size(ks, default = None):
632 for p in ks.handler.partition.partitions:
633 if p.mountpoint == "/" and p.size:
636 return int(__size) * 1024L * 1024L
640 def get_image_fstype(ks, default = None):
641 for p in ks.handler.partition.partitions:
642 if p.mountpoint == "/" and p.fstype:
646 def get_image_fsopts(ks, default = None):
647 for p in ks.handler.partition.partitions:
648 if p.mountpoint == "/" and p.fsopts:
654 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
655 devices.append(ks.handler.device)
657 devices.extend(ks.handler.device.deviceList)
660 for device in devices:
661 if not device.moduleName:
663 modules.extend(device.moduleName.split(":"))
667 def get_timeout(ks, default = None):
668 if not hasattr(ks.handler.bootloader, "timeout"):
670 if ks.handler.bootloader.timeout is None:
672 return int(ks.handler.bootloader.timeout)
674 def get_kernel_args(ks, default = "ro liveimg"):
675 if not hasattr(ks.handler.bootloader, "appendLine"):
677 if ks.handler.bootloader.appendLine is None:
679 return "%s %s" %(default, ks.handler.bootloader.appendLine)
681 def get_menu_args(ks, default = ""):
682 if not hasattr(ks.handler.bootloader, "menus"):
684 if ks.handler.bootloader.menus in (None, ""):
686 return "%s" % ks.handler.bootloader.menus
688 def get_default_kernel(ks, default = None):
689 if not hasattr(ks.handler.bootloader, "default"):
691 if not ks.handler.bootloader.default:
693 return ks.handler.bootloader.default
695 def get_repos(ks, repo_urls = {}):
697 for repo in ks.handler.repo.repoList:
699 if hasattr(repo, "includepkgs"):
700 inc.extend(repo.includepkgs)
703 if hasattr(repo, "excludepkgs"):
704 exc.extend(repo.excludepkgs)
706 baseurl = repo.baseurl
707 mirrorlist = repo.mirrorlist
709 if repo.name in repo_urls:
710 baseurl = repo_urls[repo.name]
713 if repos.has_key(repo.name):
714 msger.warning("Overriding already specified repo %s" %(repo.name,))
717 if hasattr(repo, "proxy"):
719 proxy_username = None
720 if hasattr(repo, "proxy_username"):
721 proxy_username = repo.proxy_username
722 proxy_password = None
723 if hasattr(repo, "proxy_password"):
724 proxy_password = repo.proxy_password
725 if hasattr(repo, "debuginfo"):
726 debuginfo = repo.debuginfo
727 if hasattr(repo, "source"):
729 if hasattr(repo, "gpgkey"):
731 if hasattr(repo, "disable"):
732 disable = repo.disable
734 if hasattr(repo, "ssl_verify"):
735 ssl_verify = repo.ssl_verify == "yes"
737 if hasattr(repo, "cost"):
740 if hasattr(repo, "priority"):
741 priority = repo.priority
743 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
744 proxy, proxy_username, proxy_password, debuginfo,
745 source, gpgkey, disable, ssl_verify, cost, priority)
747 return repos.values()
749 def convert_method_to_repo(ks):
751 ks.handler.repo.methodToRepo()
752 except (AttributeError, kserrors.KickstartError):
755 def get_pre_packages(ks, required = []):
756 return ks.handler.prepackages.packageList + required
758 def get_packages(ks, required = []):
759 return ks.handler.packages.packageList + required
761 def get_groups(ks, required = []):
762 return ks.handler.packages.groupList + required
764 def get_excluded(ks, required = []):
765 return ks.handler.packages.excludedList + required
767 def get_partitions(ks, required = []):
768 return ks.handler.partition.partitions
770 def ignore_missing(ks):
771 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
773 def exclude_docs(ks):
774 return ks.handler.packages.excludeDocs
777 if hasattr(ks.handler.packages, "instLange"):
778 return ks.handler.packages.instLange
779 elif hasattr(ks.handler.packages, "instLangs"):
780 return ks.handler.packages.instLangs
783 def get_post_scripts(ks):
785 for s in ks.handler.scripts:
786 if s.type != ksparser.KS_SCRIPT_POST:
791 def add_repo(ks, repostr):
792 args = repostr.split()
793 repoobj = ks.handler.repo.parse(args[1:])
794 if repoobj and repoobj not in ks.handler.repo.repoList:
795 ks.handler.repo.repoList.append(repoobj)
797 def remove_all_repos(ks):
798 while len(ks.handler.repo.repoList) != 0:
799 del ks.handler.repo.repoList[0]
801 def remove_duplicate_repos(ks):
805 if len(ks.handler.repo.repoList) < 2:
807 if i >= len(ks.handler.repo.repoList) - 1:
809 name = ks.handler.repo.repoList[i].name
810 baseurl = ks.handler.repo.repoList[i].baseurl
811 if j < len(ks.handler.repo.repoList):
812 if (ks.handler.repo.repoList[j].name == name or \
813 ks.handler.repo.repoList[j].baseurl == baseurl):
814 del ks.handler.repo.repoList[j]
817 if j >= len(ks.handler.repo.repoList):
824 def resolve_groups(creatoropts, repometadata):
826 if 'zypp' == creatoropts['pkgmgr']:
828 ks = creatoropts['ks']
830 for repo in repometadata:
831 """ Mustn't replace group with package list if repo is ready for the
832 corresponding package manager.
835 if iszypp and repo["patterns"]:
837 if not iszypp and repo["comps"]:
840 # But we also must handle such cases, use zypp but repo only has comps,
841 # use yum but repo only has patterns, use zypp but use_comps is true,
842 # use yum but use_comps is false.
844 if iszypp and repo["comps"]:
845 groupfile = repo["comps"]
846 get_pkglist_handler = misc.get_pkglist_in_comps
847 if not iszypp and repo["patterns"]:
848 groupfile = repo["patterns"]
849 get_pkglist_handler = misc.get_pkglist_in_patterns
854 if i >= len(ks.handler.packages.groupList):
856 pkglist = get_pkglist_handler(
857 ks.handler.packages.groupList[i].name,
860 del ks.handler.packages.groupList[i]
862 if pkg not in ks.handler.packages.packageList:
863 ks.handler.packages.packageList.append(pkg)