
Lucky for me, we had the luxury of a Netapp SAN in our main pop, which is like a dream for VMWare. A SAN, and especially a Netapp SAN, due to its inherent ability to act as an NFS NAS head, allows multiple VMWare host servers to connect up and share disk space for as many VMs as the disk space will allow. In addition, you get the inherent safety and speed from heavily RAIDed disks. One of the features that ESX gives you, which is not present in the free server is the ability to rapidly create a VM from a template and, knowing we needed that functionality, I set out to mimic it with the 'sysadmin swiss army knife,' PERL.
NEWVM.PL:
** This script assumes you have a VM template created for your environment **
#!/usr/bin/perl
use strict;
use Getopt::Std;
use File::Copy::Recursive qw(dircopy);
# Where are your VMs located?
my $vmpath = "/mnt/netapp_nfs/";
# Second vmpath for system calls - needed in case of space in dir name
my $sysvmpath = '/mnt/netapp_nfs/';
# The name of the template vm's directory.
my $template = "template";
# I use this to label my vmx and vmsd files by OS
my $os = "RHEL_4";
# Accepts an incoming command line argument to name the new vm.
my $vmname = $ARGV[0];
chomp $vmname;
my $orig = "$vmpath" . "$template";
my $new = "$vmpath" . "$vmname";
my $passed = scalar(@ARGV);
my $oldflat = "$new/$template-flat.vmdk";
my $newflat = "$new/$vmname-flat.vmdk";
my $oldvmdk = "$new/$template.vmdk";
my $newvmdk = "$new/$vmname.vmdk";
my $vmx = "$new/RHEL_4.vmx";
# Second vmx for system calls - modify it by OS again
my $sysvmx="$sysvmpath" . "$vmname" . "/RHEL_4.vmx";
my $vmdkcon;
my $vmxcon;
# Exit if no argument or the vm dir is already there.
die "\nError: Please provide the name of the new VM as an argument.\n\n" if $passed != 1;
die "\nError: The new VM directory already exists.\n\n" if -e $new;
# System call to copy the appropriate template over to the new vm - believe it or not,
# forking a system call for this is faster than doing it in perl.
print "\nCopying template directory. This can take some time...\n";
dircopy("$orig","$new") or die $!;
print "Done!\n";
# Change the file names to match the vm
print "Moving vmdk files...\n";
rename $oldflat, $newflat;
rename $oldvmdk, $newvmdk;
print "Done!\n";
# Change template references in the vmdk and vmx files
undef $/;
print "Modifying vmdk and vmx files...\n";
open(VMDKREAD,"$newvmdk") or die "\nError: Couldn't read vmdk.\n\n";
while(
$vmdkcon = $_;
$vmdkcon =~ s/$template/$vmname/g;
}
close(VMDKREAD);
open(VMDKWRITE,">$newvmdk") or die "\nError: Couldn't write vmdk.\n\n";
print VMDKWRITE $vmdkcon;
close(VMDKWRITE);
open(VMXREAD,"$vmx") or die "\nError: Couldn't read vmx.\n\n";
while(
$vmxcon = $_;
$vmxcon =~ s/$template/$vmname/g;
}
close(VMXREAD);
open(VMXWRITE,">$vmx") or die "\nError: Couldn't write vmx.\n\n";
print VMXWRITE $vmxcon;
close(VMXWRITE);
print "Done!\n";
# Remove old vmsd file - needed for pausing your new vm.
system("/bin/rm -f $new/*.vmsd");
# Register the vm for vmware inventory list on the host server
print "Registering your new VM with VMWare Server...\n";
system("/usr/bin/vmware-cmd -s register $sysvmx");
print "Done!\n";
# Power on the new vm
print "Powering on your new VM...\n";
system("/usr/bin/vmware-cmd $sysvmx start");
print "Done!\n";
# Notify user of success.
print "\nYour VM is made and ready to use. Please connect to the appropriate host\nwith VMWare Server Console and configure.\n";
So that should do it. Of course, the script will need to be modified to fit your own environment. Feel free to give it a whirl and see what happens. It works for us and ends up taking approximately 4 minutes to create a 10 GB VM from our template. If you have any questions, of course, feel free to send a message or leave a comment!