Пример #1
0
        public bool InitializeAdminBuildpack(StagingStartRequestAdminBuildpack adminBuildpack, string adminBuildpackDir, bool checkWindowsCompatibility)
        {
            var dir            = Path.Combine(adminBuildpackDir, adminBuildpack.Key);
            var buildpackMutex = new Mutex(false, AdminBuildpackMutexName(adminBuildpack.Key));

            try
            {
                buildpackMutex.WaitOne();

                DownloadAdminBuildpack(adminBuildpack, adminBuildpackDir);

                if (checkWindowsCompatibility)
                {
                    var winBuildpack = BuildpackHasWindowsCompatibleBinaries(dir);
                    if (!winBuildpack)
                    {
                        Logger.Info("Ignoring buildpack {1}. Staging task {0}. Unable to detect compatible windows executables in buildpack bin.", this.Properties.TaskId, dir);
                        return(false);
                    }
                }

                DEAUtilities.DirectoryCopy(dir, Path.Combine(this.Workspace.TempDir, "buildpack"), true);
            }

            finally
            {
                buildpackMutex.ReleaseMutex();
                buildpackMutex.Dispose();
            }

            return(true);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationBits"/> class.
        /// </summary>
        public ApplicationBits()
        {
            // Force to load assemby to allow decompression to be executed under a impersonated user
            DEAUtilities.InitizlizeExtractor();

            this.Stacks = new HashSet <string>();
            if (!this.DisableDirCleanup)
            {
                TimerHelper.RecurringCall(CleanCacheIntervalMilliseconds, delegate { this.CleanCacheDirectory(); });
            }
        }
Пример #3
0
        public void PrepareStagingDirs()
        {
            string appDir  = Path.Combine(this.Workspace.StagedDir, "app");
            string logsDir = Path.Combine(this.Workspace.StagedDir, "logs");
            string tmpDir  = Path.Combine(this.Workspace.StagedDir, "tmp");

            Directory.CreateDirectory(appDir);
            Directory.CreateDirectory(logsDir);
            Directory.CreateDirectory(tmpDir);
            DEAUtilities.DirectoryCopy(this.Workspace.UnstagedDir, appDir, true);
        }
Пример #4
0
 public bool Cleanup()
 {
     // don't crash if cleanup fails
     try
     {
         DEAUtilities.RemoveReadOnlyAttribute(this.Workspace.BaseDir);
         Directory.Delete(this.Workspace.BaseDir, true);
         return(true);
     }
     catch { }
     return(false);
 }
Пример #5
0
        public void GetBuildpack(StagingStartMessageRequest message, string gitPath, string buildpacksDir)
        {
            if (message.Properties.Buildpack != null)
            {
                Logger.Info("Staging task {0}: Downloading buildpack from {1}", this.Properties.TaskId, message.Properties.Buildpack);
                Directory.CreateDirectory(Path.Combine(this.Workspace.TempDir, "buildpacks"));
                string buildpackPath = Path.Combine(this.Workspace.TempDir, "buildpacks", Path.GetFileName(new Uri(message.Properties.Buildpack).LocalPath));
                string command       = string.Format("\"{0}\" clone --quiet --recursive {1} {2}", gitPath, message.Properties.Buildpack, buildpackPath);
                Logger.Debug(command);
                int success = Command.ExecuteCommand(command, this.Workspace.TempDir);
                if (success != 0)
                {
                    throw new Exception(string.Format("Failed to git clone buildpack. Exit code: {0}", success));
                }
                this.Buildpack = new Buildpack(buildpackPath, Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);

                bool detected = this.Buildpack.Detect(this.Container);
                if (!detected)
                {
                    throw new Exception("Buildpack does not support this application.");
                }
            }
            else
            {
                Logger.Info("Staging task {0}: Detecting buildpack", this.Properties.TaskId);
                foreach (string dir in Directory.EnumerateDirectories(buildpacksDir))
                {
                    DEAUtilities.DirectoryCopy(dir, Path.Combine(this.Workspace.TempDir, "buildpack"), true);
                    Buildpack bp      = new Buildpack(Path.Combine(this.Workspace.TempDir, "buildpack"), Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);
                    bool      success = bp.Detect(this.Container);
                    if (success)
                    {
                        this.Buildpack = bp;
                        break;
                    }
                    else
                    {
                        Directory.Delete(Path.Combine(this.Workspace.TempDir, "buildpack"), true);
                    }
                }

                if (this.Buildpack == null)
                {
                    throw new Exception("Unable to detect a supported application type");
                }
                Logger.Info("Staging task {0}: Detected buildpack {1}", this.Properties.TaskId, this.Buildpack.Name);
            }
            this.Properties.DetectedBuildpack = this.Buildpack.Name;
        }
Пример #6
0
        public void UnpackDroplet()
        {
            Directory.CreateDirectory(this.Workspace.UnstagedDir);
            if (File.Exists(this.Workspace.DownloadDropletPath))
            {
                DEAUtilities.ExtractArchive(this.Workspace.DownloadDropletPath, this.Workspace.UnstagedDir);
            }
            else
            {
                throw new Exception(string.Format("Could not find file {0}", this.Workspace.DownloadDropletPath));
            }
            Directory.CreateDirectory(this.Workspace.Cache);
            if (File.Exists(this.Workspace.DownloadBuildpackCachePath))
            {
                Logger.Debug("Staging task {0}: Unpacking buildpack cache {1}", this.Properties.TaskId, this.Workspace.DownloadBuildpackCachePath);

                DEAUtilities.ExtractArchive(this.Workspace.DownloadBuildpackCachePath, this.Workspace.Cache);
            }
        }
        /// <summary>
        /// Prepares the app directory.
        /// </summary>
        /// <param name="bitsFile">The bits file.</param>
        /// <param name="bitsUri">The bits URI.</param>
        /// <param name="hash">The sha1.</param>
        /// <param name="tarZipFile">The TGZ file.</param>
        /// <param name="instance">The instance.</param>
        public void PrepareAppDirectory(string bitsFile, string bitsUri, string hash, string tarZipFile, DropletInstance instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            // What we do here, in order of preference..
            // 1. Check our own staged directory.
            // 2. Check shared directory from CloudController that could be mounted (bits_file)
            // 3. Pull from http if needed.
            string instanceDir = instance.Properties.Directory;

            lock (this.stagerLock)
            {
                // check before downloading
                if (instance.Properties.StopProcessed)
                {
                    return;
                }

                if (File.Exists(tarZipFile))
                {
                    Logger.Debug(Strings.FoundStagedBitsInLocalCache);
                }
                else
                {
                    // If we have a shared volume from the CloudController we can see the bits directly, just link into our staged version.
                    DateTime start = DateTime.Now;
                    if (File.Exists(bitsFile))
                    {
                        Logger.Debug(Strings.SharingCloudControllerStagingDirectory);
                        File.Copy(bitsFile, tarZipFile);
                        Logger.Debug(Strings.TookXSecondsToCopyFromShared, DateTime.Now - start);
                    }
                    else
                    {
                        Uri downloadUri = new Uri(bitsUri);

                        Logger.Debug(Strings.Needtodownloadappbitsfrom, downloadUri);

                        this.DownloadAppBits(downloadUri, hash, tarZipFile);

                        Logger.Debug(Strings.TookXSecondsToDownloadAndWrite, DateTime.Now - start);
                    }
                }

                // create log files
                string logDir = Path.Combine(instance.Properties.Directory, "logs");
                Directory.CreateDirectory(logDir);
                using (File.Create(Path.Combine(logDir, "stdout.log"))) { }
                using (File.Create(Path.Combine(logDir, "stderr.log"))) { }

                // check before extracting
                if (instance.Properties.StopProcessed)
                {
                    return;
                }

                DateTime startStageing = DateTime.Now;

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

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

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

                // Taking ownership of a file has to be executed with restore privilege elevated privilages
                using (new ProcessPrivileges.PrivilegeEnabler(Process.GetCurrentProcess(), ProcessPrivileges.Privilege.Restore))
                {
                    deploymentDirInfo.SetAccessControl(deploymentDirSecurity);
                }

                // Impersonate user to cascade the owernship to every file
                // Neccessary for windows disk quota
                using (new UserImpersonator(instance.Properties.WindowsUserName, ".", instance.Properties.WindowsPassword, true))
                {
                    DEAUtilities.ExtractArchive(tarZipFile, instanceDir);
                }

                Logger.Debug(Strings.TookXSecondsToStageTheApp, DateTime.Now - startStageing);
            }
        }
Пример #8
0
        public void GetBuildpack(StagingStartMessageRequest message, string gitPath, string buildpacksDir, string adminBuildpackDir)
        {
            string buildpackUrl = message.Properties.Buildpack ?? message.Properties.BuildpackGitUrl;

            if (buildpackUrl != null)
            {
                Logger.Info("Staging task {0}: Downloading buildpack from {1}", this.Properties.TaskId, message.Properties.Buildpack);
                Directory.CreateDirectory(Path.Combine(this.Workspace.TempDir, "buildpacks"));
                string buildpackPath = Path.Combine(this.Workspace.TempDir, "buildpacks", Path.GetFileName(new Uri(message.Properties.Buildpack).LocalPath));
                string command       = string.Format("set GIT_TERMINAL_PROMPT=0& \"{0}\" clone --quiet --recursive {1} {2}", gitPath, message.Properties.Buildpack, buildpackPath);
                Logger.Debug(command);
                int success = Command.ExecuteCommand(command, this.Workspace.TempDir);
                if (success != 0)
                {
                    throw new Exception(string.Format("Failed to git clone buildpack. Exit code: {0}", success));
                }
                this.Buildpack = new Buildpack(buildpackPath, Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);

                bool detected = this.Buildpack.Detect(this.Container);
                if (!detected)
                {
                    throw new Exception("Buildpack does not support this application.");
                }
            }
            else if (message.Properties.BuildpackKey != null)
            {
                Logger.Info("Staging task {0}: Using admin buildpack {1}", this.Properties.TaskId, message.Properties.BuildpackKey);

                TryCleanupUnusedAdminBuildpacks(message.AdminBuildpacks, adminBuildpackDir);
                var adminBuildpack = message.AdminBuildpacks.First(i => i.Key == message.Properties.BuildpackKey);

                InitializeAdminBuildpack(adminBuildpack, adminBuildpackDir, false);

                this.Buildpack = new Buildpack(Path.Combine(this.Workspace.TempDir, "buildpack"), Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);

                bool detected = this.Buildpack.Detect(this.Container);
                if (!detected)
                {
                    throw new InvalidOperationException("Buildpack does not support this application.");
                }
            }
            else
            {
                Logger.Info("Staging task {0}: Detecting buildpack", this.Properties.TaskId);

                if (message.AdminBuildpacks != null)
                {
                    TryCleanupUnusedAdminBuildpacks(message.AdminBuildpacks, adminBuildpackDir);

                    foreach (var adminBuildpack in message.AdminBuildpacks)
                    {
                        if (!InitializeAdminBuildpack(adminBuildpack, adminBuildpackDir, true))
                        {
                            continue;
                        }

                        Buildpack bp      = new Buildpack(Path.Combine(this.Workspace.TempDir, "buildpack"), Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);
                        bool      success = bp.Detect(this.Container);
                        if (success)
                        {
                            this.Buildpack = bp;
                            break;
                        }
                        else
                        {
                            Directory.Delete(Path.Combine(this.Workspace.TempDir, "buildpack"), true);
                        }
                    }
                }

                if (this.Buildpack == null)
                {
                    if (Directory.Exists(buildpacksDir))
                    {
                        List <string> systemBuildpacks = Directory.EnumerateDirectories(buildpacksDir).ToList();

                        foreach (string dir in systemBuildpacks)
                        {
                            DEAUtilities.DirectoryCopy(dir, Path.Combine(this.Workspace.TempDir, "buildpack"), true);
                            Buildpack bp      = new Buildpack(Path.Combine(this.Workspace.TempDir, "buildpack"), Path.Combine(this.Workspace.StagedDir, "app"), this.Workspace.Cache, this.Workspace.StagingLogPath);
                            bool      success = bp.Detect(this.Container);
                            if (success)
                            {
                                this.Buildpack = bp;
                                break;
                            }
                            else
                            {
                                Directory.Delete(Path.Combine(this.Workspace.TempDir, "buildpack"), true);
                            }
                        }
                    }
                }

                if (this.Buildpack == null)
                {
                    throw new InvalidOperationException("Unable to detect a supported application type.");
                }
                Logger.Info("Staging task {0}: Detected buildpack {1}", this.Properties.TaskId, this.Buildpack.Name);
            }

            this.Properties.DetectedBuildpack = this.Buildpack.Name;
        }