summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic/partition.py
diff options
context:
space:
mode:
authorEd Bartosh <ed.bartosh@linux.intel.com>2016-01-14 14:12:51 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-01-18 11:47:05 +0000
commite5e1905c367db00ed73aa2f893e4fa70e4d701fa (patch)
tree9584cb153fa8e84401152f80411ff062cc86dd12 /scripts/lib/wic/partition.py
parent180f17049ea3e8da75c384d3c1e2f9a7ee06f181 (diff)
downloadpoky-e5e1905c367db00ed73aa2f893e4fa70e4d701fa.tar.gz
wic: add partition module
Copied partition-related API from kickstart/custom_commands/partition.py to separate module in preparation for removal of all pykickstart related code. (From OE-Core rev: a915c4cbc33ef0a12546ac0000ecf8aedb6241d5) Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/wic/partition.py')
-rw-r--r--scripts/lib/wic/partition.py410
1 files changed, 410 insertions, 0 deletions
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
new file mode 100644
index 0000000000..9bb1a0ab9a
--- /dev/null
+++ b/scripts/lib/wic/partition.py
@@ -0,0 +1,410 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# Copyright (c) 2013-2016 Intel Corporation.
5# All rights reserved.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# DESCRIPTION
21# This module provides the OpenEmbedded partition object definitions.
22#
23# AUTHORS
24# Tom Zanussi <tom.zanussi (at] linux.intel.com>
25# Ed Bartosh <ed.bartosh> (at] linux.intel.com>
26
27import os
28import tempfile
29import uuid
30
31from wic.utils.oe.misc import msger, parse_sourceparams
32from wic.utils.oe.misc import exec_cmd, exec_native_cmd
33from wic.plugin import pluginmgr
34
35partition_methods = {
36 "do_stage_partition":None,
37 "do_prepare_partition":None,
38 "do_configure_partition":None,
39}
40
41class Partition(object):
42
43 def __init__(self, args, lineno):
44 self.args = args
45 self.active = args.active
46 self.align = args.align
47 self.disk = args.disk
48 self.extra_space = args.extra_space
49 self.fsopts = args.fsopts
50 self.fstype = args.fstype
51 self.label = args.label
52 self.mountpoint = args.mountpoint
53 self.no_table = args.no_table
54 self.overhead_factor = args.overhead_factor
55 self.part_type = args.part_type
56 self.rootfs_dir = args.rootfs_dir
57 self.size = args.size
58 self.source = args.source
59 self.sourceparams = args.sourceparams
60 self.uuid = args.uuid
61
62 self.lineno = lineno
63 self.source_file = ""
64 self.sourceparams_dict = {}
65
66 def get_extra_block_count(self, current_blocks):
67 """
68 The --size param is reflected in self.size (in kB), and we already
69 have current_blocks (1k) blocks, calculate and return the
70 number of (1k) blocks we need to add to get to --size, 0 if
71 we're already there or beyond.
72 """
73 msger.debug("Requested partition size for %s: %d" % \
74 (self.mountpoint, self.size))
75
76 if not self.size:
77 return 0
78
79 requested_blocks = self.size
80
81 msger.debug("Requested blocks %d, current_blocks %d" % \
82 (requested_blocks, current_blocks))
83
84 if requested_blocks > current_blocks:
85 return requested_blocks - current_blocks
86 else:
87 return 0
88
89 def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir,
90 bootimg_dir, kernel_dir, native_sysroot):
91 """
92 Prepare content for individual partitions, depending on
93 partition command parameters.
94 """
95 if self.sourceparams:
96 self.sourceparams_dict = parse_sourceparams(self.sourceparams)
97
98 if not self.source:
99 if not self.size:
100 msger.error("The %s partition has a size of zero. Please "
101 "specify a non-zero --size for that partition." % \
102 self.mountpoint)
103 if self.fstype and self.fstype == "swap":
104 self.prepare_swap_partition(cr_workdir, oe_builddir,
105 native_sysroot)
106 elif self.fstype:
107 rootfs = "%s/fs_%s.%s.%s" % (cr_workdir, self.label,
108 self.lineno, self.fstype)
109 if os.path.isfile(rootfs):
110 os.remove(rootfs)
111 for prefix in ("ext", "btrfs", "vfat", "squashfs"):
112 if self.fstype.startswith(prefix):
113 method = getattr(self,
114 "prepare_empty_partition_" + prefix)
115 method(rootfs, oe_builddir, native_sysroot)
116 self.source_file = rootfs
117 break
118 return
119
120 plugins = pluginmgr.get_source_plugins()
121
122 if self.source not in plugins:
123 msger.error("The '%s' --source specified for %s doesn't exist.\n\t"
124 "See 'wic list source-plugins' for a list of available"
125 " --sources.\n\tSee 'wic help source-plugins' for "
126 "details on adding a new source plugin." % \
127 (self.source, self.mountpoint))
128
129 self._source_methods = pluginmgr.get_source_plugin_methods(\
130 self.source, partition_methods)
131 self._source_methods["do_configure_partition"](self, self.sourceparams_dict,
132 creator, cr_workdir,
133 oe_builddir,
134 bootimg_dir,
135 kernel_dir,
136 native_sysroot)
137 self._source_methods["do_stage_partition"](self, self.sourceparams_dict,
138 creator, cr_workdir,
139 oe_builddir,
140 bootimg_dir, kernel_dir,
141 native_sysroot)
142 self._source_methods["do_prepare_partition"](self, self.sourceparams_dict,
143 creator, cr_workdir,
144 oe_builddir,
145 bootimg_dir, kernel_dir, rootfs_dir,
146 native_sysroot)
147
148 def prepare_rootfs_from_fs_image(self, cr_workdir, oe_builddir,
149 rootfs_dir):
150 """
151 Handle an already-created partition e.g. xxx.ext3
152 """
153 rootfs = oe_builddir
154 du_cmd = "du -Lbks %s" % rootfs
155 out = exec_cmd(du_cmd)
156 rootfs_size = out.split()[0]
157
158 self.size = rootfs_size
159 self.source_file = rootfs
160
161 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir,
162 native_sysroot):
163 """
164 Prepare content for a rootfs partition i.e. create a partition
165 and fill it from a /rootfs dir.
166
167 Currently handles ext2/3/4, btrfs and vfat.
168 """
169 p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot)
170 p_localstatedir = os.environ.get("PSEUDO_LOCALSTATEDIR",
171 "%s/../pseudo" % rootfs_dir)
172 p_passwd = os.environ.get("PSEUDO_PASSWD", rootfs_dir)
173 p_nosymlinkexp = os.environ.get("PSEUDO_NOSYMLINKEXP", "1")
174 pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix
175 pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % p_localstatedir
176 pseudo += "export PSEUDO_PASSWD=%s;" % p_passwd
177 pseudo += "export PSEUDO_NOSYMLINKEXP=%s;" % p_nosymlinkexp
178 pseudo += "%s/usr/bin/pseudo " % native_sysroot
179
180 rootfs = "%s/rootfs_%s.%s.%s" % (cr_workdir, self.label,
181 self.lineno, self.fstype)
182 if os.path.isfile(rootfs):
183 os.remove(rootfs)
184
185 for prefix in ("ext", "btrfs", "vfat", "squashfs"):
186 if self.fstype.startswith(prefix):
187 method = getattr(self, "prepare_rootfs_" + prefix)
188 method(rootfs, oe_builddir, rootfs_dir, native_sysroot, pseudo)
189
190 self.source_file = rootfs
191
192 # get the rootfs size in the right units for kickstart (kB)
193 du_cmd = "du -Lbks %s" % rootfs
194 out = exec_cmd(du_cmd)
195 self.size = out.split()[0]
196
197 break
198
199 def prepare_rootfs_ext(self, rootfs, oe_builddir, rootfs_dir,
200 native_sysroot, pseudo):
201 """
202 Prepare content for an ext2/3/4 rootfs partition.
203 """
204 du_cmd = "du -ks %s" % rootfs_dir
205 out = exec_cmd(du_cmd)
206 actual_rootfs_size = int(out.split()[0])
207
208 extra_blocks = self.get_extra_block_count(actual_rootfs_size)
209 if extra_blocks < self.extra_space:
210 extra_blocks = self.extra_space
211
212 rootfs_size = actual_rootfs_size + extra_blocks
213 rootfs_size *= self.overhead_factor
214
215 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
216 (extra_blocks, self.mountpoint, rootfs_size))
217
218 dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \
219 (rootfs, rootfs_size)
220 exec_cmd(dd_cmd)
221
222 extra_imagecmd = "-i 8192"
223
224 label_str = ""
225 if self.label:
226 label_str = "-L %s" % self.label
227
228 mkfs_cmd = "mkfs.%s -F %s %s %s -d %s" % \
229 (self.fstype, extra_imagecmd, rootfs, label_str, rootfs_dir)
230 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
231
232 def prepare_rootfs_btrfs(self, rootfs, oe_builddir, rootfs_dir,
233 native_sysroot, pseudo):
234 """
235 Prepare content for a btrfs rootfs partition.
236
237 Currently handles ext2/3/4 and btrfs.
238 """
239 du_cmd = "du -ks %s" % rootfs_dir
240 out = exec_cmd(du_cmd)
241 actual_rootfs_size = int(out.split()[0])
242
243 extra_blocks = self.get_extra_block_count(actual_rootfs_size)
244 if extra_blocks < self.extra_space:
245 extra_blocks = self.extra_space
246
247 rootfs_size = actual_rootfs_size + extra_blocks
248 rootfs_size *= self.overhead_factor
249
250 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
251 (extra_blocks, self.mountpoint, rootfs_size))
252
253 dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \
254 (rootfs, rootfs_size)
255 exec_cmd(dd_cmd)
256
257 label_str = ""
258 if self.label:
259 label_str = "-L %s" % self.label
260
261 mkfs_cmd = "mkfs.%s -b %d -r %s %s %s" % \
262 (self.fstype, rootfs_size * 1024, rootfs_dir, label_str, rootfs)
263 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
264
265 def prepare_rootfs_vfat(self, rootfs, oe_builddir, rootfs_dir,
266 native_sysroot, pseudo):
267 """
268 Prepare content for a vfat rootfs partition.
269 """
270 du_cmd = "du -bks %s" % rootfs_dir
271 out = exec_cmd(du_cmd)
272 blocks = int(out.split()[0])
273
274 extra_blocks = self.get_extra_block_count(blocks)
275 if extra_blocks < self.extra_space:
276 extra_blocks = self.extra_space
277
278 blocks += extra_blocks
279
280 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
281 (extra_blocks, self.mountpoint, blocks))
282
283 # Ensure total sectors is an integral number of sectors per
284 # track or mcopy will complain. Sectors are 512 bytes, and we
285 # generate images with 32 sectors per track. This calculation
286 # is done in blocks, thus the mod by 16 instead of 32. Apply
287 # sector count fix only when needed.
288 if blocks % 16 != 0:
289 blocks += (16 - (blocks % 16))
290
291 label_str = "-n boot"
292 if self.label:
293 label_str = "-n %s" % self.label
294
295 dosfs_cmd = "mkdosfs %s -S 512 -C %s %d" % (label_str, rootfs, blocks)
296 exec_native_cmd(dosfs_cmd, native_sysroot)
297
298 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, rootfs_dir)
299 exec_native_cmd(mcopy_cmd, native_sysroot)
300
301 chmod_cmd = "chmod 644 %s" % rootfs
302 exec_cmd(chmod_cmd)
303
304 def prepare_rootfs_squashfs(self, rootfs, oe_builddir, rootfs_dir,
305 native_sysroot, pseudo):
306 """
307 Prepare content for a squashfs rootfs partition.
308 """
309 squashfs_cmd = "mksquashfs %s %s -noappend" % \
310 (rootfs_dir, rootfs)
311 exec_native_cmd(squashfs_cmd, native_sysroot, pseudo=pseudo)
312
313 def prepare_empty_partition_ext(self, rootfs, oe_builddir,
314 native_sysroot):
315 """
316 Prepare an empty ext2/3/4 partition.
317 """
318 dd_cmd = "dd if=/dev/zero of=%s bs=1k seek=%d count=0" % \
319 (rootfs, self.size)
320 exec_cmd(dd_cmd)
321
322 extra_imagecmd = "-i 8192"
323
324 label_str = ""
325 if self.label:
326 label_str = "-L %s" % self.label
327
328 mkfs_cmd = "mkfs.%s -F %s %s %s" % \
329 (self.fstype, extra_imagecmd, label_str, rootfs)
330 exec_native_cmd(mkfs_cmd, native_sysroot)
331
332 def prepare_empty_partition_btrfs(self, rootfs, oe_builddir,
333 native_sysroot):
334 """
335 Prepare an empty btrfs partition.
336 """
337 dd_cmd = "dd if=/dev/zero of=%s bs=1k seek=%d count=0" % \
338 (rootfs, self.size)
339 exec_cmd(dd_cmd)
340
341 label_str = ""
342 if self.label:
343 label_str = "-L %s" % self.label
344
345 mkfs_cmd = "mkfs.%s -b %d %s %s" % \
346 (self.fstype, self.size * 1024, label_str, rootfs)
347 exec_native_cmd(mkfs_cmd, native_sysroot)
348
349 def prepare_empty_partition_vfat(self, rootfs, oe_builddir,
350 native_sysroot):
351 """
352 Prepare an empty vfat partition.
353 """
354 blocks = self.size
355
356 label_str = "-n boot"
357 if self.label:
358 label_str = "-n %s" % self.label
359
360 dosfs_cmd = "mkdosfs %s -S 512 -C %s %d" % (label_str, rootfs, blocks)
361 exec_native_cmd(dosfs_cmd, native_sysroot)
362
363 chmod_cmd = "chmod 644 %s" % rootfs
364 exec_cmd(chmod_cmd)
365
366 def prepare_empty_partition_squashfs(self, cr_workdir, oe_builddir,
367 native_sysroot):
368 """
369 Prepare an empty squashfs partition.
370 """
371 msger.warning("Creating of an empty squashfs %s partition was attempted. " \
372 "Proceeding as requested." % self.mountpoint)
373
374 path = "%s/fs_%s.%s" % (cr_workdir, self.label, self.fstype)
375 os.path.isfile(path) and os.remove(path)
376
377 # it is not possible to create a squashfs without source data,
378 # thus prepare an empty temp dir that is used as source
379 tmpdir = tempfile.mkdtemp()
380
381 squashfs_cmd = "mksquashfs %s %s -noappend" % \
382 (tmpdir, path)
383 exec_native_cmd(squashfs_cmd, native_sysroot)
384
385 os.rmdir(tmpdir)
386
387 # get the rootfs size in the right units for kickstart (kB)
388 du_cmd = "du -Lbks %s" % path
389 out = exec_cmd(du_cmd)
390 fs_size = out.split()[0]
391
392 self.size = fs_size
393
394 def prepare_swap_partition(self, cr_workdir, oe_builddir, native_sysroot):
395 """
396 Prepare a swap partition.
397 """
398 path = "%s/fs.%s" % (cr_workdir, self.fstype)
399
400 dd_cmd = "dd if=/dev/zero of=%s bs=1k seek=%d count=0" % \
401 (path, self.size)
402 exec_cmd(dd_cmd)
403
404 import uuid
405 label_str = ""
406 if self.label:
407 label_str = "-L %s" % self.label
408 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, str(uuid.uuid1()), path)
409 exec_native_cmd(mkswap_cmd, native_sysroot)
410