diff options
Diffstat (limited to 'scripts/lib/wic/plugins/source/isoimage_isohybrid.py')
-rw-r--r-- | scripts/lib/wic/plugins/source/isoimage_isohybrid.py | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py new file mode 100644 index 0000000000..5d42eb5d3e --- /dev/null +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py | |||
@@ -0,0 +1,463 @@ | |||
1 | # | ||
2 | # Copyright OpenEmbedded Contributors | ||
3 | # | ||
4 | # SPDX-License-Identifier: GPL-2.0-only | ||
5 | # | ||
6 | # DESCRIPTION | ||
7 | # This implements the 'isoimage_isohybrid' source plugin class for 'wic' | ||
8 | # | ||
9 | # AUTHORS | ||
10 | # Mihaly Varga <mihaly.varga (at] ni.com> | ||
11 | |||
12 | import glob | ||
13 | import logging | ||
14 | import os | ||
15 | import re | ||
16 | import shutil | ||
17 | |||
18 | from wic import WicError | ||
19 | from wic.engine import get_custom_config | ||
20 | from wic.pluginbase import SourcePlugin | ||
21 | from wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var | ||
22 | |||
23 | logger = logging.getLogger('wic') | ||
24 | |||
25 | class IsoImagePlugin(SourcePlugin): | ||
26 | """ | ||
27 | Create a bootable ISO image | ||
28 | |||
29 | This plugin creates a hybrid, legacy and EFI bootable ISO image. The | ||
30 | generated image can be used on optical media as well as USB media. | ||
31 | |||
32 | Legacy boot uses syslinux and EFI boot uses grub or gummiboot (not | ||
33 | implemented yet) as bootloader. The plugin creates the directories required | ||
34 | by bootloaders and populates them by creating and configuring the | ||
35 | bootloader files. | ||
36 | |||
37 | Example kickstart file: | ||
38 | part /boot --source isoimage_isohybrid --sourceparams="loader=grub-efi, \\ | ||
39 | image_name= IsoImage" --ondisk cd --label LIVECD | ||
40 | bootloader --timeout=10 --append=" " | ||
41 | |||
42 | In --sourceparams "loader" specifies the bootloader used for booting in EFI | ||
43 | mode, while "image_name" specifies the name of the generated image. In the | ||
44 | example above, wic creates an ISO image named IsoImage-cd.direct (default | ||
45 | extension added by direct imeger plugin) and a file named IsoImage-cd.iso | ||
46 | """ | ||
47 | |||
48 | name = 'isoimage_isohybrid' | ||
49 | |||
50 | @classmethod | ||
51 | def do_configure_syslinux(cls, creator, cr_workdir): | ||
52 | """ | ||
53 | Create loader-specific (syslinux) config | ||
54 | """ | ||
55 | splash = os.path.join(cr_workdir, "ISO/boot/splash.jpg") | ||
56 | if os.path.exists(splash): | ||
57 | splashline = "menu background splash.jpg" | ||
58 | else: | ||
59 | splashline = "" | ||
60 | |||
61 | bootloader = creator.ks.bootloader | ||
62 | |||
63 | syslinux_conf = "" | ||
64 | syslinux_conf += "PROMPT 0\n" | ||
65 | syslinux_conf += "TIMEOUT %s \n" % (bootloader.timeout or 10) | ||
66 | syslinux_conf += "\n" | ||
67 | syslinux_conf += "ALLOWOPTIONS 1\n" | ||
68 | syslinux_conf += "SERIAL 0 115200\n" | ||
69 | syslinux_conf += "\n" | ||
70 | if splashline: | ||
71 | syslinux_conf += "%s\n" % splashline | ||
72 | syslinux_conf += "DEFAULT boot\n" | ||
73 | syslinux_conf += "LABEL boot\n" | ||
74 | |||
75 | kernel = get_bitbake_var("KERNEL_IMAGETYPE") | ||
76 | if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": | ||
77 | if get_bitbake_var("INITRAMFS_IMAGE"): | ||
78 | kernel = "%s-%s.bin" % \ | ||
79 | (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) | ||
80 | |||
81 | syslinux_conf += "KERNEL /" + kernel + "\n" | ||
82 | syslinux_conf += "APPEND initrd=/initrd LABEL=boot %s\n" \ | ||
83 | % bootloader.append | ||
84 | |||
85 | logger.debug("Writing syslinux config %s/ISO/isolinux/isolinux.cfg", | ||
86 | cr_workdir) | ||
87 | |||
88 | with open("%s/ISO/isolinux/isolinux.cfg" % cr_workdir, "w") as cfg: | ||
89 | cfg.write(syslinux_conf) | ||
90 | |||
91 | @classmethod | ||
92 | def do_configure_grubefi(cls, part, creator, target_dir): | ||
93 | """ | ||
94 | Create loader-specific (grub-efi) config | ||
95 | """ | ||
96 | configfile = creator.ks.bootloader.configfile | ||
97 | if configfile: | ||
98 | grubefi_conf = get_custom_config(configfile) | ||
99 | if grubefi_conf: | ||
100 | logger.debug("Using custom configuration file %s for grub.cfg", | ||
101 | configfile) | ||
102 | else: | ||
103 | raise WicError("configfile is specified " | ||
104 | "but failed to get it from %s", configfile) | ||
105 | else: | ||
106 | splash = os.path.join(target_dir, "splash.jpg") | ||
107 | if os.path.exists(splash): | ||
108 | splashline = "menu background splash.jpg" | ||
109 | else: | ||
110 | splashline = "" | ||
111 | |||
112 | bootloader = creator.ks.bootloader | ||
113 | |||
114 | grubefi_conf = "" | ||
115 | grubefi_conf += "serial --unit=0 --speed=115200 --word=8 " | ||
116 | grubefi_conf += "--parity=no --stop=1\n" | ||
117 | grubefi_conf += "default=boot\n" | ||
118 | grubefi_conf += "timeout=%s\n" % (bootloader.timeout or 10) | ||
119 | grubefi_conf += "\n" | ||
120 | grubefi_conf += "search --set=root --label %s " % part.label | ||
121 | grubefi_conf += "\n" | ||
122 | grubefi_conf += "menuentry 'boot'{\n" | ||
123 | |||
124 | kernel = get_bitbake_var("KERNEL_IMAGETYPE") | ||
125 | if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": | ||
126 | if get_bitbake_var("INITRAMFS_IMAGE"): | ||
127 | kernel = "%s-%s.bin" % \ | ||
128 | (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) | ||
129 | |||
130 | grubefi_conf += "linux /%s rootwait %s\n" \ | ||
131 | % (kernel, bootloader.append) | ||
132 | grubefi_conf += "initrd /initrd \n" | ||
133 | grubefi_conf += "}\n" | ||
134 | |||
135 | if splashline: | ||
136 | grubefi_conf += "%s\n" % splashline | ||
137 | |||
138 | cfg_path = os.path.join(target_dir, "grub.cfg") | ||
139 | logger.debug("Writing grubefi config %s", cfg_path) | ||
140 | |||
141 | with open(cfg_path, "w") as cfg: | ||
142 | cfg.write(grubefi_conf) | ||
143 | |||
144 | @staticmethod | ||
145 | def _build_initramfs_path(rootfs_dir, cr_workdir): | ||
146 | """ | ||
147 | Create path for initramfs image | ||
148 | """ | ||
149 | |||
150 | initrd = get_bitbake_var("INITRD_LIVE") or get_bitbake_var("INITRD") | ||
151 | if not initrd: | ||
152 | initrd_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") | ||
153 | if not initrd_dir: | ||
154 | raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting.") | ||
155 | |||
156 | image_name = get_bitbake_var("IMAGE_BASENAME") | ||
157 | if not image_name: | ||
158 | raise WicError("Couldn't find IMAGE_BASENAME, exiting.") | ||
159 | |||
160 | image_type = get_bitbake_var("INITRAMFS_FSTYPES") | ||
161 | if not image_type: | ||
162 | raise WicError("Couldn't find INITRAMFS_FSTYPES, exiting.") | ||
163 | |||
164 | machine = os.path.basename(initrd_dir) | ||
165 | |||
166 | pattern = '%s/%s*%s.%s' % (initrd_dir, image_name, machine, image_type) | ||
167 | files = glob.glob(pattern) | ||
168 | if files: | ||
169 | initrd = files[0] | ||
170 | |||
171 | if not initrd or not os.path.exists(initrd): | ||
172 | # Create initrd from rootfs directory | ||
173 | initrd = "%s/initrd.cpio.gz" % cr_workdir | ||
174 | initrd_dir = "%s/INITRD" % cr_workdir | ||
175 | shutil.copytree("%s" % rootfs_dir, \ | ||
176 | "%s" % initrd_dir, symlinks=True) | ||
177 | |||
178 | if os.path.isfile("%s/init" % rootfs_dir): | ||
179 | shutil.copy2("%s/init" % rootfs_dir, "%s/init" % initrd_dir) | ||
180 | elif os.path.lexists("%s/init" % rootfs_dir): | ||
181 | os.symlink(os.readlink("%s/init" % rootfs_dir), \ | ||
182 | "%s/init" % initrd_dir) | ||
183 | elif os.path.isfile("%s/sbin/init" % rootfs_dir): | ||
184 | shutil.copy2("%s/sbin/init" % rootfs_dir, \ | ||
185 | "%s" % initrd_dir) | ||
186 | elif os.path.lexists("%s/sbin/init" % rootfs_dir): | ||
187 | os.symlink(os.readlink("%s/sbin/init" % rootfs_dir), \ | ||
188 | "%s/init" % initrd_dir) | ||
189 | else: | ||
190 | raise WicError("Couldn't find or build initrd, exiting.") | ||
191 | |||
192 | exec_cmd("cd %s && find . | cpio -o -H newc -R root:root >%s/initrd.cpio " \ | ||
193 | % (initrd_dir, cr_workdir), as_shell=True) | ||
194 | exec_cmd("gzip -f -9 %s/initrd.cpio" % cr_workdir, as_shell=True) | ||
195 | shutil.rmtree(initrd_dir) | ||
196 | |||
197 | return initrd | ||
198 | |||
199 | @classmethod | ||
200 | def do_configure_partition(cls, part, source_params, creator, cr_workdir, | ||
201 | oe_builddir, bootimg_dir, kernel_dir, | ||
202 | native_sysroot): | ||
203 | """ | ||
204 | Called before do_prepare_partition(), creates loader-specific config | ||
205 | """ | ||
206 | isodir = "%s/ISO/" % cr_workdir | ||
207 | |||
208 | if os.path.exists(isodir): | ||
209 | shutil.rmtree(isodir) | ||
210 | |||
211 | install_cmd = "install -d %s " % isodir | ||
212 | exec_cmd(install_cmd) | ||
213 | |||
214 | # Overwrite the name of the created image | ||
215 | logger.debug(source_params) | ||
216 | if 'image_name' in source_params and \ | ||
217 | source_params['image_name'].strip(): | ||
218 | creator.name = source_params['image_name'].strip() | ||
219 | logger.debug("The name of the image is: %s", creator.name) | ||
220 | |||
221 | @staticmethod | ||
222 | def _install_payload(source_params, iso_dir): | ||
223 | """ | ||
224 | Copies contents of payload directory (as specified in 'payload_dir' param) into iso_dir | ||
225 | """ | ||
226 | |||
227 | if source_params.get('payload_dir'): | ||
228 | payload_dir = source_params['payload_dir'] | ||
229 | |||
230 | logger.debug("Payload directory: %s", payload_dir) | ||
231 | shutil.copytree(payload_dir, iso_dir, symlinks=True, dirs_exist_ok=True) | ||
232 | |||
233 | @classmethod | ||
234 | def do_prepare_partition(cls, part, source_params, creator, cr_workdir, | ||
235 | oe_builddir, bootimg_dir, kernel_dir, | ||
236 | rootfs_dir, native_sysroot): | ||
237 | """ | ||
238 | Called to do the actual content population for a partition i.e. it | ||
239 | 'prepares' the partition to be incorporated into the image. | ||
240 | In this case, prepare content for a bootable ISO image. | ||
241 | """ | ||
242 | |||
243 | isodir = "%s/ISO" % cr_workdir | ||
244 | |||
245 | cls._install_payload(source_params, isodir) | ||
246 | |||
247 | if part.rootfs_dir is None: | ||
248 | if not 'ROOTFS_DIR' in rootfs_dir: | ||
249 | raise WicError("Couldn't find --rootfs-dir, exiting.") | ||
250 | rootfs_dir = rootfs_dir['ROOTFS_DIR'] | ||
251 | else: | ||
252 | if part.rootfs_dir in rootfs_dir: | ||
253 | rootfs_dir = rootfs_dir[part.rootfs_dir] | ||
254 | elif part.rootfs_dir: | ||
255 | rootfs_dir = part.rootfs_dir | ||
256 | else: | ||
257 | raise WicError("Couldn't find --rootfs-dir=%s connection " | ||
258 | "or it is not a valid path, exiting." % | ||
259 | part.rootfs_dir) | ||
260 | |||
261 | if not os.path.isdir(rootfs_dir): | ||
262 | rootfs_dir = get_bitbake_var("IMAGE_ROOTFS") | ||
263 | if not os.path.isdir(rootfs_dir): | ||
264 | raise WicError("Couldn't find IMAGE_ROOTFS, exiting.") | ||
265 | |||
266 | part.rootfs_dir = rootfs_dir | ||
267 | deploy_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") | ||
268 | img_iso_dir = get_bitbake_var("ISODIR") | ||
269 | |||
270 | # Remove the temporary file created by part.prepare_rootfs() | ||
271 | if os.path.isfile(part.source_file): | ||
272 | os.remove(part.source_file) | ||
273 | |||
274 | # Support using a different initrd other than default | ||
275 | if source_params.get('initrd'): | ||
276 | initrd = source_params['initrd'] | ||
277 | if not deploy_dir: | ||
278 | raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") | ||
279 | cp_cmd = "cp %s/%s %s" % (deploy_dir, initrd, cr_workdir) | ||
280 | exec_cmd(cp_cmd) | ||
281 | else: | ||
282 | # Prepare initial ramdisk | ||
283 | initrd = "%s/initrd" % deploy_dir | ||
284 | if not os.path.isfile(initrd): | ||
285 | initrd = "%s/initrd" % img_iso_dir | ||
286 | if not os.path.isfile(initrd): | ||
287 | initrd = cls._build_initramfs_path(rootfs_dir, cr_workdir) | ||
288 | |||
289 | install_cmd = "install -m 0644 %s %s/initrd" % (initrd, isodir) | ||
290 | exec_cmd(install_cmd) | ||
291 | |||
292 | # Remove the temporary file created by _build_initramfs_path function | ||
293 | if os.path.isfile("%s/initrd.cpio.gz" % cr_workdir): | ||
294 | os.remove("%s/initrd.cpio.gz" % cr_workdir) | ||
295 | |||
296 | kernel = get_bitbake_var("KERNEL_IMAGETYPE") | ||
297 | if get_bitbake_var("INITRAMFS_IMAGE_BUNDLE") == "1": | ||
298 | if get_bitbake_var("INITRAMFS_IMAGE"): | ||
299 | kernel = "%s-%s.bin" % \ | ||
300 | (get_bitbake_var("KERNEL_IMAGETYPE"), get_bitbake_var("INITRAMFS_LINK_NAME")) | ||
301 | |||
302 | install_cmd = "install -m 0644 %s/%s %s/%s" % \ | ||
303 | (kernel_dir, kernel, isodir, kernel) | ||
304 | exec_cmd(install_cmd) | ||
305 | |||
306 | #Create bootloader for efi boot | ||
307 | try: | ||
308 | target_dir = "%s/EFI/BOOT" % isodir | ||
309 | if os.path.exists(target_dir): | ||
310 | shutil.rmtree(target_dir) | ||
311 | |||
312 | os.makedirs(target_dir) | ||
313 | |||
314 | if source_params['loader'] == 'grub-efi': | ||
315 | # Builds bootx64.efi/bootia32.efi if ISODIR didn't exist or | ||
316 | # didn't contains it | ||
317 | target_arch = get_bitbake_var("TARGET_SYS") | ||
318 | if not target_arch: | ||
319 | raise WicError("Coludn't find target architecture") | ||
320 | |||
321 | if re.match("x86_64", target_arch): | ||
322 | grub_src_image = "grub-efi-bootx64.efi" | ||
323 | grub_dest_image = "bootx64.efi" | ||
324 | elif re.match('i.86', target_arch): | ||
325 | grub_src_image = "grub-efi-bootia32.efi" | ||
326 | grub_dest_image = "bootia32.efi" | ||
327 | else: | ||
328 | raise WicError("grub-efi is incompatible with target %s" % | ||
329 | target_arch) | ||
330 | |||
331 | grub_target = os.path.join(target_dir, grub_dest_image) | ||
332 | if not os.path.isfile(grub_target): | ||
333 | grub_src = os.path.join(deploy_dir, grub_src_image) | ||
334 | if not os.path.exists(grub_src): | ||
335 | raise WicError("Grub loader %s is not found in %s. " | ||
336 | "Please build grub-efi first" % (grub_src_image, deploy_dir)) | ||
337 | shutil.copy(grub_src, grub_target) | ||
338 | |||
339 | if not os.path.isfile(os.path.join(target_dir, "boot.cfg")): | ||
340 | cls.do_configure_grubefi(part, creator, target_dir) | ||
341 | |||
342 | else: | ||
343 | raise WicError("unrecognized bootimg_efi loader: %s" % | ||
344 | source_params['loader']) | ||
345 | except KeyError: | ||
346 | raise WicError("bootimg_efi requires a loader, none specified") | ||
347 | |||
348 | # Create efi.img that contains bootloader files for EFI booting | ||
349 | # if ISODIR didn't exist or didn't contains it | ||
350 | if os.path.isfile("%s/efi.img" % img_iso_dir): | ||
351 | install_cmd = "install -m 0644 %s/efi.img %s/efi.img" % \ | ||
352 | (img_iso_dir, isodir) | ||
353 | exec_cmd(install_cmd) | ||
354 | else: | ||
355 | # Default to 100 blocks of extra space for file system overhead | ||
356 | esp_extra_blocks = int(source_params.get('esp_extra_blocks', '100')) | ||
357 | |||
358 | du_cmd = "du -bks %s/EFI" % isodir | ||
359 | out = exec_cmd(du_cmd) | ||
360 | blocks = int(out.split()[0]) | ||
361 | blocks += esp_extra_blocks | ||
362 | logger.debug("Added 100 extra blocks to %s to get to %d " | ||
363 | "total blocks", part.mountpoint, blocks) | ||
364 | |||
365 | # dosfs image for EFI boot | ||
366 | bootimg = "%s/efi.img" % isodir | ||
367 | |||
368 | esp_label = source_params.get('esp_label', 'EFIimg') | ||
369 | |||
370 | dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \ | ||
371 | % (esp_label, bootimg, blocks) | ||
372 | exec_native_cmd(dosfs_cmd, native_sysroot) | ||
373 | |||
374 | mmd_cmd = "mmd -i %s ::/EFI" % bootimg | ||
375 | exec_native_cmd(mmd_cmd, native_sysroot) | ||
376 | |||
377 | mcopy_cmd = "mcopy -i %s -s %s/EFI/* ::/EFI/" \ | ||
378 | % (bootimg, isodir) | ||
379 | exec_native_cmd(mcopy_cmd, native_sysroot) | ||
380 | |||
381 | chmod_cmd = "chmod 644 %s" % bootimg | ||
382 | exec_cmd(chmod_cmd) | ||
383 | |||
384 | # Prepare files for legacy boot | ||
385 | syslinux_dir = get_bitbake_var("STAGING_DATADIR") | ||
386 | if not syslinux_dir: | ||
387 | raise WicError("Couldn't find STAGING_DATADIR, exiting.") | ||
388 | |||
389 | if os.path.exists("%s/isolinux" % isodir): | ||
390 | shutil.rmtree("%s/isolinux" % isodir) | ||
391 | |||
392 | install_cmd = "install -d %s/isolinux" % isodir | ||
393 | exec_cmd(install_cmd) | ||
394 | |||
395 | cls.do_configure_syslinux(creator, cr_workdir) | ||
396 | |||
397 | install_cmd = "install -m 444 %s/syslinux/ldlinux.sys " % syslinux_dir | ||
398 | install_cmd += "%s/isolinux/ldlinux.sys" % isodir | ||
399 | exec_cmd(install_cmd) | ||
400 | |||
401 | install_cmd = "install -m 444 %s/syslinux/isohdpfx.bin " % syslinux_dir | ||
402 | install_cmd += "%s/isolinux/isohdpfx.bin" % isodir | ||
403 | exec_cmd(install_cmd) | ||
404 | |||
405 | install_cmd = "install -m 644 %s/syslinux/isolinux.bin " % syslinux_dir | ||
406 | install_cmd += "%s/isolinux/isolinux.bin" % isodir | ||
407 | exec_cmd(install_cmd) | ||
408 | |||
409 | install_cmd = "install -m 644 %s/syslinux/ldlinux.c32 " % syslinux_dir | ||
410 | install_cmd += "%s/isolinux/ldlinux.c32" % isodir | ||
411 | exec_cmd(install_cmd) | ||
412 | |||
413 | #create ISO image | ||
414 | iso_img = "%s/tempiso_img.iso" % cr_workdir | ||
415 | iso_bootimg = "isolinux/isolinux.bin" | ||
416 | iso_bootcat = "isolinux/boot.cat" | ||
417 | efi_img = "efi.img" | ||
418 | |||
419 | mkisofs_cmd = "mkisofs -V %s " % part.label | ||
420 | mkisofs_cmd += "-o %s -U " % iso_img | ||
421 | mkisofs_cmd += "-J -joliet-long -r -iso-level 2 -b %s " % iso_bootimg | ||
422 | mkisofs_cmd += "-c %s -no-emul-boot -boot-load-size 4 " % iso_bootcat | ||
423 | mkisofs_cmd += "-boot-info-table -eltorito-alt-boot " | ||
424 | mkisofs_cmd += "-eltorito-platform 0xEF -eltorito-boot %s " % efi_img | ||
425 | mkisofs_cmd += "-no-emul-boot %s " % isodir | ||
426 | |||
427 | logger.debug("running command: %s", mkisofs_cmd) | ||
428 | exec_native_cmd(mkisofs_cmd, native_sysroot) | ||
429 | |||
430 | shutil.rmtree(isodir) | ||
431 | |||
432 | du_cmd = "du -Lbks %s" % iso_img | ||
433 | out = exec_cmd(du_cmd) | ||
434 | isoimg_size = int(out.split()[0]) | ||
435 | |||
436 | part.size = isoimg_size | ||
437 | part.source_file = iso_img | ||
438 | |||
439 | @classmethod | ||
440 | def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir, | ||
441 | bootimg_dir, kernel_dir, native_sysroot): | ||
442 | """ | ||
443 | Called after all partitions have been prepared and assembled into a | ||
444 | disk image. In this case, we insert/modify the MBR using isohybrid | ||
445 | utility for booting via BIOS from disk storage devices. | ||
446 | """ | ||
447 | |||
448 | iso_img = "%s.p1" % disk.path | ||
449 | full_path = creator._full_path(workdir, disk_name, "direct") | ||
450 | full_path_iso = creator._full_path(workdir, disk_name, "iso") | ||
451 | |||
452 | isohybrid_cmd = "isohybrid -u %s" % iso_img | ||
453 | logger.debug("running command: %s", isohybrid_cmd) | ||
454 | exec_native_cmd(isohybrid_cmd, native_sysroot) | ||
455 | |||
456 | # Replace the image created by direct plugin with the one created by | ||
457 | # mkisofs command. This is necessary because the iso image created by | ||
458 | # mkisofs has a very specific MBR is system area of the ISO image, and | ||
459 | # direct plugin adds and configures an another MBR. | ||
460 | logger.debug("Replaceing the image created by direct plugin\n") | ||
461 | os.remove(disk.path) | ||
462 | shutil.copy2(iso_img, full_path_iso) | ||
463 | shutil.copy2(full_path_iso, full_path) | ||