Manually clone a VMWare Virtual machine from the shell

1230

Introduction

Sometimes you’ve VMWare appliances and you need to get a physical copy instantly and you don’t have VMWare Tools with you or you’re doing everything from command line (on a remote console), sometimes you don’t even have VMWare (ESX/GSX/VSphere/player) installed or you’ve just the Player (no cloning from there) but you still need to get a clone of a working machine. I usually create my own appliances with my own utilities, packages and tools installed, I store them as .TAR.GZ and I use them as a base for new machines. Here’s what I do to have an exact copy of a machine; it’s not a geek trick, it’s just a plain basic task, this always works, no matter about the OS inside your VM (Win/Linux/BSD/Plan9/BeOS/…).

 

First: of all you need to do is stop your source machine (in my example “Debian 6”) and locate its directory, then copy the whole source Dir to a new path (in my example “new.machine”)

$ cp -R Debian 6   new.machine
$ ls -la new.machine/
total 534520
drwxr-xr-x 2 ben ben 4096 2011-02-09 09:53 .
drwxr-xr-x 12 ben ben 4096 2011-02-09 09:53 ..
-rw------- 1 ben ben 8684 2011-02-09 09:53 Debian 6.nvram
-rw------- 1 ben ben 211550208 2011-02-09 09:53 Debian 6-s001.vmdk
-rw------- 1 ben ben 234356736 2011-02-09 09:53 Debian 6-s002.vmdk
-rw------- 1 ben ben 107347968 2011-02-09 09:53 Debian 6-s003.vmdk
-rw------- 1 ben ben 2621440 2011-02-09 09:53 Debian 6-s004.vmdk
-rw------- 1 ben ben 65536 2011-02-09 09:53 Debian 6-s005.vmdk
-rw------- 1 ben ben 639 2011-02-09 09:53 Debian 6.vmdk
-rw-r--r-- 1 ben ben 0 2011-02-09 09:53 Debian 6.vmsd
-rwxr-xr-x 1 ben ben 1652 2011-02-09 09:53 Debian 6.vmx
-rw-r--r-- 1 ben ben 263 2011-02-09 09:53 Debian 6.vmxf
-rw-r--r-- 1 ben ben 88558 2011-02-09 09:53 vmware-0.log
-rw-r--r-- 1 ben ben 49667 2011-02-09 09:53 vmware-1.log
-rw-r--r-- 1 ben ben 64331 2011-02-09 09:53 vmware-2.log
-rw-r--r-- 1 ben ben 63492 2011-02-09 09:53 vmware.log

Now delete unnecessary files like the logs

$ rm *.log

Do a massive rename, source/previous virtual machine was named “Debian 6”, you need to replace it with “new.machine” (our new name)

$ mv "Debian 6.nvram" new.machine.nvram
$ mv "Debian 6-s001.vmdk" new.machine-s001.vmdk
$ mv "Debian 6-s002.vmdk" new.machine-s002.vmdk
$ mv "Debian 6-s003.vmdk" new.machine-s003.vmdk
$ mv "Debian 6-s004.vmdk" new.machine-s004.vmdk
$ mv "Debian 6-s005.vmdk" new.machine-s005.vmdk
$ mv "Debian 6.vmdk" new.machine.vmdk
$ mv "Debian 6.vmsd" new.machine.vmsd
$ mv "Debian 6.vmx" new.machine.vmx
$ mv "Debian 6.vmxf" new.machine.vmxf

NOTE: .vmxf file is present on newer releases of VMWare appliances, if you don’t have it just ignore it

Now it’s time to change information inside your virtual machines, you just need to use your favorite text editor to change few things, keep this files as they’re

new.machine-s*
new.machine.nvram
new.machine.vmsd

NVRam is your bios/nvram, it’s a binary file and you don’t need to change it, *.vmdk are your disks, you just need to change the information header of the disk (new.machine.vmdk), leave the other VMDK files as they are (new.machine-s*.vmdk); VMSD file is usually empty, don’t need to change it.

 

Modify your hard disks

If you’ve more than one hard disk you’ve more than one .VMDK master file, you need to apply few mods on it, here’s the content of the original file (was “Debian 6.vmdk”, now “new.machine.vmdk”)

# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=71ad0a67
parentCID=ffffffff
isNativeSnapshot="no"
createType="twoGbMaxExtentSparse"

