Fake Hostid on Solaris Zones

The hostid in Solaris non-global zones is inherited from the global zones. There are some conditions (e.g. licensed software) where it is essential that the hostid stays the same when the zone is moved from one physical host to another. There are two possible solutions how to fix this problem and give a solaris non-global zone an individual hostid.

Solaris 8/9 Branded Zone

The hostid can be set in the zone configuration. See How to Configure a solaris9 Branded Zone.

  zonecfg -z myzone 
  add attr
    set name=hostid
    set type=string
    set value=8090a0b0
  end 

Solaris 10 Native Zone

The hostid can be faked with dtrace. The script below can be used as a startup service within a non-global Solaris zone. It is based upon Brendan Gregg's zhostid which is started in the global zone instead. It requires dtrace permissions in the zone configuration.

zonecfg -z myzone "set limitpriv=default,dtrace_proc,dtrace_user"

Script /etc/init.d/fake_hostid.

#!/usr/bin/ksh
#
# Fake hostid of a solaris 10 zone
# --------------------------------
# Based upon http://www.brendangregg.com/DTrace/zhostid
# Modified to run as a startup daemon within a non-global zone. Requires 
# zonecfg -z myzone "set limitpriv=default,dtrace_proc,dtrace_user"
# in zone configuration.
# Copy it to /etc/init.d/fake_hostid and make symlinks
# from /etc/rc3.d before starting license server.

FAKE_HOSTID='8090a0b0'

zone=`zonename`

if [[ $zone == 'global' ]]; then
  echo "Don't run this inside a global zone!"
  exit 1
fi



function run_dtrace
{
  hostid_hex=$1
  if [[ "$hostid_hex" == *[g-zG-Z]* ]]; then
    echo "ERROR2: Invalid hostid $hostid_hex. "
    echo "Please use hexadecimal.\n"
    exit 2
  fi
  if (( ${#hostid_hex} > 11)); then
    # see /usr/src/uts/common/conf/param.c for limit.
    echo "ERROR3: Length of hostid $hostid_hex too long. "
    echo "Limit 11 chars.\n"
    exit 3
  fi
  if [[ ! -x /usr/sbin/dtrace ]]; then
    echo "ERROR4: /usr/sbin/dtrace missing."
    exit 4
  fi

  ### Convert hostid to decimal
  typeset -i10 hostid_dec
  hostid_dec=16#$hostid_hex

  ### Run DTrace in background
  /usr/sbin/dtrace -n '
    #pragma D option destructive
    #pragma D option quiet
    #pragma D option bufsize=32k
    inline string hostid = "'$hostid_dec'";
    syscall::systeminfo:entry
    { self->command = arg0;
      self->buffer = arg1;
    }
    syscall::systeminfo:return
    /zonename == "'$zone'" && self->command == 7/
    { copyoutstr("'$hostid_dec'", self->buffer, 11);
    }
    syscall::systeminfo:return
    { self->command = 0;
      self->buffer = 0;
    }' &
}


case "$1" in
  start) run_dtrace $FAKE_HOSTID       ;;
  stop)  pkill dtrace                  ;;
  *)     echo "Usage: $0 {start|stop}" ;;
esac

Usage:

  [root@myzone /]$ hostid
  11223344
  [root@myzone /]$ /etc/init.d/fake_hostid start
  [root@myzone /]$ hostid
  9090a0b0