public DumpClusterTopology(AmCluster cluster, ITaskOutputHelper output) { this.m_ownsClusterHandle = true; base..ctor(); this.m_nodeNameToConnect = "<existing cluster handle>"; this.m_output = output; this.m_indentlevel = 0U; this.m_cluster = cluster; this.m_ownsClusterHandle = false; }
// Token: 0x060008B4 RID: 2228 RVA: 0x00029BAC File Offset: 0x00027DAC internal static void FollowBestPractices(ITaskOutputHelper output, IAmCluster cluster) { if (string.Empty != cluster.CnoName) { using (IAmClusterGroup amClusterGroup = cluster.FindCoreClusterGroup()) { using (IAmClusterResource amClusterResource = amClusterGroup.FindResourceByTypeName("Network Name")) { output.AppendLogMessage("Setting the DNS TTL to 300", new object[0]); amClusterResource.SetPrivateProperty <int>("HostRecordTTL", 300); } } } }
public DumpClusterTopology(string nameCluster, ITaskOutputHelper output) { this.m_ownsClusterHandle = true; base..ctor(); this.m_nodeNameToConnect = nameCluster; this.m_output = output; this.m_indentlevel = 0U; Exception ex = null; try { if (string.IsNullOrEmpty(nameCluster)) { this.WriteLine("DumpClusterTopology: Opening local cluster.", new object[0]); this.m_cluster = AmCluster.Open(); } else { this.WriteLine("DumpClusterTopology: Opening remote cluster {0}.", new object[] { nameCluster }); AmServerName serverName = new AmServerName(nameCluster); this.m_cluster = AmCluster.OpenByName(serverName); } } catch (ClusterException ex2) { ex = ex2; } catch (AmCommonTransientException ex3) { ex = ex3; } catch (AmCommonException ex4) { ex = ex4; } catch (TransientException ex5) { ex = ex5; } if (ex != null) { this.WriteLine("DumpClusterTopology: Failed opening with {0}", new object[] { ex }); } }
private IPAddress[] GetDagIpAddressesFromAd(ITaskOutputHelper output, DatabaseAvailabilityGroup dag) { MultiValuedProperty <IPAddress> databaseAvailabilityGroupIpv4Addresses = dag.DatabaseAvailabilityGroupIpv4Addresses; IPAddress[] array = new IPAddress[0]; if (databaseAvailabilityGroupIpv4Addresses.Count > 0) { array = databaseAvailabilityGroupIpv4Addresses.ToArray(); } string[] value = (from addr in array select addr.ToString()).ToArray <string>(); output.AppendLogMessage("Got the following IP addresses for the DAG (blank means DHCP): {0}", new object[] { string.Join(",", value) }); return(array); }
private void CheckForNodesJoining(ITaskOutputHelper output, AmServerName nodeName, NodeAction nodeAction, TimeSpan maxWaitDurationForJoining) { if (maxWaitDurationForJoining == TimeSpan.Zero) { return; } TimeSpan timeSpan = TimeSpan.FromSeconds((double)RegistryParameters.NodeActionDelayBetweenIterationsInSec); if (maxWaitDurationForJoining < timeSpan) { timeSpan = maxWaitDurationForJoining; } bool flag = true; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (;;) { Dictionary <AmServerName, AmNodeState> allClusterNodeStates = this.GetAllClusterNodeStates(output); KeyValuePair <AmServerName, AmNodeState>[] array = (from kv in allClusterNodeStates where kv.Value == AmNodeState.Joining select kv).ToArray <KeyValuePair <AmServerName, AmNodeState> >(); if (array.Length == 0) { break; } string nodeStatesAsSingleString = this.GetNodeStatesAsSingleString(array); if (flag) { output.AppendLogMessage("Delaying the action '{1}' for node '{0} since some nodes are still in joining state. (Nodes: {2})", new object[] { nodeName, nodeAction, nodeStatesAsSingleString }); ReplayCrimsonEvents.ClusterNodeActionBlockedDueToJoiningNodes.Log <AmServerName, NodeAction, string>(nodeName, nodeAction, nodeStatesAsSingleString); flag = false; } if (stopwatch.Elapsed > maxWaitDurationForJoining) { return; } Thread.Sleep(timeSpan); } }
// Token: 0x060008AD RID: 2221 RVA: 0x000296B0 File Offset: 0x000278B0 private static void SetFswSharePath(ITaskOutputHelper output, IAmCluster cluster, IAmClusterResource fsw, string fswShare) { try { fsw.OfflineResource(); fsw.SetPrivateProperty <string>("SharePath", fswShare); fsw.OnlineResource(); } catch (ClusterException ex) { Win32Exception ex2 = null; if (ex.TryGetTypedInnerException(out ex2)) { output.AppendLogMessage("SetFswSharePath() caught an AmClusterApiException with errorcode={0} and NativeErrorCode={1}. ex = {2}", new object[] { ex2.ErrorCode, ex2.NativeErrorCode, ex2 }); if (ex2.NativeErrorCode == 5) { string text = cluster.CnoName; if (text == string.Empty) { using (IAmClusterGroup amClusterGroup = cluster.FindCoreClusterGroup()) { if (amClusterGroup != null && amClusterGroup.OwnerNode != null) { text = amClusterGroup.OwnerNode.NetbiosName; } } } output.WriteErrorSimple(new DagTaskFswNeedsCnoPermissionException(fswShare, text)); } } throw; } }
private void LogStatusCompleted(ITaskOutputHelper output, AmServerName nodeName, NodeAction nodeAction, Exception exception) { string allNodesStillInList = this.GetAllNodesStillInList(nodeName); if (!string.IsNullOrEmpty(allNodesStillInList)) { output.AppendLogMessage("Stale node action entries that are still present after attemping action '{1}' for node '{0}'. Stale: {2}", new object[] { nodeName, nodeAction, allNodesStillInList }); } string nodeStatesAsSingleString = this.GetNodeStatesAsSingleString(this.GetAllClusterNodeStates(output)); output.AppendLogMessage("State of the cluster nodes after performing action '{1}' for node '{0}': {2}", new object[] { nodeName, nodeAction, nodeStatesAsSingleString }); ReplayCrimsonEvents.ClusterNodeActionCompleted.Log <AmServerName, NodeAction, string, string, string>(nodeName, nodeAction, allNodesStillInList, nodeStatesAsSingleString, (exception != null) ? exception.Message : "<none>"); }
private void LogStatusStarting(ITaskOutputHelper output, AmServerName nodeName, NodeAction nodeAction, TimeSpan joiningDuration, TimeSpan inProgressDuration) { string allNodesStillInList = this.GetAllNodesStillInList(nodeName); if (!string.IsNullOrEmpty(allNodesStillInList)) { output.AppendLogMessage("There are stale node action entries that are still present when attemping action '{1}' for node '{0}'. Stale: {2}", new object[] { nodeName, nodeAction, allNodesStillInList }); } string nodeStatesAsSingleString = this.GetNodeStatesAsSingleString(this.GetAllClusterNodeStates(output)); output.AppendLogMessage("State of the cluster nodes before performing action '{1}' for node '{0}': {2}", new object[] { nodeName, nodeAction, nodeStatesAsSingleString }); ReplayCrimsonEvents.ClusterNodeActionStarted.Log <AmServerName, NodeAction, TimeSpan, TimeSpan, string, string>(nodeName, nodeAction, joiningDuration, inProgressDuration, allNodesStillInList, nodeStatesAsSingleString); }
internal void PerformNodeAction(ITaskOutputHelper output, AmServerName nodeName, NodeAction nodeAction, Action clusterAction) { TimeSpan maxWaitDurationForJoining = TimeSpan.FromSeconds((double)RegistryParameters.NodeActionNodeStateJoiningWaitDurationInSec); TimeSpan timeSpan = TimeSpan.FromSeconds((double)RegistryParameters.NodeActionInProgressWaitDurationInSec); TimeSpan timeSpan2 = TimeSpan.FromSeconds((double)RegistryParameters.NodeActionDelayBetweenIterationsInSec); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); this.CheckForNodesJoining(output, nodeName, nodeAction, maxWaitDurationForJoining); TimeSpan elapsed = stopwatch.Elapsed; if (timeSpan < timeSpan2) { timeSpan2 = timeSpan; } bool flag = true; TimeSpan inProgressDuration = TimeSpan.Zero; Exception exception = null; try { Stopwatch stopwatch2 = new Stopwatch(); stopwatch2.Start(); ExDateTime t = ExDateTime.Now.Add(timeSpan); for (;;) { List <NodeActionTracker.NodeActionInfo> list = new List <NodeActionTracker.NodeActionInfo>(15); lock (this.locker) { ExDateTime now = ExDateTime.Now; if (this.nodeActionMap.Count > 0) { foreach (NodeActionTracker.NodeActionInfo nodeActionInfo in this.nodeActionMap.Values) { if (now - nodeActionInfo.StartTime < timeSpan) { list.Add(nodeActionInfo); } } } if (list.Count == 0 || now > t) { NodeActionTracker.NodeActionInfo value = new NodeActionTracker.NodeActionInfo(nodeName, nodeAction); this.nodeActionMap[nodeName] = value; break; } } string nodeInfoListAsString = this.GetNodeInfoListAsString(list); if (flag) { output.AppendLogMessage("Blocking '{1}' action for node '{0}'. InProgress: {2}", new object[] { nodeName, nodeAction, nodeInfoListAsString }); ReplayCrimsonEvents.ClusterNodeActionBlockedDueToInProgress.Log <AmServerName, NodeAction, string>(nodeName, nodeAction, nodeInfoListAsString); flag = false; } Thread.Sleep(timeSpan2); } inProgressDuration = stopwatch2.Elapsed; this.LogStatusStarting(output, nodeName, nodeAction, elapsed, inProgressDuration); clusterAction(); } catch (Exception ex) { exception = ex; throw; } finally { lock (this.locker) { this.nodeActionMap.Remove(nodeName); } this.LogStatusCompleted(output, nodeName, nodeAction, exception); } }
protected virtual Dictionary <AmServerName, AmNodeState> GetAllClusterNodeStates(ITaskOutputHelper output) { Dictionary <AmServerName, AmNodeState> dictionary = new Dictionary <AmServerName, AmNodeState>(15); try { using (IAmCluster amCluster = ClusterFactory.Instance.Open()) { foreach (IAmClusterNode amClusterNode in amCluster.EnumerateNodes()) { using (amClusterNode) { AmNodeState state = amClusterNode.GetState(false); dictionary[amClusterNode.Name] = state; } } } } catch (ClusterException ex) { output.AppendLogMessage("GetAllClusterNodeStates() failed with error {0}", new object[] { ex.Message }); } return(dictionary); }
internal static void FixIPAddress(AmServerName nodeName, DatabaseAvailabilityGroup dag, IEnumerable <AmServerName> startedMailboxServers, ITaskOutputHelper output) { output.WriteProgressSimple(Strings.DagTaskFixingUpIpResources); MultiValuedProperty <IPAddress> databaseAvailabilityGroupIpv4Addresses = dag.DatabaseAvailabilityGroupIpv4Addresses; IPAddress[] array = new IPAddress[0]; if (databaseAvailabilityGroupIpv4Addresses.Count > 0) { array = databaseAvailabilityGroupIpv4Addresses.ToArray(); } string[] value = (from addr in array select addr.ToString()).ToArray <string>(); output.AppendLogMessage("Got the following IP addresses for the DAG (blank means DHCP):{0}", new object[] { string.Join(",", value) }); using (AmCluster amCluster = AmCluster.OpenByNames(startedMailboxServers)) { if (amCluster.CnoName != string.Empty) { using (IAmClusterGroup amClusterGroup = amCluster.FindCoreClusterGroup()) { using (IAmClusterResource amClusterResource = amClusterGroup.FindResourceByTypeName("Network Name")) { LocalizedString value2 = AmClusterResourceHelper.FixUpIpAddressesForNetName(output, amCluster, (AmClusterGroup)amClusterGroup, (AmClusterResource)amClusterResource, array); output.WriteProgressSimple(Strings.DagTaskFixedUpIpResources(value2)); DagTaskHelper.LogCnoState(output, dag.Name, amClusterResource); } } } } }
private static IEnumerable <AmClusterResource> AddStaticIpAddressesToStrandedNetworks(ITaskOutputHelper logger, AmClusterGroup group, AmClusterResource netname, IEnumerable <AmClusterNetwork> publicNetworks, IEnumerable <string> networksWithResources, IEnumerable <IPAddress> staticIpAddresses) { logger = (logger ?? NullTaskOutputHelper.GetNullLogger()); if (publicNetworks.Count <AmClusterNetwork>() <= networksWithResources.Count <string>()) { logger.AppendLogMessage("AddStaticIpAddressesToStrandedNetworks: publicNetworks.Count({0}) <= networksWithResources.Count({1}). So we're doing nothing.", new object[] { publicNetworks.Count <AmClusterNetwork>(), networksWithResources.Count <string>() }); return(new List <AmClusterResource>(0)); } List <AmClusterResource> list = new List <AmClusterResource>(publicNetworks.Count <AmClusterNetwork>() - networksWithResources.Count <string>()); IEnumerable <AmClusterNetwork> enumerable = from publicNet in publicNetworks where !networksWithResources.Contains(publicNet.Name) select publicNet; bool flag = false; using (IEnumerator <AmClusterNetwork> enumerator = enumerable.GetEnumerator()) { while (enumerator.MoveNext()) { AmClusterNetwork publicNetwork = enumerator.Current; logger.AppendLogMessage("AddStaticIpAddressesToStrandedNetworks() There doesn't appear to be an IP resource on network '{0}'.", new object[] { publicNetwork.Name }); IEnumerable <IPAddress> enumerable2 = from staticIp in staticIpAddresses where publicNetwork.IsIPInNetwork(staticIp) select staticIp; if (enumerable2.Count <IPAddress>() > 0) { flag = true; } foreach (IPAddress ipaddress in enumerable2) { logger.AppendLogMessage("AddStaticIpAddressesToStrandedNetworks() Adding IP {0} to network '{1}'.", new object[] { ipaddress, publicNetwork.Name }); int num = 1; bool flag2 = false; AmClusterResource amClusterResource = null; try { amClusterResource = (AmClusterResource)group.CreateUniqueResource(logger, "IPv4 Static Address", "IP Address", ref num); logger.AppendLogMessage("Created new ipv4 static resource. (resource:{0}, address:{1})", new object[] { amClusterResource.Name, ipaddress.ToString() }); int num2; using (AmClusterPropListDisposable amClusterPropListDisposable = AmClusPropListMaker.CreatePropListString("Address", ipaddress.ToString(), out num2)) { using (AmClusterPropListDisposable amClusterPropListDisposable2 = AmClusPropListMaker.DupeAndAppendPropListString(amClusterPropListDisposable.RawBuffer, (int)amClusterPropListDisposable.BufferSize, "Network", publicNetwork.Name, out num2)) { using (AmClusterPropListDisposable amClusterPropListDisposable3 = AmClusPropListMaker.DupeAndAppendPropListString(amClusterPropListDisposable2.RawBuffer, (int)amClusterPropListDisposable2.BufferSize, "SubnetMask", publicNetwork.GetAddressMask(), out num2)) { logger.AppendLogMessage("Created new ipv4 resource: name '{0}' to be {1} on network named '{2}' with mask={3}.", new object[] { amClusterResource.Name, ipaddress.ToString(), publicNetwork.Name, publicNetwork.GetAddressMask() }); amClusterResource.SetPrivatePropertyList(amClusterPropListDisposable3); } } } list.Add(amClusterResource); flag2 = true; } finally { if (!flag2 && amClusterResource != null) { logger.AppendLogMessage("There was some error creating and configuring the IP address resource {0}. Making a best-effort attempt to delete it.", new object[] { ipaddress }); try { amClusterResource.OfflineResource(); amClusterResource.DeleteResource(); } catch (ClusterApiException ex) { logger.AppendLogMessage("There was an error deleting the incomplete IP address. Ignoring the error and continuing. The error was {0}", new object[] { ex }); } if (amClusterResource != null) { amClusterResource.Dispose(); amClusterResource = null; } } } } } } if (!flag) { string[] value = (from network in enumerable select network.Name).ToArray <string>(); string[] value2 = (from staticIp in staticIpAddresses select staticIp.ToString()).ToArray <string>(); logger.WriteWarning(Strings.DagTaskNotEnoughStaticIPAddresses(string.Join(",", value), string.Join(",", value2))); } return(list); }
internal static LocalizedString FixUpIpAddressesForNetName(ITaskOutputHelper logger, IAmCluster cluster, AmClusterGroup group, AmClusterResource netname, IEnumerable <IPAddress> staticIpAddresses) { logger = (logger ?? NullTaskOutputHelper.GetNullLogger()); LocalizedString localizedString = Strings.FixUpIpAddressStatusUnchanged; if (staticIpAddresses != null && staticIpAddresses.Count <IPAddress>() == 1 && IPAddress.Any.Equals(staticIpAddresses.ElementAt(0))) { logger.AppendLogMessage("DAG IP Address was specified in AD, but it's the sentinel value for forcing DHCP ({0}).", new object[] { IPAddress.Any }); staticIpAddresses = new IPAddress[0]; } bool flag = staticIpAddresses != null && staticIpAddresses.Count <IPAddress>() > 0; bool flag2 = staticIpAddresses != null && staticIpAddresses.Count <IPAddress>() == 0; logger.AppendLogMessage("FixUpIpAddressesForNetName: goingToStaticIps: {0}, goingToDynamicIps = {1}.", new object[] { flag, flag2 }); if (flag) { logger.AppendLogMessage("FixUpIpAddressesForNetName: The static IPs specified are:", new object[0]); foreach (IPAddress ipaddress in staticIpAddresses) { logger.AppendLogMessage(" -> {0}", new object[] { ipaddress }); } } IEnumerable <AmClusterNetwork> enumerable = null; IEnumerable <AmClusterResource> enumerable2 = null; IEnumerable <AmClusterResource> enumerable3 = null; IEnumerable <AmClusterResource> enumerable4 = null; try { enumerable = cluster.EnumerateNetworks(); IEnumerable <AmClusterNetwork> enumerable5 = AmClusterResourceHelper.FilterPublicNetworksFromAllNetworks(enumerable); enumerable2 = group.EnumerateResourcesOfType("IP Address"); enumerable3 = group.EnumerateResourcesOfType("IPv6 Address"); IEnumerable <AmClusterResource> enumerable6 = enumerable2.Concat(enumerable3); IList <string> networksWithResources; int num = AmClusterResourceHelper.DeleteOrphanedIpAddresses(logger, group, netname, enumerable6, staticIpAddresses, enumerable5, out networksWithResources); if (num > 0) { SharedHelper.DisposeObjectList <AmClusterResource>(enumerable6); enumerable2 = group.EnumerateResourcesOfType("IP Address"); enumerable3 = group.EnumerateResourcesOfType("IPv6 Address"); } if (flag) { enumerable4 = AmClusterResourceHelper.AddStaticIpAddressesToStrandedNetworks(logger, group, netname, enumerable5, networksWithResources, staticIpAddresses); } else { enumerable4 = AmClusterResourceHelper.AddIpAddressesToStrandedNetworks(logger, group, netname, enumerable5, networksWithResources); } int num2 = enumerable4.Count <AmClusterResource>(); if (num2 > 0) { HashSet <string> hashSet = new HashSet <string>(); foreach (AmClusterResource amClusterResource in enumerable2) { hashSet.Add(amClusterResource.Name); } foreach (AmClusterResource amClusterResource2 in enumerable3) { hashSet.Add(amClusterResource2.Name); } foreach (AmClusterResource amClusterResource3 in enumerable4) { hashSet.Add(amClusterResource3.Name); } string text = string.Format("[{0}]", string.Join("] OR [", hashSet.ToArray <string>())); logger.AppendLogMessage("Setting the dependency on netname '{0}' to '{1}'", new object[] { netname.Name, text }); netname.OfflineResource(); uint num3 = netname.SetDependencyExpression(text); logger.AppendLogMessage("SetDependencyExpression returned {0}.", new object[] { num3 }); } localizedString = Strings.FixUpIpAddressStatusUpdated(num, num2); } finally { SharedHelper.DisposeObjectList <AmClusterNetwork>(enumerable); SharedHelper.DisposeObjectList <AmClusterResource>(enumerable2); SharedHelper.DisposeObjectList <AmClusterResource>(enumerable3); SharedHelper.DisposeObjectList <AmClusterResource>(enumerable4); netname.OnlineResource(); } logger.AppendLogMessage("Successfully completed fixing up the IP addresses for netname '{0}'. Changes made: {1}", new object[] { netname.Name, localizedString }); return(localizedString); }
// Token: 0x060008AC RID: 2220 RVA: 0x00029304 File Offset: 0x00027504 internal static void CreateFileShareWitnessQuorum(ITaskOutputHelper output, IAmCluster cluster, string fswShare) { output = (output ?? NullTaskOutputHelper.GetNullLogger()); IAmClusterGroup amClusterGroup = cluster.FindCoreClusterGroup(); if (amClusterGroup == null) { Thread.Sleep(10000); amClusterGroup = cluster.FindCoreClusterGroup(); if (amClusterGroup == null) { throw new FailedToGetClusterCoreGroupException(); } } using (amClusterGroup) { IEnumerable <AmClusterResource> source = amClusterGroup.EnumerateResourcesOfType("File Share Witness"); IAmClusterResource amClusterResource = source.ElementAtOrDefault(0); try { bool flag = false; if (amClusterResource == null) { output.AppendLogMessage("CreateFileShareWitnessQuorum: Could not find an existing FSW resource. A new one will be created.", new object[0]); flag = true; } else if (amClusterResource.GetState() == AmResourceState.Failed) { output.AppendLogMessage("CreateFileShareWitnessQuorum: The existing FSW resource is in a Failed state. It should be deleted and recreated.", new object[0]); flag = true; } else { string privateProperty = amClusterResource.GetPrivateProperty <string>("SharePath"); if (!SharedHelper.StringIEquals(privateProperty, fswShare)) { output.AppendLogMessage("CreateFileShareWitnessQuorum: There is already a FSW, but the current share path ({0}) is not what's desired ({1}). Will try to fix it.", new object[] { privateProperty, fswShare }); List <string> list = new List <string>(4); foreach (IAmClusterNode amClusterNode in cluster.EnumerateNodes()) { using (amClusterNode) { if (!AmClusterNode.IsNodeUp(amClusterNode.State)) { list.Add(amClusterNode.Name.NetbiosName); } } } if (list.Count > 0) { output.WriteErrorSimple(new DagTaskSetDagNeedsAllNodesUpToChangeQuorumException(string.Join(",", list.ToArray()))); } DagHelper.SetFswSharePath(output, cluster, amClusterResource, fswShare); } } AmResourceState state; if (!flag && amClusterResource != null) { try { state = amClusterResource.GetState(); if (state != AmResourceState.Online) { output.AppendLogMessage("The FSW is not online (it is {0}). Attempting to bring online.", new object[] { state }); amClusterResource.OnlineResource(); } state = amClusterResource.GetState(); output.AppendLogMessage("The fsw resource is now in state {0}.", new object[] { state }); if (state != AmResourceState.Online) { flag = true; } } catch (ClusterException ex) { output.AppendLogMessage("Bringing the FSW resource online failed, so it will be deleted and recreated. For the record, the error was {0}", new object[] { ex }); flag = true; } } if (flag) { if (amClusterResource != null) { amClusterResource.Dispose(); amClusterResource = null; } output.AppendLogMessage("CreateFileShareWitnessQuorum: Calling RevertToMnsQuorum to clean everything up first.", new object[0]); DagHelper.RevertToMnsQuorum(output, cluster); string text = string.Format("File Share Witness ({0})", fswShare); output.AppendLogMessage("Creating a new file share witness resource named '{0}'.", new object[] { text }); amClusterResource = amClusterGroup.CreateResource(text, "File Share Witness"); DagHelper.SetFswSharePath(output, cluster, amClusterResource, fswShare); } output.AppendLogMessage("The FSW resource is now in state {0}.", new object[] { amClusterResource.GetState() }); string text2; uint maxLogSize; string quorumResourceInformation = cluster.GetQuorumResourceInformation(out text2, out maxLogSize); output.AppendLogMessage("The current quorum resource is '{0}'. About to set it to the FSW.", new object[] { quorumResourceInformation }); state = amClusterResource.GetState(); if (state != AmResourceState.Online) { output.WriteErrorSimple(new DagTaskFileShareWitnessResourceIsStillNotOnlineException(fswShare, state.ToString())); } cluster.SetQuorumResource(amClusterResource, null, maxLogSize); quorumResourceInformation = cluster.GetQuorumResourceInformation(out text2, out maxLogSize); output.AppendLogMessage("The quorum resource is now '{0}'.", new object[] { quorumResourceInformation }); output.AppendLogMessage("Bringing the quorum resource online...", new object[0]); amClusterResource.OnlineResource(); } finally { if (amClusterResource != null) { amClusterResource.Dispose(); amClusterResource = null; } } } }