[Kimchi-devel] [PATCH v2 1/4] Add functions for package manager monitoring

Jose Ricardo Ziviani joserz at linux.vnet.ibm.com
Sun Oct 4 20:44:37 UTC 2015


 - Kimchi package manager classes are now able to know if there is already a
   package manager instance running in the system and where to find the
   default logfiles for those package managers.

Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
---
 src/wok/plugins/kimchi/i18n.py     |  1 +
 src/wok/plugins/kimchi/swupdate.py | 84 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/src/wok/plugins/kimchi/i18n.py b/src/wok/plugins/kimchi/i18n.py
index ea325b8..416d951 100644
--- a/src/wok/plugins/kimchi/i18n.py
+++ b/src/wok/plugins/kimchi/i18n.py
@@ -270,6 +270,7 @@ messages = {
     "KCHPKGUPD0002E": _("Package %(name)s is not marked to be updated."),
     "KCHPKGUPD0003E": _("Error while getting packages marked to be updated. Details: %(err)s"),
     "KCHPKGUPD0004E": _("There is no compatible package manager for this system."),
+    "KCHPKGUPD0005E": _("There is a package manager instance running in the system."),
 
     "KCHUTILS0003E": _("Unable to choose a virtual machine name"),
 
diff --git a/src/wok/plugins/kimchi/swupdate.py b/src/wok/plugins/kimchi/swupdate.py
index b966424..f86c12e 100644
--- a/src/wok/plugins/kimchi/swupdate.py
+++ b/src/wok/plugins/kimchi/swupdate.py
@@ -17,6 +17,7 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 
+import fcntl
 import os
 import signal
 import subprocess
@@ -27,6 +28,7 @@ from wok.exception import NotFoundError, OperationFailed
 from wok.utils import run_command, wok_log
 
 from config import kimchiLock
+from psutil import pid_exists
 from yumparser import get_yum_packages_list_update
 
 
@@ -157,6 +159,24 @@ class YumUpdate(object):
     def __init__(self):
         self._pkgs = {}
         self.update_cmd = ["yum", "-y", "update"]
+        self.logfile = self._get_output_log()
+
+    def _get_output_log(self):
+        """
+        Return the logfile path
+        """
+        try:
+            with open('/etc/yum.conf', 'r') as config:
+                for line in config:
+                    if 'logfile' in line:
+                        logfile = line.split('=')[1].strip()
+                        if not logfile:
+                            return None
+
+                        return logfile
+
+        except (IndexError, IOError):
+            return None
 
     def _refreshUpdateList(self):
         """
@@ -177,6 +197,9 @@ class YumUpdate(object):
         package = {'package_name': <string>, 'version': <string>,
                    'arch': <string>, 'repository': <string>}
         """
+        if self.isRunning():
+            raise OperationFailed('KCHPKGUPD0005E')
+
         self._refreshUpdateList()
         pkg_list = []
         for pkg in self._pkgs:
@@ -185,6 +208,25 @@ class YumUpdate(object):
             pkg_list.append(package)
         return pkg_list
 
+    def isRunning(self):
+        """
+        Return True whether the YUM package manager is already running or
+        False otherwise.
+        """
+        try:
+            with open('/var/run/yum.pid', 'r') as pidfile:
+                pid = int(pidfile.read().rstrip('\n'))
+
+        # cannot find pidfile, assumes yum is not running
+        except (IOError, ValueError):
+            return False
+
+        # the pidfile exists and it lives in process table
+        if pid_exists(pid):
+            return True
+
+        return False
+
 
 class AptUpdate(object):
     """
@@ -196,6 +238,7 @@ class AptUpdate(object):
         self._pkgs = {}
         self.pkg_lock = getattr(__import__('apt_pkg'), 'SystemLock')
         self.update_cmd = ['apt-get', 'upgrade', '-y']
+        self.logfile = '/var/log/apt/term.log'
 
     def _refreshUpdateList(self):
         """
@@ -218,6 +261,9 @@ class AptUpdate(object):
         package = {'package_name': <string>, 'version': <string>,
                    'arch': <string>, 'repository': <string>}
         """
+        if self.isRunning():
+            raise OperationFailed('KCHPKGUPD0005E')
+
         kimchiLock.acquire()
         self._refreshUpdateList()
         kimchiLock.release()
@@ -231,6 +277,21 @@ class AptUpdate(object):
 
         return pkg_list
 
+    def isRunning(self):
+        """
+        Return True whether the APT package manager is already running or
+        False otherwise.
+        """
+        try:
+            with open('/var/lib/dpkg/lock', 'w') as lockfile:
+                fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+
+        # cannot open dpkg lock file to write in exclusive mode means the
+        # apt is currently running
+        except IOError:
+            return True
+
+        return False
 
 class ZypperUpdate(object):
     """
@@ -242,6 +303,7 @@ class ZypperUpdate(object):
         self._pkgs = {}
         self.update_cmd = ["zypper", "--non-interactive", "update",
                            "--auto-agree-with-licenses"]
+        self.logfile = '/var/log/zypp/history'
 
     def _refreshUpdateList(self):
         """
@@ -268,7 +330,29 @@ class ZypperUpdate(object):
         package = {'package_name': <string>, 'version': <string>,
                    'arch': <string>, 'repository': <string>}
         """
+        if self.isRunning():
+            raise OperationFailed('KCHPKGUPD0005E')
+
         kimchiLock.acquire()
         self._refreshUpdateList()
         kimchiLock.release()
         return self._pkgs
+
+    def isRunning(self):
+        """
+        Return True whether the Zypper package manager is already running or
+        False otherwise.
+        """
+        try:
+            with open('/var/run/zypp.pid', 'r') as pidfile:
+                pid = int(pidfile.read().rstrip('\n'))
+
+        # cannot find pidfile, assumes yum is not running
+        except (IOError, ValueError):
+            return False
+
+        # the pidfile exists and it lives in process table
+        if pid_exists(pid):
+            return True
+
+        return False
-- 
1.9.1




More information about the Kimchi-devel mailing list