Xserve Cluster Setup
Enable rsh and rlogin

To enable rsh and login on Mac OS X simply edit the /etc/xinetd.d/login and /etc/xinetd.d/shell files and change disable from "yes" to "no":


service shell
{
        disable         = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/libexec/rshd
        groups          = yes
        flags           = REUSE
}

service login
{
        disable         = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/libexec/rlogind
        groups          = yes
        flags           = REUSE
}

Of course please note the security risks involved with enabling login and rsh. We use rsh to run out radmind script remotely as well as some cluster functions. These services are entirely optional and not required.


Mac OS X Server Negative

I began with a negative script posted to the radmind discussion list by Craig Kabis and made slight modifications to further imporve it. This negative is still a work in progress, but seems to be working in its current state:


# Mac OS X Server Negative Transcript
# Still a work in progress, be sure to test before deploying
# Please send comments to rrdionne@geocenter.com
# Based upon Craig Kabis Server Negative (craigkabis@hotmail.com)
#                 
d /.Trashes                                     1333     0    80
a /.hotfiles.btree                              0600     0    80
d /.vol                                         0444     0     0
d /Groups                                       0775     0    80
d /Library/Caches                               1777     0    80
d /Library/ColorSync/Profiles/Displays          0775     0    80
d /Library/Logs                                 0775     0    80
f /Library/Preferences/.GlobalPreferences.plist 0644   501    80
d /Library/Preferences/SystemConfiguration      0755     0    80
# f /Library/Preferences/Server\bMonitor\bPrefs 0644   501    80
f /Library/Preferences/com.apple.loginwindow.plist 0644     0    80
d /Network                                      0755     0     0
d /Shared\bItems                                0775     0    80
# a /Shared\bItems/Icon\r                       0644     0    80
d /Shared\bItems/Public                         0775     0    80
d /System/Library/Caches                        0755     0     0
# Kernel extensions cache files. Created on boot if missing or
# older than /System/Library/Extensions.
f /System/Library/Extensions.kextcache          0644     0     0
f /System/Library/Extensions.mkext              0644     0     0
#d /Users                                       1775     0    80
d /Volumes                                      1777     0    80
d /automount                                    0755     0    80
d /dev                                          0555     0     0
# mach symbol file created in /etc/rc on reboot
f /mach.sym                                     0444     0    80
/vlWAYkK/YBwk=
#d /mnt                                         0777     0    80 
d /private/Network                              0775     0     0
# Apple File Server - config file for AFP server
# f /private/etc/AFP.conf                       0644     0     0
1ndZE8AFb5h5mvC1wYOoU=
f /private/etc/MailServicesOther.plist          0644     0     0
/vlWAYkK/YBwk=
# Printer configurations. Placed here so desktop users can add and delete
# printers as it becomes necessary.
d /private/etc/cups/certs                       0711     0    26
d /private/etc/cups/ppd                         0755     0    26
f /private/etc/cups/ppds.dat                    0644     0    26
vlWAYkK/YBwk=
f /private/etc/cups/printers.conf               0600     0    26
/vlWAYkK/YBwk=
# holds filesystem backup information for the backup and rdump commands
f /private/etc/dumpdates                        0644     0     0
# Used to turn on and off system services
f /private/etc/hostconfig                       0444     0     0
# Web sharing configuration        
f /private/etc/httpd/httpd.conf                 0644     0     0
d /private/etc/httpd/users                      0755     0     0
# Firewall - stores rules for firewall
f /private/etc/ipfilter/ipfw.conf               0644     0     0
f /private/etc/ipfilter/ipfw.conf.apple         0644     0     0
# NAT - This file is reserved for configuration automatically generated by the Server Admin app.
f /private/etc/nat/natd.conf.apple              0444     0     0
# Printer file manager by CUPS
f /private/etc/printcap                         0644     0     0
# Windows File Server - config file for Samba SMB server
f /private/etc/smb.conf                         0644     0     0
# DHCP - has something to do with DHCP
# f /private/etc/xinetd.d/bootps                0644     0     0
# world-writable temporary space
d /private/tmp                                  1777     0     0
#d /private/var/automount/Network/Servers       0755    0       0
# Contains databases of system information, such as NetInfo.
#d /private/var/db                              0755     0     0
# System log directory
d /private/var/log                              0755     0     0
# Location of radmind files on the client
d /private/var/radmind/client                   0755     0     0
# root user's home directory
#d /private/var/root                            0750     0     0
# Directories containing temporary items
d /private/var/run                              0775     0     1
# Apparantly associated with Server Admin.app on Mac OS X Server
# These constantly change and you'll get this error if you uplaod a file in a new transcript
# warning: line XXXX: size in transcript does not match size of file
# /private/var/servermgrd/servermgr_netboot.lockd 
d /private/var/servermgrd                       0755     0     0
f /private/var/servermgrd/servermgr_afp.lock    0770     0     0
f /private/var/servermgrd/servermgr_appserver.lock 0770     0     0
f /private/var/servermgrd/servermgr_dhcp.lock   0770     0     0
f /private/var/servermgrd/servermgr_dirserv.lock 0770     0     0
f /private/var/servermgrd/servermgr_dns.lock    0770     0     0
f /private/var/servermgrd/servermgr_filebrowser.lock 0770     0     0
f /private/var/servermgrd/servermgr_ftp.lock    0770     0     0
f /private/var/servermgrd/servermgr_info.lock   0770     0     0
f /private/var/servermgrd/servermgr_ipfilter.lock 0770     0     0
f /private/var/servermgrd/servermgr_mail.lock   0770     0     0
f /private/var/servermgrd/servermgr_nat.lock    0770     0     0
f /private/var/servermgrd/servermgr_netboot.lock 0770     0     0
f /private/var/servermgrd/servermgr_nfs.lock    0770     0     0
f /private/var/servermgrd/servermgr_print.lock  0770     0     0
f /private/var/servermgrd/servermgr_privs.lock  0770     0     0
f /private/var/servermgrd/servermgr_qtss.lock   0770     0     0
f /private/var/servermgrd/servermgr_qtsscontents.lock 0770     0     0
f /private/var/servermgrd/servermgr_qtssfiletransfer.lock       0770     0
f /private/var/servermgrd/servermgr_signaler.lock 0770     0     0
f /private/var/servermgrd/servermgr_smb.lock    0770     0     0
f /private/var/servermgrd/servermgr_vpn.lock    0770     0     0
f /private/var/servermgrd/servermgr_web.lock    0770     0     0
f /private/var/servermgrd/servermgr_xserve.lock 0770     0     0
# This folder stores different sessions from people that login to Server Admin.app
# example of a file is below.  itadmin is the username of the user that logged in.
# /private/var/servermgrd/sessions/itadmin@QbwL98CoAXMAAAGNTVw.servermgr_info
# d /private/var/servermgrd/sessions            0700     0     0
d /private/var/spool                            0755     0     0
d /private/var/tmp                              1777     0     0
# SLP - initial registration file automatically generated
# f /private/var/slp.regfile                    0644     0     0
# Virtual memory
d /private/var/vm                               0755     0     0
# whatis database. Rebuilt weekly by /private/etc/periodic/weekly/500.weekly
f /usr/share/man/whatis.db                      0644     0     0


