VMmanager 5 KVM: Administrator guide

How to create OS templates

An operating system template is a set of disk images and installation scripts consisting of the distribution and other data required for OS installation. Templates facilitate the installation of operating systems on virtual machines. 

This article describes how you can create and manage templates of operating systems.

An OS template is the metainfo.xml file describing mechanisms that will be used during the installation process. at 

You can view the pre-configured OS templates in our repository.

Create a directory in [NFS storage]/image/YOUR_TEMPLATE_NAME. It must contain the metainfo.xml file with an XML description of the template. The directory must also include all the files specified in the template parameters.

The template description should contain:

<date>2013-04-14 15:37:21</date>
<install_result>ok</install_result>

These strings indicate that the template is already installed. In our example, the fields are not specified, because the description is given in the format that is used for templates from the repository.

Once completed, the newly created template will be added to the list of OS templates. You can add and manage it, all the changes made to the template file will be applied immediately.

For more information on how to add an OS template repository, please refer to the article How to create an OS template repository.

Parameters

Parameters

  • <kernel>File name</kernel> — Linux kernel;
  • <initrd>File name</initrd> — initrd;
  • <kernelcommand>Parameters</kernelcommand> - kernel boot parameters. Example:
<kernelcommand>lang=en_US keymap=us ks=($OSINSTALLINFO_HTTP) method=http://mirror.yandex.ru/centos/6/os/x86_64/ initrd=initrd ip=($IP) netmask=($NETMASK) gateway=($GATEWAY) dns=($NAMESERVER)</kernelcommand>
  • <installdrive>File name</installdrive> - an additional virtual disk (this is a file up to 1 MB in size) can be connected to the virtual machine. You can use macros. This method can be used for FreeBSD 9 installation (for more details, see the FreeBSD installation guide). ("installdrive" is only used by VMmanager)
  • <installcfg>File name</installcfg> - the file that will be returned when following the url ($OSINSTALLINFO_HTTP). You can use macros.
  • <image>File name</image> - the ISO image that will be mounted as CDROM.
  • <tempipv4>yes</tempipv4> - an Ipv4-address is required for installation of OS with main IPv6 address.
  • <sharedir>Directory name</sharedir> - directory which files will be accessible through the http protocol. You can locate it in the OS template macros.
  • <support><elem version='5.1.0'>vmmgr</elem><elem>dcimgr</elem></support> - indicates software products that support this template. version - the minimum version of the control panel.
  • <rebootcount>1</rebootcount> - the number or reboots after which VMmanager considers the operating system to be installed.
  • <illegal_password_characters>Forbidden characters</illegal_password_characters> - characters that cannot be used in passwords.
  • <sshpublickey>yes</sshpublickey> - template supports public SSH-keys.
  • <up_mem_on_install>512</up_mem_on_install> - increase RAM up to this value during installation. When OS is installed, RAM will be reset to its previous value. The feature is supported only in VMmanager.
  • <virtionet>yes</virtionet> - templates supports virtio network. This feature is available only in VMmanager 5.4.0 and later.
  • <virtiodisk>yes</virtiodisk> - template supports virtio disks. This feature is available only in VMmanager 5.4.0 and later.
  • <chpasswd_method>mount.linux</chpasswd_method> - template supports password change. Currently the mount.linux method is used for linux-templates.
  • <loaderefi64>pxelinux.efi</loaderefi64> - template supports boot via UEFI (from version 5.127).
  • <ipxeconf>ipxe.conf</ipxeconf> - configuration file for boot via iPXE (from version 5.127).
  • <ipxeconf type="tftp"> - convert the filename record for iPXE in the dhcpd.conf configuration file to "tftp://10.10.10.10/.../ipxe.conf".


View details

Limits

The limit node describes all template's limits. Note: you cannot create a virtual machine using that template if it does not meet its resource requirements. If the limits are not specified, the check won't be performed.

  • ipv4 - support IPv4 as the main IP address. yes/no
  • ipv6 - support IPv6 as the main IP address. yes/no
  • mem - the minimum amount of RAM in MiB.
  • disk - the minimum amount of disk space in MB.

For example:

<limit>
	<elem name="ipv4">yes</elem>
	<elem name="ipv6">no</elem>
	<elem name="mem">512</elem>
	<elem name="disk">1500</elem>
</limit>

Template examples

kickstart (CentOS, Fedora, RedHat)

We recommend that you use them for CentOS, Fedora, RedHat. For more information about kickstart please refer to this article. It allows for flexible configuration of installation parameters.  kernel and initrd are specified for installation, the URL to the response file is given in the kernel command.

