Mercurial > servermonitor
view ServerMonitor/Objects/Checks/DiskSpaceCheck.cs @ 23:3866c19535fd
Fix NullReferenceException when checks are executed on a brand new server.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Thu, 30 May 2019 21:40:27 -0400 |
parents | 68d7834dc28e |
children |
line wrap: on
line source
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace ServerMonitorApp { /// <summary>Checks the available disk space on a remote server.</summary> [DisplayName("Disk space check"), Description("Check the remaining free disk space"), DisplayWeight(11)] public class DiskSpaceCheck : SshCheck { /// <summary>The command to execute. Must return the POSIX output format of df(1).</summary> public override string Command => string.Format(DiskSpaceCommand, Device); /// <summary>The command to execute, with a placeholder of {0} for the device to check.</summary> protected string DiskSpaceCommand => "df -P -k {0}"; /// <summary>The device or file on the device to check.</summary> public string Device { get; set; } /// <summary>The minimum free space allowed for the check to pass.</summary> public double MinFreeSpace { get; set; } /// <summary>The storage units or percentage for MinFreeSpace.</summary> public FreeSpaceUnits FreeSpaceUnits { get; set; } public DiskSpaceCheck() { // Set general SSH check settings for disk space checks. CheckExitCode = true; ExitCode = 0; } /// <summary>Processes the output of the disk space check command.</summary> protected override List<CheckResult> ProcessCommandResult(string output, int exitCode) { // Check for general SSH failures. List<CheckResult> results = base.ProcessCommandResult(output, exitCode); // If there was an error running the command, fail immediately. if (results.Any(r => r.Failed)) return results; /* Parse the command results, expected in the POSIX output format of df(1): Filesystem 1024-blocks Used Available Capacity Mounted on <file system name> <total space> <space used> <space free> <percentage used> <file system root> */ // Split the output into lines and remove the header row. List<string> lines = output.Split('\n').ToList(); lines.RemoveAt(0); // Make sure there is only a single line of output remaining. if (lines.Count > 1) { results.Add(Fail("df output was more than one line: " + string.Join("\n", lines))); } else { // Split the string into tokens on whitespace. string[] tokens = lines[0].Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (FreeSpaceUnits == FreeSpaceUnits.percent) { // Test on percentage: calculate the capacity free percent from the capacity used percent reported. if (int.TryParse(tokens[4].Replace("%", ""), out int percent)) { percent = 100 - percent; string message = string.Format("Free disk space is {0}%", percent); if (percent < MinFreeSpace) results.Add(Fail(message)); else results.Add(Pass(message)); } else { results.Add(Fail("Unable to parse df output as integer: " + tokens[4].Replace("%", ""))); } } else { // Test on bytes: calculate the remaining available space from the reported available space. if (int.TryParse(tokens[3], out int freeSpace)) { // Available space is returned in KB. Convert to MB (our default unit). freeSpace /= 1024; // If the unit is GB, convert MB to GB. if (FreeSpaceUnits == FreeSpaceUnits.GB) freeSpace /= 1024; string message = string.Format("Free disk space is {0} {1}", freeSpace, FreeSpaceUnits); if (freeSpace < MinFreeSpace) results.Add(Fail(message)); else results.Add(Pass(message)); } else { results.Add(Fail("Unable to parse df output as integer: " + tokens[3])); } } } return results; } /// <summary>Validates disk space check options.</summary> public override string Validate(bool saving = true) { string message = base.Validate(); if (Device.IsNullOrEmpty()) message += "Device is required." + Environment.NewLine; if (MinFreeSpace <= 0) message += "Free space must be greater than 0." + Environment.NewLine; else if (FreeSpaceUnits == FreeSpaceUnits.percent && MinFreeSpace > 100) message += "Free space percent must be between 0 and 100." + Environment.NewLine; return message; } } /// <summary>The units to use when testing available disk space.</summary> public enum FreeSpaceUnits { /// <summary>Tests available disk space in megabytes.</summary> MB = 0, /// <summary>Tests available disk space in gigabytes.</summary> GB = 1, /// <summary>Tests available disk space as a percentage of the total space.</summary> percent = 2 } }