#!/usr/bin/ruby
#
# Copyright (c) 2010 Apple Inc.
# All Rights Reserved.
#
# This script delays xsand startup until all directory service nodes
# in the authentication search path are available or a timeout occurs.
#
# See http://support.apple.com/kb/TS3556 for more information.

TIMEOUT_SECONDS = 60
SCRIPT_NAME = File.basename($0)

# Snow Leopard is required.
product_version = `/usr/bin/sw_vers -productVersion`.strip
if product_version.strip.split('.')[0..1].join('.') != '10.6'
  warn "#{SCRIPT_NAME} requires Snow Leopard. Exiting."
  exit 1
end

require 'timeout'
require 'osx/cocoa'
OSX.require_framework('OpenDirectory')
KODNodeTypeAuthentication = 0x2201

# Wait until nodes are available or timeout occurs.
def wait_with_timeout(seconds = TIMEOUT_SECONDS)
  unreachables = []
  begin
    Timeout::timeout(seconds) do
      loop do
        break if (unreachables = get_unreachable_nodes).empty?
        sleep 1
      end
    end
  rescue Timeout::Error
    warn "#{SCRIPT_NAME} timed out with unreachable nodes: #{unreachables.join(' ')}"
  end
  nil
end

# Return the list of unreachable nodes as an array.
def get_unreachable_nodes
  OSX::NSODNode.nodeWithSession_type_error_(
    OSX::NSODSession.defaultSession, KODNodeTypeAuthentication, nil
  ).unreachableSubnodeNamesAndReturnError(nil).to_a
end

# These lines are run when the script is executed.
if __FILE__ == $0
  begin
    warn "#{SCRIPT_NAME} started"
    wait_with_timeout
  rescue ScriptError, StandardError
    warn "#{SCRIPT_NAME} error: #{$!}"
  ensure
    warn "#{SCRIPT_NAME} starting xsand"
    exec '/Library/Filesystems/Xsan/bin/xsand'
  end
end
