Example #1
0
        /// <summary>
        /// start service host by serviceInfo
        /// </summary>
        /// <param name="serviceInfo"></param>
        /// <returns></returns>
        public static int OpenService(ServiceInfo serviceInfo)
        {
            void SetEnvironment()
            {
                if (serviceInfo.Environment == null)
                {
                    TraceHelper.TraceVerbose(Utility.GetJobId(), "No environment fond.");
                    return;
                }

                foreach (var env in serviceInfo.Environment)
                {
                    Environment.SetEnvironmentVariable(env.Key, env.Value);
                    TraceHelper.TraceVerbose(Utility.GetJobId(), $"Set environment {env.Key}={env.Value}.");
                }
            }

            async Task <string[]> DownloadDependFiles()
            {
                if (serviceInfo.DependFiles != null && serviceInfo.DependFiles.Any())
                {
                    var downloadTasks = serviceInfo.DependFiles.Select(fileInfo => StandaloneDataClient.DownloadFileFromSasAsync(
                                                                           fileInfo.Value,
                                                                           Path.Combine(Path.Combine(Path.GetTempPath(), "ExcelOffloading"), Path.GetFileName(fileInfo.Key))));
                    return(await Task.WhenAll(downloadTasks));
                }
                else
                {
                    TraceHelper.TraceVerbose(Utility.GetJobId(), "No depend files fond.");
                    return(new string[0]);
                }
            }

            Environment.SetEnvironmentVariable(Constant.JobIDEnvVar, serviceInfo.JobId.ToString());
            Environment.SetEnvironmentVariable(Constant.TaskIDEnvVar, serviceInfo.TaskId.ToString());
            Environment.SetEnvironmentVariable(Constant.CoreIdsEnvVar, serviceInfo.CoreId.ToString());
            Environment.SetEnvironmentVariable(Constant.ServiceConfigFileNameEnvVar, serviceInfo.FileName);
            if (!string.IsNullOrEmpty(serviceInfo.RegistrationPath))
            {
                Environment.SetEnvironmentVariable(Constant.RegistryPathEnv, serviceInfo.RegistrationPath);
            }
            else
            {
                Environment.SetEnvironmentVariable(Constant.RegistryPathEnv, Path.Combine(Environment.CurrentDirectory, defaultRegistryPath));
            }

            TraceHelper.TraceVerbose(Utility.GetJobId(), $"Set {Constant.RegistryPathEnv} to {Environment.GetEnvironmentVariable(Constant.RegistryPathEnv)}");

            // use default values for following environment variables
            Environment.SetEnvironmentVariable(Constant.ProcNumEnvVar, "1");
            Environment.SetEnvironmentVariable(Constant.NetworkPrefixEnv, Constant.EnterpriseNetwork);
            Environment.SetEnvironmentVariable(Constant.ServiceInitializationTimeoutEnvVar, "60000");
            Environment.SetEnvironmentVariable(Constant.CancelTaskGracePeriodEnvVar, "15");
            Environment.SetEnvironmentVariable(Constant.ServiceConfigMaxMessageEnvVar, "65536");
            Environment.SetEnvironmentVariable(Constant.ServiceConfigServiceOperatonTimeoutEnvVar, "86400000");

            // the local host process won't be preempted by the scheduler
            Environment.SetEnvironmentVariable(Constant.EnableMessageLevelPreemptionEnvVar, bool.FalseString);

            SetEnvironment();
            var dependFilePath = DownloadDependFiles().GetAwaiter().GetResult();

            Environment.SetEnvironmentVariable(Constant.DataServiceSharedFileEnvVar, string.Join(";", dependFilePath));

#if DEBUG
            #region For EndpointNotFoundException test
            try
            {
                string strWaitPeriod = ConfigurationManager.AppSettings["Test_WaitPeriodBeforeStartup"];
                if (!string.IsNullOrEmpty(strWaitPeriod))
                {
                    int waitPeriodInMilliSecond = int.Parse(strWaitPeriod);
                    Console.Error.WriteLine("Debug: waiting {0} ms before startup service", waitPeriodInMilliSecond);
                    Thread.Sleep(waitPeriodInMilliSecond);
                }
            }
            catch (Exception)
            {
                // do nothing
            }
            #endregion
#endif

            jobId = Utility.GetJobId();

            string serviceConfigFullPath;

            bool onAzure = SoaHelper.IsOnAzure();
            TraceHelper.TraceInfo(
                jobId,
                "OnAzure = {0}",
                onAzure);

            bool bOpenDummy = false;
            try
            {
                string serviceConfigFileName = Environment.GetEnvironmentVariable(Constant.ServiceConfigFileNameEnvVar);

                // exit if no such env var
                if (string.IsNullOrEmpty(serviceConfigFileName))
                {
                    bOpenDummy = true;
                    Console.Error.WriteLine(StringTable.ServiceConfigFileNameNotSpecified);
                    return(ErrorCode.ServiceHost_ServiceConfigFileNameNotSpecified);
                }

                if (onAzure)
                {
                    string localCacheFolder = Utility.GetServiceLocalCacheFullPath();
                    serviceConfigFullPath = Path.Combine(localCacheFolder, serviceConfigFileName);
                }
                else
                {
                    serviceConfigFullPath = GetServiceInfo(serviceConfigFileName);
                }

                if (!File.Exists(serviceConfigFullPath))
                {
                    bOpenDummy = true;
                    Console.Error.WriteLine(StringTable.CantFindServiceRegistrationFile, serviceConfigFullPath);
                    return(ErrorCode.ServiceHost_ServiceRegistrationFileNotFound);
                }

                TraceHelper.TraceInfo(
                    jobId,
                    "ServiceConfigFullPath = {0}",
                    serviceConfigFullPath);
                ServiceRegistration registration;
                string assemblyFullPath;
                int    errorCode = Utility.GetServiceRegistration(serviceConfigFullPath, onAzure, out registration, out assemblyFullPath);
                if (errorCode != ErrorCode.Success)
                {
                    bOpenDummy = true;
                    return(errorCode);
                }

                // Open the host in another application domain
                AppDomain domain = CreateNewServiceDomain(serviceConfigFullPath, assemblyFullPath);



                using (CcpServiceHostWrapper host =
                           CreateInstanceFromAndUnwrap <CcpServiceHostWrapper>(
                               domain,
                               Assembly.GetExecutingAssembly().Location,
                               serviceConfigFullPath,
                               onAzure,
                               ServiceHostRuntimeConfiguration.Standalone))
                {
                    host.Initialize();
                    host.Run();
                    TraceHelper.TraceInfo(
                        jobId,
                        "Sleep...");

                    if (ServiceHostRuntimeConfiguration.Standalone)
                    {
                        // Endless listening, till service info deleted.
                        while (true)
                        {
                            lock (ServiceInfo.s_lock)
                            {
                                if (SvcHostMgmtRestServer.Info == null)
                                {
                                    TraceHelper.TraceInfo(
                                        jobId,
                                        "Close service host!");
                                    host.Dispose();
                                    return(0);
                                }
                            }
                            Thread.Sleep(1000);
                        }
                    }
                    else
                    {
                        // Endless waiting, till it's being killed
                        Thread.Sleep(Timeout.Infinite);
                    }
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);

                TraceHelper.TraceError(
                    jobId,
                    e.ToString());

                // Failed to open service, fall back to open an dummy service.
                bOpenDummy = true;
            }
            finally
            {
                if (bOpenDummy)
                {
                    OpenDummyService(onAzure);
                }
            }

            return(0);
        }