# Extent description
RW 4192256 SPARSE "Debian 6-s001.vmdk"
RW 4192256 SPARSE "Debian 6-s002.vmdk"
RW 4192256 SPARSE "Debian 6-s003.vmdk"
RW 4192256 SPARSE "Debian 6-s004.vmdk"
RW 8192 SPARSE "Debian 6-s005.vmdk"

# The Disk Data Base
#DDB
ddb.virtualHWVersion = "7"
ddb.longContentID ="86aa7ebbb50ab88b973ea60271ad0a67"
ddb.uuid = "60 00 C2 9f 9a e3 43 6a-ea 70 c7 fa 35 72 7c 04"
ddb.geometry.cylinders = "1044"
ddb.geometry.heads = "255"
ddb.geometry.sectors = "63"
ddb.adapterType = "lsilogic"

Row order and content may vary, VMWare configuration files don’t have a fixed order, you may change row order, add comments and some other stuff inside it. Here’s what you need to change:

RW 4192256 SPARSE "new.machine-s001.vmdk"
RW 4192256 SPARSE "new.machine-s002.vmdk"
RW 4192256 SPARSE "new.machine-s003.vmdk"
RW 4192256 SPARSE "new.machine-s004.vmdk"
RW 8192 SPARSE "new.machine-s005.vmdk"

So all you need to do is change references to physical hard disk files, nothing more, just change the lines above in your new.machine.vmdk file and nothing else

 

Other Descriptors

It’s time to change the VMXF file (extra configs from VMWare), if you don’t have it, just skip this step. Your new.machine.vmxf file could be something like that:

52 62 73 9d 7f 10 1b 58-8e 3c 8e 15 8e ef f4 a3 Debian 6.vmx

It’s an XML file as you may see, content and VMIDs may change a little bit but it doesn’t matter. All you need to do here is to replace this string:

Debian 6.vmx

with this one

new.machine.vmx

and nothing more, here’s the result:

52 62 73 9d 7f 10 1b 58-8e 3c 8e 15 8e ef f4 a3 new.machine.vmx

VMX Main configuration file

new.machine.vmx is the machine main configuration file, inside it you find hardware description and file references, it may vary a lot according to virtual hardware, player version and hardware machine version, here’s a copy of my new.machine.vmx (original copy from Debian 6.vmx)

.encoding = "UTF-8"
config.version = "8"
virtualHW.version = "7"
scsi0.present = "TRUE"
scsi0.virtualDev = "lsilogic"
memsize = "256"
scsi0:0.present = "TRUE"
scsi0:0.fileName = "Debian 6.vmdk"
ethernet0.present = "TRUE"
ethernet0.connectionType = "bridged"
ethernet0.wakeOnPcktRcv = "FALSE"
ethernet0.addressType = "generated"
pciBridge0.present = "TRUE"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge4.functions = "8"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
vmci0.present = "TRUE"
roamingVM.exitBehavior = "go"
displayName = "Debian 6"
guestOS = "other26xlinux"
nvram = "Debian 6.nvram"
virtualHW.productCompatibility = "hosted"
gui.exitOnCLIHLT = "FALSE"
extendedConfigFile = "Debian 6.vmxf"
ethernet0.generatedAddress = "00:0c:29:b1:8b:e6"
uuid.location = "56 4d 05 92 24 e8 b0 b3-f7 37 1f d9 51 b1 8b e6"
uuid.bios = "56 4d 05 92 24 e8 b0 b3-f7 37 1f d9 51 b1 8b e6"
cleanShutdown = "TRUE"
replay.supported = "FALSE"
replay.filename = ""
scsi0:0.redo = ""
pciBridge0.pciSlotNumber = "17"
pciBridge4.pciSlotNumber = "21"
pciBridge5.pciSlotNumber = "22"
pciBridge6.pciSlotNumber = "23"
pciBridge7.pciSlotNumber = "24"
scsi0.pciSlotNumber = "16"
ethernet0.pciSlotNumber = "32"
vmci0.pciSlotNumber = "34"
vmotion.checkpointFBSize = "16777216"
ethernet0.generatedAddressOffset = "0"
vmci0.id = "1370590182"
vmi.present = "FALSE"
ide1:0.present = "FALSE"
floppy0.present = "FALSE"

