Packer – Full vSphere Integration

Standard

After some testing I now have a complete setup for interacting Packer with vSphere.

My parameters here are for testing hence the small disk, tiny kickstart etc. Use it as your base for further enhancements/testing.

This setup has been tested on a CentOS 6.5 Server. The eth1toeth0.sh script is not needed for Redhat/CentOS 5.X installations. The variables part are passed to the Linux Boot Menu i.e. by pressing [TAB].

I am using Python’s integrated HTTP Server:

python -m SimpleHTTPServer

I start the http server in my home dir:

/Users/TheDude

My Build/Source Directory:

/Users/TheDude/Build/{scripts,kickstart}

My ISO Directory is:

/Users/TheDude/packer/{ISO}

VMware Tools package recovered from a Linux box by mounting the VMware Tools DVD.
Use headless mode depending if you want to see VMware installation running. Good for debugging!

Launching the build/validate process

Validate JSON:

RockSolid:~ TheDude$ packer validate templateCOS6.json

Std:

RockSolid:~ TheDude$ packer build templateCOS6.json

Ex. VARIABLES

RockSolid:~ TheDude$ packer build -var "myhost=MyOtherCentOS" -var "myip=192.168.198.120" templateCOS6.json

Ex. VARIABLES With Logging:

RockSolid:~ TheDude$ PACKER_LOG=1 packer build -var "myhost=MyOtherCentOS" -var "myip=192.168.198.120" templateCOS6.json

StartHTTP.sh Script:

#!/bin/sh
python -m SimpleHTTPServer

Output from Terminal:

RockSolid:~ TheDude$ ./StartHTTP.sh 
Serving HTTP on 0.0.0.0 port 8000 ...

vCenter JSON:

{
 "variables": {
       "remote_host": "192.168.198.50",
       "myhost": "rhdev100",
       "mydomain": "rocksolid.com",
       "myip": "192.168.198.29",
       "mygw": "192.168.198.2",
       "mymask": "255.255.255.0",
       "mydns1": "192.168.198.2",
       "mydns2": "192.168.198.3",
       "mydatastore": "NFS_DATASTORE_01"
       },
 "builders": [
    {
     "boot_command": [
       "<tab>",
       "vmlinuz initrd=initrd.img ",
       "myhostname={{user `myhost`}} ",
       "mydomain={{user `mydomain`}} ",
       "myip={{user `myip`}} ",
       "mygateway={{user `mygw`}} ",
       "mynetmask={{user `mymask`}} ",
       "mydns1={{user `mydns1`}} ",
       "mydns2={{user `mydns2`}} ",
       "ks=http://192.168.198.1:8000/Build/kickstart/rh.cfg <enter><wait>"
      ],
       "boot_wait": "5s",
       "disk_size": 4098,
       "guest_os_type": "rhel6-64",
       "headless": false,
       "http_directory": "http",
       "iso_checksum": "32c7695b97f7dcd1f59a77a71f64f2957dddf738",
       "iso_checksum_type": "sha1",
       "iso_url": "http://192.168.198.1:8000/packer/ISO/CentOS-6.5-x86_64-bin-DVD1.iso",
       "output_directory": "{{user `myhost`}}",
       "name": "rhel6-64",
       "shutdown_command": "shutdown -h now",
       "skip_compaction": false,
       "ssh_password": "SecretPasswd",
       "ssh_port": 22,
       "ssh_username": "root",
       "ssh_wait_timeout": "10000s",
       "tools_upload_flavor": "linux",
       "type": "vmware-iso",
       "vmx_data": {
              "ethernet0.networkName": "VM Network",
              "ethernet0.present": "TRUE",
              "ethernet0.virtualDev": "vmxnet3",
              "cpuid.coresPerSocket": "1",
              "memsize": "512",
              "numvcpus": "1",
              "scsi0:0.fileName": "disk.vmdk",
              "scsi0:0.present": "TRUE",
              "scsi0:0.redo": ""
      }
    }
  ],
       "provisioners": [
              {
              "type": "file",
              "source": "/Users/TheDude/Build/VMware/VMwareTools-9.6.1-1378637.tar.gz",
              "destination": "/tmp/VMwareTools-9.6.1-1378637.tar.gz"
              },
              {
              "execute_command": "echo 'TheDude' | {{.Vars}} sudo -S -E bash '{{.Path}}'",
              "scripts": [
                     "scripts/yum.sh",
                     "scripts/sysctl.sh",
                     "scripts/vmtools.sh",
                     "scripts/network.sh",
                     "scripts/eth1toeth0.sh"
              ],
              "type": "shell"
              }
       ],
       "post-processors": [
              {
              "type": "vsphere",
              "host": "vc01.rocksolid.com",
              "username": "TheDude",
              "password": "SecretPasswd",
              "datacenter": "DC01",
              "cluster": "Lab",
              "resource_pool": " ",
              "datastore": "{{user `mydatastore`}}",
              "vm_folder": "CentOS",
              "vm_name": "{{user `myhost`}}", 
              "vm_network": "VM Network",
              "insecure" : "true"
              }
       ]
}