metainfo.xml
<?xml version="1.0"?>
<doc>
  <osname>CentOS-6-amd64</osname>
  <support>
    <elem>VMmgr</elem>
    <elem>IFXmgr</elem>
  </support>
  <rebootcount>1</rebootcount>
  <kernel>vmlinuz</kernel>
  <initrd>initrd.img</initrd>
  <type>ostemplate</type>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <tempipv4>yes</tempipv4>
  <kernelcommand>lang=en_US keymap=us ks=($OSINSTALLINFO_HTTPv4) ksdevice=link method=http://mirror.yandex.ru/centos/6/os/x86_64/ ip=($IPv4) netmask=($NETMASKv4) gateway=($GATEWAYv4) dns=($NAMESERVERv4) roxy=($HTTPPROXYv4) text</kernelcommand>
  <installcfg>install.cfg</installcfg>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">2000</elem>
  </limit>
 </doc>
install.cfg
%pre

#!/bin/sh

for disk in `ls -la /dev/sd?`; do
    dd if=/dev/zero of=$disk bs=512 count=32
done

SWSIZE=$(grep MemTotal /proc/meminfo  | awk '{print int($2/1024)+1}')
if [ ${SWSIZE} -gt 2048 ]; then
    SWSIZE=2048
fi

if [ `cat /proc/scsi/scsi | grep -wc ATA` -eq 2 ]; then
     set $(fdisk -l 2>/dev/null | grep -vi mapper | grep Disk | grep dev |  sed 's/://' | awk '{print $2}' | tr '\n' ' ')
     HD1=$1
    HD2=$2
    if [ -b ${HD2} ]; then
        SIZE1=$(fdisk -l "${HD1}"  2>/dev/null  | grep Disk | grep dev |  sed 's/://'|awk '{print $5}')
        SIZE2=$(fdisk -l "${HD2}"  2>/dev/null  | grep Disk | grep dev |  sed 's/://'|awk '{print $5}')
        if [ -n "${SIZE1}" ] && [ -n "${SIZE2}" ] && [ "${SIZE1}" = "${SIZE2}" ]; then
            USE_MIRROR=yes
        fi
    fi
fi

if [ -n "${USE_MIRROR}" ]; then
cat > /tmp/part-include << EOF
part raid.11 --size=256 --asprimary --ondisk=sda
part raid.12 --size=${SWSIZE} --asprimary --ondisk=sda 
part raid.13 --size=1 --grow --asprimary --ondisk=sda 
part raid.21 --size=256 --asprimary --ondisk=sdb
part raid.22 --size=${SWSIZE} --asprimary --ondisk=sdb 
part raid.23 --size=1 --grow --asprimary --ondisk=sdb
raid /boot --fstype ext4 --device md0 --level=RAID1 raid.11 raid.21
raid swap --fstype swap --device md1 --level=RAID1 raid.12 raid.22
raid / --fstype ext4 --device md2 --level=RAID1 raid.13 raid.23
EOF
else
cat > /tmp/part-include << EOF
part /boot --fstype ext4 --size=256 --asprimary --ondisk=sda
part swap --size=${SWSIZE} --asprimary --ondisk=sda
part / --fstype ext4 --size=1 --grow --asprimary --ondisk=sda
EOF
fi

%end
auth --useshadow --enablemd5
# Crete partition map
bootloader --location=mbr
zerombr
clearpart --all --initlabel
firstboot --disable
# Disk partitioning information
%include /tmp/part-include
# System keyboard
keyboard us
# System language
lang en_US.UTF-8
# Installation logging level
logging --level=info
# Use NFS installation media
url --url http://mirror.yandex.ru/centos/6/os/x86_64/
#Root password
rootpw ($PASS)
# SELinux configuration
selinux --disabled
# Text installation
text
# System timezone
timezone --utc Europe/Moscow

# Network
network --bootproto=static --ip=($IPv4) --netmask=($NETMASK)  --gateway=($GATEWAYv4) --nameserver=($NAMESERVERv4) --hostname=($HOSTNAME) --device=link

# Install OS instead of upgrade
install
%packages
@core
%end

%post
# Network configuration
#echo "NETWORKING=yes" > /etc/sysconfig/network
#echo "HOSTNAME=($HOSTNAME)"
ETHDEV=$(ip route show | grep default | grep -Eo 'dev\ .+\ ' | awk '{print $2}')
HWADDR=$(cat /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F= '/HWADDR/ {print $2}' | sed 's/"//g')
UUID=$(cat /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F= '/UUID/ {print $2}' | sed 's/"//g')

if [ -n "($IPv6)" ]; then
cat > /etc/sysconfig/network << EOF
NETWORKING=yes
NETWORKING_IPV6=yes
HOSTNAME=($HOSTNAME)
IPV6_DEFAULTGW=($GATEWAY)
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-${ETHDEV} << EOF
DEVICE="${ETHDEV}"
BOOTPROTO="static"
DNS1="($NAMESERVER)"
HWADDR="${HWADDR}"
IPV6ADDR="($IPv6)/($NETMASKv6)"
IPV6INIT="yes"
IPV6_AUTOCONF="no"
IPV6_DEFAULTGW="($GATEWAY)"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="${UUID}"
EOF

fi
%end

%post --nochroot
wget -O /dev/null --no-check-certificate "($FINISHv4)"
# Reboot after installation
%end

reboot

FreeBSD 9