Example #2
0
        /// <summary>
        ///   <para>
        /// Initializes session parameters and calls open session. Only for cluster computation.
        /// </para>
        /// </summary>
        /// <param name="headNode">
        ///   <para>Name of cluster head node</para>
        /// </param>
        /// <param name="remoteWorkbookPath">
        ///   <para>Workbook location relative to compute node</para>
        /// </param>
        /// <param name="minResources">
        ///   <para>minimum number of resources requested</para>
        /// </param>
        /// <param name="maxResources">
        ///   <para>Maximum number of resources required</para>
        /// </param>
        /// <param name="resourceType">
        ///   <para>Name of resource requested (core, node, or socket)</para>
        /// </param>
        /// <param name="jobTemplate">
        ///   <para> Name of the job template to be used </para>
        /// </param>
        /// <param name="serviceName">
        ///   <para> Name of the service to use </para>
        /// </param>
        /// <param name="jobName">
        ///   <para>Specify the job name</para>
        /// </param>
        /// <param name="projectName">
        ///   <para>Specify the project name</para>
        /// </param>
        /// <param name="transportScheme">
        ///   <para>The transport scheme (Http or NetTcp)</para>
        /// </param>
        /// <param name="useAzureQueue">
        ///   <para>Specify if Azure storage queue is used (True or False)</para>
        /// </param>
        /// <param name="username">
        ///   <para>Specify the user name</para>
        /// </param>
        /// <param name="password">
        ///   <para>Specify the password</para>
        /// </param>
        /// <param name="jobPriority">
        ///   <para>Specify the job priority</para>
        /// </param>
        /// <returns>
        ///   <para> ID of opened session </para>
        /// </returns>
        public int OpenSession(string headNode, string remoteWorkbookPath, [Optional] object minResources, [Optional] object maxResources, [Optional] object resourceType, [Optional] string jobTemplate, [Optional] string serviceName, [Optional] string jobName, [Optional] string projectName, [Optional] string transportScheme, [Optional] object useAzureQueue, [Optional] string username, [Optional] string password, [Optional] object jobPriority)
        {
            // Check if workbook path has been provided (ExcelClient initialize called)
            if (!this.initialized)
            {
                Tracing.WriteDebugTextError(Tracing.ComponentId.ExcelClient, Resources.ExcelClientOpenSessionBeforeInit);
                throw new InvalidOperationException(Resources.ExcelClientOpenSessionBeforeInit);
            }
            SessionStartInfo info;
            bool             useWebApi = false;

            if (headNode.StartsWith("d:", StringComparison.OrdinalIgnoreCase))
            {
                // HACK: using head node string to pass actual parameters
                var      param = headNode.Split('?');
                string   serviceRegDirectory = null;
                string[] computeNodeIpList   = null;
                string   storageCredential   = null;
                string[] dependFiles         = null;

                bool CheckParameterSwitch(string parameter, string switchStr)
                {
                    return(parameter.StartsWith(switchStr, StringComparison.OrdinalIgnoreCase));
                }

                foreach (var p in param)
                {
                    if (CheckParameterSwitch(p, "d:"))
                    {
                        serviceRegDirectory = p.Substring(p.IndexOf(":") + 1);
                    }
                    else if (CheckParameterSwitch(p, "c:"))
                    {
                        computeNodeIpList = p.Substring(p.IndexOf(":") + 1).Split(',');
                    }
                    else if (CheckParameterSwitch(p, "s:"))
                    {
                        storageCredential = p.Substring(p.IndexOf(":") + 1);
                    }
                    else if (CheckParameterSwitch(p, "f:"))
                    {
                        dependFiles = p.Substring(p.IndexOf(":") + 1).Split(',');
                    }
                }

                if (serviceRegDirectory == null || computeNodeIpList == null)
                {
                    throw new ArgumentNullException();
                }


                // Standalone mode
                if (string.IsNullOrEmpty(serviceName))
                {
                    info = new SessionStartInfo(Microsoft.Hpc.Excel.ExcelClient.SERVICE, serviceRegDirectory, null, computeNodeIpList);
                }
                else
                {
                    info = new SessionStartInfo(serviceName, serviceRegDirectory, null, computeNodeIpList);
                }

                if (dependFiles != null && dependFiles.Any())
                {
                    // Start data client related logic
                    // TODO: move logic into ExcelClient
                    try
                    {
                        if (string.IsNullOrEmpty(storageCredential))
                        {
                            throw new ArgumentNullException(nameof(storageCredential));
                        }

                        StandaloneDataClient dataClient = new StandaloneDataClient(storageCredential);
                        var sasTokens = dataClient.UploadFilesAsync(dependFiles).GetAwaiter().GetResult();

                        if (sasTokens.Length != dependFiles.Length)
                        {
                            throw new InvalidOperationException($"Number of sas token ({sasTokens.Length}) does not equal to depend files ({dependFiles.Length})");
                        }

                        var depFileInfo = new Dictionary <string, string>();
                        for (int i = 0; i != sasTokens.Length; ++i)
                        {
                            depFileInfo[Path.GetFileName(dependFiles[i])] = sasTokens[i];
                        }

                        info.DependFilesStorageInfo = depFileInfo;
                        remoteWorkbookPath          = Path.GetFileName(remoteWorkbookPath);
                    }
                    catch (Exception ex)
                    {
                        Tracing.SoaTrace(
                            XlTraceLevel.Error, "error when uploading files {0}", ex.ToString());
                        throw;
                    }

                    // End data client related logic
                }

                info.UseInprocessBroker = true;
                info.IsNoSession        = true;
            }
            else
            {
                // If https prefix from head node name
                useWebApi = Microsoft.Hpc.Excel.ExcelClient.TryRemoveWebApiPrefix(ref headNode);

                // If the service name is provided, use it rather than the default in ExcelClient
                if (string.IsNullOrEmpty(serviceName))
                {
                    info = new SessionStartInfo(headNode, Microsoft.Hpc.Excel.ExcelClient.SERVICE);
                }
                else
                {
                    info = new SessionStartInfo(headNode, serviceName);
                }
            }

            if (useWebApi)
            {
                info.TransportScheme = TransportScheme.WebAPI;
            }

            if (!string.IsNullOrEmpty(transportScheme))
            {
                if (transportScheme.Equals("Http", StringComparison.InvariantCultureIgnoreCase))
                {
                    info.TransportScheme = TransportScheme.Http;
                }
                else if (transportScheme.Equals("NetTcp", StringComparison.InvariantCultureIgnoreCase))
                {
                    info.TransportScheme = TransportScheme.NetTcp;
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidTransportScheme, transportScheme), "transportScheme");
                }
            }

            if (!(useAzureQueue == null || System.Reflection.Missing.Value.Equals(useAzureQueue) || DBNull.Value.Equals(useAzureQueue)))
            {
                bool useAQ;
                if (bool.TryParse(useAzureQueue.ToString(), out useAQ))
                {
                    info.UseAzureQueue = useAQ;
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidBoolParamValue, "useAzureQueue", useAzureQueue), "useAzureQueue");
                }
            }

            if (!string.IsNullOrEmpty(username))
            {
                info.Username = username;
            }

            if (!string.IsNullOrEmpty(password))
            {
                info.Password = password;
            }

            if (!string.IsNullOrEmpty(jobName))
            {
                info.ServiceJobName = jobName;
            }

            if (!string.IsNullOrEmpty(projectName))
            {
                info.Project = projectName;
            }

            // If jobPriority is specified, try to parse it into an integer.
            if (!(jobPriority == null || System.Reflection.Missing.Value.Equals(jobPriority) || DBNull.Value.Equals(jobPriority)))
            {
                int priority;
                if (int.TryParse(jobPriority.ToString(), out priority))
                {
                    info.SessionPriority = priority;
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidMinCores, jobPriority), "minResources");
                }
            }

            // If minResources is specified, try to parse it into an integer.
            if (!(minResources == null || System.Reflection.Missing.Value.Equals(minResources) || DBNull.Value.Equals(minResources)))
            {
                int minUnits;
                if (int.TryParse(minResources.ToString(), out minUnits))
                {
                    info.MinimumUnits = minUnits;
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidMinCores, minResources), "minResources");
                }
            }

            // If maxResources is specified, try to parse it into an integer
            if (!(maxResources == null || System.Reflection.Missing.Value.Equals(maxResources) || DBNull.Value.Equals(maxResources)))
            {
                int maxUnits;
                if (int.TryParse(maxResources.ToString(), out maxUnits))
                {
                    info.MaximumUnits = maxUnits;
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidMaxCores, maxResources), "maxResources");
                }
            }

            // If job template is specified, set it
            if (!string.IsNullOrEmpty(jobTemplate))
            {
                info.JobTemplate = jobTemplate;
            }

            // Set resource type (defaults to core)
            if (!(resourceType == null || System.Reflection.Missing.Value.Equals(resourceType) || DBNull.Value.Equals(resourceType)))
            {
                int resIndex;
                if (int.TryParse(resourceType.ToString(), out resIndex))
                {
                    info.SessionResourceUnitType = ResourceToSessionUnitType((Microsoft.Hpc.Excel.Com.SessionUnitType)resIndex);
                }
                else
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.ExcelClient_InvalidResType, resourceType), "resourceType");
                }
            }

            // Set interface mode to UI to ensure that Excel asks for credentials in the UI when not cached
            SessionBase.SetInterfaceMode(false, new IntPtr(this.client.Driver.App.Hwnd));

            return(this.client.OpenSession(info, remoteWorkbookPath));
        }