const SCRIPT_VERSION = "1.0"
dim WRITELINEHEADER
WRITELINEHEADER = "AmalgaUpdateClusterState.vbs" & vbcrlf & "Microsoft.Amalga.Library.UpdateClusterState" & vbcrlf & "script version: " & SCRIPT_VERSION & vbcrlf & "script start: " & now()
dim LogEnabled
LogEnabled = false
dim ManagedEntityId
ManagedEntityId = ""
Dim oAPI
Set oAPI = CreateObject("MOM.ScriptAPI")
dim DebugEventSource
dim LogEventSource
dim LogSeverity
LogSeverity = LOGSEVERITY_INFO
DebugEventSource = "$Config/DebugEventSource$"
if instr(DebugEventSource,"$") then
LogEventSource = "Amalga"
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine "Error in DebugEventSource - $ not translated - " & DebugEventSource
cdate("unexpected error - macro subsitution did not happen")
else
LogEventSource = trim(DebugEventSource & "")
if (LogEventSource = "") then
LogEventSource = "Amalga"
LogEnabled = true
LogSeverity = LOGSEVERITY_WARN
WriteLine "missing DebugEventSource, defaulting to 'Amalga'"
LogEnabled = false
LogSeverity = LOGSEVERITY_INFO
end if
end if
Dim oArgs
Set oArgs = WScript.Arguments
DumpArgs(oArgs)
if (oArgs.Count <> EXPECTED_PARAM_COUNT) then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine "invalid arg count: " & oArgs.Count & " expected " & EXPECTED_PARAM_COUNT
oArgs = cdate("invalid arg count") ''' intentionally crash
end if
ManagedEntityId = GetArg(oArgs(0))
dim DebugEnabled
DebugEnabled = "$Config/DebugEnabled$"
if instr(DebugEnabled,"$") then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine "Error in DebugEnabled - $ not translated - " & DebugEnabled
cdate("unexpected error - macro subsitution did not happen") ''' intentionally crash
end if
DebugEnabled = trim(ucase(DebugEnabled & " "))
LogEnabled = (DebugEnabled = "TRUE")
Dim TargetComputer, PrincipalName, NetBIOSComputerName, Environment, BoxEnvNum, ThisMachineName
TargetComputer = "$Config/PrincipalName$"
if instr(TargetComputer,"$") then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine "Error in serviceinstancename - $ not translated - " & serviceinstancename
cdate("unexpected error - macro subsitution did not happen") ''' intentionally crash
end if
PrincipalName = TargetComputer
NetBIOSComputerName = "$Config/NetBIOSComputerName$"
if instr(NetBIOSComputerName,"$") then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine "Error in serviceinstancename - $ not translated - " & serviceinstancename
cdate("unexpected error - macro subsitution did not happen") ''' intentionally crash
end if
Environment = "$Config/Environment$"
if instr(Environment,"$") then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
cdate("unexpected error - macro subsitution did not happen") ''' intentionally crash
end if
BoxEnvNum = "$Config/BoxEnvNum$"
if instr(BoxEnvNum,"$") then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
cdate("unexpected error - macro subsitution did not happen") ''' intentionally crash
end if
WriteLine("LogEnabled=" & LogEnabled & " (DebugEnabled:" & DebugEnabled & ")")
WriteLine("TargetComputer=" & TargetComputer)
WriteLine("PrincipalName=" & PrincipalName)
WriteLine("NetBIOSComputerName=" & NetBIOSComputerName)
WriteLine("Environment=" & Environment)
WriteLine("BoxEnvNum=" & BoxEnvNum)
WriteLine "running script on machine: "
dim wshshell, objenv
on error resume next
Set WshShell = CreateObject("WScript.Shell")
Set objEnv = WshShell.Environment("Process")
ThisMachineName = "" & objEnv("COMPUTERNAME")
WriteLine "This machine's name is: " & ThisMachineName
on error goto 0
'' We can have several targets resolving to the same box, but we want to only allow the registry to be updated from the physical box
'' so we don't confuse it when computing the active/passive state
if trim(lcase(NetBIOSComputerName) & " ") <> trim(lcase(ThisMachineName) & " ") then
WriteLine("NetBIOSComputerName does not equal physical box's hostname, skipping cluster state update operations.")
else
'' empty BoxEnvNum indicates the class was discovered from another node, so the same Environment keys might not exist on both nodes
if (BoxEnvNum <> "0" and BoxEnvNum <> "") then
WriteLine "There are potentially more than 1 environments configured for this physical server, skipping this environment so we don't hit concurrency issues while writing to the same registry keys."
else
call UpdateClusterStates(TargetComputer, NetBIOSComputerName)
end if
end if
sub DumpArgs(Args)
dim i, status
WriteLine("Dumping args as passed in.")
WriteLine("Note: If you see quotes, they are actually part of the argument literal.")
dim untranslated
untranslated = false
for i = 0 to Args.Count - 1
WriteLine(i & ": " & Args(i))
if (instr(Args(i),"$") > 0) then
untranslated = true
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine("ERROR: untranslated $ encountered at arg " & i & ": " & Args(i))
end if
next
if (untranslated) then
LogEnabled = true
LogSeverity = LOGSEVERITY_ERROR
WriteLine("ERROR: one or more untranslated $ args encountered, quitting.")
status = cdate("ERROR: one or more untranslated $ args encountered, quitting.") ''' intentionally crash here
end if
end sub
'////////////////////////////
function GetArg(quotedarg)
dim s
s = quotedarg
if s <> "" then
if mid(s,1,1) = """" then
s = mid(s,2, len(s)-1)
end if
if mid(s,len(s),1) = """" then
s = mid(s, 1, len(s)-1)
end if
end if
GetArg = s
end function
'////////////////////////////
sub WriteLine(in_line)
if (LogEnabled) then
dim s
s = vbcrlf & "ID: " & ManagedEntityId & vbcrlf & WRITELINEHEADER & vbcrlf & vbcrlf & in_line
wscript.echo in_line
call oAPI.LogScriptEvent(LogEventSource, 100, LogSeverity, s)
end if
end sub
'////////////////////////////
Function Connect(server)
'
' Opens a global cluster object. Using Windows Script Host syntax,
' the cluster name or "" must be passed as the first argument.
'
WriteLine "connecting to " & server
ClusterConnectErrorMsg = ""
on error resume next
Set objCluster = Nothing
Set objCluster = CreateObject("MSCluster.Cluster")
if (Err.Number <> 0) or (objCluster is nothing) then
ClusterConnectErrorMsg = Err.Number & " - " & Err.description & " (" & TargetComputer & ")"
if Err.Number = 429 then '' activex object not registered, MSCS not installed
WriteLine "ClusterConnectErrorMsg = " & ClusterConnectErrorMsg
ClusterConnectErrorMsg = "MSCS not installed (" & TargetComputer & ")"
end if
WriteLine "could not instantiate MSCS to connect to " & server
WriteLine "ClusterConnectErrorMsg = " & ClusterConnectErrorMsg
call WriteClusterState(server, NotClusterState, ClusterConnectErrorMsg)
exit function
else
WriteLine "instantiated MSCS to connect to " & server
end if
objCluster.Open server
if (Err.Number <> 0) then
ClusterConnectErrorMsg = Err.Number & " - " & Err.description & " (" & TargetComputer & ")"
WriteLine "Error opening connection to " & server & " closing MSCS object!"
WriteLine "ClusterConnectErrorMsg = " & ClusterConnectErrorMsg
Set objCluster = Nothing
call WriteClusterState(server, NotClusterState, ClusterConnectErrorMsg)
end if
on error goto 0
End Function
sub Disconnect()
'
' Dereferences global objects. Used with Connect.
'
Set objCluster = Nothing
Set objArgs = Nothing
end sub
sub EnumerateResourceGroups(in_TargetComputer, in_TargetVIP)
'
' Returns a delimited string of names from a collection.
' Objects in the collection must support the Name property.
'
dim i, Value, objEnum
WriteLine "EnumerateResourceGroups()"
if (objCluster is nothing) then
WriteLine "could not instantiate MSCS objects, exiting early!"
exit sub
end if
dim targetVIP
targetVIP = lcase(trim(in_TargetVIP & " "))
if targetVIP = "" then
WriteLine "invalid targetVIP"
exit sub
end if
dim f
f = -1
on error resume next
f = objCluster.Resources.count
on error goto 0
WriteLine "objCluster.Resources.count = " & f
if f <= 0 then
WriteLine "exiting early!"
exit sub
end if
dim j, VIPgroupname, VIPgroupowner, VIPgroupNetworkName
dim domain
'' record self before enumerating clusters
call WriteClusterState(in_TargetComputer, NotClusterState, "recording self")
on error resume next
for i = 1 to f
If LCase(objCluster.Resources.Item(i).TypeName) = "network name" Then
For j = 1 To objCluster.Resources.Item(i).PrivateProperties.Count
If LCase(objCluster.Resources.Item(i).PrivateProperties(j).Name) = "name" Then
VIPgroupname = objCluster.Resources.Item(i).Group.Name
VIPgroupNetworkName = objCluster.Resources.Item(i).PrivateProperties(j).Value
End If
next
VIPgroupNetworkName = lcase(trim(VIPgroupNetworkName & " "))
WriteLine "group " & VIPgroupname & "'s network name: " & VIPgroupNetworkName
if (domain <> "") and (instr(VIPgroupNetworkName,domain) = 0) then
WriteLine "Domain " & domain & " is missing, adding it"
VIPgroupNetworkName = VIPgroupNetworkName & "." & domain
end if
WriteLine "VIPgroupNetworkName = " & VIPgroupNetworkName
VIPgroupowner = "unknown node owner"
VIPgroupowner = lcase(trim(objCluster.Resources.Item(i).Group.OwnerNode.Name & " "))
WriteLine "VIPgroupowner = " & VIPgroupowner
WriteLine VIPgroupowner & " owns " & VIPgroupNetworkName
if VIPgroupowner = targetVIP then
call WriteClusterState(VIPgroupNetworkName, ActiveState, VIPgroupowner & " owns " & VIPgroupNetworkName)
else
call WriteClusterState(VIPgroupNetworkName, PassiveState, VIPgroupowner & " owns " & VIPgroupNetworkName)
end if
End If
next
on error goto 0
end sub
Function GetValue(obj)
dim retval
retval=""
on error resume next
retval = obj.Value & ""
on error goto 0
GetValue = retval
End Function
sub UpdateClusterStates(in_TargetComputer, in_NetBIOSComputerName)
sub WriteClusterState(in_clustername, in_state, in_errormsg)
WriteLine "Writing " & in_clustername & "'s cluster state (" & in_state & ") to the registry."
WriteLine "errormsg: " & in_errormsg
dim oReg, strComputer, strKeyPath, strValueName, strValue
Const HKEY_LOCAL_MACHINE = &H80000002
''strComputer = "."
strComputer = principalname
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Microsoft\Amalga\SCOM\Volatile\Clusters\" & lcase(in_clustername)
end sub
'////////////////////////////
function GetDomainFromTargetComputer(machinename)
dim pos, temp
temp = machinename
temp = lcase(" " & temp & " ")
pos = instr(temp,".")
if (pos >0) then
GetDomainFromTargetComputer = trim(mid(temp,pos+1))
else
GetDomainFromTargetComputer = ""
end if
end function
'////////////////////////////
function NormalizeDate(x)
dim retval, i, L, c
L = len(x)
for i = 1 to L
c = ucase(mid(x,i,1))
if (instr("/:AMP ",c)=0) then
retval = retval & c
end if
next