public DropletInstance CreateDropletInstance(DeaStartMessageRequest message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            DropletInstance instance = null;

            instance = new DropletInstance();

            string instanceId = Credentials.GenerateSecureGuid().ToString("N");
            string privateInstanceId = Credentials.GenerateSecureGuid().ToString("N") + Credentials.GenerateSecureGuid().ToString("N");

            instance.Properties.State = DropletInstanceState.Starting;
            instance.Properties.StateTimestamp = DateTime.Now;
            instance.Properties.Start = DateTime.Now;

            instance.Properties.InstanceId = instanceId;
            instance.Properties.PrivateInstanceId = privateInstanceId;

            instance.Properties.DropletId = message.DropletId;
            instance.Properties.InstanceIndex = message.Index;
            instance.Properties.Name = message.Name;
            instance.Properties.Uris = message.Uris;
            instance.Properties.Users = message.Users;
            instance.Properties.Version = message.Version;
            instance.Properties.Stack = message.Stack;
            instance.Properties.LoggingId = string.Format(CultureInfo.InvariantCulture, Strings.NameAppIdInstance, message.Name, message.DropletId, instanceId, message.Index);
            instance.Properties.Flapping = message.Flapping;
            instance.Properties.CloudControllerPartition = message.CloudControllerPartition;

            this.AddDropletInstance(instance);

            return instance;
        }
        private void DeaStartHandler(string message, string reply, string subject)
        {
            DeaStartMessageRequest pmessage;
            DropletInstance instance;

            try
            {
                this.droplets.Lock.EnterWriteLock();

                if (this.shuttingDown)
                {
                    return;
                }

                Logger.Debug(Strings.DeaReceivedStartMessage, message);

                pmessage = new DeaStartMessageRequest();

                // Environment variable ca be of any type. It comes directly from the user with no validation, sanitization or preprocessing.
                try
                {
                    pmessage.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(message));
                }
                catch (Exception e)
                {
                    Logger.Error("Ignoring dea.start request. Unable to parse dea.start message. Exception: {0}", e.ToString());
                    return;
                }

                long memoryMbytes = pmessage.Limits != null && pmessage.Limits.MemoryMbytes != null ? pmessage.Limits.MemoryMbytes.Value : Monitoring.DefaultAppMemoryMbytes;
                long diskMbytes = pmessage.Limits != null && pmessage.Limits.DiskMbytes != null ? pmessage.Limits.DiskMbytes.Value : Monitoring.DefaultAppDiskMbytes;
                long fds = pmessage.Limits != null && pmessage.Limits.FileDescriptors != null ? pmessage.Limits.FileDescriptors.Value : Monitoring.DefaultAppFds;

                if (this.monitoring.MemoryReservedMbytes + memoryMbytes > this.monitoring.MaxMemoryMbytes || this.monitoring.Clients >= this.monitoring.MaxClients)
                {
                    Logger.Info(Strings.Donothaveroomforthisclient);
                    return;
                }

                if (string.IsNullOrEmpty(pmessage.SHA1) || string.IsNullOrEmpty(pmessage.ExecutableFile) || string.IsNullOrEmpty(pmessage.ExecutableUri))
                {
                    Logger.Warning(Strings.StartRequestMissingProper, message);
                    return;
                }

                // TODO: Enable this when cc sends the stack name in the message
                //// if (!this.stager.StackSupported(pmessage.Stack))
                //// {
                ////     Logger.Warning(Strings.CloudNotStartRuntimeNot, message);
                ////     return;
                //// }

                instance = this.droplets.CreateDropletInstance(pmessage);
                instance.Properties.MemoryQuotaBytes = memoryMbytes * 1024 * 1024;
                instance.Properties.DiskQuotaBytes = diskMbytes * 1024 * 1024;
                instance.Properties.FDSQuota = fds;
                instance.Properties.Staged = instance.Properties.Name + "-" + instance.Properties.InstanceIndex + "-" + instance.Properties.InstanceId;
                instance.Properties.Directory = Path.Combine(this.fileResources.AppsDir, instance.Properties.Staged);

                if (!string.IsNullOrEmpty(instance.Properties.DebugMode))
                {
                    instance.Properties.DebugPort = NetworkInterface.GrabEphemeralPort();
                    instance.Properties.DebugIP = Host;
                }

                instance.Properties.Port = NetworkInterface.GrabEphemeralPort();
                instance.Properties.EnvironmentVariables = this.SetupInstanceEnv(instance, pmessage.Environment, pmessage.Services);

                if (this.enforceUlimit)
                {
                    // instance.JobObject.JobMemoryLimit = instance.Properties.MemoryQuotaBytes;
                }

                this.monitoring.AddInstanceResources(instance);
            }
            finally
            {
                this.droplets.Lock.ExitWriteLock();
            }

            // TODO: the pre-starting stage should be able to gracefuly stop when the shutdown flag is set
            ThreadPool.QueueUserWorkItem(delegate(object data)
            {
                this.StartDropletInstance(instance, pmessage.SHA1, pmessage.ExecutableFile, pmessage.ExecutableUri);
            });
        }