예제 #1
0
        public StagingTask(StagingStartMessageRequest message)
        {
            UhuruSection uhuruSection = (UhuruSection)ConfigurationManager.GetSection("uhuru");

            this.TaskId = message.TaskID;
            this.Message = message;
            this.workspace = new StagingWorkspace(Path.Combine(uhuruSection.DEA.BaseDir, "staging"), message.TaskID);
            this.buildpacksDir = Path.GetFullPath(uhuruSection.DEA.Staging.BuildpacksDirectory);
            this.stagingTimeout = uhuruSection.DEA.Staging.StagingTimeoutMs;
            this.gitExe = Path.GetFullPath(uhuruSection.DEA.Staging.GitExecutable);

            var prisonInfo = new ProcessPrisonCreateInfo();
            prisonInfo.Id = this.TaskId;
            prisonInfo.TotalPrivateMemoryLimit = (long)this.Message.Properties.Resources.MemoryMbytes * 1024 * 1024;

            if (uhuruSection.DEA.UseDiskQuota)
            {
                prisonInfo.DiskQuotaBytes = (long)this.Message.Properties.Resources.DiskMbytes * 1024 * 1024;
                prisonInfo.DiskQuotaPath = this.workspace.BaseDir;
            }

            if (uhuruSection.DEA.UploadThrottleBitsps > 0)
            {
                prisonInfo.NetworkOutboundRateLimitBitsPerSecond = uhuruSection.DEA.UploadThrottleBitsps;
            }

            this.prison = new ProcessPrison();
            prison.Create(prisonInfo);
        }
예제 #2
0
        public void Attach(ProcessPrisonCreateInfo createInfo)
        {
            if (createInfo.Id == null)
            {
                throw new ArgumentException("Id from createInfo is null", "createInfo");
            }

            if (createInfo.WindowsPassword == null)
            {
                throw new ArgumentException("WindowsPassword from createInfo is null", "createInfo");
            }

            this.Id = createInfo.Id;

            this.createInfo = createInfo;

            // The Job Object will disapear after a reboot or if all job's processes exit.
            // It is fine if it is created again with the same name id if the Job doesn't exist.

            try
            {
                // try only to attach and fail if it doesn't exist
                this.jobObject = JobObject.Attach(JobObjectNamespace() + this.Id);
            }
            catch (Win32Exception)
            {
                // try to create the job Id;
                this.jobObject = new JobObject(JobObjectNamespace() + this.Id);
            }


            this.WindowsPassword = this.createInfo.WindowsPassword;
            this.WindowsUsername = GenerateDecoratedUsername(this.Id);

            if (this.createInfo.DiskQuotaBytes > -1)
            {
                userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername);
            }

            this.Created = true;
        }
