mayflower: support live USB on large systems
[livecd/EL-5.git] / imgcreate / live.py
blob8b529c5d53be57c49fd2941f7ff9681aa17a6199
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 *
29 import imgcreate.mayflower as mayflower
31 class LiveImageCreatorBase(LoopImageCreator):
32 """A base class for LiveCD image creators.
34 This class serves as a base class for the architecture-specific LiveCD
35 image creator subclass, LiveImageCreator.
37 LiveImageCreator creates a bootable ISO containing the system image,
38 bootloader, bootloader configuration, kernel and initramfs.
40 """
42 def __init__(self, *args):
43 """Initialise a LiveImageCreator instance.
45 This method takes the same arguments as ImageCreator.__init__().
47 """
48 LoopImageCreator.__init__(self, *args)
50 self.skip_compression = False
51 """Controls whether to use squashfs to compress the image."""
53 self.skip_minimize = False
54 """Controls whether an image minimizing snapshot should be created.
56 This snapshot can be used when copying the system image from the ISO in
57 order to minimize the amount of data that needs to be copied; simply,
58 it makes it possible to create a version of the image's filesystem with
59 no spare space.
61 """
63 self._timeout = kickstart.get_timeout(self.ks, 10)
64 """The bootloader timeout from kickstart."""
66 self._default_kernel = kickstart.get_default_kernel(self.ks, "kernel")
67 """The default kernel type from kickstart."""
69 self.__isodir = None
71 self.__modules = ["=ata", "sym53c8xx", "aic7xxx", "=usb", "=firewire", "=mmc", "=pcmcia", "mptsas", "udf"]
72 self.__modules.extend(kickstart.get_modules(self.ks))
74 self._isofstype = "iso9660"
77 # Hooks for subclasses
79 def _configure_bootloader(self, isodir):
80 """Create the architecture specific booloader configuration.
82 This is the hook where subclasses must create the booloader
83 configuration in order to allow a bootable ISO to be built.
85 isodir -- the directory where the contents of the ISO are to be staged
87 """
88 raise CreatorError("Bootloader configuration is arch-specific, "
89 "but not implemented for this arch!")
91 def _get_kernel_options(self):
92 """Return a kernel options string for bootloader configuration.
94 This is the hook where subclasses may specify a set of kernel options
95 which should be included in the images bootloader configuration.
97 A sensible default implementation is provided.
99 """
100 r = kickstart.get_kernel_args(self.ks)
101 if os.path.exists(self._instroot + "/usr/bin/rhgb"):
102 r += " rhgb"
103 if os.path.exists(self._instroot + "/usr/bin/plymouth"):
104 r += " rhgb"
105 return r
107 def _get_mkisofs_options(self, isodir):
108 """Return the architecture specific mkisosfs options.
110 This is the hook where subclasses may specify additional arguments to
111 mkisofs, e.g. to enable a bootable ISO to be built.
113 By default, an empty list is returned.
116 return []
119 # Helpers for subclasses
121 def _has_checkisomd5(self):
122 """Check whether checkisomd5 is available in the install root."""
123 def exists(instroot, path):
124 return os.path.exists(instroot + path)
126 if (exists(self._instroot, "/usr/lib/anaconda-runtime/checkisomd5") or
127 exists(self._instroot, "/usr/bin/checkisomd5")):
128 return True
130 return False
133 # Actual implementation
135 def _base_on(self, base_on):
136 """helper function to extract ext3 file system from a live CD ISO"""
137 isoloop = DiskMount(LoopbackDisk(base_on, 0), self._mkdtemp())
139 try:
140 isoloop.mount()
141 except MountError, e:
142 raise CreatorError("Failed to loopback mount '%s' : %s" %
143 (base_on, e))
145 # legacy LiveOS filesystem layout support, remove for F9 or F10
146 if os.path.exists(isoloop.mountdir + "/squashfs.img"):
147 squashimg = isoloop.mountdir + "/squashfs.img"
148 else:
149 squashimg = isoloop.mountdir + "/LiveOS/squashfs.img"
151 squashloop = DiskMount(LoopbackDisk(squashimg, 0), self._mkdtemp(), "squashfs")
153 try:
154 if not squashloop.disk.exists():
155 raise CreatorError("'%s' is not a valid live CD ISO : "
156 "squashfs.img doesn't exist" % base_on)
158 try:
159 squashloop.mount()
160 except MountError, e:
161 raise CreatorError("Failed to loopback mount squashfs.img "
162 "from '%s' : %s" % (base_on, e))
164 # legacy LiveOS filesystem layout support, remove for F9 or F10
165 if os.path.exists(squashloop.mountdir + "/os.img"):
166 os_image = squashloop.mountdir + "/os.img"
167 else:
168 os_image = squashloop.mountdir + "/LiveOS/ext3fs.img"
170 if not os.path.exists(os_image):
171 raise CreatorError("'%s' is not a valid live CD ISO : neither "
172 "LiveOS/ext3fs.img nor os.img exist" %
173 base_on)
175 shutil.copyfile(os_image, self._image)
176 finally:
177 squashloop.cleanup()
178 isoloop.cleanup()
180 def _mount_instroot(self, base_on = None):
181 LoopImageCreator._mount_instroot(self, base_on)
182 self.__write_initrd_conf(self._instroot + "/etc/mayflower.conf")
184 def _unmount_instroot(self):
185 try:
186 os.unlink(self._instroot + "/etc/mayflower.conf")
187 except:
188 pass
189 LoopImageCreator._unmount_instroot(self)
191 def __ensure_isodir(self):
192 if self.__isodir is None:
193 self.__isodir = self._mkdtemp("iso-")
194 return self.__isodir
196 def _create_bootconfig(self):
197 """Configure the image so that it's bootable."""
198 mayflower.create_initramfs(self._instroot, self._chroot, self._get_kernel_versions())
199 self._configure_bootloader(self.__ensure_isodir())
201 def _get_post_scripts_env(self, in_chroot):
202 env = LoopImageCreator._get_post_scripts_env(self, in_chroot)
204 if not in_chroot:
205 env["LIVE_ROOT"] = self.__ensure_isodir()
207 return env
209 def __write_initrd_conf(self, path):
210 if not os.path.exists(os.path.dirname(path)):
211 makedirs(os.path.dirname(path))
212 f = open(path, "a")
214 f.write('LIVEOS="yes"\n')
215 f.write('PROBE="no"\n')
216 f.write('MODULES+="squashfs ext3 ext2 vfat msdos "\n')
217 f.write('MODULES+="sr_mod sd_mod ide-cd cdrom "\n')
218 # all scsi drivers included by anaconda
219 mods = subprocess.Popen(["/usr/lib/anaconda-runtime/modlist",
220 "-f",
221 "/usr/lib/anaconda-runtime/loader/module-info",
222 "scsi"], stdout=subprocess.PIPE).communicate()[0]
223 self.__modules.extend(mods.split())
225 for module in self.__modules:
226 if module == "=usb":
227 f.write('MODULES+="ehci_hcd uhci_hcd ohci_hcd "\n')
228 f.write('MODULES+="usb_storage usbhid "\n')
229 elif module == "=firewire":
230 f.write('MODULES+="firewire-sbp2 firewire-ohci "\n')
231 f.write('MODULES+="sbp2 ohci1394 ieee1394 "\n')
232 elif module == "=mmc":
233 f.write('MODULES+="mmc_block sdhci sdhci-pci "\n')
234 elif module == "=pcmcia":
235 f.write('MODULES+="pata_pcmcia "\n')
236 else:
237 f.write('MODULES+="' + module + ' "\n')
239 f.close()
241 def __create_iso(self, isodir):
242 iso = self._outdir + "/" + self.name + ".iso"
244 args = ["/usr/bin/mkisofs",
245 "-J", "-r",
246 "-hide-rr-moved", "-hide-joliet-trans-tbl",
247 "-V", self.fslabel,
248 "-o", iso]
250 args.extend(self._get_mkisofs_options(isodir))
251 if self._isofstype == "udf":
252 args.append("-allow-limited-size")
254 args.append(isodir)
256 if subprocess.call(args) != 0:
257 raise CreatorError("ISO creation failed!")
259 self.__implant_md5sum(iso)
261 def __implant_md5sum(self, iso):
262 """Implant an isomd5sum."""
263 if os.path.exists("/usr/bin/implantisomd5"):
264 implantisomd5 = "/usr/bin/implantisomd5"
265 elif os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"):
266 implantisomd5 = "/usr/lib/anaconda-runtime/implantisomd5"
267 else:
268 logging.warn("isomd5sum not installed; not setting up mediacheck")
270 subprocess.call([implantisomd5, iso])
272 def _stage_final_image(self):
273 try:
274 makedirs(self.__ensure_isodir() + "/LiveOS")
276 minimal_size = self._resparse()
278 if not self.skip_minimize:
279 create_image_minimizer(self.__isodir + "/LiveOS/osmin.img",
280 self._image, minimal_size)
282 if self.skip_compression:
283 shutil.move(self._image, self.__isodir + "/LiveOS/ext3fs.img")
284 if os.stat(self.__isodir + "/LiveOS/ext3fs.img").st_size >= 4*1024*1024*1024:
285 self._isofstype = "udf"
286 logging.warn("Switching to UDF due to size of LiveOS/ext3fs.img")
287 else:
288 makedirs(os.path.join(os.path.dirname(self._image), "LiveOS"))
289 shutil.move(self._image,
290 os.path.join(os.path.dirname(self._image),
291 "LiveOS", "ext3fs.img"))
292 mksquashfs(os.path.dirname(self._image),
293 self.__isodir + "/LiveOS/squashfs.img")
294 if os.stat(self.__isodir + "/LiveOS/squashfs.img").st_size >= 4*1024*1024*1024:
295 self._isofstype = "udf"
296 logging.warn("Switching to UDF due to size of LiveOS/squashfs.img")
299 self.__create_iso(self.__isodir)
300 finally:
301 shutil.rmtree(self.__isodir, ignore_errors = True)
302 self.__isodir = None
304 class x86LiveImageCreator(LiveImageCreatorBase):
305 """ImageCreator for x86 machines"""
306 def _get_mkisofs_options(self, isodir):
307 return [ "-b", "isolinux/isolinux.bin",
308 "-c", "isolinux/boot.cat",
309 "-no-emul-boot", "-boot-info-table",
310 "-boot-load-size", "4" ]
312 def _get_required_packages(self):
313 return ["syslinux"] + LiveImageCreatorBase._get_required_packages(self)
315 def _get_isolinux_stanzas(self, isodir):
316 return ""
318 def __find_syslinux_menu(self):
319 for menu in ["vesamenu.c32", "menu.c32"]:
320 if os.path.isfile(self._instroot + "/usr/lib/syslinux/" + menu):
321 return menu
323 raise CreatorError("syslinux not installed : "
324 "no suitable /usr/lib/syslinux/*menu.c32 found")
326 def __find_syslinux_mboot(self):
328 # We only need the mboot module if we have any xen hypervisors
330 if not glob.glob(self._instroot + "/boot/xen.gz*"):
331 return None
333 return "mboot.c32"
335 def __copy_syslinux_files(self, isodir, menu, mboot = None):
336 files = ["isolinux.bin", menu]
337 if mboot:
338 files += [mboot]
340 for f in files:
341 path = self._instroot + "/usr/lib/syslinux/" + f
343 if not os.path.isfile(path):
344 raise CreatorError("syslinux not installed : "
345 "%s not found" % path)
347 shutil.copy(path, isodir + "/isolinux/")
349 def __copy_syslinux_background(self, isodest):
350 background_path = self._instroot + \
351 "/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg"
353 if not os.path.exists(background_path):
354 return False
356 shutil.copyfile(background_path, isodest)
358 return True
360 def __copy_kernel_and_initramfs(self, isodir, version, index):
361 bootdir = self._instroot + "/boot"
363 shutil.copyfile(bootdir + "/vmlinuz-" + version,
364 isodir + "/isolinux/vmlinuz" + index)
366 shutil.copyfile(bootdir + "/initrd-" + version + ".img",
367 isodir + "/isolinux/initrd" + index + ".img")
369 is_xen = False
370 if os.path.exists(bootdir + "/xen.gz-" + version[:-3]):
371 shutil.copyfile(bootdir + "/xen.gz-" + version[:-3],
372 isodir + "/isolinux/xen" + index + ".gz")
373 is_xen = True
375 return is_xen
377 def __is_default_kernel(self, kernel, kernels):
378 if len(kernels) == 1:
379 return True
381 if kernel == self._default_kernel:
382 return True
384 if kernel.startswith("kernel-") and kernel[7:] == self._default_kernel:
385 return True
387 return False
389 def __get_basic_syslinux_config(self, **args):
390 return """
391 default %(menu)s
392 timeout %(timeout)d
394 %(background)s
395 menu title Welcome to %(name)s!
396 menu color border 0 #ffffffff #00000000
397 menu color sel 7 #ffffffff #ff000000
398 menu color title 0 #ffffffff #00000000
399 menu color tabmsg 0 #ffffffff #00000000
400 menu color unsel 0 #ffffffff #00000000
401 menu color hotsel 0 #ff000000 #ffffffff
402 menu color hotkey 7 #ffffffff #ff000000
403 menu color timeout_msg 0 #ffffffff #00000000
404 menu color timeout 0 #ffffffff #00000000
405 menu color cmdline 0 #ffffffff #00000000
406 menu hidden
407 menu hiddenrow 5
408 """ % args
410 def __get_image_stanza(self, is_xen, **args):
411 if not is_xen:
412 template = """label %(short)s
413 menu label %(long)s
414 kernel vmlinuz%(index)s
415 append initrd=initrd%(index)s.img root=CDLABEL=%(fslabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s
417 else:
418 template = """label %(short)s
419 menu label %(long)s
420 kernel mboot.c32
421 append xen%(index)s.gz --- vmlinuz%(index)s root=CDLABEL=%(fslabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s --- initrd%(index)s.img
423 return template % args
425 def __get_image_stanzas(self, isodir):
426 versions = []
427 kernels = self._get_kernel_versions()
428 for kernel in kernels:
429 for version in kernels[kernel]:
430 versions.append(version)
432 kernel_options = self._get_kernel_options()
434 checkisomd5 = self._has_checkisomd5()
436 cfg = ""
438 index = "0"
439 for version in versions:
440 is_xen = self.__copy_kernel_and_initramfs(isodir, version, index)
442 default = self.__is_default_kernel(kernel, kernels)
444 if default:
445 long = "Boot"
446 elif kernel.startswith("kernel-"):
447 long = "Boot %s(%s)" % (self.name, kernel[7:])
448 else:
449 long = "Boot %s(%s)" % (self.name, kernel)
451 cfg += self.__get_image_stanza(is_xen,
452 fslabel = self.fslabel,
453 isofstype = "auto",
454 liveargs = kernel_options,
455 long = long,
456 short = "linux" + index,
457 extra = "",
458 index = index)
460 if default:
461 cfg += "menu default\n"
463 if checkisomd5:
464 cfg += self.__get_image_stanza(is_xen,
465 fslabel = self.fslabel,
466 isofstype = "auto",
467 liveargs = kernel_options,
468 long = "Verify and " + long,
469 short = "check" + index,
470 extra = "check",
471 index = index)
473 index = str(int(index) + 1)
475 return cfg
477 def __get_memtest_stanza(self, isodir):
478 memtest = glob.glob(self._instroot + "/boot/memtest86*")
479 if not memtest:
480 return ""
482 shutil.copyfile(memtest[0], isodir + "/isolinux/memtest")
484 return """label memtest
485 menu label Memory Test
486 kernel memtest
489 def __get_local_stanza(self, isodir):
490 return """label local
491 menu label Boot from local drive
492 localboot 0xffff
495 def _configure_syslinux_bootloader(self, isodir):
496 """configure the boot loader"""
497 makedirs(isodir + "/isolinux")
499 menu = self.__find_syslinux_menu()
501 self.__copy_syslinux_files(isodir, menu,
502 self.__find_syslinux_mboot())
504 background = ""
505 if self.__copy_syslinux_background(isodir + "/isolinux/splash.jpg"):
506 background = "menu background splash.jpg"
508 cfg = self.__get_basic_syslinux_config(menu = menu,
509 background = background,
510 name = self.name,
511 timeout = self._timeout * 10)
513 cfg += self.__get_image_stanzas(isodir)
514 cfg += self.__get_memtest_stanza(isodir)
515 cfg += self.__get_local_stanza(isodir)
516 cfg += self._get_isolinux_stanzas(isodir)
518 cfgf = open(isodir + "/isolinux/isolinux.cfg", "w")
519 cfgf.write(cfg)
520 cfgf.close()
522 def __copy_efi_files(self, isodir):
523 if not os.path.exists(self._instroot + "/boot/efi/EFI/redhat/grub.efi"):
524 return False
525 shutil.copy(self._instroot + "/boot/efi/EFI/redhat/grub.efi",
526 isodir + "/EFI/boot/grub.efi")
527 shutil.copy(self._instroot + "/boot/grub/splash.xpm.gz",
528 isodir + "/EFI/boot/splash.xpm.gz")
530 return True
532 def __get_basic_efi_config(self, **args):
533 return """
534 default=0
535 splashimage=/EFI/boot/splash.xpm.gz
536 timeout %(timeout)d
537 hiddenmenu
539 """ %args
541 def __get_efi_image_stanza(self, **args):
542 return """title %(long)s
543 kernel /EFI/boot/vmlinuz%(index)s root=CDLABEL=%(fslabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s
544 initrd /EFI/boot/initrd%(index)s.img
545 """ %args
547 def __get_efi_image_stanzas(self, isodir, name):
548 # FIXME: this only supports one kernel right now...
550 kernel_options = self._get_kernel_options()
551 checkisomd5 = self._has_checkisomd5()
553 cfg = ""
555 for index in range(0, 9):
556 # we don't support xen kernels
557 if os.path.exists("%s/EFI/boot/xen%d.gz" %(isodir, index)):
558 continue
559 cfg += self.__get_efi_image_stanza(fslabel = self.fslabel,
560 isofstype = "auto",
561 liveargs = kernel_options,
562 long = name,
563 extra = "", index = index)
564 if checkisomd5:
565 cfg += self.__get_efi_image_stanza(fslabel = self.fslabel,
566 isofstype = "auto",
567 liveargs = kernel_options,
568 long = "Verify and Boot " + name,
569 extra = "check",
570 index = index)
571 break
573 return cfg
575 def _configure_efi_bootloader(self, isodir):
576 """Set up the configuration for an EFI bootloader"""
577 makedirs(isodir + "/EFI/boot")
579 if not self.__copy_efi_files(isodir):
580 shutil.rmtree(isodir + "/EFI")
581 return
583 for f in os.listdir(isodir + "/isolinux"):
584 os.link("%s/isolinux/%s" %(isodir, f),
585 "%s/EFI/boot/%s" %(isodir, f))
588 cfg = self.__get_basic_efi_config(name = self.name,
589 timeout = self._timeout)
590 cfg += self.__get_efi_image_stanzas(isodir, self.name)
592 cfgf = open(isodir + "/EFI/boot/grub.conf", "w")
593 cfgf.write(cfg)
594 cfgf.close()
596 # first gen mactel machines get the bootloader name wrong apparently
597 if rpmUtils.arch.getBaseArch() == "i386":
598 os.link(isodir + "/EFI/boot/grub.efi", isodir + "/EFI/boot/boot.efi")
599 os.link(isodir + "/EFI/boot/grub.conf", isodir + "/EFI/boot/boot.conf")
601 # for most things, we want them named boot$efiarch
602 efiarch = {"i386": "ia32", "x86_64": "x64"}
603 efiname = efiarch[rpmUtils.arch.getBaseArch()]
604 os.rename(isodir + "/EFI/boot/grub.efi", isodir + "/EFI/boot/boot%s.efi" %(efiname,))
605 os.link(isodir + "/EFI/boot/grub.conf", isodir + "/EFI/boot/boot%s.conf" %(efiname,))
608 def _configure_bootloader(self, isodir):
609 self._configure_syslinux_bootloader(isodir)
610 self._configure_efi_bootloader(isodir)
612 class ppcLiveImageCreator(LiveImageCreatorBase):
613 def _get_mkisofs_options(self, isodir):
614 return [ "-hfs", "-nodesktop", "-part"
615 "-map", isodir + "/ppc/mapping",
616 "-hfs-bless", isodir + "/ppc/mac",
617 "-hfs-volid", self.fslabel ]
619 def _get_required_packages(self):
620 return ["yaboot"] + \
621 LiveImageCreatorBase._get_required_packages(self)
623 def _get_excluded_packages(self):
624 # kind of hacky, but exclude memtest86+ on ppc so it can stay in cfg
625 return ["memtest86+"] + \
626 LiveImageCreatorBase._get_excluded_packages(self)
628 def __copy_boot_file(self, destdir, file):
629 for dir in ["/usr/share/ppc64-utils",
630 "/usr/lib/anaconda-runtime/boot"]:
631 path = self._instroot + dir + "/" + file
632 if not os.path.exists(path):
633 continue
635 makedirs(destdir)
636 shutil.copy(path, destdir)
637 return
639 raise CreatorError("Unable to find boot file " + file)
641 def __kernel_bits(self, kernel):
642 testpath = (self._instroot + "/lib/modules/" +
643 kernel + "/kernel/arch/powerpc/platforms")
645 if not os.path.exists(testpath):
646 return { "32" : True, "64" : False }
647 else:
648 return { "32" : False, "64" : True }
650 def __copy_kernel_and_initramfs(self, destdir, version):
651 bootdir = self._instroot + "/boot"
653 makedirs(destdir)
655 shutil.copyfile(bootdir + "/vmlinuz-" + version,
656 destdir + "/vmlinuz")
658 shutil.copyfile(bootdir + "/initrd-" + version + ".img",
659 destdir + "/initrd.img")
661 def __get_basic_yaboot_config(self, **args):
662 return """
663 init-message = "Welcome to %(name)s"
664 timeout=%(timeout)d
665 """ % args
667 def __get_image_stanza(self, **args):
668 return """
670 image=/ppc/ppc%(bit)s/vmlinuz
671 label=%(short)s
672 initrd=/ppc/ppc%(bit)s/initrd.img
673 read-only
674 append="root=CDLABEL=%(fslabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s"
675 """ % args
678 def __write_yaboot_config(isodir, bit):
679 cfg = self.__get_basic_yaboot_config(name = self.name,
680 timeout = self._timeout * 100)
682 kernel_options = self._get_kernel_options()
684 cfg += self.__get_image_stanza(fslabel = self.fslabel,
685 isofstype = "auto",
686 short = "linux",
687 long = "Run from image",
688 extra = "",
689 bit = bit,
690 liveargs = kernel_options)
692 if self._has_checkisomd5():
693 cfg += self.__get_image_stanza(fslabel = self.fslabel,
694 isofstype = "auto",
695 short = "check",
696 long = "Verify and run from image",
697 extra = "check",
698 bit = bit,
699 liveargs = kernel_options)
701 f = open(isodir + "/ppc/ppc" + bit + "/yaboot.conf", "w")
702 f.write(cfg)
703 f.close()
705 def __write_not_supported(isodir, bit):
706 makedirs(isodir + "/ppc/ppc" + bit)
708 message = "Sorry, this LiveCD does not support your hardware"
710 f = open(isodir + "/ppc/ppc" + bit + "/yaboot.conf", "w")
711 f.write('init-message = "' + message + '"')
712 f.close()
715 def __write_dualbits_yaboot_config(isodir, **args):
716 cfg = """
717 init-message = "\nWelcome to %(name)s!\nUse 'linux32' for 32-bit kernel.\n\n"
718 timeout=%(timeout)d
719 default=linux
721 image=/ppc/ppc64/vmlinuz
722 label=linux64
723 alias=linux
724 initrd=/ppc/ppc64/initrd.img
725 read-only
727 image=/ppc/ppc32/vmlinuz
728 label=linux32
729 initrd=/ppc/ppc32/initrd.img
730 read-only
731 """ % args
733 f = open(isodir + "/etc/yaboot.conf", "w")
734 f.write(cfg)
735 f.close()
737 def _configure_bootloader(self, isodir):
738 """configure the boot loader"""
739 havekernel = { 32: False, 64: False }
741 self.__copy_boot_file("mapping", isodir + "/ppc")
742 self.__copy_boot_file("bootinfo.txt", isodir + "/ppc")
743 self.__copy_boot_file("ofboot.b", isodir + "/ppc/mac")
745 shutil.copyfile(self._instroot + "/usr/lib/yaboot/yaboot",
746 isodir + "/ppc/mac/yaboot")
748 makedirs(isodir + "/ppc/chrp")
749 shutil.copyfile(self._instroot + "/usr/lib/yaboot/yaboot",
750 isodir + "/ppc/chrp/yaboot")
752 subprocess.call(["/usr/sbin/addnote", isodir + "/ppc/chrp/yaboot"])
755 # FIXME: ppc should support multiple kernels too...
757 kernel = self._get_kernel_versions().values()[0][0]
759 kernel_bits = self.__kernel_bits(kernel)
761 for (bit, present) in kernel_bits.items():
762 if not present:
763 self.__write_not_supported(isodir, bit)
764 continue
766 self.__copy_kernel_and_initramfs(isodir + "/ppc/ppc" + bit, kernel)
767 self.__write_yaboot_config(isodir, bit)
769 makedirs(isodir + "/etc")
770 if kernel_bits["32"] and not kernel_bits["64"]:
771 shutil.copyfile(isodir + "/ppc/ppc32/yaboot.conf",
772 isodir + "/etc/yaboot.conf")
773 elif kernel_bits["64"] and not kernel_bits["32"]:
774 shutil.copyfile(isodir + "/ppc/ppc64/yaboot.conf",
775 isodir + "/etc/yaboot.conf")
776 else:
777 self.__write_dualbits_yaboot_config(isodir,
778 name = self.name,
779 timeout = self._timeout * 100)
782 # FIXME: build 'netboot' images with kernel+initrd, like mk-images.ppc
785 class ppc64LiveImageCreator(ppcLiveImageCreator):
786 def _get_excluded_packages(self):
787 # FIXME:
788 # while kernel.ppc and kernel.ppc64 co-exist,
789 # we can't have both
790 return ["kernel.ppc"] + \
791 ppcLiveImageCreator._get_excluded_packages(self)
793 arch = rpmUtils.arch.getBaseArch()
794 if arch in ("i386", "x86_64"):
795 LiveImageCreator = x86LiveImageCreator
796 elif arch in ("ppc",):
797 LiveImageCreator = ppcLiveImageCreator
798 elif arch in ("ppc64",):
799 LiveImageCreator = ppc64LiveImageCreator
800 else:
801 raise CreatorError("Architecture not supported!")