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.
25 import pykickstart.sections as kssections
26 import pykickstart.commands as kscommands
27 import pykickstart.constants as ksconstants
28 import pykickstart.errors as kserrors
29 import pykickstart.parser as ksparser
30 import pykickstart.version as ksversion
31 from pykickstart.handlers.control import commandMap
32 from pykickstart.handlers.control import dataMap
35 from mic.utils import errors, misc, runner, fs_related as fs
36 from custom_commands import desktop, micrepo, micboot, partition, installerfw
37 from mic.utils.safeurl import SafeURL
40 AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
43 class PrepackageSection(kssections.Section):
44 sectionOpen = "%prepackages"
46 def handleLine(self, line):
50 (h, s, t) = line.partition('#')
53 self.handler.prepackages.add([line])
55 def handleHeader(self, lineno, args):
56 kssections.Section.handleHeader(self, lineno, args)
58 class AttachmentSection(kssections.Section):
59 sectionOpen = "%attachment"
61 def handleLine(self, line):
65 (h, s, t) = line.partition('#')
68 self.handler.attachment.add([line])
70 def handleHeader(self, lineno, args):
71 kssections.Section.handleHeader(self, lineno, args)
73 def apply_wrapper(func):
74 def wrapper(*kargs, **kwargs):
76 func(*kargs, **kwargs)
77 except (OSError, IOError, errors.KsError), err:
78 cfgcls = kargs[0].__class__.__name__
79 if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
80 msger.warning("%s" % err)
83 # just throw out the exception
87 def read_kickstart(path):
88 """Parse a kickstart file and return a KickstartParser instance.
90 This is a simple utility function which takes a path to a kickstart file,
91 parses it and returns a pykickstart KickstartParser instance which can
92 be then passed to an ImageCreator constructor.
94 If an error occurs, a CreatorError exception is thrown.
97 #version = ksversion.makeVersion()
98 #ks = ksparser.KickstartParser(version)
100 using_version = ksversion.DEVEL
101 commandMap[using_version]["desktop"] = desktop.Mic_Desktop
102 commandMap[using_version]["repo"] = micrepo.Mic_Repo
103 commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
104 commandMap[using_version]["part"] = partition.Mic_Partition
105 commandMap[using_version]["partition"] = partition.Mic_Partition
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 f = open(self.path("/etc/locale.conf"), "w+")
167 f.write("LANG=\"" + kslang.lang + "\"\n")
170 class KeyboardConfig(KickstartConfig):
171 """A class to apply a kickstart keyboard configuration to a system."""
173 def apply(self, kskeyboard):
176 # should this impact the X keyboard config too?
177 # or do we want to make X be able to do this mapping?
179 #k = rhpl.keyboard.Keyboard()
180 #if kskeyboard.keyboard:
181 # k.set(kskeyboard.keyboard)
182 #k.write(self.instroot)
185 class TimezoneConfig(KickstartConfig):
186 """A class to apply a kickstart timezone configuration to a system."""
188 def apply(self, kstimezone):
189 self._check_sysconfig()
190 tz = kstimezone.timezone or "America/New_York"
191 utc = str(kstimezone.isUtc)
193 f = open(self.path("/etc/sysconfig/clock"), "w+")
194 f.write("ZONE=\"" + tz + "\"\n")
195 f.write("UTC=" + utc + "\n")
197 tz_source = "/usr/share/zoneinfo/%s" % (tz)
198 tz_dest = "/etc/localtime"
200 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
202 self.call([cpcmd, "-f", tz_source, tz_dest])
204 cpcmd = fs.find_binary_path('cp')
205 subprocess.call([cpcmd, "-f",
206 self.path(tz_source),
208 except (IOError, OSError), (errno, msg):
209 raise errors.KsError("Timezone setting error: %s" % msg)
211 class AuthConfig(KickstartConfig):
212 """A class to apply a kickstart authconfig configuration to a system."""
214 def apply(self, ksauthconfig):
215 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
216 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
217 self.call(args + auth.split())
219 class FirewallConfig(KickstartConfig):
220 """A class to apply a kickstart firewall configuration to a system."""
222 def apply(self, ksfirewall):
224 # FIXME: should handle the rest of the options
226 if not os.path.exists(self.path("/usr/sbin/lokkit")):
228 if ksfirewall.enabled:
231 status = "--disabled"
233 self.call(["/usr/sbin/lokkit",
234 "-f", "--quiet", "--nostart", status])
236 class RootPasswordConfig(KickstartConfig):
237 """A class to apply a kickstart root password configuration to a system."""
239 self.call(["/usr/bin/passwd", "-d", "root"])
241 def set_encrypted(self, password):
242 self.call(["/usr/sbin/usermod", "-p", password, "root"])
244 def set_unencrypted(self, password):
245 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
246 if not os.path.exists("%s/%s" %(self.instroot, p)):
247 raise errors.KsError("Unable to set unencrypted password due "
250 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
251 stdout = subprocess.PIPE,
252 preexec_fn = self.chroot)
253 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
255 stdout = subprocess.PIPE,
256 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, ",") ]
296 args += [ "-d", "/home/%s" % userconfig.name ]
297 args.append(userconfig.name)
299 dev_null = os.open("/dev/null", os.O_WRONLY)
300 msger.debug('adding user with %s' % args)
301 subprocess.call(args,
304 preexec_fn = self.chroot)
307 msger.warning('Cannot add user using "useradd"')
309 if userconfig.password not in (None, ""):
310 if userconfig.isCrypted:
311 self.set_encrypted_passwd(userconfig.name,
314 self.set_unencrypted_passwd(userconfig.name,
317 self.set_empty_passwd(userconfig.name)
319 raise errors.KsError("Invalid kickstart command: %s" \
320 % userconfig.__str__())
323 def apply(self, user):
324 for userconfig in user.userList:
325 self.addUser(userconfig)
327 class ServicesConfig(KickstartConfig):
328 """A class to apply a kickstart services configuration to a system."""
330 def apply(self, ksservices):
331 if not os.path.exists(self.path("/sbin/chkconfig")):
333 for s in ksservices.enabled:
334 self.call(["/sbin/chkconfig", s, "on"])
335 for s in ksservices.disabled:
336 self.call(["/sbin/chkconfig", s, "off"])
338 class XConfig(KickstartConfig):
339 """A class to apply a kickstart X configuration to a system."""
341 def apply(self, ksxconfig):
342 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
343 f = open(self.path("/etc/inittab"), "rw+")
345 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
349 if ksxconfig.defaultdesktop:
350 self._check_sysconfig()
351 f = open(self.path("/etc/sysconfig/desktop"), "w")
352 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
355 class DesktopConfig(KickstartConfig):
356 """A class to apply a kickstart desktop configuration to a system."""
358 def apply(self, ksdesktop):
359 if ksdesktop.defaultdesktop:
360 self._check_sysconfig()
361 f = open(self.path("/etc/sysconfig/desktop"), "w")
362 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
364 if os.path.exists(self.path("/etc/gdm/custom.conf")):
365 f = open(self.path("/etc/skel/.dmrc"), "w")
366 f.write("[Desktop]\n")
367 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
369 if ksdesktop.session:
370 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
371 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
372 f.write("session="+ksdesktop.session.lower()+"\n")
374 if ksdesktop.autologinuser:
375 self._check_sysconfig()
376 f = open(self.path("/etc/sysconfig/desktop"), "a+")
377 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
379 if os.path.exists(self.path("/etc/gdm/custom.conf")):
380 f = open(self.path("/etc/gdm/custom.conf"), "w")
381 f.write("[daemon]\n")
382 f.write("AutomaticLoginEnable=true\n")
383 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
386 class MoblinRepoConfig(KickstartConfig):
387 """A class to apply a kickstart desktop configuration to a system."""
388 def __create_repo_section(self, repo, type, fd):
391 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
392 reponame = repo.name + reposuffix[type]
395 baseurl = repo.baseurl
397 mirrorlist = repo.mirrorlist
399 elif type == "debuginfo":
401 if repo.baseurl.endswith("/"):
402 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
404 baseurl = os.path.dirname(repo.baseurl)
408 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
409 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
410 mirrorlist += "debug" + "-" + variant
412 elif type == "source":
414 if repo.baseurl.endswith("/"):
415 baseurl = os.path.dirname(
417 os.path.dirname(repo.baseurl)))
419 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
423 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
424 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
425 mirrorlist += "source" + "-" + variant
427 fd.write("[" + reponame + "]\n")
428 fd.write("name=" + reponame + "\n")
429 fd.write("failovermethod=priority\n")
431 auth_url = re.compile(AUTH_URL_PTN)
432 m = auth_url.match(baseurl)
434 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
435 fd.write("baseurl=" + baseurl + "\n")
437 fd.write("mirrorlist=" + mirrorlist + "\n")
438 """ Skip saving proxy settings """
440 # fd.write("proxy=" + repo.proxy + "\n")
441 #if repo.proxy_username:
442 # fd.write("proxy_username=" + repo.proxy_username + "\n")
443 #if repo.proxy_password:
444 # fd.write("proxy_password=" + repo.proxy_password + "\n")
446 fd.write("gpgkey=" + repo.gpgkey + "\n")
447 fd.write("gpgcheck=1\n")
449 fd.write("gpgcheck=0\n")
450 if type == "source" or type == "debuginfo" or repo.disable:
451 fd.write("enabled=0\n")
453 fd.write("enabled=1\n")
456 def __create_repo_file(self, repo, repodir):
457 fs.makedirs(self.path(repodir))
458 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
459 self.__create_repo_section(repo, "base", f)
461 self.__create_repo_section(repo, "debuginfo", f)
463 self.__create_repo_section(repo, "source", f)
467 def apply(self, ksrepo, repodata, repourl):
468 for repo in ksrepo.repoList:
469 if repo.name in repourl:
470 repo.baseurl = repourl[repo.name]
472 #self.__create_repo_file(repo, "/etc/yum.repos.d")
473 self.__create_repo_file(repo, "/etc/zypp/repos.d")
474 """ Import repo gpg keys """
476 for repo in repodata:
479 "--root=%s" % self.instroot,
483 class RPMMacroConfig(KickstartConfig):
484 """A class to apply the specified rpm macros to the filesystem"""
489 if not os.path.exists(self.path("/etc/rpm")):
490 os.mkdir(self.path("/etc/rpm"))
491 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
493 f.write("%_excludedocs 1\n")
494 f.write("%__file_context_path %{nil}\n")
495 if inst_langs(ks) != None:
496 f.write("%_install_langs ")
497 f.write(inst_langs(ks))
501 class NetworkConfig(KickstartConfig):
502 """A class to apply a kickstart network configuration to a system."""
503 def write_ifcfg(self, network):
504 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
509 f.write("DEVICE=%s\n" % network.device)
510 f.write("BOOTPROTO=%s\n" % network.bootProto)
512 if network.bootProto.lower() == "static":
514 f.write("IPADDR=%s\n" % network.ip)
516 f.write("NETMASK=%s\n" % network.netmask)
519 f.write("ONBOOT=on\n")
521 f.write("ONBOOT=off\n")
524 f.write("ESSID=%s\n" % network.essid)
527 if network.ethtool.find("autoneg") == -1:
528 network.ethtool = "autoneg off " + network.ethtool
529 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
531 if network.bootProto.lower() == "dhcp":
533 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
534 if network.dhcpclass:
535 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
538 f.write("MTU=%s\n" % network.mtu)
542 def write_wepkey(self, network):
543 if not network.wepkey:
546 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
549 f.write("KEY=%s\n" % network.wepkey)
552 def write_sysconfig(self, useipv6, hostname, gateway):
553 path = self.path("/etc/sysconfig/network")
557 f.write("NETWORKING=yes\n")
560 f.write("NETWORKING_IPV6=yes\n")
562 f.write("NETWORKING_IPV6=no\n")
565 f.write("HOSTNAME=%s\n" % hostname)
567 f.write("HOSTNAME=localhost.localdomain\n")
570 f.write("GATEWAY=%s\n" % gateway)
574 def write_hosts(self, hostname):
576 if hostname and hostname != "localhost.localdomain":
577 localline += hostname + " "
578 l = hostname.split(".")
580 localline += l[0] + " "
581 localline += "localhost.localdomain localhost"
583 path = self.path("/etc/hosts")
586 f.write("127.0.0.1\t\t%s\n" % localline)
587 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
590 def write_resolv(self, nodns, nameservers):
591 if nodns or not nameservers:
594 path = self.path("/etc/resolv.conf")
598 for ns in (nameservers):
600 f.write("nameserver %s\n" % ns)
605 def apply(self, ksnet):
606 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
614 for network in ksnet.network:
615 if not network.device:
616 raise errors.KsError("No --device specified with "
617 "network kickstart command")
619 if (network.onboot and network.bootProto.lower() != "dhcp" and
620 not (network.ip and network.netmask)):
621 raise errors.KsError("No IP address and/or netmask "
622 "specified with static "
623 "configuration for '%s'" %
626 self.write_ifcfg(network)
627 self.write_wepkey(network)
635 hostname = network.hostname
637 gateway = network.gateway
639 if network.nameserver:
640 nameservers = network.nameserver.split(",")
642 self.write_sysconfig(useipv6, hostname, gateway)
643 self.write_hosts(hostname)
644 self.write_resolv(nodns, nameservers)
646 def use_installerfw(ks, feature):
647 """ Check if the installer framework has to be used for a feature
650 features = ks.handler.installerfw.features
652 if feature in features or "all" in features:
656 def get_image_size(ks, default = None):
658 for p in ks.handler.partition.partitions:
659 if p.mountpoint == "/" and p.size:
662 return int(__size) * 1024L * 1024L
666 def get_image_fstype(ks, default = None):
667 for p in ks.handler.partition.partitions:
668 if p.mountpoint == "/" and p.fstype:
672 def get_image_fsopts(ks, default = None):
673 for p in ks.handler.partition.partitions:
674 if p.mountpoint == "/" and p.fsopts:
680 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
681 devices.append(ks.handler.device)
683 devices.extend(ks.handler.device.deviceList)
686 for device in devices:
687 if not device.moduleName:
689 modules.extend(device.moduleName.split(":"))
693 def get_timeout(ks, default = None):
694 if not hasattr(ks.handler.bootloader, "timeout"):
696 if ks.handler.bootloader.timeout is None:
698 return int(ks.handler.bootloader.timeout)
700 def get_kernel_args(ks, default = "ro rd.live.image"):
701 if not hasattr(ks.handler.bootloader, "appendLine"):
703 if ks.handler.bootloader.appendLine is None:
705 return "%s %s" %(default, ks.handler.bootloader.appendLine)
707 def get_menu_args(ks, default = ""):
708 if not hasattr(ks.handler.bootloader, "menus"):
710 if ks.handler.bootloader.menus in (None, ""):
712 return "%s" % ks.handler.bootloader.menus
714 def get_default_kernel(ks, default = None):
715 if not hasattr(ks.handler.bootloader, "default"):
717 if not ks.handler.bootloader.default:
719 return ks.handler.bootloader.default
721 RepoType = collections.namedtuple("Repo",
722 "name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy, \
723 proxy_username, proxy_password, debuginfo, \
724 source, gpgkey, disable, ssl_verify, nocache, \
727 def Repo(name, baseurl, mirrorlist=None, includepkgs=[], excludepkgs=[], proxy=None,
728 proxy_username=None, proxy_password=None, debuginfo=None,
729 source=None, gpgkey=None, disable=None, ssl_verify=False,
730 nocache=False, cost=None, priority=None):
731 return RepoType(name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy,
732 proxy_username, proxy_password, debuginfo,
733 source, gpgkey, disable, ssl_verify == "yes", nocache,
737 def get_repos(ks, repo_urls=None, ignore_ksrepo=False):
739 for repodata in ks.handler.repo.repoList:
741 for field in RepoType._fields:
742 if hasattr(repodata, field) and getattr(repodata, field):
743 repo[field] = getattr(repodata, field)
745 if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'):
746 repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'),
747 getattr(repodata, 'user', None),
748 getattr(repodata, 'passwd', None))
751 repos[repo['name']] = Repo(**repo)
756 for name, repo in repo_urls.items():
757 if 'baseurl' in repo:
758 repo['baseurl'] = SafeURL(repo.get('baseurl'),
759 repo.get('user', None),
760 repo.get('passwd', None))
761 repos[name] = Repo(**repo)
763 return repos.values()
765 def convert_method_to_repo(ks):
767 ks.handler.repo.methodToRepo()
768 except (AttributeError, kserrors.KickstartError):
771 def get_attachment(ks, required=()):
772 return ks.handler.attachment.packageList + list(required)
774 def get_pre_packages(ks, required=()):
775 return ks.handler.prepackages.packageList + list(required)
777 def get_packages(ks, required=()):
778 return ks.handler.packages.packageList + list(required)
780 def get_groups(ks, required=()):
781 return ks.handler.packages.groupList + list(required)
783 def get_excluded(ks, required=()):
784 return ks.handler.packages.excludedList + list(required)
786 def get_partitions(ks):
787 return ks.handler.partition.partitions
789 def ignore_missing(ks):
790 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
792 def exclude_docs(ks):
793 return ks.handler.packages.excludeDocs
796 if hasattr(ks.handler.packages, "instLange"):
797 return ks.handler.packages.instLange
798 elif hasattr(ks.handler.packages, "instLangs"):
799 return ks.handler.packages.instLangs
802 def get_post_scripts(ks):
804 for s in ks.handler.scripts:
805 if s.type != ksparser.KS_SCRIPT_POST:
810 def add_repo(ks, repostr):
811 args = repostr.split()
812 repoobj = ks.handler.repo.parse(args[1:])
813 if repoobj and repoobj not in ks.handler.repo.repoList:
814 ks.handler.repo.repoList.append(repoobj)
816 def remove_all_repos(ks):
817 while len(ks.handler.repo.repoList) != 0:
818 del ks.handler.repo.repoList[0]
820 def remove_duplicate_repos(ks):
824 if len(ks.handler.repo.repoList) < 2:
826 if i >= len(ks.handler.repo.repoList) - 1:
828 name = ks.handler.repo.repoList[i].name
829 baseurl = ks.handler.repo.repoList[i].baseurl
830 if j < len(ks.handler.repo.repoList):
831 if (ks.handler.repo.repoList[j].name == name or \
832 ks.handler.repo.repoList[j].baseurl == baseurl):
833 del ks.handler.repo.repoList[j]
836 if j >= len(ks.handler.repo.repoList):
843 def resolve_groups(creatoropts, repometadata):
845 if 'zypp' == creatoropts['pkgmgr']:
847 ks = creatoropts['ks']
849 for repo in repometadata:
850 """ Mustn't replace group with package list if repo is ready for the
851 corresponding package manager.
854 if iszypp and repo["patterns"]:
856 if not iszypp and repo["comps"]:
859 # But we also must handle such cases, use zypp but repo only has comps,
860 # use yum but repo only has patterns, use zypp but use_comps is true,
861 # use yum but use_comps is false.
863 if iszypp and repo["comps"]:
864 groupfile = repo["comps"]
865 get_pkglist_handler = misc.get_pkglist_in_comps
866 if not iszypp and repo["patterns"]:
867 groupfile = repo["patterns"]
868 get_pkglist_handler = misc.get_pkglist_in_patterns
873 if i >= len(ks.handler.packages.groupList):
875 pkglist = get_pkglist_handler(
876 ks.handler.packages.groupList[i].name,
879 del ks.handler.packages.groupList[i]
881 if pkg not in ks.handler.packages.packageList:
882 ks.handler.packages.packageList.append(pkg)