tags:

views:

30779

answers:

7

Is there a simple way to copy a VMware virtual machine? I want to do this for a few reasons, including making multiple backups of a machine's state, and duplicating system configurations so I can try out different ways of setting up a server.

Edit: Although it is possible to make linked clones and snapshots, I would really like to be able to make an independently functioning copy of the machine.

+2  A: 

Inside VMware there is a "clone" option

From help file:

Setting a Clone Template Choose: VM > Settings > Options > Advanced When you create a linked clone of a virtual machine, the clone depends on the parent virtual machine to function. If a linked clone is unable to access the parent virtual machine or the snapshot on which the clone is based, the clone no longer operates. You can avoid this problem by designating the parent virtual machine of a linked clone as a template. Normally, to clone a virtual machine, you must have write access to that virtual machine. A virtual machine that is designated as a clone template can be cloned by users who do not have write access to the template virtual machine. To designate this virtual machine as a template, select Enable Template mode. In order to protect linked clones, a template virtual machine cannot be deleted or added to a team. None of the template’s snapshots be deleted. For more information on linked clones, see Snapshot Actions and see the chapter about cloning virtual machines in the VMware Workstation User’s Manual.

Roman M
A: 

If "making multiple backups of a machine's state" and "try out different ways of setting up a server" is what your question is actually about, you don't want to copy the VM, but instead just take Snapshots. You can return to any of the snapshots at any time and even branch to another state. And from here, cloning is finally available, but you'll only need it to copy one of the snapshots to another machine.

Taking and restoring snapshots is, in my experience, much faster than cloning.

OregonGhost
+7  A: 

If you saved all VM files in the same directory, then just make a copy and it will work fine.
I have a few versions of Windows burnt on a DVD like that and they always work on any PC I put them.

mwore
This might not be enough if you expect to use that copy as a real working server. See this tip: http://stackoverflow.com/questions/898141/vmware-script-automatic-backups/904864#904864
Dan Tanner
+2  A: 

Make sure the machine is shutdown first, not supper important but just a good idea, then copy the entire directory somewhere else. When you open the VM from the VMWare interface, it will notice if it's not in the same directory and ask if you have moved or copied the VM. Obviously choose, copy. It really is pretty much that simple.

I VMWare workstation, you can make clones of VM's in other directories, and this pretty much does the same thing as copying them. Remember a linked clone is dependent on the VM it was created from, its simply a delta of it.

Brettski
However, making sure the machine is at least suspended, if not shut down, is super important. :-)
Chris Jester-Young
A: 

To get an independent copy you can copy the virtual machine directory or do a Full Clone from the VMware interface. I'd recommend using Clone rather than copy for the reasons below.

If you copy you will get the VM with all the snapshots you currently have. If you do a Full Clone you will just get the state you pick which will make the copy smaller than the original. Even if you don't have any snapshots doing a Full Clone can create a smaller copy so it's usually best to do this.

If you copy the files when you next start the VM you will get a message asking if you Moved or Copied the VM. If you answer "Copied" VMware will change the MAC addresses of the virtual network cards. If you select Full Clone the MAC address will always be changed without asking

If you want to network your copies together - or even just have them running at the same time - new MAC addresses are crucial.

However, some Linux distros will fix network interfaces to MAC addresses so you'll need to re-configure your networking after the copy. Alternatively, you can edit the configuration beforehand so Linux doesn't pay attention to the MAC address. Windows does not fix interfaces to hardware addresses so you won't see this problem.

Dave Webb
A: 

I've done full copies of VMware virtual machines before. The instruction manual (for VMware Server at least) says that you have to suspend the virtual machine while it's being backed up, if it's currently running.

I wrote a script for doing VMware virtual machine backups, too. It may or may not work for you; if you wish to use it, try it on a test virtual machine first, and make sure it does what you need before deploying it fully. :-)

#!/usr/bin/perl -w
use strict;
use Carp;
use Fcntl qw(:mode);
use POSIX qw(:sys_wait_h);

use File::Spec;
use IO::Dir;
use VMware::VmPerl;
use VMware::VmPerl::ConnectParams;
use VMware::VmPerl::VM;

