Saturday, March 5, 2011

How to properly "halt" virtual machine in LXC

While running a number of virtual machines in LXC you might need gracefully shutdown each virtual machine while host reboot. Here is a script (file /usr/local/sbin/lxc-shutdown):
#!/bin/sh

name=$1
timeout=15

if lxc-info -n $name | grep -qs "STOPPED"
then
    echo $name not running...
    exit 0
fi                                           
                                                                               
ssh $name halt &                                                               
#if [ -e /usr/bin/lxc-halt ]; then                                             
#    /usr/bin/lxc-halt -n $name                                                
#else                                                                          
#    ssh $name halt &                                                          
#fi

while [ $timeout -gt 0 ]
do
    timeout=$(($timeout-1));sleep 1
    if lxc-info -n $name | grep -qs "STOPPED"
    then
        exit 0
    fi
done

lxc-stop -n $name
lxc-wait -n $name -s 'STOPPED'
This approach requires root to have password-less ssh login (see more here). So now that you have a script that let you halt gracefully virtual machine, let make few changes to /etc/init.d/lxc (somewhere around line 56):
# ...
    stop)
    log_daemon_msg "Stopping $DESC"
    #action_all "lxc-stop -n"
    # Uncomment below if you need to halt containers 
    # in reverse order
    CONTAINERS=`echo $CONTAINERS | tac -s ' '`
    action_all "lxc-halt"
    ;;
# ...
Use the following two commands to override lxc-shutdown for lxc v0.8+
                                           
update-alternatives --install /usr/bin/lxc-shutdown \                        
   lxc-shutdown /usr/local/sbin/lxc-shutdown 1                                
update-alternatives --set lxc-shutdown \                                     
   /usr/local/sbin/lxc-shutdown

Friday, March 4, 2011

Exim4 SSL/TLS Configuration

Here we are going configure exim4 to use SSL/TLS for incoming connections:
  1. First of all let create an exim4 certificate request (see here how to create a certificate authority):
    openssl req -newkey rsa:2048 -keyout exim.key -out exim.csr -days 3650 -nodes
    
  2. Now let sign it with our certificate authority:
    openssl ca -out exim.crt -infiles exim.csr
    
  3. Here we get two important files: exim.key (that is private key) and exim.crt (x509 certificate file). Let copy them to /etc/exim4
  4. Secure certificates:
    chown root:Debian-exim exim.key exim.crt
    chmod g=r,o= exim.key exim.crt
    
  5. Enable exim4 daemon listening options for ports 25 and 465 (file /etc/default/exim4):
    SMTPLISTENEROPTIONS='-oX 465:25 -oP /var/run/exim4/exim.pid'
    
  6. Turn on SSL/TLS option (new file /etc/exim4/conf.d/main/00_exim4-localmacros):
    MAIN_TLS_ENABLE = true
    
  7. Restart exim4 and have a look at log file when you send a test message.
    /etc/init.d/exim4 restart
    echo test | mail -s "ssl/tls test" root@dev.local
    
    Here is what you will see in log file (/var/log/exim4/mainlog):
    ... P=esmtps X=TLS1.0:RSA_AES_256_CBC_SHA1:32 ...
    
    If for some reason you can not see esmtps message in log file it most likely it doesn't use SSL/TLS for local delivery, try from remote machine.

Alternative Certificate Location

You can specify any location for ssl/tls certificate (file /etc/exim4/conf.d/main/00_exim4-localmacros):
MAIN_TLS_CERTIFICATE=/etc/ssl/certs/mail.dev.local-cert.pem
MAIN_TLS_PRIVATEKEY=/etc/ssl/private/mail.dev.local-key.pem
This is useful when you host both SMTP and IMAP services on the same host. Note, group Debian-exim must have read access to both files.

Wednesday, March 2, 2011

How to generate consistent "random" numbers

Here is an article that explain a way to get consistent "random" number. The problem appears in virtual environments, like lxc, where hostid is the same. The sample below solves this problem by generating "random" number from a network adapter (eth0) MAC address. So here it is (file func/random_sleep)
#!/bin/bash

# 
# random_sleep shift_max rnd_max
#
# shift_max - a number to generate consistent "random"
# number.
# rnd_max - a random number to add
random_sleep()
{
    shift_max=600
    if [ ! -z $1 ]; then shift_max=$1; fi

    rnd_max=60
    if [ ! -z $2 ]; then rnd_max=$2; fi

    # shift is a number betweem 0 and 600
    shift=`/sbin/ifconfig eth0 | /bin/grep HWaddr | \
        /bin/sed -e 's/.*HWaddr //' | /usr/bin/tr -d ':'`
    shift=$((0x$shift%$shift_max))

    # Sleep a random amount of time + shift
    sleep_time=$(($RANDOM % $rnd_max + $shift))

    echo "Sleeping for $sleep_time seconds..."
    /bin/sleep $sleep_time
}
Here is how you can use it:
#!/bin/bash
. /usr/local/sbin/func/random_sleep
# or
# . `dirname $_`/func/random_sleep

random_sleep 300 60