pkvlm-create
author Tero Marttila <terom@fixme.fi>
Thu, 05 Jan 2012 14:57:37 +0200
changeset 9 ef5f501266ae
parent 8 ba98eb53344a
child 11 8e5fce1229b6
permissions -rwxr-xr-x
fixfix
#!/bin/bash

### Initialize 
set -u
set -e

TESTING=

DO_SHOWSPEC=y
DO_VIRTINSTALL=

scripts=$(dirname $0)/scripts
. $scripts/lib.sh

### Command-line input
## Command-line options
function _help () {
    cat <<END
Usage: $1 [options] <name> [param=value [...]]

Options:
    -h      Show this help text

    -D      Debug
    -v      Verbose
    -q      Quiet

    -N      Mock command execution
    -P      Skip command prompts

    -I      Do a virt-install

    -T      Just testing..

Parameters are given as:

    NAME=value-{FOO}

END
}

while getopts "hDvqNPTI" opt; do
    case "$opt" in
        h)
            _help $0

            exit 0
            ;;

        D)
            LOG_DEBUG=y
            LOG_CMD=y

            ;;

        v)
            LOG_CMD=y

            log_debug "log: Commands"
            ;;

        q)
            LOG_CMD=
            LOG_INFO=
            DO_SHOWSPEC=
            
            log_debug "log: Quiet"
            ;;

        N)
            log_info "Mock-executing commands (this will break functionality..)"

            CMD_MOCK=y
            ;;

        P)
            log_info "Skipping command confirmations"

            CMD_PROMPT=
            ;;

        T)
            log_info "Just testing.."

            TESTING=y
            ;;

        I)
            log_info "Do virt-install"

            DO_VIRTINSTALL=y
            ;;
        ?)
            _help $0

            exit 1
            ;;
    esac
done


# forget them
[ $OPTIND -gt 1 ] && shift $(( $OPTIND - 1 ))

## Command-line arguments
# Name
[ -z $1 ] && die "Machine name must be given as first argument"

opt_name="$1"; shift

# Defaults
function define_opt () {
    local name=$1
    local value=${2:-}

    log_debugf "%-20s = %s" $name "$value"
    eval "opt_${name}=${value}"
}

function resolve_name () {
    local name=$1
    local out=$(dig +short $name)

    [ -z "$out" ] && die "Hostname lookup failed: $name"

    echo $out
}

define_opt  ram         1G
define_opt  cpus        2
define_opt  os          debiansqueeze
define_opt  disk_size   10G
define_opt  disk_vg     pvl
define_opt  disk_lv     $opt_name
define_opt  disk_bus    virtio
define_opt  guest_disk  /dev/vda
define_opt  hostname    $opt_name
define_opt  bridge      br-lan
define_opt  dns_domain  paivola.fi
define_opt  ip          