예제 #3
0
        public void Create(ProcessPrisonCreateInfo createInfo)
        {
            if (createInfo.Id == null)
            {
                this.Id = GenerateSecureGuid().ToString();
            }
            else
            {
                this.Id = createInfo.Id;
            }

            string[] keys = new string[] { "ALLUSERSPROFILE", "APPDATA", "CommonProgramFiles", "CommonProgramFiles(x86)", "CommonProgramW6432", "COMPUTERNAME",
                                           "HOMEDRIVE", "LOCALAPPDATA", "NUMBER_OF_PROCESSORS", "OS", "Path", "PROCESSOR_ARCHITECTURE", "PROCESSOR_IDENTIFIER", "PROCESSOR_LEVEL",
                                           "PROCESSOR_REVISION", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432", "PROMPT", "PSModulePath",
                                           "SystemDrive", "SystemRoot", "windir" };

            this.myenvvars["HOMEPATH"] = createInfo.DiskQuotaPath;
            this.myenvvars["TEMP"]     = Path.Combine(createInfo.DiskQuotaPath, "tmp");
            this.myenvvars["TMP"]      = Path.Combine(createInfo.DiskQuotaPath, "tmp");

            foreach (string key in keys)
            {
                this.myenvvars[key] = Environment.GetEnvironmentVariable(key);
            }

            this.createInfo = createInfo;
            this.jobObject  = new JobObject(JobObjectNamespace() + this.Id);

            this.jobObject.ActiveProcessesLimit = this.createInfo.RunningProcessesLimit;
            this.jobObject.JobMemoryLimitBytes  = this.createInfo.TotalPrivateMemoryLimitBytes;

            this.jobObject.KillProcessesOnJobClose = this.createInfo.KillProcessesrOnPrisonClose;


            if (this.createInfo.WindowsPassword == null)
            {
                this.WindowsPassword = GenerateSecurePassword(40);
            }
            else
            {
                this.WindowsPassword = this.createInfo.WindowsPassword;
            }


            this.WindowsUsername = CreateDecoratedUser(this.Id, this.WindowsPassword);


            if (this.createInfo.DiskQuotaBytes > -1)
            {
                if (string.IsNullOrEmpty(this.createInfo.DiskQuotaPath))
                {
                    // set this.createInfo.DiskQuotaPath to the output of GetUserProfileDirectory
                    throw new NotImplementedException();
                }

                // Set the disk quota to 0 for all disks, exept disk quota path
                var volumesQuotas = DiskQuotaManager.GetDisksQuotaUser(this.WindowsUsername);
                foreach (var volumeQuota in volumesQuotas)
                {
                    volumeQuota.QuotaLimit = 0;
                }

                userQuota            = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername);
                userQuota.QuotaLimit = this.createInfo.DiskQuotaBytes;
            }

            if (this.createInfo.UrlPortAccess > 0)
            {
                UrlsAcl.AddPortAccess(this.createInfo.UrlPortAccess, this.WindowsUsername);
            }

            if (this.createInfo.NetworkOutboundRateLimitBitsPerSecond > 0)
            {
                NetworkQos.CreateOutboundThrottlePolicy(this.WindowsUsername, this.WindowsUsername, this.createInfo.NetworkOutboundRateLimitBitsPerSecond);

                if (this.createInfo.UrlPortAccess > 0)
                {
                    NetworkQos.CreateOutboundThrottlePolicy(this.createInfo.UrlPortAccess.ToString(), this.createInfo.UrlPortAccess, this.createInfo.NetworkOutboundRateLimitBitsPerSecond);
                }
            }

            this.Created = true;
        }
예제 #4
0
        private void CleanupStagingInstances()
        {
            if (!File.Exists(this.stagingTaskRegistry.StagingStateFile))
            {
                return;
            }

            object[] instances = JsonConvertibleObject.DeserializeFromJsonArray(File.ReadAllText(this.stagingTaskRegistry.StagingStateFile));

            foreach (object obj in instances)
            {
                StagingInstance instance = null;
                try
                {
                    instance = new StagingInstance();
                    instance.Properties.FromJsonIntermediateObject(obj);

                    var prisonInfo = new ProcessPrisonCreateInfo();
                    prisonInfo.Id = instance.Properties.InstanceId;

                    prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes;
                    prisonInfo.WindowsPassword = instance.Properties.WindowsPassword;

                    if (this.useDiskQuota)
                    {
                        prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes;
                        prisonInfo.DiskQuotaPath = instance.Properties.Directory;
                    }

                    Logger.Info("Recovering Process Prisson: {0}", prisonInfo.Id);

                    instance.Prison.Attach(prisonInfo);
                    foreach (Process p in instance.Prison.jobObject.GetJobProcesses())
                    {
                        if (!p.HasExited)
                        {
                            p.Kill();
                        }
                    }
                    if (instance.Prison.Created)
                    {
                        instance.Prison.Destroy();
                    }
                    instance.Workspace = new StagingWorkspace(instance.Properties.Directory);
                    instance.Cleanup();
                }
                catch (Exception ex)
                {
                    Logger.Warning("Error deleting staging environment for task {0}: {1}", instance.Properties.TaskId, ex.ToString());
                }
                finally
                {
                    this.stagingTaskRegistry.RemoveStagingInstance(instance);
                    if (instance != null)
                    {
                        instance.Dispose();
                    }
                }
            }
        }