The installation is made using the modified image of the installation disk. bootonly.iso is used. After the OS is booted from the disk, the /etc/rc.local file will be uploaded and modified.

To change settings of the newly installed system (its password, network, packets, etc) and allow your users not to modify the image themselves, complete the following steps. An additional disk (shell script of 1 MB in size) is connected to the virtual machine. Once the OS is booted from the disk, rc.local will start to read all of the data from the second hard drive, put them into /tmp/install.sh and start install.sh. Any actions can be described in install.sh.

The OS template includes the install.sh script. You can use macros, which VMmanager will change into corresponding values.

metainfo.xml
<?xml version="1.0"?>
<doc>
  <osname>FreeBSD-9-amd64</osname>
  <support>
    <elem>VMmgr</elem>
    <elem>IFXmgr</elem>
  </support>
  <image>freebsd.iso</image>
  <rebootcount>1</rebootcount>
  <type>ostemplate</type>
  <installdrive>freebsdinstall.sh</installdrive>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <installcfg>freebsdinstall.sh</installcfg>
  <initrd>freebsd.iso</initrd>
  <kernel>memdisk</kernel>
  <kernelcommand>iso raw</kernelcommand>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">1500</elem>
  </limit>
</doc>
freebsdinstall.sh
#!/bin/sh

WGET="fetch -o- -q "

if [ "$START_BSD_INSTALL" != "yes" ]; then
export START_BSD_INSTALL="yes"
bsdinstall ../../../$0

exit 0
fi

clear
echo "Begin Installation at $(date)" | tee -a $BSDINSTALL_LOG

2>>$BSDINSTALL_LOG

error() {
	${WGET} "($FAILURL)?error=$1"
	exit 1
} 

rm -rf $BSDINSTALL_TMPETC
mkdir $BSDINSTALL_TMPETC

echo "Setting hostname..."
HOSTNAME=($HOSTNAME)
echo "hostname=\"$HOSTNAME\"" > $BSDINSTALL_TMPETC/rc.conf.hostname
hostname -s "$HOSTNAME"

echo "Configuring interfaces"
echo "Detecting..."
INTERFACES="${IFACE}"
if [ -z "${INTERFACES}" ]; then
	for IF in `ifconfig -l`; do
       test "$IF" = "lo0" && continue
       INTERFACES="$IF"
	done
fi
if [ -z "$INTERFACES" ]; then
       dialog --backtitle 'FreeBSD Installer' \
           --title 'Network Configuration Error' \
           --msgbox 'No network interfaces present to configure.' 0 0
       exit 1
fi

if [ -n "($IPv6)" ]; then
	echo "Configuring IPv6"
	export http_proxy="($HTTPPROXYv6)"
	export HTTP_PROXY="($HTTPPROXYv6)"
	ifconfig $INTERFACES inet6 ($IPv6) prefixlen ($NETMASKv6)
	route add -inet6 default ($GATEWAYv6)
	echo "nameserver ($NAMESERVERv6)" >> /etc/resolv.conf

	cat >> $BSDINSTALL_TMPETC/rc.conf.network << EOF
ipv6_defaultrouter="($GATEWAYv6)"
ifconfig_${INTERFACES}_ipv6="inet6 ($IPv6) prefixlen ($NETMASKv6)" 
sshd_enable="YES"
ipv6_all_interfaces="YES"
EOF
	echo "nameserver ($NAMESERVERv6)" >> $BSDINSTALL_TMPETC/resolv.conf
elif [ -n "($IPv4)" ]; then
	echo "Configuring IPv4"
	export http_proxy="($HTTPPROXYv4)"
	export HTTP_PROXY="($HTTPPROXYv4)"
	ifconfig $INTERFACES inet ($IPv4) netmask ($NETMASKv4)
	route add default ($GATEWAYv4)
	echo "nameserver ($NAMESERVERv4)" >> /etc/resolv.conf
	echo "name_servers=($NAMESERVERv4)" >> /etc/resolvconf.conf

	cat >> $BSDINSTALL_TMPETC/rc.conf.network << EOF
defaultrouter="($GATEWAYv4)"
ifconfig_${INTERFACES}="inet ($IPv4) netmask ($NETMASKv4)" 
sshd_enable="YES"
EOF

	echo "nameserver ($NAMESERVERv4)" >> $BSDINSTALL_TMPETC/resolv.conf
fi
sleep 5

echo "Setting files for download"
if [ "#$(uname -m)" = "#amd64" ]; then
       export DISTRIBUTIONS="base.txz kernel.txz lib32.txz"
else
        export DISTRIBUTIONS="base.txz kernel.txz"
fi

FETCH_DISTRIBUTIONS=""
for dist in $DISTRIBUTIONS; do
       if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
               FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
       fi
