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):
109 def __init__(self, mapping={}):
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:
319 self.addUser(userconfig)
323 class ServicesConfig(KickstartConfig):
324 """A class to apply a kickstart services configuration to a system."""
326 def apply(self, ksservices):
327 if not os.path.exists(self.path("/sbin/chkconfig")):
329 for s in ksservices.enabled:
330 self.call(["/sbin/chkconfig", s, "on"])
331 for s in ksservices.disabled:
332 self.call(["/sbin/chkconfig", s, "off"])
334 class XConfig(KickstartConfig):
335 """A class to apply a kickstart X configuration to a system."""
337 def apply(self, ksxconfig):
338 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
339 f = open(self.path("/etc/inittab"), "rw+")
341 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
345 if ksxconfig.defaultdesktop:
346 self._check_sysconfig()
347 f = open(self.path("/etc/sysconfig/desktop"), "w")
348 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
351 class DesktopConfig(KickstartConfig):
352 """A class to apply a kickstart desktop configuration to a system."""
354 def apply(self, ksdesktop):
355 if ksdesktop.defaultdesktop:
356 self._check_sysconfig()
357 f = open(self.path("/etc/sysconfig/desktop"), "w")
358 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
360 if os.path.exists(self.path("/etc/gdm/custom.conf")):
361 f = open(self.path("/etc/skel/.dmrc"), "w")
362 f.write("[Desktop]\n")
363 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
365 if ksdesktop.session:
366 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
367 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
368 f.write("session="+ksdesktop.session.lower()+"\n")
370 if ksdesktop.autologinuser:
371 self._check_sysconfig()
372 f = open(self.path("/etc/sysconfig/desktop"), "a+")
373 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
375 if os.path.exists(self.path("/etc/gdm/custom.conf")):
376 f = open(self.path("/etc/gdm/custom.conf"), "w")
377 f.write("[daemon]\n")
378 f.write("AutomaticLoginEnable=true\n")
379 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
382 class MoblinRepoConfig(KickstartConfig):
383 """A class to apply a kickstart desktop configuration to a system."""
384 def __create_repo_section(self, repo, type, fd):
387 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
388 reponame = repo.name + reposuffix[type]
391 baseurl = repo.baseurl
393 mirrorlist = repo.mirrorlist
395 elif type == "debuginfo":
397 if repo.baseurl.endswith("/"):
398 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
400 baseurl = os.path.dirname(repo.baseurl)
404 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
405 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
406 mirrorlist += "debug" + "-" + variant
408 elif type == "source":
410 if repo.baseurl.endswith("/"):
411 baseurl = os.path.dirname(
413 os.path.dirname(repo.baseurl)))
415 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
419 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
420 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
421 mirrorlist += "source" + "-" + variant
423 fd.write("[" + reponame + "]\n")
424 fd.write("name=" + reponame + "\n")
425 fd.write("failovermethod=priority\n")
427 auth_url = re.compile(AUTH_URL_PTN)
428 m = auth_url.match(baseurl)
430 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
431 fd.write("baseurl=" + baseurl + "\n")
433 fd.write("mirrorlist=" + mirrorlist + "\n")
434 """ Skip saving proxy settings """
436 # fd.write("proxy=" + repo.proxy + "\n")
437 #if repo.proxy_username:
438 # fd.write("proxy_username=" + repo.proxy_username + "\n")
439 #if repo.proxy_password:
440 # fd.write("proxy_password=" + repo.proxy_password + "\n")
442 fd.write("gpgkey=" + repo.gpgkey + "\n")
443 fd.write("gpgcheck=1\n")
445 fd.write("gpgcheck=0\n")
446 if type == "source" or type == "debuginfo" or repo.disable:
447 fd.write("enabled=0\n")
449 fd.write("enabled=1\n")
452 def __create_repo_file(self, repo, repodir):
453 fs.makedirs(self.path(repodir))
454 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
455 self.__create_repo_section(repo, "base", f)
457 self.__create_repo_section(repo, "debuginfo", f)
459 self.__create_repo_section(repo, "source", f)
463 def apply(self, ksrepo, repodata, repourl):
464 for repo in ksrepo.repoList:
465 if repo.name in repourl:
466 repo.baseurl = repourl[repo.name]
468 #self.__create_repo_file(repo, "/etc/yum.repos.d")
469 self.__create_repo_file(repo, "/etc/zypp/repos.d")
470 """ Import repo gpg keys """
472 for repo in repodata:
475 "--root=%s" % self.instroot,
479 class RPMMacroConfig(KickstartConfig):
480 """A class to apply the specified rpm macros to the filesystem"""
485 if not os.path.exists(self.path("/etc/rpm")):
486 os.mkdir(self.path("/etc/rpm"))
487 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
489 f.write("%_excludedocs 1\n")
490 f.write("%__file_context_path %{nil}\n")
491 if inst_langs(ks) != None:
492 f.write("%_install_langs ")
493 f.write(inst_langs(ks))
497 class NetworkConfig(KickstartConfig):
498 """A class to apply a kickstart network configuration to a system."""
499 def write_ifcfg(self, network):
500 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
505 f.write("DEVICE=%s\n" % network.device)
506 f.write("BOOTPROTO=%s\n" % network.bootProto)
508 if network.bootProto.lower() == "static":
510 f.write("IPADDR=%s\n" % network.ip)
512 f.write("NETMASK=%s\n" % network.netmask)
515 f.write("ONBOOT=on\n")
517 f.write("ONBOOT=off\n")
520 f.write("ESSID=%s\n" % network.essid)
523 if network.ethtool.find("autoneg") == -1:
524 network.ethtool = "autoneg off " + network.ethtool
525 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
527 if network.bootProto.lower() == "dhcp":
529 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
530 if network.dhcpclass:
531 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
534 f.write("MTU=%s\n" % network.mtu)
538 def write_wepkey(self, network):
539 if not network.wepkey:
542 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
545 f.write("KEY=%s\n" % network.wepkey)
548 def write_sysconfig(self, useipv6, hostname, gateway):
549 path = self.path("/etc/sysconfig/network")
553 f.write("NETWORKING=yes\n")
556 f.write("NETWORKING_IPV6=yes\n")
558 f.write("NETWORKING_IPV6=no\n")
561 f.write("HOSTNAME=%s\n" % hostname)
563 f.write("HOSTNAME=localhost.localdomain\n")
566 f.write("GATEWAY=%s\n" % gateway)
570 def write_hosts(self, hostname):
572 if hostname and hostname != "localhost.localdomain":
573 localline += hostname + " "
574 l = hostname.split(".")
576 localline += l[0] + " "
577 localline += "localhost.localdomain localhost"
579 path = self.path("/etc/hosts")
582 f.write("127.0.0.1\t\t%s\n" % localline)
583 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
586 def write_resolv(self, nodns, nameservers):
587 if nodns or not nameservers:
590 path = self.path("/etc/resolv.conf")
594 for ns in (nameservers):
596 f.write("nameserver %s\n" % ns)
601 def apply(self, ksnet):
602 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
610 for network in ksnet.network:
611 if not network.device:
612 raise errors.KsError("No --device specified with "
613 "network kickstart command")
615 if (network.onboot and network.bootProto.lower() != "dhcp" and
616 not (network.ip and network.netmask)):
617 raise errors.KsError("No IP address and/or netmask "
618 "specified with static "
619 "configuration for '%s'" %
622 self.write_ifcfg(network)
623 self.write_wepkey(network)
631 hostname = network.hostname
633 gateway = network.gateway
635 if network.nameserver:
636 nameservers = network.nameserver.split(",")
638 self.write_sysconfig(useipv6, hostname, gateway)
639 self.write_hosts(hostname)
640 self.write_resolv(nodns, nameservers)
643 def get_image_size(ks, default = None):
645 for p in ks.handler.partition.partitions:
646 if p.mountpoint == "/" and p.size:
649 return int(__size) * 1024L * 1024L
653 def get_image_fstype(ks, default = None):
654 for p in ks.handler.partition.partitions:
655 if p.mountpoint == "/" and p.fstype:
659 def get_image_fsopts(ks, default = None):
660 for p in ks.handler.partition.partitions:
661 if p.mountpoint == "/" and p.fsopts:
667 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
668 devices.append(ks.handler.device)
670 devices.extend(ks.handler.device.deviceList)
673 for device in devices:
674 if not device.moduleName:
676 modules.extend(device.moduleName.split(":"))
680 def get_timeout(ks, default = None):
681 if not hasattr(ks.handler.bootloader, "timeout"):
683 if ks.handler.bootloader.timeout is None:
685 return int(ks.handler.bootloader.timeout)
687 def get_kernel_args(ks, default = "ro rd.live.image"):
688 if not hasattr(ks.handler.bootloader, "appendLine"):
690 if ks.handler.bootloader.appendLine is None:
692 return "%s %s" %(default, ks.handler.bootloader.appendLine)
694 def get_menu_args(ks, default = ""):
695 if not hasattr(ks.handler.bootloader, "menus"):
697 if ks.handler.bootloader.menus in (None, ""):
699 return "%s" % ks.handler.bootloader.menus
701 def get_default_kernel(ks, default = None):
702 if not hasattr(ks.handler.bootloader, "default"):
704 if not ks.handler.bootloader.default:
706 return ks.handler.bootloader.default
708 def get_repos(ks, repo_urls = {}):
710 for repo in ks.handler.repo.repoList:
712 if hasattr(repo, "includepkgs"):
713 inc.extend(repo.includepkgs)
716 if hasattr(repo, "excludepkgs"):
717 exc.extend(repo.excludepkgs)
719 baseurl = repo.baseurl
720 mirrorlist = repo.mirrorlist
722 if repo.name in repo_urls:
723 baseurl = repo_urls[repo.name]
726 if repos.has_key(repo.name):
727 msger.warning("Overriding already specified repo %s" %(repo.name,))
730 if hasattr(repo, "proxy"):
732 proxy_username = None
733 if hasattr(repo, "proxy_username"):
734 proxy_username = repo.proxy_username
735 proxy_password = None
736 if hasattr(repo, "proxy_password"):
737 proxy_password = repo.proxy_password
738 if hasattr(repo, "debuginfo"):
739 debuginfo = repo.debuginfo
740 if hasattr(repo, "source"):
742 if hasattr(repo, "gpgkey"):
744 if hasattr(repo, "disable"):
745 disable = repo.disable
747 if hasattr(repo, "ssl_verify"):
748 ssl_verify = repo.ssl_verify == "yes"
750 if hasattr(repo, "nocache"):
751 nocache = repo.nocache
753 if hasattr(repo, "cost"):
756 if hasattr(repo, "priority"):
757 priority = repo.priority
759 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
760 proxy, proxy_username, proxy_password, debuginfo,
761 source, gpgkey, disable, ssl_verify, nocache,
764 return repos.values()
766 def convert_method_to_repo(ks):
768 ks.handler.repo.methodToRepo()
769 except (AttributeError, kserrors.KickstartError):
772 def get_attachment(ks, required = []):
773 return ks.handler.attachment.packageList + required
775 def get_pre_packages(ks, required = []):
776 return ks.handler.prepackages.packageList + required
778 def get_packages(ks, required = []):
779 return ks.handler.packages.packageList + required
781 def get_groups(ks, required = []):
782 return ks.handler.packages.groupList + required
784 def get_excluded(ks, required = []):
785 return ks.handler.packages.excludedList + required
787 def get_partitions(ks, required = []):
788 return ks.handler.partition.partitions
790 def ignore_missing(ks):
791 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
793 def exclude_docs(ks):
794 return ks.handler.packages.excludeDocs
797 if hasattr(ks.handler.packages, "instLange"):
798 return ks.handler.packages.instLange
799 elif hasattr(ks.handler.packages, "instLangs"):
800 return ks.handler.packages.instLangs
803 def get_post_scripts(ks):
805 for s in ks.handler.scripts:
806 if s.type != ksparser.KS_SCRIPT_POST:
811 def add_repo(ks, repostr):
812 args = repostr.split()
813 repoobj = ks.handler.repo.parse(args[1:])
814 if repoobj and repoobj not in ks.handler.repo.repoList:
815 ks.handler.repo.repoList.append(repoobj)
817 def remove_all_repos(ks):
818 while len(ks.handler.repo.repoList) != 0:
819 del ks.handler.repo.repoList[0]
821 def remove_duplicate_repos(ks):
825 if len(ks.handler.repo.repoList) < 2:
827 if i >= len(ks.handler.repo.repoList) - 1:
829 name = ks.handler.repo.repoList[i].name
830 baseurl = ks.handler.repo.repoList[i].baseurl
831 if j < len(ks.handler.repo.repoList):
832 if (ks.handler.repo.repoList[j].name == name or \
833 ks.handler.repo.repoList[j].baseurl == baseurl):
834 del ks.handler.repo.repoList[j]
837 if j >= len(ks.handler.repo.repoList):
844 def resolve_groups(creatoropts, repometadata):
846 if 'zypp' == creatoropts['pkgmgr']:
848 ks = creatoropts['ks']
850 for repo in repometadata:
851 """ Mustn't replace group with package list if repo is ready for the
852 corresponding package manager.
855 if iszypp and repo["patterns"]:
857 if not iszypp and repo["comps"]:
860 # But we also must handle such cases, use zypp but repo only has comps,
861 # use yum but repo only has patterns, use zypp but use_comps is true,
862 # use yum but use_comps is false.
864 if iszypp and repo["comps"]:
865 groupfile = repo["comps"]
866 get_pkglist_handler = misc.get_pkglist_in_comps
867 if not iszypp and repo["patterns"]:
868 groupfile = repo["patterns"]
869 get_pkglist_handler = misc.get_pkglist_in_patterns
874 if i >= len(ks.handler.packages.groupList):
876 pkglist = get_pkglist_handler(
877 ks.handler.packages.groupList[i].name,
880 del ks.handler.packages.groupList[i]
882 if pkg not in ks.handler.packages.packageList:
883 ks.handler.packages.packageList.append(pkg)