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, installerfw
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 commandMap[using_version]["installerfw"] = installerfw.Mic_installerfw
105 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
106 dataMap[using_version]["PartData"] = partition.Mic_PartData
107 superclass = ksversion.returnClassForVersion(version=using_version)
109 class KSHandlers(superclass):
111 superclass.__init__(self, mapping=commandMap[using_version])
112 self.prepackages = ksparser.Packages()
113 self.attachment = ksparser.Packages()
115 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
116 ks.registerSection(PrepackageSection(ks.handler))
117 ks.registerSection(AttachmentSection(ks.handler))
120 ks.readKickstart(path)
121 except (kserrors.KickstartParseError, kserrors.KickstartError), err:
122 if msger.ask("Errors occured on kickstart file, skip and continue?"):
123 msger.warning("%s" % err)
126 raise errors.KsError("%s" % err)
130 class KickstartConfig(object):
131 """A base class for applying kickstart configurations to a system."""
132 def __init__(self, instroot):
133 self.instroot = instroot
135 def path(self, subpath):
136 return self.instroot + subpath
138 def _check_sysconfig(self):
139 if not os.path.exists(self.path("/etc/sysconfig")):
140 fs.makedirs(self.path("/etc/sysconfig"))
143 os.chroot(self.instroot)
146 def call(self, args):
147 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
148 raise errors.KsError("Can't find %s in chroot" % args[0])
149 subprocess.call(args, preexec_fn = self.chroot)
154 class LanguageConfig(KickstartConfig):
155 """A class to apply a kickstart language configuration to a system."""
157 def apply(self, kslang):
158 self._check_sysconfig()
160 f = open(self.path("/etc/sysconfig/i18n"), "w+")
161 f.write("LANG=\"" + kslang.lang + "\"\n")
164 class KeyboardConfig(KickstartConfig):
165 """A class to apply a kickstart keyboard configuration to a system."""
167 def apply(self, kskeyboard):
170 # should this impact the X keyboard config too?
171 # or do we want to make X be able to do this mapping?
173 #k = rhpl.keyboard.Keyboard()
174 #if kskeyboard.keyboard:
175 # k.set(kskeyboard.keyboard)
176 #k.write(self.instroot)
179 class TimezoneConfig(KickstartConfig):
180 """A class to apply a kickstart timezone configuration to a system."""
182 def apply(self, kstimezone):
183 self._check_sysconfig()
184 tz = kstimezone.timezone or "America/New_York"
185 utc = str(kstimezone.isUtc)
187 f = open(self.path("/etc/sysconfig/clock"), "w+")
188 f.write("ZONE=\"" + tz + "\"\n")
189 f.write("UTC=" + utc + "\n")
191 tz_source = "/usr/share/zoneinfo/%s" % (tz)
192 tz_dest = "/etc/localtime"
194 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
196 self.call([cpcmd, "-f", tz_source, tz_dest])
198 cpcmd = fs.find_binary_path('cp')
199 subprocess.call([cpcmd, "-f",
200 self.path(tz_source),
202 except (IOError, OSError), (errno, msg):
203 raise errors.KsError("Timezone setting error: %s" % msg)
205 class AuthConfig(KickstartConfig):
206 """A class to apply a kickstart authconfig configuration to a system."""
208 def apply(self, ksauthconfig):
209 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
210 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
211 self.call(args + auth.split())
213 class FirewallConfig(KickstartConfig):
214 """A class to apply a kickstart firewall configuration to a system."""
216 def apply(self, ksfirewall):
218 # FIXME: should handle the rest of the options
220 if not os.path.exists(self.path("/usr/sbin/lokkit")):
222 if ksfirewall.enabled:
225 status = "--disabled"
227 self.call(["/usr/sbin/lokkit",
228 "-f", "--quiet", "--nostart", status])
230 class RootPasswordConfig(KickstartConfig):
231 """A class to apply a kickstart root password configuration to a system."""
233 self.call(["/usr/bin/passwd", "-d", "root"])
235 def set_encrypted(self, password):
236 self.call(["/usr/sbin/usermod", "-p", password, "root"])
238 def set_unencrypted(self, password):
239 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
240 if not os.path.exists("%s/%s" %(self.instroot, p)):
241 raise errors.KsError("Unable to set unencrypted password due "
244 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
245 stdout = subprocess.PIPE,
246 preexec_fn = self.chroot)
247 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
249 stdout = subprocess.PIPE,
250 preexec_fn = self.chroot)
254 def apply(self, ksrootpw):
255 if ksrootpw.isCrypted:
256 self.set_encrypted(ksrootpw.password)
257 elif ksrootpw.password != "":
258 self.set_unencrypted(ksrootpw.password)
262 class UserConfig(KickstartConfig):
263 def set_empty_passwd(self, user):
264 self.call(["/usr/bin/passwd", "-d", user])
266 def set_encrypted_passwd(self, user, password):
267 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
269 def set_unencrypted_passwd(self, user, password):
270 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
271 if not os.path.exists("%s/%s" %(self.instroot, p)):
272 raise errors.KsError("Unable to set unencrypted password due "
275 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
276 stdout = subprocess.PIPE,
277 preexec_fn = self.chroot)
278 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
280 stdout = subprocess.PIPE,
281 preexec_fn = self.chroot)
284 def addUser(self, userconfig):
285 args = [ "/usr/sbin/useradd" ]
286 if userconfig.groups:
287 args += [ "--groups", string.join(userconfig.groups, ",") ]
290 args += [ "-d", "/home/%s" % userconfig.name ]
291 args.append(userconfig.name)
293 dev_null = os.open("/dev/null", os.O_WRONLY)
294 msger.debug('adding user with %s' % args)
295 subprocess.call(args,
298 preexec_fn = self.chroot)
301 msger.warning('Cannot add user using "useradd"')
303 if userconfig.password not in (None, ""):
304 if userconfig.isCrypted:
305 self.set_encrypted_passwd(userconfig.name,
308 self.set_unencrypted_passwd(userconfig.name,
311 self.set_empty_passwd(userconfig.name)
313 raise errors.KsError("Invalid kickstart command: %s" \
314 % userconfig.__str__())
317 def apply(self, user):
318 for userconfig in user.userList:
319 self.addUser(userconfig)
321 class ServicesConfig(KickstartConfig):
322 """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."""
335 def apply(self, ksxconfig):
336 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
337 f = open(self.path("/etc/inittab"), "rw+")
339 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
343 if ksxconfig.defaultdesktop:
344 self._check_sysconfig()
345 f = open(self.path("/etc/sysconfig/desktop"), "w")
346 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
349 class DesktopConfig(KickstartConfig):
350 """A class to apply a kickstart desktop configuration to a system."""
352 def apply(self, ksdesktop):
353 if ksdesktop.defaultdesktop:
354 self._check_sysconfig()
355 f = open(self.path("/etc/sysconfig/desktop"), "w")
356 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
358 if os.path.exists(self.path("/etc/gdm/custom.conf")):
359 f = open(self.path("/etc/skel/.dmrc"), "w")
360 f.write("[Desktop]\n")
361 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
363 if ksdesktop.session:
364 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
365 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
366 f.write("session="+ksdesktop.session.lower()+"\n")
368 if ksdesktop.autologinuser:
369 self._check_sysconfig()
370 f = open(self.path("/etc/sysconfig/desktop"), "a+")
371 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
373 if os.path.exists(self.path("/etc/gdm/custom.conf")):
374 f = open(self.path("/etc/gdm/custom.conf"), "w")
375 f.write("[daemon]\n")
376 f.write("AutomaticLoginEnable=true\n")
377 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
380 class MoblinRepoConfig(KickstartConfig):
381 """A class to apply a kickstart desktop configuration to a system."""
382 def __create_repo_section(self, repo, type, fd):
385 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
386 reponame = repo.name + reposuffix[type]
389 baseurl = repo.baseurl
391 mirrorlist = repo.mirrorlist
393 elif type == "debuginfo":
395 if repo.baseurl.endswith("/"):
396 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
398 baseurl = os.path.dirname(repo.baseurl)
402 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
403 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
404 mirrorlist += "debug" + "-" + variant
406 elif type == "source":
408 if repo.baseurl.endswith("/"):
409 baseurl = os.path.dirname(
411 os.path.dirname(repo.baseurl)))
413 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
417 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
418 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
419 mirrorlist += "source" + "-" + variant
421 fd.write("[" + reponame + "]\n")
422 fd.write("name=" + reponame + "\n")
423 fd.write("failovermethod=priority\n")
425 auth_url = re.compile(AUTH_URL_PTN)
426 m = auth_url.match(baseurl)
428 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
429 fd.write("baseurl=" + baseurl + "\n")
431 fd.write("mirrorlist=" + mirrorlist + "\n")
432 """ Skip saving proxy settings """
434 # fd.write("proxy=" + repo.proxy + "\n")
435 #if repo.proxy_username:
436 # fd.write("proxy_username=" + repo.proxy_username + "\n")
437 #if repo.proxy_password:
438 # fd.write("proxy_password=" + repo.proxy_password + "\n")
440 fd.write("gpgkey=" + repo.gpgkey + "\n")
441 fd.write("gpgcheck=1\n")
443 fd.write("gpgcheck=0\n")
444 if type == "source" or type == "debuginfo" or repo.disable:
445 fd.write("enabled=0\n")
447 fd.write("enabled=1\n")
450 def __create_repo_file(self, repo, repodir):
451 fs.makedirs(self.path(repodir))
452 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
453 self.__create_repo_section(repo, "base", f)
455 self.__create_repo_section(repo, "debuginfo", f)
457 self.__create_repo_section(repo, "source", f)
461 def apply(self, ksrepo, repodata, repourl):
462 for repo in ksrepo.repoList:
463 if repo.name in repourl:
464 repo.baseurl = repourl[repo.name]
466 #self.__create_repo_file(repo, "/etc/yum.repos.d")
467 self.__create_repo_file(repo, "/etc/zypp/repos.d")
468 """ Import repo gpg keys """
470 for repo in repodata:
473 "--root=%s" % self.instroot,
477 class RPMMacroConfig(KickstartConfig):
478 """A class to apply the specified rpm macros to the filesystem"""
483 if not os.path.exists(self.path("/etc/rpm")):
484 os.mkdir(self.path("/etc/rpm"))
485 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
487 f.write("%_excludedocs 1\n")
488 f.write("%__file_context_path %{nil}\n")
489 if inst_langs(ks) != None:
490 f.write("%_install_langs ")
491 f.write(inst_langs(ks))
495 class NetworkConfig(KickstartConfig):
496 """A class to apply a kickstart network configuration to a system."""
497 def write_ifcfg(self, network):
498 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
503 f.write("DEVICE=%s\n" % network.device)
504 f.write("BOOTPROTO=%s\n" % network.bootProto)
506 if network.bootProto.lower() == "static":
508 f.write("IPADDR=%s\n" % network.ip)
510 f.write("NETMASK=%s\n" % network.netmask)
513 f.write("ONBOOT=on\n")
515 f.write("ONBOOT=off\n")
518 f.write("ESSID=%s\n" % network.essid)
521 if network.ethtool.find("autoneg") == -1:
522 network.ethtool = "autoneg off " + network.ethtool
523 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
525 if network.bootProto.lower() == "dhcp":
527 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
528 if network.dhcpclass:
529 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
532 f.write("MTU=%s\n" % network.mtu)
536 def write_wepkey(self, network):
537 if not network.wepkey:
540 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
543 f.write("KEY=%s\n" % network.wepkey)
546 def write_sysconfig(self, useipv6, hostname, gateway):
547 path = self.path("/etc/sysconfig/network")
551 f.write("NETWORKING=yes\n")
554 f.write("NETWORKING_IPV6=yes\n")
556 f.write("NETWORKING_IPV6=no\n")
559 f.write("HOSTNAME=%s\n" % hostname)
561 f.write("HOSTNAME=localhost.localdomain\n")
564 f.write("GATEWAY=%s\n" % gateway)
568 def write_hosts(self, hostname):
570 if hostname and hostname != "localhost.localdomain":
571 localline += hostname + " "
572 l = hostname.split(".")
574 localline += l[0] + " "
575 localline += "localhost.localdomain localhost"
577 path = self.path("/etc/hosts")
580 f.write("127.0.0.1\t\t%s\n" % localline)
581 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
584 def write_resolv(self, nodns, nameservers):
585 if nodns or not nameservers:
588 path = self.path("/etc/resolv.conf")
592 for ns in (nameservers):
594 f.write("nameserver %s\n" % ns)
599 def apply(self, ksnet):
600 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
608 for network in ksnet.network:
609 if not network.device:
610 raise errors.KsError("No --device specified with "
611 "network kickstart command")
613 if (network.onboot and network.bootProto.lower() != "dhcp" and
614 not (network.ip and network.netmask)):
615 raise errors.KsError("No IP address and/or netmask "
616 "specified with static "
617 "configuration for '%s'" %
620 self.write_ifcfg(network)
621 self.write_wepkey(network)
629 hostname = network.hostname
631 gateway = network.gateway
633 if network.nameserver:
634 nameservers = network.nameserver.split(",")
636 self.write_sysconfig(useipv6, hostname, gateway)
637 self.write_hosts(hostname)
638 self.write_resolv(nodns, nameservers)
640 def use_installerfw(ks, feature):
641 """ Check if the installer framework has to be used for a feature
644 features = ks.handler.installerfw.features
646 if feature in features or "all" in features:
650 def get_image_size(ks, default = None):
652 for p in ks.handler.partition.partitions:
653 if p.mountpoint == "/" and p.size:
656 return int(__size) * 1024L * 1024L
660 def get_image_fstype(ks, default = None):
661 for p in ks.handler.partition.partitions:
662 if p.mountpoint == "/" and p.fstype:
666 def get_image_fsopts(ks, default = None):
667 for p in ks.handler.partition.partitions:
668 if p.mountpoint == "/" and p.fsopts:
674 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
675 devices.append(ks.handler.device)
677 devices.extend(ks.handler.device.deviceList)
680 for device in devices:
681 if not device.moduleName:
683 modules.extend(device.moduleName.split(":"))
687 def get_timeout(ks, default = None):
688 if not hasattr(ks.handler.bootloader, "timeout"):
690 if ks.handler.bootloader.timeout is None:
692 return int(ks.handler.bootloader.timeout)
694 def get_kernel_args(ks, default = "ro rd.live.image"):
695 if not hasattr(ks.handler.bootloader, "appendLine"):
697 if ks.handler.bootloader.appendLine is None:
699 return "%s %s" %(default, ks.handler.bootloader.appendLine)
701 def get_menu_args(ks, default = ""):
702 if not hasattr(ks.handler.bootloader, "menus"):
704 if ks.handler.bootloader.menus in (None, ""):
706 return "%s" % ks.handler.bootloader.menus
708 def get_default_kernel(ks, default = None):
709 if not hasattr(ks.handler.bootloader, "default"):
711 if not ks.handler.bootloader.default:
713 return ks.handler.bootloader.default
715 def get_repos(ks, repo_urls=None):
717 for repo in ks.handler.repo.repoList:
719 if hasattr(repo, "includepkgs"):
720 inc.extend(repo.includepkgs)
723 if hasattr(repo, "excludepkgs"):
724 exc.extend(repo.excludepkgs)
726 baseurl = repo.baseurl
727 mirrorlist = repo.mirrorlist
729 if repo_urls and repo.name in repo_urls:
730 baseurl = repo_urls[repo.name]
733 if repos.has_key(repo.name):
734 msger.warning("Overriding already specified repo %s" %(repo.name,))
737 if hasattr(repo, "proxy"):
739 proxy_username = None
740 if hasattr(repo, "proxy_username"):
741 proxy_username = repo.proxy_username
742 proxy_password = None
743 if hasattr(repo, "proxy_password"):
744 proxy_password = repo.proxy_password
745 if hasattr(repo, "debuginfo"):
746 debuginfo = repo.debuginfo
747 if hasattr(repo, "source"):
749 if hasattr(repo, "gpgkey"):
751 if hasattr(repo, "disable"):
752 disable = repo.disable
754 if hasattr(repo, "ssl_verify"):
755 ssl_verify = repo.ssl_verify == "yes"
757 if hasattr(repo, "nocache"):
758 nocache = repo.nocache
760 if hasattr(repo, "cost"):
763 if hasattr(repo, "priority"):
764 priority = repo.priority
766 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
767 proxy, proxy_username, proxy_password, debuginfo,
768 source, gpgkey, disable, ssl_verify, nocache,
771 return repos.values()
773 def convert_method_to_repo(ks):
775 ks.handler.repo.methodToRepo()
776 except (AttributeError, kserrors.KickstartError):
779 def get_attachment(ks, required=()):
780 return ks.handler.attachment.packageList + list(required)
782 def get_pre_packages(ks, required=()):
783 return ks.handler.prepackages.packageList + list(required)
785 def get_packages(ks, required=()):
786 return ks.handler.packages.packageList + list(required)
788 def get_groups(ks, required=()):
789 return ks.handler.packages.groupList + list(required)
791 def get_excluded(ks, required=()):
792 return ks.handler.packages.excludedList + list(required)
794 def get_partitions(ks):
795 return ks.handler.partition.partitions
797 def ignore_missing(ks):
798 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
800 def exclude_docs(ks):
801 return ks.handler.packages.excludeDocs
804 if hasattr(ks.handler.packages, "instLange"):
805 return ks.handler.packages.instLange
806 elif hasattr(ks.handler.packages, "instLangs"):
807 return ks.handler.packages.instLangs
810 def get_post_scripts(ks):
812 for s in ks.handler.scripts:
813 if s.type != ksparser.KS_SCRIPT_POST:
818 def add_repo(ks, repostr):
819 args = repostr.split()
820 repoobj = ks.handler.repo.parse(args[1:])
821 if repoobj and repoobj not in ks.handler.repo.repoList:
822 ks.handler.repo.repoList.append(repoobj)
824 def remove_all_repos(ks):
825 while len(ks.handler.repo.repoList) != 0:
826 del ks.handler.repo.repoList[0]
828 def remove_duplicate_repos(ks):
832 if len(ks.handler.repo.repoList) < 2:
834 if i >= len(ks.handler.repo.repoList) - 1:
836 name = ks.handler.repo.repoList[i].name
837 baseurl = ks.handler.repo.repoList[i].baseurl
838 if j < len(ks.handler.repo.repoList):
839 if (ks.handler.repo.repoList[j].name == name or \
840 ks.handler.repo.repoList[j].baseurl == baseurl):
841 del ks.handler.repo.repoList[j]
844 if j >= len(ks.handler.repo.repoList):
851 def resolve_groups(creatoropts, repometadata):
853 if 'zypp' == creatoropts['pkgmgr']:
855 ks = creatoropts['ks']
857 for repo in repometadata:
858 """ Mustn't replace group with package list if repo is ready for the
859 corresponding package manager.
862 if iszypp and repo["patterns"]:
864 if not iszypp and repo["comps"]:
867 # But we also must handle such cases, use zypp but repo only has comps,
868 # use yum but repo only has patterns, use zypp but use_comps is true,
869 # use yum but use_comps is false.
871 if iszypp and repo["comps"]:
872 groupfile = repo["comps"]
873 get_pkglist_handler = misc.get_pkglist_in_comps
874 if not iszypp and repo["patterns"]:
875 groupfile = repo["patterns"]
876 get_pkglist_handler = misc.get_pkglist_in_patterns
881 if i >= len(ks.handler.packages.groupList):
883 pkglist = get_pkglist_handler(
884 ks.handler.packages.groupList[i].name,
887 del ks.handler.packages.groupList[i]
889 if pkg not in ks.handler.packages.packageList:
890 ks.handler.packages.packageList.append(pkg)