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 #cp ks lang setting to other file, then can access the file in %post section
171 fs.makedirs(self.path("/etc/config"))
172 f = open(self.path("/etc/config/mic_language"), "w+")
173 f.write("LANG=\"" + kslang.lang + "\"\n")
176 class KeyboardConfig(KickstartConfig):
177 """A class to apply a kickstart keyboard configuration to a system."""
179 def apply(self, kskeyboard):
182 # should this impact the X keyboard config too?
183 # or do we want to make X be able to do this mapping?
185 #k = rhpl.keyboard.Keyboard()
186 #if kskeyboard.keyboard:
187 # k.set(kskeyboard.keyboard)
188 #k.write(self.instroot)
191 class TimezoneConfig(KickstartConfig):
192 """A class to apply a kickstart timezone configuration to a system."""
194 def apply(self, kstimezone):
195 self._check_sysconfig()
196 tz = kstimezone.timezone or "America/New_York"
197 utc = str(kstimezone.isUtc)
199 f = open(self.path("/etc/sysconfig/clock"), "w+")
200 f.write("ZONE=\"" + tz + "\"\n")
201 f.write("UTC=" + utc + "\n")
203 tz_source = "/usr/share/zoneinfo/%s" % (tz)
204 tz_dest = "/etc/localtime"
206 lncmd = fs.find_binary_inchroot('ln', self.instroot)
208 self.call([lncmd, "-s", tz_source, tz_dest])
210 lncmd = fs.find_binary_path('ln')
211 subprocess.call([lncmd, "-s",
212 self.path(tz_source),
214 except (IOError, OSError), (errno, msg):
215 raise errors.KsError("Timezone setting error: %s" % msg)
217 class AuthConfig(KickstartConfig):
218 """A class to apply a kickstart authconfig configuration to a system."""
220 def apply(self, ksauthconfig):
221 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
222 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
223 self.call(args + auth.split())
225 class FirewallConfig(KickstartConfig):
226 """A class to apply a kickstart firewall configuration to a system."""
228 def apply(self, ksfirewall):
230 # FIXME: should handle the rest of the options
232 if not os.path.exists(self.path("/usr/sbin/lokkit")):
234 if ksfirewall.enabled:
237 status = "--disabled"
239 self.call(["/usr/sbin/lokkit",
240 "-f", "--quiet", "--nostart", status])
242 class RootPasswordConfig(KickstartConfig):
243 """A class to apply a kickstart root password configuration to a system."""
245 self.call(["/usr/bin/passwd", "-d", "root"])
247 def set_encrypted(self, password):
248 self.call(["/usr/sbin/usermod", "-p", password, "root"])
250 def set_unencrypted(self, password):
251 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
252 if not os.path.exists("%s/%s" %(self.instroot, p)):
253 raise errors.KsError("Unable to set unencrypted password due "
256 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
257 stdout = subprocess.PIPE,
258 preexec_fn = self.chroot)
259 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
261 stdout = subprocess.PIPE,
262 preexec_fn = self.chroot)
266 def apply(self, ksrootpw):
267 if ksrootpw.isCrypted:
268 self.set_encrypted(ksrootpw.password)
269 elif ksrootpw.password != "":
270 self.set_unencrypted(ksrootpw.password)
274 class UserConfig(KickstartConfig):
275 def set_empty_passwd(self, user):
276 self.call(["/usr/bin/passwd", "-d", user])
278 def set_encrypted_passwd(self, user, password):
279 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
281 def set_unencrypted_passwd(self, user, password):
282 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
283 if not os.path.exists("%s/%s" %(self.instroot, p)):
284 raise errors.KsError("Unable to set unencrypted password due "
287 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
288 stdout = subprocess.PIPE,
289 preexec_fn = self.chroot)
290 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
292 stdout = subprocess.PIPE,
293 preexec_fn = self.chroot)
296 def addUser(self, userconfig):
297 args = [ "/usr/sbin/useradd" ]
298 if userconfig.groups:
299 args += [ "--groups", string.join(userconfig.groups, ",") ]
302 args += [ "-d", "/home/%s" % userconfig.name ]
303 args.append(userconfig.name)
305 dev_null = os.open("/dev/null", os.O_WRONLY)
306 msger.debug('adding user with %s' % args)
307 subprocess.call(args,
310 preexec_fn = self.chroot)
313 msger.warning('Cannot add user using "useradd"')
315 if userconfig.password not in (None, ""):
316 if userconfig.isCrypted:
317 self.set_encrypted_passwd(userconfig.name,
320 self.set_unencrypted_passwd(userconfig.name,
323 self.set_empty_passwd(userconfig.name)
325 raise errors.KsError("Invalid kickstart command: %s" \
326 % userconfig.__str__())
329 def apply(self, user):
330 for userconfig in user.userList:
331 self.addUser(userconfig)
333 class ServicesConfig(KickstartConfig):
334 """A class to apply a kickstart services configuration to a system."""
336 def apply(self, ksservices):
337 if not os.path.exists(self.path("/sbin/chkconfig")):
339 for s in ksservices.enabled:
340 self.call(["/sbin/chkconfig", s, "on"])
341 for s in ksservices.disabled:
342 self.call(["/sbin/chkconfig", s, "off"])
344 class XConfig(KickstartConfig):
345 """A class to apply a kickstart X configuration to a system."""
347 def apply(self, ksxconfig):
348 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
349 f = open(self.path("/etc/inittab"), "rw+")
351 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
355 if ksxconfig.defaultdesktop:
356 self._check_sysconfig()
357 f = open(self.path("/etc/sysconfig/desktop"), "w")
358 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
361 class DesktopConfig(KickstartConfig):
362 """A class to apply a kickstart desktop configuration to a system."""
364 def apply(self, ksdesktop):
365 if ksdesktop.defaultdesktop:
366 self._check_sysconfig()
367 f = open(self.path("/etc/sysconfig/desktop"), "w")
368 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
370 if os.path.exists(self.path("/etc/gdm/custom.conf")):
371 f = open(self.path("/etc/skel/.dmrc"), "w")
372 f.write("[Desktop]\n")
373 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
375 if ksdesktop.session:
376 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
377 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
378 f.write("session="+ksdesktop.session.lower()+"\n")
380 if ksdesktop.autologinuser:
381 self._check_sysconfig()
382 f = open(self.path("/etc/sysconfig/desktop"), "a+")
383 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
385 if os.path.exists(self.path("/etc/gdm/custom.conf")):
386 f = open(self.path("/etc/gdm/custom.conf"), "w")
387 f.write("[daemon]\n")
388 f.write("AutomaticLoginEnable=true\n")
389 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
392 class MoblinRepoConfig(KickstartConfig):
393 """A class to apply a kickstart desktop configuration to a system."""
394 def __create_repo_section(self, repo, type, fd):
397 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
398 reponame = repo.name + reposuffix[type]
401 baseurl = repo.baseurl
403 mirrorlist = repo.mirrorlist
405 elif type == "debuginfo":
407 if repo.baseurl.endswith("/"):
408 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
410 baseurl = os.path.dirname(repo.baseurl)
414 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
415 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
416 mirrorlist += "debug" + "-" + variant
418 elif type == "source":
420 if repo.baseurl.endswith("/"):
421 baseurl = os.path.dirname(
423 os.path.dirname(repo.baseurl)))
425 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
429 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
430 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
431 mirrorlist += "source" + "-" + variant
433 fd.write("[" + reponame + "]\n")
434 fd.write("name=" + reponame + "\n")
435 fd.write("failovermethod=priority\n")
437 auth_url = re.compile(AUTH_URL_PTN)
438 m = auth_url.match(baseurl)
440 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
441 fd.write("baseurl=" + baseurl + "\n")
443 fd.write("mirrorlist=" + mirrorlist + "\n")
444 """ Skip saving proxy settings """
446 # fd.write("proxy=" + repo.proxy + "\n")
447 #if repo.proxy_username:
448 # fd.write("proxy_username=" + repo.proxy_username + "\n")
449 #if repo.proxy_password:
450 # fd.write("proxy_password=" + repo.proxy_password + "\n")
452 fd.write("gpgkey=" + repo.gpgkey + "\n")
453 fd.write("gpgcheck=1\n")
455 fd.write("gpgcheck=0\n")
456 if type == "source" or type == "debuginfo" or repo.disable:
457 fd.write("enabled=0\n")
459 fd.write("enabled=1\n")
462 def __create_repo_file(self, repo, repodir):
463 fs.makedirs(self.path(repodir))
464 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
465 self.__create_repo_section(repo, "base", f)
467 self.__create_repo_section(repo, "debuginfo", f)
469 self.__create_repo_section(repo, "source", f)
473 def apply(self, ksrepo, repodata, repourl):
474 for repo in ksrepo.repoList:
475 if repo.name in repourl:
476 repo.baseurl = repourl[repo.name]
478 #self.__create_repo_file(repo, "/etc/yum.repos.d")
479 self.__create_repo_file(repo, "/etc/zypp/repos.d")
480 """ Import repo gpg keys """
482 for repo in repodata:
485 "--root=%s" % self.instroot,
489 class RPMMacroConfig(KickstartConfig):
490 """A class to apply the specified rpm macros to the filesystem"""
495 if not os.path.exists(self.path("/etc/rpm")):
496 os.mkdir(self.path("/etc/rpm"))
497 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
499 f.write("%_excludedocs 1\n")
500 f.write("%__file_context_path %{nil}\n")
501 if inst_langs(ks) != None:
502 f.write("%_install_langs ")
503 f.write(inst_langs(ks))
507 class NetworkConfig(KickstartConfig):
508 """A class to apply a kickstart network configuration to a system."""
509 def write_ifcfg(self, network):
510 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
515 f.write("DEVICE=%s\n" % network.device)
516 f.write("BOOTPROTO=%s\n" % network.bootProto)
518 if network.bootProto.lower() == "static":
520 f.write("IPADDR=%s\n" % network.ip)
522 f.write("NETMASK=%s\n" % network.netmask)
525 f.write("ONBOOT=on\n")
527 f.write("ONBOOT=off\n")
530 f.write("ESSID=%s\n" % network.essid)
533 if network.ethtool.find("autoneg") == -1:
534 network.ethtool = "autoneg off " + network.ethtool
535 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
537 if network.bootProto.lower() == "dhcp":
539 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
540 if network.dhcpclass:
541 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
544 f.write("MTU=%s\n" % network.mtu)
548 def write_wepkey(self, network):
549 if not network.wepkey:
552 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
555 f.write("KEY=%s\n" % network.wepkey)
558 def write_sysconfig(self, useipv6, hostname, gateway):
559 path = self.path("/etc/sysconfig/network")
563 f.write("NETWORKING=yes\n")
566 f.write("NETWORKING_IPV6=yes\n")
568 f.write("NETWORKING_IPV6=no\n")
571 f.write("HOSTNAME=%s\n" % hostname)
573 f.write("HOSTNAME=localhost.localdomain\n")
576 f.write("GATEWAY=%s\n" % gateway)
580 def write_hosts(self, hostname):
582 if hostname and hostname != "localhost.localdomain":
583 localline += hostname + " "
584 l = hostname.split(".")
586 localline += l[0] + " "
587 localline += "localhost.localdomain localhost"
589 path = self.path("/etc/hosts")
592 f.write("127.0.0.1\t\t%s\n" % localline)
593 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
596 def write_resolv(self, nodns, nameservers):
597 if nodns or not nameservers:
600 path = self.path("/etc/resolv.conf")
604 for ns in (nameservers):
606 f.write("nameserver %s\n" % ns)
611 def apply(self, ksnet):
612 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
620 for network in ksnet.network:
621 if not network.device:
622 raise errors.KsError("No --device specified with "
623 "network kickstart command")
625 if (network.onboot and network.bootProto.lower() != "dhcp" and
626 not (network.ip and network.netmask)):
627 raise errors.KsError("No IP address and/or netmask "
628 "specified with static "
629 "configuration for '%s'" %
632 self.write_ifcfg(network)
633 self.write_wepkey(network)
641 hostname = network.hostname
643 gateway = network.gateway
645 if network.nameserver:
646 nameservers = network.nameserver.split(",")
648 self.write_sysconfig(useipv6, hostname, gateway)
649 self.write_hosts(hostname)
650 self.write_resolv(nodns, nameservers)
652 def use_installerfw(ks, feature):
653 """ Check if the installer framework has to be used for a feature
656 features = ks.handler.installerfw.features
658 if feature in features or "all" in features:
662 def get_image_size(ks, default = None):
664 for p in ks.handler.partition.partitions:
665 if p.mountpoint == "/" and p.size:
668 return int(__size) * 1024L * 1024L
672 def get_image_fstype(ks, default = None):
673 for p in ks.handler.partition.partitions:
674 if p.mountpoint == "/" and p.fstype:
678 def get_image_fsopts(ks, default = None):
679 for p in ks.handler.partition.partitions:
680 if p.mountpoint == "/" and p.fsopts:
686 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
687 devices.append(ks.handler.device)
689 devices.extend(ks.handler.device.deviceList)
692 for device in devices:
693 if not device.moduleName:
695 modules.extend(device.moduleName.split(":"))
699 def get_timeout(ks, default = None):
700 if not hasattr(ks.handler.bootloader, "timeout"):
702 if ks.handler.bootloader.timeout is None:
704 return int(ks.handler.bootloader.timeout)
706 def get_kernel_args(ks, default = "ro rd.live.image"):
707 if not hasattr(ks.handler.bootloader, "appendLine"):
709 if ks.handler.bootloader.appendLine is None:
711 return "%s %s" %(default, ks.handler.bootloader.appendLine)
713 def get_menu_args(ks, default = ""):
714 if not hasattr(ks.handler.bootloader, "menus"):
716 if ks.handler.bootloader.menus in (None, ""):
718 return "%s" % ks.handler.bootloader.menus
720 def get_default_kernel(ks, default = None):
721 if not hasattr(ks.handler.bootloader, "default"):
723 if not ks.handler.bootloader.default:
725 return ks.handler.bootloader.default
727 RepoType = collections.namedtuple("Repo",
728 "name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy, \
729 proxy_username, proxy_password, debuginfo, \
730 source, gpgkey, disable, ssl_verify, nocache, \
733 def Repo(name, baseurl, mirrorlist=None, includepkgs=[], excludepkgs=[], proxy=None,
734 proxy_username=None, proxy_password=None, debuginfo=None,
735 source=None, gpgkey=None, disable=None, ssl_verify=None,
736 nocache=False, cost=None, priority=None):
737 return RepoType(name, baseurl, mirrorlist, includepkgs, excludepkgs, proxy,
738 proxy_username, proxy_password, debuginfo,
739 source, gpgkey, disable, ssl_verify, nocache,
743 def get_repos(ks, repo_urls=None, ignore_ksrepo=False):
745 for repodata in ks.handler.repo.repoList:
747 for field in RepoType._fields:
748 if hasattr(repodata, field) and getattr(repodata, field):
749 repo[field] = getattr(repodata, field)
751 if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'):
752 repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'),
753 getattr(repodata, 'user', None),
754 getattr(repodata, 'passwd', None))
757 repos[repo['name']] = Repo(**repo)
762 for name, repo in repo_urls.items():
763 if 'baseurl' in repo:
764 repo['baseurl'] = SafeURL(repo.get('baseurl'),
765 repo.get('user', None),
766 repo.get('passwd', None))
767 repos[name] = Repo(**repo)
769 return repos.values()
771 def convert_method_to_repo(ks):
773 ks.handler.repo.methodToRepo()
774 except (AttributeError, kserrors.KickstartError):
777 def get_attachment(ks, required=()):
778 return ks.handler.attachment.packageList + list(required)
780 def get_pre_packages(ks, required=()):
781 return ks.handler.prepackages.packageList + list(required)
783 def get_packages(ks, required=()):
784 return ks.handler.packages.packageList + list(required)
786 def get_groups(ks, required=()):
787 return ks.handler.packages.groupList + list(required)
789 def get_excluded(ks, required=()):
790 return ks.handler.packages.excludedList + list(required)
792 def get_partitions(ks):
793 return ks.handler.partition.partitions
795 def ignore_missing(ks):
796 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
798 def exclude_docs(ks):
799 return ks.handler.packages.excludeDocs
802 if hasattr(ks.handler.packages, "instLange"):
803 return ks.handler.packages.instLange
804 elif hasattr(ks.handler.packages, "instLangs"):
805 return ks.handler.packages.instLangs
808 def get_post_scripts(ks):
810 for s in ks.handler.scripts:
811 if s.type != ksparser.KS_SCRIPT_POST:
816 def get_sign_scripts(ks):
818 for s in ks.handler.scripts:
819 if s.type != ksparser.KS_SCRIPT_RUN:
823 def add_repo(ks, repostr):
824 args = repostr.split()
825 repoobj = ks.handler.repo.parse(args[1:])
826 if repoobj and repoobj not in ks.handler.repo.repoList:
827 ks.handler.repo.repoList.append(repoobj)
829 def remove_all_repos(ks):
830 while len(ks.handler.repo.repoList) != 0:
831 del ks.handler.repo.repoList[0]
833 def remove_duplicate_repos(ks):
837 if len(ks.handler.repo.repoList) < 2:
839 if i >= len(ks.handler.repo.repoList) - 1:
841 name = ks.handler.repo.repoList[i].name
842 baseurl = ks.handler.repo.repoList[i].baseurl
843 if j < len(ks.handler.repo.repoList):
844 if (ks.handler.repo.repoList[j].name == name or \
845 ks.handler.repo.repoList[j].baseurl == baseurl):
846 del ks.handler.repo.repoList[j]
849 if j >= len(ks.handler.repo.repoList):
856 def resolve_groups(creatoropts, repometadata):
858 if 'zypp' == creatoropts['pkgmgr']:
860 ks = creatoropts['ks']
862 for repo in repometadata:
863 """ Mustn't replace group with package list if repo is ready for the
864 corresponding package manager.
867 if iszypp and repo["patterns"]:
869 if not iszypp and repo["comps"]:
872 # But we also must handle such cases, use zypp but repo only has comps,
873 # use yum but repo only has patterns, use zypp but use_comps is true,
874 # use yum but use_comps is false.
876 if iszypp and repo["comps"]:
877 groupfile = repo["comps"]
878 get_pkglist_handler = misc.get_pkglist_in_comps
879 if not iszypp and repo["patterns"]:
880 groupfile = repo["patterns"]
881 get_pkglist_handler = misc.get_pkglist_in_patterns
886 if i >= len(ks.handler.packages.groupList):
888 pkglist = get_pkglist_handler(
889 ks.handler.packages.groupList[i].name,
892 del ks.handler.packages.groupList[i]
894 if pkg not in ks.handler.packages.packageList:
895 ks.handler.packages.packageList.append(pkg)