October 6, 2010 - Sven Huisman

Xenserver: fast-clone a VM 120 times in 90 seconds

I’ve been working on Project VRC lately and in this role I’ve had the opportunity to work with different hypervisors. In my quest to conquer Xenserver I ran into a couple of challenges and I would like to share these with my readers (as I learned it the hard way, why not make it easier for you).
One of the things I needed to figure out was how to clone a VM multiple times. With Xenserver, there are a couple of options to clone a VM. From XenCenter you can right-click a VM and choose: Copy VM…

You then have 2 options: a full copy or a fast-clone, a faster “Copy-on-Write” (CoW) mode which only writes modified blocks to disk. I needed to fast-clone, because if I was going to full copy my Windows 7 VM I would need more diskspace than was available in the server.

First challenge: I was working with local storage. By default, the XenServer installation creates the local storage with Logical Volume Manager (LVM). Fast Cloning of VM templates is currently supported with the following storage types: ext, nfs, netapp, equallogic, so no LVM! Luckily, there is a Citrix article where it is described how to change your existing Local LVM storage to ext type.

After doing this I was able to fast-clone a VM. Next was to find out how to script this fast-cloning, because I needed to fast-clone a VM 120 times. I asked around but no one had a script to do this. My colleague Ruben then posted a question on the Citrix Community forum and within a coupleof hours a simple script was posted. I tested the script and it seem to work: it successfully cloned a VM. I started the script for 120 VM’s and went to bed. The next morning, it had only cloned only 60 VM’s and was still busy. Also the local storage was almost full. Mmm… that’s no “fast” cloning. So I adjusted the script and now I was able to fast-clone a VM 120 times in 90 seconds! Here is the script I used:

#!/bin/bash
read -p "Template: " TEMPLATE
read -p "Name Prefix: " NAME
read -p "Quantity: " QUANTITY
COUNT=1
while [ $COUNT -le $QUANTITY ] ; do
  xe vm-clone vm="$TEMPLATE" \
  new-name-label="$NAME$COUNT";
  let COUNT=COUNT+1
  done
exit 0

I noticed it’s not easy/possible in XenCenter to select 120 VM’s and shut them down or start them up with one click. So I adjusted the script to do just that:

Start VM’s
#!/bin/bash
read -p "Name Prefix: " NAME
read -p "Quantity: " QUANTITY
COUNT=1
while [ $COUNT -le $QUANTITY ] ; do
  xe vm-start vm="$NAME$COUNT";
  let COUNT=COUNT+1
  done
exit 0

Shutdown VM’s
#!/bin/bash
read -p "Name Prefix: " NAME
read -p "Quantity: " QUANTITY
COUNT=1
while [ $COUNT -le $QUANTITY ] ; do
  xe vm-shutdown vm="$NAME$COUNT";
  let COUNT=COUNT+1
  done
exit 0

Delete VM’s
#!/bin/bash
read -p "Name Prefix: " NAME
read -p "Quantity: " QUANTITY
COUNT=1
while [ $COUNT -le $QUANTITY ] ; do
  xe vm-uninstall vm="$NAME$COUNT" force=true;
  let COUNT=COUNT+1
  done
exit 0

As you notice, I am no script kiddy and there is probably an easy way to put this all in 1 script and create a menu for each option (if you can, be my guest and post it as comment).

On another note, I also couldn’t find a decent sysprep.xml to sysprep a Windows 7 machine which was 100% unattended (autogenerate computername, join domain). I could find some sysprep examples but none of them did what I wanted. Here’s the one I created and used for my Windows 7 VM’s. Just put on the C-drive of the VM and run the following command from c:\windows\system32\sysprep: sysprep.exe /generalize /oobe /shutdown /unattend:”C:\sysprep.xml”

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-International-Core" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <InputLocale>nl-US</InputLocale>
            <SystemLocale>nl-US</SystemLocale>
            <UILanguage>nl-US</UILanguage>
            <UserLocale>nl-US</UserLocale>
        </component>
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <OOBE>
                <HideEULAPage>true</HideEULAPage>
                <NetworkLocation>Work</NetworkLocation>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <ProtectYourPC>3</ProtectYourPC>
            </OOBE>
            <RegisteredOrganization>VRC</RegisteredOrganization>
            <RegisteredOwner>VRC</RegisteredOwner>
        </component>
    </settings>
    <settings pass="specialize">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ComputerName>*</ComputerName>
            <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet>
            <ShowWindowsLive>false</ShowWindowsLive>
            <TimeZone>W. Europe Standard Time</TimeZone>
        </component>
        <component name="Security-Malware-Windows-Defender" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <DisableAntiSpyware>true</DisableAntiSpyware>
        </component>
        <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Identification>
                <Credentials>
                    <Domain>domain name here</Domain>
                    <Password>password here</Password>
                    <Username>username to join domain</Username>
                </Credentials>
                <JoinDomain>domain name here</JoinDomain>
                <MachineObjectOU>OU=Computers,OU=VRC,DC=domain,DC=local</MachineObjectOU>
            </Identification>
        </component>
    </settings>
    <settings pass="generalize">
        <component name="Microsoft-Windows-Security-SPP" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <SkipRearm>1</SkipRearm>
        </component>
    </settings>
    <cpi:offlineImage cpi:source="wim:c:/bin/asus.wim#EF WW W7HP 32R" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>

Virtual Infrastructure Citrix / Clone / VRC / xenserver /