Now let’s focus on the changes, it’s basically straightforward to understand it but I need to mention:

change previous VMDK references to newly created hard disk, basically you need to replace “Debian 6.vmdk” with “new.machine.vmdk” everywhere in your file (just one occurrence)

scsi0:0.fileName = "new.machine.vmdk"

Now it’s time to change the label for your new machine in the Server (ESX,GSX,VSphere) or Player with your favorite name (“My new Machine Name” in my case), here’s:

displayName = "My new Machine Name"

NVRam file with the new name:

nvram = "new.machine.nvram"

Extended configuration file (only if this is present) with the new one:

extendedConfigFile = "new.machine.vmxf"

Now change the Ethernet mac address with a new one or your machines cannot be on the same network with the same address (as in real cases), just respect mac address notations and change something random in it

ethernet0.generatedAddress = "00:0c:29:b1:ab:ab"

You may change UIDs inside the file but you don’t need to bother about them. Save everything and import your newly created/cloned machine inside your favorite player/server.

 

Ready, Set, Go!

Locate your new .VMX file and open it with your Server/Player, you’ll see your new machine inside the remote/local repository and you’re ready to start it.

We didn’t change the machine UID because it’s not necessary, VMWare will do it for us, when you run your machine the first time you’ll see a window like this

Just select “I copied it” button and VMWare will generate the serial UID for the new machine. Now the machine runs an exact copy of your previous one with the same operating system and configurations inside it, please read these hints to solve possible problems:

  • If you’re using a static IP address you need to change it in your new machine to avoid conflicts with the previous one (obviously)

  • If you’re using a MS Windows OS you need to change the machine name or you’ll have a “name duplicated” error when you start the machine, just change the name and make a new reboot

  • If you’re serving clients with a basic service (DHCP, DNS, MS Domain Controller) you need to stop it or you’ll have few network troubles (as with real servers) due to two services running in the same network (two DHCP servers in the same net are a bad thing…)

  • udev troubles and linux networking, please read below if you’re running a perfect Linux machine but without networking capabilities

 

No networking ? Please read

Everything is fine with your new virtual machine but…. you don’t have a network card properly configured ? Keep reading.

If you’re using UDEVD (http://linuxmanpages.com/man8/udevd.8.php) you may have a problem, it’s just a minor trouble as you’ll see.

UDEVD defines plugged network cards in a proper configuration file, network cards are located generally in /etc/udev/rules.d, there’s a file called: “z25_persistent-net.rules” | “70-persistent-net.rules” (Debian | Gentoo) or something like that, it’s not hard to find it (or let me know and I’ll add your information here), generically it’s called *persistent-net.rules, let’s see it to understand how it works:

~$ cat /etc/udev/rules.d/70-persistent-net.rules
# This file was automatically generated by the /lib64/udev/write_net_rules
# program run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single line.


# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", DRIVERS=="?*", ATTR{address}=="00:21:85:c1:79:37", KERNEL=="eth*", NAME="eth0"

 

Here’s the “old” network card (the one you cloned), it’s called “eth0” and this card is not available any more (you’ve just changed the mac address), you may:

  • Delete the line reporting the “eth0” device, just delete this line

  • Change the line with the proper mac address (the one you’ve changed in the VMX file)

I usually prefer to delete the line so a new one will be created for you on the next reboot

 

NOTE: If you’ve a line with “eth1” device and you don’t have two network cards it means UDEVD has created the line for your with your new (according to him) network card and it left the previous one already there and configured, you may remove eth0 line and rename eth1 to eth0 OR delete both lines. UDEVD will recreate what it needs on the next reboot, don’t change your network configuration (etc/networking and so on), just leave UDEVD with the proper card and you’ll see it running fine from the next boot

NOTE SAMPLE: If you’re following my own example with a Debian 6 installation you don’t need to worry about udev, previous versions (etc, lenny, …) are affected by this


IMPROVED SCRIPT
: After few comments reported on this blog I’ve decided to write a new blog with an automated script, the script does everything reported it by itself, check it out here


I hope this small guide will assist you in some way if you decide to clone your VMWare machines on your own, file formats are basically the same for a long time and that’s what I do for basic sys Admin when I don’t have the hypervisor or proper tools with me.

Share your comments

Hope it helps

 

Andrea (Ben) Benini