4d602f189b9a213f7a0e54de1ce2be49a4d60395
[tools/mic.git] / plugins / imager / liveusb_plugin.py
1 #!/usr/bin/python
2 import os.path
3 import sys
4 import subprocess
5 import logging
6 import shutil
7 import tempfile
8
9 from mic.pluginbase.imager_plugin import ImagerPlugin
10 import mic.imager.liveusb as liveusb
11 import mic.utils.misc as misc
12 import mic.utils.fs_related as fs_related
13 import mic.utils.cmdln as cmdln
14 import mic.configmgr as configmgr
15 import mic.pluginmgr as pluginmgr
16 from mic.utils.partitionedfs import PartitionedMount
17 from mic.utils.errors import *
18 import mic.chroot as chroot
19
20 class LiveUSBPlugin(ImagerPlugin):
21     #@cmdln.option
22     @classmethod
23     def do_create(self, subcmd, opts, *args):
24         """${cmd_name}: create liveusb image
25
26         ${cmd_usage}
27         ${cmd_option_list}
28         """
29         if len(args) == 0:
30             return
31         if len(args) == 1:
32             ksconf = args[0]
33         else:
34             raise errors.Usage("Extra arguments given")
35
36
37         cfgmgr = configmgr.getConfigMgr()
38         creatoropts = cfgmgr.create
39         cfgmgr.setProperty("ksconf", args[0])
40         plgmgr = pluginmgr.PluginMgr()
41         plgmgr.loadPlugins()
42
43         for (key, pcls) in plgmgr.getBackendPlugins():
44             if key == creatoropts['pkgmgr']:
45                 pkgmgr = pcls
46
47         creator = liveusb.LiveUSBImageCreator(creatoropts, pkgmgr)
48         try:
49             creator.check_depend_tools()
50             creator.mount(None, creatoropts["cachedir"])
51             creator.install()
52             creator.configure(creatoropts["repomd"])
53             creator.unmount()
54             creator.package(creatoropts["outdir"])
55             outimage = creator.outimage
56             creator.print_outimage_info()
57             outimage = creator.outimage
58         except CreatorError, e:
59             logging.exception(e)
60             raise CreatorError("failed to create image : %s" % e)
61         finally:
62             creator.cleanup()
63             print "Finished."
64         return 0
65
66     @classmethod
67     def do_chroot(cls, target):
68         os_image = cls.do_unpack(target)
69         os_image_dir = os.path.dirname(os_image)
70         #unpack image to target dir
71         imgsize = misc.get_file_size(os_image) * 1024L * 1024L
72         extmnt = misc.mkdtemp()
73         tfstype = "ext3"
74         tlabel = "ext3 label"
75         MyDiskMount = fs_related.ExtDiskMount
76         #if imgcreate.fstype_is_btrfs(os_image):
77         #    tfstype = "btrfs"
78         #    tlabel = "btrfs label"
79         #    MyDiskMount = fs_related.BtrfsDiskMount
80         extloop = MyDiskMount(fs_related.SparseLoopbackDisk(os_image, imgsize),
81                                               extmnt,
82                                               tfstype,
83                                                                                                                            4096,
84                                               tlabel)
85         try:
86             extloop.mount()
87         except MountError, e:
88             extloop.cleanup()
89             shutil.rmtree(extmnt, ignore_errors = True)
90             raise CreatorError("Failed to loopback mount '%s' : %s" %(os_image, e))
91         try:
92             chroot.chroot(extmnt, None,  "/bin/env HOME=/root /bin/bash")
93         except:
94             raise CreatorError("Failed to chroot to %s." %target)
95         finally:
96             chroot.cleanup_after_chroot("img", extloop, os_image_dir, extmnt)
97
98     @classmethod
99     def do_pack(cls, base_on):
100         def __mkinitrd(instance):
101             kernelver = instance._get_kernel_versions().values()[0][0]
102             args = [ "/usr/libexec/mkliveinitrd", "/boot/initrd-%s.img" % kernelver, "%s" % kernelver ]
103             try:
104                 subprocess.call(args, preexec_fn = instance._chroot)
105             except OSError, (err, msg):
106                raise CreatorError("Failed to execute /usr/libexec/mkliveinitrd: %s" % msg)
107
108         def __run_post_cleanups(instance):
109             kernelver = instance._get_kernel_versions().values()[0][0]
110             args = ["rm", "-f", "/boot/initrd-%s.img" % kernelver]
111             try:
112                 subprocess.call(args, preexec_fn = instance._chroot)
113             except OSError, (err, msg):
114                raise CreatorError("Failed to run post cleanups: %s" % msg)
115
116         convertor = liveusb.LiveUSBImageCreator()
117         srcimgsize = (misc.get_file_size(base_on)) * 1024L * 1024L
118         convertor._set_fstype("ext3")
119         convertor._set_image_size(srcimgsize)
120         base_on_dir = os.path.dirname(base_on)
121         convertor._LoopImageCreator__imgdir = base_on_dir
122         convertor.mount()
123         __mkinitrd(convertor)
124         convertor._create_bootconfig()
125         __run_post_cleanups(convertor)
126         convertor.unmount()
127         convertor.package()
128         convertor.print_outimage_info()
129         shutil.rmtree(base_on_dir, ignore_errors = True)
130
131     @classmethod
132     def do_unpack(cls, srcimg):
133         img = srcimg
134         imgsize = misc.get_file_size(img) * 1024L * 1024L
135         imgmnt = misc.mkdtemp()
136         disk = fs_related.SparseLoopbackDisk(img, imgsize)
137         imgloop = PartitionedMount({'/dev/sdb':disk}, imgmnt, skipformat = True)
138         imgloop.add_partition(imgsize/1024/1024, "/dev/sdb", "/", "vfat", boot=False)
139         try:
140             imgloop.mount()
141         except MountError, e:
142             imgloop.cleanup()
143             raise CreatorError("Failed to loopback mount '%s' : %s" %(img, e))
144
145         # legacy LiveOS filesystem layout support, remove for F9 or F10
146         if os.path.exists(imgmnt + "/squashfs.img"):
147             squashimg = imgmnt + "/squashfs.img"
148         else:
149             squashimg = imgmnt + "/LiveOS/squashfs.img"
150
151         tmpoutdir = misc.mkdtemp()
152         # unsquashfs requires outdir mustn't exist
153         shutil.rmtree(tmpoutdir, ignore_errors = True)
154         misc.uncompress_squashfs(squashimg, tmpoutdir)
155
156         try:
157             # legacy LiveOS filesystem layout support, remove for F9 or F10
158             if os.path.exists(tmpoutdir + "/os.img"):
159                 os_image = tmpoutdir + "/os.img"
160             else:
161                 os_image = tmpoutdir + "/LiveOS/ext3fs.img"
162
163             if not os.path.exists(os_image):
164                 raise CreatorError("'%s' is not a valid live CD ISO : neither "
165                                    "LiveOS/ext3fs.img nor os.img exist" %img)
166             rtimage = os.path.join(tempfile.mkdtemp(dir = "/var/tmp", prefix = "tmp"), "target.img")
167             shutil.copyfile(os_image, rtimage)
168         finally:
169             imgloop.cleanup()
170             shutil.rmtree(tmpoutdir, ignore_errors = True)
171             shutil.rmtree(imgmnt, ignore_errors = True)
172
173         return rtimage
174
175 mic_plugin = ["liveusb", LiveUSBPlugin]