Merge release-0.28.17 from 'tools/mic'
[platform/upstream/mic.git] / plugins / imager / loop_plugin.py
1 #!/usr/bin/python -tt
2 #
3 # Copyright (c) 2011 Intel, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 import os
19 import subprocess
20 import shutil
21 import tempfile
22
23 from mic import chroot, msger, rt_util
24 from mic.utils import misc, fs_related, errors, runner
25 from mic.plugin import pluginmgr
26 from mic.imager.loop import LoopImageCreator, load_mountpoints
27
28 from mic.pluginbase import ImagerPlugin
29 class LoopPlugin(ImagerPlugin):
30     name = 'loop'
31
32     @classmethod
33     def do_create(self, args):
34         """${cmd_name}: create loop image
35         """
36
37         creatoropts, pkgmgr, recording_pkgs = rt_util.prepare_create(args)
38
39         creator = LoopImageCreator(creatoropts,
40                                    pkgmgr,
41                                    args.compress_image,
42                                    args.shrink)
43
44         if len(recording_pkgs) > 0:
45             creator._recording_pkgs = recording_pkgs
46
47         image_names = [creator.name + ".img"]
48         image_names.extend(creator.get_image_names())
49         self.check_image_exists(creator.destdir,
50                                 creator.pack_to,
51                                 image_names,
52                                 creatoropts['release'])
53
54         try:
55             creator.check_depend_tools()
56             creator.mount(None, creatoropts["cachedir"])
57             creator.install()
58             creator.tpkinstall()
59             creator.configure(creatoropts["repomd"])
60             creator.copy_kernel()
61             creator.create_cpio_image()
62             creator.unmount()
63             creator.copy_cpio_image()
64             creator.package(creatoropts["destdir"])
65             creator.create_manifest()
66
67             if creatoropts['release'] is not None:
68                 creator.release_output(args.ksfile,
69                                        creatoropts['destdir'],
70                                        creatoropts['release'])
71             creator.print_outimage_info()
72
73         except errors.CreatorError:
74             raise
75         finally:
76             creator.cleanup()
77
78         #Run script of --run_script after image created
79         if creatoropts['run_script']:
80             cmd = creatoropts['run_script']
81             try:
82                 runner.show(cmd)
83             except OSError as err:
84                 msger.warning(str(err))
85
86         msger.info("Finished.")
87         return 0
88
89     @classmethod
90     def _do_chroot_tar(cls, target, cmd=[]):
91         mountfp_xml = os.path.splitext(target)[0] + '.xml'
92         if not os.path.exists(mountfp_xml):
93             raise errors.CreatorError("No mount point file found for this tar "
94                                       "image, please check %s" % mountfp_xml)
95
96         import tarfile
97         tar = tarfile.open(target, 'r')
98         tmpdir = misc.mkdtemp()
99         tar.extractall(path=tmpdir)
100         tar.close()
101
102         mntdir = misc.mkdtemp()
103
104         loops = []
105         for (mp, label, name, size, fstype) in load_mountpoints(mountfp_xml):
106             if fstype in ("ext2", "ext3", "ext4"):
107                 myDiskMount = fs_related.ExtDiskMount
108             elif fstype == "btrfs":
109                 myDiskMount = fs_related.BtrfsDiskMount
110             elif fstype in ("vfat", "msdos"):
111                 myDiskMount = fs_related.VfatDiskMount
112             else:
113                 raise errors.CreatorError("Cannot support fstype: %s" % fstype)
114
115             name = os.path.join(tmpdir, name)
116             size = size * 1024 * 1024
117             loop = myDiskMount(fs_related.SparseLoopbackDisk(name, size),
118                                os.path.join(mntdir, mp.lstrip('/')),
119                                fstype, size, label)
120
121             try:
122                 msger.verbose("Mount %s to %s" % (mp, mntdir + mp))
123                 fs_related.makedirs(os.path.join(mntdir, mp.lstrip('/')))
124                 loop.mount()
125
126             except:
127                 loop.cleanup()
128                 for lp in reversed(loops):
129                     chroot.cleanup_after_chroot("img", lp, None, mntdir)
130
131                 shutil.rmtree(tmpdir, ignore_errors=True)
132                 raise
133
134             loops.append(loop)
135
136         try:
137             if len(cmd) != 0:
138                 cmdline = "/usr/bin/env HOME=/root " + ' '.join(cmd)
139             else:
140                 cmdline = "/usr/bin/env HOME=/root /bin/bash"
141             chroot.chroot(mntdir, None, cmdline)
142         except:
143             raise errors.CreatorError("Failed to chroot to %s." % target)
144         finally:
145             for loop in reversed(loops):
146                 chroot.cleanup_after_chroot("img", loop, None, mntdir)
147
148             shutil.rmtree(tmpdir, ignore_errors=True)
149
150     @classmethod
151     def do_chroot(cls, target, cmd=[]):
152         if target.endswith('.tar'):
153             import tarfile
154             if tarfile.is_tarfile(target):
155                 LoopPlugin._do_chroot_tar(target, cmd)
156                 return
157             else:
158                 raise errors.CreatorError("damaged tarball for loop images")
159
160         img = target
161         imgsize = misc.get_file_size(img) * 1024 * 1024
162         imgtype = misc.get_image_type(img)
163         if imgtype == "btrfsimg":
164             fstype = "btrfs"
165             myDiskMount = fs_related.BtrfsDiskMount
166         elif imgtype in ("ext3fsimg", "ext4fsimg"):
167             fstype = imgtype[:4]
168             myDiskMount = fs_related.ExtDiskMount
169         elif imgtype == "f2fsimg":
170             fstype = "f2fs"
171             myDiskMount = fs_related.F2fsDiskMount
172         else:
173             raise errors.CreatorError("Unsupported filesystem type: %s" \
174                                       % imgtype)
175
176         extmnt = misc.mkdtemp()
177         extloop = myDiskMount(fs_related.SparseLoopbackDisk(img, imgsize),
178                                                          extmnt,
179                                                          fstype,
180                                                          4096,
181                                                          "%s label" % fstype)
182         try:
183             extloop.mount()
184
185         except errors.MountError:
186             extloop.cleanup()
187             shutil.rmtree(extmnt, ignore_errors=True)
188             raise
189
190         try:
191             if cmd is not None:
192                 cmdline = cmd
193             else:
194                 cmdline = "/bin/bash"
195             envcmd = fs_related.find_binary_inchroot("env", extmnt)
196             if envcmd:
197                 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
198             chroot.chroot(extmnt, None, cmdline)
199         except:
200             raise errors.CreatorError("Failed to chroot to %s." % img)
201         finally:
202             chroot.cleanup_after_chroot("img", extloop, None, extmnt)
203
204     @classmethod
205     def do_unpack(cls, srcimg):
206         image = os.path.join(tempfile.mkdtemp(dir="/var/tmp", prefix="tmp"),
207                              "target.img")
208         msger.info("Copying file system ...")
209         shutil.copyfile(srcimg, image)
210         return image