예제 #5
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;

                    var prisonInfo = new ProcessPrisonCreateInfo();

                    prisonInfo.Id = instance.Properties.InstanceId;
                    prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes;
                    prisonInfo.WindowsPassword = instance.Properties.WindowsPassword;

                    if (this.useDiskQuota)
                    {
                        prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes;
                        prisonInfo.DiskQuotaPath = instance.Properties.Directory;
                    }

                    Logger.Info("Recovering Process Prisson: {0}", prisonInfo.Id);

                    instance.Prison.Attach(prisonInfo);

                    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();
        }
예제 #6
0
        private void StartDropletInstance(DropletInstance instance, string sha1, string executableFile, string executableUri)
        {
            try
            {
                try
                {
                    instance.Lock.EnterWriteLock();

                    var prisonInfo = new ProcessPrisonCreateInfo();

                    prisonInfo.Id = instance.Properties.InstanceId;
                    prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes;

                    if (this.useDiskQuota)
                    {
                        prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes;
                        prisonInfo.DiskQuotaPath = instance.Properties.Directory;
                    }

                    if (this.uploadThrottleBitsps > 0)
                    {
                        prisonInfo.NetworkOutboundRateLimitBitsPerSecond = this.uploadThrottleBitsps;
                    }

                    prisonInfo.UrlPortAccess = instance.Properties.Port;

                    Logger.Info("Creating Process Prisson: {0}", prisonInfo.Id);

                    instance.Prison.Create(prisonInfo);

                    Logger.Info("Opening firewall port {0} for instance {1}", instance.Properties.Port, instance.Properties.LoggingId);

                    FirewallTools.OpenPort(instance.Properties.Port, instance.Properties.InstanceId);

                    instance.Properties.WindowsPassword = instance.Prison.WindowsPassword;
                    instance.Properties.WindowsUserName = instance.Prison.WindowsUsername;
                }
                finally
                {
                    instance.Lock.ExitWriteLock();
                }

                string tgzFile = Path.Combine(this.fileResources.StagedDir, sha1 + ".tgz");
                this.fileResources.PrepareAppDirectory(executableFile, executableUri, sha1, tgzFile, instance);
                Logger.Debug(Strings.Downloadcompleate);

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

                Logger.Info(starting);

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

                try
                {
                    instance.Lock.EnterWriteLock();

                    instance.Properties.EnvironmentVariables.Add(VcapWindowsUserVariable, instance.Properties.WindowsUserName);
                    instance.Properties.EnvironmentVariables.Add(VcapWindowsUserPasswordVariable, instance.Properties.WindowsPassword);

                    instance.Prison.SetUsersEnvironmentVariables(instance.Properties.EnvironmentVariables);

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

                DateTime start = DateTime.Now;

                string startSciprtPath = this.CreateStartScript(instance);

                var runInfo = new ProcessPrisonRunInfo();
                runInfo.WorkingDirectory = Path.Combine(instance.Properties.Directory, "app");
                runInfo.FileName = startSciprtPath;

                instance.Prison.RunProcess(runInfo);

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

                try
                {
                    instance.Lock.EnterWriteLock();

                    if (!instance.Properties.StopProcessed)
                    {
                        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();
                }
            }
        }
예제 #7
0
        public void Create(ProcessPrisonCreateInfo createInfo)
        {
            if (createInfo.Id == null)
                this.Id = GenerateSecureGuid().ToString();
            else
                this.Id = createInfo.Id;

            string[] keys = new string[] { "ALLUSERSPROFILE", "APPDATA", "CommonProgramFiles", "CommonProgramFiles(x86)", "CommonProgramW6432", "COMPUTERNAME",
                "HOMEDRIVE", "LOCALAPPDATA", "NUMBER_OF_PROCESSORS", "OS", "Path", "PROCESSOR_ARCHITECTURE", "PROCESSOR_IDENTIFIER", "PROCESSOR_LEVEL",
                "PROCESSOR_REVISION", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432", "PROMPT", "PSModulePath",
                "SystemDrive", "SystemRoot", "windir"  };

            this.myenvvars["HOMEPATH"] = createInfo.DiskQuotaPath;
            this.myenvvars["TEMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp");
            this.myenvvars["TMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp");

            foreach (string key in keys)
            {
                this.myenvvars[key] = Environment.GetEnvironmentVariable(key);
            }

            this.createInfo = createInfo;
            this.jobObject = new JobObject(JobObjectNamespace() + this.Id);

            this.jobObject.ActiveProcessesLimit = this.createInfo.RunningProcessesLimit;
            this.jobObject.JobMemoryLimitBytes = this.createInfo.TotalPrivateMemoryLimitBytes;

            this.jobObject.KillProcessesOnJobClose = this.createInfo.KillProcessesrOnPrisonClose;

            if (this.createInfo.WindowsPassword == null)
                this.WindowsPassword = GenerateSecurePassword(40);
            else
                this.WindowsPassword = this.createInfo.WindowsPassword;

            this.WindowsUsername = CreateDecoratedUser(this.Id, this.WindowsPassword);

            if (this.createInfo.DiskQuotaBytes > -1)
            {
                if (string.IsNullOrEmpty(this.createInfo.DiskQuotaPath))
                {
                    // set this.createInfo.DiskQuotaPath to the output of GetUserProfileDirectory
                    throw new NotImplementedException();
                }

                // Set the disk quota to 0 for all disks, exept disk quota path
                var volumesQuotas = DiskQuotaManager.GetDisksQuotaUser(this.WindowsUsername);
                foreach (var volumeQuota in volumesQuotas)
                {
                    volumeQuota.QuotaLimit = 0;
                }

                userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername);
                userQuota.QuotaLimit = this.createInfo.DiskQuotaBytes;
            }

            if (this.createInfo.UrlPortAccess > 0)
            {
                UrlsAcl.AddPortAccess(this.createInfo.UrlPortAccess, this.WindowsUsername);
            }

            if (this.createInfo.NetworkOutboundRateLimitBitsPerSecond > 0)
            {
                NetworkQos.CreateOutboundThrottlePolicy(this.WindowsUsername, this.WindowsUsername, this.createInfo.NetworkOutboundRateLimitBitsPerSecond);

                if (this.createInfo.UrlPortAccess > 0)
                {
                    NetworkQos.CreateOutboundThrottlePolicy(this.createInfo.UrlPortAccess.ToString(), this.createInfo.UrlPortAccess, this.createInfo.NetworkOutboundRateLimitBitsPerSecond);
                }
            }

            this.Created = true;
        }
예제 #8
0
        public void Attach(ProcessPrisonCreateInfo createInfo)
        {
            if (createInfo.Id == null)
            {
                throw new ArgumentException("Id from createInfo is null", "createInfo");
            }

            if (createInfo.WindowsPassword == null)
            {
                throw new ArgumentException("WindowsPassword from createInfo is null", "createInfo");
            }

            this.Id = createInfo.Id;

            this.createInfo = createInfo;

            // The Job Object will disapear after a reboot or if all job's processes exit.
            // It is fine if it is created again with the same name id if the Job doesn't exist.

            try
            {
                // try only to attach and fail if it doesn't exist
                this.jobObject = JobObject.Attach(JobObjectNamespace() + this.Id);
            }
            catch (Win32Exception)
            {
                // try to create the job Id;
                this.jobObject = new JobObject(JobObjectNamespace() + this.Id);
            }

            this.WindowsPassword = this.createInfo.WindowsPassword;
            this.WindowsUsername = GenerateDecoratedUsername(this.Id);

            if (this.createInfo.DiskQuotaBytes > -1)
            {
                userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername);
            }

            this.Created = true;
        }
