diff --git a/.gitignore b/.gitignore index 4c9209c8a..5a315736a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,7 @@ agent/plugins/* ncpa.db prereqs.installed .python-version +.DS_Store +build/ncpa +build/*.dmg +build/NCPA-* diff --git a/CHANGES.rst b/CHANGES.rst index a28eed7b1..f43161a06 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,8 @@ Changelog 2.4.1 - 2022-08-16 ================== - Changed the date format in the changelog (#838) (ccztux) +- Added new interface metrics speed, duplex, mtu and isup (#646) (ccztux) +- Removed max_file_length and max_file_path from graphing (ccztux) - NRDP connection timeout is missing in the admin section of the gui (#841) (ccztux) - Updated psutil to address incorrectly reported mounts on Windows (#863) - Changed the way NCPA detects the number of CPUs (#864) diff --git a/README.rst b/README.rst index f01ca01a2..ee51e83d2 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,7 @@ Downloads Current versions: +---------+-------------+-------------------------------------------------------+ -| Current | **2.4.0** | `Downloads `_ | +| Current | **2.5.0** | `Downloads `_ | +---------+-------------+-------------------------------------------------------+ `Older Versions `_ @@ -21,9 +21,10 @@ We currently build for the following operating systems: - Windows (7+) - Mac OS X (10.7+) -- CentOS / RHEL 7, 8 -- CentOS Stream -- Debian 9, 10 +- RHEL 7, 8, 9 +- CentOS 7 +- CentOS Stream 8, 9 +- Debian 9, 10, 11 - Ubuntu 16.04, 18.04, 20.04 - OpenSUSE Leap 15, Tumbleweed - SLES 11, 12, 15 diff --git a/VERSION b/VERSION index 005119baa..58073ef8d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.1 +2.4.1 \ No newline at end of file diff --git a/agent/build_resources/macosinstall.sh b/agent/build_resources/macosinstall.sh index 00560d452..9e56a565b 100644 --- a/agent/build_resources/macosinstall.sh +++ b/agent/build_resources/macosinstall.sh @@ -1,8 +1,10 @@ #!/bin/sh -set -e - -pushd /Volumes/NCPA-* +scriptUser=$(whoami) +if ! id -Gn "${scriptUser}" | grep -q -w admin; then + echo -e "\n\n ERROR!!!: You must have admin privileges to run this script!\n\n" + exit 1 +fi # These values are set in the ncpa.cfg for the user to drop permissions to username="nagios" @@ -14,47 +16,66 @@ added="0" # Check if NCPA is installed if [ -d ${homedir} ]; then upgrade="1" - echo "Starting upgrade..." + echo "Starting upgrade... " else - echo "Starting install..." + echo "Starting install... " +fi + +# Get MacOS version +macOSVer="" +if [[ $OSTYPE == 'darwin'* ]]; then + macOSVer=`sw_vers | grep ProductVersion | awk '{print $2}'` + echo " MacOS version: $macOSVer." fi -# Disable NCPA if it's already installed for upgrade +# Go to install script directory +pushd $( dirname -- "${0}" ) + +# Quit if any errors occur +set -e + +# Save config and disable NCPA if it's already installed for upgrade if [ ${upgrade} -eq "1" ]; then - echo -n "Stopping old NCPA services..." + # Temporarily save etc directory + echo -n " Saving configuration... " + cp -Rf ${homedir}/etc /tmp/ncpa_etc + echo "Done." + + echo -n " Stopping old NCPA services... " launchctl stop com.nagios.ncpa.listener launchctl stop com.nagios.ncpa.passive # Give launchctl time to stop services before continuing sleep 5 - echo "done" + echo "Done." fi # Create the group account -if ! dscl . -read /Groups/${groupname} > /dev/null 2>&1; -then - # Select GID the same way - PrimaryGroupID=`dscl . -list /Groups PrimaryGroupID | awk '{print $2}' | sort -ug | tail -1` - let PrimaryGroupID=PrimaryGroupID+1 - - # Create the group if we need to +if ! dscl . -read /Groups/${groupname} > /dev/null 2>&1; then + echo -n " Adding nagios user and group... " + echo -n "Creating the group account... " + # Select GID the same way + PrimaryGroupID=`dscl . -list /Groups PrimaryGroupID | awk '{print $2}' | sort -ug | tail -1` + let PrimaryGroupID=PrimaryGroupID+1 + + # Create the group if we need to dscl . -create /Groups/${groupname} dscl . -create /Groups/${groupname} RecordName "_${groupname} ${username}" dscl . -create /Groups/${groupname} PrimaryGroupID ${PrimaryGroupID} dscl . -create /Groups/${groupname} RealName "${groupname}" dscl . -create /Groups/${groupname} Password "*" - added="1" + added="1" fi # Create the user account -if ! dscl . -read /Users/${username} > /dev/null 2>&1; -then - # Find the highest UID that exists, pick the next one - UniqueID=`dscl . -list /Users UniqueID | awk '{print $2}' | sort -ug | tail -1` - let UniqueID=UniqueID+1 +if ! dscl . -read /Users/${username} > /dev/null 2>&1; then + echo -n "Creating the user account... " + # Find the highest UID that exists, pick the next one + UniqueID=`dscl . -list /Users UniqueID | awk '{print $2}' | sort -ug | tail -1` + let UniqueID=UniqueID+1 - # Create the actual user if we need to + # Create the actual user if we need to dscl . -create /Users/${username} dscl . -create /Users/${username} UserShell /usr/bin/false dscl . -create /Users/${username} UniqueID ${UniqueID} @@ -63,68 +84,115 @@ then dscl . -create /Users/${username} Password "*" dscl . -create /Users/${username} NFSHomeDirectory ${homedir} - added="1" + added="1" fi if [ ${added} -eq "1" ]; then - echo "Users and group set" + echo "Done." +else + echo " Nagios user and group already exist." fi # Unload the daemons so they can be re-loaded after if [ ${upgrade} -eq "1" ]; then - echo -n "Re-loading services..." + echo -n " Unloading old NCPA services... " launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.listener.plist launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.passive.plist -else - echo -n "Loading services..." + echo "Done." fi cp ncpa/build_resources/ncpa_listener.plist /Library/LaunchDaemons/com.nagios.ncpa.listener.plist cp ncpa/build_resources/ncpa_passive.plist /Library/LaunchDaemons/com.nagios.ncpa.passive.plist -echo "done" -echo -n "Setting permissions..." - -mkdir -p ${homedir} +# Remove MacOS x attributes +echo -n " Removing MacOS xattributes from LaunchDaemon plists... " +if [[ $(xattr -l /Library/LaunchDaemons/com.nagios.ncpa.listener.plist) ]]; then + xattr -d com.apple.quarantine /Library/LaunchDaemons/com.nagios.ncpa.listener.plist +fi -# Temporarily save etc directory -if [ ${upgrade} -eq "1" ]; then - cp -Rf ${homedir}/etc /tmp/ncpa_etc +if [[ $(xattr -l /Library/LaunchDaemons/com.nagios.ncpa.passive.plist) ]]; then + xattr -d com.apple.quarantine /Library/LaunchDaemons/com.nagios.ncpa.passive.plist fi -# Copy over files +echo "Done." + +echo -n " Copying new NCPA files... " +mkdir -p ${homedir} cp -Rf ncpa/* ${homedir} +echo "Done." + +echo -n " Setting permissions... " chmod -R 775 ${homedir} chown -R ${username}:${groupname} ${homedir} chmod +x "${homedir}/uninstall.sh" +echo "Done." -# Replace files +echo -n " Removing MacOS xattributes from ${homedir}... " +xattr -d -r com.apple.quarantine ${homedir} +echo "Done." + +# Restore config files if [ ${upgrade} -eq "1" ]; then - cp -Rf /tmp/ncpa_etc ${homedir} + echo -n " Restoring configuration to ${homedir}/etc... " + rm -rf ${homedir}/etc + cp -Rf "/tmp/ncpa_etc" "${homedir}/etc" rm -rf /tmp/ncpa_etc + echo "Done." fi -echo "done" -echo -n "Starting NCPA..." - +echo -n " Starting NCPA... " launchctl load /Library/LaunchDaemons/com.nagios.ncpa.listener.plist launchctl load /Library/LaunchDaemons/com.nagios.ncpa.passive.plist launchctl start com.nagios.ncpa.passive launchctl start com.nagios.ncpa.listener +echo "Done." -echo "done" +listNCPAcomponents() { + echo "---------------------------------------" + echo "Listing NCPA components... " + echo "\nProcesses?:" + ps aux | grep -v grep | grep ncpa_ + + echo "\nLaunchDaemons?:" + launchctl list | grep nagios + + echo "\nLaunchDaemon plists?:" + ls -al /Library/LaunchDaemons/ | grep nagios + + echo "\ndscl group?:" + sudo dscl . -ls /Groups | grep nagios + + echo "\ndscl user?:" + sudo dscl . -ls /Users | grep nagios + + echo "\nHome dir?:" + ls -al /usr/local | grep ncpa +} + +listNCPAcomponents # Installation completed -echo "\n\n" +echo " " +tokenPhrase="'mytoken'" if [ ${upgrade} -eq "1" ]; then - echo "-------------------" - echo " Upgrade Completed " - echo "-------------------" + echo "-------------------" + echo " Upgrade Completed " + echo "-------------------" + tokenPhrase="your token" else - echo "-------------------" - echo " Install Completed " - echo "-------------------" + echo "-------------------" + echo " Install Completed " + echo "-------------------" fi +echo "\nConfirm your installation:" +echo " 1. In a web browser, navigate to https://localhost:5693 " +echo " (acknowledge the uncertified certificate warning, if necessary)" +echo " 2. Enter ${tokenPhrase} when it asks for a token or a password" +echo " 3. Click the 'See Live Stats' button\n" +echo " After several seconds the graphs should start populating with data." +echo " NCPA is now capturing data from your Mac!" + popd +exit 0 diff --git a/agent/build_resources/macosreadme.txt b/agent/build_resources/macosreadme.txt new file mode 100644 index 000000000..942084d9f --- /dev/null +++ b/agent/build_resources/macosreadme.txt @@ -0,0 +1,14 @@ +Installing NCPA: + 1. Download MacOS archive (https://www.nagios.org/ncpa/#downloads) + 2. Double click open the disk image file to mount it + 3. Find the installer volume name in the terminal: + ls /Volumes + Look for NCPA- (e.g. NCPA-2.4.0) + + 4. Run the installer, and follow any user prompts: + sudo zsh /Volumes/NCPA-/install.sh + +Note: if you already have NCPA installed, the installer will upgrade the NCPA software, and retain your configuration. + +Uninstalling NCPA + 1. On the command line, enter: sudo zsh /usr/local/ncpa/uninstall.sh diff --git a/agent/build_resources/macosuninstall.sh b/agent/build_resources/macosuninstall.sh index cf35541e2..8ebf5abd9 100755 --- a/agent/build_resources/macosuninstall.sh +++ b/agent/build_resources/macosuninstall.sh @@ -1,6 +1,10 @@ #!/bin/sh -set -e +scriptUser=$(whoami) +if ! id -Gn "${scriptUser}" | grep -q -w admin; then + echo -e "\n\n ERROR!!!: You must have admin privileges to run this script!\n\n" + exit 1 +fi # These values are set in the ncpa.cfg for the user to drop permissions to username="nagios" @@ -9,39 +13,133 @@ homedir="/usr/local/ncpa" # Check if NCPA is installed if [ -d ${homedir} ]; then - - echo "Starting uninstall..." + echo "Starting uninstall... " else - echo "NCPA is not installed or installed in an alternate location." - exit 0 + echo "NCPA may not be fully installed, clean up other NCPA artifacts." +fi + +# Get MacOS version +macOSVer="" +if [[ $OSTYPE == 'darwin'* ]]; then + macOSVer=`sw_vers | grep ProductVersion | awk '{print $2}'` + echo " MacOS version: $macOSVer." fi -echo -n "Stopping NCPA services..." -launchctl stop com.nagios.ncpa.listener -launchctl stop com.nagios.ncpa.passive +removeNCPAdaemons() { + echo -n " Stopping NCPA services... " + stopped='' + hasListener=$(launchctl list | grep ncpa_listener) + if [[ $hasListener ]]; then + launchctl stop com.nagios.ncpa.listener + echo -n "listener stopped... " + stopped=1 + fi + hasPassive=$(launchctl list | grep ncpa_passive) + if [[ $hasPassive ]]; then + launchctl stop com.nagios.ncpa.passive + echo -n "passive stopped... " + stopped=1 + fi + + # Give launchctl time to stop services before continuing + if [[ $stopped ]]; then + sleep 5 + fi + echo "Done." + + echo -n " Unloading NCPA services... " + if [[ -f "/Library/LaunchDaemons/com.nagios.ncpa.listener.plist" ]] ; then + launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.listener.plist + fi + + if [[ -f "/Library/LaunchDaemons/com.nagios.ncpa.listener.plist" ]] ; then + launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.passive.plist + fi + + launchctl remove com.nagios.ncpa.listener + launchctl remove com.nagios.ncpa.passive + echo "Done." +} + +removeNCPAplists() { + echo -n " Removing NCPA plists... " + rm -f /Library/LaunchDaemons/com.nagios.ncpa.listener.plist + rm -f /Library/LaunchDaemons/com.nagios.ncpa.passive.plist + echo "Done." +} + +killNCPAprocesses() { + echo -n " Kill NCPA processes... " + pid=`ps aux | grep -v grep | grep ncpa_listener | awk '{print $2}'` + if [[ $pid ]]; then + kill $pid + echo -n "Killed $pid ncpa_listener, " + fi + + pid=`ps aux | grep -v grep | grep ncpa_passive | awk '{print $2}'` + if [[ $pid ]]; then + kill $pid + echo -n "Killed $pid ncpa_passive, " + fi + echo "Done." +} + +removeNCPAuser() { + if dscl . -read "/Groups/${groupname}" > /dev/null 2>&1; then + echo -n " Removing nagios user and group... " + echo -n "/Users/${username}... " + sudo dscl . -delete "/Users/${username}" + echo -n "/Groups/${groupname}... " + sudo dscl . -delete "/Groups/${groupname}" + echo -n "/Groups/_${groupname} ${groupname}... " + sudo dscl . -delete "/Groups/_${groupname} ${groupname}" + echo "Done." + else + echo "No group/user to remove." + fi +} + +removeNCPAcode() { + if [[ -d "${homedir}" ]]; then + echo -n " Removing $homedir... " + rm -rf $homedir + echo "Done." + else + echo "No ${homedir} to remove" + fi +} + +listNCPAcomponents() { + echo "\n---------------------------------------" + echo "Listing NCPA components... " + echo "\nProcesses?:" + ps aux | grep -v grep | grep ncpa_ + + echo "\nLaunchDaemons?:" + launchctl list | grep nagios + + echo "\nLaunchDaemon plists?:" + ls -al /Library/LaunchDaemons/ | grep nagios -# Give launchctl time to stop services before continuing -sleep 5 -echo "done" + echo "\ndscl group?:" + sudo dscl . -ls /Groups | grep nagios -echo "Unloading NCPA services..." -launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.listener.plist -launchctl unload /Library/LaunchDaemons/com.nagios.ncpa.passive.plist + echo "\ndscl user?:" + sudo dscl . -ls /Users | grep nagios -echo "Removing NCPA services..." -rm -f /Library/LaunchDaemons/com.nagios.ncpa.listener.plist -rm -f /Library/LaunchDaemons/com.nagios.ncpa.passive.plist + echo "\nHome dir?:" + ls -al /usr/local | grep ncpa +} -echo -n "Removing NCPA..." -rm -rf $homedir -echo "done" +removeNCPAdaemons +removeNCPAplists +killNCPAprocesses +removeNCPAuser +removeNCPAcode +listNCPAcomponents -echo -n "Removing nagios user and group..." -dscl . -delete /Groups/{$groupname} -dscl . -delete /Users/${username} -echo "done" +echo "\n--------------------------" +echo " Uninstall NCPA Completed " +echo "--------------------------" -echo "\n\n" -echo "----------------------" -echo " Un-install Completed " -echo "----------------------" +exit diff --git a/agent/listener/psapi.py b/agent/listener/psapi.py index 17ecd4bc6..72c9bb787 100644 --- a/agent/listener/psapi.py +++ b/agent/listener/psapi.py @@ -92,24 +92,39 @@ def make_mount_other_nodes(partition): return ParentNode(safe_mountpoint, children=[dvn, fstype, opts]) def make_if_nodes(if_name): - x = ps.net_io_counters(pernic=True) - - bytes_sent = RunnableNode('bytes_sent', method=lambda: (x[if_name].bytes_sent, 'B')) - bytes_recv = RunnableNode('bytes_recv', method=lambda: (x[if_name].bytes_recv, 'B')) - packets_sent = RunnableNode('packets_sent', method=lambda: (x[if_name].packets_sent, 'packets')) - packets_recv = RunnableNode('packets_recv', method=lambda: (x[if_name].packets_recv, 'packets')) - errin = RunnableNode('errin', method=lambda: (x[if_name].errin, 'errors')) - errout = RunnableNode('errout', method=lambda: (x[if_name].errout, 'errors')) - dropin = RunnableNode('dropin', method=lambda: (x[if_name].dropin, 'packets')) - dropout = RunnableNode('dropout', method=lambda: (x[if_name].dropout, 'packets')) + duplex_map = { + ps.NIC_DUPLEX_FULL: "full", + ps.NIC_DUPLEX_HALF: "half", + ps.NIC_DUPLEX_UNKNOWN: "unknown", + } + + io_counters = ps.net_io_counters(pernic=True) + io = io_counters[if_name] + bytes_sent = RunnableNode('bytes_sent', method=lambda: (io.bytes_sent, 'B')) + bytes_recv = RunnableNode('bytes_recv', method=lambda: (io.bytes_recv, 'B')) + packets_sent = RunnableNode('packets_sent', method=lambda: (io.packets_sent, 'packets')) + packets_recv = RunnableNode('packets_recv', method=lambda: (io.packets_recv, 'packets')) + errin = RunnableNode('errin', method=lambda: (io.errin, 'errors')) + errout = RunnableNode('errout', method=lambda: (io.errout, 'errors')) + dropin = RunnableNode('dropin', method=lambda: (io.dropin, 'packets')) + dropout = RunnableNode('dropout', method=lambda: (io.dropout, 'packets')) + + stats = ps.net_if_stats() + st = stats[if_name] + isup = RunnableNode('isup', method=lambda: (True if st.isup else "false", '')) + duplex = RunnableNode('duplex', method=lambda: (duplex_map[st.duplex], '')) + speed = RunnableNode('speed', method=lambda: (st.speed, 'Mbit/s')) + mtu = RunnableNode('mtu', method=lambda: (st.mtu, '')) # Temporary fix for Windows (latin-1 should catch most things) name = if_name if environment.SYSTEM == "Windows": name = unicode(if_name, "latin-1", errors="replace") - return RunnableParentNode(name, primary='bytes_sent', children=[bytes_sent, bytes_recv, packets_sent, - packets_recv, errin, errout, dropin, dropout]) + return RunnableParentNode(name, + children=[bytes_sent, bytes_recv, packets_sent, packets_recv, errin, errout, dropin, dropout, isup, duplex, speed, mtu], + primary='bytes_sent', + include=('bytes_sent', 'bytes_recv', 'packets_sent', 'packets_recv', 'errin', 'errout', 'dropin', 'dropout', 'speed')) def get_timezone(): diff --git a/agent/listener/static/help/index.html b/agent/listener/static/help/index.html index 3b7967683..7e6497606 100644 --- a/agent/listener/static/help/index.html +++ b/agent/listener/static/help/index.html @@ -93,6 +93,26 @@

Restarting the NCPA Services

+ +
+ +

Changes from 2.4 to 2.5

+

You can also view the full changelog on the NCPA GitHub repository .

+

+

    +
  1. Interface checks - The interface node now contains the following new endpoints: +
      +
    1. speed - The NIC speed expressed in mega bits (Mbit/s), if it can’t be determined (e.g. ‘localhost’) it will be set to 0. +
    2. mtu - NIC’s maximum transmission unit expressed in bytes. +
    3. duplex - The duplex communication type; it can be either full, half or unknown. +
    4. isup - A bool indicating whether the NIC is up and running (meaning ethernet cable or Wi-Fi is connected). +
    +
  2. +
+

+ +
+
diff --git a/agent/listener/templates/gui/graphs.html b/agent/listener/templates/gui/graphs.html index 8d89614de..50698b891 100644 --- a/agent/listener/templates/gui/graphs.html +++ b/agent/listener/templates/gui/graphs.html @@ -67,7 +67,7 @@ function generate_select(obj) { var select = $('