rh.cfg Script:

##########################################################
# RHEL6.X Kickstart Example Small
##########################################################

text
install
cdrom

network --bootproto=dhcp

# US Lang/Keyb
lang en_US.UTF-8
keyboard us

# Mots de pass root
rootpw MySecretPassword

# Disable Firewall
firewall --disabled

# Disable SELinux
selinux --disabled

# Authentication 
authconfig --enableshadow --enablemd5

timezone --utc Europe/Paris

# Disk stuff!
bootloader --location=mbr --driveorder=sda --append="crashkernel=auto rhgb quiet"

# ZAP the disk before using.
zerombr yes
clearpart --drives=sda --initlabel

part /boot --fstype ext4 --size=500
part pv.008034 --size=1 --grow
volgroup VolGroup00 --pesize=4096 pv.008034
logvol / --fstype ext4 --name=lv_root --vgname=VolGroup00 --grow --size=1024
logvol swap --fstype swap --name=lv_swap --vgname=VolGroup00 --size=1024 --grow --maxsize=1024

# Reboot Server and finish Packer
reboot

# Packages (Minimal for testing only)
%packages
@Base
@Core
openssh-server
sudo

######################################################## 
# Post Configuration -nochroot environment
########################################################

# Add Log
%post --nochroot --log=/mnt/sysimage/root/my-post-log

# Extract variables from Boot Menu
CMDLINE_FILE=/proc/cmdline
THIS_HOSTNAME=$(cat ${CMDLINE_FILE} | grep myhostname | sed -e 's/.*myhostname=\([^ ]*\).*/\1/')
THIS_DOMAIN=$(cat ${CMDLINE_FILE} | grep mydomain | sed -e 's/.*mydomain=\([^ ]*\).*/\1/')
THIS_IPADDR=$(cat ${CMDLINE_FILE} | grep myip | sed -e 's/.*myip=\([^ ]*\).*/\1/')
THIS_NETMASK=$(cat ${CMDLINE_FILE} | grep mynetmask | sed -e 's/.*mynetmask=\([^ ]*\).*/\1/')
THIS_GATEWAY=$(cat ${CMDLINE_FILE} | grep mygateway | sed -e 's/.*mygateway=\([^ ]*\).*/\1/')
THIS_DNS_1=$(cat ${CMDLINE_FILE} | grep mydns1 | sed -e 's/.*mydns1=\([^ ]*\).*/\1/')
THIS_DNS_2=$(cat ${CMDLINE_FILE} | grep mydns2 | sed -e 's/.*mydns2=\([^ ]*\).*/\1/')

# Saving variables from Boot Menu -> /root/network.params.txt"
RH_INSTALL_LOG=/mnt/sysimage/root/network.params.txt
echo "myhostname ${THIS_HOSTNAME}" >> ${RH_INSTALL_LOG}
echo "mydomain ${THIS_DOMAIN}" >> ${RH_INSTALL_LOG}
echo "myip ${THIS_IPADDR}" >> ${RH_INSTALL_LOG}
echo "mygateway ${THIS_GATEWAY}" >> ${RH_INSTALL_LOG}
echo "mynetmask ${THIS_NETMASK}" >> ${RH_INSTALL_LOG}
echo "mydns1 ${THIS_DNS_1}" >> ${RH_INSTALL_LOG}
echo "mydns2 ${THIS_DNS_2}" >> ${RH_INSTALL_LOG}

######################################################## 
# Post Configuration chroot environment
########################################################

%post 

echo "Disabling useless services if enabled!"

# Disable rhnsd daemon
/sbin/chkconfig rhnsd off
/sbin/chkconfig rhsmcertd off

# Disable yum-updatesd daemon
/sbin/chkconfig yum-updatesd off

# Disable smartd daemon
/sbin/chkconfig smartd off

# Disable iptables daemon
/sbin/chkconfig ip6tables off
/sbin/chkconfig iptables off

