Ejemplo n.º 1
0
        /// <summary>
        /// Updates the hive services and containers.
        /// </summary>
        /// <param name="force"><c>true</c> to disable the update prompt.</param>
        /// <param name="maxParallel">Maximum number of parallel operations.</param>
        /// <param name="imageTag">Optionally overrides the default image tag.</param>
        private void UpdateServices(bool force, int maxParallel, string imageTag = null)
        {
            EnsureRootPivileges();

            if (!force && !Program.PromptYesNo($"*** Are you sure you want to UPDATE HIVE services on [{hive.Name}]?"))
            {
                Program.Exit(0);
            }

            var controller = new SetupController <NodeDefinition>("hive update images", hive.Nodes)
            {
                MaxParallel = maxParallel,
                ShowStatus  = true
            };

            controller.SetDefaultRunOptions(RunOptions.FaultOnError);

            HiveUpdateManager.AddHiveUpdateSteps(hive, controller, out var restartRequired, servicesOnly: true, serviceUpdateParallism: Program.MaxParallel, imageTag: imageTag);

            if (controller.StepCount == 0)
            {
                Console.WriteLine("The hive is already up-to-date.");
                Program.Exit(0);
            }

            if (!controller.Run())
            {
                Console.Error.WriteLine("*** ERROR: One or more UPDATE steps failed.");
                Program.Exit(1);
            }

            Console.WriteLine();
            Console.WriteLine("*** Hive services and containers were updated successfully.");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Updates the hive hive configuration, services and containers.
        /// </summary>
        /// <param name="force"><c>true</c> to disable the update prompt.</param>
        /// <param name="maxParallel">Maximum number of parallel operations.</param>
        /// <param name="imageTag">Optionally overrides the default image tag.</param>
        private void UpdateHive(bool force, int maxParallel, string imageTag = null)
        {
            EnsureRootPivileges();

            if (!force && !Program.PromptYesNo($"*** Are you sure you want to UPDATE HIVE components and services on [{hive.Name}]?"))
            {
                Program.Exit(0);
            }

            var controller = new SetupController <NodeDefinition>("hive update", hive.Nodes)
            {
                ShowStatus = !Program.Quiet
            };

            controller.MaxParallel = maxParallel;
            controller.SetDefaultRunOptions(RunOptions.FaultOnError);

            var hiveUpdateCount = HiveUpdateManager.AddHiveUpdateSteps(hive, controller, out var restartRequired, serviceUpdateParallism: Program.MaxParallel, imageTag: imageTag);

            if (controller.StepCount == 0)
            {
                Console.WriteLine("The hive is already up-to-date.");
                Program.Exit(0);
            }

            if (!controller.Run())
            {
                Console.Error.WriteLine("*** ERROR: One or more UPDATE steps failed.");
                Program.Exit(1);
            }

            Console.WriteLine();
            Console.WriteLine("*** Hive components, services, and containers were updated successfully.");

            if (hive.Globals.TryGetBool(HiveGlobals.UserDisableAutoUnseal, out var disableAutoUnseal) || !disableAutoUnseal)
            {
                Console.WriteLine();
                Console.WriteLine("*** WARNING: The hive Vault is probably sealed now because auto-unseal is disabled.");
                Console.WriteLine();
                Console.WriteLine("Use these command to check Vault status and manually unseal if necessary:");
                Console.WriteLine();
                Console.WriteLine("    neon vault -- status");
                Console.WriteLine("    Neon vault -- unseal");
                Console.WriteLine();
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Checks the hive for pending updates.
        /// </summary>
        /// <param name="maxParallel">Maximum number of parallel operations.</param>
        private void CheckHive(int maxParallel)
        {
            EnsureRootPivileges();

            // Use a temporary controller to determine how  many hive
            // updates are pending.

            var controller = new SetupController <NodeDefinition>("hive update check", hive.Nodes)
            {
                MaxParallel = maxParallel,
                ShowStatus  = !Program.Quiet
            };

            controller.SetDefaultRunOptions(RunOptions.FaultOnError);

            var hiveUpdateCount = HiveUpdateManager.AddHiveUpdateSteps(hive, controller, out var restartRequired, serviceUpdateParallism: Program.MaxParallel);

            // Create another controller to actually scan the hive nodes to
            // count the pending Linux updates as well as the system containers
            // and services that need to be updated.

            // $todo(jeff.lill):
            //
            // We need to query a new image lookup service to get the images
            // compatible with the hive and then determine whether any of
            // these need updating on any node.  Right now, we're just checking
            // the Linux package updates.
            //
            // We should do something similar for the host services like:
            // consul, docker, powerdns, and vault.

            controller = new SetupController <NodeDefinition>("hive update check", hive.Nodes)
            {
                MaxParallel = maxParallel,
                ShowStatus  = !Program.Quiet
            };

            controller.SetDefaultRunOptions(RunOptions.FaultOnError);

            var syncLock           = new object();
            var maxUpdates         = 0;
            var maxSecurityUpdates = 0;
            var componentInfo      = hive.Headend.GetComponentInfo(hive.Globals.Version, ThisAssembly.Git.Branch);
            var dockerVersions     = new Dictionary <SemanticVersion, int>();   // Counts the numbers versions installed
            var consulVersions     = new Dictionary <SemanticVersion, int>();   // on hive nodes.
            var vaultVersions      = new Dictionary <SemanticVersion, int>();

            controller.AddStep("scan hive",
                               (node, stepDelay) =>
            {
                Thread.Sleep(stepDelay);

                //---------------------------------------------------------
                // Look for Linux package updates.

                node.Status = "run: safe-apt-get update";
                node.SudoCommand("safe-apt-get update");

                node.Status  = "run: apt-check";
                var response = node.SudoCommand("/usr/lib/update-notifier/apt-check");

                // This command returns the total number of updates and
                // the security updates like: TOTAL;SECURITY.

                var fields = response.ErrorText.Trim().Split(';');

                if (fields.Length < 2 || !int.TryParse(fields[0], out var updates) || !int.TryParse(fields[1], out var securityUpdates))
                {
                    node.Fault($"Unexpected update response: {response.OutputText}");
                    return;
                }

                lock (syncLock)
                {
                    maxUpdates         = Math.Max(maxUpdates, updates);
                    maxSecurityUpdates = Math.Max(maxSecurityUpdates, securityUpdates);
                }

                //---------------------------------------------------------
                // Determine the versions of Docker, Consul, and Vault installed
                // on this node and tally the versions for the hive.  Note that
                // it's possible for multiple versions of a compontent to be
                // installed on different nodes if a previous update did not
                // run until completion.

                node.Status       = "docker version";
                var dockerVersion = node.GetDockerVersion(faultIfNotInstalled: true);

                node.Status       = "consul version";
                var consulVersion = node.GetConsulVersion(faultIfNotInstalled: true);

                node.Status      = "vault version";
                var vaultVersion = node.GetVaultVersion(faultIfNotInstalled: true);

                if (!node.IsFaulted)
                {
                    lock (syncLock)
                    {
                        int count;

                        if (!dockerVersions.TryGetValue(dockerVersion, out count))
                        {
                            count = 0;
                        }

                        dockerVersions[dockerVersion] = count + 1;

                        if (!consulVersions.TryGetValue(consulVersion, out count))
                        {
                            count = 0;
                        }

                        consulVersions[consulVersion] = count + 1;

                        if (!vaultVersions.TryGetValue(vaultVersion, out count))
                        {
                            count = 0;
                        }

                        vaultVersions[vaultVersion] = count + 1;
                    }
                }
            });

            if (!controller.Run())
            {
                Console.Error.WriteLine("*** ERROR: One or more CHECK steps failed.");
                Program.Exit(1);
            }

            // Output the results.

            var title = $"[{hive.Name}] hive";

            Console.WriteLine();
            Console.WriteLine(title);
            Console.WriteLine(new string('-', title.Length));

            var restartStatus       = restartRequired ? "    *** hive restart required ***" : string.Empty;
            var hiveStatus          = (hiveUpdateCount == 0 && maxUpdates == 0) ? "CURRENT" : hiveUpdateCount.ToString() + restartStatus;
            var linuxPackageStatus  = (maxUpdates == 0) ? "CURRENT" : maxUpdates.ToString();
            var linuxSecurityStatus = (maxSecurityUpdates == 0) ? "CURRENT" : maxSecurityUpdates.ToString();

            Console.WriteLine($"neonHIVE updates:       {hiveStatus}");
            Console.WriteLine($"Linux package updates:  {linuxPackageStatus}");
            Console.WriteLine($"Linux security updates: {linuxSecurityStatus}");

            //-------------------------------------------------------------
            // Docker status

            string dockerVersionInfo;

            if (dockerVersions.Count == 0)
            {
                dockerVersionInfo = "*** ERROR: Docker is not installed.";
            }
            else if (dockerVersions.Count == 1)
            {
                dockerVersionInfo = (string)dockerVersions.Keys.First();
            }
            else
            {
                var sb = new StringBuilder();

                foreach (var version in dockerVersions.Keys.OrderBy(v => v))
                {
                    sb.AppendWithSeparator((string)version, ", ");
                }

                dockerVersionInfo = sb.ToString();
            }

            var dockerStatus = "CURRENT";

            if (dockerVersions.Count == 0)
            {
                dockerStatus = "ERROR: cannot detect version";
            }
            else if (dockerVersions.Count > 1)
            {
                dockerStatus = "WARNING: multiple versions installed";
            }
            else if (dockerVersions.Keys.Min(v => v) < (SemanticVersion)componentInfo.Docker)
            {
                dockerStatus = "UPDATE AVAILABLE";
            }

            var dockerTitle = $"Docker Engine: {dockerStatus}";

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(dockerTitle);
            Console.WriteLine(new string('-', dockerTitle.Length));
            Console.WriteLine($"Current: {dockerVersionInfo}");
            Console.WriteLine($"Latest:  {componentInfo.Docker}");

            //-------------------------------------------------------------
            // Consul status

            string consulVersionInfo;

            if (consulVersions.Count == 0)
            {
                consulVersionInfo = "*** ERROR: Consul is not installed.";
            }
            else if (consulVersions.Count == 1)
            {
                consulVersionInfo = (string)consulVersions.Keys.First();
            }
            else
            {
                var sb = new StringBuilder();

                foreach (var version in consulVersions.Keys.OrderBy(v => v))
                {
                    sb.AppendWithSeparator((string)version, ", ");
                }

                consulVersionInfo = sb.ToString();
            }

            var consulStatus = "CURRENT";

            if (consulVersions.Count == 0)
            {
                consulStatus = "ERROR: cannot detect version";
            }
            else if (consulVersions.Count > 1)
            {
                consulStatus = "WARNING: multiple versions installed";
            }
            else if (consulVersions.Keys.Min(v => v) < (SemanticVersion)componentInfo.Consul)
            {
                consulStatus = "UPDATE AVAILABLE";
            }

            var consulTitle = $"HashiCorp Consul: {consulStatus}";

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(consulTitle);
            Console.WriteLine(new string('-', consulTitle.Length));
            Console.WriteLine($"Current: {consulVersionInfo}");
            Console.WriteLine($"Latest:  {componentInfo.Consul}");

            //-------------------------------------------------------------
            // Vault status

            string vaultVersionInfo;

            if (consulVersions.Count == 0)
            {
                vaultVersionInfo = "*** ERROR: Vault is not installed.";
            }
            else if (consulVersions.Count == 1)
            {
                vaultVersionInfo = (string)vaultVersions.Keys.First();
            }
            else
            {
                var sb = new StringBuilder();

                foreach (var version in vaultVersions.Keys.OrderBy(v => v))
                {
                    sb.AppendWithSeparator((string)version, ", ");
                }

                vaultVersionInfo = sb.ToString();
            }

            var vaultStatus = "CURRENT";

            if (vaultVersions.Count == 0)
            {
                vaultStatus = "ERROR: cannot detect version";
            }
            else if (vaultVersions.Count > 1)
            {
                vaultStatus = "WARNING: multiple versions installed";
            }
            else if (vaultVersions.Keys.Min(v => v) < (SemanticVersion)componentInfo.Vault)
            {
                vaultStatus = "UPDATE AVAILABLE";
            }

            var vaultTitle = $"HashiCorp Vault: {vaultStatus}";

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(vaultTitle);
            Console.WriteLine(new string('-', vaultTitle.Length));
            Console.WriteLine($"Current: {vaultVersionInfo}");
            Console.WriteLine($"Latest:  {componentInfo.Vault}");
        }