done
FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS` # Trim white space

MIRROR="http://mirror.yandex.ru/freebsd/snapshots"
BSDVER="9.1-STABLE"

BSDINSTALL_DISTSITE="$MIRROR/`uname -m`/`uname -p`/${BSDVER}"

export BSDINSTALL_DISTSITE


echo "Detecting disks"
rm $PATH_FSTAB
touch $PATH_FSTAB

DISKS=`/sbin/sysctl -n kern.disks`
if [ -n ${SKIP_HD} ]; then
	DISKS=$(echo ${DISKS} | sed "s/${SKIP_HD}[ ]\{0,\}//")
fi


HD=${HD:-empty}
if [ $HD = "empty" ]; then
 HD=`echo $DISKS | xargs -n1 echo | grep ar | sort -tr -k2 -n | head -1`
 if [ -z "$HD" ]; then
   HD=`echo $DISKS | xargs -n1 echo | grep ad | sort -td -k2 -n | head -1`
   if [ -z "$HD" ]; then
     HD=`echo $DISKS | xargs -n1 echo | grep da | sort -ta -k2 -n | head -1`
     if [ -z "$HD" ]; then
       HD=`echo $DISKS | /usr/bin/cut -d ' ' -f1`
       if [ -z "$HD" ]; then
         exit 1
       fi
     fi
   fi
 fi
else
 if [ ! -b /dev/$HD ]; then
   # Hard disk device with this name not found
   # Terminate install with error
   error "disknodetect"
 fi
fi

DISK_TYPE=$(echo ${HD} | sed -e 's/[0-9]\{1,\}.*$//g')
echo "Disk type: ${DISK_TYPE}"

if [ $(echo ${DISKS} | grep -Eo "${DISK_TYPE}[0-9]" | wc -l) -eq 2 ]; then
# Mirror
	HDDS=$(echo ${DISKS} | grep -Eo "${DISK_TYPE}[0-9]")
	echo "${HDDS}"
	set ${HDDS}
	HD1=$1
	HD2=$2
	echo "Disk1: ${HD1}"
	echo "Disk2: ${HD2}"
	SIZE1=$(grep -Eio "^${HD1}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot | awk '{print $2}')
	SIZE2=$(grep -Eio "^${HD2}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot | awk '{print $2}')

	grep -Eio "^${HD1}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot
	echo "Disk1 size: ${SIZE1}"
	grep -Eio "^${HD2}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot
	echo "Disk2 size: ${SIZE2}"

	if [ -n "${SIZE1}" ] && [ -n "${SIZE2}" ] && [ "${SIZE1}" = "${SIZE2}" ]; then
		echo "This is miroor system"
		GMIRROR=yes
	else
		echo "Disks size is differ"
		echo "This is single system"
		HDDS=${HD}
	fi
else
# single
	echo "This is single system"
	HDDS=${HD}
fi

#exec 1>&2
echo "Formatting disks"

clear_disks() {
	# $1 — disk
	# $2 — disk-label-ending
        gpart delete -i 2 $1
        gpart delete -i 3 $1
        gpart delete -i 4 $1
        gpart delete -i 5 $1
        gpart delete -i 6 $1
        echo "destroy" | tee -a $BSDINSTALL_LOG
        gpart destroy -F $1
        echo "create GPT" | tee -a $BSDINSTALL_LOG
        gpart create -s GPT $1
        echo "add boot" | tee -a $BSDINSTALL_LOG
        gpart add -t freebsd-boot -l gpboot$2 -s 256K $1
        echo "set bootcode" | tee -a $BSDINSTALL_LOG
        gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 $1
        echo "add swap" >> $BSDINSTALL_LOG
        SWSIZE=$(sysctl -n hw.realmem | awk '{print int($1/1024/1024)+1}')
		if [ ${SWSIZE} -gt 2048 ]; then
			SWSIZE=2048
		fi
        gpart add -t freebsd-swap -l swap$2 -s ${SWSIZE}M $1
        echo "add root" | tee -a $BSDINSTALL_LOG

        # calculating size (not neded now)
        #let "ROOT_PART = ($VOL_SIZE_M) — 1"
        #echo "$ROOT_PART"
        #gpart add -t freebsd-ufs -l rootfs -s "$ROOT_PART"M $HD
        gpart add -t freebsd-ufs -l rootfs$2 $1 

}

if [ -n "${GMIRROR}" ]; then
	clear_disks ${HD1} ${HD1}
	clear_disks ${HD2} ${HD2}
else
	clear_disks ${HD}
fi

if [ -n "${GMIRROR}" ]; then
	echo "Creating mirror"
	gmirror load
	gmirror label -v rootfs /dev/gpt/rootfs${HD1} /dev/gpt/rootfs${HD2}
	gmirror label -v swap /dev/gpt/swap${HD1} /dev/gpt/swap${HD2}

	echo "newfs root" | tee -a $BSDINSTALL_LOG
	newfs -U /dev/mirror/rootfs

	echo "mount" | tee -a $BSDINSTALL_LOG
	mount /dev/mirror/rootfs $BSDINSTALL_CHROOT

	echo "# Device Mountpoint FStype Options Dump Pass#" > $PATH_FSTAB
	echo "/dev/mirror/swap none swap sw 0 0"    >> $PATH_FSTAB
	echo "/dev/mirror/rootfs / ufs rw 1 1" >> $PATH_FSTAB
else

	echo "newfs root" | tee -a $BSDINSTALL_LOG
	newfs -U /dev/gpt/rootfs

	echo "mount" | tee -a $BSDINSTALL_LOG
	mount /dev/gpt/rootfs $BSDINSTALL_CHROOT

	echo "# Device Mountpoint FStype Options Dump Pass#" > $PATH_FSTAB
	echo "/dev/gpt/swap none swap sw 0 0"    >> $PATH_FSTAB
	echo "/dev/gpt/rootfs / ufs rw 1 1" >> $PATH_FSTAB
fi

if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
       ALL_DISTRIBUTIONS="$DISTRIBUTIONS"

       # Download to a directory in the new system as scratch space
       BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
       mkdir -p "$BSDINSTALL_FETCHDEST" || error

       export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
       # Try to use any existing distfiles
       if [ -d $BSDINSTALL_DISTDIR ]; then
               DISTDIR_IS_UNIONFS=1
               mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
       else
               export DISTRIBUTIONS="MANIFEST $ALL_DISTRIBUTIONS"
               export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
       fi

       export FTP_PASSIVE_MODE=YES
       bsdinstall distfetch || error fetch
       export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
        clear
fi

bsdinstall checksum || error checksummincorrect
bsdinstall distextract || error distextractfail
clear

echo "Setting password"
PASSWORD="($PASS)"

echo $PASSWORD | pw -V "$BSDINSTALL_CHROOT/etc" usermod root -h0

echo "Configuring services"
echo "PermitRootLogin yes" >> "$BSDINSTALL_CHROOT/etc/ssh/sshd_config"

#echo sshd_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services
echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services

if [ -n "${GMIRROR}" ]; then
	echo geom_mirror_load="YES" >> $BSDINSTALL_CHROOT/boot/loader.conf
fi

echo "Installing configs"
bsdinstall config  || error

echo "Installing vim"
chroot $BSDINSTALL_CHROOT pkg_add -r vim-lite
sed -i "" -E 's/EDITOR(.*)vi/EDITOR\1vim/g' $BSDINSTALL_CHROOT/root/.cshrc
cat >> $BSDINSTALL_CHROOT/root/.vimrc << EOF
set nocompatible
set encoding=utf8mb4
syntax on
EOF

cp $BSDINSTALL_LOG $BSDINSTALL_CHROOT/root/
dmesg > $BSDINSTALL_CHROOT/root/dmesg
if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
       [ "$BSDINSTALL_FETCHDEST" != "$BSDINSTALL_DISTDIR" ] && \
           umount "$BSDINSTALL_DISTDIR"
       rm -rf "$BSDINSTALL_FETCHDEST"
fi

echo "Installation complete"
$WGET "($FINISH)"

echo "Installation Completed at $(date)" | tee -a $BSDINSTALL_LOG
cp $BSDINSTALL_LOG $BSDINSTALL_CHROOT/root


preseed (Debian, Ubuntu)

We recommend that you use them for Debian, Ubuntu templates. 

<?xml version="1.0"?>
<doc>
  <osname>Debian-7-amd64</osname>
  <support>
    <elem>IFXmgr</elem>
    <elem>VMmgr</elem>
  </support>
  <rebootcount>1</rebootcount>
  <kernel>linux</kernel>
  <initrd>initrd.gz</initrd>
  <type>ostemplate</type>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <tempipv4>yes</tempipv4>
  <kernelcommand>url=($OSINSTALLINFO_HTTPv4) language=en debian-installer/country=RU locale=en_US keyboard-configuration/xkb-keymap=us console-keymaps-at/keymap=us interface=auto netcfg/disable_dhcp=true netcfg/get_ipaddress=($IPv4) netcfg/get_netmask=($NETMASKv4) netcfg/get_gateway=($GATEWAYv4) netcfg/get_nameservers=($NAMESERVERv4) hostname=($HOSTNAME) domain=($HOSTNAME)</kernelcommand>
  <installcfg>install.cfg</installcfg>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">1000</elem>
  </limit>
</doc>


install.cfg
d-i keyboard-configuration/xkb-keymap select us

# Mirrors
#d-i mirror/protocol string ftp
#d-i mirror/country string manual
#d-i mirror/ftp/hostname string ftp.ru.debian.org
#d-i mirror/ftp/directory string /debian
#d-i mirror/ftp/proxy string
d-i mirror/country string manual
d-i mirror/http/hostname string mirror.yandex.ru
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string ($HTTPPROXYv4)

d-i passwd/make-user boolean false

d-i passwd/root-password password ($PASS)
d-i passwd/root-password-again password ($PASS)

d-i clock-setup/utc boolean true

d-i time/zone string Europe/Moscow

d-i preseed/early_command string \
	anna-install parted-udeb 

# Partitioning
d-i partman/early_command string \
for DISK in $(list-devices disk); do \
    dd if=/dev/zero of=${DISK} bs=512 count=1; \
    parted -s ${DISK} mklabel gpt; \
done; \
set $(list-devices disk); \
let numb=$#/2; \
DISKA=$1; \
DISKB=$2; \
if [ -b "${DISKB}" ]; then \
    SIZE1=$(fdisk -l "${DISKA}" 2>/dev/null|grep Disk|grep dev|cut -d' ' -f5); \
    SIZE2=$(fdisk -l "${DISKB}" 2>/dev/null|grep Disk|grep dev|cut -d' ' -f5); \
	if [ -n ${SIZE1} ] && [ -n ${SIZE2} ] && [ "${SIZE1}" = "${SIZE2}" ]; then \
	    USE_MIRROR=yes; \
	else \
	    USE_MIRROR=no; \
	fi; \
fi; \
if [ "#${USE_MIRROR}" = "#yes" ]; then \
	debconf-set partman-auto/disk "$DISKA $DISKB";\
	debconf-set partman-auto/method "raid";\
	debconf-set partman-auto/expert_recipe "multiraid :: \  100 50 100 raid $primary{ } method{ raid } . \  128 512 100% raid method{ raid } . \  1024 10000 1000000000 raid method{ raid } . ";\
	debconf-set partman-auto-raid/recipe "1 2 0 ext2 /boot ${DISKA}1#${DISKB}1 . \  1 2 0 swap — ${DISKA}5#${DISKB}5 . \  1 2 0 ext4 / ${DISKA}6#${DISKB}6 . ";\
	debconf-set grub-installer/bootdev "$DISKA $DISKB";\
else \
	debconf-set partman-auto/disk "$DISKA";\
	debconf-set partman-auto/method "regular";\
	debconf-set partman-auto/expert_recipe "boot-root :: \  100 50 100 ext2 $primary{ } $bootable{ } method{ format } format{ } use_filesystem{ } filesystem{ ext2 } mountpoint{ /boot } . \  128 512 100% linux-swap method{ swap } format{ } . \  1024 10000 1000000000 ext4 method{ format } format{ } use_filesystem{ } filesystem{ ext4 } mountpoint{ / } . ";\
	debconf-set grub-installer/bootdev "$DISKA";\
fi 


#d-i partman-auto/method string regular

#d-i partman-auto/expert_recipe string \
# boot-root :: \
# 40 50 100 ext2 \
# $primary{ } $bootable{ } \
# method{ format } format{ } \
# use_filesystem{ } filesystem{ ext2 } \
# mountpoint{ /boot } \
# . \
# 500 10000 1000000000 ext4 \
# method{ format } format{ } \
# use_filesystem{ } filesystem{ ext4 } \
# mountpoint{ / } \
# . \
# 64 512 300% linux-swap \
# method{ swap } format{ } \
# .

# Force overwrite partitions

d-i partman-partitioning/choose_label       select gpt
d-i partman-partitioning/confirm_new_label  boolean true
d-i partman-partitioning/unknown_label  boolean true
d-i partman/exception_handler   select  Yes
partman-partitioning    partman-partitioning/choose_label       select gpt
partman-partitioning    partman-partitioning/confirm_new_label  boolean true
partman-partitioning    partman-partitioning/unknown_label  boolean true
partman-base    partman/exception_handler   select  Yes

d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/device_remove_lvm boolean true 
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

d-i partman/mount_style select traditional

# Apt

#d-i base-installer/install-recommends boolean true

#d-i base-installer/kernel/linux/initramfs-generators string initramfs-tools
#d-i base-installer/kernel/image string linux-image-amd64

d-i apt-setup/contrib boolean true
#d-i apt-setup/use_mirror boolean true

# Packages
d-i apt-setup/services-select multiselect security, volatile
tasksel tasksel/first multiselect standard
d-i pkgsel/include string openssh-server vim wget

popularity-contest popularity-contest/participate boolean false

# Grub
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true

d-i finish-install/keep-consoles boolean true

d-i preseed/late_command string \
	in-target rm -f /etc/apt/apt.conf ;\
	ETHDEV=$(ip route show | grep default | grep -Eo 'dev\ .+\ ' | cut -d' ' -f2) ;\
	if [ -n "($IPv6)" ]; then \
		echo "# The loopback network interface" > /target/etc/network/interfaces ;\
		echo "auto lo" >> /target/etc/network/interfaces ;\
		echo "iface lo inet loopback" >> /target/etc/network/interfaces ;\
		echo "" >> /target/etc/network/interfaces ;\
		echo "# The primary network interface" >> /target/etc/network/interfaces ;\
		echo "allow-hotplug ${ETHDEV}" >> /target/etc/network/interfaces ;\
		echo "iface ${ETHDEV} inet6 static" >> /target/etc/network/interfaces ;\
		echo -e "\taddress ($IPv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tnetmask ($NETMASKv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tgateway ($GATEWAYv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tdns-nameservers ($NAMESERVERv6)" >> /target/etc/network/interfaces ;\
		echo "nameserver ($NAMESERVERv6)" > /target/etc/resolv.conf ;\
		sed -i "s/($IPv4)/($IPv6)/" /etc/hosts ;\
		sed -i "s/($IPv4)/($IPv6)/" /target/etc/hosts ;\
		echo "# The loopback network interface" > /etc/network/interfaces ;\
		echo "auto lo" >> /etc/network/interfaces ;\
		echo "iface lo inet loopback" >> /etc/network/interfaces ;\
		echo "" >> /etc/network/interfaces ;\
		echo "# The primary network interface" >> /etc/network/interfaces ;\
		echo "allow-hotplug ${ETHDEV}" >> /etc/network/interfaces ;\
		echo "iface ${ETHDEV} inet6 static" >> /etc/network/interfaces ;\
		echo -e "\taddress ($IPv6)" >> /etc/network/interfaces ;\
		echo -e "\tnetmask ($NETMASKv6)" >> /etc/network/interfaces ;\
		echo -e "\tgateway ($GATEWAYv6)" >> /etc/network/interfaces ;\
		echo -e "\tdns-nameservers ($NAMESERVERv6)" >> /etc/network/interfaces ;\
		echo "nameserver ($NAMESERVERv6)" > /etc/resolv.conf ;\
	fi ;\
	in-target wget --no-check-certificate "($FINISHv4)"

d-i finish-install/reboot_in_progress note

Windows

The system installs a ready-to-use image of the operating system. The C:\vmmgr\firstrun.cmd script boots automatically. The script uses dd to read the data from a 1MB virtual disk containing the script from VMmanager. We recommend that you use Task Scheduler for auto-reboot.

Windows auto-start script

Locate the scripts in C:\vmmgr\

firstrun.cmd
@echo off
powershell.exe C:\vmmgr\firstrun.ps1 >NUL
firstrun.ps1
$ddout = C:\vmmgr\ddwrap.cmd
$ddout
$list = $ddout | select-string "size is 1048576 bytes" -Context 3,0
$list
$context = $list.Context.PreContext | select-string Part
$str = $context.Line
$str
C:\vmmgr\dd.exe if=$str of=C:\vmmgr\vmmgr.cmd bs=512 count=2048
C:\vmmgr\vmmgr.cmd
ddwrap.cmd
c:\vmmgr\dd.exe --list 2>&1

When using our boot scripts, you should allow unsigned scripts in PowerShell. In PowerShell and execute the command:

Set-ExecutionPolicy RemoteSigned

Add the dd utility into C:\vmmgr\ . Follow this URL to use the utility. 

Template files

metainfo.xml
<?xml version="1.0"?>
<doc>
  <osname>Windows-Server-2012</osname>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">no</elem>
    <elem name="mem">1024</elem>
    <elem name="disk">10000</elem>
  </limit>
  <support>
    <elem>VMmgr</elem>
  </support>
  <hddimage>win_ser_2012_str.hddimage</hddimage>
  <rebootcount>1</rebootcount>
  <type>ostemplate</type>
  <installdrive>win_ser_2012_str.cmd</installdrive>
  <instal_result>ok</install_result>
</doc>
Note
Make sure that there are no spaces before the string .


In the installation script, comment out the lines for Windows activation and specify your key.

win_ser_2012_str.cmd
@echo off
set logfile=C:\setup.log 
echo ------Set static IP-------------------------------------[%DATE%-%TIME%]      > %logfile%
echo --- IP/NM=($IP)/($NETMASK)  GW=($GATEWAY)      >> %logfile%
echo --- NS1=($NAMESERVER)                                                   >> %logfile%
netsh interface ip set address    "Ethernet" static ($IP) ($NETMASK) ($GATEWAY)  >> %logfile%
netsh interface ip add dnsservers "Ethernet" ($NAMESERVER)          >> %logfile%
echo --- set Administartor password >> %logfile%
net user Administrator ($PASS)  >> %logfile%
set extendfile=C:\vmmgr\extend.txt
echo --- resize disk >> %logfile%
echo select volume 1 > %extendfile%
echo extend noerr >> %extendfile%
diskpart.exe /s %extendfile% >> %logfile%

#Uncomment the following 3 lines and enter your activation key.
#echo activate windows >> %logfile%
#cscript %windir%\system32\slmgr.vbs -ipk XXXXX-XXXXX-XXXXX-XXXXX-XXXX
#cscript %windir%\system32\slmgr.vbs -ato

echo remove task vmmgr_firstrun >> %logfile%
schtasks /Delete /TN "vmmgr_firstrun" /F  >> %logfile%
echo restart OS >> %logfile%
echo ------END--------------------------------------------------[%DATE%-%TIME%]     >> %logfile%

echo RMDIR /s /Q  C:\vmmgr >> c:\del.cmd
echo shutdown /r >> c:\del.cmd
cmd /c c:\del.cmd

CentOS. Extraction of OS template from a file

You can create a Linux template that will be extracted from a predefined disk image. Before you start, make sure that OS file system supports "resizing on the fly" on a mounted file system (e.g. ext4).

We'll take an example on CentOS.

Creating a disk image

In order to create an image, you need to create a virtual machine running CentOS with a small disk size (2GB)

You can install and required software applications.

Disk partition:

/dev/vda1 — /boot
/dev/vda2 — swap
/dev/vda3 — / 

In /etc/rc.local add a command to run the installation script that will be connected with the installdrive option.

echo "sh /dev/sda" >> /etc/rc.local
Note
If you run Debian, the /etc/rc.local file ends with exit 0, and you need to add before "exit" rather than at the end of the file.

If virtio is not supported, the setup disk will be /dev/sdb

Make a "disk dump" into the file of the template directory:

For LVM
dd if=/dev/MyLvm/VMNAME of=centos_hdd.image
For RAW
dd if=PATH_TO_FILE of=centos_hdd.image

Installation script

The example for CentOS. If you run Debian, the script will differ. A file name is specified in the installdrive parameter

#!/bin/sh
 
clean_files() {
        rm -f /etc/ssh/*key*
        sed -r -i '/sh \/dev\/sda/d' /etc/rc.local
}
 
 
disk_format() {
        fdisk /dev/vda <<EOF                                                                                                                                                                 
c                                                                                                                                                                                            
d                                                                                                                                                                                            
3                                                                                                                                                                                            
n                                                                                                                                                                                            
p                                                                                                                                                                                            
3                                                                                                                                                                                            
                                                                                                                                                                                             
                                                                                                                                                                                             
w                                                                                                                                                                                            
EOF
}
 
resize_fs() {
        cat >> /etc/init.d/resize_fs << EOF
#!/bin/bash
#
# Resize fs
#
### BEGIN INIT INFO
# Default-Start:        1 2 3 4 5
# Default-Stop:         0 6
# Required-Start:
# Required-Stop?
# Short-Description:    Resize root filesystem
# Description:          Resize root filesystem
# Provides:             resize_fs
### END INIT INFO
 
. /etc/init.d/functions
 
case "\$1" in
        start|reload)
                resize2fs /dev/root
                chkconfig --del resize_fs
                rm -f /etc/init.d/resize_fs
                exit 0
                ;;
        *)
                echo "service resize_fs start"
                exit 2
esac
 
EOF
chmod +x /etc/init.d/resize_fs
chkconfig --add resize_fs
}
 
network_configure() {
        IPv4=($IPv4)
        NETMASK=($NETMASKv4)
        GATEWAYv4=($GATEWAYv4)
        IPv6=($IPv6)
        PREFIX=($NETMASKv6)
        GATEWAYv6=($GATEWAYv6)
        HOSTNAME=($HOSTNAME)
 
        if [ -n "${GATEWAYv4}" ]; then
                GATEWAY=${GATEWAYv4}
        else
                GATEWAY=${GATEWAYv6}
        fi
 
        # Removing udev rules
        rm -f /etc/udev/rules.d/70-persistent-net.rules
 
 
        # Configuring network
        sed -r -i '/HOSTNAME=.+/d; /GATEWAY=.+/d' /etc/sysconfig/network
cat >> /etc/sysconfig/network << EOF
HOSTNAME=${HOSTNAME}
GATEWAY=${GATEWAY}
EOF
 
        ip link set eth1 name eth0
        HWADDR=$(ip link show eth0 | awk '/link\/ether/ {print $2}' | tr [:lower:] [:upper:])
 
        cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE="eth0"
BOOTPROTO="static"
DNS1="($NAMESERVER)"
HWADDR="${HWADDR}"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
EOF
 
        if [ -n "${IPv4}" ]; then
                cat >> /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
GATEWAY="${GATEWAYv4}"
IPADDR="${IPv4}"
NETMASK="${NETMASK}"
EOF
 
        else
                cat >> /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
IPV6INIT="yes"
IPV6ADDR="${IPv6}/${PREFIX}"
IPV6_DEFAULTGW="${GATEWAYv6}"
EOF
 
        fi
 
        ifup eth0
}
 
clean_files
disk_format
resize_fs
echo "($PASS)" | passwd --stdin root
network_configure
wget -q -O /dev/null --no-check-certificate "($FINISH)"
reboot

This script will:

  • resize the partition
  • set a password
  • enable file system resize after next start. It cannot be done after you apply the changes, as the OS kernel will get information about the changes you have made only after reboot.
  • delete the command for its start from /etc/rc.local


metainfo.xml
<?xml version="1.0"?>
<doc>
  <osname>CentOS-6-amd64-fromdisk</osname>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">2000</elem>
  </limit>
  <support>
    <elem version="5.4.0">VMmgr</elem>
  </support>
  <hddimage>centos_hdd.image</hddimage>
  <rebootcount>1</rebootcount>
  <type>ostemplate</type>
  <installdrive>install.sh</installdrive>
  <virtiodisk>yes</virtiodisk>
  <virtionet>yes</virtionet>
  <date>2013-09-20 12:59:19</date>
  <install_result>ok</install_result>
</doc>
Note
The image file name must end with _hdd.image. For example, centos_hdd.image.