/// <summary> /// Initializes a new instance of the ServiceJobProvider class /// </summary> /// <param name="headNode">indicating the head node</param> /// <param name="endpointPrefix">indicating the endpoint prefix</param> /// <param name="binding">indicting the binding</param> //public ServiceJobProvider(string headNode, string endpointPrefix, Binding binding) //{ // this.headNode = headNode; // this.endpointPrefix = endpointPrefix; // this.binding = binding; // this.client = new SessionLauncherClient(Utility.GetSessionLauncher(headNode, endpointPrefix), binding); //} /// <summary> /// Initializes a new instance of the ServiceJobProvider class /// </summary> /// <param name="info">The session start info</param> /// <param name="binding">indicting the binding</param> public ServiceJobProvider(SessionStartInfo info, Binding binding) { this.headNode = info.Headnode; this.binding = binding; if ((info.TransportScheme & TransportScheme.NetTcp) == TransportScheme.NetTcp) { this.endpointPrefix = SessionLauncherClient.EndpointPrefix; } else if ((info.TransportScheme & TransportScheme.Http) == TransportScheme.Http || (info.TransportScheme & TransportScheme.NetHttp) == TransportScheme.NetHttp) { this.endpointPrefix = SessionLauncherClient.HttpsEndpointPrefix; } else if ((info.TransportScheme & TransportScheme.Custom) == TransportScheme.Custom) { this.endpointPrefix = SessionLauncherClient.EndpointPrefix; } this.client = new SessionLauncherClient(info, binding); #if !net40 if (info.UseAad) { this.client.Endpoint.Behaviors.UseAadClientBehaviors(info).GetAwaiter().GetResult(); } #endif }
/// <summary> /// Free resource by cancel service job /// </summary> /// <param name="sessionId">indicating the session id</param> public async Task FreeResource(SessionStartInfo startInfo, int sessionId) { try { if (sessionId != 0) { RetryManager retry = SoaHelper.GetDefaultExponentialRetryManager(); await RetryHelper <object> .InvokeOperationAsync( async() => { await this.client.TerminateV5Async(sessionId).ConfigureAwait(false); return(null); }, (e, r) => { if (e is EndpointNotFoundException) { Utility.SafeCloseCommunicateObject(this.client); this.client = new SessionLauncherClient(startInfo, this.binding); } else { r.MaxRetryCount = 0; } return(CompletedTask); }, retry).ConfigureAwait(false); } } catch { // if terminate the session failed, then do nothing here. } }
/// <summary> /// Get resource information /// </summary> /// <param name="attachInto">indicating session attach information</param> /// <param name="timeout">indicating the timeout</param> /// <returns>returns session information</returns> public async Task <SessionInfo> GetResourceInfo(SessionAttachInfo attachInfo, TimeSpan timeout) { this.client.InnerChannel.OperationTimeout = timeout; RetryManager retry = SoaHelper.GetDefaultExponentialRetryManager(); SessionInfo info; DateTime startTime = DateTime.Now; if (attachInfo.TransportScheme == TransportScheme.Http) { info = Utility.BuildSessionInfoFromDataContract(await RetryHelper <SessionInfoContract> .InvokeOperationAsync( async() => await this.client.GetInfoV5Sp1Async(SessionLauncherClient.HttpsEndpointPrefix, attachInfo.SessionId, attachInfo.UseAad).ConfigureAwait(false), (e, r) => { var remainingTime = GetRemainingTime(timeout, startTime); if ((e is EndpointNotFoundException || (e is CommunicationException && !(e is FaultException <SessionFault>))) && remainingTime > TimeSpan.Zero) { Utility.SafeCloseCommunicateObject(this.client); this.client = new SessionLauncherClient(attachInfo, this.binding); this.client.InnerChannel.OperationTimeout = remainingTime; } else { r.MaxRetryCount = 0; } return(CompletedTask); }, retry).ConfigureAwait(false)); } else { info = Utility.BuildSessionInfoFromDataContract(await RetryHelper <SessionInfoContract> .InvokeOperationAsync( async() => await this.client.GetInfoV5Sp1Async(SessionLauncherClient.EndpointPrefix, attachInfo.SessionId, attachInfo.UseAad).ConfigureAwait(false), (e, r) => { var remainingTime = GetRemainingTime(timeout, startTime); if ((e is EndpointNotFoundException || (e is CommunicationException && !(e is FaultException <SessionFault>))) && remainingTime > TimeSpan.Zero) { Utility.SafeCloseCommunicateObject(this.client); this.client = new SessionLauncherClient(attachInfo, this.binding); this.client.InnerChannel.OperationTimeout = remainingTime; } else { r.MaxRetryCount = 0; } return(CompletedTask); }, retry).ConfigureAwait(false)); } return(info); }
protected override void Dispose(bool disposing) { if (disposing) { if (this.client != null) { Utility.SafeCloseCommunicateObject(this.client); this.client = null; } } base.Dispose(disposing); }
/// <summary> /// This method closes the session async with the given ID /// </summary> /// <param name="headNode">Headnode name</param> /// <param name="sessionId">The ID of the session to be closed</param> /// <param name="binding">indicting the binding</param> /// <param name="isAadUser">If the session is belong to a AAD user</param> /// <param name="token">The cancellation token.</param> public static async Task CloseSessionAsync(string headNode, string sessionId, Binding binding, bool isAadUser, CancellationToken token) { Utility.ThrowIfEmpty(headNode, "headNode"); SessionLauncherClient client = null; BrokerLauncherClient broker = null; string headNodeMachine = await TelepathyContext.GetOrAdd(headNode).ResolveSessionLauncherNodeAsync().ConfigureAwait(false); try { client = new SessionLauncherClient(headNodeMachine, binding, isAadUser); client.InnerChannel.OperationTimeout = GetTimeout(DateTime.MaxValue); // TODO: need to change the endpoint prefix for https SessionInfo info = null; if (binding is NetTcpBinding) { info = Utility.BuildSessionInfoFromDataContract(await client.GetInfoAsync(SessionLauncherClient.EndpointPrefix, sessionId).ConfigureAwait(false)); } #if !net40 else if (binding is BasicHttpBinding || binding is NetHttpBinding || binding is NetHttpsBinding) { info = Utility.BuildSessionInfoFromDataContract(await client.GetInfoAsync(SessionLauncherClient.HttpsEndpointPrefix, sessionId).ConfigureAwait(false)); } #endif broker = new BrokerLauncherClient(info, binding, new Uri(info.BrokerLauncherEpr)); broker.InnerChannel.OperationTimeout = GetTimeout(DateTime.MaxValue); broker.Close(sessionId); } catch (FaultException <SessionFault> e) { throw Utility.TranslateFaultException(e); } finally { if (client != null) { Utility.SafeCloseCommunicateObject(client); } if (broker != null) { Utility.SafeCloseCommunicateObject(broker); } } }
/// <summary> /// When failure, terminate the session /// </summary> protected override async Task CleanupOnFailure() { if (this.sessionid != 0) { SessionLauncherClient client = new SessionLauncherClient(this.StartInfo, this.binding); try { SessionBase.TraceSource.TraceEvent(TraceEventType.Information, 0, "[Session:{0}] Terminate session because create session failed.", this.sessionid); await client.TerminateV5Async(this.sessionid).ConfigureAwait(false); } catch (Exception e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}] Failed to terminate session: {1}", this.sessionid, e); // swallow } finally { Utility.SafeCloseCommunicateObject(client); } } }
public static async Task <bool> RetrieveCredentialOnPremise(SessionStartInfo info, CredType expectedCredType, Binding binding) { bool popupDialog = false; // Make sure that we have a password and credentials for the user. if (String.IsNullOrEmpty(info.Username) || String.IsNullOrEmpty(info.InternalPassword)) { string username = null; // First try to get something from the cache. if (String.IsNullOrEmpty(info.Username)) { username = WindowsIdentity.GetCurrent().Name; } else { username = info.Username; } // Use local machine name for session without service job string headnode = info.Headnode; if (String.IsNullOrEmpty(headnode)) { headnode = Environment.MachineName; } //TODO: SF: headnode is a gateway string now // For back compact, get the cached password if it exists. byte[] cached = CredentialHelper.FetchPassword(headnode, username); if (cached != null) { info.Username = username; info.InternalPassword = Encoding.Unicode.GetString(ProtectedData.Unprotect(cached, null, DataProtectionScope.CurrentUser)); } else { if (expectedCredType != CredType.None) { if (expectedCredType == CredType.Either || expectedCredType == CredType.Either_CredUnreusable) { // Pops up dialog asking users to specify the type of the credetial (password or certificate). // The behavior here aligns with the job submission. expectedCredType = CredUtil.PromptForCredentialType(bConsole, hwnd, expectedCredType); } Debug.Assert(expectedCredType == CredType.Password || expectedCredType == CredType.Password_CredUnreusable || expectedCredType == CredType.Certificate); if (expectedCredType == CredType.Password) { bool fSave = false; SecureString password = null; Credentials.PromptForCredentials(headnode, ref username, ref password, ref fSave, bConsole, hwnd); popupDialog = true; info.Username = username; info.SavePassword = fSave; info.InternalPassword = Credentials.UnsecureString(password); } else if (expectedCredType == CredType.Password_CredUnreusable) { SecureString password = null; Credentials.PromptForCredentials(headnode, ref username, ref password, bConsole, hwnd); popupDialog = true; info.Username = username; info.SavePassword = false; info.InternalPassword = Credentials.UnsecureString(password); } else { // Get the value of cluster parameter HpcSoftCardTemplate. SessionLauncherClient client = new SessionLauncherClient(await Utility.GetSessionLauncherAsync(info, binding).ConfigureAwait(false), binding, info.IsAadOrLocalUser); string softCardTemplate = String.Empty; try { softCardTemplate = await client.GetSOAConfigurationAsync(Constant.HpcSoftCardTemplateParam).ConfigureAwait(false); } finally { Utility.SafeCloseCommunicateObject(client); } // Query certificate from local store, and pops up CertSelectionDialog. SecureString pfxPwd; info.Certificate = CredUtil.GetCertFromStore(null, softCardTemplate, bConsole, hwnd, out pfxPwd); info.PfxPassword = Credentials.UnsecureString(pfxPwd); } } else { // Expect to use the cached credential at scheuler side. // Exception may happen later if no cached redential or it is invalid. info.ClearCredential(); info.Username = username; } } } return(popupDialog); }
/// <summary> /// Allocate resource for service job and provide broker epr /// </summary> /// <param name="startInfo">indicating session start information</param> /// <param name="durable">indicating whether it is a durable session</param> /// <param name="timeout">indicating the timeout</param> /// <param name="eprs">output string array of available broker epr list</param> /// <param name="sessionInfo">the session info</param> /// <returns>returns unique session id</returns> public async Task <SessionAllocateInfoContract> AllocateResource(SessionStartInfo startInfo, bool durable, TimeSpan timeout) { SessionAllocateInfoContract sessionAllocateInfo = new SessionAllocateInfoContract(); this.client.InnerChannel.OperationTimeout = timeout; RetryManager retry = SoaHelper.GetDefaultExponentialRetryManager(); SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:Unknown] Allocating resource... IsDurable = {0}, is LocalUser = {1}", durable, startInfo.LocalUser); DateTime startTime = DateTime.Now; if (durable) { sessionAllocateInfo = await RetryHelper <SessionAllocateInfoContract> .InvokeOperationAsync( async() => await this.client.AllocateDurableV5Async(startInfo.Data, this.endpointPrefix).ConfigureAwait(false), (e, r) => { var remainingTime = GetRemainingTime(timeout, startTime); if ((e is EndpointNotFoundException || (e is CommunicationException && !(e is FaultException <SessionFault>))) && remainingTime > TimeSpan.Zero) { Utility.SafeCloseCommunicateObject(this.client); this.client = new SessionLauncherClient(startInfo, this.binding); this.client.InnerChannel.OperationTimeout = remainingTime; } else { r.MaxRetryCount = 0; } return(CompletedTask); }, retry).ConfigureAwait(false); } else { sessionAllocateInfo = await RetryHelper <SessionAllocateInfoContract> .InvokeOperationAsync( async() => await this.client.AllocateV5Async(startInfo.Data, this.endpointPrefix).ConfigureAwait(false), (e, r) => { var remainingTime = GetRemainingTime(timeout, startTime); if ((e is EndpointNotFoundException || (e is CommunicationException && !(e is FaultException <SessionFault>))) && remainingTime > TimeSpan.Zero) { Utility.SafeCloseCommunicateObject(this.client); this.client = new SessionLauncherClient(startInfo, this.binding); this.client.InnerChannel.OperationTimeout = remainingTime; } else { r.MaxRetryCount = 0; } return(CompletedTask); }, retry).ConfigureAwait(false); } SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}] Successfully allocated resource. Eprs = {1}", sessionAllocateInfo.Id, sessionAllocateInfo.BrokerLauncherEpr == null ? string.Empty : string.Join(",", sessionAllocateInfo.BrokerLauncherEpr)); if (sessionAllocateInfo.ServiceVersion != null) { try { startInfo.Data.ServiceVersion = sessionAllocateInfo.ServiceVersion; } catch { throw new SessionException(SR.InvalidServiceVersionReturned); } } if (startInfo.UseSessionPool) { return(sessionAllocateInfo); } else { if (!startInfo.UseInprocessBroker && (sessionAllocateInfo.BrokerLauncherEpr == null || sessionAllocateInfo.BrokerLauncherEpr.Length == 0)) { throw new SessionException(SR.NoBrokerNodeFound); } return(sessionAllocateInfo); } }
/// <summary> /// Allocate the session resource. The function will check password /// </summary> /// <param name="client"></param> /// <param name="startInfo"></param> private async Task BeginAllocate(SessionStartInfo startInfo, CredType credType) { bool durable = (GetType() == typeof(DurableSessionAsyncResult)); SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:Unknown] Start to create session, IsDurable = {0}.", durable); while (retry > 0) { try { SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:Unknown] Authenticating... Retry Count = {0}, CredType = {1}", HardCodedRetryLimit + 1 - retry, credType); if (SoaHelper.IsSchedulerOnAzure(this.StartInfo.Headnode) || SoaHelper.IsSchedulerOnIaaS(this.StartInfo.Headnode)) { SessionBase.RetrieveCredentialOnAzure(this.StartInfo); } else { await SessionBase.RetrieveCredentialOnPremise(this.StartInfo, credType, this.binding).ConfigureAwait(false); SessionBase.CheckCredential(this.StartInfo); } break; } catch (AuthenticationException) { if (credType == CredType.None) { credType = await CredUtil.GetCredTypeFromClusterAsync(this.StartInfo, this.binding).ConfigureAwait(false); } this.StartInfo.ClearCredential(); SessionBase.PurgeCredential(this.StartInfo); retry--; if (retry == 0) { throw; } } } SessionLauncherClient client = new SessionLauncherClient(startInfo, this.binding); try { SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:Unknown] Allocating resource..."); if (durable) { if ((StartInfo.TransportScheme & TransportScheme.NetTcp) == TransportScheme.NetTcp) { client.BeginAllocateDurable(this.StartInfo.Data, SessionLauncherClient.EndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.NetHttp) == TransportScheme.NetHttp) { client.BeginAllocateDurable(this.StartInfo.Data, SessionLauncherClient.HttpsEndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.Http) == TransportScheme.Http) { client.BeginAllocateDurable(this.StartInfo.Data, SessionLauncherClient.HttpsEndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.Custom) == TransportScheme.Custom) { client.BeginAllocateDurable(this.StartInfo.Data, SessionLauncherClient.EndpointPrefix, this.AllocateCallback, client); } } else { if ((StartInfo.TransportScheme & TransportScheme.NetTcp) == TransportScheme.NetTcp) { client.BeginAllocate(this.StartInfo.Data, SessionLauncherClient.EndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.NetHttp) == TransportScheme.NetHttp) { client.BeginAllocate(this.StartInfo.Data, SessionLauncherClient.HttpsEndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.Http) == TransportScheme.Http) { client.BeginAllocate(this.StartInfo.Data, SessionLauncherClient.HttpsEndpointPrefix, this.AllocateCallback, client); } else if ((StartInfo.TransportScheme & TransportScheme.Custom) == TransportScheme.Custom) { client.BeginAllocate(this.StartInfo.Data, SessionLauncherClient.EndpointPrefix, this.AllocateCallback, client); } } } catch (EndpointNotFoundException e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:Unknown] EndpointNotFoundException occured while allocating resource: {0}", e); SessionBase.HandleEndpointNotFoundException(this.StartInfo.Headnode); } return; }
/// <summary> /// The callback function for the allocate operation to session launcher /// </summary> /// <param name="ar">the async result</param> private void AllocateCallback(IAsyncResult ar) { SessionLauncherClient client = (SessionLauncherClient)ar.AsyncState; SessionInfoContract sessionInfo; try { try { bool durable = (GetType() == typeof(DurableSessionAsyncResult)); if (durable) { this.eprCanidates = client.EndAllocateDurable(out this.sessionid, out serviceVersion, out sessionInfo, ar); } else { this.eprCanidates = client.EndAllocate(out this.sessionid, out serviceVersion, out sessionInfo, ar); } SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}] Successfully allocated resource. ServiceVersion = {1}", this.sessionid, serviceVersion); this.eprPtr = 0; // If HpcSession returns a version, pass it to HpcBroker if (!String.IsNullOrEmpty(serviceVersion)) { try { this.StartInfo.Data.ServiceVersion = new Version(serviceVersion); } catch { throw new SessionException(SR.InvalidServiceVersionReturned); } } SessionBase.SaveCrendential(this.StartInfo, this.binding); if (this.eprCanidates == null || this.eprCanidates.Length == 0) { throw new SessionException(SR.NoBrokerNodeFound); } if (SoaHelper.IsSchedulerOnIaaS(this.StartInfo.Headnode)) { string suffix = SoaHelper.GetSuffixFromHeadNodeEpr(this.StartInfo.Headnode); for (int i = 0; i < this.eprCanidates.Length; i++) { this.eprCanidates[i] = SoaHelper.UpdateEprWithCloudServiceName(this.eprCanidates[i], suffix); } } SessionBase.TraceSource.TraceInformation("Get the EPR list from headnode. number of eprCanidates={0}", this.eprCanidates.Length); if (!this.Canceled) { this.ConnectToNextBroker(); } else { // Bug 11765: If the operation is canceled, when allocating // resource, do cleanup the resource this.CleanupOnFailure().GetAwaiter().GetResult(); } } catch (AuthenticationException ex) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] AuthenticationException occured while allocating resource: {0}", ex); this.StartInfo.ClearCredential(); SessionBase.PurgeCredential(this.StartInfo); if (retry > 0) { //TODO: remove sync wait BeginAllocate(this.StartInfo, CredType.None).GetAwaiter().GetResult(); } else { this.MarkFinish(new AuthenticationException(SR.AuthenticationFailed, ex)); } } catch (MessageSecurityException ex) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] MessageSecurityException occured while allocating resource: {0}", ex); this.StartInfo.ClearCredential(); SessionBase.PurgeCredential(this.StartInfo); if (retry > 0) { //TODO: remove sync wait BeginAllocate(this.StartInfo, CredType.None).GetAwaiter().GetResult(); } else { this.MarkFinish(new AuthenticationException(SR.AuthenticationFailed, ex)); } } catch (FaultException <SessionFault> ex) { int faultCode = (ex as FaultException <SessionFault>).Detail.Code; CredType type = CredUtil.GetCredTypeFromFaultCode(faultCode); SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] Fault exception occured while allocating resource. FaultCode = {0}, CredType = {1}", faultCode, type); if (type != CredType.None) { this.StartInfo.ClearCredential(); if (retry > 0) { //TODO: remove sync wait BeginAllocate(this.StartInfo, type).GetAwaiter().GetResult(); } else { this.MarkFinish(new AuthenticationException(SR.AuthenticationFailed, ex)); } } else { throw; } } } catch (FaultException <SessionFault> ex) { this.MarkFinish(Utility.TranslateFaultException(ex)); } catch (Exception ex) { this.MarkFinish(ex); } finally { Utility.SafeCloseCommunicateObject(client); } }
/// <summary> /// Get the expected credential type according to the cluster parameters /// "HpcSoftCard" and "DisableCredentialReuse" /// </summary> /// <param name="headnode">scheduler name</param> /// <param name="binding">indicating the binding</param> /// <returns>credential type</returns> internal static async Task <CredType> GetCredTypeFromClusterAsync(string headnode, Binding binding, bool isAadUser) { HpcSoftCardPolicy policy = HpcSoftCardPolicy.Disabled; bool disableCredentialReuse = false; //TODO: SF: retry SessionLauncherClient client = new SessionLauncherClient(headnode, binding, isAadUser); try { List <string> keys = new List <string>() { Constant.HpcSoftCard, Constant.DisableCredentialReuse }; Dictionary <string, string> result = await client.GetSOAConfigurationsAsync(keys).ConfigureAwait(false); string hpcSoftCardString = result[Constant.HpcSoftCard]; if (!String.IsNullOrEmpty(hpcSoftCardString)) { try { policy = (HpcSoftCardPolicy)Enum.Parse(typeof(HpcSoftCardPolicy), hpcSoftCardString); } catch (ArgumentException) { // use the default value if the value is not valid } } string disableCredentialReuseString = result[Constant.DisableCredentialReuse]; if (!String.IsNullOrEmpty(disableCredentialReuseString)) { try { disableCredentialReuse = Boolean.Parse(disableCredentialReuseString); } catch (FormatException) { // use the default value if the value is not valid } } } catch (Exception) { // the previous version server doesn't provide such info, so use the default values } finally { Utility.SafeCloseCommunicateObject(client); } switch (policy) { case HpcSoftCardPolicy.Disabled: if (disableCredentialReuse) { return(CredType.Password_CredUnreusable); } else { return(CredType.Password); } case HpcSoftCardPolicy.Allowed: if (disableCredentialReuse) { return(CredType.Either_CredUnreusable); } else { return(CredType.Either); }; case HpcSoftCardPolicy.Required: return(CredType.Certificate); default: return(CredType.None); } }