Check for these CPU extensions:
# grep -E 'svm|vmx' /proc/cpuinfo
- vmx is for Intel processors
- svm is for AMD processors

Install Packages
There are several RPMs to install that are not part of the base RHEL 6 installation. Assuming that you have a yum repository, install the following:
# yum install kvm python-virtinst libvirt libvirt-python virt-manager virt-viewer libguestfs-tools
Verify the following kernel modules are loaded, and if not load manually:
kvm
kvm_intel (only on Intel-based systems)

Networking
By default, the VMs will only have network access to other VMs on the same server (and to the host itself) via private network 192.168.122.0. If you want the VMs to have access to your LAN, then you must create a network bridge on the host. Follow these steps to create a network bridge:
1. Turn off NetworkManager (the network bridge does not like it) and use the network service instead. Be sure to set the NM_CONTROLLED=NO parameter in the network controller configuration file.
# chkconfig NetworkManager off
# chkconfig network on
# service NetworkManager stop
# service network start
2. Add to your network controller configuration file (presumably /etc/sysconfig/network-scripts/ifcfg-eth0) the following line:
BRIDGE=br0
3. Create /etc/sysconfig/network-scripts/ifcfg-br0 and add:
DEVICE="br0"
# BOOTPROTO is your preference. It can be “dhcp” or “static”.
# If “static”, be sure to specify the IP address, netmask and gateway.
BOOTPROTO="dhcp"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Bridge"
DELAY="0"
4. Create a FORWARD firewall rule for the bridge br0 so that VM network traffic can be forwarded through it. This rule works for all bridge devices:
# iptables -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT
# service iptables save
5. Enable forwarding. Edit /etc/sysctl.conf:
inet.ipv4.ip_forward = 1
And read the file:
# sysctl -p /etc/sysctl.conf
6. Restart the network service so that the network bridge you just created can get an IP address:
# service network restart

SELinux
If you are using SELinux in Enforcing mode, then there are some things to consider. The most common issue is when you use a non-default directory for your VM p_w_picpaths. If you use a directory other than /var/lib/libvirt/p_w_picpaths, then you must change the security context for that directory. For example, let?s say you select /vm-p_w_picpaths to place your VM p_w_picpaths:
1. Create the directory:
# mkdir /vm-p_w_picpaths
2. Install the policycoreutils-python package (which contains the semanage SELinux utility):
# yum -y install policycoreutils-python
3. Set the security context for the directory and everything under it:
# semanage fcontext --add -t virt_p_w_picpath_t '/vm-p_w_picpaths(/.*)?'
Verify it:
# semanage fcontext -l | grep virt_p_w_picpath_t
4. Restore the security context. This will effectively change the context to virt_p_w_picpath_t:
# restorecon -R -v /vm-p_w_picpaths
Verify that the context was changed:
# ls –aZ /vm-p_w_picpaths
drwxr-xr-x. root root system_u:object_r:virt_p_w_picpath_t:s0 .
dr-xr-xr-x. root root system_u:object_r:root_t:s0 ..
5. If you are going to export the directory /vm-p_w_picpaths as a samba or NFS share, there are SELinux Booleans that need to be set as well:
# setsebool -P virt_use_samba 1
# setsebool -P virt_use_nfs 1

Creating VMs
Installation of VMs using the virt-install tool is very straight-forward. This tool can run in interactive or non-interactive mode. Let us use virt-install in non-interactive mode to create a RHEL 6.1 x64 VM named vm1 with one virtual CPU, 1 GB memory and 10 GB of disk space:
# virt-install \
--network bridge:br0 \
--name vm1 \
--ram=1024 \
--vcpus=1 \
--disk path=/vm-p_w_picpaths/vm1.img,size=10 \
--graphics none \
--location=http://my.server.com/pub/rhel6.1/install-x86_64/ \
--extra-args="console=tty0 console=ttyS0,115200"
 --network bridge:br0
If you created a network bridge (as specified in Chapter I, steps 6-10) and want to use it for full inbound and outbound connectivity, then you must specify it.
 --name vm1
No big mystery here, this is the name of the VM
 --ram=1024
This is the amount of memory in the VM in MBs
 --vcpus=1
You guessed it, this is the number of virtual CPUs
 --disk path=/vm-p_w_picpaths/vm1.img,size=10
This is the p_w_picpath file for the VM, the size is specified in GBs.
 --graphics none
This tells the installer not to launch a VNC window to access the VM?s main console. Instead, it will use a text console on the VM?s serial port. If you rather use an X window with graphics to install the OS on the VM, omit this parameter.
 --location=http://my.server.com/pub/rhel6.1/install-x86_64/
