summaryrefslogtreecommitdiffstats
path: root/scripts/lib/mic/plugins/imager
diff options
context:
space:
mode:
authorTom Zanussi <tom.zanussi@linux.intel.com>2013-08-24 15:31:34 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-10-01 22:56:03 +0100
commit9fc88f96d40b17c90bac53b90045a87b2d2cff84 (patch)
tree63010e5aabf895697655baf89bd668d6752b3f97 /scripts/lib/mic/plugins/imager
parent53a1d9a788fd9f970af980da2ab975cca60685c4 (diff)
downloadpoky-9fc88f96d40b17c90bac53b90045a87b2d2cff84.tar.gz
wic: Add mic w/pykickstart
This is the starting point for the implemention described in [YOCTO 3847] which came to the conclusion that it would make sense to use kickstart syntax to implement image creation in OpenEmbedded. I subsequently realized that there was an existing tool that already implemented image creation using kickstart syntax, the Tizen/Meego mic tool. As such, it made sense to use that as a starting point - this commit essentially just copies the relevant Python code from the MIC tool to the scripts/lib dir, where it can be accessed by the previously created wic tool. Most of this will be removed or renamed by later commits, since we're initially focusing on partitioning only. Care should be taken so that we can easily add back any additional functionality should we decide later to expand the tool, though (we may also want to contribute our local changes to the mic tool to the Tizen project if it makes sense, and therefore should avoid gratuitous changes to the original code if possible). Added the /mic subdir from Tizen mic repo as a starting point: git clone git://review.tizen.org/tools/mic.git For reference, the top commit: commit 20164175ddc234a17b8a12c33d04b012347b1530 Author: Gui Chen <gui.chen@intel.com> Date: Sun Jun 30 22:32:16 2013 -0400 bump up to 0.19.2 Also added the /plugins subdir, moved to under the /mic subdir (to match the default plugin_dir location in mic.conf.in, which was renamed to yocto-image.conf (moved and renamed by later patches) and put into /scripts. (From OE-Core rev: 31f0360f1fd4ebc9dfcaed42d1c50d2448b4632e) Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Saul Wold <sgw@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/mic/plugins/imager')
-rw-r--r--scripts/lib/mic/plugins/imager/fs_plugin.py143
-rw-r--r--scripts/lib/mic/plugins/imager/livecd_plugin.py255
-rw-r--r--scripts/lib/mic/plugins/imager/liveusb_plugin.py260
-rw-r--r--scripts/lib/mic/plugins/imager/loop_plugin.py255
-rw-r--r--scripts/lib/mic/plugins/imager/raw_plugin.py275
5 files changed, 1188 insertions, 0 deletions
diff --git a/scripts/lib/mic/plugins/imager/fs_plugin.py b/scripts/lib/mic/plugins/imager/fs_plugin.py
new file mode 100644
index 0000000000..8e758db544
--- /dev/null
+++ b/scripts/lib/mic/plugins/imager/fs_plugin.py
@@ -0,0 +1,143 @@
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
18import os
19import sys
20
21from mic import chroot, msger, rt_util
22from mic.utils import cmdln, misc, errors, fs_related
23from mic.imager import fs
24from mic.conf import configmgr
25from mic.plugin import pluginmgr
26
27from mic.pluginbase import ImagerPlugin
28class FsPlugin(ImagerPlugin):
29 name = 'fs'
30
31 @classmethod
32 @cmdln.option("--include-src",
33 dest="include_src",
34 action="store_true",
35 default=False,
36 help="Generate a image with source rpms included")
37 def do_create(self, subcmd, opts, *args):
38 """${cmd_name}: create fs image
39
40 Usage:
41 ${name} ${cmd_name} <ksfile> [OPTS]
42
43 ${cmd_option_list}
44 """
45
46 if len(args) != 1:
47 raise errors.Usage("Extra arguments given")
48
49 creatoropts = configmgr.create
50 ksconf = args[0]
51
52 if creatoropts['runtime'] == 'bootstrap':
53 configmgr._ksconf = ksconf
54 rt_util.bootstrap_mic()
55
56 recording_pkgs = []
57 if len(creatoropts['record_pkgs']) > 0:
58 recording_pkgs = creatoropts['record_pkgs']
59
60 if creatoropts['release'] is not None:
61 if 'name' not in recording_pkgs:
62 recording_pkgs.append('name')
63 if 'vcs' not in recording_pkgs:
64 recording_pkgs.append('vcs')
65
66 configmgr._ksconf = ksconf
67
68 # Called After setting the configmgr._ksconf as the creatoropts['name'] is reset there.
69 if creatoropts['release'] is not None:
70 creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'], creatoropts['release'], creatoropts['name'])
71
72 # try to find the pkgmgr
73 pkgmgr = None
74 backends = pluginmgr.get_plugins('backend')
75 if 'auto' == creatoropts['pkgmgr']:
76 for key in configmgr.prefer_backends:
77 if key in backends:
78 pkgmgr = backends[key]
79 break
80 else:
81 for key in backends.keys():
82 if key == creatoropts['pkgmgr']:
83 pkgmgr = backends[key]
84 break
85
86 if not pkgmgr:
87 raise errors.CreatorError("Can't find backend: %s, "
88 "available choices: %s" %
89 (creatoropts['pkgmgr'],
90 ','.join(backends.keys())))
91
92 creator = fs.FsImageCreator(creatoropts, pkgmgr)
93 creator._include_src = opts.include_src
94
95 if len(recording_pkgs) > 0:
96 creator._recording_pkgs = recording_pkgs
97
98 self.check_image_exists(creator.destdir,
99 creator.pack_to,
100 [creator.name],
101 creatoropts['release'])
102
103 try:
104 creator.check_depend_tools()
105 creator.mount(None, creatoropts["cachedir"])
106 creator.install()
107 #Download the source packages ###private options
108 if opts.include_src:
109 installed_pkgs = creator.get_installed_packages()
110 msger.info('--------------------------------------------------')
111 msger.info('Generating the image with source rpms included ...')
112 if not misc.SrcpkgsDownload(installed_pkgs, creatoropts["repomd"], creator._instroot, creatoropts["cachedir"]):
113 msger.warning("Source packages can't be downloaded")
114
115 creator.configure(creatoropts["repomd"])
116 creator.copy_kernel()
117 creator.unmount()
118 creator.package(creatoropts["outdir"])
119 if creatoropts['release'] is not None:
120 creator.release_output(ksconf, creatoropts['outdir'], creatoropts['release'])
121 creator.print_outimage_info()
122 except errors.CreatorError:
123 raise
124 finally:
125 creator.cleanup()
126
127 msger.info("Finished.")
128 return 0
129
130 @classmethod
131 def do_chroot(self, target, cmd=[]):#chroot.py parse opts&args
132 try:
133 if len(cmd) != 0:
134 cmdline = ' '.join(cmd)
135 else:
136 cmdline = "/bin/bash"
137 envcmd = fs_related.find_binary_inchroot("env", target)
138 if envcmd:
139 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
140 chroot.chroot(target, None, cmdline)
141 finally:
142 chroot.cleanup_after_chroot("dir", None, None, None)
143 return 1
diff --git a/scripts/lib/mic/plugins/imager/livecd_plugin.py b/scripts/lib/mic/plugins/imager/livecd_plugin.py
new file mode 100644
index 0000000000..d24ef59264
--- /dev/null
+++ b/scripts/lib/mic/plugins/imager/livecd_plugin.py
@@ -0,0 +1,255 @@
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
18import os
19import shutil
20import tempfile
21
22from mic import chroot, msger, rt_util
23from mic.utils import misc, fs_related, errors
24from mic.conf import configmgr
25import mic.imager.livecd as livecd
26from mic.plugin import pluginmgr
27
28from mic.pluginbase import ImagerPlugin
29class LiveCDPlugin(ImagerPlugin):
30 name = 'livecd'
31
32 @classmethod
33 def do_create(self, subcmd, opts, *args):
34 """${cmd_name}: create livecd image
35
36 Usage:
37 ${name} ${cmd_name} <ksfile> [OPTS]
38
39 ${cmd_option_list}
40 """
41
42 if len(args) != 1:
43 raise errors.Usage("Extra arguments given")
44
45 creatoropts = configmgr.create
46 ksconf = args[0]
47
48 if creatoropts['runtime'] == 'bootstrap':
49 configmgr._ksconf = ksconf
50 rt_util.bootstrap_mic()
51
52 if creatoropts['arch'] and creatoropts['arch'].startswith('arm'):
53 msger.warning('livecd cannot support arm images, Quit')
54 return
55
56 recording_pkgs = []
57 if len(creatoropts['record_pkgs']) > 0:
58 recording_pkgs = creatoropts['record_pkgs']
59
60 if creatoropts['release'] is not None:
61 if 'name' not in recording_pkgs:
62 recording_pkgs.append('name')
63 if 'vcs' not in recording_pkgs:
64 recording_pkgs.append('vcs')
65
66 configmgr._ksconf = ksconf
67
68 # Called After setting the configmgr._ksconf as the creatoropts['name'] is reset there.
69 if creatoropts['release'] is not None:
70 creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'], creatoropts['release'], creatoropts['name'])
71
72 # try to find the pkgmgr
73 pkgmgr = None
74 backends = pluginmgr.get_plugins('backend')
75 if 'auto' == creatoropts['pkgmgr']:
76 for key in configmgr.prefer_backends:
77 if key in backends:
78 pkgmgr = backends[key]
79 break
80 else:
81 for key in backends.keys():
82 if key == creatoropts['pkgmgr']:
83 pkgmgr = backends[key]
84 break
85
86 if not pkgmgr:
87 raise errors.CreatorError("Can't find backend: %s, "
88 "available choices: %s" %
89 (creatoropts['pkgmgr'],
90 ','.join(backends.keys())))
91
92 creator = livecd.LiveCDImageCreator(creatoropts, pkgmgr)
93
94 if len(recording_pkgs) > 0:
95 creator._recording_pkgs = recording_pkgs
96
97 self.check_image_exists(creator.destdir,
98 creator.pack_to,
99 [creator.name + ".iso"],
100 creatoropts['release'])
101
102 try:
103 creator.check_depend_tools()
104 creator.mount(None, creatoropts["cachedir"])
105 creator.install()
106 creator.configure(creatoropts["repomd"])
107 creator.copy_kernel()
108 creator.unmount()
109 creator.package(creatoropts["outdir"])
110 if creatoropts['release'] is not None:
111 creator.release_output(ksconf, creatoropts['outdir'], creatoropts['release'])
112 creator.print_outimage_info()
113
114 except errors.CreatorError:
115 raise
116 finally:
117 creator.cleanup()
118
119 msger.info("Finished.")
120 return 0
121
122 @classmethod
123 def do_chroot(cls, target, cmd=[]):
124 os_image = cls.do_unpack(target)
125 os_image_dir = os.path.dirname(os_image)
126
127 # unpack image to target dir
128 imgsize = misc.get_file_size(os_image) * 1024L * 1024L
129 imgtype = misc.get_image_type(os_image)
130 if imgtype == "btrfsimg":
131 fstype = "btrfs"
132 myDiskMount = fs_related.BtrfsDiskMount
133 elif imgtype in ("ext3fsimg", "ext4fsimg"):
134 fstype = imgtype[:4]
135 myDiskMount = fs_related.ExtDiskMount
136 else:
137 raise errors.CreatorError("Unsupported filesystem type: %s" % fstype)
138
139 extmnt = misc.mkdtemp()
140 extloop = myDiskMount(fs_related.SparseLoopbackDisk(os_image, imgsize),
141 extmnt,
142 fstype,
143 4096,
144 "%s label" % fstype)
145 try:
146 extloop.mount()
147
148 except errors.MountError:
149 extloop.cleanup()
150 shutil.rmtree(extmnt, ignore_errors = True)
151 shutil.rmtree(os_image_dir, ignore_errors = True)
152 raise
153
154 try:
155 if len(cmd) != 0:
156 cmdline = ' '.join(cmd)
157 else:
158 cmdline = "/bin/bash"
159 envcmd = fs_related.find_binary_inchroot("env", extmnt)
160 if envcmd:
161 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
162 chroot.chroot(extmnt, None, cmdline)
163 except:
164 raise errors.CreatorError("Failed to chroot to %s." %target)
165 finally:
166 chroot.cleanup_after_chroot("img", extloop, os_image_dir, extmnt)
167
168 @classmethod
169 def do_pack(cls, base_on):
170 import subprocess
171
172 def __mkinitrd(instance):
173 kernelver = instance._get_kernel_versions().values()[0][0]
174 args = [ "/usr/libexec/mkliveinitrd", "/boot/initrd-%s.img" % kernelver, "%s" % kernelver ]
175 try:
176 subprocess.call(args, preexec_fn = instance._chroot)
177 except OSError, (err, msg):
178 raise errors.CreatorError("Failed to execute /usr/libexec/mkliveinitrd: %s" % msg)
179
180 def __run_post_cleanups(instance):
181 kernelver = instance._get_kernel_versions().values()[0][0]
182 args = ["rm", "-f", "/boot/initrd-%s.img" % kernelver]
183
184 try:
185 subprocess.call(args, preexec_fn = instance._chroot)
186 except OSError, (err, msg):
187 raise errors.CreatorError("Failed to run post cleanups: %s" % msg)
188
189 convertoropts = configmgr.convert
190 convertoropts['name'] = os.path.splitext(os.path.basename(base_on))[0]
191 convertor = livecd.LiveCDImageCreator(convertoropts)
192 imgtype = misc.get_image_type(base_on)
193 if imgtype == "btrfsimg":
194 fstype = "btrfs"
195 elif imgtype in ("ext3fsimg", "ext4fsimg"):
196 fstype = imgtype[:4]
197 else:
198 raise errors.CreatorError("Unsupported filesystem type: %s" % fstype)
199 convertor._set_fstype(fstype)
200 try:
201 convertor.mount(base_on)
202 __mkinitrd(convertor)
203 convertor._create_bootconfig()
204 __run_post_cleanups(convertor)
205 convertor.launch_shell(convertoropts['shell'])
206 convertor.unmount()
207 convertor.package()
208 convertor.print_outimage_info()
209 finally:
210 shutil.rmtree(os.path.dirname(base_on), ignore_errors = True)
211
212 @classmethod
213 def do_unpack(cls, srcimg):
214 img = srcimg
215 imgmnt = misc.mkdtemp()
216 imgloop = fs_related.DiskMount(fs_related.LoopbackDisk(img, 0), imgmnt)
217 try:
218 imgloop.mount()
219 except errors.MountError:
220 imgloop.cleanup()
221 raise
222
223 # legacy LiveOS filesystem layout support, remove for F9 or F10
224 if os.path.exists(imgmnt + "/squashfs.img"):
225 squashimg = imgmnt + "/squashfs.img"
226 else:
227 squashimg = imgmnt + "/LiveOS/squashfs.img"
228
229 tmpoutdir = misc.mkdtemp()
230 # unsquashfs requires outdir mustn't exist
231 shutil.rmtree(tmpoutdir, ignore_errors = True)
232 misc.uncompress_squashfs(squashimg, tmpoutdir)
233
234 try:
235 # legacy LiveOS filesystem layout support, remove for F9 or F10
236 if os.path.exists(tmpoutdir + "/os.img"):
237 os_image = tmpoutdir + "/os.img"
238 else:
239 os_image = tmpoutdir + "/LiveOS/ext3fs.img"
240
241 if not os.path.exists(os_image):
242 raise errors.CreatorError("'%s' is not a valid live CD ISO : neither "
243 "LiveOS/ext3fs.img nor os.img exist" %img)
244
245 imgname = os.path.basename(srcimg)
246 imgname = os.path.splitext(imgname)[0] + ".img"
247 rtimage = os.path.join(tempfile.mkdtemp(dir = "/var/tmp", prefix = "tmp"), imgname)
248 shutil.copyfile(os_image, rtimage)
249
250 finally:
251 imgloop.cleanup()
252 shutil.rmtree(tmpoutdir, ignore_errors = True)
253 shutil.rmtree(imgmnt, ignore_errors = True)
254
255 return rtimage
diff --git a/scripts/lib/mic/plugins/imager/liveusb_plugin.py b/scripts/lib/mic/plugins/imager/liveusb_plugin.py
new file mode 100644
index 0000000000..7aa8927df9
--- /dev/null
+++ b/scripts/lib/mic/plugins/imager/liveusb_plugin.py
@@ -0,0 +1,260 @@
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
18import os
19import shutil
20import tempfile
21
22from mic import chroot, msger, rt_util
23from mic.utils import misc, fs_related, errors
24from mic.utils.partitionedfs import PartitionedMount
25from mic.conf import configmgr
26from mic.plugin import pluginmgr
27
28import mic.imager.liveusb as liveusb
29
30from mic.pluginbase import ImagerPlugin
31class LiveUSBPlugin(ImagerPlugin):
32 name = 'liveusb'
33
34 @classmethod
35 def do_create(self, subcmd, opts, *args):
36 """${cmd_name}: create liveusb image
37
38 Usage:
39 ${name} ${cmd_name} <ksfile> [OPTS]
40
41 ${cmd_option_list}
42 """
43
44 if len(args) != 1:
45 raise errors.Usage("Extra arguments given")
46
47 creatoropts = configmgr.create
48 ksconf = args[0]
49
50 if creatoropts['runtime'] == "bootstrap":
51 configmgr._ksconf = ksconf
52 rt_util.bootstrap_mic()
53
54 if creatoropts['arch'] and creatoropts['arch'].startswith('arm'):
55 msger.warning('liveusb cannot support arm images, Quit')
56 return
57
58 recording_pkgs = []
59 if len(creatoropts['record_pkgs']) > 0:
60 recording_pkgs = creatoropts['record_pkgs']
61
62 if creatoropts['release'] is not None:
63 if 'name' not in recording_pkgs:
64 recording_pkgs.append('name')
65 if 'vcs' not in recording_pkgs:
66 recording_pkgs.append('vcs')
67
68 configmgr._ksconf = ksconf
69
70 # Called After setting the configmgr._ksconf as the creatoropts['name'] is reset there.
71 if creatoropts['release'] is not None:
72 creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'], creatoropts['release'], creatoropts['name'])
73
74 # try to find the pkgmgr
75 pkgmgr = None
76 backends = pluginmgr.get_plugins('backend')
77 if 'auto' == creatoropts['pkgmgr']:
78 for key in configmgr.prefer_backends:
79 if key in backends:
80 pkgmgr = backends[key]
81 break
82 else:
83 for key in backends.keys():
84 if key == creatoropts['pkgmgr']:
85 pkgmgr = backends[key]
86 break
87
88 if not pkgmgr:
89 raise errors.CreatorError("Can't find backend: %s, "
90 "available choices: %s" %
91 (creatoropts['pkgmgr'],
92 ','.join(backends.keys())))
93
94 creator = liveusb.LiveUSBImageCreator(creatoropts, pkgmgr)
95
96 if len(recording_pkgs) > 0:
97 creator._recording_pkgs = recording_pkgs
98
99 self.check_image_exists(creator.destdir,
100 creator.pack_to,
101 [creator.name + ".usbimg"],
102 creatoropts['release'])
103 try:
104 creator.check_depend_tools()
105 creator.mount(None, creatoropts["cachedir"])
106 creator.install()
107 creator.configure(creatoropts["repomd"])
108 creator.copy_kernel()
109 creator.unmount()
110 creator.package(creatoropts["outdir"])
111 if creatoropts['release'] is not None:
112 creator.release_output(ksconf, creatoropts['outdir'], creatoropts['release'])
113 creator.print_outimage_info()
114
115 except errors.CreatorError:
116 raise
117 finally:
118 creator.cleanup()
119
120 msger.info("Finished.")
121 return 0
122
123 @classmethod
124 def do_chroot(cls, target, cmd=[]):
125 os_image = cls.do_unpack(target)
126 os_image_dir = os.path.dirname(os_image)
127
128 # unpack image to target dir
129 imgsize = misc.get_file_size(os_image) * 1024L * 1024L
130 imgtype = misc.get_image_type(os_image)
131 if imgtype == "btrfsimg":
132 fstype = "btrfs"
133 myDiskMount = fs_related.BtrfsDiskMount
134 elif imgtype in ("ext3fsimg", "ext4fsimg"):
135 fstype = imgtype[:4]
136 myDiskMount = fs_related.ExtDiskMount
137 else:
138 raise errors.CreatorError("Unsupported filesystem type: %s" % fstype)
139
140 extmnt = misc.mkdtemp()
141 extloop = myDiskMount(fs_related.SparseLoopbackDisk(os_image, imgsize),
142 extmnt,
143 fstype,
144 4096,
145 "%s label" % fstype)
146
147 try:
148 extloop.mount()
149
150 except errors.MountError:
151 extloop.cleanup()
152 shutil.rmtree(extmnt, ignore_errors = True)
153 raise
154
155 try:
156 if len(cmd) != 0:
157 cmdline = ' '.join(cmd)
158 else:
159 cmdline = "/bin/bash"
160 envcmd = fs_related.find_binary_inchroot("env", extmnt)
161 if envcmd:
162 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
163 chroot.chroot(extmnt, None, cmdline)
164 except:
165 raise errors.CreatorError("Failed to chroot to %s." %target)
166 finally:
167 chroot.cleanup_after_chroot("img", extloop, os_image_dir, extmnt)
168
169 @classmethod
170 def do_pack(cls, base_on):
171 import subprocess
172
173 def __mkinitrd(instance):
174 kernelver = instance._get_kernel_versions().values()[0][0]
175 args = [ "/usr/libexec/mkliveinitrd", "/boot/initrd-%s.img" % kernelver, "%s" % kernelver ]
176 try:
177 subprocess.call(args, preexec_fn = instance._chroot)
178
179 except OSError, (err, msg):
180 raise errors.CreatorError("Failed to execute /usr/libexec/mkliveinitrd: %s" % msg)
181
182 def __run_post_cleanups(instance):
183 kernelver = instance._get_kernel_versions().values()[0][0]
184 args = ["rm", "-f", "/boot/initrd-%s.img" % kernelver]
185
186 try:
187 subprocess.call(args, preexec_fn = instance._chroot)
188 except OSError, (err, msg):
189 raise errors.CreatorError("Failed to run post cleanups: %s" % msg)
190
191 convertoropts = configmgr.convert
192 convertoropts['name'] = os.path.splitext(os.path.basename(base_on))[0]
193 convertor = liveusb.LiveUSBImageCreator(convertoropts)
194 imgtype = misc.get_image_type(base_on)
195 if imgtype == "btrfsimg":
196 fstype = "btrfs"
197 elif imgtype in ("ext3fsimg", "ext4fsimg"):
198 fstype = imgtype[:4]
199 else:
200 raise errors.CreatorError("Unsupported filesystem type: %s" % fstyp)
201 convertor._set_fstype(fstype)
202 try:
203 convertor.mount(base_on)
204 __mkinitrd(convertor)
205 convertor._create_bootconfig()
206 __run_post_cleanups(convertor)
207 convertor.launch_shell(convertoropts['shell'])
208 convertor.unmount()
209 convertor.package()
210 convertor.print_outimage_info()
211 finally:
212 shutil.rmtree(os.path.dirname(base_on), ignore_errors = True)
213
214 @classmethod
215 def do_unpack(cls, srcimg):
216 img = srcimg
217 imgsize = misc.get_file_size(img) * 1024L * 1024L
218 imgmnt = misc.mkdtemp()
219 disk = fs_related.SparseLoopbackDisk(img, imgsize)
220 imgloop = PartitionedMount(imgmnt, skipformat = True)
221 imgloop.add_disk('/dev/sdb', disk)
222 imgloop.add_partition(imgsize/1024/1024, "/dev/sdb", "/", "vfat", boot=False)
223 try:
224 imgloop.mount()
225 except errors.MountError:
226 imgloop.cleanup()
227 raise
228
229 # legacy LiveOS filesystem layout support, remove for F9 or F10
230 if os.path.exists(imgmnt + "/squashfs.img"):
231 squashimg = imgmnt + "/squashfs.img"
232 else:
233 squashimg = imgmnt + "/LiveOS/squashfs.img"
234
235 tmpoutdir = misc.mkdtemp()
236 # unsquashfs requires outdir mustn't exist
237 shutil.rmtree(tmpoutdir, ignore_errors = True)
238 misc.uncompress_squashfs(squashimg, tmpoutdir)
239
240 try:
241 # legacy LiveOS filesystem layout support, remove for F9 or F10
242 if os.path.exists(tmpoutdir + "/os.img"):
243 os_image = tmpoutdir + "/os.img"
244 else:
245 os_image = tmpoutdir + "/LiveOS/ext3fs.img"
246
247 if not os.path.exists(os_image):
248 raise errors.CreatorError("'%s' is not a valid live CD ISO : neither "
249 "LiveOS/ext3fs.img nor os.img exist" %img)
250 imgname = os.path.basename(srcimg)
251 imgname = os.path.splitext(imgname)[0] + ".img"
252 rtimage = os.path.join(tempfile.mkdtemp(dir = "/var/tmp", prefix = "tmp"), imgname)
253 shutil.copyfile(os_image, rtimage)
254
255 finally:
256 imgloop.cleanup()
257 shutil.rmtree(tmpoutdir, ignore_errors = True)
258 shutil.rmtree(imgmnt, ignore_errors = True)
259
260 return rtimage
diff --git a/scripts/lib/mic/plugins/imager/loop_plugin.py b/scripts/lib/mic/plugins/imager/loop_plugin.py
new file mode 100644
index 0000000000..8f4b030f6b
--- /dev/null
+++ b/scripts/lib/mic/plugins/imager/loop_plugin.py
@@ -0,0 +1,255 @@
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
18import os
19import shutil
20import tempfile
21
22from mic import chroot, msger, rt_util
23from mic.utils import misc, fs_related, errors, cmdln
24from mic.conf import configmgr
25from mic.plugin import pluginmgr
26from mic.imager.loop import LoopImageCreator, load_mountpoints
27
28from mic.pluginbase import ImagerPlugin
29class LoopPlugin(ImagerPlugin):
30 name = 'loop'
31
32 @classmethod
33 @cmdln.option("--compress-disk-image", dest="compress_image",
34 type='choice', choices=("gz", "bz2"), default=None,
35 help="Same with --compress-image")
36 # alias to compress-image for compatibility
37 @cmdln.option("--compress-image", dest="compress_image",
38 type='choice', choices=("gz", "bz2"), default=None,
39 help="Compress all loop images with 'gz' or 'bz2'")
40 @cmdln.option("--shrink", action='store_true', default=False,
41 help="Whether to shrink loop images to minimal size")
42 def do_create(self, subcmd, opts, *args):
43 """${cmd_name}: create loop image
44
45 Usage:
46 ${name} ${cmd_name} <ksfile> [OPTS]
47
48 ${cmd_option_list}
49 """
50
51 if len(args) != 1:
52 raise errors.Usage("Extra arguments given")
53
54 creatoropts = configmgr.create
55 ksconf = args[0]
56
57 if creatoropts['runtime'] == "bootstrap":
58 configmgr._ksconf = ksconf
59 rt_util.bootstrap_mic()
60
61 recording_pkgs = []
62 if len(creatoropts['record_pkgs']) > 0:
63 recording_pkgs = creatoropts['record_pkgs']
64
65 if creatoropts['release'] is not None:
66 if 'name' not in recording_pkgs:
67 recording_pkgs.append('name')
68 if 'vcs' not in recording_pkgs:
69 recording_pkgs.append('vcs')
70
71 configmgr._ksconf = ksconf
72
73 # Called After setting the configmgr._ksconf
74 # as the creatoropts['name'] is reset there.
75 if creatoropts['release'] is not None:
76 creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'],
77 creatoropts['release'],
78 creatoropts['name'])
79 # try to find the pkgmgr
80 pkgmgr = None
81 backends = pluginmgr.get_plugins('backend')
82 if 'auto' == creatoropts['pkgmgr']:
83 for key in configmgr.prefer_backends:
84 if key in backends:
85 pkgmgr = backends[key]
86 break
87 else:
88 for key in backends.keys():
89 if key == creatoropts['pkgmgr']:
90 pkgmgr = backends[key]
91 break
92
93 if not pkgmgr:
94 raise errors.CreatorError("Can't find backend: %s, "
95 "available choices: %s" %
96 (creatoropts['pkgmgr'],
97 ','.join(backends.keys())))
98
99 creator = LoopImageCreator(creatoropts,
100 pkgmgr,
101 opts.compress_image,
102 opts.shrink)
103
104 if len(recording_pkgs) > 0:
105 creator._recording_pkgs = recording_pkgs
106
107 image_names = [creator.name + ".img"]
108 image_names.extend(creator.get_image_names())
109 self.check_image_exists(creator.destdir,
110 creator.pack_to,
111 image_names,
112 creatoropts['release'])
113
114 try:
115 creator.check_depend_tools()
116 creator.mount(None, creatoropts["cachedir"])
117 creator.install()
118 creator.configure(creatoropts["repomd"])
119 creator.copy_kernel()
120 creator.unmount()
121 creator.package(creatoropts["outdir"])
122
123 if creatoropts['release'] is not None:
124 creator.release_output(ksconf,
125 creatoropts['outdir'],
126 creatoropts['release'])
127 creator.print_outimage_info()
128
129 except errors.CreatorError:
130 raise
131 finally:
132 creator.cleanup()
133
134 msger.info("Finished.")
135 return 0
136
137 @classmethod
138 def _do_chroot_tar(cls, target, cmd=[]):
139 mountfp_xml = os.path.splitext(target)[0] + '.xml'
140 if not os.path.exists(mountfp_xml):
141 raise errors.CreatorError("No mount point file found for this tar "
142 "image, please check %s" % mountfp_xml)
143
144 import tarfile
145 tar = tarfile.open(target, 'r')
146 tmpdir = misc.mkdtemp()
147 tar.extractall(path=tmpdir)
148 tar.close()
149
150 mntdir = misc.mkdtemp()
151
152 loops = []
153 for (mp, label, name, size, fstype) in load_mountpoints(mountfp_xml):
154 if fstype in ("ext2", "ext3", "ext4"):
155 myDiskMount = fs_related.ExtDiskMount
156 elif fstype == "btrfs":
157 myDiskMount = fs_related.BtrfsDiskMount
158 elif fstype in ("vfat", "msdos"):
159 myDiskMount = fs_related.VfatDiskMount
160 else:
161 msger.error("Cannot support fstype: %s" % fstype)
162
163 name = os.path.join(tmpdir, name)
164 size = size * 1024L * 1024L
165 loop = myDiskMount(fs_related.SparseLoopbackDisk(name, size),
166 os.path.join(mntdir, mp.lstrip('/')),
167 fstype, size, label)
168
169 try:
170 msger.verbose("Mount %s to %s" % (mp, mntdir + mp))
171 fs_related.makedirs(os.path.join(mntdir, mp.lstrip('/')))
172 loop.mount()
173
174 except:
175 loop.cleanup()
176 for lp in reversed(loops):
177 chroot.cleanup_after_chroot("img", lp, None, mntdir)
178
179 shutil.rmtree(tmpdir, ignore_errors=True)
180 raise
181
182 loops.append(loop)
183
184 try:
185 if len(cmd) != 0:
186 cmdline = "/usr/bin/env HOME=/root " + ' '.join(cmd)
187 else:
188 cmdline = "/usr/bin/env HOME=/root /bin/bash"
189 chroot.chroot(mntdir, None, cmdline)
190 except:
191 raise errors.CreatorError("Failed to chroot to %s." % target)
192 finally:
193 for loop in reversed(loops):
194 chroot.cleanup_after_chroot("img", loop, None, mntdir)
195
196 shutil.rmtree(tmpdir, ignore_errors=True)
197
198 @classmethod
199 def do_chroot(cls, target, cmd=[]):
200 if target.endswith('.tar'):
201 import tarfile
202 if tarfile.is_tarfile(target):
203 LoopPlugin._do_chroot_tar(target, cmd)
204 return
205 else:
206 raise errors.CreatorError("damaged tarball for loop images")
207
208 img = target
209 imgsize = misc.get_file_size(img) * 1024L * 1024L
210 imgtype = misc.get_image_type(img)
211 if imgtype == "btrfsimg":
212 fstype = "btrfs"
213 myDiskMount = fs_related.BtrfsDiskMount
214 elif imgtype in ("ext3fsimg", "ext4fsimg"):
215 fstype = imgtype[:4]
216 myDiskMount = fs_related.ExtDiskMount
217 else:
218 raise errors.CreatorError("Unsupported filesystem type: %s" \
219 % imgtype)
220
221 extmnt = misc.mkdtemp()
222 extloop = myDiskMount(fs_related.SparseLoopbackDisk(img, imgsize),
223 extmnt,
224 fstype,
225 4096,
226 "%s label" % fstype)
227 try:
228 extloop.mount()
229
230 except errors.MountError:
231 extloop.cleanup()
232 shutil.rmtree(extmnt, ignore_errors=True)
233 raise
234
235 try:
236 if len(cmd) != 0:
237 cmdline = ' '.join(cmd)
238 else:
239 cmdline = "/bin/bash"
240 envcmd = fs_related.find_binary_inchroot("env", extmnt)
241 if envcmd:
242 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
243 chroot.chroot(extmnt, None, cmdline)
244 except:
245 raise errors.CreatorError("Failed to chroot to %s." % img)
246 finally:
247 chroot.cleanup_after_chroot("img", extloop, None, extmnt)
248
249 @classmethod
250 def do_unpack(cls, srcimg):
251 image = os.path.join(tempfile.mkdtemp(dir="/var/tmp", prefix="tmp"),
252 "target.img")
253 msger.info("Copying file system ...")
254 shutil.copyfile(srcimg, image)
255 return image
diff --git a/scripts/lib/mic/plugins/imager/raw_plugin.py b/scripts/lib/mic/plugins/imager/raw_plugin.py
new file mode 100644
index 0000000000..1b9631dfa2
--- /dev/null
+++ b/scripts/lib/mic/plugins/imager/raw_plugin.py
@@ -0,0 +1,275 @@
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
18import os
19import shutil
20import re
21import tempfile
22
23from mic import chroot, msger, rt_util
24from mic.utils import misc, fs_related, errors, runner, cmdln
25from mic.conf import configmgr
26from mic.plugin import pluginmgr
27from mic.utils.partitionedfs import PartitionedMount
28
29import mic.imager.raw as raw
30
31from mic.pluginbase import ImagerPlugin
32class RawPlugin(ImagerPlugin):
33 name = 'raw'
34
35 @classmethod
36 @cmdln.option("--compress-disk-image", dest="compress_image", type='choice',
37 choices=("gz", "bz2"), default=None,
38 help="Same with --compress-image")
39 @cmdln.option("--compress-image", dest="compress_image", type='choice',
40 choices=("gz", "bz2"), default = None,
41 help="Compress all raw images before package")
42 @cmdln.option("--generate-bmap", action="store_true", default = None,
43 help="also generate the block map file")
44 @cmdln.option("--fstab-entry", dest="fstab_entry", type='choice',
45 choices=("name", "uuid"), default="uuid",
46 help="Set fstab entry, 'name' means using device names, "
47 "'uuid' means using filesystem uuid")
48 def do_create(self, subcmd, opts, *args):
49 """${cmd_name}: create raw image
50
51 Usage:
52 ${name} ${cmd_name} <ksfile> [OPTS]
53
54 ${cmd_option_list}
55 """
56
57 if len(args) != 1:
58 raise errors.Usage("Extra arguments given")
59
60 creatoropts = configmgr.create
61 ksconf = args[0]
62
63 if creatoropts['runtime'] == "bootstrap":
64 configmgr._ksconf = ksconf
65 rt_util.bootstrap_mic()
66
67 recording_pkgs = []
68 if len(creatoropts['record_pkgs']) > 0:
69 recording_pkgs = creatoropts['record_pkgs']
70
71 if creatoropts['release'] is not None:
72 if 'name' not in recording_pkgs:
73 recording_pkgs.append('name')
74 if 'vcs' not in recording_pkgs:
75 recording_pkgs.append('vcs')
76
77 configmgr._ksconf = ksconf
78
79 # Called After setting the configmgr._ksconf as the creatoropts['name'] is reset there.
80 if creatoropts['release'] is not None:
81 creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'], creatoropts['release'], creatoropts['name'])
82
83 # try to find the pkgmgr
84 pkgmgr = None
85 backends = pluginmgr.get_plugins('backend')
86 if 'auto' == creatoropts['pkgmgr']:
87 for key in configmgr.prefer_backends:
88 if key in backends:
89 pkgmgr = backends[key]
90 break
91 else:
92 for key in backends.keys():
93 if key == creatoropts['pkgmgr']:
94 pkgmgr = backends[key]
95 break
96
97 if not pkgmgr:
98 raise errors.CreatorError("Can't find backend: %s, "
99 "available choices: %s" %
100 (creatoropts['pkgmgr'],
101 ','.join(backends.keys())))
102
103 creator = raw.RawImageCreator(creatoropts, pkgmgr, opts.compress_image,
104 opts.generate_bmap, opts.fstab_entry)
105
106 if len(recording_pkgs) > 0:
107 creator._recording_pkgs = recording_pkgs
108
109 images = ["%s-%s.raw" % (creator.name, disk_name)
110 for disk_name in creator.get_disk_names()]
111 self.check_image_exists(creator.destdir,
112 creator.pack_to,
113 images,
114 creatoropts['release'])
115
116 try:
117 creator.check_depend_tools()
118 creator.mount(None, creatoropts["cachedir"])
119 creator.install()
120 creator.configure(creatoropts["repomd"])
121 creator.copy_kernel()
122 creator.unmount()
123 creator.generate_bmap()
124 creator.package(creatoropts["outdir"])
125 if creatoropts['release'] is not None:
126 creator.release_output(ksconf, creatoropts['outdir'], creatoropts['release'])
127 creator.print_outimage_info()
128
129 except errors.CreatorError:
130 raise
131 finally:
132 creator.cleanup()
133
134 msger.info("Finished.")
135 return 0
136
137 @classmethod
138 def do_chroot(cls, target, cmd=[]):
139 img = target
140 imgsize = misc.get_file_size(img) * 1024L * 1024L
141 partedcmd = fs_related.find_binary_path("parted")
142 disk = fs_related.SparseLoopbackDisk(img, imgsize)
143 imgmnt = misc.mkdtemp()
144 imgloop = PartitionedMount(imgmnt, skipformat = True)
145 imgloop.add_disk('/dev/sdb', disk)
146 img_fstype = "ext3"
147
148 msger.info("Partition Table:")
149 partnum = []
150 for line in runner.outs([partedcmd, "-s", img, "print"]).splitlines():
151 # no use strip to keep line output here
152 if "Number" in line:
153 msger.raw(line)
154 if line.strip() and line.strip()[0].isdigit():
155 partnum.append(line.strip()[0])
156 msger.raw(line)
157
158 rootpart = None
159 if len(partnum) > 1:
160 rootpart = msger.choice("please choose root partition", partnum)
161
162 # Check the partitions from raw disk.
163 # if choose root part, the mark it as mounted
164 if rootpart:
165 root_mounted = True
166 else:
167 root_mounted = False
168 partition_mounts = 0
169 for line in runner.outs([partedcmd,"-s",img,"unit","B","print"]).splitlines():
170 line = line.strip()
171
172 # Lines that start with number are the partitions,
173 # because parted can be translated we can't refer to any text lines.
174 if not line or not line[0].isdigit():
175 continue
176
177 # Some vars have extra , as list seperator.
178 line = line.replace(",","")
179
180 # Example of parted output lines that are handled:
181 # Number Start End Size Type File system Flags
182 # 1 512B 3400000511B 3400000000B primary
183 # 2 3400531968B 3656384511B 255852544B primary linux-swap(v1)
184 # 3 3656384512B 3720347647B 63963136B primary fat16 boot, lba
185
186 partition_info = re.split("\s+",line)
187
188 size = partition_info[3].split("B")[0]
189
190 if len(partition_info) < 6 or partition_info[5] in ["boot"]:
191 # No filesystem can be found from partition line. Assuming
192 # btrfs, because that is the only MeeGo fs that parted does
193 # not recognize properly.
194 # TODO: Can we make better assumption?
195 fstype = "btrfs"
196 elif partition_info[5] in ["ext2","ext3","ext4","btrfs"]:
197 fstype = partition_info[5]
198 elif partition_info[5] in ["fat16","fat32"]:
199 fstype = "vfat"
200 elif "swap" in partition_info[5]:
201 fstype = "swap"
202 else:
203 raise errors.CreatorError("Could not recognize partition fs type '%s'." % partition_info[5])
204
205 if rootpart and rootpart == line[0]:
206 mountpoint = '/'
207 elif not root_mounted and fstype in ["ext2","ext3","ext4","btrfs"]:
208 # TODO: Check that this is actually the valid root partition from /etc/fstab
209 mountpoint = "/"
210 root_mounted = True
211 elif fstype == "swap":
212 mountpoint = "swap"
213 else:
214 # TODO: Assing better mount points for the rest of the partitions.
215 partition_mounts += 1
216 mountpoint = "/media/partition_%d" % partition_mounts
217
218 if "boot" in partition_info:
219 boot = True
220 else:
221 boot = False
222
223 msger.verbose("Size: %s Bytes, fstype: %s, mountpoint: %s, boot: %s" % (size, fstype, mountpoint, boot))
224 # TODO: add_partition should take bytes as size parameter.
225 imgloop.add_partition((int)(size)/1024/1024, "/dev/sdb", mountpoint, fstype = fstype, boot = boot)
226
227 try:
228 imgloop.mount()
229
230 except errors.MountError:
231 imgloop.cleanup()
232 raise
233
234 try:
235 if len(cmd) != 0:
236 cmdline = ' '.join(cmd)
237 else:
238 cmdline = "/bin/bash"
239 envcmd = fs_related.find_binary_inchroot("env", imgmnt)
240 if envcmd:
241 cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
242 chroot.chroot(imgmnt, None, cmdline)
243 except:
244 raise errors.CreatorError("Failed to chroot to %s." %img)
245 finally:
246 chroot.cleanup_after_chroot("img", imgloop, None, imgmnt)
247
248 @classmethod
249 def do_unpack(cls, srcimg):
250 srcimgsize = (misc.get_file_size(srcimg)) * 1024L * 1024L
251 srcmnt = misc.mkdtemp("srcmnt")
252 disk = fs_related.SparseLoopbackDisk(srcimg, srcimgsize)
253 srcloop = PartitionedMount(srcmnt, skipformat = True)
254
255 srcloop.add_disk('/dev/sdb', disk)
256 srcloop.add_partition(srcimgsize/1024/1024, "/dev/sdb", "/", "ext3", boot=False)
257 try:
258 srcloop.mount()
259
260 except errors.MountError:
261 srcloop.cleanup()
262 raise
263
264 image = os.path.join(tempfile.mkdtemp(dir = "/var/tmp", prefix = "tmp"), "target.img")
265 args = ['dd', "if=%s" % srcloop.partitions[0]['device'], "of=%s" % image]
266
267 msger.info("`dd` image ...")
268 rc = runner.show(args)
269 srcloop.cleanup()
270 shutil.rmtree(os.path.dirname(srcmnt), ignore_errors = True)
271
272 if rc != 0:
273 raise errors.CreatorError("Failed to dd")
274 else:
275 return image