Scripts

We are currently still formulating our script which will trigger the run_radmind.pl script on the cluster nodes. Check back soon for more information. The run_radmind.pl script is located on each node and can be run via rsh to initiate a rebuild of the node.


#!/usr/bin/perl
##############################################################################
# This script is based on the University of Utah Student Computing Labs
# run_radmind.pl script. It has been slightly modified to suit our needs.
#
# This script runs radmind and reboots.
#
# Requires the radmind client tools (and a running server obviously).
# (See http://rsug.itd.umich.edu/software/radmind)
#
# Can also be used with iHook
# (See http://rsug.itd.umich.edu/software/ihook)
#
# Copyright (c) 2002 University of Utah Student Computing Labs.
# All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appears in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation, and that the name of The University
# of Utah not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission. This software is supplied as is without expressed or
# implied warranties of any kind.
#
#
# 2004_05_05
#    Totally redid this script, added lots of functions, gave it parameters
#    so it will act as prepForOverload, instead of having a totally different
#    script.
#
# 2004_01_30
#    Added logging to system commands and a few other tweaks
#    
#
##############################################################################
##############################################################################
$rserver = "-h yourserverhere";
$cksum = ""; # change to "" to disable
$fsdiffpath = "/"; # change to "/" if your setup has that path
$ktcheckoutput = "/var/log/ktcheck_output.log";
$ktcheckoutput_backup_number = 5;
$fsdiffoutput = "/var/log/fsdiff_output.T";
$fsdiffoutput_backup_number = 5;
$lapplyoutput = "/var/log/lapply_output.log";
$lapplyoutput_backup_number = 5;
$max_tries = 1;
# customize here:
$radmind_error = "/var/radmind/triggerFiles/radmind_error";
$radmind_log = "/var/log/run_radmind";
$errorlog = "/var/log/radmind_error.log";
$ktcheck = "/usr/local/bin/ktcheck -c sha1 $rserver 2> \"$errorlog\"";
$fsdiff = "/usr/local/bin/fsdiff -A $cksum $fsdiffpath 2> \"$errorlog\"";
$lapply = "/usr/local/bin/lapply -F $cksum $rserver $fsdiffoutput 2> \"$errorlog\"";
# Optional stuff that is commented out in the script by default
$radmind_successful_script = "/var/radmind/scripts/radmind_successful.pl";
$radmind_finished = "/var/radmind/triggerFiles/radmind_finished";
$idleScriptQuitTriggerFile = "/var/radmind/triggerFiles/quitIdleScript";
$runRadmindTriggerFile = "/var/radmind/runRM";

