static void PrintNotification(RESP_ASYNC_NOTIFY respNotify) { if ((SwnMessageType)respNotify.MessageType == SwnMessageType.RESOURCE_CHANGE_NOTIFICATION) { Console.WriteLine("MessageType: SWN_SERVER_MESSAGE_RESOURCE_CHANGE_NOTIFICATION"); RESOURCE_CHANGE[] resourceChangeList; SwnUtility.ParseResourceChange(respNotify, out resourceChangeList); foreach (var res in resourceChangeList) { Console.WriteLine("Resource name: {0}", res.ResourceName); switch ((SwnResourceChangeType)res.ChangeType) { case SwnResourceChangeType.RESOURCE_STATE_UNKNOWN: Console.WriteLine("Change type: RESOURCE_STATE_UNKNOWN"); break; case SwnResourceChangeType.RESOURCE_STATE_AVAILABLE: Console.WriteLine("Change type: RESOURCE_STATE_AVAILABLE"); break; case SwnResourceChangeType.RESOURCE_STATE_UNAVAILABLE: Console.WriteLine("Change type: SWN_RESOURCE_STATE_UNAVAILABLE"); break; default: Console.WriteLine("Change type: Unknown type {0}", res.ChangeType); break; } } } else if ((SwnMessageType)respNotify.MessageType == SwnMessageType.RESOURCE_MOVE_NOTIFICATION) { Console.WriteLine("MessageType: SWN_SERVER_MESSAGE_RESOURCE_MOVE_NOTIFICATION"); MOVE_REQUEST moveRequest; SwnUtility.ParseMoveRequest(respNotify, out moveRequest); foreach (var ip in moveRequest.IPAddrList) { Console.WriteLine("---------------------------------"); if (((uint)SwnIPAddrType.MOVE_DST_IPADDR_V4 & ip.Flags) != 0) { Console.WriteLine("IPAddr V4: {0}", ip.IPV4); } if (((uint)SwnIPAddrType.MOVE_DST_IPADDR_V6 & ip.Flags) != 0) { Console.WriteLine("IPAddr V6: {0}", ip.IPV6); } } } else { Console.WriteLine("MessageType: Unknown type: {0}", respNotify.MessageType); } }
/// <summary> /// Verify RESOURCE_CHANGE_NOTIFICATION in Asynchronous Notification /// </summary> /// <param name="respNotify">Asynchronous notification</param> /// <param name="changeType">State change of the resource</param> public static void VerifyResourceChange(RESP_ASYNC_NOTIFY respNotify, SwnResourceChangeType changeType) { BaseTestSite.Assert.AreEqual <uint>((uint)SwnMessageType.RESOURCE_CHANGE_NOTIFICATION, respNotify.MessageType, "Expect MessageType is set to RESOURCE_CHANGE_NOTIFICATION"); RESOURCE_CHANGE[] resourceChangeList; SwnUtility.ParseResourceChange(respNotify, out resourceChangeList); BaseTestSite.Assert.AreEqual <uint>(0x00000001, respNotify.NumberOfMessages, "Expect NumberOfMessages is set to 1."); BaseTestSite.Assert.AreEqual <uint>((uint)changeType, resourceChangeList[0].ChangeType, "Expect ChangeType is set to {0}.", changeType); }
private void FileServerFailoverTest(string server, FileServerType fsType, bool reconnectWithoutFailover = false) { int ret = 0; uint callId = 0; IPAddress currentAccessIpAddr = null; WITNESS_INTERFACE_INFO registerInterface = new WITNESS_INTERFACE_INFO(); WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST(); currentAccessIpAddr = SWNTestUtility.GetCurrentAccessIP(server); BaseTestSite.Log.Add(LogEntryKind.Debug, "Get current file server IP: {0}.", currentAccessIpAddr); #region Register SWN witness if (witnessType == WitnessType.SwnWitness) { if (TestConfig.IsWindowsPlatform && fsType == FileServerType.ScaleOutFileServer) { // Windows Server: when stopping a non-owner node of ScaleOutFS, no notication will be sent by SMB witness. // So get one IP of the owner node of ScaleOutFS to access. string resourceOwnerNode = sutController.GetClusterResourceOwner(server); IPAddress[] ownerIpList = Dns.GetHostEntry(resourceOwnerNode).AddressList; foreach (var ip in ownerIpList) { BaseTestSite.Log.Add(LogEntryKind.Debug, "Owner IP: {0}", ip); } if (!ownerIpList.Contains(currentAccessIpAddr)) { currentAccessIpAddr = null; IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList; foreach (var ip in accessIpList) { if (ownerIpList.Contains(ip)) { currentAccessIpAddr = ip; break; } } BaseTestSite.Assert.IsNotNull(currentAccessIpAddr, "IP should not be null."); BaseTestSite.Log.Add(LogEntryKind.Debug, "Get the owner IP {0} as file server IP.", currentAccessIpAddr); } DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIpAddr, TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage, TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, resourceOwnerNode), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); } else { DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIpAddr, TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage, TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, server), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); } DoUntilSucceed(() => { ret = swnClientForInterface.WitnessrGetInterfaceList(out interfaceList); BaseTestSite.Assert.AreEqual <SwnErrorCode>( SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrGetInterfaceList returns with result code = 0x{0:x8}", ret); return(SWNTestUtility.VerifyInterfaceList(interfaceList, TestConfig.Platform)); }, TestConfig.FailoverTimeout, "Retry to call WitnessrGetInterfaceList until succeed within timeout span."); SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface); DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForWitness, (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6), TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage, TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, registerInterface.InterfaceGroupName), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); string clientName = Guid.NewGuid().ToString(); BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server)); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIpAddr.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName); ret = swnClientForWitness.WitnessrRegister(SwnVersion.SWN_VERSION_1, SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server), currentAccessIpAddr.ToString(), clientName, out pContext); BaseTestSite.Assert.AreEqual <SwnErrorCode>( SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegister returns with result code = 0x{0:x8}", ret); BaseTestSite.Assert.IsNotNull( pContext, "Expect pContext is not null."); callId = swnClientForWitness.WitnessrAsyncNotify(pContext); BaseTestSite.Assert.AreNotEqual <uint>( 0, callId, "WitnessrAsyncNotify returns callId = {0}", callId); } #endregion #region Create a file and write content string uncSharePath = Smb2Utility.GetUncPath(server, TestConfig.ClusteredFileShare); string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); string testDirectory = CreateTestDirectory(uncSharePath); string file = Path.Combine(testDirectory, Guid.NewGuid().ToString()); Guid clientGuid = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); DoUntilSucceed(() => WriteContentBeforeFailover(fsType, server, currentAccessIpAddr, uncSharePath, file, content, clientGuid, createGuid), TestConfig.FailoverTimeout, "Before failover, retry Write content until succeed within timeout span."); #endregion #region Disable accessed node if (TestConfig.IsWindowsPlatform) { AssignCurrentAccessNode(server, fsType, currentAccessIpAddr); } if (!reconnectWithoutFailover) { BaseTestSite.Log.Add( LogEntryKind.TestStep, "Disable owner node for general file server or the node currently provides the access for scale-out file server."); FailoverServer(currentAccessIpAddr, server, fsType); } #endregion #region Wait for available server BaseTestSite.Log.Add(LogEntryKind.TestStep, "Wait for available server."); if (witnessType == WitnessType.None) { if (fsType == FileServerType.GeneralFileServer) { currentAccessIpAddr = null; IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList; DoUntilSucceed(() => { foreach (IPAddress ipAddress in accessIpList) { Smb2FunctionalClient pingClient = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); try { pingClient.ConnectToServerOverTCP(ipAddress); pingClient.Disconnect(); pingClient = null; currentAccessIpAddr = ipAddress; return(true); } catch { } } return(false); }, TestConfig.FailoverTimeout, "Retry to ping to server until succeed within timeout span"); } else { currentAccessIpAddr = null; IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList; foreach (IPAddress ipAddress in accessIpList) { if (TestConfig.IsWindowsPlatform) { // When setting failover mode to StopNodeService for Windows, SMB2 servers on two nodes can still be accessed by the client. // So the client needs to get the new node to access it after failover by comparing host name. if (string.Compare(currentAccessNode, Dns.GetHostEntry(ipAddress).HostName, true) == 0) { continue; } } Smb2FunctionalClient pingClient = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); try { pingClient.ConnectToServerOverTCP(ipAddress); pingClient.Disconnect(); pingClient = null; currentAccessIpAddr = ipAddress; break; } catch { } } } } else if (witnessType == WitnessType.SwnWitness) { // Verifying for notification RESP_ASYNC_NOTIFY respNotify; do { // Wait the notification ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify); BaseTestSite.Assert.AreEqual <SwnErrorCode>( SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "ExpectWitnessrAsyncNotify returns with result code = 0x{0:x8}", ret); SWNTestUtility.PrintNotification(respNotify); RESOURCE_CHANGE[] resourceChangeList; SwnUtility.ParseResourceChange(respNotify, out resourceChangeList); BaseTestSite.Assert.AreEqual <uint>(0x00000001, respNotify.NumberOfMessages, "Expect NumberOfMessages is set to 1."); if (resourceChangeList[0].ChangeType == (uint)SwnResourceChangeType.RESOURCE_STATE_AVAILABLE) { // Verify RESP_ASYNC_NOTIFY, the resource is available SWNTestUtility.VerifyResourceChange(respNotify, SwnResourceChangeType.RESOURCE_STATE_AVAILABLE); break; } // Verify RESP_ASYNC_NOTIFY, the resource is unavailable SWNTestUtility.VerifyResourceChange(respNotify, SwnResourceChangeType.RESOURCE_STATE_UNAVAILABLE); callId = swnClientForWitness.WitnessrAsyncNotify(pContext); BaseTestSite.Assert.AreNotEqual <uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId); } while (true); ret = swnClientForWitness.WitnessrUnRegister(pContext); BaseTestSite.Assert.AreEqual <SwnErrorCode>( SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret); pContext = IntPtr.Zero; swnClientForWitness.SwnUnbind(TestConfig.Timeout); if (fsType == FileServerType.ScaleOutFileServer) { // For scale-out file server case, retrieve and use another access IP for connection currentAccessIpAddr = (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6); } } #endregion #region Read content and close the file DoUntilSucceed(() => ReadContentAfterFailover(server, currentAccessIpAddr, uncSharePath, file, content, clientGuid, createGuid), TestConfig.FailoverTimeout, "After failover, retry Read content until succeed within timeout span."); #endregion }
/// <summary> /// Print RESP_ASYNC_NOTIFY /// </summary> /// <param name="respNotify">Asynchronous notification</param> public static void PrintNotification(RESP_ASYNC_NOTIFY respNotify) { BaseTestSite.Log.Add(LogEntryKind.Debug, "Receive asynchronous notification"); switch ((SwnMessageType)respNotify.MessageType) { case SwnMessageType.RESOURCE_CHANGE_NOTIFICATION: { RESOURCE_CHANGE[] resourceChangeList; SwnUtility.ParseResourceChange(respNotify, out resourceChangeList); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tRESOURCE_CHANGE"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tcount: {0}", resourceChangeList.Length); foreach (var res in resourceChangeList) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\t\tResource name: {0}", res.ResourceName.Substring(0, res.ResourceName.Length - 1)); switch ((SwnResourceChangeType)res.ChangeType) { case SwnResourceChangeType.RESOURCE_STATE_UNKNOWN: BaseTestSite.Log.Add(LogEntryKind.Debug, "\t\tChange type: RESOURCE_STATE_UNKNOWN"); break; case SwnResourceChangeType.RESOURCE_STATE_AVAILABLE: BaseTestSite.Log.Add(LogEntryKind.Debug, "\t\tChange type: RESOURCE_STATE_AVAILABLE"); break; case SwnResourceChangeType.RESOURCE_STATE_UNAVAILABLE: BaseTestSite.Log.Add(LogEntryKind.Debug, "\t\tChange type: RESOURCE_STATE_UNAVAILABLE"); break; default: BaseTestSite.Log.Add(LogEntryKind.Debug, "\t\tChange type: Unknown type {0}", res.ChangeType); break; } } } break; case SwnMessageType.CLIENT_MOVE_NOTIFICATION: { IPADDR_INFO_LIST IPAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out IPAddrInfoList); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tCLIENT_MOVE"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tReserved: {0}", IPAddrInfoList.Reserved); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIP address count: {0}", IPAddrInfoList.IPAddrInstances); foreach (var ip in IPAddrInfoList.IPAddrList) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tFlags: {0}", ip.Flags); if (((uint)SwnIPAddrInfoFlags.IPADDR_V4 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V4: {0}", (new IPAddress(ip.IPV4)).ToString()); } if (((uint)SwnIPAddrInfoFlags.IPADDR_V6 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V6: {0}", ConvertIPV6(ip.IPV6).ToString()); } } } break; case SwnMessageType.SHARE_MOVE_NOTIFICATION: { IPADDR_INFO_LIST IPAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out IPAddrInfoList); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tSHARE_MOVE"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tReserved: {0}", IPAddrInfoList.Reserved); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIP address count: {0}", IPAddrInfoList.IPAddrInstances); foreach (var ip in IPAddrInfoList.IPAddrList) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tFlags: {0}", ip.Flags); if (((uint)SwnIPAddrInfoFlags.IPADDR_V4 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V4: {0}", (new IPAddress(ip.IPV4)).ToString()); } if (((uint)SwnIPAddrInfoFlags.IPADDR_V6 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V6: {0}", ConvertIPV6(ip.IPV6).ToString()); } } } break; case SwnMessageType.IP_CHANGE_NOTIFICATION: { IPADDR_INFO_LIST IPAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out IPAddrInfoList); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIP_CHANGE"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tReserved: {0}", IPAddrInfoList.Reserved); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIP address count: {0}", IPAddrInfoList.IPAddrInstances); foreach (var ip in IPAddrInfoList.IPAddrList) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tFlags: {0}", ip.Flags); if (((uint)SwnIPAddrInfoFlags.IPADDR_V4 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V4: {0}", (new IPAddress(ip.IPV4)).ToString()); } if (((uint)SwnIPAddrInfoFlags.IPADDR_V6 & ip.Flags) != 0) { BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddr V6: {0}", ConvertIPV6(ip.IPV6).ToString()); } } } break; default: BaseTestSite.Assert.Fail("\t\tMessage type: Unknown type {0}", respNotify.MessageType); break; } }