Exemplo n.º 1
0
        /// <summary>
        /// Deploy fast-cgi settings
        /// </summary>
        protected void DeployFasctCgi()
        {
            var limits = this.Deployment.GetApplicationLimits();

            using (ServerManager serverManager = new ServerManager())
            {
                this.Logger.LogWarning(false, "Deploying fastCgi based applications causes IIS to internally reset to pick the new configuration because fastCgi is configured at the server level.");

                var phpRuntime  = this.GetFastCgiExe();
                var iniFilePath = this.GetIniFilePath();
                var phpIniFile  = this.GetIniFilePath();

                string siteAlias = this.Deployment.getShortId();

                // fastCgi settings in IIS can only be set at the HOSTS level
                // we found no way to set this at a web.config level.
                Microsoft.Web.Administration.Configuration config = serverManager.GetApplicationHostConfiguration();
                ConfigurationSection section = config.GetSection("system.webServer/fastCgi");
                ConfigurationElement cfs     = null;

                // Each fastCgi in IIS is a unique combination of RUNTIME_PATH|ARGUMENTS, try to find
                // the current application.
                foreach (ConfigurationElement sec in section.GetCollection())
                {
                    // Cada aplicación se identifica de manera única por la combincación de atributo y path de ejecución.
                    if (sec.HasValue("arguments", siteAlias) && sec.HasValue("fullPath", phpRuntime))
                    {
                        cfs = sec;
                        break;
                    }
                }

                // We need to keep track if the element already existed
                // in the configuration, or it is new.
                bool addApplication = false;
                ConfigurationElementCollection elems = section.GetCollection();
                if (cfs == null)
                {
                    cfs            = elems.CreateElement("application");
                    addApplication = true;
                }

                // In this deployment we are not really passing
                // any argments to PHP, simply use the site Alias to
                // isolate each PHP site.
                // OJO: PONER EL SITE ALIAS AQUÍ NO ES ALGO
                // GRATUITO. LUEGO EN EL WEB.CONFIG DE LA PROPIA
                // APLICACIÓN DEBE ESTAR EXACTAMENTE IGUAL.
                cfs.SetAttributeValue("arguments", siteAlias);

                // Set reasonable defaults, even if the user configuration says differently
                var instanceMaxRequests = this.PhpSettings.instanceMaxRequests > 200 ? this.PhpSettings.instanceMaxRequests : 10000;
                var maxInstances        = this.PhpSettings.maxInstances > 3 ? this.PhpSettings.maxInstances : 10;
                var activityTimeout     = this.PhpSettings.activityTimeout > 100 ? this.PhpSettings.activityTimeout : 600;
                var requestTimeout      = this.PhpSettings.requestTimeout > 60 ? this.PhpSettings.requestTimeout : 300;

                // Ensure that all values are within the limits
                if (maxInstances > limits.FastCgiMaxInstances && limits.FastCgiMaxInstances > 0)
                {
                    maxInstances = limits.FastCgiMaxInstances.Value;
                }

                // Runtime Path.
                cfs.SetAttributeValue("fullPath", phpRuntime);
                cfs.SetAttributeValue("maxInstances", maxInstances);
                cfs.SetAttributeValue("activityTimeout", activityTimeout);
                cfs.SetAttributeValue("requestTimeout", requestTimeout);
                cfs.SetAttributeValue("instanceMaxRequests", instanceMaxRequests);

                // Make sure that changes to PHP.ini are refreshed properly
                if (File.Exists(iniFilePath))
                {
                    cfs.SetAttributeValue("monitorChangesTo", iniFilePath);
                }

                // Este setting no sirve para nada según -E- de MS porque
                // la implementación de FastCGI está mal hecha en IIS.
                // Los eventos internos de señal no se llegan a ejecutar nunca,
                // lo único que consigues es demorar el cierre de instancias.
                cfs.SetAttributeValue("signalBeforeTerminateSeconds", 0);

                if (!File.Exists(phpIniFile))
                {
                    throw new Exception("PHP.ini file not found. This will break the IIS FastCgiModule when using monitorChangesTo feature.");
                }

                // Retrieve the environment variables.
                ConfigurationElement           cfgEnvironment = cfs.GetChildElement("environmentVariables");
                ConfigurationElementCollection a = cfgEnvironment.GetCollection();

                // This is fastcgi specific.
                a.AddOrUpdateConfigurationElementInCollection("PHP_FCGI_MAX_REQUESTS", instanceMaxRequests.ToString());

                // Add all the environment variables.
                var environmentVariables = this.GetEnvironmentVariables();
                foreach (var p in environmentVariables)
                {
                    a.AddOrUpdateConfigurationElementInCollection(p.Key, p.Value);
                }

                if (addApplication)
                {
                    elems.Add(cfs);
                }

                // Cleanup any fastCgi applications that point to non-existent handlers
                // see the comments in FastCgiRemove() as to why this is here.
                var fastCgiHandlers = section.GetCollection();
                foreach (ConfigurationElement sec in fastCgiHandlers.ToList())
                {
                    if (sec.RawAttributes.Keys.Contains("fullPath"))
                    {
                        string fullPath = sec.GetAttributeValue("fullPath").ToString();
                        if (!File.Exists(fullPath))
                        {
                            this.Logger.LogInfo(true, "Removed stale fastCgi handler {0}", fullPath);
                            fastCgiHandlers.Remove(sec);
                        }
                    }
                }

                UtilsIis.CommitChanges(serverManager);
            }
        }