This is the location of the RHEL 6.1 x64 installation directory, which of course will be different for you. If you don?t have a remote installation location for the OS, you can install from an iso instead. Instead of using the location parameter, use the cdrom parameter:
--cdrom /root/RHEL6.1-20110510.1-Server-x86_64-DVD1.iso
 --extra-args="console=tty0 console=ttyS0,115200"
The extra-args parameter is used to pass kernel boot parameters to the OS installer. In this case, since we are connecting to the VM?s serial port, we must the proper kernel parameters to set it up, just like we would on any server, virtual or not.
The extra-args parameter can also be used to specify a kickstart file for non-interactive installations. So if we had a kickstart file we would use:
--extra-args="ks=http://my.server.com/pub/ks.cfg console=tty0 console=ttyS0,115200”
The OS installation on the VM proceeds as with a physical server, where you provide information such as disk partitions, time zone, root password, etc.
Here is another example: Install a RHEL 6.0 x86 VM with 2 VCPUs, 2GB of memory, 15GB disk space, using the default network (private VM network), install from a local iso on the host and use VNC to interact with the VM (must have an X server running):
# virt-install \
--name vm1 \
--ram=2048 \
--vcpus=2 \
--disk path=/vm-p_w_picpaths/vm1.img,size=15 \
--cdrom /root/RHEL6.0-20100922.1-Server-i386-DVD1.iso
For more information on all virt-install parameters, refer to the virt-install man page.

Cloning VMs
If you want several VMs with the same OS and same configuration, I recommend cloning existing VMs rather than installing the OS on each one, which can quickly become a time-consuming & tedious task. In this example, we clone vm1 to create a new VM clone called vm1-clone:
1. Suspend the VM to be cloned. This is a requirement since it ensures that all data and network I/O on the VM is stopped.
# virsh suspend vm1
2. Run the virt-clone command:
# virt-clone \
--connect qemu:///system \
--original vm1 \
--name vm1-clone \
--file /vm-p_w_picpaths/vm1-clone.img
This operation will take 2-3 minutes, depending on the size of the VM.
3. When done, you can resume the original VM:
# virsh resume vm1
4. The cloned VM is placed in shutdown mode. To start it:
# virsh start vm1-clone
The cloned VM is an exact copy of the original VM, all VM properties (VCPUs, memory, disk space) and disk contents will be the same. The virt-clone command takes care to generate a new MAC address for the VM clone and updates the proper network controller configuration file (i.e. /etc/sysconfig/network-scripts/ifcfg-eth0), thus avoiding duplicate MAC addresses.
For more information, refer to the virt-clone man page.

Managing VMs
These are some of the commands I use to administer my VMs, and to be honest I don?t use them very often, but they can be handy. As always, for a list of all available commands, your best bet is the virsh man page.
Common tasks
1.List all VMs on a host, running or otherwise:
# virsh list –all
2.Show VM information:
# virsh dominfo vm1
3.Show VCPU/memory usage for all running VMs:
# virt-top
4.Show VM disk partitions:
# virt-df vm1
5.Stop a VM (shutdown the OS):
# virsh shutdown vm1
6.Start VM:
# virsh start vm1
7.Mark VM for autostart (VM will start automatically after host reboots):
# virsh autostart vm1
8.Mark VM for manual start (VM will not start automatically after host reboots):
# virsh autostart –disable vm1
9.Getting access to a VMs console
If you do not have an X server running on your host, connecting to a VMs serial console might be the only way to login to a VM if networking is not available. Setting up access to a VM’s console is no different than in a physical server, where you simply add the proper kernel boot parameters to the VM. For example, for a RHEL VM, append the following parameters to the kernel boot line in /etc/grub.conf and then reboot the VM:
console=tty0 console=ttyS0,115200
Then, after the VM boots, run in the host:
# virsh console vm1
10.Attaching USB storage device to a VM
Say you have files in a USB key that you want to copy to your VM. Rather than copying the files to your VM via the network, you can directly attach the USB key (or any USB storage device) to your VM, which will then appear as an additional storage device on your VM. First identify the device name of your USB storage device after you plug it in on the host. In this example, it will be /dev/sdb:
# virsh attach-disk vm1 /dev/sdb vdb --driver tap --mode shareable
 vdb is the device name you want to map to inside the VM
 you can mount your USB device to more than one VM at a time, but be careful as there is no write access control here.
You can now access the USB storage device directly from your VM at /dev/vdb. When you are done with it, simply detach it from your VM:
# virsh detach-disk vm1 vdb