log_info "Processing ${#@} parameters:"
for param in "$@"; do
    name=${param%=*}
    value=${param##*=}

    # evaluate
    value=$(expand_line "$value")

    define_opt ${name} "${value}"
done

# resolve defaults
if [ -z $opt_ip ]; then
    define_opt  ip          $(resolve_name ${opt_name}.${opt_dns_domain})
fi

### State
## Guest info
GUEST_NAME=$opt_name

# Basic params
GUEST_RAM=$opt_ram
GUEST_VCPUS=$opt_cpus

# OS variant (for virt-install)
GUEST_OS_VARIANT=$opt_os

## Disk
# Size of LV to create
DISK_SIZE=$opt_disk_size

# LVM vg to use
DISK_VG=$opt_disk_vg

# LVM lv to use
DISK_NAME=$opt_disk_lv

# Path to disk block device
DISK_PATH=/dev/mapper/${DISK_VG}-${DISK_NAME}
DISK_BUS=$opt_disk_bus
GUEST_DISK=$opt_guest_disk

## Network
NET_HOSTNAME=$opt_hostname
NET_BRIDGE=$opt_bridge
NET_IPADDR=$opt_ip

## Installation image
# Original Debian Installer image (iso)
INSTALLER_NAME="debian-6.0.3-amd64"
INSTALLER_ISO="iso-in/${INSTALLER_NAME}-netinst.iso"
INSTALLER_TREE="iso-in/$INSTALLER_NAME"
INSTALLER_FLAG="${INSTALLER_TREE}.unpacked"

# Customized preseed image name
INSTALL_NAME="debian-6.0.3-amd64_${GUEST_NAME}"

# Customized image content
INSTALL_TREE="images/${INSTALL_NAME}"
INSTALL_ISO="iso-out/${INSTALL_NAME}.iso"

# Preseed output file in install tree

# Preseed source template
PRESEED_NAME="preseed.cfg"
PRESEED_TEMPLATE="preseed/${PRESEED_NAME}"
PRESEED_FILE="${INSTALL_TREE}/${PRESEED_NAME}"
PRESEED_ISOLINUX="preseed/isolinux.cfg"
PRESEED_INCLUDES=("preseed/passwords.cfg" "preseed/host.cfg")

PRESEED_CHECKSUM= # set later

## External progs
# Bootable .iso for Debian isolinux-based installer CDs
GENISOIMAGE=/usr/bin/genisoimage
GENISOIMAGE_OPTS="-r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat"

# LVM
LVM=/sbin/lvm

# Libvirt --connect URL
LIBVIRT=qemu:///system
VIRSH=/usr/bin/virsh

function virsh () {
    $VIRSH --connect $LIBVIRT "$@"
}

# type of guest to create
LIBVIRT_TYPE=kvm

# virt-install
VIRT_INSTALL="/usr/bin/virt-install"

## SELinux?
#SEMANAGE=/usr/sbin/semanage
#RESTORECON=/sbin/restorecon

### Prepare
if [ $DO_SHOWSPEC ]; then
    cat <<END
Guest:
    Name:       $GUEST_NAME
    CPUs:       $GUEST_VCPUS
    RAM:        $GUEST_RAM
    OS:         $GUEST_OS_VARIANT

    Disk:       $GUEST_DISK

Disk:
    Method:     LVM
    Size:       $DISK_SIZE
    LVM:
        VG:     $DISK_VG
        LV:     $DISK_NAME

    Path:       $DISK_PATH
    Bus:        $DISK_BUS

Net:
    Hostname:   $NET_HOSTNAME
    Method:     Bridge
    IP:         $NET_IPADDR

    Bridge:
        Name:   $NET_BRIDGE

Installer:
    Name:       $INSTALLER_NAME
    ISO:        $INSTALLER_ISO
    Tree:       $INSTALLER_TREE

Install:
    Name:       $INSTALL_NAME
    Tree:       $INSTALL_TREE
    ISO:        $INSTALL_ISO

Preseed:
    Name:       $PRESEED_NAME
    Template:   $PRESEED_TEMPLATE
    Target:     $PRESEED_FILE
    Isolinux:   $PRESEED_ISOLINUX
    Includes:   $PRESEED_INCLUDES

END
fi

[ $TESTING ] && exit 0

### Check
# Parameters given?
[ -z $NET_IPADDR ] && die "net: No IP-address given: ip"

# VM exists?
if cmd virsh domid ${GUEST_NAME} > /dev/null 2> /dev/null; then
    die "Virtual machine already exists: ${GUEST_NAME}"
fi

# Installer exists?
if cmd test ! -f ${INSTALLER_ISO}; then
    die "Installer not found: ${INSTALLER_ISO}"
fi

### Prepare install
## Extract .iso
if [ -f ${INSTALLER_FLAG} ]; then
    log_info "Installer already unpacked: ${INSTALLER_TREE}"

else
    log_info "Unpacking installer: ${INSTALLER_ISO}"
    cmd extract_iso ${INSTALLER_ISO} ${INSTALLER_TREE}
    cmd touch ${INSTALLER_FLAG}
fi

# Copy to customized tree
cmd cp -r ${INSTALLER_TREE} ${INSTALL_TREE}
cmd chmod -R u=rwX,og=rX ${INSTALL_TREE}

log_info "Installer extracted: $INSTALL_TREE"

## Customize preseed
cmd expand_template ${PRESEED_TEMPLATE} ${PRESEED_FILE}

# md5sum
PRESEED_CHECKSUM=$(my_md5sum $PRESEED_FILE)

# Isolinux .cfg
cmd expand_template ${PRESEED_ISOLINUX} ${INSTALL_TREE}/isolinux/isolinux.cfg

# Others
for file in ${PRESEED_INCLUDES[@]}; do
    name=$(basename $file)

    cmd expand_template $file ${INSTALL_TREE}/${name}
done

log_info "Preseed generated: $PRESEED_FILE"

## Create .iso
[ -f ${INSTALL_ISO} ] && cmd rm -f ${INSTALL_ISO}

# generates a lot of output
cmd ${GENISOIMAGE} -o ${INSTALL_ISO} -quiet ${GENISOIMAGE_OPTS} ${INSTALL_TREE} 

log_info "Install ISO generated: $INSTALL_ISO"

### Create virtual machine
if [ $DO_VIRTINSTALL ]; then
    ## Disk
    # Create LV (unless it already exists)
    [ -e $DISK_PATH ] || cmd_confirm sudo $LVM lvcreate -L $DISK_SIZE -n $DISK_NAME $DISK_VG

    ## SELinux?
    #$SEMANAGE fcontext -a -t virt_image_t $DISK
    #$RESTORECON -v $DISK

    ## virt-install
    cmd_confirm $VIRT_INSTALL \
            --connect $LIBVIRT \
            --name $GUEST_NAME \
            --ram $(expand_MB $GUEST_RAM) --vcpus $GUEST_VCPUS \
            --cdrom "$INSTALL_ISO" \
            --os-variant $GUEST_OS_VARIANT \
            --disk path=$DISK_PATH,bus=$DISK_BUS \
            --network bridge:$NET_BRIDGE \
            --vnc \
            --virt-type $LIBVIRT_TYPE \
            --accelerate --hvm \
            --serial pty
fi