# Disable wpa_supplicant
/sbin/chkconfig wpa_supplicant off

# Disable sendmail
/sbin/chkconfig sendmail off

# Enable postfix
/sbin/chkconfig postfix off

# Disable bluetooth
/sbin/chkconfig bluetooth off

# Disable SNMP
/sbin/chkconfig snmpd off
/sbin/chkconfig snmptrapd off

# Enable NTP
/sbin/chkconfig ntpd on

# Disable PC/SC Smartcard
/sbin/chkconfig pcscd off

# Enable/Disable Portmap
/sbin/chkconfig portmap off

# Disable other useless services
/sbin/chkconfig atd
/sbin/chkconfig lm_sensors off
/sbin/chkconfig mdmonitor off
/sbin/chkconfig mcstrans off
/sbin/chkconfig xinetd off
/sbin/chkconfig gpm off
/sbin/chkconfig isdn off
/sbin/chkconfig iscsi off
/sbin/chkconfig iscsid off
/sbin/chkconfig pcmcia off
/sbin/chkconfig cups off
/sbin/chkconfig hidd off
/sbin/chkconfig anacron off
/sbin/chkconfig avahi-daemon off
/sbin/chkconfig cpuspeed off
/sbin/chkconfig kudzu off
/sbin/chkconfig rpcgssd off
/sbin/chkconfig rpcidmapd off

yum.sh Script:

#!/bin/bash -eux

######################################################## 
# Post Configuration
########################################################

function addPkgs() {
	
    echo "Update packages + Security packages"
    # Update with more packages & update security packages
    yum -y -q install openssh*
    yum -y -q install openssl*
    yum -y -q install net-snmp
    yum -y -q install ntp
    yum -y -q install vim-common
    yum -y -q install vim-enhanced
    yum -y -q install nfs-utils
    yum -y update --security
}

function addUser() {
	
    echo "Adding Local User => TheDude"
    # Add Local User => TheDude
    /usr/sbin/useradd TheDude
    echo "SecretPasswd" | passwd --stdin TheDude  
    # sudo
    echo "TheDude        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers
    sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers

}

setupPasswd() {
    
    echo "Removing entries from /etc/passwd file"
    sed -i '/news/d' /etc/passwd
    sed -i '/operator/d' /etc/passwd
    sed -i '/games/d' /etc/passwd
    sed -i '/gopher/d' /etc/passwd
    sed -i '/ftp/d' /etc/passwd
}

setupNtp() {
(cat <<- EOF
########################
# Local /etc/ntp.conf
########################

# Line for Virtual Machines
tinker panic 0

restrict 127.0.0.1
restrict default kod nomodify notrap

# Use PHM servers.
server 0.centos.pool.ntp.org
server 1.centos.pool.ntp.org
server 2.centos.pool.ntp.org
driftfile /var/lib/ntp/drift
keys /etc/ntp/keys
EOF
) > /etc/ntp.conf
}

######################################################## 
# Run the Functions
########################################################
addUser
setupPasswd
setupNtp
addPkgs

sysctl.sh Script:

#!/bin/bash -eux

