Example #1
0
        public void TC001_ConfigureApplicationTest()
        {
            //Arrange
            IISPlugin target = new IISPlugin();
            ApplicationVariable[] appVariables = new ApplicationVariable[] {
              new ApplicationVariable() { Name = "VCAP_PLUGIN_STAGING_INFO", Value=@"{""assembly"":""Uhuru.CloudFoundry.DEA.Plugins.dll"",""class_name"":""Uhuru.CloudFoundry.DEA.Plugins.IISPlugin"",""logs"":{""app_error"":""logs/stderr.log"",""dea_error"":""logs/err.log"",""startup"":""logs/startup.log"",""app"":""logs/stdout.log""},""auto_wire_templates"":{""mssql-2008"":""Data Source={host},{port};Initial Catalog={name};User Id={user};Password={password};MultipleActiveResultSets=true"",""mysql-5.1"":""server={host};port={port};Database={name};Uid={user};Pwd={password};""}}" },
              new ApplicationVariable() { Name = "VCAP_APPLICATION", Value=@"{""instance_id"":""646c477f54386d8afb279ec2f990a823"",""instance_index"":0,""name"":""sinatra_env_test_app"",""uris"":[""sinatra_env_test_app.uhurucloud.net""],""users"":[""*****@*****.**""],""version"":""c394f661a907710b8a8bb70b84ff0c83354dbbed-1"",""start"":""2011-12-07 14:40:12 +0200"",""runtime"":""iis"",""state_timestamp"":1323261612,""port"":51202,""limits"":{""fds"":256,""mem"":67108864,""disk"":2147483648},""host"":""192.168.1.117""}" },
              new ApplicationVariable() { Name = "VCAP_SERVICES", Value=@"{""mssql-2008"":[{""name"":""mssql-b24a2"",""label"":""mssql-2008"",""plan"":""free"",""tags"":[""mssql"",""2008"",""relational""],""credentials"":{""name"":""D4Tac4c307851cfe495bb829235cd384f094"",""username"":""US3RTfqu78UpPM5X"",""user"":""US3RTfqu78UpPM5X"",""password"":""P4SSdCGxh2gYjw54"",""hostname"":""192.168.1.3"",""port"":1433,""bind_opts"":{}}}]}" },
              new ApplicationVariable() { Name = "VCAP_APP_HOST", Value=@"192.168.1.118" },
              new ApplicationVariable() { Name = "VCAP_APP_PORT", Value=@"65498" },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER_PASSWORD", Value = password },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER", Value = user },
              new ApplicationVariable() { Name = "HOME", Value=TestUtil.CopyFolderToTemp(testAppLoc) }
            };

            Exception exception = null;

            //Act
            try
            {
                target.ConfigureApplication(appVariables);
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            //Assert
            Assert.IsNull(exception, "Exception thrown");
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ApplicationParsedData"/> class.
 /// </summary>
 /// <param name="appInfo">The app info.</param>
 /// <param name="runtime">The runtime.</param>
 /// <param name="variables">The variables.</param>
 /// <param name="services">The services.</param>
 /// <param name="urls">The URLs.</param>
 /// <param name="logFilePath">The log file path.</param>
 /// <param name="errorLogFilePath">The error log file path.</param>
 /// <param name="startupLogFilePath">The startup log file path.</param>
 /// <param name="autoWireTemplates">A list of connection string templates for services.</param>
 public ApplicationParsedData(
     ApplicationInfo appInfo, 
     string runtime, 
     ApplicationVariable[] variables, 
     ApplicationService[] services,
     string[] urls,
     string logFilePath, 
     string errorLogFilePath, 
     string startupLogFilePath, 
     Dictionary<string, string> autoWireTemplates)
 {
     this.appInfo = appInfo;
     this.runtime = runtime;
     this.variables = variables;
     this.services = services;
     this.logFilePath = logFilePath;
     this.errorLogFilePath = errorLogFilePath;
     this.startupLogFilePath = startupLogFilePath;
     this.autoWireTemplates = autoWireTemplates;
     this.appUrls = urls;
 }
 public void GetParsedDataTest()
 {
     ApplicationVariable[] appVariables = new ApplicationVariable[] {
       new ApplicationVariable() { Name = "VCAP_PLUGIN_STAGING_INFO", Value=@"{""assembly"":""Uhuru.CloudFoundry.DEA.Plugins.dll"",""class_name"":""Uhuru.CloudFoundry.DEA.Plugins.IISPlugin"",""logs"":{""app_error"":""logs/stderr.log"",""dea_error"":""logs/err.log"",""startup"":""logs/startup.log"",""app"":""logs/stdout.log""},""auto_wire_templates"":{""mssql-2008"":""Data Source={host},{port};Initial Catalog={name};User Id={user};Password={password};MultipleActiveResultSets=true"",""mysql-5.1"":""server={host};port={port};Database={name};Uid={user};Pwd={password};""}}" },
       new ApplicationVariable() { Name = "VCAP_APPLICATION", Value=@"{""instance_id"":""646c477f54386d8afb279ec2f990a823"",""instance_index"":0,""name"":""sinatra_env_test_app"",""uris"":[""sinatra_env_test_app.uhurucloud.net""],""users"":[""*****@*****.**""],""version"":""c394f661a907710b8a8bb70b84ff0c83354dbbed-1"",""start"":""2011-12-07 14:40:12 +0200"",""runtime"":""iis"",""state_timestamp"":1323261612,""port"":51202,""limits"":{""fds"":256,""mem"":67108864,""disk"":2147483648},""host"":""192.168.1.117""}" },
       new ApplicationVariable() { Name = "VCAP_SERVICES", Value=@"{""mssql-2008"":[{""name"":""mssql-b24a2"",""label"":""mssql-2008"",""plan"":""free"",""tags"":[""mssql"",""2008"",""relational""],""credentials"":{""name"":""D4Tac4c307851cfe495bb829235cd384f094"",""username"":""US3RTfqu78UpPM5X"",""user"":""US3RTfqu78UpPM5X"",""password"":""P4SSdCGxh2gYjw54"",""hostname"":""192.168.1.3"",""port"":1433,""bind_opts"":{}}}]}" },
       new ApplicationVariable() { Name = "VCAP_APP_HOST", Value=@"192.168.1.118" },
       new ApplicationVariable() { Name = "VCAP_APP_PORT", Value=@"65498" },
       new ApplicationVariable() { Name = "VCAP_WINDOWS_USER_PASSWORD", Value=@"password" },
       new ApplicationVariable() { Name = "VCAP_WINDOWS_USER", Value=@"cfuser" },
       new ApplicationVariable() { Name = "HOME", Value=@"c:\droplets\mydroplet" }
     };
     ApplicationParsedData actual;
     actual = PluginHelper.GetParsedData(appVariables);
     Assert.AreEqual("646c477f54386d8afb279ec2f990a823", actual.AppInfo.InstanceId);
     Assert.AreEqual("192.168.1.118", actual.AppInfo.LocalIP);
     Assert.AreEqual("sinatra_env_test_app", actual.AppInfo.Name);
     Assert.AreEqual(@"c:\droplets\mydroplet\app", actual.AppInfo.Path);
     Assert.AreEqual(65498, actual.AppInfo.Port);
     Assert.AreEqual("cfuser", actual.AppInfo.WindowsUserName);
     Assert.AreEqual("password", actual.AppInfo.WindowsPassword);
     Assert.AreEqual(2, actual.AutoWireTemplates.Count);
     Assert.AreEqual(@"c:\droplets\mydroplet\logs/stderr.log", actual.ErrorLogFilePath);
     Assert.AreEqual(@"c:\droplets\mydroplet\logs/stdout.log", actual.LogFilePath);
     Assert.AreEqual("iis", actual.Runtime);
     Assert.AreEqual("192.168.1.3", actual.GetServices()[0].Host);
     Assert.AreEqual("D4Tac4c307851cfe495bb829235cd384f094", actual.GetServices()[0].InstanceName);
     Assert.AreEqual("mssql-b24a2", actual.GetServices()[0].Name);
     Assert.AreEqual("P4SSdCGxh2gYjw54", actual.GetServices()[0].Password);
     Assert.AreEqual("free", actual.GetServices()[0].Plan);
     Assert.AreEqual(1433, actual.GetServices()[0].Port);
     Assert.AreEqual("mssql-2008", actual.GetServices()[0].ServiceLabel);
     Assert.AreEqual(3, actual.GetServices()[0].GetServiceTags().Length);
     Assert.AreEqual("US3RTfqu78UpPM5X", actual.GetServices()[0].User);
     Assert.AreEqual(@"c:\droplets\mydroplet\logs/startup.log", actual.StartupLogFilePath);
 }
        /// <summary>
        /// sets the initial data for an application
        /// </summary>
        /// <param name="variables">All variables needed to run the application.</param>
        public void ConfigureApplication(ApplicationVariable[] variables)
        {
            try
            {
                ApplicationParsedData parsedData = PluginHelper.GetParsedData(variables);
                this.startupLogger = new FileLogger(parsedData.StartupLogFilePath);

                this.appName = RemoveSpecialCharacters(parsedData.AppInfo.Name) + parsedData.AppInfo.Port.ToString(CultureInfo.InvariantCulture);
                this.appPath = parsedData.AppInfo.Path;

                this.applicationInfo = parsedData.AppInfo;

                this.autoWireTemplates = parsedData.AutoWireTemplates;

                this.aspDotNetVersion = this.GetAppVersion(this.applicationInfo);

                this.cpuTarget = this.GetCpuTarget(this.applicationInfo);

                this.AutowireApp(parsedData.AppInfo, variables, parsedData.GetServices(), parsedData.LogFilePath, parsedData.ErrorLogFilePath);
            }
            catch (Exception ex)
            {
                this.startupLogger.Error(ex.ToString());
                throw;
            }
        }
        /// <summary>
        /// Auto-wires the application variables and the log file path in the web.config file.
        /// </summary>
        /// <param name="configPath">The config file path.</param>
        /// <param name="variables">The variables.</param>
        /// <param name="logFilePath">The log file path.</param>
        /// <param name="errorLogFilePath">The error log file path.</param>
        private void SetApplicationVariables(string configPath, ApplicationVariable[] variables, string logFilePath, string errorLogFilePath)
        {
            this.startupLogger.Info(Strings.SettingUpApplicationVariables);

            var configFile = new FileInfo(configPath);
            var vdm = new System.Web.Configuration.VirtualDirectoryMapping(configFile.DirectoryName, true, configFile.Name);
            var wcfm = new System.Web.Configuration.WebConfigurationFileMap();
            wcfm.VirtualDirectories.Add("/", vdm);
            System.Configuration.Configuration webConfig = System.Web.Configuration.WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");

            bool hasUhuruLogFile = false;
            bool hasUhuruErrorLogFile = false;

            foreach (ApplicationVariable var in variables)
            {
                if (var.Name == "UHURU_LOG_FILE")
                {
                    hasUhuruLogFile = true;
                }

                if (var.Name == "UHURU_ERROR_LOG_FILE")
                {
                    hasUhuruErrorLogFile = true;
                }

                if (webConfig.AppSettings.Settings[var.Name] == null)
                {
                    webConfig.AppSettings.Settings.Add(var.Name, var.Value);
                }
                else
                {
                    webConfig.AppSettings.Settings[var.Name].Value = var.Value;
                }
            }

            if (!hasUhuruLogFile)
            {
                if (webConfig.AppSettings.Settings["UHURU_LOG_FILE"] == null)
                {
                    webConfig.AppSettings.Settings.Add("UHURU_LOG_FILE", logFilePath);
                }
                else
                {
                    webConfig.AppSettings.Settings["UHURU_LOG_FILE"].Value = logFilePath;
                }
            }

            if (!hasUhuruErrorLogFile)
            {
                if (webConfig.AppSettings.Settings["UHURU_ERROR_LOG_FILE"] == null)
                {
                    webConfig.AppSettings.Settings.Add("UHURU_ERROR_LOG_FILE", errorLogFilePath);
                }
                else
                {
                    webConfig.AppSettings.Settings["UHURU_ERROR_LOG_FILE"].Value = errorLogFilePath;
                }
            }

            this.startupLogger.Info(Strings.DoneSettingUpApplication);

            webConfig.Save();
        }
        /// <summary>
        /// Autowires the service connections and ASP.NET health monitoring in the application's web.config
        /// </summary>
        /// <param name="appInfo">The application info structure.</param>
        /// <param name="variables">All application variables.</param>
        /// <param name="services">The services.</param>
        /// <param name="logFilePath">The ASP.NET "Heartbeat" and "Lifetime Events" log file path.</param>
        /// <param name="errorLogFilePath">The ASP.NET "All Errors" events log file path.</param>
        private void AutowireApp(ApplicationInfo appInfo, ApplicationVariable[] variables, ApplicationService[] services, string logFilePath, string errorLogFilePath)
        {
            this.startupLogger.Info(Strings.StartingApplicationAutoWiring);

            List<ApplicationVariable> varList = variables.ToList<ApplicationVariable>();
            ApplicationVariable applicationVariable = new ApplicationVariable();
            applicationVariable.Name = "TUNNEL_NET_TCP_PORT";
            applicationVariable.Value = NetworkInterface.GrabEphemeralPort().ToString(CultureInfo.InvariantCulture);
            varList.Add(applicationVariable);
            variables = varList.ToArray();

            // get all config files
            string[] allConfigFiles = Directory.GetFiles(appInfo.Path, "*.config", SearchOption.AllDirectories);

            foreach (string configFile in allConfigFiles)
            {
                if (File.Exists(configFile))
                {
                    string configFileContents = File.ReadAllText(configFile);

                    if (services != null)
                    {
                        Dictionary<string, string> connections = new Dictionary<string, string>();
                        Dictionary<string, string> connValues = new Dictionary<string, string>();

                        foreach (ApplicationService service in services)
                        {
                            string key = service.ServiceLabel;
                            string template = string.Empty;

                            if (this.autoWireTemplates.TryGetValue(key, out template))
                            {
                                template = template.Replace(Strings.Host, service.Host);
                                template = template.Replace(Strings.Port, service.Port.ToString(CultureInfo.InvariantCulture));
                                template = template.Replace(Strings.Name, service.InstanceName);
                                template = template.Replace(Strings.User, service.User);
                                template = template.Replace(Strings.Password, service.Password);

                                connections[string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", key, service.Name)] = template;
                            }

                            char[] charsToTrim = { '{', '}' };
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.User.Trim(charsToTrim)), service.User);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Host.Trim(charsToTrim)), service.Host);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Port.Trim(charsToTrim)), service.Port.ToString(CultureInfo.InvariantCulture));
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Password.Trim(charsToTrim)), service.Password);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Name.Trim(charsToTrim)), service.InstanceName);
                        }

                        foreach (string con in connections.Keys)
                        {
                            this.startupLogger.Info(Strings.ConfiguringService + con);
                            configFileContents = configFileContents.Replace(con, connections[con]);
                        }

                        foreach (string key in connValues.Keys)
                        {
                            this.startupLogger.Info(string.Format(CultureInfo.InvariantCulture, Strings.ConfiguringServiceValue, key));
                            configFileContents = configFileContents.Replace(key, connValues[key]);
                        }
                    }

                    File.WriteAllText(configFile, configFileContents);
                }
            }

            string webConfigFile = Path.Combine(appInfo.Path, "web.config");
            if (File.Exists(webConfigFile))
            {
                this.SetApplicationVariables(webConfigFile, variables, logFilePath, errorLogFilePath);

                this.startupLogger.Info(Strings.SavedConfigurationFile);

                this.startupLogger.Info(Strings.SettingUpLogging);

                string appDir = Path.GetDirectoryName(webConfigFile);
                string binDir = Path.Combine(appDir, "bin");
                string assemblyFile = typeof(LogFileWebEventProvider).Assembly.Location;
                string destinationAssemblyFile = Path.Combine(binDir, Path.GetFileName(assemblyFile));

                Directory.CreateDirectory(binDir);

                File.Copy(assemblyFile, destinationAssemblyFile, true);

                this.startupLogger.Info(Strings.CopiedLoggingBinariesToBin);

                SiteConfig siteConfiguration = new SiteConfig(appDir, true);
                HealthMonRewire healthMon = new HealthMonRewire();
                healthMon.Register(siteConfiguration);

                siteConfiguration.Rewire(false);
                siteConfiguration.CommitChanges();

                this.startupLogger.Info(Strings.UpdatedLoggingConfiguration);

                DirectoryInfo errorLogDir = new DirectoryInfo(Path.GetDirectoryName(errorLogFilePath));
                DirectoryInfo logDir = new DirectoryInfo(Path.GetDirectoryName(logFilePath));

                DirectorySecurity errorLogDirSecurity = errorLogDir.GetAccessControl();
                DirectorySecurity logDirSecurity = logDir.GetAccessControl();

                errorLogDirSecurity.SetAccessRule(
                    new FileSystemAccessRule(
                        appInfo.WindowsUserName,
                        FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.CreateFiles,
                        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                        PropagationFlags.None,
                        AccessControlType.Allow));

                logDirSecurity.SetAccessRule(
                    new FileSystemAccessRule(
                        appInfo.WindowsUserName,
                        FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.CreateFiles,
                        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                        PropagationFlags.None,
                        AccessControlType.Allow));

                errorLogDir.SetAccessControl(errorLogDirSecurity);
                logDir.SetAccessControl(logDirSecurity);
            }
        }
 /// <summary>
 /// recovers a running application
 /// </summary>
 /// <param name="variables">All variables needed to run the application.</param>
 public void RecoverApplication(ApplicationVariable[] variables)
 {
     try
     {
         ApplicationParsedData parsedData = PluginHelper.GetParsedData(variables);
         this.startupLogger = new FileLogger(parsedData.StartupLogFilePath);
         this.appName = RemoveSpecialCharacters(parsedData.AppInfo.Name) + parsedData.AppInfo.Port.ToString(CultureInfo.InvariantCulture);
         this.appPath = parsedData.AppInfo.Path;
         this.applicationInfo = parsedData.AppInfo;
         this.autoWireTemplates = parsedData.AutoWireTemplates;
     }
     catch (Exception ex)
     {
         this.startupLogger.Error(ex.ToString());
         throw;
     }
 }
