Example #1
0
        /// <summary>
        /// Updates a service or container start script on a hive node with a new image.
        /// </summary>
        /// <param name="node">The target hive node.</param>
        /// <param name="scriptName">The script name (without the <b>.sh</b>).</param>
        /// <param name="image">The fully qualified image name.</param>
        private static void UpdateStartScript(SshProxy <NodeDefinition> node, string scriptName, string image)
        {
            var scriptPath = LinuxPath.Combine(HiveHostFolders.Scripts, $"{scriptName}.sh");

            node.Status = $"edit: {scriptPath}";

            if (node.FileExists(scriptPath))
            {
                var curScript   = node.DownloadText(scriptPath);
                var sbNewScript = new StringBuilder();

                // Scan for the generated code section and then replace the first
                // line that looks like:
                //
                //      TARGET_IMAGE=OLD-IMAGE
                //
                // with the new image and then upload the change.

                using (var reader = new StringReader(curScript))
                {
                    var inGenerated = false;
                    var wasEdited   = false;

                    foreach (var line in reader.Lines())
                    {
                        if (wasEdited)
                        {
                            sbNewScript.AppendLine(line);
                            continue;
                        }

                        if (!inGenerated && line.StartsWith(ServiceHelper.ParamSectionMarker))
                        {
                            inGenerated = true;
                        }

                        if (line.StartsWith("TARGET_IMAGE="))
                        {
                            sbNewScript.AppendLine($"TARGET_IMAGE={image}");
                            wasEdited = true;
                        }
                        else
                        {
                            sbNewScript.AppendLine(line);
                        }
                    }
                }

                node.UploadText(scriptPath, sbNewScript.ToString(), permissions: "740");
            }

            node.Status = string.Empty;
        }
Example #2
0
        /// <summary>
        /// Update the Elasticsearch container launch scripts to enable automatic
        /// memory settings based on any cgroup limits.
        /// </summary>
        /// <param name="node">The target node.</param>
        private void UpdateElasticsearch(SshProxy <NodeDefinition> node)
        {
            // This method is called for all cluster nodes, even those
            // that aren't currently hosting Elasticsearch, so we can
            // update any scripts that may have been orphaned (for
            // consistency).
            //
            // The update consists of replacing the script line that
            // sets the [ES_JAVA_OPTS] environment variable with:
            //
            //      --env ES_JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap \
            //
            // To ensure that this feature is enabled in favor of the
            // old hacked memory level settings.

            var scriptPath = LinuxPath.Combine(HiveHostFolders.Scripts, "neon-log-esdata.sh");

            node.InvokeIdempotentAction(GetIdempotentTag("neon-log-esdata"),
                                        () =>
            {
                if (node.FileExists(scriptPath))
                {
                    node.Status = $"edit: {scriptPath}";

                    var orgScript = node.DownloadText(scriptPath);
                    var newScript = new StringBuilder();

                    foreach (var line in new StringReader(orgScript).Lines())
                    {
                        if (line.Contains("ES_JAVA_OPTS="))
                        {
                            newScript.AppendLine("    --env \"ES_JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap\" \\");
                        }
                        else
                        {
                            newScript.AppendLine(line);
                        }
                    }

                    node.UploadText(scriptPath, newScript.ToString(), permissions: "");

                    node.Status = string.Empty;
                }
            });
        }
Example #3
0
        /// <summary>
        /// Initializes a near virgin server with the basic capabilities required
        /// for a cluster host node.
        /// </summary>
        /// <param name="node">The target cluster node.</param>
        /// <param name="clusterDefinition">The cluster definition.</param>
        /// <param name="kubeSetupInfo">Kubernetes setup details.</param>
        /// <param name="shutdown">Optionally shuts down the node.</param>
        public static void PrepareNode(SshProxy <NodeDefinition> node, ClusterDefinition clusterDefinition, KubeSetupInfo kubeSetupInfo, bool shutdown = false)
        {
            Covenant.Requires <ArgumentNullException>(node != null);
            Covenant.Requires <ArgumentNullException>(clusterDefinition != null);
            Covenant.Requires <ArgumentNullException>(kubeSetupInfo != null);

            if (node.FileExists($"{KubeHostFolders.State}/setup/prepared"))
            {
                return;     // Already prepared
            }

            //-----------------------------------------------------------------
            // Ensure that the cluster host folders exist.

            node.CreateHostFolders();

            //-----------------------------------------------------------------
            // Package manager configuration.

            if (!clusterDefinition.NodeOptions.AllowPackageManagerIPv6)
            {
                // Restrict the [apt] package manager to using IPv4 to communicate
                // with the package mirrors, since IPv6 often doesn't work.

                node.UploadText("/etc/apt/apt.conf.d/99-force-ipv4-transport", "Acquire::ForceIPv4 \"true\";");
                node.SudoCommand("chmod 644 /etc/apt/apt.conf.d/99-force-ipv4-transport");
            }

            // Configure [apt] to retry.

            node.UploadText("/etc/apt/apt.conf.d/99-retries", $"APT::Acquire::Retries \"{clusterDefinition.NodeOptions.PackageManagerRetries}\";");
            node.SudoCommand("chmod 644 /etc/apt/apt.conf.d/99-retries");

            //-----------------------------------------------------------------
            // Other configuration.

            ConfigureOpenSSH(node, TimeSpan.Zero);
            node.UploadConfigFiles(clusterDefinition, kubeSetupInfo);
            node.UploadResources(clusterDefinition, kubeSetupInfo);

            if (clusterDefinition != null)
            {
                ConfigureEnvironmentVariables(node, clusterDefinition);
            }

            node.SudoCommand("safe-apt-get update");

            node.InvokeIdempotentAction("setup/prep-node",
                                        () =>
            {
                node.Status = "preparing";
                node.SudoCommand("setup-prep.sh");
                node.Reboot(wait: true);
            });

            // We need to upload the cluster configuration and initialize drives attached
            // to the node.  We're going to assume that these are not already initialized.

            // $todo(jeff.lill):
            //
            // We may need an option that allows an operator to pre-build a hardware
            // based drive array or something.  I'm going to defer this to later and
            // concentrate on commodity hardware and cloud deployments for now.

            CommonSteps.ConfigureEnvironmentVariables(node, clusterDefinition);

            node.Status = "setup: disk";
            node.SudoCommand("setup-disk.sh");

            // Clear any DHCP leases to be super sure that cloned node
            // VMs will obtain fresh IP addresses.

            node.Status = "clear: DHCP leases";
            node.SudoCommand("rm -f /var/lib/dhcp/*");

            // Indicate that the node has been fully prepared.

            node.SudoCommand($"touch {KubeHostFolders.State}/setup/prepared");

            // Shutdown the node if requested.

            if (shutdown)
            {
                node.Status = "shutdown";
                node.SudoCommand("shutdown 0", RunOptions.Defaults | RunOptions.Shutdown);
            }
        }