Hostid in Solaris Zonen fälschen

Die Hostid in nicht-globalen Solaris Zonen wird von der globalen Zone vererbt. Es gibt jedoch Fälle, in denen das nicht gewünscht wird, z.B. wenn man eine lizenzierte Software oder Lizenzserver innerhalb einer Solaris Zone laufen lassen muss und die Software auch noch funktionieren soll, nachdem eine Zone auf ein anderes physisches System verlegt wurde. Hierfür gibt es zwei mögliche Methoden, wie man einer nicht-globalen Solaris Zone eine eigene Hostid geben kann.

Solaris 8/9 Branded Zone

Die Hostid kann in der Zonenkonfiguration gesetzt werden. Siehe 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

Hier funktioniert obige Methode leider nicht (Stand Solaris 10 8/05). Die Hostid kann jedoch mit dtrace gefälscht werden. Das unten aufgeführte Script kann als Startdienst in einer nicht-globalen Zone verwendet werden. Es basiert auf Brendan Gregg's zhostid, welches jedoch innerhalb einer globalen Zone gestartet wird. Es benötigt dtrace-Rechte in der Zonenkonfiguration.

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