Example #8
0
        public void TC002_StartWebAppTest()
        {
            //Arrange
            IISPlugin target = new IISPlugin();

            int port = Uhuru.Utilities.NetworkInterface.GrabEphemeralPort();

            ApplicationVariable[] appVariables = new ApplicationVariable[] {
              new ApplicationVariable() { Name = "VCAP_PLUGIN_STAGING_INFO", Value=@"{""assembly"":""Uhuru.CloudFoundry.DEA.Plugins.dll"",""class_name"":""Uhuru.CloudFoundry.DEA.Plugins.IISPlugin"",""logs"":{""app_error"":""logs/stderr.log"",""dea_error"":""logs/err.log"",""startup"":""logs/startup.log"",""app"":""logs/stdout.log""},""auto_wire_templates"":{""mssql-2008"":""Data Source={host},{port};Initial Catalog={name};User Id={user};Password={password};MultipleActiveResultSets=true"",""mysql-5.1"":""server={host};port={port};Database={name};Uid={user};Pwd={password};""}}" },
              new ApplicationVariable() { Name = "VCAP_APPLICATION", Value=@"{""instance_id"":""" + Guid.NewGuid().ToString() + @""",""instance_index"":0,""name"":""MyTestApp"",""uris"":[""sinatra_env_test_app.uhurucloud.net""],""users"":[""*****@*****.**""],""version"":""c394f661a907710b8a8bb70b84ff0c83354dbbed-1"",""start"":""2011-12-07 14:40:12 +0200"",""runtime"":""iis"",""state_timestamp"":1323261612,""port"":51202,""limits"":{""fds"":256,""mem"":67108864,""disk"":2147483648},""host"":""192.168.1.117""}" },
              new ApplicationVariable() { Name = "VCAP_SERVICES", Value=@"{""mssql-2008"":[{""name"":""mssql-b24a2"",""label"":""mssql-2008"",""plan"":""free"",""tags"":[""mssql"",""2008"",""relational""],""credentials"":{""name"":""D4Tac4c307851cfe495bb829235cd384f094"",""username"":""US3RTfqu78UpPM5X"",""user"":""US3RTfqu78UpPM5X"",""password"":""P4SSdCGxh2gYjw54"",""hostname"":""192.168.1.3"",""port"":1433,""bind_opts"":{}}}]}" },
              new ApplicationVariable() { Name = "VCAP_APP_HOST", Value=TestUtil.GetLocalIp() },
              new ApplicationVariable() { Name = "VCAP_APP_PORT", Value = port.ToString() },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER_PASSWORD", Value = password },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER", Value = user },
              new ApplicationVariable() { Name = "HOME", Value=TestUtil.CopyFolderToTemp(testAppLoc) }
            };

            //Act
            target.ConfigureApplication(appVariables);
            target.StartApplication();

            //Assert
            WebClient client = new WebClient();
            string html = client.DownloadString("http://localhost:" + port.ToString());
            Assert.IsTrue(html.Contains("My ASP.NET Application"));

            target.StopApplication();

            try
            {
                html = client.DownloadString("http://localhost:" + port.ToString());
            }
            catch
            {
                return;
            }
            Assert.Fail();
        }
Example #9
0
        public void TC003_MultipleWebApps()
        {
            List<ApplicationVariable[]> appInfos = new List<ApplicationVariable[]>();
            List<IISPlugin> plugins = new List<IISPlugin>();
            List<Thread> threadsStart = new List<Thread>();
            List<Thread> threadsStop = new List<Thread>();

            for (int i = 0; i < 20; i++)
            {
                int port = Uhuru.Utilities.NetworkInterface.GrabEphemeralPort();
                ApplicationVariable[] appInfo = new ApplicationVariable[] {
              new ApplicationVariable() { Name = "VCAP_PLUGIN_STAGING_INFO", Value=@"{""assembly"":""Uhuru.CloudFoundry.DEA.Plugins.dll"",""class_name"":""Uhuru.CloudFoundry.DEA.Plugins.IISPlugin"",""logs"":{""app_error"":""logs/stderr.log"",""dea_error"":""logs/err.log"",""startup"":""logs/startup.log"",""app"":""logs/stdout.log""},""auto_wire_templates"":{""mssql-2008"":""Data Source={host},{port};Initial Catalog={name};User Id={user};Password={password};MultipleActiveResultSets=true"",""mysql-5.1"":""server={host};port={port};Database={name};Uid={user};Pwd={password};""}}" },
              new ApplicationVariable() { Name = "VCAP_APPLICATION", Value=@"{""instance_id"":""" + Guid.NewGuid().ToString() + @""",""instance_index"":0,""name"":""MyTestApp"",""uris"":[""sinatra_env_test_app.uhurucloud.net""],""users"":[""*****@*****.**""],""version"":""c394f661a907710b8a8bb70b84ff0c83354dbbed-1"",""start"":""2011-12-07 14:40:12 +0200"",""runtime"":""iis"",""state_timestamp"":1323261612,""port"":51202,""limits"":{""fds"":256,""mem"":67108864,""disk"":2147483648},""host"":""192.168.1.117""}" },
              new ApplicationVariable() { Name = "VCAP_SERVICES", Value=@"{""mssql-2008"":[{""name"":""mssql-b24a2"",""label"":""mssql-2008"",""plan"":""free"",""tags"":[""mssql"",""2008"",""relational""],""credentials"":{""name"":""D4Tac4c307851cfe495bb829235cd384f094"",""username"":""US3RTfqu78UpPM5X"",""user"":""US3RTfqu78UpPM5X"",""password"":""P4SSdCGxh2gYjw54"",""hostname"":""192.168.1.3"",""port"":1433,""bind_opts"":{}}}]}" },
              new ApplicationVariable() { Name = "VCAP_APP_HOST", Value=TestUtil.GetLocalIp() },
              new ApplicationVariable() { Name = "VCAP_APP_PORT", Value = port.ToString() },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER_PASSWORD", Value = password },
              new ApplicationVariable() { Name = "VCAP_WINDOWS_USER", Value = user },
              new ApplicationVariable() { Name = "HOME", Value=TestUtil.CopyFolderToTemp(testAppLoc) }
            };

                appInfos.Add(appInfo);
                plugins.Add(new IISPlugin());
            }

            for (int i = 0; i < 20; i++)
            {
                threadsStart.Add(new Thread(new ParameterizedThreadStart(delegate(object data)
                {
                    try
                    {
                        IISPlugin target = plugins[(int)data];

                        target.ConfigureApplication(appInfos[(int)data]);
                        target.StartApplication();
                    }
                    catch (Exception ex)
                    {
                        Logger.Fatal(ex.ToString());
                    }
                })));
            }

            for (int i = 0; i < threadsStart.Count; i++)
            {
                Thread thread = threadsStart[i];
                thread.Start(i);
            }

            foreach (Thread thread in threadsStart)
            {
                thread.Join();
            }

            foreach (ApplicationVariable[] appInfo in appInfos)
            {
                WebClient client = new WebClient();
                string html = client.DownloadString("http://localhost:" + appInfo.First(v => v.Name == "VCAP_APP_PORT").Value);
                Assert.IsTrue(html.Contains("My ASP.NET Application"));
            }

            for (int i = 0; i < 20; i++)
            {
                threadsStop.Add(new Thread(new ParameterizedThreadStart(delegate(object data)
                {
                    try
                    {
                        IISPlugin target = plugins[(int)data];
                        target.StopApplication();
                    }
                    catch (Exception ex)
                    {
                        Logger.Fatal(ex.ToString());
                    }
                })));
            }

            for (int i = 0; i < threadsStop.Count; i++)
            {
                Thread thread = threadsStop[i];
                thread.Start(i);
            }

            foreach (Thread thread in threadsStop)
            {
                thread.Join();
            }

            foreach (ApplicationVariable[] appInfo in appInfos)
            {
                try
                {
                    WebClient client = new WebClient();
                    string html = client.DownloadString("http://localhost:" + appInfo.First(v => v.Name == "VCAP_APP_PORT").Value);
                    Assert.Fail();
                }
                catch
                {
                }
            }
        }
Example #10
0
        /// <summary>
        /// Gets the parsed data for an application.
        /// </summary>
        /// <param name="appVariables">The unstructured app variables.</param>
        /// <returns>An ApplicationParsedData object, that contains structured information about the application.</returns>
        public static ApplicationParsedData GetParsedData(ApplicationVariable[] appVariables)
        {
            if (appVariables == null)
            {
                throw new ArgumentNullException("appVariables");
            }

            Dictionary<string, string> variablesHash = new Dictionary<string, string>(appVariables.Length);

            foreach (ApplicationVariable variable in appVariables)
            {
                variablesHash[variable.Name] = variable.Value;
            }

            ApplicationVariable[] variables = appVariables;

            ApplicationInfo appInfo = new ApplicationInfo();

            VcapApplication vcapApplication = new VcapApplication();
            vcapApplication.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapApplicationVariable]));

            appInfo.InstanceId = vcapApplication.InstanceId;
            appInfo.LocalIP = variablesHash[PluginBaseRes.VcapAppHostVariable];
            appInfo.Name = vcapApplication.Name;
            appInfo.Path = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], "app");
            appInfo.Port = int.Parse(variablesHash[PluginBaseRes.VcapAppPortVariable], CultureInfo.InvariantCulture);
            appInfo.WindowsPassword = variablesHash[PluginBaseRes.VcapWindowsUserPasswordVariable];
            appInfo.WindowsUserName = variablesHash[PluginBaseRes.VcapWindowsUserVariable];

            string runtime = vcapApplication.Runtime;

            string servicesJson = variablesHash[PluginBaseRes.VcapServicesVariable];
            Dictionary<string, object[]> vcapProvisionedServices = new Dictionary<string, object[]>();
            List<ApplicationService> services = new List<ApplicationService>();
            vcapProvisionedServices = JsonConvertibleObject.ObjectToValue<Dictionary<string, object[]>>(JsonConvertibleObject.DeserializeFromJson(servicesJson));

            foreach (string serviceLabel in vcapProvisionedServices.Keys)
            {
                foreach (object provisionedService in vcapProvisionedServices[serviceLabel])
                {
                    VcapProvisionedService service = new VcapProvisionedService();
                    service.FromJsonIntermediateObject(provisionedService);

                    ApplicationService appService = new ApplicationService(
                        service.Name,
                        string.IsNullOrEmpty(service.Credentials.User) ? service.Credentials.Username : service.Credentials.User,
                        service.Credentials.Password,
                        service.Credentials.Port,
                        service.Plan,
                        service.PlanOptions,
                        string.IsNullOrEmpty(service.Credentials.Hostname) ? service.Credentials.Host : service.Credentials.Hostname,
                        service.Credentials.InstanceName,
                        service.Label,
                        service.Tags);

                    services.Add(appService);
                }
            }

            VcapPluginStagingInfo vcapPluginStagingInfo = new VcapPluginStagingInfo();
            vcapPluginStagingInfo.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapPluginStagingInfoVariable]));

            string logFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppLog);
            string errorLogFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppErrorLog);
            string startupLogFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.StartupLog);

            return new ApplicationParsedData(
                appInfo,
                runtime,
                variables,
                services.ToArray(),
                vcapApplication.Urls,
                logFilePath,
                errorLogFilePath,
                startupLogFilePath,
                vcapPluginStagingInfo.AutoWireTemplates);
        }
Example #11
0
        /// <summary>
        /// Auto-wires the application variables and the log file path in the web.config file.
        /// </summary>
        /// <param name="configFileContents">The config file contents.</param>
        /// <param name="variables">The variables.</param>
        /// <param name="logFilePath">The log file path.</param>
        /// <param name="errorLogFilePath">The error log file path.</param>
        /// <returns>An xml document ready containing the updated configuration file.</returns>
        private XmlDocument SetApplicationVariables(string configFileContents, ApplicationVariable[] variables, string logFilePath, string errorLogFilePath)
        {
            this.startupLogger.Info(Strings.SettingUpApplicationVariables);

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(configFileContents);

            XmlNode appSettingsNode = doc.SelectSingleNode("configuration/appSettings");

            if (appSettingsNode == null)
            {
                appSettingsNode = doc.CreateNode(XmlNodeType.Element, "appSettings", string.Empty);

                doc.SelectSingleNode("configuration").PrependChild(appSettingsNode);
            }

            bool exists = false;
            bool hasUhuruLogFile = false;
            bool hasUhuruErrorLogFile = false;

            foreach (ApplicationVariable var in variables)
            {
                exists = false;
                if (var.Name == "UHURU_LOG_FILE")
                {
                    hasUhuruLogFile = true;
                }

                if (var.Name == "UHURU_ERROR_LOG_FILE")
                {
                    hasUhuruErrorLogFile = true;
                }

                XmlNode n = doc.CreateNode(XmlNodeType.Element, "add", string.Empty);

                XmlAttribute keyAttr = doc.CreateAttribute("key");
                keyAttr.Value = var.Name;

                XmlAttribute valueAttr = doc.CreateAttribute("value");
                valueAttr.Value = var.Value;

                n.Attributes.Append(keyAttr);
                n.Attributes.Append(valueAttr);

                XPathNodeIterator iter = appSettingsNode.CreateNavigator().Select("add");

                while (iter.MoveNext())
                {
                    string key = iter.Current.GetAttribute("key", string.Empty);
                    if (!string.IsNullOrEmpty(key) && key == var.Name)
                    {
                        exists = true;
                        iter.Current.ReplaceSelf(n.CreateNavigator());
                    }
                }

                if (!exists)
                {
                    appSettingsNode.AppendChild(n);
                }
            }

            if (!hasUhuruLogFile)
            {
                exists = false;
                XmlNode n = doc.CreateNode(XmlNodeType.Element, "add", string.Empty);

                XmlAttribute keyAttr = doc.CreateAttribute("key");
                keyAttr.Value = "UHURU_LOG_FILE";

                XmlAttribute valueAttr = doc.CreateAttribute("value");
                valueAttr.Value = logFilePath;

                n.Attributes.Append(keyAttr);
                n.Attributes.Append(valueAttr);

                XPathNodeIterator iter = appSettingsNode.CreateNavigator().Select("add");

                while (iter.MoveNext())
                {
                    string key = iter.Current.GetAttribute("key", string.Empty);
                    if (!string.IsNullOrEmpty(key) && key == "UHURU_LOG_FILE")
                    {
                        exists = true;
                        iter.Current.ReplaceSelf(n.CreateNavigator());
                    }
                }

                if (!exists)
                {
                    appSettingsNode.AppendChild(n);
                }
            }

            if (!hasUhuruErrorLogFile)
            {
                exists = false;
                XmlNode n = doc.CreateNode(XmlNodeType.Element, "add", string.Empty);

                XmlAttribute keyAttr = doc.CreateAttribute("key");
                keyAttr.Value = "UHURU_ERROR_LOG_FILE";

                XmlAttribute valueAttr = doc.CreateAttribute("value");
                valueAttr.Value = errorLogFilePath;

                n.Attributes.Append(keyAttr);
                n.Attributes.Append(valueAttr);

                XPathNodeIterator iter = appSettingsNode.CreateNavigator().Select("add");

                while (iter.MoveNext())
                {
                    string key = iter.Current.GetAttribute("key", string.Empty);
                    if (!string.IsNullOrEmpty(key) && key == "UHURU_ERROR_LOG_FILE")
                    {
                        exists = true;
                        iter.Current.ReplaceSelf(n.CreateNavigator());
                    }
                }

                if (!exists)
                {
                    appSettingsNode.AppendChild(n);
                }
            }

            this.startupLogger.Info(Strings.DoneSettingUpApplication);

            return doc;
        }
Example #12
0
        private void AutowireUhurufs(ApplicationInfo appInfo, ApplicationVariable[] variables, ApplicationService[] services, string homeAppPath)
        {
            this.startupLogger.Info(Strings.StartingApplicationAutoWiring);

            Dictionary<string, HashSet<string>> persistentFiles = new Dictionary<string, HashSet<string>>();

            foreach (ApplicationVariable var in variables)
            {
                if (var.Name.StartsWith("uhurufs_", StringComparison.Ordinal))
                {
                    string serviceName = var.Name.Split(new string[] { "uhurufs_" }, 2, StringSplitOptions.RemoveEmptyEntries)[0];
                    if (!persistentFiles.ContainsKey(serviceName))
                    {
                        persistentFiles[serviceName] = new HashSet<string>();
                    }

                    string[] persistedItems = var.Value.Trim(new char[] { '"' }).Split(new char[] { ';', ',', ':' });

                    foreach (string item in persistedItems)
                    {
                        persistentFiles[serviceName].Add(item.Replace('/', '\\'));
                    }
                }
            }

            foreach (ApplicationService serv in services)
            {
                if (serv.ServiceLabel.StartsWith("uhurufs", StringComparison.Ordinal))
                {
                    string shareHost = GenerateUhurufsHost(appInfo.InstanceId, serv.InstanceName, serv.User);

                    try
                    {
                        if (!SystemHosts.Exists(shareHost))
                        {
                            // Note: delete the host after the app is deleted
                            SystemHosts.Add(shareHost, serv.Host);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // If the service host cannot be added to hosts connect
                        shareHost = serv.Host;
                    }

                    string remotePath = string.Format(CultureInfo.InvariantCulture, @"\\{0}\{1}", shareHost, serv.InstanceName);
                    string mountPath = GenerateMountPath(homeAppPath, serv.Name);
                    Directory.CreateDirectory(Path.Combine(mountPath, @".."));

                    // Add the share users credentials to the application user.
                    // This way the application can use the share directly without invoking `net use` with the credentials.
                    using (new UserImpersonator(appInfo.WindowsUserName, ".", appInfo.WindowsPassword, true))
                    {
                        SaveCredentials.AddDomainUserCredential(shareHost, serv.User, serv.Password);
                    }

                    // The impersonated user cannot create links
                    // Note: unmount the share after the app is deleted
                    SambaWindowsClient.Mount(remotePath, serv.User, serv.Password);
                    SambaWindowsClient.LinkDirectory(remotePath, mountPath);

                    if (persistentFiles.ContainsKey(serv.Name))
                    {
                        foreach (string fileSystemItem in persistentFiles[serv.Name])
                        {
                            try
                            {
                                this.PersistFileSystemItem(appInfo.Path, fileSystemItem, Path.Combine(mountPath, appInfo.Name));
                            }
                            catch (Exception ex)
                            {
                                this.startupLogger.Error("Failed linking file/directory: {0}. Exception: {1}", fileSystemItem, ex.ToString());
                            }
                        }
                    }
                }
            }
        }
Example #13
0
        public void RecoverExistingDroplets()
        {
            if (!File.Exists(this.droplets.AppStateFile))
            {
                this.droplets.RecoveredDroplets = true;
                return;
            }

            object[] instances = JsonConvertibleObject.DeserializeFromJsonArray(File.ReadAllText(this.droplets.AppStateFile));

            foreach (object obj in instances)
            {
                DropletInstance instance = null;

                try
                {
                    instance = new DropletInstance();
                    instance.Properties.FromJsonIntermediateObject(obj);
                    instance.Properties.Orphaned = true;
                    instance.Properties.ResourcesTracked = false;
                    this.monitoring.AddInstanceResources(instance);
                    instance.Properties.StopProcessed = false;
                    instance.JobObject.JobMemoryLimit = instance.Properties.MemoryQuotaBytes;

                    try
                    {
                        instance.LoadPlugin();

                        instance.Properties.EnvironmentVariables[VcapAppPidVariable] = instance.Properties.ProcessId.ToString(CultureInfo.InvariantCulture);
                        List<ApplicationVariable> appVariables = new List<ApplicationVariable>();
                        foreach (KeyValuePair<string, string> appEnv in instance.Properties.EnvironmentVariables)
                        {
                            ApplicationVariable appVariable = new ApplicationVariable();
                            appVariable.Name = appEnv.Key;
                            appVariable.Value = appEnv.Value;
                            appVariables.Add(appVariable);
                        }

                        instance.Plugin.RecoverApplication(appVariables.ToArray());
                    }
                    catch (Exception ex)
                    {
                        instance.ErrorLog.Error(ex.ToString());
                    }

                    if (instance.Properties.State == DropletInstanceState.Starting)
                    {
                        this.DetectAppReady(instance);
                    }

                    this.droplets.AddDropletInstance(instance);
                    instance = null;
                }
                catch (Exception ex)
                {
                    Logger.Warning(Strings.ErrorRecoveringDropletWarningMessage, instance.Properties.InstanceId, ex.ToString());
                }
                finally
                {
                    if (instance != null)
                    {
                        instance.Dispose();
                    }
                }
            }

            this.droplets.RecoveredDroplets = true;

            if (this.monitoring.Clients > 0)
            {
                Logger.Info(Strings.DeaRecoveredApplications, this.monitoring.Clients);
            }

            this.MonitorApps();
            this.droplets.ForEach(delegate(DropletInstance instance)
            {
                this.RegisterInstanceWithRouter(instance);
            });
            this.SendHeartbeat();
            this.droplets.ScheduleSnapshotAppState();
        }
Example #14
0
        private void StartDropletInstance(DropletInstance instance, string sha1, string executableFile, Uri executableUri)
        {
            try
            {
                string tgzFile = Path.Combine(this.stager.StagedDir, sha1 + ".tgz");
                this.stager.StageAppDirectory(executableFile, executableUri, sha1, tgzFile, instance);

                Logger.Debug(Strings.Downloadcompleate);

                string starting = string.Format(CultureInfo.InvariantCulture, Strings.StartingUpInstanceOnPort, instance.Properties.LoggingId, instance.Properties.Port);

                if (!string.IsNullOrEmpty(instance.Properties.DebugMode))
                {
                    Logger.Info(starting + Strings.WithDebuggerPort, instance.Properties.DebugPort);
                }
                else
                {
                    Logger.Info(starting);
                }

                Logger.Debug(Strings.Clients, this.monitoring.Clients);
                Logger.Debug(Strings.ReservedMemoryUsageMb, this.monitoring.MemoryReservedMbytes, this.monitoring.MaxMemoryMbytes);

                List<ApplicationVariable> appVariables = new List<ApplicationVariable>();
                try
                {
                    instance.Lock.EnterWriteLock();

                    instance.Properties.WindowsPassword = "******" + Credentials.GenerateCredential();
                    instance.Properties.WindowsUserName = WindowsVCAPUsers.CreateUser(instance.Properties.InstanceId, instance.Properties.WindowsPassword);

                    instance.Properties.EnvironmentVariables.Add(VcapWindowsUserVariable, instance.Properties.WindowsUserName);
                    instance.Properties.EnvironmentVariables.Add(VcapWindowsUserPasswordVariable, instance.Properties.WindowsPassword);
                    instance.Properties.EnvironmentVariables.Add(VcapPluginStagingInfoVariable, File.ReadAllText(Path.Combine(instance.Properties.Directory, "startup")));

                    foreach (KeyValuePair<string, string> appEnv in instance.Properties.EnvironmentVariables)
                    {
                        ApplicationVariable appVariable = new ApplicationVariable();
                        appVariable.Name = appEnv.Key;
                        appVariable.Value = appEnv.Value;
                        appVariables.Add(appVariable);
                    }
                }
                finally
                {
                    instance.Lock.ExitWriteLock();
                }

                DateTime start = DateTime.Now;

                instance.LoadPlugin();
                instance.Plugin.ConfigureApplication(appVariables.ToArray());
                instance.Plugin.StartApplication();

                int pid = instance.Plugin.GetApplicationProcessId();

                Logger.Debug(Strings.TookXTimeToLoadConfigureAndStartDebugMessage, (DateTime.Now - start).TotalSeconds);

                try
                {
                    instance.Lock.EnterWriteLock();

                    if (!instance.Properties.StopProcessed)
                    {
                        Logger.Info(Strings.PidAssignedToDroplet, pid, instance.Properties.LoggingId);
                        instance.Properties.ProcessId = pid;
                        this.droplets.ScheduleSnapshotAppState();
                    }
                }
                finally
                {
                    instance.Lock.ExitWriteLock();
                }

                this.DetectAppReady(instance);
            }
            catch (Exception ex)
            {
                Logger.Warning(Strings.FailedStagingAppDir, instance.Properties.Directory, instance.Properties.LoggingId, ex.ToString());
                try
                {
                    instance.Lock.EnterWriteLock();

                    instance.Properties.State = DropletInstanceState.Crashed;
                    instance.Properties.ExitReason = DropletExitReason.Crashed;
                    instance.Properties.StateTimestamp = DateTime.Now;

                    this.StopDroplet(instance);
                }
                finally
                {
                    instance.Lock.ExitWriteLock();
                }
            }
        }