public void PostReceive(RubyHash options) { Logger.Debug("Running post receive for gear {0}", this.Uuid); Dictionary <string, string> gearEnv = Environ.ForGear(this.ContainerDir); string repoDir = Path.Combine(this.ContainerDir, "app-root", "runtime", "repo"); Directory.CreateDirectory(repoDir); ApplicationRepository applicationRepository = new ApplicationRepository(this); applicationRepository.Archive(repoDir, options["ref"]); options["deployment_datetime"] = this.LatestDeploymentDateTime(); Build(options); Logger.Debug("Running post receive - prepare for gear {0}", this.Uuid); Prepare(options); Logger.Debug("Running post receive - distribute for gear {0}", this.Uuid); Distribute(options); Logger.Debug("Running post receive - activate for gear {0}", this.Uuid); Activate(options); }
public string Tidy() { StringBuilder output = new StringBuilder(); Dictionary <string, string> env = Environ.ForGear(this.ContainerDir); string gearDir = env["OPENSHIFT_HOMEDIR"]; string appName = env["OPENSHIFT_APP_NAME"]; string gearRepoDir = Path.Combine(gearDir, "git", string.Format("{0}.git", appName)); string gearTmpDir = Path.Combine(gearDir, ".tmp"); output.Append(StopGear(new Dictionary <string, object>() { { "user_initiated", false } })); try { GearLevelTidyTmp(gearTmpDir); output.AppendLine(this.Cartridge.Tidy()); output.AppendLine(GearLevelTidyGit(gearRepoDir)); } catch (Exception ex) { output.AppendLine(ex.ToString()); } finally { StartGear(new Dictionary <string, object>() { { "user_initiated", false } }); } return(output.ToString()); }
public string DeletePublicEndpoints(string cartName) { Manifest cart = Cartridge.GetCartridge(cartName); StringBuilder output = new StringBuilder(); Dictionary <string, string> env = Environ.ForGear(this.ContainerDir); try { foreach (Endpoint endpoint in cart.Endpoints) { string port = env[endpoint.PrivatePortName]; // TODO: will have to change this once prison is integrated Network.CloseFirewallPort(port); output.AppendFormat("NOTIFY_ENDPOINT_DELETE: {0} {1}", NodeConfig.Values["PUBLIC_IP"], port); } Logger.Warning(@"Deleted all public endpoints for cart {0} in gear {1}", cartName, this.Uuid); } catch (Exception ex) { Logger.Warning(@"Couldn't delete all public endpoints for cart {0} in gear {1}: {2} - {3}", cartName, this.Uuid, ex.Message, ex.StackTrace); } return(output.ToString()); }
public string CartridgeAction(Manifest cartridge, string action, string softwareVersion, bool renderErbs = false) { string cartridgeHome = Path.Combine(this.container.ContainerDir, cartridge.Dir); action = Path.Combine(cartridgeHome, "bin", action + ".ps1"); if (!File.Exists(action)) { return(string.Empty); } Dictionary <string, string> gearEnv = Environ.ForGear(this.container.ContainerDir); string cartridgeEnvHome = Path.Combine(cartridgeHome, "env"); Dictionary <string, string> cartridgeEnv = Environ.Load(cartridgeEnvHome); cartridgeEnv.Remove("PATH"); foreach (var kvp in gearEnv) { cartridgeEnv[kvp.Key] = kvp.Value; } if (renderErbs) { // TODO: render erb } // TODO: vladi: implement hourglass string cmd = string.Format("{0} -ExecutionPolicy Bypass -InputFormat None -noninteractive -file {1} --version {2}", ProcessExtensions.Get64BitPowershell(), action, softwareVersion); string output = this.container.RunProcessInContainerContext(cartridgeHome, cmd, 0).StdOut; // TODO: vladi: add logging return(output); }
public void Test_Environ() { string gearDir = "TestGearDir"; Dictionary <string, string> result = Environ.ForGear(gearDir); DirectoryUtil.EmptyDirectory(gearDir); Directory.Delete(gearDir); Assert.IsNotNull(result); }
public List <RubyHash> WithGearRotation(RubyHash options, GearRotationCallback action) { dynamic localGearEnv = Environ.ForGear(this.ContainerDir); Manifest proxyCart = this.Cartridge.WebProxy(); List <object> gears = new List <object>(); // TODO: vladi: verify if this is needed for scalable apps //if (options.ContainsKey("all") && proxyCart != null) //{ // if ((bool)options["all"]) // { // gears = this.GearRegist.Entries["web"].Keys.ToList<object>(); // } // else if (options.ContainsKey("gears")) // { // List<string> g = (List<string>)options["gears"]; // gears = this.GearRegist.Entries["web"].Keys.Where(e => g.Contains(e)).ToList<object>(); // } // else // { // try // { // gears.Add(this.GearRegist.Entries["web"][this.Uuid]); // } // catch // { // gears.Add(this.Uuid); // } // } //} //else { gears.Add(this.Uuid); } double parallelConcurrentRatio = PARALLEL_CONCURRENCY_RATIO; if (options.ContainsKey("parallel_concurrency_ratio")) { parallelConcurrentRatio = (double)options["parallel_concurrency_ratio"]; } int batchSize = CalculateBatchSize(gears.Count, parallelConcurrentRatio); int threads = Math.Max(batchSize, MAX_THREADS); List <RubyHash> result = new List <RubyHash>(); // need to parallelize foreach (var targetGear in gears) { result.Add(RotateAndYield(targetGear, localGearEnv, options, action)); } return(result); }
private string CartridgeTeardown(string cartridgeName, bool removeCartridgeDir) { string cartridgeHome = Path.Combine(this.container.ContainerDir, cartridgeName); Dictionary <string, string> env = Environ.ForGear(this.container.ContainerDir, cartridgeHome); string teardown = Path.Combine(cartridgeHome, "bin", "teardown.ps1"); if (!File.Exists(teardown)) { return(string.Empty); } // run teardown script return(string.Empty); }
public Manifest GetPrimaryCartridge() { Dictionary <string, string> env = Environ.ForGear(container.ContainerDir); string primaryCartDir = null; if (env.ContainsKey("OPENSHIFT_PRIMARY_CARTRIDGE_DIR")) { primaryCartDir = env["OPENSHIFT_PRIMARY_CARTRIDGE_DIR"]; } else { return(null); } return(GetCartridgeFromDirectory(primaryCartDir)); }
public string Prepare(RubyHash options = null) { if (options == null) { options = new RubyHash(); } StringBuilder output = new StringBuilder(); output.AppendLine("Preparing build for deployment"); if (!options.ContainsKey("deployment_datetime")) { throw new ArgumentException("deployment_datetime is required"); } string deploymentDatetime = options["deployment_datetime"].ToString(); Dictionary <string, string> env = Environ.ForGear(this.ContainerDir); // TODO clean runtime dirs, extract archive this.Cartridge.DoActionHook("prepare", env, options); string deploymentId = CalculateDeploymentId(); LinkDeploymentId(deploymentDatetime, deploymentId); try { SyncRuntimeRepoDirToDeployment(deploymentDatetime); SyncRuntimeDependenciesDirToDeployment(deploymentDatetime); SyncRuntimeBuildDependenciesDirToDeployment(deploymentDatetime); DeploymentMetadata deploymentMetadata = DeploymentMetadataFor(deploymentDatetime); deploymentMetadata.Id = deploymentId; deploymentMetadata.Checksum = CalculateDeploymentChecksum(deploymentId); deploymentMetadata.Save(); options["deployment_id"] = deploymentId; output.AppendLine("Deployment id is " + deploymentId); } catch (Exception e) { Logger.Error("Error preparing deployment. Options: {0} - {1} - {2}", JsonConvert.SerializeObject(options), e.Message, e.StackTrace); output.AppendLine("Error preparing deployment " + deploymentId); UnlinkDeploymentId(deploymentId); } return(output.ToString()); }
public ReturnStatus Execute() { ReturnStatus returnStatus = new ReturnStatus(); try { Logger.Debug(string.Format("Running Get-Gear-Envs-Action for {0}", Uuid)); string containerDir = ApplicationContainer.GetFromUuid(Uuid).ContainerDir; Dictionary <string, string> envVars = Environ.ForGear(containerDir); returnStatus.Output = JsonConvert.SerializeObject(envVars); Logger.Debug(string.Format("Output for Get-Gear-Envs-Action{0} ", returnStatus.Output)); returnStatus.ExitCode = 0; } catch (Exception ex) { Logger.Error("Error running get-gear-envs-actions command: {0} - {1}", ex.Message, ex.StackTrace); returnStatus.ExitCode = 1; } return(returnStatus); }
public string CreatePublicEndpoints(string cartName) { // currently on Windows private service ports are the same as public ports Manifest cart = Cartridge.GetCartridge(cartName); StringBuilder output = new StringBuilder(); Dictionary <string, string> env = Environ.ForGear(this.ContainerDir); foreach (Endpoint endpoint in cart.Endpoints) { string port = env[endpoint.PrivatePortName]; this.AddEnvVar(endpoint.PublicPortName, port); // TODO: will have to change this once prison is integrated Network.OpenFirewallPort(port, this.Uuid); output.Append(this.GenerateEndpointCreationNotificationMsg(cart, endpoint, "127.0.0.1", port)); } return(output.ToString()); }
private void CreateCartridgeDirectory(Manifest cartridge, string softwareVersion) { string target = Path.Combine(this.container.ContainerDir, cartridge.Dir); CartridgeRepository.InstantiateCartridge(cartridge, target); string ident = Manifest.BuildIdent(cartridge.CartridgeVendor, cartridge.Name, softwareVersion, cartridge.CartridgeVersion); Dictionary <string, string> envs = new Dictionary <string, string>(); envs[string.Format("{0}_DIR", cartridge.ShortName)] = target + Path.DirectorySeparatorChar; envs[string.Format("{0}_IDENT", cartridge.ShortName)] = ident; WriteEnvironmentVariables(Path.Combine(target, "env"), envs); envs = new Dictionary <string, string>(); if (!string.IsNullOrEmpty(this.container.Namespace)) { envs["namespace"] = this.container.Namespace; } Dictionary <string, string> currentGearEnv = Environ.ForGear(this.container.ContainerDir); if (!currentGearEnv.ContainsKey("OPENSHIFT_PRIMARY_CARTRIDGE_DIR")) { envs["PRIMARY_CARTRIDGE_DIR"] = target + Path.DirectorySeparatorChar; } if (envs.Count > 0) { WriteEnvironmentVariables(Path.Combine(this.container.ContainerDir, ".env"), envs); } var prison = Prison.Prison.LoadPrisonNoAttach(PrisonIdConverter.Generate(this.container.Uuid)); Logger.Debug("Setting permisions to dir {0}, prison user {1}", target, prison.User.Username); LinuxFiles.TakeOwnership(target, prison.User.Username); Logger.Info("Created cartridge directory {0}/{1}", container.Uuid, cartridge.Dir); }
public RubyHash UpdateProxyStatus(RubyHash options) { string action = options["action"]; if (action != "enable" && action != "disable") { throw new ArgumentException("action must either be :enable or :disable"); } if (options["gear_uuid"] == null) { throw new ArgumentException("gear_uuid is required"); } string gearUuid = options["gear_uuid"]; Manifest cartridge; if (options["cartridge"] == null) { cartridge = this.Cartridge.WebProxy(); } else { cartridge = options["cartridge"]; } if (cartridge == null) { throw new ArgumentException("Unable to update proxy status - no proxy cartridge found"); } dynamic persist = options["persist"]; Dictionary <string, string> gearEnv = Environ.ForGear(this.ContainerDir); RubyHash result = new RubyHash() { { "status", RESULT_SUCCESS }, { "target_gear_uuid", gearUuid }, { "proxy_results", new RubyHash() } }; RubyHash gearResult = new RubyHash(); if (gearEnv["OPENSHIFT_APP_DNS"] != gearEnv["OPENSHIFT_GEAR_DNS"]) { gearResult = this.UpdateLocalProxyStatus(new RubyHash() { { "cartridge", cartridge }, { "action", action }, { "proxy_gear", this.Uuid }, { "target_gear", gearUuid }, { "persist", persist } }); result["proxy_results"][this.Uuid] = gearResult; } else { // only update the other proxies if we're the currently elected proxy // TODO the way we determine this needs to change so gears other than // the initial proxy gear can be elected GearRegistry.Entry[] proxyEntries = this.gearRegistry.Entries["proxy"].Values.ToArray(); // TODO: vladi: Make this parallel RubyHash[] parallelResults = proxyEntries.Select(entry => this.UpdateRemoteProxyStatus(new RubyHash() { { "current_gear", this.Uuid }, { "proxy_gear", entry }, { "target_gear", gearUuid }, { "cartridge", cartridge }, { "action", action }, { "persist", persist }, { "gear_env", gearEnv } })).ToArray(); foreach (RubyHash parallelResult in parallelResults) { if (parallelResult.ContainsKey("proxy_results")) { result["proxy_results"] = result["proxy_results"].Merge(parallelResult["proxy_results"]); } else { result["proxy_results"][parallelResult["proxy_gear_uuid"]] = parallelResult; } } } // if any results failed, consider the overall operation a failure foreach (RubyHash proxyResult in result["proxy_results"].Values) { if (proxyResult["status"] != RESULT_SUCCESS) { result["status"] = RESULT_FAILURE; } } return(result); }
private RubyHash ActivateLocalGear(dynamic options) { string deploymentId = options["deployment_id"]; Logger.Debug("Activating local gear with deployment id {0}", deploymentId); RubyHash result = new RubyHash(); result["status"] = RESULT_FAILURE; result["gear_uuid"] = this.Uuid; result["deployment_id"] = deploymentId; result["messages"] = new List <string>(); result["errors"] = new List <string>(); if (!DeploymentExists(deploymentId)) { Logger.Warning("No deployment with id {0} found on gear", deploymentId); result["errors"].Add(string.Format("No deployment with id {0} found on gear", deploymentId)); return(result); } try { string deploymentDateTime = GetDeploymentDateTimeForDeploymentId(deploymentId); string deploymentDir = Path.Combine(this.ContainerDir, "app-deployments", deploymentDateTime); Dictionary <string, string> gearEnv = Environ.ForGear(this.ContainerDir); string output = string.Empty; Logger.Debug("Current deployment state for deployment {0} is {1}", deploymentId, this.State.Value()); if (Runtime.State.STARTED.EqualsString(State.Value())) { options["exclude_web_proxy"] = true; output = StopGear(options); result["messages"].Add(output); } SyncDeploymentRepoDirToRuntime(deploymentDateTime); SyncDeploymentDependenciesDirToRuntime(deploymentDateTime); SyncDeploymentBuildDependenciesDirToRuntime(deploymentDateTime); UpdateCurrentDeploymentDateTimeSymlink(deploymentDateTime); Manifest primaryCartridge = this.Cartridge.GetPrimaryCartridge(); this.Cartridge.DoControl("update-configuration", primaryCartridge); result["messages"].Add("Starting application " + ApplicationName); Dictionary <string, object> opts = new Dictionary <string, object>(); opts["secondary_only"] = true; opts["user_initiated"] = true; opts["hot_deploy"] = options["hot_deploy"]; output = StartGear(opts); result["messages"].Add(output); this.State.Value(Runtime.State.DEPLOYING); opts = new Dictionary <string, object>(); opts["pre_action_hooks_enabled"] = false; opts["prefix_action_hooks"] = false; output = this.Cartridge.DoControl("deploy", primaryCartridge, opts); result["messages"].Add(output); opts = new Dictionary <string, object>(); opts["primary_only"] = true; opts["user_initiated"] = true; opts["hot_deploy"] = options["hot_deploy"]; output = StartGear(opts); result["messages"].Add(output); opts = new Dictionary <string, object>(); opts["pre_action_hooks_enabled"] = false; opts["prefix_action_hooks"] = false; output = this.Cartridge.DoControl("post-deploy", primaryCartridge, opts); result["messages"].Add(output); if (options.ContainsKey("post_install")) { string primaryCartEnvDir = Path.Combine(this.ContainerDir, primaryCartridge.Dir, "env"); Dictionary <string, string> primaryCartEnv = Environ.Load(primaryCartEnvDir); string ident = (from kvp in primaryCartEnv where Regex.Match(kvp.Key, "^OPENSHIFT_.*_IDENT").Success select kvp.Value).FirstOrDefault(); string version = Manifest.ParseIdent(ident)[2]; this.Cartridge.PostInstall(primaryCartridge, version); } DeploymentMetadata deploymentMetadata = DeploymentMetadataFor(deploymentDateTime); deploymentMetadata.RecordActivation(); deploymentMetadata.Save(); if (options.ContainsKey("report_deployments") && gearEnv["OPENSHIFT_APP_DNS"] == gearEnv["OPENSHIFT_GEAR_DNS"]) { ReportDeployments(gearEnv); } result["status"] = RESULT_SUCCESS; } catch (Exception e) { result["status"] = RESULT_FAILURE; result["errors"].Add(string.Format("Error activating gear: {0}", e.ToString())); } return(result); }
private string Build(RubyHash options) { this.State.Value(Runtime.State.BUILDING); string deploymentDateTime = options["deployment_datetime"] != null ? options["deployment_datetime"] : LatestDeploymentDateTime(); DeploymentMetadata deploymentMetadata = DeploymentMetadataFor(deploymentDateTime); if (!options.ContainsKey("deployment_datetime")) { // this will execute if coming from a CI builder, since it doesn't // specify :deployment_datetime in the options hash throw new NotImplementedException(); } StringBuilder buffer = new StringBuilder(); if (deploymentMetadata.ForceCleanBuild) { buffer.AppendLine("Force clean build enabled - cleaning dependencies"); CleanRuntimeDirs(new RubyHash() { { "dependencies", true }, { "build_dependencies", true } }); this.Cartridge.EachCartridge(delegate(Manifest cartridge) { this.Cartridge.CreateDependencyDirectories(cartridge); }); } buffer.AppendLine(string.Format("Building git ref {0}, commit {1}", deploymentMetadata.GitRef, deploymentMetadata.GitSha)); Dictionary <string, string> env = Environ.ForGear(this.ContainerDir); int deploymentsToKeep = DeploymentsToKeep(env); try { Manifest primaryCartridge = this.Cartridge.GetPrimaryCartridge(); buffer.AppendLine(this.Cartridge.DoControl("update-configuration", primaryCartridge, new RubyHash() { { "pre_action_hooks_enabled", false }, { "post_action_hooks_enabled", false } })); buffer.AppendLine(this.Cartridge.DoControl("pre-build", primaryCartridge, new RubyHash() { { "pre_action_hooks_enabled", false }, { "post_action_hooks_enabled", false } })); buffer.AppendLine(this.Cartridge.DoControl("build", primaryCartridge, new RubyHash() { { "pre_action_hooks_enabled", false }, { "post_action_hooks_enabled", false } })); } catch (Exception ex) { buffer.AppendLine("Encountered a failure during build: " + ex.ToString()); if (deploymentsToKeep > 1) { buffer.AppendLine("Restarting application"); buffer.AppendLine(StartGear(new RubyHash() { { "user_initiated", true }, { "hot_deploy", deploymentMetadata.HotDeploy } })); } throw ex; } return(buffer.ToString()); }
protected override void ProcessRecord() { ReturnStatus returnStatus = new ReturnStatus(); try { NodeConfig config = new NodeConfig(); string gearPath = config.Get("GEAR_BASE_DIR"); string[] folders = Directory.GetDirectories(gearPath); List <RubyHash> endpoints = new List <RubyHash>(); RubyHash outputHash = new RubyHash(); foreach (string folder in folders) { string folderName = Path.GetFileName(folder); if (!folderName.StartsWith(".")) { ApplicationContainer container = ApplicationContainer.GetFromUuid(folderName); Dictionary <string, string> env = Environ.ForGear(container.ContainerDir); container.Cartridge.EachCartridge(cart => { cart.Endpoints.ForEach(endpoint => { RubyHash endpointHash = new RubyHash(); endpointHash.Add("cartridge_name", string.Format("{0}-{1}", cart.Name, cart.Version)); if (env.ContainsKey(endpoint.PublicPortName)) { endpointHash.Add("external_port", env[endpoint.PublicPortName]); } else { endpointHash.Add("external_port", null); } endpointHash.Add("internal_address", env[endpoint.PrivateIpName]); endpointHash.Add("internal_port", endpoint.PrivatePort); endpointHash.Add("protocols", endpoint.Protocols); endpointHash.Add("type", new List <string>()); if (cart.WebProxy) { endpointHash["protocols"] = container.Cartridge.GetPrimaryCartridge().Endpoints.First().Protocols; endpointHash["type"] = new List <string>() { "load_balancer" }; } else if (cart.WebFramework) { endpointHash["type"] = new List <string>() { "web_framework" }; } else if (cart.Categories.Contains("database")) { endpointHash["type"] = new List <string>() { "web_framework" }; } else if (cart.Categories.Contains("plugin")) { endpointHash["type"] = new List <string>() { "plugin" }; } else { endpointHash["type"] = new List <string>() { "other" }; } if (endpoint.Mappings != null && endpoint.Mappings.Count > 0) { List <RubyHash> mappingsList = new List <RubyHash>(); foreach (Uhuru.Openshift.Common.Models.Endpoint.Mapping mapping in endpoint.Mappings) { RubyHash mappings = new RubyHash(); mappings.Add("frontend", mapping.Frontend); mappings.Add("backend", mapping.Backend); mappingsList.Add(mappings); } endpointHash.Add("mappings", mappingsList); } endpoints.Add(endpointHash); }); }); if (endpoints.Count > 0) { outputHash.Add(folderName, endpoints); } } } string output = Newtonsoft.Json.JsonConvert.SerializeObject(outputHash); returnStatus.Output = output; returnStatus.ExitCode = 0; } catch (Exception ex) { Logger.Error("Error running get-all-gears-endpoints-action command: {0} - {1}", ex.Message, ex.StackTrace); returnStatus.Output = ex.ToString(); returnStatus.ExitCode = 1; } this.WriteObject(returnStatus); }