/// <summary> /// Verify CLIENT_MOVE_NOTIFICATION/SHARE_MOVE_NOTIFICATION/IP_CHANGE_NOTIFICATION in Asynchronous Notification /// </summary> /// <param name="respNotify">Asynchronous notification</param> /// <param name="expectedMessageType">Expected message type</param> /// <param name="expectedIPAddrInforFlag">Expected flag</param> /// <param name="platform">Platform of SUT</param> public static void VerifyClientMoveShareMoveAndIpChange(RESP_ASYNC_NOTIFY respNotify, SwnMessageType expectedMessageType, uint expectedIPAddrInforFlag, Platform platform) { BaseTestSite.Assert.AreEqual <uint>((uint)expectedMessageType, respNotify.MessageType, "Expect MessageType is set to " + expectedMessageType.ToString()); BaseTestSite.Assert.AreEqual <uint>(1, respNotify.NumberOfMessages, "NumberOfMessages MUST be set to 1."); IPADDR_INFO_LIST IPAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out IPAddrInfoList); BaseTestSite.Assert.AreEqual <uint>(respNotify.Length, IPAddrInfoList.Length, "Expect Length is the size of the IPADDR_INFO_LIST structure."); BaseTestSite.Assert.AreEqual <uint>(0, IPAddrInfoList.Reserved, "Expect Reserved is 0."); BaseTestSite.Assert.IsTrue(IPAddrInfoList.IPAddrInstances >= 1, "Expect that there is at least one available IPAddress in the IPADDR_INFO structures."); BaseTestSite.Assert.AreEqual <uint>(IPAddrInfoList.IPAddrInstances, (uint)IPAddrInfoList.IPAddrList.Length, "Expect that the length of IPAddrList equals IPAddrInstances ."); for (int i = 0; i < IPAddrInfoList.IPAddrInstances; i++) { /// 2.2.2.1 IPADDR_INFO /// Flags (4 bytes): The Flags field SHOULD<1> be set to a combination of one or more of the following values. /// <1> Section 2.2.2.1: Windows Server 2012 and Windows Server 2012 R2 set the undefined Flags field bits to arbitrary values. if (platform == Platform.NonWindows) { BaseTestSite.Assert.AreEqual <uint>(expectedIPAddrInforFlag, IPAddrInfoList.IPAddrList[i].Flags, "Expect the Flags in IPADDR_INFO structures in the IPAddrList equals " + expectedIPAddrInforFlag.ToString()); } if ((IPAddrInfoList.IPAddrList[i].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 && IPAddrInfoList.IPAddrList[i].IPV4 == 0) { BaseTestSite.Assert.Fail("The IPV4 {0} in IPAddrInfoList.IPAddrList is invalid.", new IPAddress(IPAddrInfoList.IPAddrList[i].IPV4).ToString()); } else if ((IPAddrInfoList.IPAddrList[i].Flags & (uint)SwnNodeFlagsValue.IPv6) != 0 && IPAddrInfoList.IPAddrList[i].IPV6.All(ip => ip == 0)) { BaseTestSite.Assert.Fail("The IPV6 {0} in IPAddrInfoList.IPAddrList is invalid.", ConvertIPV6(IPAddrInfoList.IPAddrList[i].IPV6).ToString()); } } }
/// <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; } }
/// <summary> /// Test CLIENT_MOVE_NOTIFICATION. /// </summary> /// <param name="expectedVersion">SwnVersion.SWN_VERSION_2 indicates that register with WitnessrRegisterEx, SwnVersion.SWN_VERSION_1 indicates that register with WitnessrRegister.</param> private void SWNAsyncNotification_ClientMove(SwnVersion expectedVersion) { int ret = 0; uint callId = 0; WITNESS_INTERFACE_INFO registerInterface; string server = TestConfig.ClusteredScaleOutFileServerName; #region Get the file server to access it through SMB2 IPAddress currentAccessIp = SWNTestUtility.GetCurrentAccessIP(server); BaseTestSite.Assert.AreNotEqual(null, currentAccessIp, "IP address of the file server should NOT be empty"); BaseTestSite.Log.Add(LogEntryKind.Debug, "Got the IP {0} to access the file server", currentAccessIp.ToString()); #endregion #region Get register interface DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIp, TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage, TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, server), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST(); 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"); swnClientForInterface.SwnUnbind(TestConfig.Timeout); SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface); SWNTestUtility.CheckVersion(expectedVersion, (SwnVersion)registerInterface.Version); #endregion #region Register SWN witness 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, server), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); string clientName = Guid.NewGuid().ToString(); string netName = SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server); BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", netName); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName); if (SwnVersion.SWN_VERSION_2 == expectedVersion) { ret = swnClientForWitness.WitnessrRegisterEx(SwnVersion.SWN_VERSION_2, netName, null, currentAccessIp.ToString(), clientName, WitnessrRegisterExFlagsValue.WITNESS_REGISTER_IP_NOTIFICATION, 120, out pContext); BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegisterEx returns with result code = 0x{0:x8}", ret); } else { ret = swnClientForWitness.WitnessrRegister(SwnVersion.SWN_VERSION_1, netName, currentAccessIp.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(); FileServerType fsType = FileServerType.ScaleOutFileServer; DoUntilSucceed(() => WriteContentBeforeFailover(fsType, server, currentAccessIp, uncSharePath, file, content, clientGuid, createGuid), TestConfig.FailoverTimeout, "Before failover, retry Write content until succeed within timeout span."); #endregion #region Move resource node // Move resource node to trigger CLIENT_MOVE_NOTIFICATION BaseTestSite.Log.Add(LogEntryKind.Debug, "Move resource to interface {0} to trigger CLIENT_MOVE_NOTIFICATION", registerInterface.InterfaceGroupName); sutController.MoveSmbWitnessClient(clientName, SWNTestUtility.GetPrincipleName(TestConfig.DomainName, registerInterface.InterfaceGroupName)); #endregion #region Wait CLIENT_MOVE_NOTIFICATION RESP_ASYNC_NOTIFY respNotify; // Wait the CLIENT_MOVE_NOTIFICATION ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify); BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrAsyncNotify returns with result code = 0x{0:x8}", ret); SWNTestUtility.PrintNotification(respNotify); // Verify RESP_ASYNC_NOTIFY SWNTestUtility.VerifyClientMoveShareMoveAndIpChange(respNotify, SwnMessageType.CLIENT_MOVE_NOTIFICATION, (uint)SwnIPAddrInfoFlags.IPADDR_V4, TestConfig.Platform); #endregion #region Get the new IpAddr IPADDR_INFO_LIST ipAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out ipAddrInfoList); currentAccessIp = (ipAddrInfoList.IPAddrList[0].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(ipAddrInfoList.IPAddrList[0].IPV4) : SWNTestUtility.ConvertIPV6(ipAddrInfoList.IPAddrList[0].IPV6); #endregion #region Unregister SWN Witness 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); #endregion #region Make sure Cluster Share is available DoUntilSucceed(() => sutProtocolController.CheckIfShareIsAvailable(uncSharePath), testConfig.Timeout, "Make sure cluster share is available."); #endregion #region Read content and close the file DoUntilSucceed(() => ReadContentAfterFailover(server, currentAccessIp, uncSharePath, file, content, clientGuid, createGuid), TestConfig.FailoverTimeout, "Retry Read content until succeed within timeout span."); #endregion }
private void TestAsymmetricShare(DialectRevision requestMaxDialect, string serverName, bool isAsymmetricShare) { int ret = 0; uint callId = 0; Guid clientGuid = Guid.NewGuid(); WITNESS_INTERFACE_INFO registerInterface; string shareName = isAsymmetricShare ? TestConfig.AsymmetricShare : TestConfig.BasicFileShare; #region Get the file server to access it through SMB2 IPAddress currentAccessIp = SWNTestUtility.GetCurrentAccessIP(serverName); BaseTestSite.Assert.IsNotNull(currentAccessIp, "IP address of the file server should NOT be empty"); BaseTestSite.Log.Add(LogEntryKind.Debug, "Got the IP {0} to access the file server", currentAccessIp.ToString()); #endregion #region Connect to the asymmetric share uncSharePath = Smb2Utility.GetUncPath(serverName, shareName); string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); testDirectory = CreateTestDirectory(uncSharePath); string file = string.Format(@"{0}\{1}", testDirectory, Guid.NewGuid().ToString()); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP"); smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); smb2Client.ConnectToServerOverTCP(currentAccessIp); smb2Client.Negotiate( Smb2Utility.GetDialects(requestMaxDialect), TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed."); BaseTestSite.Assert.AreEqual( requestMaxDialect, response.DialectRevision, "The server is expected to use dialect {0}. Actual dialect is {1}", requestMaxDialect, response.DialectRevision); }); smb2Client.SessionSetup( TestConfig.DefaultSecurityPackage, serverName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId = 0; Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request to the {0} on the {1}", shareName, serverName); DoUntilSucceed( () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { shareCapabilities = response.Capabilities; }), TestConfig.FailoverTimeout, "Retry TreeConnect until succeed within timeout span"); if (requestMaxDialect == DialectRevision.Smb302 && isAsymmetricShare) { BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC), "The capabilities of the share should contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities); } else { BaseTestSite.Assert.IsFalse(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC), "The capabilities of the share should not contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities); #region Disconnect current SMB2 connection smb2Client.TreeDisconnect(treeId); smb2Client.LogOff(); smb2Client.Disconnect(); #endregion return; } FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file."); smb2Client.Create( treeId, file, CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE); smb2Client.Write(treeId, fileId, content); string readContent; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file."); smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( content.Equals(readContent), "Content read should be identical to that written."); #endregion #region Get register interface DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIp, TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage, TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, serverName), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST(); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrGetInterfaceList."); 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"); swnClientForInterface.SwnUnbind(TestConfig.Timeout); SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface); #endregion #region Get SHARE_MOVE_NOTIFICATION 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, serverName), TestConfig.FailoverTimeout, "Retry BindServer until succeed within timeout span"); string clientName = TestConfig.WitnessClientName; BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:"); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", serverName); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrRegisterEx."); ret = swnClientForWitness.WitnessrRegisterEx(SwnVersion.SWN_VERSION_2, serverName, shareName, currentAccessIp.ToString(), clientName, WitnessrRegisterExFlagsValue.WITNESS_REGISTER_IP_NOTIFICATION, 120, out pContext); BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegisterEx returns with result code = 0x{0:x8}", ret); BaseTestSite.Assert.IsNotNull(pContext, "Expect pContext is not null."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrAsyncNotify."); callId = swnClientForWitness.WitnessrAsyncNotify(pContext); BaseTestSite.Assert.AreNotEqual <uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId); // NOTICE // This comment is for current Windows Cluster test environment. // Current test environment has only two nodes and both they are optimum nodes. // So whatever the server name is, SHARE_MOVE_NOTIFICATION notification will be recieved. // The configuration items 'OptimumNodeOfAsymmetricShare' and 'NonOptimumNodeOfAsymmetricShare' are assigned the same default value. // The code in if block will be executed all the time. if (serverName == TestConfig.NonOptimumNodeOfAsymmetricShare) { #region Expect that SHARE_MOVE_NOTIFICATION notification will be received when the client connects to the asymmetric share on the non-optimum share RESP_ASYNC_NOTIFY respNotify; ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify); BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrAsyncNotify returns with result code = 0x{0:x8}", ret); SWNTestUtility.PrintNotification(respNotify); SWNTestUtility.VerifyClientMoveShareMoveAndIpChange(respNotify, SwnMessageType.SHARE_MOVE_NOTIFICATION, (uint)SwnIPAddrInfoFlags.IPADDR_V4, TestConfig.Platform); #region Get the new IpAddr IPADDR_INFO_LIST ipAddrInfoList; SwnUtility.ParseIPAddrInfoList(respNotify, out ipAddrInfoList); currentAccessIp = (ipAddrInfoList.IPAddrList[0].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(ipAddrInfoList.IPAddrList[0].IPV4) : SWNTestUtility.ConvertIPV6(ipAddrInfoList.IPAddrList[0].IPV6); #endregion #region Unregister SWN Witness BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister."); 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); #endregion #region Disconnect current SMB2 connection BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT."); smb2Client.TreeDisconnect(treeId); smb2Client.LogOff(); smb2Client.Disconnect(); #endregion #endregion } else { #region Expect that no SHARE_MOVE_NOTIFICATION notification will be received when the client connects to the asymmetric share on the optimum share bool isNotificationReceived = false; try { RESP_ASYNC_NOTIFY respNotify; ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify); isNotificationReceived = true; } catch (TimeoutException) { isNotificationReceived = false; } #region Disconnect current SMB2 connection BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT"); smb2Client.TreeDisconnect(treeId); smb2Client.LogOff(); smb2Client.Disconnect(); #endregion #region Unregister SWN Witness BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister."); 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); #endregion BaseTestSite.Assert.IsFalse(isNotificationReceived, "Expect that no notification will be received when the client has connected to asymmetric share on the optimum node."); #endregion return; } #endregion #region Connect to the share on the optimum node smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Got the IP {0} to access the file server", currentAccessIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP"); smb2Client.ConnectToServerOverTCP(currentAccessIp); smb2Client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: Guid.NewGuid(), checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed."); }); smb2Client.SessionSetup( TestConfig.DefaultSecurityPackage, serverName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client sends TREE_CONNECT and wait for a response until timeout."); DoUntilSucceed( () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { }), TestConfig.FailoverTimeout, "Retry TreeConnect until succeed within timeout span"); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file."); smb2Client.Create( treeId, file, CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE); smb2Client.Write(treeId, fileId, content); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file."); smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( content.Equals(readContent), "Content read should be identical to that written."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT."); smb2Client.TreeDisconnect(treeId); smb2Client.LogOff(); smb2Client.Disconnect(); #endregion }