Saturday, February 21, 2009

Cloning zones

THIS BLOG POST GIVES WRONG ADVICE. DON'T DO THIS!


As the zones use ZFS as root filesystem it's easy to do a zfs snapshot/clone to reproduce a zone. The different zones have only one difference: They differ in /etc/nodename, they have different rootpaths and they have different IP addresses.
I wrote a script to read from global's /etc/hosts the ip address. Zonerootpath is /zones/zonename and /etc/nodename must contain as well. The name of the zone is always identical to the hostname of the zone. That rule is not from OpenSolaris but from me.  ;-)

Here is my script: Beware: I hate to do a lot of checking. This is not for general use...

#!/bin/bash
echo "Creating zone $1 from zone TEMPLATE"
echo check if $1 does not already exist...
zoneadm list -cv | grep $1 && exit -1

echo -n "Retrieving TEMPLATE's IP: "
TEMPLATE_IP=$(grep TEMPLATE /etc/hosts | nawk '{print $1}')
echo $TEMPLATE_IP
echo -n "Retrieving $1's IP: "
NEW_IP=$(grep $1 /etc/hosts | nawk '{print $1}')
echo $NEW_IP

echo "Creating Command File"
rm /tmp/MBcommand 2> /dev/null
# We use the config of TEMPLATE zone and modify this
zonecfg -z TEMPLATE export | sed s/TEMPLATE/$1/ | sed s/$TEMPLATE_IP/$NEW_IP/ > /tmp/MBcommand

echo "generating new zone"
zonecfg -z $1 -f /tmp/MBcommand
echo "Installing new zone as snapshot"
zoneadm -z $1 clone TEMPLATE
echo done.

Very easy so far.
zoneadm clone will do a sys-unconfig to remove any network configuration from the clone. Acutally I don't like that. I don't want to run the whole sysidcfg configuration with every clone. So I did a hack:
AND HERE BEGINS MY PROBLEM. sys-unconfig IS NECESSARY FOR THE HOSTID. 
/usr/lib/brand/ipkg/clone is the shell script that will run, when you do a 'zoneadm clone'.
And here is the (malicious) call to /usr/sbin/sys-unconfig. I removed this and changed it to only write the new /etc/nodename file in the zone's root filesystem. Here are the last few lines of /usr/lib/brand/ipkg/clone:

/usr/sbin/mount -F zfs $zpds/$zpname/ROOT/$BENAME $zonepath/root || \
fail_incomplete "$f_zfs_mount"

#/usr/sbin/sys-unconfig -R $zonepath/root || fail_incomplete "$f_sysunconfig"
echo $zonename > $zonepath/root/etc/nodename
echo Run /usr/sbin/sys-unconfig manually. Command removed by Mario in $0
echo Instead edited only the /etc/nodename file with $zonename

/usr/sbin/umount $zonepath/root || fail_fatal "$f_umount"

exit $ZONE_SUBPROC_OK

Now I only have to populate /etc/hosts with my machines and run one command to have a completely installed and configured zone for my demo environment:

root@ap-mysql:~# ./create_zone_from_TEMPLATE berlin
Creating zone berlin from zone TEMPLATE
check if berlin does not already exist...
Retrieving TEMPLATE's IP:
Retrieving berlin's IP: 192.168.14.226
Creating Command File
generating new zone
Installing new zone as snapshot
Run /usr/sbin/sys-unconfig manually. Command removed by Mario in /usr/lib/brand/ipkg/clone
Instead only the /etc/nodename edited with berlin
done.


No comments:

Post a Comment