setupKern() {
(cat <<- EOF
# Kernel sysctl configuration file for Red Hat Linux
# Suitable for dedicated web server, mail, ftp server etc. 
# ---------------------------------------
# BOOLEAN Values:
# a) 0 (zero) - disabled / no / false
# b) Non zero - enabled / yes / true
# --------------------------------------
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
 
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
 
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
 
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
 
# Controls whether core dumps will append the PID to the core filename
# Useful for debugging multi-threaded applications
kernel.core_uses_pid = 1
 
# Controls the use of TCP syncookies
#net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2
 
########## IPv4 networking start ##############
# Send redirects, if router, but this is just server
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
 
# Accept packets with SRR option? No
net.ipv4.conf.all.accept_source_route = 0
 
# Accept Redirects? No, this is not router
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
 
# Log packets with impossible addresses to kernel log? yes
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
 
# Ignore all ICMP ECHO and TIMESTAMP requests sent to it via broadcast/multicast
net.ipv4.icmp_echo_ignore_broadcasts = 1
 
# Prevent against the common 'syn flood attack'
net.ipv4.tcp_syncookies = 1
 
# Enable source validation by reversed path, as specified in RFC1812
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
 
########## IPv6 networking start ##############
# Number of Router Solicitations to send until assuming no routers are present.
# This is host and not router
net.ipv6.conf.default.router_solicitations = 0
 
# Accept Router Preference in RA?
net.ipv6.conf.default.accept_ra_rtr_pref = 0
 
# Learn Prefix Information in Router Advertisement
net.ipv6.conf.default.accept_ra_pinfo = 0
 
# Setting controls whether the system will accept Hop Limit settings from a router advertisement
net.ipv6.conf.default.accept_ra_defrtr = 0
 
#router advertisements can cause the system to assign a global unicast address to an interface
net.ipv6.conf.default.autoconf = 0
 
#how many neighbor solicitations to send out per address?
net.ipv6.conf.default.dad_transmits = 0
 
# How many global unicast IPv6 addresses can be assigned to each interface?
net.ipv6.conf.default.max_addresses = 1
 
########## IPv6 networking ends ##############
 
#Enable ExecShield protection
kernel.exec-shield = 1
kernel.randomize_va_space = 1
 
# TCP and memory optimization 
# increase TCP max buffer size setable using setsockopt()
#net.ipv4.tcp_rmem = 4096 87380 8388608
#net.ipv4.tcp_wmem = 4096 87380 8388608
 
# increase Linux auto tuning TCP buffer limits
#net.core.rmem_max = 8388608
#net.core.wmem_max = 8388608
#net.core.netdev_max_backlog = 5000
#net.ipv4.tcp_window_scaling = 1
 
# increase system file descriptor limit    
fs.file-max = 65535
 
#Allow for more PIDs 
kernel.pid_max = 65536
 
#Increase system IP port limits
net.ipv4.ip_local_port_range = 2000 65000
EOF
) > /etc/sysctl.conf
}

# Run Function
setupKern

vmtools.sh Script:

#!/bin/bash -eux

# Install VMware Tools
cd /tmp
tar zxvf /tmp/VMwareTools-*.tar.gz -C /tmp
/tmp/vmware-tools-distrib/vmware-install.pl --default

network.sh Script:

#!/bin/bash -eux

# Get the parameters saved from Boot Menu and apply to our new VM

CMDLINE_FILE=/root/network.params.txt
THIS_HOSTNAME=$(cat ${CMDLINE_FILE} | grep myhostname | awk '{print $2}')
THIS_DOMAIN=$(cat ${CMDLINE_FILE} | grep mydomain | awk '{print $2}')
THIS_IPADDR=$(cat ${CMDLINE_FILE} | grep myip | awk '{print $2}')
THIS_NETMASK=$(cat ${CMDLINE_FILE} | grep mynetmask | awk '{print $2}')
THIS_GATEWAY=$(cat ${CMDLINE_FILE} | grep mygateway | awk '{print $2}')
THIS_DNS_1=$(cat ${CMDLINE_FILE} | grep mydns1 | awk '{print $2}')
THIS_DNS_2=$(cat ${CMDLINE_FILE} | grep mydns2 | awk '{print $2}')

echo -e "\tNetwork Interface Setup (eth0)"

(cat <<- EOF
DEVICE=eth0
BOOTPROTO=static
IPADDR=${THIS_IPADDR}
NETMASK=${THIS_NETMASK}
ONBOOT=yes
EOF
) > /etc/sysconfig/network-scripts/ifcfg-eth0
/bin/chmod 644 /etc/sysconfig/network-scripts/ifcfg-eth0

(cat <<- EOF
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=${THIS_HOSTNAME}
GATEWAY=${THIS_GATEWAY}
EOF
) > /etc/sysconfig/network
/bin/chmod 644 /etc/sysconfig/network

# DNS

# Check if we have 2 DNS Servers
if [ -z "${THIS_DNS_2}" ] ; then
(cat <<- EOF
search $THIS_DOMAIN
nameserver ${THIS_DNS_1}
EOF
) > /etc/resolv.conf

else

(cat <<- EOF
search $THIS_DOMAIN
nameserver ${THIS_DNS_1}
nameserver ${THIS_DNS_2}
EOF
) > /etc/resolv.conf

fi

# /etc/hosts

(cat <<- EOF
${THIS_IPADDR}		${THIS_HOSTNAME}.${THIS_DOMAIN} ${THIS_HOSTNAME}
EOF
) >> /etc/hosts

eth1toeth0.sh Script:

#!/bin/bash -eux

# Remove 70-persistent-net.rules and create eth0 during next boot
cp /etc/udev/rules.d/70-persistent-net.rules /var/tmp/70-persistent-net.rules
rm -f /etc/udev/rules.d/70-persistent-net.rules

Leave a Reply