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 commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
106 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
107 dataMap[using_version]["PartData"] = partition.Mic_PartData
108 superclass = ksversion.returnClassForVersion(version=using_version)
110 class KSHandlers(superclass):
112 superclass.__init__(self, mapping=commandMap[using_version])
113 self.prepackages = ksparser.Packages()
114 self.attachment = ksparser.Packages()
116 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
117 ks.registerSection(PrepackageSection(ks.handler))
118 ks.registerSection(AttachmentSection(ks.handler))
121 ks.readKickstart(path)
122 except (kserrors.KickstartParseError, kserrors.KickstartError), err:
123 if msger.ask("Errors occured on kickstart file, skip and continue?"):
124 msger.warning("%s" % err)
127 raise errors.KsError("%s" % err)
131 class KickstartConfig(object):
132 """A base class for applying kickstart configurations to a system."""
133 def __init__(self, instroot):
134 self.instroot = instroot
136 def path(self, subpath):
137 return self.instroot + subpath
139 def _check_sysconfig(self):
140 if not os.path.exists(self.path("/etc/sysconfig")):
141 fs.makedirs(self.path("/etc/sysconfig"))
144 os.chroot(self.instroot)
147 def call(self, args):
148 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
149 raise errors.KsError("Can't find %s in chroot" % args[0])
150 subprocess.call(args, preexec_fn = self.chroot)
155 class LanguageConfig(KickstartConfig):
156 """A class to apply a kickstart language configuration to a system."""
158 def apply(self, kslang):
159 self._check_sysconfig()
161 f = open(self.path("/etc/sysconfig/i18n"), "w+")
162 f.write("LANG=\"" + kslang.lang + "\"\n")
165 class KeyboardConfig(KickstartConfig):
166 """A class to apply a kickstart keyboard configuration to a system."""
168 def apply(self, kskeyboard):
171 # should this impact the X keyboard config too?
172 # or do we want to make X be able to do this mapping?
174 #k = rhpl.keyboard.Keyboard()
175 #if kskeyboard.keyboard:
176 # k.set(kskeyboard.keyboard)
177 #k.write(self.instroot)
180 class TimezoneConfig(KickstartConfig):
181 """A class to apply a kickstart timezone configuration to a system."""
183 def apply(self, kstimezone):
184 self._check_sysconfig()
185 tz = kstimezone.timezone or "America/New_York"
186 utc = str(kstimezone.isUtc)
188 f = open(self.path("/etc/sysconfig/clock"), "w+")
189 f.write("ZONE=\"" + tz + "\"\n")
190 f.write("UTC=" + utc + "\n")
192 tz_source = "/usr/share/zoneinfo/%s" % (tz)
193 tz_dest = "/etc/localtime"
195 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
197 self.call([cpcmd, "-f", tz_source, tz_dest])
199 cpcmd = fs.find_binary_path('cp')
200 subprocess.call([cpcmd, "-f",
201 self.path(tz_source),
203 except (IOError, OSError), (errno, msg):
204 raise errors.KsError("Timezone setting error: %s" % msg)
206 class AuthConfig(KickstartConfig):
207 """A class to apply a kickstart authconfig configuration to a system."""
209 def apply(self, ksauthconfig):
210 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
211 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
212 self.call(args + auth.split())
214 class FirewallConfig(KickstartConfig):
215 """A class to apply a kickstart firewall configuration to a system."""
217 def apply(self, ksfirewall):
219 # FIXME: should handle the rest of the options
221 if not os.path.exists(self.path("/usr/sbin/lokkit")):
223 if ksfirewall.enabled:
226 status = "--disabled"
228 self.call(["/usr/sbin/lokkit",
229 "-f", "--quiet", "--nostart", status])
231 class RootPasswordConfig(KickstartConfig):
232 """A class to apply a kickstart root password configuration to a system."""
234 self.call(["/usr/bin/passwd", "-d", "root"])
236 def set_encrypted(self, password):
237 self.call(["/usr/sbin/usermod", "-p", password, "root"])
239 def set_unencrypted(self, password):
240 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
241 if not os.path.exists("%s/%s" %(self.instroot, p)):
242 raise errors.KsError("Unable to set unencrypted password due "
245 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
246 stdout = subprocess.PIPE,
247 preexec_fn = self.chroot)
248 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
250 stdout = subprocess.PIPE,
251 preexec_fn = self.chroot)
255 def apply(self, ksrootpw):
256 if ksrootpw.isCrypted:
257 self.set_encrypted(ksrootpw.password)
258 elif ksrootpw.password != "":
259 self.set_unencrypted(ksrootpw.password)
263 class UserConfig(KickstartConfig):
264 def set_empty_passwd(self, user):
265 self.call(["/usr/bin/passwd", "-d", user])
267 def set_encrypted_passwd(self, user, password):
268 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
270 def set_unencrypted_passwd(self, user, password):
271 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
272 if not os.path.exists("%s/%s" %(self.instroot, p)):
273 raise errors.KsError("Unable to set unencrypted password due "
276 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
277 stdout = subprocess.PIPE,
278 preexec_fn = self.chroot)
279 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
281 stdout = subprocess.PIPE,
282 preexec_fn = self.chroot)
285 def addUser(self, userconfig):
286 args = [ "/usr/sbin/useradd" ]
287 if userconfig.groups:
288 args += [ "--groups", string.join(userconfig.groups, ",") ]
291 args += [ "-d", "/home/%s" % userconfig.name ]
292 args.append(userconfig.name)
294 dev_null = os.open("/dev/null", os.O_WRONLY)
295 msger.debug('adding user with %s' % args)
296 subprocess.call(args,
299 preexec_fn = self.chroot)
302 msger.warning('Cannot add user using "useradd"')
304 if userconfig.password not in (None, ""):
305 if userconfig.isCrypted:
306 self.set_encrypted_passwd(userconfig.name,
309 self.set_unencrypted_passwd(userconfig.name,
312 self.set_empty_passwd(userconfig.name)
314 raise errors.KsError("Invalid kickstart command: %s" \
315 % userconfig.__str__())
318 def apply(self, user):
319 for userconfig in user.userList:
320 self.addUser(userconfig)
322 class ServicesConfig(KickstartConfig):
323 """A class to apply a kickstart services configuration to a system."""
325 def apply(self, ksservices):
326 if not os.path.exists(self.path("/sbin/chkconfig")):
328 for s in ksservices.enabled:
329 self.call(["/sbin/chkconfig", s, "on"])
330 for s in ksservices.disabled:
331 self.call(["/sbin/chkconfig", s, "off"])
333 class XConfig(KickstartConfig):
334 """A class to apply a kickstart X configuration to a system."""
336 def apply(self, ksxconfig):
337 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
338 f = open(self.path("/etc/inittab"), "rw+")
340 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
344 if ksxconfig.defaultdesktop:
345 self._check_sysconfig()
346 f = open(self.path("/etc/sysconfig/desktop"), "w")
347 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
350 class DesktopConfig(KickstartConfig):
351 """A class to apply a kickstart desktop configuration to a system."""
353 def apply(self, ksdesktop):
354 if ksdesktop.defaultdesktop:
355 self._check_sysconfig()
356 f = open(self.path("/etc/sysconfig/desktop"), "w")
357 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
359 if os.path.exists(self.path("/etc/gdm/custom.conf")):
360 f = open(self.path("/etc/skel/.dmrc"), "w")
361 f.write("[Desktop]\n")
362 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
364 if ksdesktop.session:
365 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
366 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
367 f.write("session="+ksdesktop.session.lower()+"\n")
369 if ksdesktop.autologinuser:
370 self._check_sysconfig()
371 f = open(self.path("/etc/sysconfig/desktop"), "a+")
372 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
374 if os.path.exists(self.path("/etc/gdm/custom.conf")):
375 f = open(self.path("/etc/gdm/custom.conf"), "w")
376 f.write("[daemon]\n")
377 f.write("AutomaticLoginEnable=true\n")
378 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
381 class MoblinRepoConfig(KickstartConfig):
382 """A class to apply a kickstart desktop configuration to a system."""
383 def __create_repo_section(self, repo, type, fd):
386 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
387 reponame = repo.name + reposuffix[type]
390 baseurl = repo.baseurl
392 mirrorlist = repo.mirrorlist
394 elif type == "debuginfo":
396 if repo.baseurl.endswith("/"):
397 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
399 baseurl = os.path.dirname(repo.baseurl)
403 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
404 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
405 mirrorlist += "debug" + "-" + variant
407 elif type == "source":
409 if repo.baseurl.endswith("/"):
410 baseurl = os.path.dirname(
412 os.path.dirname(repo.baseurl)))
414 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
418 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
419 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
420 mirrorlist += "source" + "-" + variant
422 fd.write("[" + reponame + "]\n")
423 fd.write("name=" + reponame + "\n")
424 fd.write("failovermethod=priority\n")
426 auth_url = re.compile(AUTH_URL_PTN)
427 m = auth_url.match(baseurl)
429 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
430 fd.write("baseurl=" + baseurl + "\n")
432 fd.write("mirrorlist=" + mirrorlist + "\n")
433 """ Skip saving proxy settings """
435 # fd.write("proxy=" + repo.proxy + "\n")
436 #if repo.proxy_username:
437 # fd.write("proxy_username=" + repo.proxy_username + "\n")
438 #if repo.proxy_password:
439 # fd.write("proxy_password=" + repo.proxy_password + "\n")
441 fd.write("gpgkey=" + repo.gpgkey + "\n")
442 fd.write("gpgcheck=1\n")
444 fd.write("gpgcheck=0\n")
445 if type == "source" or type == "debuginfo" or repo.disable:
446 fd.write("enabled=0\n")
448 fd.write("enabled=1\n")
451 def __create_repo_file(self, repo, repodir):
452 fs.makedirs(self.path(repodir))
453 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
454 self.__create_repo_section(repo, "base", f)
456 self.__create_repo_section(repo, "debuginfo", f)
458 self.__create_repo_section(repo, "source", f)
462 def apply(self, ksrepo, repodata, repourl):
463 for repo in ksrepo.repoList:
464 if repo.name in repourl:
465 repo.baseurl = repourl[repo.name]
467 #self.__create_repo_file(repo, "/etc/yum.repos.d")
468 self.__create_repo_file(repo, "/etc/zypp/repos.d")
469 """ Import repo gpg keys """
471 for repo in repodata:
474 "--root=%s" % self.instroot,
478 class RPMMacroConfig(KickstartConfig):
479 """A class to apply the specified rpm macros to the filesystem"""
484 if not os.path.exists(self.path("/etc/rpm")):
485 os.mkdir(self.path("/etc/rpm"))
486 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
488 f.write("%_excludedocs 1\n")
489 f.write("%__file_context_path %{nil}\n")
490 if inst_langs(ks) != None:
491 f.write("%_install_langs ")
492 f.write(inst_langs(ks))
496 class NetworkConfig(KickstartConfig):
497 """A class to apply a kickstart network configuration to a system."""
498 def write_ifcfg(self, network):
499 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
504 f.write("DEVICE=%s\n" % network.device)
505 f.write("BOOTPROTO=%s\n" % network.bootProto)
507 if network.bootProto.lower() == "static":
509 f.write("IPADDR=%s\n" % network.ip)
511 f.write("NETMASK=%s\n" % network.netmask)
514 f.write("ONBOOT=on\n")
516 f.write("ONBOOT=off\n")
519 f.write("ESSID=%s\n" % network.essid)
522 if network.ethtool.find("autoneg") == -1:
523 network.ethtool = "autoneg off " + network.ethtool
524 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
526 if network.bootProto.lower() == "dhcp":
528 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
529 if network.dhcpclass:
530 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
533 f.write("MTU=%s\n" % network.mtu)
537 def write_wepkey(self, network):
538 if not network.wepkey:
541 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
544 f.write("KEY=%s\n" % network.wepkey)
547 def write_sysconfig(self, useipv6, hostname, gateway):
548 path = self.path("/etc/sysconfig/network")
552 f.write("NETWORKING=yes\n")
555 f.write("NETWORKING_IPV6=yes\n")
557 f.write("NETWORKING_IPV6=no\n")
560 f.write("HOSTNAME=%s\n" % hostname)
562 f.write("HOSTNAME=localhost.localdomain\n")
565 f.write("GATEWAY=%s\n" % gateway)
569 def write_hosts(self, hostname):
571 if hostname and hostname != "localhost.localdomain":
572 localline += hostname + " "
573 l = hostname.split(".")
575 localline += l[0] + " "
576 localline += "localhost.localdomain localhost"
578 path = self.path("/etc/hosts")
581 f.write("127.0.0.1\t\t%s\n" % localline)
582 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
585 def write_resolv(self, nodns, nameservers):
586 if nodns or not nameservers:
589 path = self.path("/etc/resolv.conf")
593 for ns in (nameservers):
595 f.write("nameserver %s\n" % ns)
600 def apply(self, ksnet):
601 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
609 for network in ksnet.network:
610 if not network.device:
611 raise errors.KsError("No --device specified with "
612 "network kickstart command")
614 if (network.onboot and network.bootProto.lower() != "dhcp" and
615 not (network.ip and network.netmask)):
616 raise errors.KsError("No IP address and/or netmask "
617 "specified with static "
618 "configuration for '%s'" %
621 self.write_ifcfg(network)
622 self.write_wepkey(network)
630 hostname = network.hostname
632 gateway = network.gateway
634 if network.nameserver:
635 nameservers = network.nameserver.split(",")
637 self.write_sysconfig(useipv6, hostname, gateway)
638 self.write_hosts(hostname)
639 self.write_resolv(nodns, nameservers)
641 def use_installerfw(ks, feature):
642 """ Check if the installer framework has to be used for a feature
645 features = ks.handler.installerfw.features
647 if feature in features or "all" in features:
651 def get_image_size(ks, default = None):
653 for p in ks.handler.partition.partitions:
654 if p.mountpoint == "/" and p.size:
657 return int(__size) * 1024L * 1024L
661 def get_image_fstype(ks, default = None):
662 for p in ks.handler.partition.partitions:
663 if p.mountpoint == "/" and p.fstype:
667 def get_image_fsopts(ks, default = None):
668 for p in ks.handler.partition.partitions:
669 if p.mountpoint == "/" and p.fsopts:
675 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
676 devices.append(ks.handler.device)
678 devices.extend(ks.handler.device.deviceList)
681 for device in devices:
682 if not device.moduleName:
684 modules.extend(device.moduleName.split(":"))
688 def get_timeout(ks, default = None):
689 if not hasattr(ks.handler.bootloader, "timeout"):
691 if ks.handler.bootloader.timeout is None:
693 return int(ks.handler.bootloader.timeout)
695 def get_kernel_args(ks, default = "ro rd.live.image"):
696 if not hasattr(ks.handler.bootloader, "appendLine"):
698 if ks.handler.bootloader.appendLine is None:
700 return "%s %s" %(default, ks.handler.bootloader.appendLine)
702 def get_menu_args(ks, default = ""):
703 if not hasattr(ks.handler.bootloader, "menus"):
705 if ks.handler.bootloader.menus in (None, ""):
707 return "%s" % ks.handler.bootloader.menus
709 def get_default_kernel(ks, default = None):
710 if not hasattr(ks.handler.bootloader, "default"):
712 if not ks.handler.bootloader.default:
714 return ks.handler.bootloader.default
716 def get_repos(ks, repo_urls=None):
718 for repo in ks.handler.repo.repoList:
720 if hasattr(repo, "includepkgs"):
721 inc.extend(repo.includepkgs)
724 if hasattr(repo, "excludepkgs"):
725 exc.extend(repo.excludepkgs)
727 baseurl = repo.baseurl
728 mirrorlist = repo.mirrorlist
730 if repo_urls and repo.name in repo_urls:
731 baseurl = repo_urls[repo.name]
734 if repos.has_key(repo.name):
735 msger.warning("Overriding already specified repo %s" %(repo.name,))
738 if hasattr(repo, "proxy"):
740 proxy_username = None
741 if hasattr(repo, "proxy_username"):
742 proxy_username = repo.proxy_username
743 proxy_password = None
744 if hasattr(repo, "proxy_password"):
745 proxy_password = repo.proxy_password
746 if hasattr(repo, "debuginfo"):
747 debuginfo = repo.debuginfo
748 if hasattr(repo, "source"):
750 if hasattr(repo, "gpgkey"):
752 if hasattr(repo, "disable"):
753 disable = repo.disable
755 if hasattr(repo, "ssl_verify"):
756 ssl_verify = repo.ssl_verify == "yes"
758 if hasattr(repo, "nocache"):
759 nocache = repo.nocache
761 if hasattr(repo, "cost"):
764 if hasattr(repo, "priority"):
765 priority = repo.priority
767 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
768 proxy, proxy_username, proxy_password, debuginfo,
769 source, gpgkey, disable, ssl_verify, nocache,
772 return repos.values()
774 def convert_method_to_repo(ks):
776 ks.handler.repo.methodToRepo()
777 except (AttributeError, kserrors.KickstartError):
780 def get_attachment(ks, required=()):
781 return ks.handler.attachment.packageList + list(required)
783 def get_pre_packages(ks, required=()):
784 return ks.handler.prepackages.packageList + list(required)
786 def get_packages(ks, required=()):
787 return ks.handler.packages.packageList + list(required)
789 def get_groups(ks, required=()):
790 return ks.handler.packages.groupList + list(required)
792 def get_excluded(ks, required=()):
793 return ks.handler.packages.excludedList + list(required)
795 def get_partitions(ks):
796 return ks.handler.partition.partitions
798 def ignore_missing(ks):
799 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
801 def exclude_docs(ks):
802 return ks.handler.packages.excludeDocs
805 if hasattr(ks.handler.packages, "instLange"):
806 return ks.handler.packages.instLange
807 elif hasattr(ks.handler.packages, "instLangs"):
808 return ks.handler.packages.instLangs
811 def get_post_scripts(ks):
813 for s in ks.handler.scripts:
814 if s.type != ksparser.KS_SCRIPT_POST:
819 def add_repo(ks, repostr):
820 args = repostr.split()
821 repoobj = ks.handler.repo.parse(args[1:])
822 if repoobj and repoobj not in ks.handler.repo.repoList:
823 ks.handler.repo.repoList.append(repoobj)
825 def remove_all_repos(ks):
826 while len(ks.handler.repo.repoList) != 0:
827 del ks.handler.repo.repoList[0]
829 def remove_duplicate_repos(ks):
833 if len(ks.handler.repo.repoList) < 2:
835 if i >= len(ks.handler.repo.repoList) - 1:
837 name = ks.handler.repo.repoList[i].name
838 baseurl = ks.handler.repo.repoList[i].baseurl
839 if j < len(ks.handler.repo.repoList):
840 if (ks.handler.repo.repoList[j].name == name or \
841 ks.handler.repo.repoList[j].baseurl == baseurl):
842 del ks.handler.repo.repoList[j]
845 if j >= len(ks.handler.repo.repoList):
852 def resolve_groups(creatoropts, repometadata):
854 if 'zypp' == creatoropts['pkgmgr']:
856 ks = creatoropts['ks']
858 for repo in repometadata:
859 """ Mustn't replace group with package list if repo is ready for the
860 corresponding package manager.
863 if iszypp and repo["patterns"]:
865 if not iszypp and repo["comps"]:
868 # But we also must handle such cases, use zypp but repo only has comps,
869 # use yum but repo only has patterns, use zypp but use_comps is true,
870 # use yum but use_comps is false.
872 if iszypp and repo["comps"]:
873 groupfile = repo["comps"]
874 get_pkglist_handler = misc.get_pkglist_in_comps
875 if not iszypp and repo["patterns"]:
876 groupfile = repo["patterns"]
877 get_pkglist_handler = misc.get_pkglist_in_patterns
882 if i >= len(ks.handler.packages.groupList):
884 pkglist = get_pkglist_handler(
885 ks.handler.packages.groupList[i].name,
888 del ks.handler.packages.groupList[i]
890 if pkg not in ks.handler.packages.packageList:
891 ks.handler.packages.packageList.append(pkg)