Modify imagesOnce you have obtained a virtual machine image, you may want
to make some changes to it before uploading it to the
OpenStack Image service. Here we describe several tools
available that allow you to modify images.Do not attempt to use these tools to modify an image
that is attached to a running virtual machine. These
tools are designed to only modify images that are not
currently running.guestfishThe guestfish program is a tool from
the libguestfs project that allows you to modify
the files inside of a virtual machine image.guestfish does not mount the
image directly into the local file system. Instead, it
provides you with a shell interface that enables you
to view, edit, and delete files. Many of
guestfish commands, such as
touch,
chmod, and rm,
resemble traditional bash commands.Example guestfish sessionSometimes, you must modify a virtual machine image
to remove any traces of the MAC address that was
assigned to the virtual network interface card when
the image was first created, because the MAC address
will be different when it boots the next time. This
example shows how to use guestfish to remove
references to the old MAC address by deleting the
/etc/udev/rules.d/70-persistent-net.rules
file and removing the HWADDR line
from the
/etc/sysconfig/network-scripts/ifcfg-eth0
file.Assume that you have a CentOS qcow2 image called
centos63_desktop.img. Mount
the image in read-write mode as root, as
follows:#guestfish --rw -a centos63_desktop.img
Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.
Type: 'help' for help on commands
'man' to read the manual
'quit' to quit the shell
><fs>This starts a guestfish session. Note that the
guestfish prompt looks like a fish: >
<fs>.We must first use the run command
at the guestfish prompt before we can do anything
else. This will launch a virtual machine, which will
be used to perform all of the file
manipulations.><fs>run
We can now view the file systems in the image using the
list-filesystems
command:><fs>list-filesystems/dev/vda1: ext4
/dev/vg_centosbase/lv_root: ext4
/dev/vg_centosbase/lv_swap: swapWe
need to mount the logical volume that contains the
root partition:
><fs>mount /dev/vg_centosbase/lv_root /Next, we want to delete a file. We can use the
rm guestfish command, which
works the same way it does in a traditional
shell.><fs>rm /etc/udev/rules.d/70-persistent-net.rulesWe
want to edit the ifcfg-eth0 file
to remove the HWADDR line. The
edit command will copy the file
to the host, invoke your editor, and then copy the
file back.
><fs>edit /etc/sysconfig/network-scripts/ifcfg-eth0If you want to modify this image to load the 8021q
kernel at boot time, you must create an executable
script in the
/etc/sysconfig/modules/
directory. You can use the touch
guestfish command to create an empty file, the
edit command to edit it, and
the chmod command to make it
executable.><fs>touch /etc/sysconfig/modules/8021q.modules><fs>edit /etc/sysconfig/modules/8021q.modules
We add the following line to the file and save
it:modprobe 8021qThen
we set to executable:
><fs> chmod 0755 /etc/sysconfig/modules/8021q.modulesWe're done, so we can exit using the
exit
command:><fs>exitGo further with guestfishThere is an enormous amount of functionality in
guestfish and a full treatment is beyond the scope of
this document. Instead, we recommend that you read the
guestfs-recipes documentation page for a
sense of what is possible with these tools.guestmountFor some types of changes, you may find it easier to
mount the image's file system directly in the guest. The
guestmount program, also from the
libguestfs project, allows you to do so.For example, to mount the root partition from our
centos63_desktop.qcow2 image to
/mnt, we can do:#guestmount -a centos63_desktop.qcow2 -m /dev/vg_centosbase/lv_root --rw /mntIf we didn't know in advance what the mount point is in
the guest, we could use the -i(inspect)
flag to tell guestmount to automatically determine what
mount point to
use:#guestmount -a centos63_desktop.qcow2 -i --rw /mntOnce
mounted, we could do things like list the installed
packages using
rpm:#rpm -qa --dbpath /mnt/var/lib/rpm
Once done, we
unmount:#umount /mntvirt-* toolsThe libguestfs project has a number of other
useful tools, including:virt-edit for editing a file
inside of an image.virt-df for displaying free space
inside of an image.virt-resize for resizing an
image.virt-sysprep for preparing an
image for distribution (for example, delete
SSH host keys, remove MAC address info, or
remove user accounts).virt-sparsify for making an image
sparsevirt-p2v for converting a physical
machine to an image that runs on KVMvirt-v2v for converting Xen and
VMWare images to KVM imagesModify a single file inside of an imageThis example shows how to use
virt-edit to modify a file. The
command can take either a filename as an argument with
the -a flag, or a domain name as an
argument with the -d flag. The
following examples shows how to use this to modify the
/etc/shadow file in instance
with libvirt domain name
instance-000000e1 that is
currently running:#virsh shutdown instance-000000e1#virt-edit -d instance-000000e1 /etc/shadow#virsh start instance-000000e1Resize an imageHere's a simple of example of how to use
virt-resize to resize an image.
Assume we have a 16GB Windows image in qcow2 format
that we want to resize to 50GB. First, we use
virt-filesystems to identify
the
partitions:#virt-filesystems --long --parts --blkdevs -h -a /data/images/win2012.qcow2Name Type MBR Size Parent
/dev/sda1 partition 07 350M /dev/sda
/dev/sda2 partition 07 16G /dev/sda
/dev/sda device - 16G -
In this case, it's the
/dev/sda2 partition that we
want to resize. We create a new qcow2 image and use
the virt-resize command to write a
resized copy of the original into the new
image:
#qemu-img create -f qcow2 /data/images/win2012-50gb.qcw2 50G#virt-resize --expand /dev/sda2 /data/images/win2012.qcow2 \
/data/images/win2012-50gb.qcow2Examining /data/images/win2012.qcow2 ...
**********
Summary of changes:
/dev/sda1: This partition will be left alone.
/dev/sda2: This partition will be resized from 15.7G to 49.7G. The
filesystem ntfs on /dev/sda2 will be expanded using the
'ntfsresize' method.
**********
Setting up initial partition table on /data/images/win2012-50gb.qcow2 ...
Copying /dev/sda1 ...
100% ⟦▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓⟧ 00:00
Copying /dev/sda2 ...
100% ⟦▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓⟧ 00:00
Expanding /dev/sda2 using the 'ntfsresize' method ...
Resize operation completed with no errors. Before deleting the old
disk, carefully check that the resized disk boots and works correctly.
Loop devices, kpartx, network block devicesIf you don't have access to libguestfs, you can mount
image file systems directly in the host using loop
devices, kpartx, and network block devices.Mounting untrusted guest images using the tools
described in this section is a security risk,
always use libguestfs tools such as guestfish and
guestmount if you have access to them. See A reminder why you should never mount guest
disk images on the host OS by Daniel
Berrangé for more details.Mount a raw image (without LVM)If you have a raw virtual machine image that is not
using LVM to manage its partitions. First, use the
losetup command to find an
unused loop device.
#losetup -f/dev/loop0In this example, /dev/loop0 is
free. Associate a loop device with the raw
image:#losetup /dev/loop0 fedora17.imgIf the image only has a single partition, you can
mount the loop device
directly:#mount /dev/loop0 /mntIf the image has multiple partitions, use
kpartx to expose the partitions
as separate devices (for example,
/dev/mapper/loop0p1), then
mount the partition that corresponds to the root file
system:#kpartx -av /dev/loop0If the image has, say three partitions (/boot, /,
/swap), there should be one new device created per
partition:$ls -l /dev/mapper/loop0p*brw-rw---- 1 root disk 43, 49 2012-03-05 15:32 /dev/mapper/loop0p1
brw-rw---- 1 root disk 43, 50 2012-03-05 15:32 /dev/mapper/loop0p2
brw-rw---- 1 root disk 43, 51 2012-03-05 15:32 /dev/mapper/loop0p3To
mount the second partition, as
root:#mkdir /mnt/image#mount /dev/mapper/loop0p2 /mntOnce
you're done, to clean
up:#umount /mnt#kpartx -d /dev/loop0#losetup -d /dev/loop0Mount a raw image (with LVM)If your partitions are managed with LVM, use losetup
and kpartx as in the previous example to expose the
partitions to the host:#losetup -f/dev/loop0#losetup /dev/loop0 rhel62.img#kpartx -av /dev/loop0Next, you need to use the vgscan
command to identify the LVM volume groups and then
vgchange to expose the volumes
as devices:#vgscanReading all physical volumes. This may take a while...
Found volume group "vg_rhel62x8664" using metadata type lvm2#vgchange -ay 2 logical volume(s) in volume group "vg_rhel62x8664" now active#mount /dev/vg_rhel62x8664/lv_root /mntClean up when you're done:#umount /mnt#vgchange -an vg_rhel62x8664#kpartx -d /dev/loop0#losetup -d /dev/loop0Mount a qcow2 image (without LVM)You need the nbd (network block
device) kernel module loaded to mount qcow2 images.
This will load it with support for 16 block devices,
which is fine for our purposes. As
root:#modprobe nbd max_part=16Assuming the first block device
(/dev/nbd0) is not currently
in use, we can expose the disk partitions using the
qemu-nbd and
partprobe commands. As
root:#qemu-nbd -c /dev/nbd0 image.qcow2#partprobe /dev/nbd0If the image has, say three partitions (/boot, /,
/swap), there should be one new device created for
each partition:$ls -l /dev/nbd3*brw-rw---- 1 root disk 43, 48 2012-03-05 15:32 /dev/nbd0
brw-rw---- 1 root disk 43, 49 2012-03-05 15:32 /dev/nbd0p1
brw-rw---- 1 root disk 43, 50 2012-03-05 15:32 /dev/nbd0p2
brw-rw---- 1 root disk 43, 51 2012-03-05 15:32 /dev/nbd0p3If the network block device you selected was
already in use, the initial
qemu-nbd command will fail
silently, and the
/dev/nbd3p{1,2,3} device
files will not be created.If the image partitions are not managed with LVM,
they can be mounted directly:#mkdir /mnt/image#mount /dev/nbd3p2 /mntWhen you're done, clean up:#umount /mnt#qemu-nbd -d /dev/g nbd0Mount a qcow2 image (with LVM)If the image partitions are managed with LVM, after
you use qemu-nbd and
partprobe, you must use
vgscan and vgchange
-ay in order to expose the LVM
partitions as devices that can be
mounted:#modprobe nbd max_part=16#qemu-nbd -c /dev/nbd0 image.qcow2#partprobe /dev/nbd0#vgscan Reading all physical volumes. This may take a while...
Found volume group "vg_rhel62x8664" using metadata type lvm2#vgchange -ay 2 logical volume(s) in volume group "vg_rhel62x8664" now active#mount /dev/vg_rhel62x8664/lv_root /mntWhen you're done, clean
up:#umount /mnt#vgchange -an vg_rhel62x8664#qemu-nbd -d /dev/nbd0