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.
24 import pykickstart.sections as kssections
25 import pykickstart.commands as kscommands
26 import pykickstart.constants as ksconstants
27 import pykickstart.errors as kserrors
28 import pykickstart.parser as ksparser
29 import pykickstart.version as ksversion
30 from pykickstart.handlers.control import commandMap
31 from pykickstart.handlers.control import dataMap
34 from mic.utils import errors, misc, runner, fs_related as fs
35 from custom_commands import desktop, micrepo, micboot, partition
38 AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
41 class PrepackageSection(kssections.Section):
42 sectionOpen = "%prepackages"
44 def handleLine(self, line):
48 (h, s, t) = line.partition('#')
51 self.handler.prepackages.add([line])
53 def handleHeader(self, lineno, args):
54 kssections.Section.handleHeader(self, lineno, args)
56 class AttachmentSection(kssections.Section):
57 sectionOpen = "%attachment"
59 def handleLine(self, line):
63 (h, s, t) = line.partition('#')
66 self.handler.attachment.add([line])
68 def handleHeader(self, lineno, args):
69 kssections.Section.handleHeader(self, lineno, args)
71 def apply_wrapper(func):
72 def wrapper(*kargs, **kwargs):
74 func(*kargs, **kwargs)
75 except (OSError, IOError, errors.KsError), err:
76 cfgcls = kargs[0].__class__.__name__
77 if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
78 msger.warning("%s" % err)
81 # just throw out the exception
85 def read_kickstart(path):
86 """Parse a kickstart file and return a KickstartParser instance.
88 This is a simple utility function which takes a path to a kickstart file,
89 parses it and returns a pykickstart KickstartParser instance which can
90 be then passed to an ImageCreator constructor.
92 If an error occurs, a CreatorError exception is thrown.
95 #version = ksversion.makeVersion()
96 #ks = ksparser.KickstartParser(version)
98 using_version = ksversion.DEVEL
99 commandMap[using_version]["desktop"] = desktop.Mic_Desktop
100 commandMap[using_version]["repo"] = micrepo.Mic_Repo
101 commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
102 commandMap[using_version]["part"] = partition.Mic_Partition
103 commandMap[using_version]["partition"] = partition.Mic_Partition
104 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
105 dataMap[using_version]["PartData"] = partition.Mic_PartData
106 superclass = ksversion.returnClassForVersion(version=using_version)
108 class KSHandlers(superclass):
110 superclass.__init__(self, mapping=commandMap[using_version])
111 self.prepackages = ksparser.Packages()
112 self.attachment = ksparser.Packages()
114 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
115 ks.registerSection(PrepackageSection(ks.handler))
116 ks.registerSection(AttachmentSection(ks.handler))
119 ks.readKickstart(path)
120 except (kserrors.KickstartParseError, kserrors.KickstartError), err:
121 if msger.ask("Errors occured on kickstart file, skip and continue?"):
122 msger.warning("%s" % err)
125 raise errors.KsError("%s" % err)
129 class KickstartConfig(object):
130 """A base class for applying kickstart configurations to a system."""
131 def __init__(self, instroot):
132 self.instroot = instroot
134 def path(self, subpath):
135 return self.instroot + subpath
137 def _check_sysconfig(self):
138 if not os.path.exists(self.path("/etc/sysconfig")):
139 fs.makedirs(self.path("/etc/sysconfig"))
142 os.chroot(self.instroot)
145 def call(self, args):
146 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
147 raise errors.KsError("Can't find %s in chroot" % args[0])
148 subprocess.call(args, preexec_fn = self.chroot)
153 class LanguageConfig(KickstartConfig):
154 """A class to apply a kickstart language configuration to a system."""
156 def apply(self, kslang):
157 self._check_sysconfig()
159 f = open(self.path("/etc/sysconfig/i18n"), "w+")
160 f.write("LANG=\"" + kslang.lang + "\"\n")
163 class KeyboardConfig(KickstartConfig):
164 """A class to apply a kickstart keyboard configuration to a system."""
166 def apply(self, kskeyboard):
169 # should this impact the X keyboard config too?
170 # or do we want to make X be able to do this mapping?
172 #k = rhpl.keyboard.Keyboard()
173 #if kskeyboard.keyboard:
174 # k.set(kskeyboard.keyboard)
175 #k.write(self.instroot)
178 class TimezoneConfig(KickstartConfig):
179 """A class to apply a kickstart timezone configuration to a system."""
181 def apply(self, kstimezone):
182 self._check_sysconfig()
183 tz = kstimezone.timezone or "America/New_York"
184 utc = str(kstimezone.isUtc)
186 f = open(self.path("/etc/sysconfig/clock"), "w+")
187 f.write("ZONE=\"" + tz + "\"\n")
188 f.write("UTC=" + utc + "\n")
190 tz_source = "/usr/share/zoneinfo/%s" % (tz)
191 tz_dest = "/etc/localtime"
193 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
195 self.call([cpcmd, "-f", tz_source, tz_dest])
197 cpcmd = fs.find_binary_path('cp')
198 subprocess.call([cpcmd, "-f",
199 self.path(tz_source),
201 except (IOError, OSError), (errno, msg):
202 raise errors.KsError("Timezone setting error: %s" % msg)
204 class AuthConfig(KickstartConfig):
205 """A class to apply a kickstart authconfig configuration to a system."""
207 def apply(self, ksauthconfig):
208 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
209 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
210 self.call(args + auth.split())
212 class FirewallConfig(KickstartConfig):
213 """A class to apply a kickstart firewall configuration to a system."""
215 def apply(self, ksfirewall):
217 # FIXME: should handle the rest of the options
219 if not os.path.exists(self.path("/usr/sbin/lokkit")):
221 if ksfirewall.enabled:
224 status = "--disabled"
226 self.call(["/usr/sbin/lokkit",
227 "-f", "--quiet", "--nostart", status])
229 class RootPasswordConfig(KickstartConfig):
230 """A class to apply a kickstart root password configuration to a system."""
232 self.call(["/usr/bin/passwd", "-d", "root"])
234 def set_encrypted(self, password):
235 self.call(["/usr/sbin/usermod", "-p", password, "root"])
237 def set_unencrypted(self, password):
238 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
239 if not os.path.exists("%s/%s" %(self.instroot, p)):
240 raise errors.KsError("Unable to set unencrypted password due "
243 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
244 stdout = subprocess.PIPE,
245 preexec_fn = self.chroot)
246 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
248 stdout = subprocess.PIPE,
249 preexec_fn = self.chroot)
253 def apply(self, ksrootpw):
254 if ksrootpw.isCrypted:
255 self.set_encrypted(ksrootpw.password)
256 elif ksrootpw.password != "":
257 self.set_unencrypted(ksrootpw.password)
261 class UserConfig(KickstartConfig):
262 def set_empty_passwd(self, user):
263 self.call(["/usr/bin/passwd", "-d", user])
265 def set_encrypted_passwd(self, user, password):
266 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
268 def set_unencrypted_passwd(self, user, password):
269 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
270 if not os.path.exists("%s/%s" %(self.instroot, p)):
271 raise errors.KsError("Unable to set unencrypted password due "
274 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
275 stdout = subprocess.PIPE,
276 preexec_fn = self.chroot)
277 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
279 stdout = subprocess.PIPE,
280 preexec_fn = self.chroot)
283 def addUser(self, userconfig):
284 args = [ "/usr/sbin/useradd" ]
285 if userconfig.groups:
286 args += [ "--groups", string.join(userconfig.groups, ",") ]
289 args += [ "-d", "/home/%s" % userconfig.name ]
290 args.append(userconfig.name)
292 dev_null = os.open("/dev/null", os.O_WRONLY)
293 msger.debug('adding user with %s' % args)
294 subprocess.call(args,
297 preexec_fn = self.chroot)
300 msger.warning('Cannot add user using "useradd"')
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__())
316 def apply(self, user):
317 for userconfig in user.userList:
318 self.addUser(userconfig)
320 class ServicesConfig(KickstartConfig):
321 """A class to apply a kickstart services configuration to a system."""
323 def apply(self, ksservices):
324 if not os.path.exists(self.path("/sbin/chkconfig")):
326 for s in ksservices.enabled:
327 self.call(["/sbin/chkconfig", s, "on"])
328 for s in ksservices.disabled:
329 self.call(["/sbin/chkconfig", s, "off"])
331 class XConfig(KickstartConfig):
332 """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."""
351 def apply(self, ksdesktop):
352 if ksdesktop.defaultdesktop:
353 self._check_sysconfig()
354 f = open(self.path("/etc/sysconfig/desktop"), "w")
355 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
357 if os.path.exists(self.path("/etc/gdm/custom.conf")):
358 f = open(self.path("/etc/skel/.dmrc"), "w")
359 f.write("[Desktop]\n")
360 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
362 if ksdesktop.session:
363 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
364 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
365 f.write("session="+ksdesktop.session.lower()+"\n")
367 if ksdesktop.autologinuser:
368 self._check_sysconfig()
369 f = open(self.path("/etc/sysconfig/desktop"), "a+")
370 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
372 if os.path.exists(self.path("/etc/gdm/custom.conf")):
373 f = open(self.path("/etc/gdm/custom.conf"), "w")
374 f.write("[daemon]\n")
375 f.write("AutomaticLoginEnable=true\n")
376 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
379 class MoblinRepoConfig(KickstartConfig):
380 """A class to apply a kickstart desktop configuration to a system."""
381 def __create_repo_section(self, repo, type, fd):
384 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
385 reponame = repo.name + reposuffix[type]
388 baseurl = repo.baseurl
390 mirrorlist = repo.mirrorlist
392 elif type == "debuginfo":
394 if repo.baseurl.endswith("/"):
395 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
397 baseurl = os.path.dirname(repo.baseurl)
401 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
402 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
403 mirrorlist += "debug" + "-" + variant
405 elif type == "source":
407 if repo.baseurl.endswith("/"):
408 baseurl = os.path.dirname(
410 os.path.dirname(repo.baseurl)))
412 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
416 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
417 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
418 mirrorlist += "source" + "-" + variant
420 fd.write("[" + reponame + "]\n")
421 fd.write("name=" + reponame + "\n")
422 fd.write("failovermethod=priority\n")
424 auth_url = re.compile(AUTH_URL_PTN)
425 m = auth_url.match(baseurl)
427 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
428 fd.write("baseurl=" + baseurl + "\n")
430 fd.write("mirrorlist=" + mirrorlist + "\n")
431 """ Skip saving proxy settings """
433 # fd.write("proxy=" + repo.proxy + "\n")
434 #if repo.proxy_username:
435 # fd.write("proxy_username=" + repo.proxy_username + "\n")
436 #if repo.proxy_password:
437 # fd.write("proxy_password=" + repo.proxy_password + "\n")
439 fd.write("gpgkey=" + repo.gpgkey + "\n")
440 fd.write("gpgcheck=1\n")
442 fd.write("gpgcheck=0\n")
443 if type == "source" or type == "debuginfo" or repo.disable:
444 fd.write("enabled=0\n")
446 fd.write("enabled=1\n")
449 def __create_repo_file(self, repo, repodir):
450 fs.makedirs(self.path(repodir))
451 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
452 self.__create_repo_section(repo, "base", f)
454 self.__create_repo_section(repo, "debuginfo", f)
456 self.__create_repo_section(repo, "source", f)
460 def apply(self, ksrepo, repodata, repourl):
461 for repo in ksrepo.repoList:
462 if repo.name in repourl:
463 repo.baseurl = repourl[repo.name]
465 #self.__create_repo_file(repo, "/etc/yum.repos.d")
466 self.__create_repo_file(repo, "/etc/zypp/repos.d")
467 """ Import repo gpg keys """
469 for repo in repodata:
472 "--root=%s" % self.instroot,
476 class RPMMacroConfig(KickstartConfig):
477 """A class to apply the specified rpm macros to the filesystem"""
482 if not os.path.exists(self.path("/etc/rpm")):
483 os.mkdir(self.path("/etc/rpm"))
484 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
486 f.write("%_excludedocs 1\n")
487 f.write("%__file_context_path %{nil}\n")
488 if inst_langs(ks) != None:
489 f.write("%_install_langs ")
490 f.write(inst_langs(ks))
494 class NetworkConfig(KickstartConfig):
495 """A class to apply a kickstart network configuration to a system."""
496 def write_ifcfg(self, network):
497 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
502 f.write("DEVICE=%s\n" % network.device)
503 f.write("BOOTPROTO=%s\n" % network.bootProto)
505 if network.bootProto.lower() == "static":
507 f.write("IPADDR=%s\n" % network.ip)
509 f.write("NETMASK=%s\n" % network.netmask)
512 f.write("ONBOOT=on\n")
514 f.write("ONBOOT=off\n")
517 f.write("ESSID=%s\n" % network.essid)
520 if network.ethtool.find("autoneg") == -1:
521 network.ethtool = "autoneg off " + network.ethtool
522 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
524 if network.bootProto.lower() == "dhcp":
526 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
527 if network.dhcpclass:
528 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
531 f.write("MTU=%s\n" % network.mtu)
535 def write_wepkey(self, network):
536 if not network.wepkey:
539 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
542 f.write("KEY=%s\n" % network.wepkey)
545 def write_sysconfig(self, useipv6, hostname, gateway):
546 path = self.path("/etc/sysconfig/network")
550 f.write("NETWORKING=yes\n")
553 f.write("NETWORKING_IPV6=yes\n")
555 f.write("NETWORKING_IPV6=no\n")
558 f.write("HOSTNAME=%s\n" % hostname)
560 f.write("HOSTNAME=localhost.localdomain\n")
563 f.write("GATEWAY=%s\n" % gateway)
567 def write_hosts(self, hostname):
569 if hostname and hostname != "localhost.localdomain":
570 localline += hostname + " "
571 l = hostname.split(".")
573 localline += l[0] + " "
574 localline += "localhost.localdomain localhost"
576 path = self.path("/etc/hosts")
579 f.write("127.0.0.1\t\t%s\n" % localline)
580 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
583 def write_resolv(self, nodns, nameservers):
584 if nodns or not nameservers:
587 path = self.path("/etc/resolv.conf")
591 for ns in (nameservers):
593 f.write("nameserver %s\n" % ns)
598 def apply(self, ksnet):
599 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
607 for network in ksnet.network:
608 if not network.device:
609 raise errors.KsError("No --device specified with "
610 "network kickstart command")
612 if (network.onboot and network.bootProto.lower() != "dhcp" and
613 not (network.ip and network.netmask)):
614 raise errors.KsError("No IP address and/or netmask "
615 "specified with static "
616 "configuration for '%s'" %
619 self.write_ifcfg(network)
620 self.write_wepkey(network)
628 hostname = network.hostname
630 gateway = network.gateway
632 if network.nameserver:
633 nameservers = network.nameserver.split(",")
635 self.write_sysconfig(useipv6, hostname, gateway)
636 self.write_hosts(hostname)
637 self.write_resolv(nodns, nameservers)
640 def get_image_size(ks, default = None):
642 for p in ks.handler.partition.partitions:
643 if p.mountpoint == "/" and p.size:
646 return int(__size) * 1024L * 1024L
650 def get_image_fstype(ks, default = None):
651 for p in ks.handler.partition.partitions:
652 if p.mountpoint == "/" and p.fstype:
656 def get_image_fsopts(ks, default = None):
657 for p in ks.handler.partition.partitions:
658 if p.mountpoint == "/" and p.fsopts:
664 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
665 devices.append(ks.handler.device)
667 devices.extend(ks.handler.device.deviceList)
670 for device in devices:
671 if not device.moduleName:
673 modules.extend(device.moduleName.split(":"))
677 def get_timeout(ks, default = None):
678 if not hasattr(ks.handler.bootloader, "timeout"):
680 if ks.handler.bootloader.timeout is None:
682 return int(ks.handler.bootloader.timeout)
684 def get_kernel_args(ks, default = "ro rd.live.image"):
685 if not hasattr(ks.handler.bootloader, "appendLine"):
687 if ks.handler.bootloader.appendLine is None:
689 return "%s %s" %(default, ks.handler.bootloader.appendLine)
691 def get_menu_args(ks, default = ""):
692 if not hasattr(ks.handler.bootloader, "menus"):
694 if ks.handler.bootloader.menus in (None, ""):
696 return "%s" % ks.handler.bootloader.menus
698 def get_default_kernel(ks, default = None):
699 if not hasattr(ks.handler.bootloader, "default"):
701 if not ks.handler.bootloader.default:
703 return ks.handler.bootloader.default
705 def get_repos(ks, repo_urls=None):
707 for repo in ks.handler.repo.repoList:
709 if hasattr(repo, "includepkgs"):
710 inc.extend(repo.includepkgs)
713 if hasattr(repo, "excludepkgs"):
714 exc.extend(repo.excludepkgs)
716 baseurl = repo.baseurl
717 mirrorlist = repo.mirrorlist
719 if repo_urls and repo.name in repo_urls:
720 baseurl = repo_urls[repo.name]
723 if repos.has_key(repo.name):
724 msger.warning("Overriding already specified repo %s" %(repo.name,))
727 if hasattr(repo, "proxy"):
729 proxy_username = None
730 if hasattr(repo, "proxy_username"):
731 proxy_username = repo.proxy_username
732 proxy_password = None
733 if hasattr(repo, "proxy_password"):
734 proxy_password = repo.proxy_password
735 if hasattr(repo, "debuginfo"):
736 debuginfo = repo.debuginfo
737 if hasattr(repo, "source"):
739 if hasattr(repo, "gpgkey"):
741 if hasattr(repo, "disable"):
742 disable = repo.disable
744 if hasattr(repo, "ssl_verify"):
745 ssl_verify = repo.ssl_verify == "yes"
747 if hasattr(repo, "nocache"):
748 nocache = repo.nocache
750 if hasattr(repo, "cost"):
753 if hasattr(repo, "priority"):
754 priority = repo.priority
756 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
757 proxy, proxy_username, proxy_password, debuginfo,
758 source, gpgkey, disable, ssl_verify, nocache,
761 return repos.values()
763 def convert_method_to_repo(ks):
765 ks.handler.repo.methodToRepo()
766 except (AttributeError, kserrors.KickstartError):
769 def get_attachment(ks, required=()):
770 return ks.handler.attachment.packageList + list(required)
772 def get_pre_packages(ks, required=()):
773 return ks.handler.prepackages.packageList + list(required)
775 def get_packages(ks, required=()):
776 return ks.handler.packages.packageList + list(required)
778 def get_groups(ks, required=()):
779 return ks.handler.packages.groupList + list(required)
781 def get_excluded(ks, required=()):
782 return ks.handler.packages.excludedList + list(required)
784 def get_partitions(ks):
785 return ks.handler.partition.partitions
787 def ignore_missing(ks):
788 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
790 def exclude_docs(ks):
791 return ks.handler.packages.excludeDocs
794 if hasattr(ks.handler.packages, "instLange"):
795 return ks.handler.packages.instLange
796 elif hasattr(ks.handler.packages, "instLangs"):
797 return ks.handler.packages.instLangs
800 def get_post_scripts(ks):
802 for s in ks.handler.scripts:
803 if s.type != ksparser.KS_SCRIPT_POST:
808 def add_repo(ks, repostr):
809 args = repostr.split()
810 repoobj = ks.handler.repo.parse(args[1:])
811 if repoobj and repoobj not in ks.handler.repo.repoList:
812 ks.handler.repo.repoList.append(repoobj)
814 def remove_all_repos(ks):
815 while len(ks.handler.repo.repoList) != 0:
816 del ks.handler.repo.repoList[0]
818 def remove_duplicate_repos(ks):
822 if len(ks.handler.repo.repoList) < 2:
824 if i >= len(ks.handler.repo.repoList) - 1:
826 name = ks.handler.repo.repoList[i].name
827 baseurl = ks.handler.repo.repoList[i].baseurl
828 if j < len(ks.handler.repo.repoList):
829 if (ks.handler.repo.repoList[j].name == name or \
830 ks.handler.repo.repoList[j].baseurl == baseurl):
831 del ks.handler.repo.repoList[j]
834 if j >= len(ks.handler.repo.repoList):
841 def resolve_groups(creatoropts, repometadata):
843 if 'zypp' == creatoropts['pkgmgr']:
845 ks = creatoropts['ks']
847 for repo in repometadata:
848 """ Mustn't replace group with package list if repo is ready for the
849 corresponding package manager.
852 if iszypp and repo["patterns"]:
854 if not iszypp and repo["comps"]:
857 # But we also must handle such cases, use zypp but repo only has comps,
858 # use yum but repo only has patterns, use zypp but use_comps is true,
859 # use yum but use_comps is false.
861 if iszypp and repo["comps"]:
862 groupfile = repo["comps"]
863 get_pkglist_handler = misc.get_pkglist_in_comps
864 if not iszypp and repo["patterns"]:
865 groupfile = repo["patterns"]
866 get_pkglist_handler = misc.get_pkglist_in_patterns
871 if i >= len(ks.handler.packages.groupList):
873 pkglist = get_pkglist_handler(
874 ks.handler.packages.groupList[i].name,
877 del ks.handler.packages.groupList[i]
879 if pkg not in ks.handler.packages.packageList:
880 ks.handler.packages.packageList.append(pkg)