예제 #9
0
        static void Main(string[] args)
        {
            Console.WriteLine("--- PrisonProcess REPL ---\n");
            Console.WriteLine("Use the following keys:");
            Console.WriteLine("\tc: Create a new cmd prison");
            Console.WriteLine("\tn: Create a new notepad prison");
            Console.WriteLine("\td: Destroy all prissons");
            Console.WriteLine("\tq: Quit");

            List<ProcessPrison> prisonss = new List<ProcessPrison>();

            DiskQuotaManager.StartQuotaInitialization();
            while (!DiskQuotaManager.IsQuotaInitialized())
            {
                Thread.Sleep(100);
            }

            var usersDesc = WindowsUsersAndGroups.GetUsersDescription();
            foreach (var desc in usersDesc.Values)
            {
                try
                {
                    var id = ProcessPrison.GetIdFromUserDescription(desc);

                    var ppci = new ProcessPrisonCreateInfo();
                    ppci.Id = id;
                    ppci.TotalPrivateMemoryLimitBytes = 128 * 1024 * 1024;
                    ppci.DiskQuotaBytes = 128 * 1024 * 1024;
                    ppci.DiskQuotaPath = @"C:\Users\Public";
                    // Cannot impersonate the user to create new processes or access the user's env.
                    ppci.WindowsPassword = "******";

                    var pp = new ProcessPrison();
                    pp.Attach(ppci);

                    prisonss.Add(pp);
                }
                catch(ArgumentException)
                {
                }
            }

            while (true)
            {
                var key = Console.ReadKey();
                if (key.Key == ConsoleKey.Q && key.Modifiers == ConsoleModifiers.Shift) break;

                switch (key.Key)
                {
                    case ConsoleKey.C:
                        {
                            var ppci = new ProcessPrisonCreateInfo();
                            ppci.TotalPrivateMemoryLimitBytes = 128 * 1000 * 1000;
                            ppci.DiskQuotaBytes = 128 * 1024 * 1024;
                            ppci.DiskQuotaPath = @"C:\Users\Public";
                            ppci.NetworkOutboundRateLimitBitsPerSecond = 80 * 1000;

                            var pp = new ProcessPrison();
                            pp.Create(ppci);
                            pp.SetUsersEnvironmentVariable("prison", pp.Id);

                            var ri = new ProcessPrisonRunInfo();
                            ri.Interactive = true;
                            ri.FileName = @"C:\Windows\System32\cmd.exe";
                            ri.Arguments = String.Format(" /k  title {1} & echo Wedcome to prisson {0}. & echo Running under user {1} & echo Private virtual memory limit: {2} B", pp.Id, pp.WindowsUsername, ppci.TotalPrivateMemoryLimitBytes);
                            ri.Arguments += " & echo. & echo Cmd bomb for memory test: & echo 'set loop=cmd /k ^%loop^%' & echo 'cmd /k %loop%'";
                            ri.Arguments += " & echo. & echo Ruby file server for network test: & echo 'rackup -b 'run Rack::Directory.new(\"\")''";

                            pp.RunProcess(ri);

                            prisonss.Add(pp);
                        }
                        break;
                    case ConsoleKey.N:
                        {
                            var ppci = new ProcessPrisonCreateInfo();
                            ppci.TotalPrivateMemoryLimitBytes = 128 * 1024 * 1024;
                            ppci.DiskQuotaBytes = 128 * 1024 * 1024;
                            ppci.DiskQuotaPath = @"C:\Users\Public";

                            var pp = new ProcessPrison();
                            pp.Create(ppci);
                            pp.SetUsersEnvironmentVariable("prison", pp.Id);

                            var ri = new ProcessPrisonRunInfo();
                            ri.Interactive = true;
                            ri.FileName = @"C:\Windows\System32\notepad.exe";

                            pp.RunProcess(ri);

                            prisonss.Add(pp);
                        }
                        break;
                    case ConsoleKey.D:
                        foreach (var prison in prisonss)
                        {
                            prison.Destroy();
                        }
                        prisonss.Clear();
                        break;
                    case ConsoleKey.Q:
                        return;
                }

            }

            var createInfo = new ProcessPrisonCreateInfo();

            var p = new ProcessPrison();

            p.Create(createInfo);
            var envs = p.GetUsersEnvironmentVariables();

            var runInfo = new ProcessPrisonRunInfo();
            runInfo.Interactive = false;
            runInfo.FileName = @"C:\Windows\System32\cmd.exe";
            runInfo.FileName = @"C:\Windows\System32\PING.EXE";
            // runInfo.Arguments = @"/c echo %PATH% & ping 10.0.0.10" ;
            runInfo.Arguments = @" /k rackup -b ""run lambda {|env| [200, {'Content-Type'=>'text/html'}, 'Hello World']}"" -P 2345";

            runInfo.Arguments = " 10.0.0.10 -t";
            runInfo.WorkingDirectory = @"C:\Users\Public";
            runInfo.FileName = @"C:\Windows\System32\mspaint.exe";
            runInfo.Arguments = "";

            p.RunProcess(runInfo);

            //p.RunProcess(@"C:\Windows\System32\mspaint.exe");

            Console.ReadKey();

            p.Destroy();
        }
