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(); }); } }
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); }
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); }
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; }
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); } }
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; }