sub timestamp($) {
    my ($message) = @_;
    printf STDERR "%s %s\n", scalar localtime, $message;
}

sub throw($) {
    my ($vm) = @_;
    my ($err, $errstr) = $vm->get_last_error;
    croak "VMControl error $err: $errstr";
}

sub process($$) {
    my ($vm, $proc) = @_;
    if ($vm->get_execution_state == VM_EXECUTION_STATE_ON) {
        my $name = $vm->get_config_file_name;
        timestamp "Suspending $name";
        $vm->suspend(VM_POWEROP_MODE_TRYSOFT) or throw $vm;
        &$proc;
        timestamp "Resuming $name";
        $vm->start(VM_POWEROP_MODE_TRYSOFT) or throw $vm;
    } else {
        &$proc;
    }
}

sub backup($$) {
    my ($vm_dir, $backup_prefix) = @_;
    timestamp "Backing up $vm_dir";
    system '/bin/tar', 'czSf', "$backup_prefix.tar.gz", $vm_dir;
}

die "usage: backup-vms vms-dir backup-dir\n" unless @ARGV == 2;
my ($vms_dir, $backup_dir) = @ARGV;

timestamp 'Start of backup';
tie my %vms_entries, 'IO::Dir', $vms_dir;
my @vm_dirs = grep !/^\./ && $vms_entries{$_}->mode & S_IFDIR, keys %vms_entries;
untie %vms_entries;

# The VmPerl classes' new subs are really broken: they don't use the first
# argument as the class name, and thus you aren't supposed to use constructor
# syntax with them.
my $cp = VMware::VmPerl::ConnectParams::new;
my $vm = VMware::VmPerl::VM::new;

for my $vm_dir (@vm_dirs) {
    my $full_vm_dir = File::Spec->catdir($vms_dir, $vm_dir);
    eval {
        # .vmx file assumed to be named the same as the directory
        $vm->connect($cp, File::Spec->catfile($full_vm_dir, "$vm_dir.vmx"))
            or throw $vm;
        process($vm, sub () {
            backup($full_vm_dir, File::Spec->catdir($backup_dir, $vm_dir));
        });
        $vm->disconnect;
    };
    timestamp $@ if $@;
}
timestamp 'End of backup';
Chris Jester-Young
A: 

i have created a much simpler clone script. All you have to give it is the directory of the source VM and the directory of the target VM. It will do the rest.

After the clone is created, start it up, and choose "Create" for UID and change the IP if it is statically allocated.

#!/bin/bash

if [ $# -eq 0 ] ; then
echo clone source-dir target-dir num hour/min/sec
else

echo Cloning "$1" to "$2"
vmx=`find "$1" -name '*vmx'`
if [ "$vmx" == "" ] ; then
  echo Could not find VMX
else
echo "$1" vmx is "$vmx"

if [ "$3" != "" ] ; then
declare -i sec
sec=0
  case "$4" in
  "hour")
    sec=`expr "$3" \* 3600`
  ;;
  "min")
    sec=`expr "$3" \* 60`
  ;;
  "sec")
    sec="$3"
  ;;
  esac

  echo waiting for $sec
  sleep $sec
fi

declare -i start
declare -i now
start=`date +%s`
suspend="y"
state="`vmware-cmd "$vmx" getstate`"
if [ "$state" == "getstate() = suspended" ] ; then
   suspend="n"
fi

if [ "$suspend" == "y" ] ; then
if [ "suspend() = 1" == "`vmware-cmd "$vmx" suspend`" ] ; then
 suspend="n"
fi
fi

if [ "$suspend" == "n" ] ; then

while [ "getstate() = on" == "`vmware-cmd "$vmx" getstate`" ] ; do
  vmware-cmd "$vmx" getstate
  echo Waiitng for VM to suspend
  sleep 5
done

now=`date +%s`
echo Suspend took `expr $now - $start` seconds
start=`date +%s`

#create new dir
mkdir "$2"
cp -vr "$1"/* "$2"

now=`date +%s`
echo Copy took `expr $now - $start` seconds

vmware-cmd "$vmx" start

echo Clone complete
else
  echo Suspend failed
fi
fi
fi