fix extracting boot parameters from isolinux.cfg
[livecd.git] / imgcreate / live.py
blobf98f76cf9536cb5e4fa978675b5aa2cc6ed831be
2 # live.py : LiveImageCreator class for creating Live CD images
4 # Copyright 2007, Red Hat Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Library General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 import os
20 import os.path
21 import glob
22 import shutil
23 import subprocess
24 import logging
26 from imgcreate.errors import *
27 from imgcreate.fs import *
28 from imgcreate.creator import *
30 class LiveImageCreatorBase(LoopImageCreator):
31 """A base class for LiveCD image creators.
33 This class serves as a base class for the architecture-specific LiveCD
34 image creator subclass, LiveImageCreator.
36 LiveImageCreator creates a bootable ISO containing the system image,
37 bootloader, bootloader configuration, kernel and initramfs.
39 """
41 def __init__(self, *args):
42 """Initialise a LiveImageCreator instance.
44 This method takes the same arguments as ImageCreator.__init__().
46 """
47 LoopImageCreator.__init__(self, *args)
49 self.skip_compression = False
50 """Controls whether to use squashfs to compress the image."""
52 self.skip_minimize = False
53 """Controls whether an image minimizing snapshot should be created.
55 This snapshot can be used when copying the system image from the ISO in
56 order to minimize the amount of data that needs to be copied; simply,
57 it makes it possible to create a version of the image's filesystem with
58 no spare space.
60 """
62 self._timeout = kickstart.get_timeout(self.ks, 10)
63 """The bootloader timeout from kickstart."""
65 self._default_kernel = kickstart.get_default_kernel(self.ks, "kernel")
66 """The default kernel type from kickstart."""
68 self.__isodir = None
70 self.__modules = ["=ata", "sym53c8xx", "aic7xxx", "=usb", "=firewire", "=mmc", "=pcmcia", "mptsas"]
71 self.__modules.extend(kickstart.get_modules(self.ks))
74 # Hooks for subclasses
76 def _configure_bootloader(self, isodir):
77 """Create the architecture specific booloader configuration.
79 This is the hook where subclasses must create the booloader
80 configuration in order to allow a bootable ISO to be built.
82 isodir -- the directory where the contents of the ISO are to be staged
84 """
85 raise CreatorError("Bootloader configuration is arch-specific, "
86 "but not implemented for this arch!")
88 def _get_kernel_options(self):
89 """Return a kernel options string for bootloader configuration.
91 This is the hook where subclasses may specify a set of kernel options
92 which should be included in the images bootloader configuration.
94 A sensible default implementation is provided.
96 """
97 r = kickstart.get_kernel_args(self.ks)
98 if os.path.exists(self._instroot + "/usr/bin/rhgb"):
99 r += " rhgb"
100 if os.path.exists(self._instroot + "/usr/bin/plymouth"):
101 r += " rhgb"
102 return r
104 def _get_mkisofs_options(self, isodir):
105 """Return the architecture specific mkisosfs options.
107 This is the hook where subclasses may specify additional arguments to
108 mkisofs, e.g. to enable a bootable ISO to be built.
110 By default, an empty list is returned.
113 return []
116 # Helpers for subclasses
118 def _has_checkisomd5(self):
119 """Check whether checkisomd5 is available in the install root."""
120 def exists(instroot, path):
121 return os.path.exists(instroot + path)
123 if (exists(self._instroot, "/usr/lib/anaconda-runtime/checkisomd5") or
124 exists(self._instroot, "/usr/bin/checkisomd5")):
125 return True
127 return False
130 # Actual implementation
132 def _base_on(self, base_on):
133 """helper function to extract ext3 file system from a live CD ISO"""
134 isoloop = Mount(LoopbackDisk(base_on), self._mkdtemp())
136 try:
137 isoloop.mount()
138 except MountError, e:
139 raise CreatorError("Failed to loopback mount '%s' : %s" %
140 (base_on, e))
142 # legacy LiveOS filesystem layout support, remove for F9 or F10
143 if os.path.exists(isoloop.mountdir + "/squashfs.img"):
144 squashimg = isoloop.mountdir + "/squashfs.img"
145 else:
146 squashimg = isoloop.mountdir + "/LiveOS/squashfs.img"
148 squashloop = Mount(LoopbackDisk(squashimg), self._mkdtemp(), "squashfs")
150 try:
151 if not squashloop.disk.exists():
152 raise CreatorError("'%s' is not a valid live CD ISO : "
153 "squashfs.img doesn't exist" % base_on)
155 try:
156 squashloop.mount()
157 except MountError, e:
158 raise CreatorError("Failed to loopback mount squashfs.img "
159 "from '%s' : %s" % (base_on, e))
161 # legacy LiveOS filesystem layout support, remove for F9 or F10
162 if os.path.exists(squashloop.mountdir + "/os.img"):
163 os_image = squashloop.mountdir + "/os.img"
164 else:
165 os_image = squashloop.mountdir + "/LiveOS/ext3fs.img"
167 if not os.path.exists(os_image):
168 raise CreatorError("'%s' is not a valid live CD ISO : neither "
169 "LiveOS/ext3fs.img nor os.img exist" %
170 base_on)
172 shutil.copyfile(os_image, self._image)
173 finally:
174 squashloop.cleanup()
175 isoloop.cleanup()
177 def _mount_instroot(self, base_on = None):
178 LoopImageCreator._mount_instroot(self, base_on)
179 self.__write_initrd_conf(self._instroot + "/etc/sysconfig/mkinitrd")
181 def _unmount_instroot(self):
182 try:
183 os.unlink(self._instroot + "/etc/sysconfig/mkinitrd")
184 except:
185 pass
186 LoopImageCreator._unmount_instroot(self)
188 def __ensure_isodir(self):
189 if self.__isodir is None:
190 self.__isodir = self._mkdtemp("iso-")
191 return self.__isodir
193 def _create_bootconfig(self):
194 """Configure the image so that it's bootable."""
195 self._configure_bootloader(self.__ensure_isodir())
197 def _get_post_scripts_env(self, in_chroot):
198 env = LoopImageCreator._get_post_scripts_env(self, in_chroot)
200 if not in_chroot:
201 env["LIVE_ROOT"] = self.__ensure_isodir()
203 return env
205 def __write_initrd_conf(self, path):
206 if not os.path.exists(os.path.dirname(path)):
207 makedirs(os.path.dirname(path))
208 f = open(path, "a")
210 f.write('LIVEOS="yes"\n')
211 f.write('PROBE="no"\n')
212 f.write('MODULES+="squashfs ext3 ext2 vfat msdos "\n')
213 f.write('MODULES+="sr_mod sd_mod ide-cd cdrom "\n')
215 for module in self.__modules:
216 if module == "=usb":
217 f.write('MODULES+="ehci_hcd uhci_hcd ohci_hcd "\n')
218 f.write('MODULES+="usb_storage usbhid "\n')
219 elif module == "=firewire":
220 f.write('MODULES+="firewire-sbp2 firewire-ohci "\n')
221 f.write('MODULES+="sbp2 ohci1394 ieee1394 "\n')
222 elif module == "=mmc":
223 f.write('MODULES+="mmc_block sdhci "\n')
224 elif module == "=pcmcia":
225 f.write('MODULES+="pata_pcmcia "\n')
226 else:
227 f.write('MODULES+="' + module + ' "\n')
229 f.close()
231 def __create_iso(self, isodir):
232 iso = self._outdir + "/" + self.name + ".iso"
234 args = ["/usr/bin/mkisofs",
235 "-J", "-r",
236 "-hide-rr-moved", "-hide-joliet-trans-tbl",
237 "-V", self.fslabel,
238 "-o", iso]
240 args.extend(self._get_mkisofs_options(isodir))
242 args.append(isodir)
244 if subprocess.call(args) != 0:
245 raise CreatorError("ISO creation failed!")
247 self.__implant_md5sum(iso)
249 def __implant_md5sum(self, iso):
250 """Implant an isomd5sum."""
251 if os.path.exists("/usr/bin/implantisomd5"):
252 implantisomd5 = "/usr/bin/implantisomd5"
253 elif os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"):
254 implantisomd5 = "/usr/lib/anaconda-runtime/implantisomd5"
255 else:
256 logging.warn("isomd5sum not installed; not setting up mediacheck")
258 subprocess.call([implantisomd5, iso])
260 def _stage_final_image(self):
261 try:
262 makedirs(self.__ensure_isodir() + "/LiveOS")
264 minimal_size = self._resparse()
266 if not self.skip_minimize:
267 create_image_minimizer(self.__isodir + "/LiveOS/osmin.img",
268 self._image, minimal_size)
270 if self.skip_compression:
271 shutil.move(self._image, self.__isodir + "/LiveOS/ext3fs.img")
272 else:
273 makedirs(os.path.join(os.path.dirname(self._image), "LiveOS"))
274 shutil.move(self._image,
275 os.path.join(os.path.dirname(self._image),
276 "LiveOS", "ext3fs.img"))
277 mksquashfs(os.path.dirname(self._image),
278 self.__isodir + "/LiveOS/squashfs.img")
280 self.__create_iso(self.__isodir)
281 finally:
282 shutil.rmtree(self.__isodir, ignore_errors = True)
283 self.__isodir = None
285 class x86LiveImageCreator(LiveImageCreatorBase):
286 """ImageCreator for x86 machines"""
287 def _get_mkisofs_options(self, isodir):
288 return [ "-b", "isolinux/isolinux.bin",
289 "-c", "isolinux/boot.cat",
290 "-no-emul-boot", "-boot-info-table",
291 "-boot-load-size", "4" ]
293 def _get_required_packages(self):
294 return ["syslinux"] + LiveImageCreatorBase._get_required_packages(self)
296 def _get_isolinux_stanzas(self, isodir):
297 return ""
299 def __find_syslinux_menu(self):
300 for menu in ["vesamenu.c32", "menu.c32"]:
301 if os.path.isfile(self._instroot + "/usr/lib/syslinux/" + menu):
302 return menu
304 raise CreatorError("syslinux not installed : "
305 "no suitable /usr/lib/syslinux/*menu.c32 found")
307 def __find_syslinux_mboot(self):
309 # We only need the mboot module if we have any xen hypervisors
311 if not glob.glob(self._instroot + "/boot/xen.gz*"):
312 return None
314 return "mboot.c32"
316 def __copy_syslinux_files(self, isodir, menu, mboot = None):
317 files = ["isolinux.bin", menu]
318 if mboot:
319 files += mboot
321 for f in files:
322 path = self._instroot + "/usr/lib/syslinux/" + f
324 if not os.path.isfile(path):
325 raise CreatorError("syslinux not installed : "
326 "%s not found" % path)
328 shutil.copy(path, isodir + "/isolinux/")
330 def __copy_syslinux_background(self, isodest):
331 background_path = self._instroot + \
332 "/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg"
334 if not os.path.exists(background_path):
335 return False
337 shutil.copyfile(background_path, isodest)
339 return True
341 def __copy_kernel_and_initramfs(self, isodir, version, index):
342 bootdir = self._instroot + "/boot"
344 shutil.copyfile(bootdir + "/vmlinuz-" + version,
345 isodir + "/isolinux/vmlinuz" + index)
347 shutil.copyfile(bootdir + "/initrd-" + version + ".img",
348 isodir + "/isolinux/initrd" + index + ".img")
350 is_xen = False
351 if os.path.exists(bootdir + "/boot/xen.gz-" + version[:-3]):
352 shutil.copyfile(bootdir + "/boot/xen.gz-" + version[:-3],
353 isodir + "/isolinux/xen" + index + ".gz")
354 is_xen = True
356 return is_xen
358 def __is_default_kernel(self, kernel, kernels):
359 if len(kernels) == 1:
360 return True
362 if kernel == self._default_kernel:
363 return True
365 if kernel.startswith("kernel-") and kernel[7:] == self._default_kernel:
366 return True
368 return False
370 def __get_basic_syslinux_config(self, **args):
371 return """
372 default %(menu)s
373 timeout %(timeout)d
375 %(background)s
376 menu title Welcome to %(name)s!
377 menu color border 0 #ffffffff #00000000
378 menu color sel 7 #ffffffff #ff000000
379 menu color title 0 #ffffffff #00000000
380 menu color tabmsg 0 #ffffffff #00000000
381 menu color unsel 0 #ffffffff #00000000
382 menu color hotsel 0 #ff000000 #ffffffff
383 menu color hotkey 7 #ffffffff #ff000000
384 menu color timeout_msg 0 #ffffffff #00000000
385 menu color timeout 0 #ffffffff #00000000
386 menu color cmdline 0 #ffffffff #00000000
387 menu hidden
388 menu hiddenrow 5
389 """ % args
391 def __get_image_stanza(self, is_xen, **args):
392 if not is_xen:
393 template = """label %(short)s
394 menu label %(long)s
395 kernel vmlinuz%(index)s
396 append initrd=initrd%(index)s.img root=CDLABEL=%(fslabel)s rootfstype=iso9660 %(liveargs)s %(extra)s
398 else:
399 template = """label %(short)s
400 menu label %(long)s
401 kernel mboot.c32
402 append xen%(index)s.gz --- vmlinuz%(index)s --- initrd%(index)s.img root=CDLABEL=%(fslabel)s rootfstype=iso9660 %(liveargs)s %(extra)s
404 return template % args
406 def __get_image_stanzas(self, isodir):
407 versions = []
408 kernels = self._get_kernel_versions()
409 for kernel in kernels:
410 for version in kernels[kernel]:
411 versions.append(version)
413 kernel_options = self._get_kernel_options()
415 checkisomd5 = self._has_checkisomd5()
417 cfg = ""
419 index = "0"
420 for version in versions:
421 is_xen = self.__copy_kernel_and_initramfs(isodir, version, index)
423 default = self.__is_default_kernel(kernel, kernels)
425 if default:
426 long = "Boot"
427 elif kernel.startswith("kernel-"):
428 long = "Boot %s(%s)" % (self.name, kernel[7:])
429 else:
430 long = "Boot %s(%s)" % (self.name, kernel)
432 cfg += self.__get_image_stanza(is_xen,
433 fslabel = self.fslabel,
434 liveargs = kernel_options,
435 long = long,
436 short = "linux" + index,
437 extra = "",
438 index = index)
440 if default:
441 cfg += "menu default\n"
443 if checkisomd5:
444 cfg += self.__get_image_stanza(is_xen,
445 fslabel = self.fslabel,
446 liveargs = kernel_options,
447 long = "Verify and " + long,
448 short = "check" + index,
449 extra = "check",
450 index = index)
452 index = str(int(index) + 1)
454 return cfg
456 def __get_memtest_stanza(self, isodir):
457 memtest = glob.glob(self._instroot + "/boot/memtest86*")
458 if not memtest:
459 return ""
461 shutil.copyfile(memtest[0], isodir + "/isolinux/memtest")
463 return """label memtest
464 menu label Memory Test
465 kernel memtest
468 def __get_local_stanza(self, isodir):
469 return """label local
470 menu label Boot from local drive
471 localboot 0xffff
474 def _configure_syslinux_bootloader(self, isodir):
475 """configure the boot loader"""
476 makedirs(isodir + "/isolinux")
478 menu = self.__find_syslinux_menu()
480 self.__copy_syslinux_files(isodir, menu,
481 self.__find_syslinux_mboot())
483 background = ""
484 if self.__copy_syslinux_background(isodir + "/isolinux/splash.jpg"):
485 background = "menu background splash.jpg"
487 cfg = self.__get_basic_syslinux_config(menu = menu,
488 background = background,
489 name = self.name,
490 timeout = self._timeout * 10)
492 cfg += self.__get_image_stanzas(isodir)
493 cfg += self.__get_memtest_stanza(isodir)
494 cfg += self.__get_local_stanza(isodir)
495 cfg += self._get_isolinux_stanzas(isodir)
497 cfgf = open(isodir + "/isolinux/isolinux.cfg", "w")
498 cfgf.write(cfg)
499 cfgf.close()
501 def __copy_efi_files(self, isodir):
502 if not os.path.exists(self._instroot + "/boot/efi/EFI/redhat/grub.efi"):
503 return False
504 shutil.copy(self._instroot + "/boot/efi/EFI/redhat/grub.efi",
505 isodir + "/EFI/boot/grub.efi")
506 shutil.copy(self._instroot + "/boot/grub/splash.xpm.gz",
507 isodir + "/EFI/boot/splash.xpm.gz")
509 return True
511 def __get_basic_efi_config(self, **args):
512 return """
513 default=0
514 splashimage=/EFI/boot/splash.xpm.gz
515 timeout %(timeout)d
516 hiddenmenu
518 """ %args
520 def __get_efi_image_stanza(self, **args):
521 return """title %(long)s
522 kernel /EFI/boot/vmlinuz%(index)s root=CDLABEL=%(fslabel)s rootfstype=iso9660 %(liveargs)s %(extra)s
523 initrd /EFI/boot/initrd%(index)s.img
524 """ %args
526 def __get_efi_image_stanzas(self, isodir, name):
527 # FIXME: this only supports one kernel right now...
529 kernel_options = self._get_kernel_options()
530 checkisomd5 = self._has_checkisomd5()
532 cfg = ""
534 for index in range(0, 9):
535 # we don't support xen kernels
536 if os.path.exists("%s/EFI/boot/xen%d.gz" %(isodir, index)):
537 continue
538 cfg += self.__get_efi_image_stanza(fslabel = self.fslabel,
539 liveargs = kernel_options,
540 long = name,
541 extra = "", index = index)
542 if checkisomd5:
543 cfg += self.__get_efi_image_stanza(fslabel = self.fslabel,
544 liveargs = kernel_options,
545 long = "Verify and Boot " + name,
546 extra = "check",
547 index = index)
548 break
550 return cfg
552 def _configure_efi_bootloader(self, isodir):
553 """Set up the configuration for an EFI bootloader"""
554 makedirs(isodir + "/EFI/boot")
556 if not self.__copy_efi_files(isodir):
557 shutil.rmtree(isodir + "/EFI")
558 return
560 for f in os.listdir(isodir + "/isolinux"):
561 os.link("%s/isolinux/%s" %(isodir, f),
562 "%s/EFI/boot/%s" %(isodir, f))
565 cfg = self.__get_basic_efi_config(name = self.name,
566 timeout = self._timeout)
567 cfg += self.__get_efi_image_stanzas(isodir, self.name)
569 cfgf = open(isodir + "/EFI/boot/grub.conf", "w")
570 cfgf.write(cfg)
571 cfgf.close()
573 # first gen mactel machines get the bootloader name wrong apparently
574 if rpmUtils.arch.getBaseArch() == "i386":
575 os.link(isodir + "/EFI/boot/grub.efi", isodir + "/EFI/boot/boot.efi")
576 os.link(isodir + "/EFI/boot/grub.conf", isodir + "/EFI/boot/boot.conf")
578 # for most things, we want them named boot$efiarch
579 efiarch = {"i386": "ia32", "x86_64": "x64"}
580 efiname = efiarch[rpmUtils.arch.getBaseArch()]
581 os.rename(isodir + "/EFI/boot/grub.efi", isodir + "/EFI/boot/boot%s.efi" %(efiname,))
582 os.link(isodir + "/EFI/boot/grub.conf", isodir + "/EFI/boot/boot%s.conf" %(efiname,))
585 def _configure_bootloader(self, isodir):
586 self._configure_syslinux_bootloader(isodir)
587 self._configure_efi_bootloader(isodir)
589 class ppcLiveImageCreator(LiveImageCreatorBase):
590 def _get_mkisofs_options(self, isodir):
591 return [ "-hfs", "-nodesktop", "-part"
592 "-map", isodir + "/ppc/mapping",
593 "-hfs-bless", isodir + "/ppc/mac",
594 "-hfs-volid", self.fslabel ]
596 def _get_required_packages(self):
597 return ["yaboot"] + \
598 LiveImageCreatorBase._get_required_packages(self)
600 def _get_excluded_packages(self):
601 # kind of hacky, but exclude memtest86+ on ppc so it can stay in cfg
602 return ["memtest86+"] + \
603 LiveImageCreatorBase._get_excluded_packages(self)
605 def __copy_boot_file(self, destdir, file):
606 for dir in ["/usr/share/ppc64-utils",
607 "/usr/lib/anaconda-runtime/boot"]:
608 path = self._instroot + dir + "/" + file
609 if not os.path.exists(path):
610 continue
612 makedirs(destdir)
613 shutil.copy(path, destdir)
614 return
616 raise CreatorError("Unable to find boot file " + file)
618 def __kernel_bits(self, kernel):
619 testpath = (self._instroot + "/lib/modules/" +
620 kernel + "/kernel/arch/powerpc/platforms")
622 if not os.path.exists(testpath):
623 return { "32" : True, "64" : False }
624 else:
625 return { "32" : False, "64" : True }
627 def __copy_kernel_and_initramfs(self, destdir, version):
628 bootdir = self._instroot + "/boot"
630 makedirs(destdir)
632 shutil.copyfile(bootdir + "/vmlinuz-" + version,
633 destdir + "/vmlinuz")
635 shutil.copyfile(bootdir + "/initrd-" + version + ".img",
636 destdir + "/initrd.img")
638 def __get_basic_yaboot_config(self, **args):
639 return """
640 init-message = "Welcome to %(name)s"
641 timeout=%(timeout)d
642 """ % args
644 def __get_image_stanza(self, **args):
645 return """
647 image=/ppc/ppc%(bit)s/vmlinuz
648 label=%(short)s
649 initrd=/ppc/ppc%(bit)s/initrd.img
650 read-only
651 append="root=CDLABEL=%(fslabel)s rootfstype=iso9660 %(liveargs)s %(extra)s"
652 """ % args
655 def __write_yaboot_config(isodir, bit):
656 cfg = self.__get_basic_yaboot_config(name = self.name,
657 timeout = self._timeout * 100)
659 kernel_options = self._get_kernel_options()
661 cfg += self.__get_image_stanza(fslabel = self.fslabel,
662 short = "linux",
663 long = "Run from image",
664 extra = "",
665 bit = bit,
666 liveargs = kernel_options)
668 if self._has_checkisomd5():
669 cfg += self.__get_image_stanza(fslabel = self.fslabel,
670 short = "check",
671 long = "Verify and run from image",
672 extra = "check",
673 bit = bit,
674 liveargs = kernel_options)
676 f = open(isodir + "/ppc/ppc" + bit + "/yaboot.conf", "w")
677 f.write(cfg)
678 f.close()
680 def __write_not_supported(isodir, bit):
681 makedirs(isodir + "/ppc/ppc" + bit)
683 message = "Sorry, this LiveCD does not support your hardware"
685 f = open(isodir + "/ppc/ppc" + bit + "/yaboot.conf", "w")
686 f.write('init-message = "' + message + '"')
687 f.close()
690 def __write_dualbits_yaboot_config(isodir, **args):
691 cfg = """
692 init-message = "\nWelcome to %(name)s!\nUse 'linux32' for 32-bit kernel.\n\n"
693 timeout=%(timeout)d
694 default=linux
696 image=/ppc/ppc64/vmlinuz
697 label=linux64
698 alias=linux
699 initrd=/ppc/ppc64/initrd.img
700 read-only
702 image=/ppc/ppc32/vmlinuz
703 label=linux32
704 initrd=/ppc/ppc32/initrd.img
705 read-only
706 """ % args
708 f = open(isodir + "/etc/yaboot.conf", "w")
709 f.write(cfg)
710 f.close()
712 def _configure_bootloader(self, isodir):
713 """configure the boot loader"""
714 havekernel = { 32: False, 64: False }
716 self.__copy_boot_file("mapping", isodir + "/ppc")
717 self.__copy_boot_file("bootinfo.txt", isodir + "/ppc")
718 self.__copy_boot_file("ofboot.b", isodir + "/ppc/mac")
720 shutil.copyfile(self._instroot + "/usr/lib/yaboot/yaboot",
721 isodir + "/ppc/mac/yaboot")
723 makedirs(isodir + "/ppc/chrp")
724 shutil.copyfile(self._instroot + "/usr/lib/yaboot/yaboot",
725 isodir + "/ppc/chrp/yaboot")
727 subprocess.call(["/usr/sbin/addnote", isodir + "/ppc/chrp/yaboot"])
730 # FIXME: ppc should support multiple kernels too...
732 kernel = self._get_kernel_versions().values()[0][0]
734 kernel_bits = self.__kernel_bits(kernel)
736 for (bit, present) in kernel_bits.items():
737 if not present:
738 self.__write_not_supported(isodir, bit)
739 continue
741 self.__copy_kernel_and_initramfs(isodir + "/ppc/ppc" + bit, kernel)
742 self.__write_yaboot_config(isodir, bit)
744 makedirs(isodir + "/etc")
745 if kernel_bits["32"] and not kernel_bits["64"]:
746 shutil.copyfile(isodir + "/ppc/ppc32/yaboot.conf",
747 isodir + "/etc/yaboot.conf")
748 elif kernel_bits["64"] and not kernel_bits["32"]:
749 shutil.copyfile(isodir + "/ppc/ppc64/yaboot.conf",
750 isodir + "/etc/yaboot.conf")
751 else:
752 self.__write_dualbits_yaboot_config(isodir,
753 name = self.name,
754 timeout = self._timeout * 100)
757 # FIXME: build 'netboot' images with kernel+initrd, like mk-images.ppc
760 class ppc64LiveImageCreator(ppcLiveImageCreator):
761 def _get_excluded_packages(self):
762 # FIXME:
763 # while kernel.ppc and kernel.ppc64 co-exist,
764 # we can't have both
765 return ["kernel.ppc"] + \
766 ppcLiveImageCreator._get_excluded_packages(self)
768 arch = rpmUtils.arch.getBaseArch()
769 if arch in ("i386", "x86_64"):
770 LiveImageCreator = x86LiveImageCreator
771 elif arch in ("ppc",):
772 LiveImageCreator = ppcLiveImageCreator
773 elif arch in ("ppc64",):
774 LiveImageCreator = ppc64LiveImageCreator
775 else:
776 raise CreatorError("Architecture not supported!")