##############################################################################
& main;
##############################################################################
sub main {
##############################################################################
# Turn buffering off
#
$|++;
$oldhandle = select( STDERR );
$|++;
select( $oldhandle );

##############################################################################
# Keep track of time, write to log
#
$rightnow = time; # keep track of time
system "echo \"--------------------------------\" >> $radmind_log";
system "date >> $radmind_log";
system "echo \"run_radmind started\" >> $radmind_log";

##############################################################################

unlink $radmind_finished; # remove the Radmind finished file so that we know RM is running
.
system "touch $idleScriptQuitTriggerFile";

##############################################################################
# Roll logs
#
&roll_log($ktcheckoutput, $ktcheckoutput_backup_number);
&roll_log($fsdiffoutput, $fsdiffoutput_backup_number);
&roll_log($lapplyoutput, $lapplyoutput_backup_number);

##############################################################################
# prep stuff
chdir ("/");
$current_try = 1;
while (1) {
##############################################################################
# run ktcheck
#
print "Checking for Updates\n";
$result = execute_command ("$ktcheck", $ktcheckoutput);
if ($result == 0) {
print "No updates\n";
} elsif ($result == 1) {
print "Updates found\n";
} else {
print "ktcheck encountered a fatal error: $result\n";
system "echo \"ktcheck encountered a fatal error: $result\" >> $radmind_log";
&radmindFailed;
}

##############################################################################
# run fsdiff
#
print "Scanning File System\n";
$result = execute_command ("$fsdiff", $fsdiffoutput);
if ($result != 0) {
print "fsdiff encountered a fatal error: $result\n";
system "echo \"fsdiff encountered a fatal error: $result\" >> $radmind_log";
&radmindFailed;
}

##############################################################################
# could check here for system updates and restart only if they are present.
#&checkForRestart;
##############################################################################
# run lapply
#
print "Updating File System\n";
$fsdsize = ( stat( $fsdiffoutput ))[ 7 ];
if ( $fsdsize > 0 ) {
$result = execute_command ("$lapply", $lapplyoutput);
if ($result == 0) {
&radmindSuccessful;
last;
} elsif ($result == 1) {
if ($current_try >= $max_tries) {
print "lapply failed too many times: $result\n";
system "echo \"lapply failed too many times: $result\" >> $radmind_log";
&radmindFailed;
} else {
print "lapply failed, trying again: $result\n";
system "echo \"lapply failed, trying again: $result\" >> $radmind_log";
next;
}
} else {
print "lapply encountered a fatal error - see log for errors.\n";
system "echo \"lapply failed: $result\" >> $radmind_log";
&radmindFailed;
}
} else {
print "No changes found!\n";
system "echo \"No changes found\" >> $radmind_log";
&radmindSuccessful;
last;
}
$current_try++;
}
unlink $idleScriptQuitTriggerFile;
}

##############################################################################
# This subroutine executes the radmind commands and saves the output to a log,
# prints it to stdout, and saves stderr to a log as well.
#
sub execute_command {
local ($thecommand, $path_to_log) = @_;
open (COMMAND, "$thecommand |");
open (LOG, ">>$path_to_log");
while (<COMMAND>) {
print STDERR;
print LOG;
}
close (LOG);
close (COMMAND);
return $? >> 8;
}
##############################################################################
# If radmind was successful, do these things
#
sub radmindSuccessful {
print "radmind finished, doing other tasks.\n";
system "touch $radmind_finished";
# How long did radmind take?
$rightnowwer = time;
$radmindtime = $rightnowwer - $rightnow;
system "$radmind_successful_script";
# How long did script take?
$rightnowest = time;
$totaltime = $rightnowest - $rightnow;
print "Restarting...\n";
system "echo \"run_radmind restarting\" >> $radmind_log";
sleep 2;
system "/sbin/reboot";
exit 0;
}
##############################################################################
# If radmind died, this is the cleanup subroutine.
#
sub radmindFailed {
# print error log to stdout
open (LOGGY, "<$errorlog");
while (<LOGGY>) {
print;
}
close (LOGGY);
system "touch $radmind_error";
system "rm $runRadmindTriggerFile"; # remove this file or it will keep rebooting!
# How long did script take?
$rightnowest = time;
$totaltime = $rightnowest - $rightnow;
# touch trigger file or radmind will keep running.
system "touch $radmind_finished";
system "/sbin/reboot";
exit 1;
}
##############################################################################
# This script renames $path_to_log so that the lowest number is always the
# newest. The oldest that is greater than $number_of_backups is deleted.
#
sub roll_log {
local ($path_to_log, $number_of_backups) = @_;
if (-e $path_to_log) {
if (-e $path_to_log.".bak$number_of_backups") {
unlink $path_to_log.".bak$number_of_backups";
}
for ($i = $number_of_backups ; $i > 1 ; $i-- ) {
if (-f $path_to_log.".bak".($i-1)) {
system "/bin/mv -f \"$path_to_log".".bak".($i-1)."\" \"$path_to_log".".bak$i\"";
}
}
system "/bin/mv -f \"$path_to_log\" \"$path_to_log".".bak1\"";
}
}
Next -> Porting Notes