/// <summary> /// Create session /// </summary> /// <param name="startInfo">indicating session start information</param> /// <param name="durable">indicating a value whether a durable session is to be created</param> /// <param name="timeoutMilliseconds">indicating the timeout</param> /// <param name="binding">indicating the binding</param> /// <returns>returns session instance</returns> public override async Task <SessionBase> CreateSession(SessionStartInfo startInfo, bool durable, int timeoutMilliseconds, Binding binding) { SessionBase.CheckSessionStartInfo(startInfo); DateTime targetTimeout = DateTime.Now.AddMilliseconds(Constant.DefaultCreateSessionTimeout); // if following env variable is set, we will launch the service host in an admin job. string adminJobEnv = Environment.GetEnvironmentVariable(SessionBase.EnvVarNameForAdminJob, EnvironmentVariableTarget.Process); if (!string.IsNullOrEmpty(adminJobEnv) && adminJobEnv.Equals("1", StringComparison.InvariantCultureIgnoreCase)) { startInfo.AdminJobForHostInDiag = true; } SessionAllocateInfoContract sessionAllocateInfo = null; CredType typeOfExpectedCred = CredType.None; IResourceProvider resourceProvider = null; IList <string> newDataClients = null; try { int retry = 0; bool askForCredential = false; // allow users to try credential at most MaxRetryCount times int askForCredentialTimes = 0; while (Utility.CanRetry(retry, askForCredential, askForCredentialTimes)) { retry++; try { SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:Unknown] Start to create session for on-premise cluster. IsDurable = {0}, RetryCount = {1}, AskForCredentialTimes = {2}, TimeCost = {3}", durable, retry, askForCredentialTimes, targetTimeout); Stopwatch watch = new Stopwatch(); watch.Start(); if (startInfo.UseAad) { // Authentication handled by AADUtil } else if (SoaHelper.IsSchedulerOnAzure(startInfo.Headnode) || SoaHelper.IsSchedulerOnIaaS(startInfo.Headnode) || (startInfo.TransportScheme & TransportScheme.Http) == TransportScheme.Http || (startInfo.TransportScheme & TransportScheme.NetHttp) == TransportScheme.NetHttp) { askForCredential = HpcSessionCredUtil.RetrieveCredentialOnAzure(startInfo); if (askForCredential) { askForCredentialTimes++; } } else { askForCredential = await HpcSessionCredUtil.RetrieveCredentialOnPremise(startInfo, typeOfExpectedCred, binding).ConfigureAwait(false); if (askForCredential) { askForCredentialTimes++; } HpcSessionCredUtil.CheckCredential(startInfo); } resourceProvider = BuildResourceProvider(startInfo, durable, binding); if (((newDataClients == null) || (newDataClients.Count == 0)) && (startInfo.DependFiles != null) && (startInfo.DependFiles.Count > 0)) { // Upload the data files required for this session newDataClients = this.UploadAzureFiles(startInfo); } watch.Stop(); // re-calculate the timeout to exclude the timespan for getting credential targetTimeout = targetTimeout.AddMilliseconds(watch.ElapsedMilliseconds); sessionAllocateInfo = await resourceProvider.AllocateResource(startInfo, durable, SessionBase.GetTimeout(targetTimeout)).ConfigureAwait(false); SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}] Successfully allocated resource.", sessionAllocateInfo.Id); if (sessionAllocateInfo.BrokerLauncherEpr != null) { if (SoaHelper.IsSchedulerOnIaaS(startInfo.Headnode)) { string suffix = SoaHelper.GetSuffixFromHeadNodeEpr(startInfo.Headnode); for (int i = 0; i < sessionAllocateInfo.BrokerLauncherEpr.Length; i++) { sessionAllocateInfo.BrokerLauncherEpr[i] = SoaHelper.UpdateEprWithCloudServiceName(sessionAllocateInfo.BrokerLauncherEpr[i], suffix); } } HpcSessionCredUtil.SaveCrendential(startInfo, binding); SessionBase.TraceSource.TraceInformation("Get the EPR list from headnode. number of eprs={0}", sessionAllocateInfo.BrokerLauncherEpr.Length); break; } } catch (EndpointNotFoundException e) { this.CleanUpDataClients(startInfo, newDataClients); SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:Unknown] EndpointNotFoundException occured while allocating resource: {0}", e); SessionBase.HandleEndpointNotFoundException(startInfo.Headnode); } catch (AuthenticationException e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] AuthenticationException occured while allocating resource: {0}", e); startInfo.ClearCredential(); SessionBase.PurgeCredential(startInfo); if (Utility.CanRetry(retry, askForCredential, askForCredentialTimes)) { if (typeOfExpectedCred == CredType.None) { typeOfExpectedCred = await CredUtil.GetCredTypeFromClusterAsync(startInfo, binding).ConfigureAwait(false); } if (resourceProvider is IDisposable) { ((IDisposable)resourceProvider).Dispose(); } continue; } else { if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw; } } catch (MessageSecurityException e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] MessageSecurityException occured while allocating resource: {0}", e); startInfo.ClearCredential(); SessionBase.PurgeCredential(startInfo); if (Utility.CanRetry(retry, askForCredential, askForCredentialTimes)) { if (typeOfExpectedCred == CredType.None) { typeOfExpectedCred = await CredUtil.GetCredTypeFromClusterAsync(startInfo, binding).ConfigureAwait(false); } if (resourceProvider is IDisposable) { ((IDisposable)resourceProvider).Dispose(); } continue; } else { if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw; } } catch (FaultException <SessionFault> ex) { typeOfExpectedCred = Utility.CanRetry(retry, askForCredential, askForCredentialTimes) ? CredUtil.GetCredTypeFromFaultCode(ex.Detail.Code) : CredType.None; SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] Fault exception occured while allocating resource. FaultCode = {0}. Exception = {1}", ex.Detail.Code, ex.ToString()); if (typeOfExpectedCred == CredType.None) { this.CleanUpDataClients(startInfo, newDataClients); if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw Utility.TranslateFaultException(ex); } else { startInfo.ClearCredential(); if (resourceProvider is IDisposable) { ((IDisposable)resourceProvider).Dispose(); } continue; } } catch (CommunicationException e) { this.CleanUpDataClients(startInfo, newDataClients); if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw new SessionException(SOAFaultCode.ConnectSessionLauncherFailure, SR.ConnectSessionLauncherFailure, e); } catch (TimeoutException e) { SessionBase.TraceSource.TraceInformation(e.ToString()); this.CleanUpDataClients(startInfo, newDataClients); if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw new TimeoutException(string.Format(SR.ConnectSessionLauncherTimeout, Constant.DefaultCreateSessionTimeout), e); } catch (Exception e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] Exception occured while allocating resource: {0}", e); this.CleanUpDataClients(startInfo, newDataClients); if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw; } if (sessionAllocateInfo.BrokerLauncherEpr == null && startInfo.UseSessionPool) { // If the session launcher picks a session from the pool, it returns the seesion id. // eprs is null at this case. Try to attach to the session. try { if (sessionAllocateInfo.SessionInfo == null) { SessionBase.TraceSource.TraceInformation("[Session:{0}] Attempt to attach to session {0} which is part of the session pool.", sessionAllocateInfo.Id); return(await AttachSession(new SessionAttachInfo(startInfo.Headnode, sessionAllocateInfo.Id), durable, timeoutMilliseconds, binding).ConfigureAwait(false)); } else { SessionBase.TraceSource.TraceInformation("[Session:{0}] Attempt to attach to broker of the session {0} which is part of the session pool.", sessionAllocateInfo.Id); return(await AttachBroker(startInfo, sessionAllocateInfo.SessionInfo, durable, timeoutMilliseconds, binding).ConfigureAwait(false)); } } catch (Exception e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "Failed to attach to the session {0}. {1}", sessionAllocateInfo.Id, e); if (Utility.CanRetry(retry, askForCredential, askForCredentialTimes)) { if (resourceProvider is IDisposable) { ((IDisposable)resourceProvider).Dispose(); } continue; } else { throw; } } } } IBrokerFactory brokerFactory = BuildBrokerFactory(startInfo, durable); try { return(await brokerFactory.CreateBroker(startInfo, sessionAllocateInfo.Id, targetTimeout, sessionAllocateInfo.BrokerLauncherEpr, binding).ConfigureAwait(false)); } catch { // Free resource if failed to create broker or create session this.CleanUpDataClients(startInfo, newDataClients); await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); throw; } finally { if (brokerFactory is IDisposable) { ((IDisposable)brokerFactory).Dispose(); } } } finally { if (resourceProvider != null) { if (resourceProvider is IDisposable) { ((IDisposable)resourceProvider).Dispose(); } } } }
public override async Task <SessionBase> CreateSession(SessionStartInfo startInfo, bool durable, int timeoutMilliseconds, Binding binding) { SessionBase.CheckSessionStartInfo(startInfo); DateTime targetTimeout = DateTime.Now.AddMilliseconds(Constant.DefaultCreateSessionTimeout); SessionAllocateInfoContract sessionAllocateInfo = null; IResourceProvider resourceProvider = null; try { try { resourceProvider = this.BuildResourceProvider(startInfo, binding); // re-calculate the timeout to exclude the timespan for getting credential sessionAllocateInfo = await resourceProvider.AllocateResource(startInfo, durable, SessionBase.GetTimeout(targetTimeout)).ConfigureAwait(false); SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}] Successfully allocated resource.", sessionAllocateInfo.Id); if (sessionAllocateInfo.BrokerLauncherEpr != null && sessionAllocateInfo.BrokerLauncherEpr.Count() == 1 && sessionAllocateInfo.BrokerLauncherEpr[0] == SessionInternalConstants.BrokerConnectionStringToken) { if (!startInfo.UseAzureStorage) { SessionBase.TraceSource.TraceEvent( TraceEventType.Error, 0, "[Session:{0}] Server side only supports communication via AzureStorageQueue while client doesn't specify UseAzureQueue property and not using AzureStorage scheme.", sessionAllocateInfo.Id); throw new InvalidOperationException("Server side only supports communication via AzureStorageQueue while client doesn't specify UseAzureQueue property."); } } } catch (Exception e) { SessionBase.TraceSource.TraceEvent(TraceEventType.Warning, 0, "[Session:Unknown] Exception occured while allocating resource: {0}", e); if (sessionAllocateInfo != null) { await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); } throw; } IBrokerFactory brokerFactory = BuildBrokerFactory(startInfo, durable); try { return(await brokerFactory.CreateBroker(startInfo, sessionAllocateInfo.Id, targetTimeout, sessionAllocateInfo.BrokerLauncherEpr, binding).ConfigureAwait(false)); } catch { // Free resource if failed to create broker or create session await resourceProvider.FreeResource(startInfo, sessionAllocateInfo.Id).ConfigureAwait(false); throw; } finally { if (brokerFactory != null && brokerFactory is IDisposable disposable) { disposable.Dispose(); } } } finally { if (resourceProvider != null && resourceProvider is IDisposable disposable) { disposable.Dispose(); } } }