public static Step AddCommand(this Step step, string command, bool acceptParameter = false) { var commandStep = new CommandStep(command, acceptParameter); step.AddChildStep(commandStep); return(commandStep); }
public static StepCollection AddCommandWithParameter(this Step step, string command, ILocalizedString suggestParameterText) { var commandWithParameter = new CommandStep(command, true); var commandWithoutOfParameter = new CommandStep(command, false); commandWithoutOfParameter.EchoReply(suggestParameterText, EchoOptions.EchoForceReply()); var commandAwaitParameter = commandWithoutOfParameter.AddAnyInput(); step.AddChildStep(commandWithParameter); step.AddChildStep(commandWithoutOfParameter); return(new StepCollection(new[] { commandWithParameter, commandAwaitParameter })); }
public CommandStep AddCommandStep() { foreach (CommandStep s in commandSteps) { if (!s.activated) { s.activated = true; return(s); } } CommandStep nextStep = new CommandStep(commandSteps.Count); nextStep.activated = true; commandSteps.Add(nextStep); return(nextStep); }
/// <summary> /// Appends the steps required to start a neonHIVE related Docker container and upload /// a script to the hive managers to make it easy to restart the service manually or /// for hive updates. /// </summary> /// <param name="hive">The target hive.</param> /// <param name="steps">The target step list.</param> /// <param name="node">The target hive node.</param> /// <param name="containerName">Identifies the service.</param> /// <param name="image">The Docker image to be used by the container.</param> /// <param name="command">The <c>docker service create ...</c> command.</param> /// <param name="runOptions">Optional run options (defaults to <see cref="RunOptions.FaultOnError"/>).</param> /// <remarks> /// <para> /// This method performs the following steps: /// </para> /// <list type="number"> /// <item> /// Passes <paramref name="image"/> to <see cref="Program.ResolveDockerImage(string)"/> to /// obtain the actual image to be started. /// </item> /// <item> /// Generates the first few lines of the script file that sets the /// default image as the <c>TARGET_IMAGE</c> macro and then overrides /// this with the script parameter (if there is one). We also add /// a Docker command that pulls the image. /// </item> /// <item> /// Appends the commands to the script, replacing any text that matches /// <see cref="ImagePlaceholderArg"/> with <c>${TARGET_IMAGE}</c> to make it easy /// for services to be upgraded later. /// </item> /// <item> /// Starts the service. /// </item> /// <item> /// Uploads the generated script to each hive manager to [<see cref="HiveHostFolders.Scripts"/>/<paramref name="containerName"/>.sh]. /// </item> /// </list> /// </remarks> public static void AddContainerStartSteps(HiveProxy hive, ConfigStepList steps, SshProxy <NodeDefinition> node, string containerName, string image, IBashCommandFormatter command, RunOptions runOptions = RunOptions.FaultOnError) { Covenant.Requires <ArgumentNullException>(hive != null); Covenant.Requires <ArgumentNullException>(steps != null); Covenant.Requires <ArgumentNullException>(!string.IsNullOrWhiteSpace(containerName)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrWhiteSpace(image)); Covenant.Requires <ArgumentNullException>(command != null); // Generate the container start script. var script = CreateStartScript(containerName, image, true, command); // Add steps to upload the script to the managers and then call the script // to create the container on the target node. var scriptPath = LinuxPath.Combine(HiveHostFolders.Scripts, $"{containerName}.sh"); steps.Add(hive.GetFileUploadSteps(node, scriptPath, script, permissions: "740")); steps.Add(CommandStep.CreateIdempotentDocker(node.Name, $"setup/{containerName}", scriptPath)); }
/// <summary> /// Appends the steps required to start a neonHIVE related Docker service and upload /// a script to the hive managers to make it easy to restart the service manually or /// for hive updates. /// </summary> /// <param name="hive">The target hive.</param> /// <param name="steps">The target step list.</param> /// <param name="serviceName">Identifies the service.</param> /// <param name="image">The Docker image to be used by the service.</param> /// <param name="command">The <c>docker service create ...</c> command.</param> /// <param name="runOptions">Optional run options (defaults to <see cref="RunOptions.FaultOnError"/>).</param> /// <remarks> /// <para> /// This method performs the following steps: /// </para> /// <list type="number"> /// <item> /// Passes <paramref name="image"/> to <see cref="Program.ResolveDockerImage(string)"/> to /// obtain the actual image to be started. /// </item> /// <item> /// Generates the first few lines of the script file that sets the /// default image as the <c>TARGET_IMAGE</c> macro and then overrides /// this with the script parameter (if there is one). /// </item> /// <item> /// Appends the commands to the script, replacing any text that matches /// <see cref="ImagePlaceholderArg"/> with <c>${TARGET_IMAGE}</c> to make it easy /// for services to be upgraded later. /// </item> /// <item> /// Starts the service. /// </item> /// <item> /// Uploads the generated script to each hive manager to [<see cref="HiveHostFolders.Scripts"/>/<paramref name="serviceName"/>.sh]. /// </item> /// </list> /// </remarks> public static void AddServiceStartSteps(HiveProxy hive, ConfigStepList steps, string serviceName, string image, IBashCommandFormatter command, RunOptions runOptions = RunOptions.FaultOnError) { Covenant.Requires <ArgumentNullException>(hive != null); Covenant.Requires <ArgumentNullException>(steps != null); Covenant.Requires <ArgumentNullException>(!string.IsNullOrWhiteSpace(serviceName)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrWhiteSpace(image)); Covenant.Requires <ArgumentNullException>(command != null); // Generate the service start script. var script = CreateStartScript(serviceName, image, false, command); // Add steps to upload the script to the managers and then call the script // to create the service on the first manager. var scriptPath = LinuxPath.Combine(HiveHostFolders.Scripts, $"{serviceName}.sh"); steps.Add(hive.GetFileUploadSteps(hive.Managers, scriptPath, script, permissions: "740")); steps.Add(CommandStep.CreateIdempotentDocker(hive.FirstManager.Name, $"setup/{serviceName}", scriptPath)); }
void CheckProcessorsFor(CommandAction action) { if (action == null) { return; } List <CommandStep> steps = action.steps; for (int s = 0; s < steps.Count; s++) { CommandStep step = steps[s]; for (int i = 0; i < processors.Count; i++) { Processor currentProc = processors[i]; if (currentProc.IsSupported(step.Key)) { currentProc.Process(step); } } } }
private void OnGUI() { //GUI.DrawTexture(new Rect(0,0,maxSize.x,maxSize.y), Texture2D.blackTexture,ScaleMode.StretchToFill); if (coreData == null) { foreach (string guid in AssetDatabase.FindAssets("t: CoreData")) { coreData = AssetDatabase.LoadAssetAtPath <CoreData>(AssetDatabase.GUIDToAssetPath(guid)); } } MoveList currentMovelist = coreData.moveLists[coreData.currentMovelistIndex]; GUILayout.Label(""); currentMovelist.name = GUILayout.TextField(currentMovelist.name); coreData.currentMovelistIndex = Mathf.Clamp(coreData.currentMovelistIndex, 0, coreData.moveLists.Count - 1); GUILayout.BeginHorizontal(); coreData.currentMovelistIndex = GUILayout.Toolbar(coreData.currentMovelistIndex, coreData.GetMovelistNames()); if (GUILayout.Button("New Move List", GUILayout.Width(175))) { coreData.moveLists.Add(new MoveList()); } GUILayout.EndHorizontal(); CommandState currentCommandStateObject = currentMovelist.commandStates[currentCommandStateIndex]; currentCommandStateIndex = Mathf.Clamp(currentCommandStateIndex, 0, currentMovelist.commandStates.Count - 1); GUILayout.BeginHorizontal(); currentCommandStateIndex = GUILayout.Toolbar(currentCommandStateIndex, coreData.GetCommandStateNames()); if (GUILayout.Button("New Command State", GUILayout.Width(175))) { currentMovelist.commandStates.Add(new CommandState()); } GUILayout.EndHorizontal(); currentCommandStateObject.stateName = GUILayout.TextField(currentCommandStateObject.stateName, GUILayout.Width(200)); //coreData.commandStates[currentCommandState].stateName = GUI.TextField(new Rect(0, 0, 300, 50), coreData.commandStates[currentCommandState].stateName); GUILayout.BeginHorizontal(); if (GUILayout.Button("Add Command", GUILayout.Width(120))) { if (currentCommandStateObject.commandSteps == null) { currentCommandStateObject.commandSteps = new List <CommandStep>(); } currentCommandStateObject.AddCommandStep(); currentCommandStateObject.CleanUpBaseState(); //coreData.commandStates[currentCommandState].chainSteps.Add(new ChainStep(coreData.commandStates[currentCommandState].chainSteps.Count)); } GUILayout.Label("Draw Style:", GUILayout.Width(75)); currentLineType = (LineDrawType)EditorGUILayout.EnumPopup(currentLineType, GUILayout.Width(150)); drawBaseToggle = GUILayout.Toggle(drawBaseToggle, "Draw Base Node", EditorStyles.miniButton, GUILayout.Width(150)); if (drawBaseToggle) { drawBase = -1; } else { drawBase = 0; } GUILayout.EndHorizontal(); scrollView = EditorGUILayout.BeginScrollView(scrollView); GUILayout.Label("", GUILayout.Height(2000), GUILayout.Width(2000)); //draw your nodes here Handles.BeginGUI(); int sCounter = 0; //foreach (CommandStep s in coreData.commandStates[currentCommandState].commandSteps) foreach (CommandStep s in currentCommandStateObject.commandSteps) { if (sCounter > drawBase) { int deleteMe = -1; int fCounter = 0; foreach (int f in s.followUps) { CommandStep t = currentCommandStateObject.commandSteps[f]; if (t.activated) { switch (currentLineType) { case LineDrawType.CENTER: Handles.DrawBezier( s.myRect.center, t.myRect.center, s.myRect.center, t.myRect.center, Color.white, null, 3f); break; case LineDrawType.END_TO_END: Handles.DrawBezier( new Vector2(s.myRect.xMax - 2f, s.myRect.center.y), new Vector2(t.myRect.xMin + 2, t.myRect.center.y), new Vector2(s.myRect.xMax, s.myRect.center.y), new Vector2(t.myRect.xMin, t.myRect.center.y), Color.white, null, 3f); break; case LineDrawType.BEZIER_END_TO_END: Handles.DrawBezier( new Vector2(s.myRect.xMax - 2f, s.myRect.center.y), new Vector2(t.myRect.xMin + 2f, t.myRect.center.y), new Vector2(s.myRect.xMax + 30f, s.myRect.center.y), new Vector2(t.myRect.xMin - 30f, t.myRect.center.y), Color.white, null, 3f); break; } if (GUI.Button(new Rect((t.myRect.center + s.myRect.center) * 0.5f + (xButton * -0.5f), xButton), "X")) { deleteMe = fCounter; } } fCounter++; } if (deleteMe > -1) { s.followUps.RemoveAt(deleteMe); currentCommandStateObject.CleanUpBaseState(); } } sCounter++; } Handles.EndGUI(); BeginWindows(); sizerStep = 30; //GUI.backgroundColor = Color.black; int cCounter = 0; foreach (CommandStep c in currentCommandStateObject.commandSteps) { if (c.activated && cCounter > drawBase) { c.myRect = GUI.Window(c.idIndex, c.myRect, WindowFunction, "", EditorStyles.miniButton); } cCounter++; } EndWindows(); EditorGUILayout.EndScrollView(); EditorUtility.SetDirty(coreData); }
void WindowFunction(int windowID) { MoveList currentMoveList = coreData.moveLists[coreData.currentMovelistIndex]; CommandState currentCommandStateObject = currentMoveList.commandStates[currentCommandStateIndex]; if (currentCommandStateIndex >= currentMoveList.commandStates.Count) { currentCommandStateIndex = 0; } if (windowID >= currentCommandStateObject.commandSteps.Count) { return; } currentCommandStateObject.commandSteps[windowID].myRect.width = 175; currentCommandStateObject.commandSteps[windowID].myRect.height = 50; EditorGUI.LabelField(new Rect(6, 7, 35, 20), windowID.ToString()); currentCommandStateObject.commandSteps[windowID].command.motionCommand = EditorGUI.IntPopup(new Rect(25, 5, 50, 20), currentCommandStateObject.commandSteps[windowID].command.motionCommand, coreData.GetMotionCommandNames(), null, EditorStyles.miniButtonLeft); currentCommandStateObject.commandSteps[windowID].command.input = EditorGUI.IntPopup(new Rect(75, 5, 65, 20), currentCommandStateObject.commandSteps[windowID].command.input, coreData.GetRawInputNames(), null, EditorStyles.miniButtonMid); currentCommandStateObject.commandSteps[windowID].command.state = EditorGUI.IntPopup(new Rect(40, 26, 70, 20), currentCommandStateObject.commandSteps[windowID].command.state, coreData.GetStateNames(), null, EditorStyles.miniButton); currentCommandStateObject.commandSteps[windowID].priority = EditorGUI.IntField(new Rect(6, 26, 20, 20), currentCommandStateObject.commandSteps[windowID].priority); int nextFollowup = -1; nextFollowup = EditorGUI.IntPopup(new Rect(150, 15, 21, 20), nextFollowup, coreData.GetFollowUpNames(currentCommandStateIndex, true), null, EditorStyles.miniButton); if (nextFollowup != -1) { if (currentCommandStateObject.commandSteps.Count > 0) { if (nextFollowup >= currentCommandStateObject.commandSteps.Count + 1) { currentCommandStateObject.RemoveChainCommands(windowID); } else if (nextFollowup >= currentCommandStateObject.commandSteps.Count) { CommandStep nextCommand = currentCommandStateObject.AddCommandStep(); nextCommand.myRect.x = currentCommandStateObject.commandSteps[windowID].myRect.xMax + 40f; nextCommand.myRect.y = currentCommandStateObject.commandSteps[windowID].myRect.center.y - 15f; nextCommand.command.input = currentCommandStateObject.commandSteps[windowID].command.input; nextCommand.command.state = currentCommandStateObject.commandSteps[windowID].command.state; currentCommandStateObject.commandSteps[windowID].AddFollowUp(nextCommand.idIndex); } else { currentCommandStateObject.commandSteps[windowID].AddFollowUp(nextFollowup); } } else { currentCommandStateObject.commandSteps[windowID].AddFollowUp(nextFollowup); } currentCommandStateObject.CleanUpBaseState(); } if ((Event.current.button == 0) && (Event.current.type == EventType.MouseDown)) { currentChainStep = windowID; } GUI.DragWindow(); }
void UpdateInput() { inputBuffer.Update(); bool startState = false; GetCommandState(); CommandState comState = GameEngine.gameEngine.CurrentMoveList().commandStates[currentCommandState]; if (currentCommandStep >= comState.commandSteps.Count) { currentCommandStep = 0; } cancelStepList[0] = currentCommandStep;//base sub-state cancelStepList[1] = 0; int finalS = -1; int finalF = -1; int currentPriority = -1; for (int s = 0; s < cancelStepList.Length; s++) { if (comState.commandSteps[currentCommandStep].strict && s > 0) { break; } if (!comState.commandSteps[currentCommandStep].activated) { break; } for (int f = 0; f < comState.commandSteps[cancelStepList[s]].followUps.Count; f++)// (CommandStep cStep in comState.commandSteps[currentCommandStep]) { CommandStep nextStep = comState.commandSteps[comState.commandSteps[cancelStepList[s]].followUps[f]]; InputCommand nextCommand = nextStep.command; //if(inputBuffer.) if (CheckInputCommand(nextCommand)) { if (canCancel) { if (GameEngine.coreData.characterStates[nextCommand.state].ConditionsMet(this)) { if (nextStep.priority > currentPriority) { currentPriority = nextStep.priority; startState = true; finalS = s; finalF = f; } } } } } } if (startState) { CommandStep nextStep = comState.commandSteps[comState.commandSteps[cancelStepList[finalS]].followUps[finalF]]; InputCommand nextCommand = nextStep.command; inputBuffer.UseInput(nextCommand.input); if (nextStep.followUps.Count > 0) { currentCommandStep = nextStep.idIndex; } else { currentCommandStep = 0; } StartState(nextCommand.state); } }
/// <summary> /// Adds the steps to configure the stateful Elasticsearch instances used to persist the log data. /// </summary> /// <param name="steps">The configuration step list.</param> private void AddElasticsearchSteps(ConfigStepList steps) { var esNodes = new List <SshProxy <NodeDefinition> >(); foreach (var nodeDefinition in hive.Definition.Nodes.Where(n => n.Labels.LogEsData)) { esNodes.Add(hive.GetNode(nodeDefinition.Name)); } // Determine number of manager nodes and the quorum size. // Note that we'll deploy an odd number of managers. var managerCount = Math.Min(esNodes.Count, 5); // We shouldn't ever need more than 5 managers if (!NeonHelper.IsOdd(managerCount)) { managerCount--; } var quorumCount = (managerCount / 2) + 1; // Sort the nodes by name and then separate the manager and // worker nodes (managers will be assigned to nodes that appear // first in the list). var managerEsNodes = new List <SshProxy <NodeDefinition> >(); var normalEsNodes = new List <SshProxy <NodeDefinition> >(); esNodes = esNodes.OrderBy(n => n.Name).ToList(); foreach (var esNode in esNodes) { if (managerEsNodes.Count < managerCount) { managerEsNodes.Add(esNode); } else { normalEsNodes.Add(esNode); } } // Figure out how much RAM to allocate to the Elasticsearch Docker containers // as well as Java heap within. The guidance is to set the heap size to half // the container RAM up to a maximum of 31GB. var esContainerRam = hive.Definition.Log.EsMemoryBytes; var esHeapBytes = Math.Min(esContainerRam / 2, 31L * NeonHelper.Giga); // We're going to use explicit docker commands to deploy the Elasticsearch cluster // log storage containers. // // We're mounting three volumes to the container: // // /etc/neon/host-env - Generic host specific environment variables // /etc/neon/env-log-esdata - Elasticsearch node host specific environment variables // neon-log-esdata-# - Persistent Elasticsearch data folder var esBootstrapNodes = new StringBuilder(); foreach (var esMasterNode in managerEsNodes) { esBootstrapNodes.AppendWithSeparator($"{esMasterNode.PrivateAddress}:{HiveHostPorts.LogEsDataTcp}", ","); } // Create a data volume for each Elasticsearch node and then start the node container. for (int i = 0; i < esNodes.Count; i++) { var esNode = esNodes[i]; var containerName = $"neon-log-esdata"; var isMaster = managerEsNodes.Contains(esNode) ? "true" : "false"; var volumeCommand = CommandStep.CreateSudo(esNode.Name, "docker-volume-create", containerName); steps.Add(volumeCommand); ServiceHelper.AddContainerStartSteps(hive, steps, esNode, containerName, hive.Definition.Image.Elasticsearch, new CommandBundle( "docker run", "--name", containerName, "--detach", "--restart", "always", "--volume", "/etc/neon/host-env:/etc/neon/host-env:ro", "--volume", $"{containerName}:/mnt/esdata", "--env", $"ELASTICSEARCH_CLUSTER={hive.Definition.Datacenter}.{hive.Definition.Name}.neon-log-esdata", "--env", $"ELASTICSEARCH_NODE_MASTER={isMaster}", "--env", $"ELASTICSEARCH_NODE_DATA=true", "--env", $"ELASTICSEARCH_NODE_COUNT={esNodes.Count}", "--env", $"ELASTICSEARCH_HTTP_PORT={HiveHostPorts.LogEsDataHttp}", "--env", $"ELASTICSEARCH_TCP_PORT={HiveHostPorts.LogEsDataTcp}", "--env", $"ELASTICSEARCH_QUORUM={quorumCount}", "--env", $"ELASTICSEARCH_BOOTSTRAP_NODES={esBootstrapNodes}", "--env", $"ES_JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap", "--memory", $"{esContainerRam / NeonHelper.Mega}M", "--memory-reservation", $"{esContainerRam / NeonHelper.Mega}M", "--memory-swappiness", "0", "--network", "host", "--log-driver", "json-file", // Ensure that we don't log to the pipeline to avoid cascading events. ServiceHelper.ImagePlaceholderArg)); } // Configure a private hive proxy route to the Elasticsearch nodes. steps.Add(ActionStep.Create(hive.FirstManager.Name, "setup/elasticsearch-lbrule", node => { var rule = new TrafficHttpRule() { Name = "neon-log-esdata", System = true, Log = false, // This is important: we don't want to SPAM the log database with its own traffic. Resolver = null }; rule.Frontends.Add( new TrafficHttpFrontend() { ProxyPort = HiveHostPorts.ProxyPrivateHttpLogEsData }); foreach (var esNode in esNodes) { rule.Backends.Add( new TrafficHttpBackend() { Server = esNode.Metadata.PrivateAddress.ToString(), Port = HiveHostPorts.LogEsDataHttp }); } hive.PrivateTraffic.SetRule(rule); })); // Wait for the elasticsearch cluster to become ready and then save the // [logstash-*] template. We need to do this before [neon-log-collector] // is started so we'll be sure that no indexes will be created before // we have a chance to persist the pattern. // // This works because [neon-log-collector] is the main service responsible // for persisting events to this index. steps.Add(ActionStep.Create(hive.FirstManager.Name, operationName: null, node => { node.Status = "wait for elasticsearch cluster"; using (var jsonClient = new JsonClient()) { var baseLogEsDataUri = hive.Definition.LogEsDataUri; var timeout = TimeSpan.FromMinutes(5); var timeoutTime = DateTime.UtcNow + timeout; var esNodeCount = hive.Definition.Nodes.Count(n => n.Labels.LogEsData); // Wait for the Elasticsearch cluster. jsonClient.UnsafeRetryPolicy = NoRetryPolicy.Instance; while (true) { try { var response = jsonClient.GetUnsafeAsync($"{baseLogEsDataUri}/_cluster/health").Result; if (response.IsSuccess) { var clusterStatus = response.AsDynamic(); var status = (string)(clusterStatus.status); status = status.ToUpperInvariant(); node.Status = $"wait for [neon-log-esdata] cluster: [status={status}] [{clusterStatus.number_of_nodes}/{esNodeCount} nodes ready])"; // $todo(jeff.lill): // // We're accepting YELLOW status here due to this issue: // // https://github.com/jefflill/NeonForge/issues/257 if ((status == "GREEN" || status == "YELLOW") && clusterStatus.number_of_nodes == esNodeCount) { node.Status = "elasticsearch cluster is ready"; break; } } } catch { if (DateTime.UtcNow >= timeoutTime) { node.Fault($"[neon-log-esdata] cluster not ready after waiting [{timeout}]."); return; } } Thread.Sleep(TimeSpan.FromSeconds(1)); } // Save the [logstash-*] template pattern. var templatePattern = ResourceFiles.Root.GetFolder("Elasticsearch").GetFile("logstash-template.json").Contents; jsonClient.PutAsync($"{baseLogEsDataUri}/_template/logstash-*", templatePattern).Wait(); } })); }