Tuesday 21 May 2013

Migrating a Solaris 10 zone to a Solaris 10 branded zone on Solaris 11


So there's an official Oracle procedure somewhere. Mine just goes into a little more detail and putting in workarounds for some of the bugs I found. 

*Edit: Points 5 and 11 is not necessary with the latest Solaris packages installed.

Zone name: zone1

On old (Solaris 10) global zone:
  1. zoneadm -z zone1 ready
  2. cd /zone/path
  3.  find root -print | cpio -oP@ | gzip >/dumps/zone1.cpio.gz
  4. zonecfg -z zone1 export -f /dumps/zone1.cfg
  5. Copy config and dump across to new global zone
  6. zfs send and recv any extra filesystems across to new global zone
On new (Solaris 11) global zone
  1. Notes:
    1.  I create a zpool with the name “zone”where all my zones data will sit on
    2.  I create a zfs filesystem zone/roots where all the zone paths will be in
    3.  Each zone gets a get a zfs filesystem off /zone where its mounted filesystems stem off from. e.g /zone/zone1 with /zone/zone1/home
  2. vi zone1.cfg*
    1. Change IP if needed
    2. Correct attached filesystems path if needed
    3. Set brand=Solaris10
    4. Set ip-type=exclusive
    5. Change  from net to anet
  3. zonecfg -z  zone1 -f zone1.cfg
  4. zoneadm -z zone1 attach -a /dump/zone1.cpio.gz
  5. Make sure the NIC gets configured on boot - fixes this
    1. vi /zone/path/zone1/root/etc/rc3.d/S99sol11networkaround
      • #This is a workaround for Sol10 zones on Sol11
      • # Till the bug gets fixed
      • ifconfig net0 `cat /etc/hostname.net0`
      • sleep 3
      • svcadm clear svc:/network/physical:default
    2. vi /zone/path/zone1/root/etc/hostname.net0
      • zone1 netmask 255.255.255.0 up
  6. Change root's home from /export/home/root to /root - might not be needed in your environment
    1. vi /zone/path/zone1/root/etc/passwd
    2. mv /zone/zone1/home/root /zone/roots/zone1/root/
  7. If IP is to change, vi /zone/roots/zone1/root/etc/hosts
  8. Boot zone1 and zlogin
  9. ifconfig plumb net0
  10. vi /etc/default/nfs and change: LOCKD_SERVERS=1024 - fixes this
  11. vi /etc/defaultrouter
  12. Reboot zone and test
  13. If you're changing the hostname, you'll have to do a sys-unconfigure and don't forget to update:
    1. /etc/hosts
    2. /etc/nsswitch.conf
    3. /etc/samba/smb.conf
    4. /etc/hostname.net0
    5. and you'll probably have to do a final reboot.

----
*Example zone1.cfg
create -b
set brand=solaris10
set zonepath=/zone/roots/zone1
set autoboot=false
set bootargs=”-m verbose”
set ip-type=exclusive
add fs
set dir=/export/home
set special=/zone/zone1/home
set type=lofs
end
add fs
set dir=/oracle
set special=/zone/zone1/oracle
add anet
set linkname=net0
set lower-link=aggr0
set allowed-address=192.12.23.52/24
set configure-allowed-address=true
set defrouter=192.12.23.1
set link-protection=mac-nospoof
set mac-address=random
end
add capped-memory
set physical=2G
end
----

Wednesday 15 May 2013

Time command Solaris 11

So all of the scripts so far that I've taken across from Solaris 10 to Solaris 11 have worked. Which is no surprise since I generally use the Bourne shell with the idea that it makes my scripts more acceptable in other environments.

One of my scripts didn't work though. It's a simple little script that writes a test file to the current directory and tells you how long it took.
#!/bin/sh

# This is a quick test of write speed.
# The filesize to write can be specified in gigabytes as a parameter.
# Doubt whether this script works if the test file takes more than 59m to write.
tempfile=gigfile.tmp
if [ $# = 1 ]; then
  filesizeGb=$1
else
  filesizeGb=1
fi
filesizeMb=`expr $filesizeGb \* 1024` || exit 1
# Find out the time taken to write the file
sync
timeforwrite=`time dd bs=1048576 count=$filesizeMb if=/dev/zero of=$tempfile 2>&1 | grep real | awk '{ print $NF }'`
timeforsync=`time sync 2>&1 | grep real | awk '{ print $NF }'`
#Take into account if time for write took more than a minute
if [ "`echo $timeforwrite | grep ':'`" != "" ]; then
  seconds=`echo $timeforwrite | awk -F':' '{ print $NF }'`
  minutes=`echo $timeforwrite | awk -F':' '{ print $1 }'`
  min2sec=`expr $minutes \* 60`
  timeforwrite=`echo "scalar=4;$min2sec+$seconds" | bc`
fi
# Calculate the speed
timetaken=`echo "scalar=4;$timeforwrite+$timeforsync" | bc`
writespeed=`echo "scalar=2;$filesizeMb/$timetaken" | bc`
# Do some cleaning up
[ -f "$tempfile" ] && rm "$tempfile"
echo A "$filesizeGb"Gb file was written in $timetaken seconds at a speed of approximately $writespeed"Mb/s."
exit 0

The error message when running it on Solaris 11 is not important because it incorrectly pointed out "bc" - i.e. my calculator. Looking into the script, I could see that my script wasn't giving bc the correct variables to add - none in fact.

Rather than talk you through everything, here's the conclusion. The "time" command works differently in Solaris 11 in two ways:
  1. It always outputs the time in ##m##s format, similar to the way it did in bash in Solaris 10 but not in the Bourne shell.
  2. It doesn't pipe into standard error as neatly as it did before. I'll give an example. If I wanted to store in a test file how long it takes the system to echo "hello world", previously I would run command like this: time echo "hello world" 2>output.txt. This doesn't work in Solaris 11, I need to run it like this: (time echo "hello world") 2>output.txt