Browse Source

add initial implementation of voixicron, error reporting still missing

Helmut Pozimski 7 years ago
parent
commit
21b6ae60d6
1 changed files with 116 additions and 0 deletions
  1. 116 0
      voixicron.py

+ 116 - 0
voixicron.py

@@ -0,0 +1,116 @@
+#! /usr/bin/env python3
+"""
+This script checks for available updates on Void Linux using xbps and notifies
+the configured administrator account about them. It currently requires
+python 3.x and no additional packages and is supposed to be run with cron or
+another scheduled execution mechanism.
+"""
+
+import subprocess
+import smtplib
+import socket
+import re
+
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
+
+
+# Email server to be used to send the notification
+ADMIN_EMAIL = "root"
+# Mail server to be used to send the notification
+MAIL_SERVER = "localhost"
+# Port to use on the mail server
+MAIL_SERVER_PORT = 25
+# User name to log in to the mail server
+MAIL_SERVER_USER = ""
+# Password to log in to the mail server
+MAIL_SERVER_PASSWORD = ""
+
+AVAILABLE_UPDATES = []
+
+DEVNULL = open("/dev/null", "w")
+
+try:
+    XBPS_INSTALL_RESULT = subprocess.check_output(["xbps-install", "-Sun"],
+                                                  stderr=DEVNULL)
+except subprocess.CalledProcessError:
+    pass
+else:
+    XBPS_INSTALL_RESULT = XBPS_INSTALL_RESULT.decode("utf-8").split("\n")
+    for line in XBPS_INSTALL_RESULT:
+        if "update" in line:
+            try:
+                package = line.split(" ")[0]
+                package_regex = "^([A-Za-z0-9-]*)-([0-9].*_[0-9])$"
+                match_object = re.match(package_regex, package)
+                package_name = match_object.groups()[0]
+                new_package_version = match_object.groups()[1]
+            except IndexError:
+                continue
+            else:
+                try:
+                    xbps_query_result = subprocess.check_output(
+                        ["xbps-query", "--show", package_name], stderr=DEVNULL)
+                except subprocess.CalledProcessError:
+                    pass
+                else:
+                    xbps_query_result = xbps_query_result.decode(
+                        "utf-8").split("\n")
+                    for line in xbps_query_result:
+                        if "pkgver" in line:
+                            installed_package = line.split(
+                                ":")[1].strip()
+                            match = re.match(package_regex,
+                                                       installed_package)
+                            installed_package_version = match.groups()[1]
+                            package_update = {
+                                "name": package_name,
+                                "new_version": new_package_version,
+                                "old_version": installed_package_version,
+                            }
+                            AVAILABLE_UPDATES.append(package_update)
+                            break
+if AVAILABLE_UPDATES:
+    HOSTNAME = socket.getfqdn()
+    MSG = MIMEMultipart()
+    MAIL_TEXT = "The following package updates are available on host %s:\n\n"\
+                % HOSTNAME
+    MSG["Subject"] = "%s updates available on host %s"\
+                     % (len(AVAILABLE_UPDATES), HOSTNAME)
+    MSG["From"] = "voixicron@%s" % HOSTNAME
+    MSG["To"] = ADMIN_EMAIL
+    for update in AVAILABLE_UPDATES:
+        MAIL_TEXT += "%s (%s -> %s)\n"\
+                     % (update["name"],
+                        update["old_version"],
+                        update["new_version"])
+    MSG_TEXT = MIMEText(MAIL_TEXT.encode("utf-8"), _charset="utf-8")
+    MSG.attach(MSG_TEXT)
+    SERVER_CONNECTION = smtplib.SMTP(MAIL_SERVER, MAIL_SERVER_PORT)
+    try:
+        SERVER_CONNECTION.connect()
+    except (smtplib.SMTPConnectError, smtplib.SMTPServerDisconnected,
+            socket.error):
+        pass
+    else:
+        try:
+            SERVER_CONNECTION.starttls()
+        except smtplib.SMTPException:
+            pass
+        if MAIL_SERVER_USER:
+            try:
+                SERVER_CONNECTION.login(MAIL_SERVER_USER, MAIL_SERVER_PASSWORD)
+            except smtplib.SMTPAuthenticationError:
+                pass
+            except smtplib.SMTPException:
+                pass
+        try:
+            SERVER_CONNECTION.sendmail("voixicron@%s" % HOSTNAME, ADMIN_EMAIL,
+                                       MSG.as_string())
+        except smtplib.SMTPRecipientsRefused:
+            pass
+        except smtplib.SMTPSenderRefused:
+            pass
+        else:
+            SERVER_CONNECTION.quit()
+DEVNULL.close()