GUI Tools
Ok so now I will mention a couple of GUI tools which I admit can be useful when managing and interacting with VMs.
 virt-viewer – Launches a VNC window that gives you access to a VMs main console.
 virt-manager – Launches a window where you can manage all your VMs. Among other things, you can start, pause & shutdown VMs, display VM details (VCPUs, memory, disk space), add devices to VMs and even create new VMs. I don't cover virt-manager here, but it is rather intuitive to use.

Changing VM parameters
You can easily change VM parameters after creating them, such as memory, VCPUs and disk space.
Memory
You can dynamically change the memory in a VM up to what its maximum memory setting is. Note that by default the maximum memory setting in a VM will always equal the amount of memory you specified when you created the VM with the ram parameter in virt-install.
So for example if you created a VM with 1 GB of memory, you can dynamically reduce this amount without having to shut down the VM. If you want to increase the memory above 1 GB, you will have to first increase its maximum memory setting which requires shutting down the VM first.
In our first example, let?s reduce the amount of memory in vm1 from 1 GB to 512 MB:
1. View the VM?s current memory settings:
# virsh dominfo vm1 | grep memory
Max memory: 1048576 kB
Used memory: 1048576 kB
2. To dynamically set to 512 MB, run:
# virsh setmem vm1 524288
Value must be specified in KB, so 512 MB x 1024 = 524288 KB
3. View memory settings:
# virsh dominfo vm1 | grep memory
Max memory: 1048576 kB
Used memory: 524288 kB
In our second example, let us increase the amount of memory in vm1 above from 512 MB to 2 GB:
1. In this case we will first need to increase the maximum memory setting. The best way to do it is by editing the VM's configuration file. Shutdown the VM or you might see unexpected results:
# virsh shutdown vm1
2. Edit the VM?s configuration file:
# virsh edit vm1
Change the value inside the <memory> tab to:
<memory>2097152</memory>
Remember that the value is in KB. Save the file and exit.
3. Restart the VM from its updated configuration file:
# virsh create /etc/libvirt/qemu/vm1.xml
4. View memory settings:
# virsh dominfo vm1 | grep memory
Max memory: 2097152 kB
Used memory: 524288 kB
5. Now you can dynamically change the memory:
# virsh setmem vm1 2097152
Verify:
# virsh dominfo vm1 | grep memory
Max memory: 2097152 kB
Used memory: 2097152 kB

VCPUs
To change the number of virtual CPUs in a VM, change the number in the vcpu tag in the VM?s configuration file. For example, let?s change the number of virtual CPUs to 2:
# virsh shutdown vm1
# virsh edit vm1
<vcpu>2</vcpu>
# virsh create /etc/libvirt/qemu/vm1.xml

Disk capacity
You can always add additional ?disks? to your VMs by attaching additional file p_w_picpaths. Say that you want to add an additional 10 GB of disk space in your VM, here is what you do:
1. Create a 10-GB non-sparse file:
# dd if=/dev/zero of=/vm-p_w_picpaths/vm1-add.img bs=1M count=10240
2. Shutdown the VM:
# virsh shutdown vm1
3. Add an extra entry for ?disk? in the VM's XML file in /etc/libvirt/qemu. You can look copy & paste the entry for your mail storage device and just change the target and address tags. For example:
# virsh edit vm1
<disk type='file' device='disk'>
<driver name='qemu' type='raw' cache='none' io='threads'/>
<source file='/vm-p_w_picpaths/vm1.img'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</disk>
Add:
<disk type='file' device='disk'>
<driver name='qemu' type='raw' cache='none' io='threads'/>
<source file='/vm-p_w_picpaths/vm1-add.img'/>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
make sure that the name of the device (i.e. vdb) follows the first one in sequential order
for the address tag, be sure to use a unique slot address, check with the address tag of ALL devices (not just storage devices)
4. Restart the VM from the updated XML configuration file:
# virsh create /etc/libvirt/qemu/vm1.xml

Deleting VMs
When you no longer need a VM, it is best practice to remove it to free up its resources. A VM that is shutdown is not taking up a VCPU or memory, but its p_w_picpath file is still taking up disk space.
Deleting a VM is a lot faster than creating one, just a few quick commands. Let us delete vm1-clone:
1. First, shutdown the VM:
# virsh shutdown vm1-clone
If the VM is not responding or fails to shut down, shut it down forcefully:
# virsh destroy vm1-clone
2. Undefine the VMs configuration:
# virsh undefine vm1-clone
3. Finally, remove the VM’s p_w_picpath file:
# rm /vm-p_w_picpaths/vm1-clone.img