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.
27 from imgcreate
.errors
import *
28 from imgcreate
.fs
import *
29 from imgcreate
.creator
import *
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.
42 def __init__(self
, ks
, name
, fslabel
=None, releasever
=None, tmpdir
="/tmp",
43 title
="Linux", product
="Linux", useplugins
=False):
44 """Initialise a LiveImageCreator instance.
46 This method takes the same arguments as LoopImageCreator.__init__().
49 LoopImageCreator
.__init
__(self
, ks
, name
,
51 releasever
=releasever
,
53 useplugins
=useplugins
)
55 self
.compress_type
= "xz"
56 """mksquashfs compressor to use."""
58 self
.skip_compression
= False
59 """Controls whether to use squashfs to compress the image."""
61 self
.skip_minimize
= False
62 """Controls whether an image minimizing snapshot should be created.
64 This snapshot can be used when copying the system image from the ISO in
65 order to minimize the amount of data that needs to be copied; simply,
66 it makes it possible to create a version of the image's filesystem with
71 self
._timeout
= kickstart
.get_timeout(self
.ks
, 10)
72 """The bootloader timeout from kickstart."""
74 self
._default
_kernel
= kickstart
.get_default_kernel(self
.ks
, "kernel")
75 """The default kernel type from kickstart."""
79 self
.__modules
= ["=ata", "sym53c8xx", "aic7xxx", "=usb", "=firewire",
80 "=mmc", "=pcmcia", "mptsas", "udf", "virtio_blk",
82 self
.__modules
.extend(kickstart
.get_modules(self
.ks
))
84 self
._isofstype
= "iso9660"
88 self
.product
= product
91 # Hooks for subclasses
93 def _configure_bootloader(self
, isodir
):
94 """Create the architecture specific booloader configuration.
96 This is the hook where subclasses must create the booloader
97 configuration in order to allow a bootable ISO to be built.
99 isodir -- the directory where the contents of the ISO are to be staged
102 raise CreatorError("Bootloader configuration is arch-specific, "
103 "but not implemented for this arch!")
105 def _get_kernel_options(self
):
106 """Return a kernel options string for bootloader configuration.
108 This is the hook where subclasses may specify a set of kernel options
109 which should be included in the images bootloader configuration.
111 A sensible default implementation is provided.
114 r
= kickstart
.get_kernel_args(self
.ks
)
115 if os
.path
.exists(self
._instroot
+ "/usr/bin/rhgb"):
117 if os
.path
.exists(self
._instroot
+ "/usr/bin/plymouth"):
121 def _get_mkisofs_options(self
, isodir
):
122 """Return the architecture specific mkisosfs options.
124 This is the hook where subclasses may specify additional arguments to
125 mkisofs, e.g. to enable a bootable ISO to be built.
127 By default, an empty list is returned.
133 # Helpers for subclasses
135 def _has_checkisomd5(self
):
136 """Check whether checkisomd5 is available in the install root."""
137 def exists(instroot
, path
):
138 return os
.path
.exists(instroot
+ path
)
140 if (exists(self
._instroot
, "/usr/lib/anaconda-runtime/checkisomd5") or
141 exists(self
._instroot
, "/usr/bin/checkisomd5")):
147 # Actual implementation
149 def _base_on(self
, base_on
):
150 """helper function to extract ext3 file system from a live CD ISO"""
151 isoloop
= DiskMount(LoopbackDisk(base_on
, 0), self
._mkdtemp
())
155 except MountError
, e
:
156 raise CreatorError("Failed to loopback mount '%s' : %s" %
159 # Copy the initrd%d.img and xen%d.gz files over to /isolinux
160 # This is because the originals in /boot are removed when the
161 # original .iso was created.
162 src
= isoloop
.mountdir
+ "/isolinux/"
163 dest
= self
.__ensure
_isodir
() + "/isolinux/"
165 pattern
= re
.compile(r
"(initrd\d+\.img|xen\d+\.gz)")
166 files
= [f
for f
in os
.listdir(src
) if pattern
.search(f
)
167 and os
.path
.isfile(src
+f
)]
169 shutil
.copyfile(src
+f
, dest
+f
)
171 # legacy LiveOS filesystem layout support, remove for F9 or F10
172 if os
.path
.exists(isoloop
.mountdir
+ "/squashfs.img"):
173 squashimg
= isoloop
.mountdir
+ "/squashfs.img"
175 squashimg
= isoloop
.mountdir
+ "/LiveOS/squashfs.img"
177 squashloop
= DiskMount(LoopbackDisk(squashimg
, 0), self
._mkdtemp
(), "squashfs")
179 # 'self.compress_type = None' will force reading it from base_on.
180 if self
.compress_type
is None:
181 self
.compress_type
= squashfs_compression_type(squashimg
)
182 if self
.compress_type
== 'undetermined':
183 # Default to 'gzip' for compatibility with older versions.
184 self
.compress_type
= 'gzip'
186 if not squashloop
.disk
.exists():
187 raise CreatorError("'%s' is not a valid live CD ISO : "
188 "squashfs.img doesn't exist" % base_on
)
192 except MountError
, e
:
193 raise CreatorError("Failed to loopback mount squashfs.img "
194 "from '%s' : %s" % (base_on
, e
))
196 # legacy LiveOS filesystem layout support, remove for F9 or F10
197 if os
.path
.exists(squashloop
.mountdir
+ "/os.img"):
198 os_image
= squashloop
.mountdir
+ "/os.img"
200 os_image
= squashloop
.mountdir
+ "/LiveOS/ext3fs.img"
202 if not os
.path
.exists(os_image
):
203 raise CreatorError("'%s' is not a valid live CD ISO : neither "
204 "LiveOS/ext3fs.img nor os.img exist" %
208 shutil
.copyfile(os_image
, self
._image
)
210 raise CreatorError("Failed to copy base live image to %s for modification: %s" %(self
._image
, e
))
215 def _mount_instroot(self
, base_on
= None):
217 LoopImageCreator
._mount
_instroot
(self
, base_on
)
218 self
.__write
_initrd
_conf
(self
._instroot
+ "/etc/sysconfig/mkinitrd")
219 self
.__write
_dracut
_conf
(self
._instroot
+ "/etc/dracut.conf.d/02livecd.conf")
221 def _unmount_instroot(self
):
222 self
.__restore
_file
(self
._instroot
+ "/etc/sysconfig/mkinitrd")
223 self
.__restore
_file
(self
._instroot
+ "/etc/dracut.conf.d/02livecd.conf")
224 LoopImageCreator
._unmount
_instroot
(self
)
226 def __ensure_isodir(self
):
227 if self
.__isodir
is None:
228 self
.__isodir
= self
._mkdtemp
("iso-")
231 def _generate_efiboot(self
, isodir
):
232 """Generate EFI boot images."""
233 if not os
.path
.exists(self
._instroot
+ "/boot/efi/EFI/redhat/grub.efi"):
235 subprocess
.call(["mkefiboot", isodir
+ "/EFI/BOOT",
236 isodir
+ "/isolinux/efiboot.img"])
237 subprocess
.call(["mkefiboot", "-a", isodir
+ "/EFI/BOOT",
238 isodir
+ "/isolinux/macboot.img", "-l", self
.product
,
239 "-i", "/usr/share/pixmaps/bootloader/fedora.icns",
242 def _create_bootconfig(self
):
243 """Configure the image so that it's bootable."""
244 self
._configure
_bootloader
(self
.__ensure
_isodir
())
245 self
._generate
_efiboot
(self
.__ensure
_isodir
())
247 def _get_post_scripts_env(self
, in_chroot
):
248 env
= LoopImageCreator
._get
_post
_scripts
_env
(self
, in_chroot
)
251 env
["LIVE_ROOT"] = self
.__ensure
_isodir
()
255 def __extra_filesystems(self
):
256 return "squashfs ext4 ext3 ext2 vfat msdos ";
258 def __extra_drivers(self
):
259 retval
= "sr_mod sd_mod ide-cd cdrom "
260 for module
in self
.__modules
:
262 retval
= retval
+ "ehci_hcd uhci_hcd ohci_hcd "
263 retval
= retval
+ "usb_storage usbhid "
264 elif module
== "=firewire":
265 retval
= retval
+ "firewire-sbp2 firewire-ohci "
266 retval
= retval
+ "sbp2 ohci1394 ieee1394 "
267 elif module
== "=mmc":
268 retval
= retval
+ "mmc_block sdhci sdhci-pci "
269 elif module
== "=pcmcia":
270 retval
= retval
+ "pata_pcmcia "
272 retval
= retval
+ module
+ " "
275 def __restore_file(self
,path
):
280 if os
.path
.exists(path
+ '.rpmnew'):
281 os
.rename(path
+ '.rpmnew', path
)
283 def __write_initrd_conf(self
, path
):
284 if not os
.path
.exists(os
.path
.dirname(path
)):
285 makedirs(os
.path
.dirname(path
))
287 f
.write('LIVEOS="yes"\n')
288 f
.write('PROBE="no"\n')
289 f
.write('MODULES+="' + self
.__extra
_filesystems
() + '"\n')
290 f
.write('MODULES+="' + self
.__extra
_drivers
() + '"\n')
293 def __write_dracut_conf(self
, path
):
294 if not os
.path
.exists(os
.path
.dirname(path
)):
295 makedirs(os
.path
.dirname(path
))
297 f
.write('filesystems+="' + self
.__extra
_filesystems
() + ' "\n')
298 f
.write('drivers+="' + self
.__extra
_drivers
() + ' "\n')
299 f
.write('add_dracutmodules+=" dmsquash-live "')
302 def __create_iso(self
, isodir
):
303 iso
= self
._outdir
+ "/" + self
.name
+ ".iso"
305 args
= ["/usr/bin/mkisofs",
307 "-hide-rr-moved", "-hide-joliet-trans-tbl",
311 args
.extend(self
._get
_mkisofs
_options
(isodir
))
312 if self
._isofstype
== "udf":
313 args
.append("-allow-limited-size")
317 if subprocess
.call(args
) != 0:
318 raise CreatorError("ISO creation failed!")
320 if os
.path
.exists("/usr/bin/isohybrid"):
321 if os
.path
.exists(isodir
+ "/isolinux/efiboot.img"):
322 subprocess
.call(["/usr/bin/isohybrid", "-u", "-m", iso
])
324 subprocess
.call(["/usr/bin/isohybrid", iso
])
326 self
.__implant
_md
5sum
(iso
)
328 def __implant_md5sum(self
, iso
):
329 """Implant an isomd5sum."""
330 if os
.path
.exists("/usr/bin/implantisomd5"):
331 implantisomd5
= "/usr/bin/implantisomd5"
332 elif os
.path
.exists("/usr/lib/anaconda-runtime/implantisomd5"):
333 implantisomd5
= "/usr/lib/anaconda-runtime/implantisomd5"
335 logging
.warn("isomd5sum not installed; not setting up mediacheck")
338 subprocess
.call([implantisomd5
, iso
])
340 def _stage_final_image(self
):
342 makedirs(self
.__ensure
_isodir
() + "/LiveOS")
346 if not self
.skip_minimize
:
347 create_image_minimizer(self
.__isodir
+ "/LiveOS/osmin.img",
348 self
._image
, self
.compress_type
,
349 tmpdir
= self
.tmpdir
)
351 if self
.skip_compression
:
352 shutil
.move(self
._image
, self
.__isodir
+ "/LiveOS/ext3fs.img")
353 if os
.stat(self
.__isodir
+ "/LiveOS/ext3fs.img").st_size
>= 4*1024*1024*1024:
354 self
._isofstype
= "udf"
355 logging
.warn("Switching to UDF due to size of LiveOS/ext3fs.img")
357 makedirs(os
.path
.join(os
.path
.dirname(self
._image
), "LiveOS"))
358 shutil
.move(self
._image
,
359 os
.path
.join(os
.path
.dirname(self
._image
),
360 "LiveOS", "ext3fs.img"))
361 mksquashfs(os
.path
.dirname(self
._image
),
362 self
.__isodir
+ "/LiveOS/squashfs.img",
364 if os
.stat(self
.__isodir
+ "/LiveOS/squashfs.img").st_size
>= 4*1024*1024*1024:
365 self
._isofstype
= "udf"
366 logging
.warn("Switching to UDF due to size of LiveOS/squashfs.img")
369 self
.__create
_iso
(self
.__isodir
)
371 shutil
.rmtree(self
.__isodir
, ignore_errors
= True)
374 class x86LiveImageCreator(LiveImageCreatorBase
):
375 """ImageCreator for x86 machines"""
376 def _get_mkisofs_options(self
, isodir
):
377 options
= [ "-b", "isolinux/isolinux.bin",
378 "-c", "isolinux/boot.cat",
379 "-no-emul-boot", "-boot-info-table",
380 "-boot-load-size", "4" ]
381 if os
.path
.exists(isodir
+ "/isolinux/efiboot.img"):
382 options
.extend([ "-eltorito-alt-boot",
383 "-e", "isolinux/efiboot.img",
385 "-eltorito-alt-boot",
386 "-e", "isolinux/macboot.img",
390 def _get_required_packages(self
):
391 return ["syslinux"] + LiveImageCreatorBase
._get
_required
_packages
(self
)
393 def _get_isolinux_stanzas(self
, isodir
):
396 def __find_syslinux_menu(self
):
397 for menu
in ("vesamenu.c32", "menu.c32"):
398 for dir in ("/usr/lib/syslinux/", "/usr/share/syslinux/"):
399 if os
.path
.isfile(self
._instroot
+ dir + menu
):
402 raise CreatorError("syslinux not installed : "
403 "no suitable *menu.c32 found")
405 def __find_syslinux_mboot(self
):
407 # We only need the mboot module if we have any xen hypervisors
409 if not glob
.glob(self
._instroot
+ "/boot/xen.gz*"):
414 def __copy_syslinux_files(self
, isodir
, menu
, mboot
= None):
415 files
= ["isolinux.bin", menu
]
420 if os
.path
.exists(self
._instroot
+ "/usr/lib/syslinux/" + f
):
421 path
= self
._instroot
+ "/usr/lib/syslinux/" + f
422 elif os
.path
.exists(self
._instroot
+ "/usr/share/syslinux/" + f
):
423 path
= self
._instroot
+ "/usr/share/syslinux/" + f
424 if not os
.path
.isfile(path
):
425 raise CreatorError("syslinux not installed : "
426 "%s not found" % path
)
428 shutil
.copy(path
, isodir
+ "/isolinux/")
430 def __copy_syslinux_background(self
, isodest
):
431 background_path
= self
._instroot
+ \
432 "/usr/share/anaconda/boot/syslinux-vesa-splash.jpg"
434 if not os
.path
.exists(background_path
):
435 # fallback to F13 location
436 background_path
= self
._instroot
+ \
437 "/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg"
439 if not os
.path
.exists(background_path
):
442 shutil
.copyfile(background_path
, isodest
)
446 def __copy_kernel_and_initramfs(self
, isodir
, version
, index
):
447 bootdir
= self
._instroot
+ "/boot"
449 shutil
.copyfile(bootdir
+ "/vmlinuz-" + version
,
450 isodir
+ "/isolinux/vmlinuz" + index
)
453 if os
.path
.exists(bootdir
+ "/initramfs-" + version
+ ".img"):
454 shutil
.copyfile(bootdir
+ "/initramfs-" + version
+ ".img",
455 isodir
+ "/isolinux/initrd" + index
+ ".img")
457 elif os
.path
.exists(bootdir
+ "/initrd-" + version
+ ".img"):
458 shutil
.copyfile(bootdir
+ "/initrd-" + version
+ ".img",
459 isodir
+ "/isolinux/initrd" + index
+ ".img")
460 elif not self
.base_on
:
461 logging
.error("No initrd or initramfs found for %s" % (version
,))
464 if os
.path
.exists(bootdir
+ "/xen.gz-" + version
[:-3]):
465 shutil
.copyfile(bootdir
+ "/xen.gz-" + version
[:-3],
466 isodir
+ "/isolinux/xen" + index
+ ".gz")
469 return (is_xen
, isDracut
)
471 def __is_default_kernel(self
, kernel
, kernels
):
472 if len(kernels
) == 1:
475 if kernel
== self
._default
_kernel
:
478 if kernel
.startswith("kernel-") and kernel
[7:] == self
._default
_kernel
:
483 def __get_basic_syslinux_config(self
, **args
):
487 menu background %(background)s
488 menu autoboot Starting %(title)s in # second{,s}. Press any key to interrupt.
499 menu color border * #00000000 #00000000 none
500 menu color sel 0 #ffffffff #00000000 none
501 menu color title 0 #ff7ba3d0 #00000000 none
502 menu color tabmsg 0 #ff3a6496 #00000000 none
503 menu color unsel 0 #84b8ffff #00000000 none
504 menu color hotsel 0 #84b8ffff #00000000 none
505 menu color hotkey 0 #ffffffff #00000000 none
506 menu color help 0 #ffffffff #00000000 none
507 menu color scrollbar 0 #ffffffff #ff355594 none
508 menu color timeout 0 #ffffffff #00000000 none
509 menu color timeout_msg 0 #ffffffff #00000000 none
510 menu color cmdmark 0 #84b8ffff #00000000 none
511 menu color cmdline 0 #ffffffff #00000000 none
513 menu tabmsg Press Tab for full configuration options on menu items.
517 def __get_image_stanza(self
, is_xen
, isDracut
, **args
):
519 args
["rootlabel"] = "live:CDLABEL=%(fslabel)s" % args
521 args
["rootlabel"] = "CDLABEL=%(fslabel)s" % args
524 template
= """label %(short)s
526 kernel vmlinuz%(index)s
527 append initrd=initrd%(index)s.img root=%(rootlabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s
530 template
= """label %(short)s
533 append xen%(index)s.gz --- vmlinuz%(index)s root=%(rootlabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s --- initrd%(index)s.img
536 template
+= """ text help
540 return template
% args
542 def __get_image_stanzas(self
, isodir
):
544 kernels
= self
._get
_kernel
_versions
()
545 for kernel
in kernels
:
546 for version
in kernels
[kernel
]:
547 versions
.append(version
)
549 kernel_options
= self
._get
_kernel
_options
()
551 checkisomd5
= self
._has
_checkisomd
5()
553 # Stanzas for insertion into the config template
559 for version
in versions
:
560 (is_xen
, isDracut
) = self
.__copy
_kernel
_and
_initramfs
(isodir
, version
, index
)
562 self
._isDracut
= isDracut
564 default
= self
.__is
_default
_kernel
(kernel
, kernels
)
568 elif kernel
.startswith("kernel-"):
569 long = "%s (%s)" % (self
.product
, kernel
[7:])
571 long = "%s (%s)" % (self
.product
, kernel
)
573 # tell dracut not to ask for LUKS passwords or activate mdraid sets
575 kern_opts
= kernel_options
+ " rd.luks=0 rd.md=0 rd.dm=0"
577 kern_opts
= kernel_options
579 linux
.append(self
.__get
_image
_stanza
(is_xen
, isDracut
,
580 fslabel
= self
.fslabel
,
582 liveargs
= kern_opts
,
583 long = "^Start " + long,
584 short
= "linux" + index
,
590 linux
[-1] += " menu default\n"
592 basic
.append(self
.__get
_image
_stanza
(is_xen
, isDracut
,
593 fslabel
= self
.fslabel
,
595 liveargs
= kern_opts
,
596 long = "Start " + long + " in ^basic graphics mode.",
597 short
= "basic" + index
,
598 extra
= "xdriver=vesa nomodeset",
599 help = "Try this option out if you're having trouble starting.",
603 check
.append(self
.__get
_image
_stanza
(is_xen
, isDracut
,
604 fslabel
= self
.fslabel
,
606 liveargs
= kern_opts
,
607 long = "^Test this media & start " + long,
608 short
= "check" + index
,
609 extra
= "rd.live.check",
615 index
= str(int(index
) + 1)
617 return (linux
, basic
, check
)
619 def __get_memtest_stanza(self
, isodir
):
620 memtest
= glob
.glob(self
._instroot
+ "/boot/memtest86*")
624 shutil
.copyfile(memtest
[0], isodir
+ "/isolinux/memtest")
626 return """label memtest
627 menu label Run a ^memory test.
629 If your system is having issues, an problem with your
630 system's memory may be the cause. Use this utility to
631 see if the memory is working correctly.
636 def __get_local_stanza(self
, isodir
):
637 return """label local
638 menu label Boot from ^local drive
642 def _configure_syslinux_bootloader(self
, isodir
):
643 """configure the boot loader"""
644 makedirs(isodir
+ "/isolinux")
646 menu
= self
.__find
_syslinux
_menu
()
648 self
.__copy
_syslinux
_files
(isodir
, menu
,
649 self
.__find
_syslinux
_mboot
())
652 if self
.__copy
_syslinux
_background
(isodir
+ "/isolinux/splash.jpg"):
653 background
= "splash.jpg"
655 cfg
= self
.__get
_basic
_syslinux
_config
(menu
= menu
,
656 background
= background
,
658 timeout
= self
._timeout
* 10)
659 cfg
+= "menu separator\n"
661 linux
, basic
, check
= self
.__get
_image
_stanzas
(isodir
)
662 # Add linux stanzas to main menu
665 cfg
+= "menu separator\n"
667 cfg
+= """menu begin ^Troubleshooting
668 menu title Troubleshooting
670 # Add basic video and check to submenu
671 for b
, c
in zip(basic
, check
):
676 cfg
+= self
.__get
_memtest
_stanza
(isodir
)
677 cfg
+= "menu separator\n"
679 cfg
+= self
.__get
_local
_stanza
(isodir
)
680 cfg
+= self
._get
_isolinux
_stanzas
(isodir
)
682 cfg
+= """menu separator
684 menu label Return to ^main menu.
688 cfgf
= open(isodir
+ "/isolinux/isolinux.cfg", "w")
692 def __copy_efi_files(self
, isodir
):
693 if not os
.path
.exists(self
._instroot
+ "/boot/efi/EFI/redhat/grub.efi"):
695 shutil
.copy(self
._instroot
+ "/boot/efi/EFI/redhat/grub.efi",
696 isodir
+ "/EFI/BOOT/grub.efi")
698 # Should exist, but if it doesn't we should fail
699 if os
.path
.exists(self
._instroot
+ "/boot/grub/splash.xpm.gz"):
700 shutil
.copy(self
._instroot
+ "/boot/grub/splash.xpm.gz",
701 isodir
+ "/EFI/BOOT/splash.xpm.gz")
705 def __get_basic_efi_config(self
, **args
):
708 splashimage=/EFI/BOOT/splash.xpm.gz
714 def __get_efi_image_stanza(self
, **args
):
716 args
["rootlabel"] = "live:LABEL=%(fslabel)s" % args
718 args
["rootlabel"] = "CDLABEL=%(fslabel)s" % args
719 return """title %(long)s
721 kernel /isolinux/vmlinuz%(index)s root=%(rootlabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s
722 initrd /isolinux/initrd%(index)s.img
725 def __get_efi_image_stanzas(self
, isodir
, name
):
726 # FIXME: this only supports one kernel right now...
728 kernel_options
= self
._get
_kernel
_options
()
729 checkisomd5
= self
._has
_checkisomd
5()
733 for index
in range(0, 9):
734 # we don't support xen kernels
735 if os
.path
.exists("%s/EFI/BOOT/xen%d.gz" %(isodir
, index
)):
737 cfg
+= self
.__get
_efi
_image
_stanza
(fslabel
= self
.fslabel
,
739 liveargs
= kernel_options
,
741 extra
= "", index
= index
)
743 cfg
+= self
.__get
_efi
_image
_stanza
(fslabel
= self
.fslabel
,
745 liveargs
= kernel_options
,
746 long = "Verify and Boot " + name
,
747 extra
= "rd.live.check",
753 def _configure_efi_bootloader(self
, isodir
):
754 """Set up the configuration for an EFI bootloader"""
755 makedirs(isodir
+ "/EFI/BOOT")
757 if not self
.__copy
_efi
_files
(isodir
):
758 shutil
.rmtree(isodir
+ "/EFI")
761 cfg
= self
.__get
_basic
_efi
_config
(name
= self
.name
,
762 timeout
= self
._timeout
)
763 cfg
+= self
.__get
_efi
_image
_stanzas
(isodir
, self
.name
)
765 cfgf
= open(isodir
+ "/EFI/BOOT/grub.conf", "w")
769 # first gen mactel machines get the bootloader name wrong apparently
770 if rpmUtils
.arch
.getBaseArch() == "i386":
771 os
.link(isodir
+ "/EFI/BOOT/grub.efi", isodir
+ "/EFI/BOOT/BOOT.efi")
772 os
.link(isodir
+ "/EFI/BOOT/grub.conf", isodir
+ "/EFI/BOOT/BOOT.conf")
774 # for most things, we want them named boot$efiarch
775 efiarch
= {"i386": "IA32", "x86_64": "X64"}
776 efiname
= efiarch
[rpmUtils
.arch
.getBaseArch()]
777 os
.rename(isodir
+ "/EFI/BOOT/grub.efi", isodir
+ "/EFI/BOOT/BOOT%s.efi" %(efiname
,))
778 os
.link(isodir
+ "/EFI/BOOT/grub.conf", isodir
+ "/EFI/BOOT/BOOT%s.conf" %(efiname
,))
781 def _configure_bootloader(self
, isodir
):
782 self
._configure
_syslinux
_bootloader
(isodir
)
783 self
._configure
_efi
_bootloader
(isodir
)
785 class ppcLiveImageCreator(LiveImageCreatorBase
):
786 def _get_mkisofs_options(self
, isodir
):
787 return [ "-hfs", "-no-desktop", "-part",
788 "-map", isodir
+ "/ppc/mapping",
789 "-hfs-bless", isodir
+ "/ppc/mac",
790 "-hfs-volid", self
.fslabel
]
792 def _get_required_packages(self
):
793 return ["yaboot"] + \
794 LiveImageCreatorBase
._get
_required
_packages
(self
)
796 def _get_excluded_packages(self
):
797 # kind of hacky, but exclude memtest86+ on ppc so it can stay in cfg
798 return ["memtest86+"] + \
799 LiveImageCreatorBase
._get
_excluded
_packages
(self
)
801 def __copy_boot_file(self
, destdir
, file):
802 for dir in ["/usr/share/ppc64-utils",
803 "/usr/lib/anaconda-runtime/boot"]:
804 path
= self
._instroot
+ dir + "/" + file
805 if not os
.path
.exists(path
):
809 shutil
.copy(path
, destdir
)
812 raise CreatorError("Unable to find boot file " + file)
814 def __kernel_bits(self
, kernel
):
815 testpath
= (self
._instroot
+ "/lib/modules/" +
816 kernel
+ "/kernel/arch/powerpc/platforms")
818 if not os
.path
.exists(testpath
):
819 return { "32" : True, "64" : False }
821 return { "32" : False, "64" : True }
823 def __copy_kernel_and_initramfs(self
, destdir
, version
):
825 bootdir
= self
._instroot
+ "/boot"
829 shutil
.copyfile(bootdir
+ "/vmlinuz-" + version
,
830 destdir
+ "/vmlinuz")
832 if os
.path
.exists(bootdir
+ "/initramfs-" + version
+ ".img"):
833 shutil
.copyfile(bootdir
+ "/initramfs-" + version
+ ".img",
834 destdir
+ "/initrd.img")
837 shutil
.copyfile(bootdir
+ "/initrd-" + version
+ ".img",
838 destdir
+ "/initrd.img")
842 def __get_basic_yaboot_config(self
, **args
):
844 init-message = "Welcome to %(name)s"
848 def __get_image_stanza(self
, **args
):
850 args
["rootlabel"] = "live:LABEL=%(fslabel)s" % args
852 args
["rootlabel"] = "CDLABEL=%(fslabel)s" % args
855 image=/ppc/ppc%(bit)s/vmlinuz
857 initrd=/ppc/ppc%(bit)s/initrd.img
859 append="root=%(rootlabel)s rootfstype=%(isofstype)s %(liveargs)s %(extra)s"
863 def __write_yaboot_config(self
, isodir
, bit
, isDracut
= False):
864 cfg
= self
.__get
_basic
_yaboot
_config
(name
= self
.name
,
865 timeout
= self
._timeout
* 100)
867 kernel_options
= self
._get
_kernel
_options
()
869 cfg
+= self
.__get
_image
_stanza
(fslabel
= self
.fslabel
,
872 long = "Run from image",
875 liveargs
= kernel_options
,
878 if self
._has
_checkisomd
5():
879 cfg
+= self
.__get
_image
_stanza
(fslabel
= self
.fslabel
,
881 short
= "rd.live.check",
882 long = "Verify and run from image",
883 extra
= "rd.live.check",
885 liveargs
= kernel_options
,
888 f
= open(isodir
+ "/ppc/ppc" + bit
+ "/yaboot.conf", "w")
892 def __write_not_supported(self
, isodir
, bit
):
893 makedirs(isodir
+ "/ppc/ppc" + bit
)
895 message
= "Sorry, this LiveCD does not support your hardware"
897 f
= open(isodir
+ "/ppc/ppc" + bit
+ "/yaboot.conf", "w")
898 f
.write('init-message = "' + message
+ '"')
902 def __write_dualbits_yaboot_config(isodir
, **args
):
904 init-message = "\nWelcome to %(name)s!\nUse 'linux32' for 32-bit kernel.\n\n"
908 image=/ppc/ppc64/vmlinuz
911 initrd=/ppc/ppc64/initrd.img
914 image=/ppc/ppc32/vmlinuz
916 initrd=/ppc/ppc32/initrd.img
920 f
= open(isodir
+ "/etc/yaboot.conf", "w")
924 def _configure_bootloader(self
, isodir
):
925 """configure the boot loader"""
926 havekernel
= { 32: False, 64: False }
928 self
.__copy
_boot
_file
(isodir
+ "/ppc", "mapping")
929 self
.__copy
_boot
_file
(isodir
+ "/ppc", "bootinfo.txt")
930 self
.__copy
_boot
_file
(isodir
+ "/ppc/mac", "ofboot.b")
932 shutil
.copyfile(self
._instroot
+ "/usr/lib/yaboot/yaboot",
933 isodir
+ "/ppc/mac/yaboot")
935 makedirs(isodir
+ "/ppc/chrp")
936 shutil
.copyfile(self
._instroot
+ "/usr/lib/yaboot/yaboot",
937 isodir
+ "/ppc/chrp/yaboot")
939 subprocess
.call(["/usr/sbin/addnote", isodir
+ "/ppc/chrp/yaboot"])
942 # FIXME: ppc should support multiple kernels too...
944 kernel
= self
._get
_kernel
_versions
().values()[0][0]
946 kernel_bits
= self
.__kernel
_bits
(kernel
)
948 for (bit
, present
) in kernel_bits
.items():
950 self
.__write
_not
_supported
(isodir
, bit
)
953 isDracut
= self
.__copy
_kernel
_and
_initramfs
(isodir
+ "/ppc/ppc" + bit
, kernel
)
954 self
.__write
_yaboot
_config
(isodir
, bit
, isDracut
)
956 makedirs(isodir
+ "/etc")
957 if kernel_bits
["32"] and not kernel_bits
["64"]:
958 shutil
.copyfile(isodir
+ "/ppc/ppc32/yaboot.conf",
959 isodir
+ "/etc/yaboot.conf")
960 elif kernel_bits
["64"] and not kernel_bits
["32"]:
961 shutil
.copyfile(isodir
+ "/ppc/ppc64/yaboot.conf",
962 isodir
+ "/etc/yaboot.conf")
964 self
.__write
_dualbits
_yaboot
_config
(isodir
,
966 timeout
= self
._timeout
* 100)
969 # FIXME: build 'netboot' images with kernel+initrd, like mk-images.ppc
972 class ppc64LiveImageCreator(ppcLiveImageCreator
):
973 def _get_excluded_packages(self
):
975 # while kernel.ppc and kernel.ppc64 co-exist,
977 return ["kernel.ppc"] + \
978 ppcLiveImageCreator
._get
_excluded
_packages
(self
)
980 arch
= rpmUtils
.arch
.getBaseArch()
981 if arch
in ("i386", "x86_64"):
982 LiveImageCreator
= x86LiveImageCreator
983 elif arch
in ("ppc",):
984 LiveImageCreator
= ppcLiveImageCreator
985 elif arch
in ("ppc64",):
986 LiveImageCreator
= ppc64LiveImageCreator
987 elif arch
.startswith('arm'):
988 LiveImageCreator
= LiveImageCreatorBase
991 raise CreatorError("Architecture not supported!")