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
36 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 def apply_wrapper(func):
73 def wrapper(*kargs, **kwargs):
75 func(*kargs, **kwargs)
76 except (OSError, IOError, errors.KsError), err:
77 cfgcls = kargs[0].__class__.__name__
78 if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
79 msger.warning("%s" % err)
82 # just throw out the exception
86 def read_kickstart(path):
87 """Parse a kickstart file and return a KickstartParser instance.
89 This is a simple utility function which takes a path to a kickstart file,
90 parses it and returns a pykickstart KickstartParser instance which can
91 be then passed to an ImageCreator constructor.
93 If an error occurs, a CreatorError exception is thrown.
96 #version = ksversion.makeVersion()
97 #ks = ksparser.KickstartParser(version)
99 using_version = ksversion.DEVEL
100 commandMap[using_version]["desktop"] = desktop.Mic_Desktop
101 commandMap[using_version]["repo"] = micrepo.Mic_Repo
102 commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
103 commandMap[using_version]["part"] = partition.Mic_Partition
104 commandMap[using_version]["partition"] = partition.Mic_Partition
105 commandMap[using_version]["installerfw"] = installerfw.Mic_installerfw
106 commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
107 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
108 dataMap[using_version]["PartData"] = partition.Mic_PartData
109 superclass = ksversion.returnClassForVersion(version=using_version)
111 class KSHandlers(superclass):
113 superclass.__init__(self, mapping=commandMap[using_version])
114 self.prepackages = ksparser.Packages()
115 self.attachment = ksparser.Packages()
117 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
118 ks.registerSection(PrepackageSection(ks.handler))
119 ks.registerSection(AttachmentSection(ks.handler))
122 ks.readKickstart(path)
123 except (kserrors.KickstartParseError, kserrors.KickstartError), err:
124 if msger.ask("Errors occured on kickstart file, skip and continue?"):
125 msger.warning("%s" % err)
128 raise errors.KsError("%s" % err)
132 class KickstartConfig(object):
133 """A base class for applying kickstart configurations to a system."""
134 def __init__(self, instroot):
135 self.instroot = instroot
137 def path(self, subpath):
138 return self.instroot + subpath
140 def _check_sysconfig(self):
141 if not os.path.exists(self.path("/etc/sysconfig")):
142 fs.makedirs(self.path("/etc/sysconfig"))
145 os.chroot(self.instroot)
148 def call(self, args):
149 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
150 raise errors.KsError("Can't find %s in chroot" % args[0])
151 subprocess.call(args, preexec_fn = self.chroot)
156 class LanguageConfig(KickstartConfig):
157 """A class to apply a kickstart language configuration to a system."""
159 def apply(self, kslang):
160 self._check_sysconfig()
162 f = open(self.path("/etc/sysconfig/i18n"), "w+")
163 f.write("LANG=\"" + kslang.lang + "\"\n")
166 class KeyboardConfig(KickstartConfig):
167 """A class to apply a kickstart keyboard configuration to a system."""
169 def apply(self, kskeyboard):
172 # should this impact the X keyboard config too?
173 # or do we want to make X be able to do this mapping?
175 #k = rhpl.keyboard.Keyboard()
176 #if kskeyboard.keyboard:
177 # k.set(kskeyboard.keyboard)
178 #k.write(self.instroot)
181 class TimezoneConfig(KickstartConfig):
182 """A class to apply a kickstart timezone configuration to a system."""
184 def apply(self, kstimezone):
185 self._check_sysconfig()
186 tz = kstimezone.timezone or "America/New_York"
187 utc = str(kstimezone.isUtc)
189 f = open(self.path("/etc/sysconfig/clock"), "w+")
190 f.write("ZONE=\"" + tz + "\"\n")
191 f.write("UTC=" + utc + "\n")
193 tz_source = "/usr/share/zoneinfo/%s" % (tz)
194 tz_dest = "/etc/localtime"
196 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
198 self.call([cpcmd, "-f", tz_source, tz_dest])
200 cpcmd = fs.find_binary_path('cp')
201 subprocess.call([cpcmd, "-f",
202 self.path(tz_source),
204 except (IOError, OSError), (errno, msg):
205 raise errors.KsError("Timezone setting error: %s" % msg)
207 class AuthConfig(KickstartConfig):
208 """A class to apply a kickstart authconfig configuration to a system."""
210 def apply(self, ksauthconfig):
211 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
212 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
213 self.call(args + auth.split())
215 class FirewallConfig(KickstartConfig):
216 """A class to apply a kickstart firewall configuration to a system."""
218 def apply(self, ksfirewall):
220 # FIXME: should handle the rest of the options
222 if not os.path.exists(self.path("/usr/sbin/lokkit")):
224 if ksfirewall.enabled:
227 status = "--disabled"
229 self.call(["/usr/sbin/lokkit",
230 "-f", "--quiet", "--nostart", status])
232 class RootPasswordConfig(KickstartConfig):
233 """A class to apply a kickstart root password configuration to a system."""
235 self.call(["/usr/bin/passwd", "-d", "root"])
237 def set_encrypted(self, password):
238 self.call(["/usr/sbin/usermod", "-p", password, "root"])
240 def set_unencrypted(self, password):
241 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
242 if not os.path.exists("%s/%s" %(self.instroot, p)):
243 raise errors.KsError("Unable to set unencrypted password due "
246 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
247 stdout = subprocess.PIPE,
248 preexec_fn = self.chroot)
249 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
251 stdout = subprocess.PIPE,
252 preexec_fn = self.chroot)
256 def apply(self, ksrootpw):
257 if ksrootpw.isCrypted:
258 self.set_encrypted(ksrootpw.password)
259 elif ksrootpw.password != "":
260 self.set_unencrypted(ksrootpw.password)
264 class UserConfig(KickstartConfig):
265 def set_empty_passwd(self, user):
266 self.call(["/usr/bin/passwd", "-d", user])
268 def set_encrypted_passwd(self, user, password):
269 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
271 def set_unencrypted_passwd(self, user, password):
272 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
273 if not os.path.exists("%s/%s" %(self.instroot, p)):
274 raise errors.KsError("Unable to set unencrypted password due "
277 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
278 stdout = subprocess.PIPE,
279 preexec_fn = self.chroot)
280 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
282 stdout = subprocess.PIPE,
283 preexec_fn = self.chroot)
286 def addUser(self, userconfig):
287 args = [ "/usr/sbin/useradd" ]
288 if userconfig.groups:
289 args += [ "--groups", string.join(userconfig.groups, ",") ]
292 args += [ "-d", "/home/%s" % userconfig.name ]
293 args.append(userconfig.name)
295 dev_null = os.open("/dev/null", os.O_WRONLY)
296 msger.debug('adding user with %s' % args)
297 subprocess.call(args,
300 preexec_fn = self.chroot)
303 msger.warning('Cannot add user using "useradd"')
305 if userconfig.password not in (None, ""):
306 if userconfig.isCrypted:
307 self.set_encrypted_passwd(userconfig.name,
310 self.set_unencrypted_passwd(userconfig.name,
313 self.set_empty_passwd(userconfig.name)
315 raise errors.KsError("Invalid kickstart command: %s" \
316 % userconfig.__str__())
319 def apply(self, user):
320 for userconfig in user.userList:
321 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)
642 def use_installerfw(ks, feature):
643 """ Check if the installer framework has to be used for a feature
646 features = ks.handler.installerfw.features
648 if feature in features or "all" in features:
652 def get_image_size(ks, default = None):
654 for p in ks.handler.partition.partitions:
655 if p.mountpoint == "/" and p.size:
658 return int(__size) * 1024L * 1024L
662 def get_image_fstype(ks, default = None):
663 for p in ks.handler.partition.partitions:
664 if p.mountpoint == "/" and p.fstype:
668 def get_image_fsopts(ks, default = None):
669 for p in ks.handler.partition.partitions:
670 if p.mountpoint == "/" and p.fsopts:
676 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
677 devices.append(ks.handler.device)
679 devices.extend(ks.handler.device.deviceList)
682 for device in devices:
683 if not device.moduleName:
685 modules.extend(device.moduleName.split(":"))
689 def get_timeout(ks, default = None):
690 if not hasattr(ks.handler.bootloader, "timeout"):
692 if ks.handler.bootloader.timeout is None:
694 return int(ks.handler.bootloader.timeout)
696 def get_kernel_args(ks, default = "ro rd.live.image"):
697 if not hasattr(ks.handler.bootloader, "appendLine"):
699 if ks.handler.bootloader.appendLine is None:
701 return "%s %s" %(default, ks.handler.bootloader.appendLine)
703 def get_menu_args(ks, default = ""):
704 if not hasattr(ks.handler.bootloader, "menus"):
706 if ks.handler.bootloader.menus in (None, ""):
708 return "%s" % ks.handler.bootloader.menus
710 def get_default_kernel(ks, default = None):
711 if not hasattr(ks.handler.bootloader, "default"):
713 if not ks.handler.bootloader.default:
715 return ks.handler.bootloader.default
717 def get_repos(ks, repo_urls=None):
719 for repo in ks.handler.repo.repoList:
721 if hasattr(repo, "includepkgs"):
722 inc.extend(repo.includepkgs)
725 if hasattr(repo, "excludepkgs"):
726 exc.extend(repo.excludepkgs)
728 baseurl = repo.baseurl
729 mirrorlist = repo.mirrorlist
731 if repo_urls and repo.name in repo_urls:
732 baseurl = repo_urls[repo.name]
735 baseurl = SafeURL(baseurl, repo.user, repo.passwd)
737 if repos.has_key(repo.name):
738 msger.warning("Overriding already specified repo %s" %(repo.name,))
741 if hasattr(repo, "proxy"):
743 proxy_username = None
744 if hasattr(repo, "proxy_username"):
745 proxy_username = repo.proxy_username
746 proxy_password = None
747 if hasattr(repo, "proxy_password"):
748 proxy_password = repo.proxy_password
749 if hasattr(repo, "debuginfo"):
750 debuginfo = repo.debuginfo
751 if hasattr(repo, "source"):
753 if hasattr(repo, "gpgkey"):
755 if hasattr(repo, "disable"):
756 disable = repo.disable
758 if hasattr(repo, "ssl_verify"):
759 ssl_verify = repo.ssl_verify == "yes"
761 if hasattr(repo, "nocache"):
762 nocache = repo.nocache
764 if hasattr(repo, "cost"):
767 if hasattr(repo, "priority"):
768 priority = repo.priority
770 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
771 proxy, proxy_username, proxy_password, debuginfo,
772 source, gpgkey, disable, ssl_verify, nocache,
775 return repos.values()
777 def convert_method_to_repo(ks):
779 ks.handler.repo.methodToRepo()
780 except (AttributeError, kserrors.KickstartError):
783 def get_attachment(ks, required=()):
784 return ks.handler.attachment.packageList + list(required)
786 def get_pre_packages(ks, required=()):
787 return ks.handler.prepackages.packageList + list(required)
789 def get_packages(ks, required=()):
790 return ks.handler.packages.packageList + list(required)
792 def get_groups(ks, required=()):
793 return ks.handler.packages.groupList + list(required)
795 def get_excluded(ks, required=()):
796 return ks.handler.packages.excludedList + list(required)
798 def get_partitions(ks):
799 return ks.handler.partition.partitions
801 def ignore_missing(ks):
802 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
804 def exclude_docs(ks):
805 return ks.handler.packages.excludeDocs
808 if hasattr(ks.handler.packages, "instLange"):
809 return ks.handler.packages.instLange
810 elif hasattr(ks.handler.packages, "instLangs"):
811 return ks.handler.packages.instLangs
814 def get_post_scripts(ks):
816 for s in ks.handler.scripts:
817 if s.type != ksparser.KS_SCRIPT_POST:
822 def add_repo(ks, repostr):
823 args = repostr.split()
824 repoobj = ks.handler.repo.parse(args[1:])
825 if repoobj and repoobj not in ks.handler.repo.repoList:
826 ks.handler.repo.repoList.append(repoobj)
828 def remove_all_repos(ks):
829 while len(ks.handler.repo.repoList) != 0:
830 del ks.handler.repo.repoList[0]
832 def remove_duplicate_repos(ks):
836 if len(ks.handler.repo.repoList) < 2:
838 if i >= len(ks.handler.repo.repoList) - 1:
840 name = ks.handler.repo.repoList[i].name
841 baseurl = ks.handler.repo.repoList[i].baseurl
842 if j < len(ks.handler.repo.repoList):
843 if (ks.handler.repo.repoList[j].name == name or \
844 ks.handler.repo.repoList[j].baseurl == baseurl):
845 del ks.handler.repo.repoList[j]
848 if j >= len(ks.handler.repo.repoList):
855 def resolve_groups(creatoropts, repometadata):
857 if 'zypp' == creatoropts['pkgmgr']:
859 ks = creatoropts['ks']
861 for repo in repometadata:
862 """ Mustn't replace group with package list if repo is ready for the
863 corresponding package manager.
866 if iszypp and repo["patterns"]:
868 if not iszypp and repo["comps"]:
871 # But we also must handle such cases, use zypp but repo only has comps,
872 # use yum but repo only has patterns, use zypp but use_comps is true,
873 # use yum but use_comps is false.
875 if iszypp and repo["comps"]:
876 groupfile = repo["comps"]
877 get_pkglist_handler = misc.get_pkglist_in_comps
878 if not iszypp and repo["patterns"]:
879 groupfile = repo["patterns"]
880 get_pkglist_handler = misc.get_pkglist_in_patterns
885 if i >= len(ks.handler.packages.groupList):
887 pkglist = get_pkglist_handler(
888 ks.handler.packages.groupList[i].name,
891 del ks.handler.packages.groupList[i]
893 if pkg not in ks.handler.packages.packageList:
894 ks.handler.packages.packageList.append(pkg)