예제 #10
0
        public void CreatePrison()
        {
            if(this.Prison.Created)
            {
                this.Prison.Destroy();
            }

            this.Lock.EnterWriteLock();
            var prisonInfo = new ProcessPrisonCreateInfo();
            prisonInfo.TotalPrivateMemoryLimitBytes = this.Properties.MemoryQuotaBytes;
            if (this.Properties.UseDiskQuota)
            {
                prisonInfo.DiskQuotaBytes = this.Properties.DiskQuotaBytes;
                prisonInfo.DiskQuotaPath = this.Properties.Directory;
            }

            if (this.Properties.UploadThrottleBitsps > 0)
            {
                prisonInfo.NetworkOutboundRateLimitBitsPerSecond = this.Properties.UploadThrottleBitsps;
            }

            Logger.Info("Creating Process Prisson: {0}", prisonInfo.Id);
            this.Prison.Create(prisonInfo);
            this.Properties.WindowsPassword = this.Prison.WindowsPassword;
            this.Properties.WindowsUserName = this.Prison.WindowsUsername;
            this.Properties.InstanceId = this.Prison.Id;
            this.Lock.ExitWriteLock();

            // Explode the app into its directory and optionally bind its local runtime.
            Directory.CreateDirectory(this.Properties.Directory);

            DirectoryInfo deploymentDirInfo = new DirectoryInfo(this.Properties.Directory);
            DirectorySecurity deploymentDirSecurity = deploymentDirInfo.GetAccessControl();

            // Owner is important to account for disk quota
            deploymentDirSecurity.SetOwner(new NTAccount(this.Properties.WindowsUserName));
            deploymentDirSecurity.SetAccessRule(
                new FileSystemAccessRule(
                    this.Properties.WindowsUserName,
                    FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.FullControl,
                    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                    PropagationFlags.None | PropagationFlags.InheritOnly,
                    AccessControlType.Allow));

            using (new ProcessPrivileges.PrivilegeEnabler(Process.GetCurrentProcess(), ProcessPrivileges.Privilege.Restore))
            {
                deploymentDirInfo.SetAccessControl(deploymentDirSecurity);
            }
        }