64b6c9261e
Current folder name New folder name Book title ---------------------------------------------------------- basic-install DELETE cli-guide DELETE common common NEW admin-guide-cloud Cloud Administrators Guide docbkx-example DELETE openstack-block-storage-admin DELETE openstack-compute-admin DELETE openstack-config config-reference OpenStack Configuration Reference openstack-ha high-availability-guide OpenStack High Availabilty Guide openstack-image image-guide OpenStack Virtual Machine Image Guide openstack-install install-guide OpenStack Installation Guide openstack-network-connectivity-admin admin-guide-network OpenStack Networking Administration Guide openstack-object-storage-admin DELETE openstack-security security-guide OpenStack Security Guide openstack-training training-guide OpenStack Training Guide openstack-user user-guide OpenStack End User Guide openstack-user-admin user-guide-admin OpenStack Admin User Guide glossary NEW OpenStack Glossary bug: #1220407 Change-Id: Id5ffc774b966ba7b9a591743a877aa10ab3094c7 author: diane fleming
313 lines
21 KiB
XML
313 lines
21 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="ch_modifying_images">
|
|
<title>Modifying images</title>
|
|
<?dbhtml stop-chunking?>
|
|
<para>Once 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.<warning>
|
|
<para>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.</para>
|
|
</warning></para>
|
|
<section xml:id="guestfish">
|
|
<title>guestfish</title>
|
|
<para>The <command>guestfish</command> program is a tool from the <link
|
|
xlink:href="http://libguestfs.org/">libguestfs</link> project that allows you to
|
|
modify the files inside of a virtual machine image.</para>
|
|
<para>Note that guestfish doesn't mount the image directly into the local filesystem.
|
|
Instead, it provides you with a shell interface that allows you to view, edit, and
|
|
delete files. Many of the guestfish commands (e.g., <command>touch</command>,
|
|
<command>chmod</command>, <command>rm</command>) are similar to traditional bash
|
|
commands.</para>
|
|
<simplesect>
|
|
<title>Example guestfish session</title>
|
|
<para>We often need to 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, since the MAC address will be different when it boots the next time.
|
|
In this example, we show how we can use guestfish to remove references to the old
|
|
MAC address by deleting the
|
|
<filename>/etc/udev/rules.d/70-persistent-net.rules</filename> file and removing
|
|
the <literal>HWADDR</literal> line from the
|
|
<filename>/etc/sysconfig/network-scripts/ifcfg-eth0</filename> file.</para>
|
|
<para>Assume we have a CentOS qcow2 image called
|
|
<filename>centos63_desktop.img</filename>. We would mount the image in
|
|
read-write mode by doing, as root:
|
|
<screen><prompt>#</prompt> <userinput>guestfish --rw -a centos63_desktop.img</userinput>
|
|
<computeroutput>
|
|
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></computeroutput></screen>This
|
|
starts a guestfish session. Note that the guestfish prompt looks like a fish:
|
|
<literal>> <fs></literal>.</para>
|
|
<para>We must first use the <command>run</command> 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.<screen><prompt>><fs></prompt> <userinput>run</userinput></screen>
|
|
We can now view the filesystems in the image using the
|
|
<command>list-filesystems</command>
|
|
command:<screen><prompt>><fs></prompt> <userinput>list-filesystems</userinput>
|
|
<computeroutput>/dev/vda1: ext4
|
|
/dev/vg_centosbase/lv_root: ext4
|
|
/dev/vg_centosbase/lv_swap: swap</computeroutput></screen>We
|
|
need to mount the logical volume that contains the root partition:
|
|
<screen><prompt>><fs></prompt> <userinput>mount /dev/vg_centosbase/lv_root /</userinput></screen></para>
|
|
<para>Next, we want to delete a file. We can use the <command>rm</command> guestfish
|
|
command, which works the same way it does in a traditional shell.</para>
|
|
<para><screen><prompt>><fs></prompt> <userinput>rm /etc/udev/rules.d/70-persistent-net.rules</userinput></screen>We
|
|
want to edit the <filename>ifcfg-eth0</filename> file to remove the
|
|
<literal>HWADDR</literal> line. The <command>edit</command> command will copy
|
|
the file to the host, invoke your editor, and then copy the file back.
|
|
<screen><prompt>><fs></prompt> <userinput>edit /etc/sysconfig/network-scripts/ifcfg-eth0</userinput></screen></para>
|
|
<para>If you want to modify this image to load the 8021q
|
|
kernel at boot time, you must create an executable
|
|
script in the
|
|
<filename>/etc/sysconfig/modules/</filename>
|
|
directory. You can use the <command>touch</command>
|
|
guestfish command to create an empty file, the
|
|
<command>edit</command> command to edit it, and
|
|
the <command>chmod</command> command to make it
|
|
executable.<screen><prompt>><fs></prompt> <userinput>touch /etc/sysconfig/modules/8021q.modules</userinput>
|
|
<prompt>><fs></prompt> <userinput>edit /etc/sysconfig/modules/8021q.modules</userinput></screen>
|
|
We add the following line to the file and save
|
|
it:<programlisting>modprobe 8021q</programlisting>Then
|
|
we set to executable:
|
|
<screen>><fs> <userinput>chmod 0755 /etc/sysconfig/modules/8021q.modules</userinput></screen></para>
|
|
<para>We're done, so we can exit using the <command>exit</command>
|
|
command:<screen><prompt>><fs></prompt> <userinput>exit</userinput></screen></para>
|
|
</simplesect>
|
|
<simplesect>
|
|
<title>Going further with guestfish</title>
|
|
<para>There 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 <link
|
|
xlink:href="http://libguestfs.org/guestfs-recipes.1.html">guestfs-recipes</link>
|
|
documentation page for a sense of what is possible with these tools.</para>
|
|
</simplesect>
|
|
</section>
|
|
<section xml:id="guestmount">
|
|
<title>guestmount</title>
|
|
<para>For some types of changes, you may find it easier to mount the image's filesystem
|
|
directly in the guest. The <command>guestmount</command> program, also from the
|
|
libguestfs project, allows you to do so.</para>
|
|
<para>For example, to mount the root partition from our
|
|
<filename>centos63_desktop.qcow2</filename> image to <filename>/mnt</filename>, we
|
|
can do:</para>
|
|
<para>
|
|
<screen><prompt>#</prompt> <userinput>guestmount -a centos63_desktop.qcow2 -m /dev/vg_centosbase/lv_root --rw /mnt</userinput></screen>
|
|
</para>
|
|
<para>If we didn't know in advance what the mountpoint is in the guest, we could use the
|
|
<literal>-i</literal>(inspect) flag to tell guestmount to automatically determine
|
|
what mount point to
|
|
use:<screen><prompt>#</prompt> <userinput>guestmount -a centos63_desktop.qcow2 -i --rw /mnt</userinput></screen>Once
|
|
mounted, we could do things like list the installed packages using
|
|
rpm:<screen><prompt>#</prompt> <userinput>rpm -qa --dbpath /mnt/var/lib/rpm</userinput></screen>
|
|
Once done, we
|
|
unmount:<screen><prompt>#</prompt> <userinput>umount /mnt</userinput></screen></para>
|
|
</section>
|
|
<section xml:id="virt-tools">
|
|
<title>virt-* tools</title>
|
|
<para>The <link xlink:href="http://libguestfs.org/">libguestfs</link> project has a number
|
|
of other useful tools, including:<itemizedlist>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-edit.1.html">virt-edit</link> for
|
|
editing a file inside of an image.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-df.1.html">virt-df</link> for
|
|
displaying free space inside of an image.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-resize.1.html"
|
|
>virt-resize</link> for resizing an image.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-sysprep.1.html"
|
|
>virt-sysprep</link> for preparing an image for distribution (e.g.,
|
|
delete SSH host keys, remove MAC address info, remove user accounts).</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-sparsify.1.html"
|
|
>virt-sparsify</link> for making an image sparse</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-v2v/">virt-p2v</link> for
|
|
converting a physical machine to an image that runs on KVM</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://libguestfs.org/virt-v2v/">virt-v2v</link> for
|
|
converting Xen and VMWare images to KVM images</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
<simplesect>
|
|
<title>Modify a single file inside of an image</title>
|
|
<para>This example shows how to use <command>virt-edit</command> to modify a file. The
|
|
command can take either a filename as an argument with the <literal>-a</literal>
|
|
flag, or a domain name as an argument with the <literal>-d</literal> flag. The
|
|
following examples shows how to use this to modify the
|
|
<filename>/etc/shadow</filename> file in instance with libvirt domain name
|
|
<literal>instance-000000e1</literal> that is currently running:</para>
|
|
<para>
|
|
<screen><prompt>#</prompt> <userinput>virsh shutdown instance-000000e1</userinput>
|
|
<prompt>#</prompt> <userinput>virt-edit -d instance-000000e1 /etc/shadow</userinput>
|
|
<prompt>#</prompt> <userinput>virsh start instance-000000e1</userinput></screen>
|
|
</para>
|
|
</simplesect>
|
|
<simplesect>
|
|
<title>Resize an image</title>
|
|
<para>Here's a simple of example of how to use <command>virt-resize</command> to resize
|
|
an image. Assume we have a 16GB Windows image in qcow2 format that we want to resize
|
|
to 50GB. First, we use <command>virt-filesystems</command> to identify the
|
|
partitions:<screen><prompt>#</prompt> <userinput>virt-filesystems --long --parts --blkdevs -h -a /data/images/win2012.qcow2</userinput>
|
|
<computeroutput>Name Type MBR Size Parent
|
|
/dev/sda1 partition 07 350M /dev/sda
|
|
/dev/sda2 partition 07 16G /dev/sda
|
|
/dev/sda device - 16G -
|
|
</computeroutput></screen></para>
|
|
<para>In this case, it's the <filename>/dev/sda2</filename> partition that we want to
|
|
resize. We create a new qcow2 image and use the <command>virt-resize</command>
|
|
command to write a resized copy of the original into the new
|
|
image<screen><prompt>#</prompt> <userinput>qemu-img create -f qcow2 /data/images/win2012-50gb.qcw2 50G</userinput>
|
|
<prompt>#</prompt> <userinput>virt-resize --expand /dev/sda2 /data/images/win2012.qcow2 /data/images/win2012-50gb.qcow2</userinput>
|
|
<computeroutput>Examining /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.
|
|
</computeroutput></screen></para>
|
|
</simplesect>
|
|
</section>
|
|
<section xml:id="losetup-kpartx-nbd">
|
|
<title>Loop devices, kpartx, network block devices</title>
|
|
<para>If 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.<warning>
|
|
<para>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 <link
|
|
xlink:href="https://www.berrange.com/posts/2013/02/20/a-reminder-why-you-should-never-mount-guest-disk-images-on-the-host-os/"
|
|
>A reminder why you should never mount guest disk images on the host
|
|
OS</link> by Daniel Berrangé for more details.</para>
|
|
</warning></para>
|
|
<simplesect>
|
|
<title>Mounting a raw image (without LVM)</title>
|
|
<para>If you have a raw virtual machine image that is not using LVM to manage its
|
|
partitions. First, use the <command>losetup</command> command to find an unused loop
|
|
device.
|
|
<screen><prompt>#</prompt> <userinput>losetup -f</userinput>
|
|
<computeroutput>/dev/loop0</computeroutput></screen></para>
|
|
<para>In this example, <filename>/dev/loop0</filename> is free. Associate a loop device
|
|
with the raw
|
|
image:<screen><prompt>#</prompt> <userinput>losetup /dev/loop0 fedora17.img</userinput></screen></para>
|
|
<para>If the image only has a single partition, you can mount the loop device
|
|
directly:<screen><prompt>#</prompt> <userinput>mount /dev/loop0 /mnt</userinput></screen></para>
|
|
<para>If the image has multiple partitions, use <command>kpartx</command> to expose the
|
|
partitions as separate devices (e.g., <filename>/dev/mapper/loop0p1</filename>),
|
|
then mount the partition that corresponds to the root file
|
|
system:<screen><prompt>#</prompt> <userinput>kpartx -av /dev/loop0</userinput></screen></para>
|
|
<para>If the image has, say three partitions (/boot, /, /swap), there should be one new
|
|
device created per
|
|
partition:<screen><prompt>$</prompt> <userinput>ls -l /dev/mapper/loop0p*</userinput><computeroutput>
|
|
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/loop0p3</computeroutput></screen>To
|
|
mount the second partition, as
|
|
root:<screen><prompt>#</prompt> <userinput>mkdir /mnt/image</userinput>
|
|
<prompt>#</prompt> <userinput>mount /dev/mapper/loop0p2 /mnt</userinput></screen>Once
|
|
you're done, to clean
|
|
up:<screen><prompt>#</prompt> <userinput>umount /mnt</userinput>
|
|
<prompt>#</prompt> <userinput>kpartx -d /dev/loop0</userinput>
|
|
<prompt>#</prompt> <userinput>losetup -d /dev/loop0</userinput></screen></para>
|
|
</simplesect>
|
|
<simplesect>
|
|
<title>Mounting a raw image (with LVM)</title>
|
|
<para>If your partitions are managed with LVM, use losetup and kpartx as in the previous
|
|
example to expose the partitions to the
|
|
host:</para><screen><prompt>#</prompt> <userinput>losetup -f</userinput>
|
|
<computeroutput>/dev/loop0</computeroutput>
|
|
<prompt>#</prompt> <userinput>losetup /dev/loop0 rhel62.img</userinput>
|
|
<prompt>#</prompt> <userinput>kpartx -av /dev/loop0</userinput></screen>
|
|
<para>Next, you need to use the <command>vgscan</command> command to identify the LVM
|
|
volume groups and then <command>vgchange</command> to expose the volumes as
|
|
devices:</para><screen><prompt>#</prompt> <userinput>vgscan</userinput>
|
|
<computeroutput>Reading all physical volumes. This may take a while...
|
|
Found volume group "vg_rhel62x8664" using metadata type lvm2</computeroutput>
|
|
<prompt>#</prompt> <userinput>vgchange -ay</userinput>
|
|
<computeroutput> 2 logical volume(s) in volume group "vg_rhel62x8664" now active</computeroutput>
|
|
<prompt>#</prompt> <userinput>mount /dev/vg_rhel62x8664/lv_root /mnt</userinput></screen>
|
|
<para>Clean up when you're
|
|
done:</para><screen><prompt>#</prompt> <userinput>umount /mnt</userinput>
|
|
<prompt>#</prompt> <userinput>vgchange -an vg_rhel62x8664</userinput>
|
|
<prompt>#</prompt> <userinput>kpartx -d /dev/loop0</userinput>
|
|
<prompt>#</prompt> <userinput>losetup -d /dev/loop0</userinput></screen>
|
|
</simplesect>
|
|
<simplesect>
|
|
<title>Mounting a qcow2 image (without LVM)</title>
|
|
<para>You need the <literal>nbd</literal> (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:<screen><prompt>#</prompt> <userinput>modprobe nbd max_part=16</userinput></screen></para>
|
|
<para>Assuming the first block device (<filename>/dev/nbd0</filename>) is not currently
|
|
in use, we can expose the disk partitions using the <command>qemu-nbd</command> and
|
|
<command>partprobe</command> commands. As
|
|
root:<screen><prompt>#</prompt> <userinput>qemu-nbd -c /dev/nbd0 image.qcow2</userinput>
|
|
<prompt>#</prompt> <userinput>partprobe /dev/nbd0</userinput></screen></para>
|
|
<para>If the image has, say three partitions (/boot, /, /swap), there should be one new
|
|
device created for each partition:</para>
|
|
<screen><prompt>$</prompt> <userinput>ls -l /dev/nbd3*</userinput>
|
|
<computeroutput>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/nbd0p3</computeroutput></screen>
|
|
<note><para>If the network block device you selected was already in use, the initial
|
|
<command>qemu-nbd</command> command will fail silently, and the
|
|
<filename>/dev/nbd3p{1,2,3}</filename> device files will not be
|
|
created.</para></note>
|
|
<para>If the image partitions are not managed with LVM, they can be mounted
|
|
directly:</para><screen><prompt>#</prompt> <userinput>mkdir /mnt/image</userinput>
|
|
<prompt>#</prompt> <userinput>mount /dev/nbd3p2 /mnt</userinput></screen>
|
|
<para>When you're done, clean
|
|
up:</para><screen><prompt>#</prompt> <userinput>umount /mnt</userinput>
|
|
<prompt>#</prompt> <userinput>qemu-nbd -d /dev/g nbd0</userinput></screen>
|
|
</simplesect>
|
|
<simplesect>
|
|
<title>Mounting a qcow2 image (with LVM)</title>
|
|
<para>If the image partitions are managed with LVM, after you use
|
|
<command>qemu-nbd</command> and <command>partprobe</command>, you must use
|
|
<command>vgscan</command> and <command>vgchange -ay</command> in order to expose
|
|
the LVM partitions as devices that can be
|
|
mounted:<screen><prompt>#</prompt> <userinput>modprobe nbd max_part=16</userinput>
|
|
<prompt>#</prompt> <userinput>qemu-nbd -c /dev/nbd0 image.qcow2</userinput>
|
|
<prompt>#</prompt> <userinput>partprobe /dev/nbd0</userinput><prompt>#</prompt> <userinput>vgscan</userinput>
|
|
<computeroutput> Reading all physical volumes. This may take a while...
|
|
Found volume group "vg_rhel62x8664" using metadata type lvm2</computeroutput>
|
|
<prompt>#</prompt> <userinput>vgchange -ay</userinput>
|
|
<computeroutput> 2 logical volume(s) in volume group "vg_rhel62x8664" now active</computeroutput>
|
|
<prompt>#</prompt> <userinput>mount /dev/vg_rhel62x8664/lv_root /mnt</userinput></screen></para>
|
|
<para>When you're done, clean
|
|
up:<screen><prompt>#</prompt> <userinput>umount /mnt</userinput>
|
|
<prompt>#</prompt> <userinput>vgchange -an vg_rhel62x8664</userinput>
|
|
<prompt>#</prompt> <userinput>qemu-nbd -d /dev/nbd0</userinput></screen></para>
|
|
</simplesect>
|
|
</section>
|
|
</chapter>
|