[Kimchi-devel] [PATCH v4 2/4] Implement the package manager monitor backend

Jose Ricardo Ziviani joserz at linux.vnet.ibm.com
Wed Oct 7 16:25:39 UTC 2015


 - The client will be able to know if there is a package manager instance
    running and to follow the package manager logfiles to know what is
    happening within.

Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
---
 src/wok/control/base.py                | 18 ++++++++++++
 src/wok/plugins/kimchi/control/host.py | 15 +++++++++-
 src/wok/plugins/kimchi/model/host.py   | 16 ++++++++++
 src/wok/plugins/kimchi/swupdate.py     | 53 ++++++++++++++++++++++++++++++++++
 4 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/src/wok/control/base.py b/src/wok/control/base.py
index 5c5c95f..e9ed3c8 100644
--- a/src/wok/control/base.py
+++ b/src/wok/control/base.py
@@ -226,6 +226,24 @@ class Resource(object):
         return {}
 
 
+class AsyncResource(Resource):
+    """
+    AsyncResource is a specialized Resource to handle async task.
+    """
+    def __init__(self, model, ident=None):
+        super(AsyncResource, self).__init__(model, ident)
+
+    def lookup(self):
+        try:
+            lookup = getattr(self.model, model_fn(self, 'lookup'))
+            self.info = lookup(*self.model_args)
+        except AttributeError:
+            self.info = {}
+
+        cherrypy.response.status = 202
+        return wok.template.render('Task', self.info)
+
+
 class Collection(object):
     """
     A Collection is a container for Resource objects.  To create a new
diff --git a/src/wok/plugins/kimchi/control/host.py b/src/wok/plugins/kimchi/control/host.py
index 0a40f1b..9fe4c0a 100644
--- a/src/wok/plugins/kimchi/control/host.py
+++ b/src/wok/plugins/kimchi/control/host.py
@@ -17,7 +17,8 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 
-from wok.control.base import Collection, Resource, SimpleCollection
+from wok.control.base import AsyncResource, Collection
+from wok.control.base import Resource, SimpleCollection
 from wok.control.utils import UrlSubNode
 from wok.exception import NotFoundError
 
@@ -39,6 +40,7 @@ class Host(Resource):
         self.packagesupdate = PackagesUpdate(self.model)
         self.repositories = Repositories(self.model)
         self.swupdate = self.generate_action_handler_task('swupdate')
+        self.swupdateprogress = SoftwareUpdateProgress(self.model)
         self.cpuinfo = CPUInfo(self.model)
 
     @property
@@ -46,6 +48,17 @@ class Host(Resource):
         return self.info
 
 
+class SoftwareUpdateProgress(AsyncResource):
+    def __init__(self, model, id=None):
+        super(SoftwareUpdateProgress, self).__init__(model, id)
+        self.role_key = 'host'
+        self.admin_methods = ['GET']
+
+    @property
+    def data(self):
+        return self.info
+
+
 class HostStats(Resource):
     def __init__(self, model, id=None):
         super(HostStats, self).__init__(model, id)
diff --git a/src/wok/plugins/kimchi/model/host.py b/src/wok/plugins/kimchi/model/host.py
index f32cf62..9b1fc32 100644
--- a/src/wok/plugins/kimchi/model/host.py
+++ b/src/wok/plugins/kimchi/model/host.py
@@ -168,6 +168,22 @@ class HostModel(object):
                 if (DOM_STATE_MAP[dom.info()[0]]) == state]
 
 
+class SoftwareUpdateProgressModel(object):
+    def __init__(self, **kargs):
+        self.task = TaskModel(**kargs)
+        self.objstore = kargs['objstore']
+
+    def lookup(self, *name):
+        try:
+            swupdate = SoftwareUpdate()
+        except:
+            raise OperationFailed('KCHPKGUPD0004E')
+
+        taskid = add_task('/plugins/kimchi/host/swupdateprogress',
+                          swupdate.tailUpdateLogs, self.objstore, None)
+        return self.task.lookup(taskid)
+
+
 class HostStatsModel(object):
     __metaclass__ = Singleton
 
diff --git a/src/wok/plugins/kimchi/swupdate.py b/src/wok/plugins/kimchi/swupdate.py
index 2fd4ff5..2eed2f5 100644
--- a/src/wok/plugins/kimchi/swupdate.py
+++ b/src/wok/plugins/kimchi/swupdate.py
@@ -123,6 +123,59 @@ class SoftwareUpdate(object):
         os.setsid()
         signal.signal(signal.SIGTERM, signal.SIG_IGN)
 
+    def tailUpdateLogs(self, cb, params):
+        """
+        When the package manager is already running (started outside kimchi or
+        if wokd is restarted) we can only know what's happening by reading the
+        logfiles. This method acts like a 'tail -f' on the default package
+        manager logfile. If the logfile is not found, a simple '*' is
+        displayed to track progress. This will be until the process finishes.
+        """
+        if not self._pkg_mnger.isRunning():
+            return
+
+        fd = None
+        try:
+            fd = os.open(self._pkg_mnger.logfile, os.O_RDONLY)
+
+        # cannot open logfile, print something to let users know that the
+        # system is being upgrading until the package manager finishes its
+        # job
+        except (TypeError, OSError):
+            msgs = []
+            while self._pkg_mnger.isRunning():
+                msgs.append('*')
+                cb(''.join(msgs))
+                time.sleep(1)
+            msgs.append('\n')
+            cb(''.join(msgs), True)
+            return
+
+        # go to the end of logfile and starts reading, if nothing is read or
+        # a pattern is not found in the message just wait and retry until
+        # the package manager finishes
+        os.lseek(fd, 0, os.SEEK_END)
+        msgs = []
+        progress = []
+        while True:
+            read = os.read(fd, 1024)
+            if not read:
+                if not self._pkg_mnger.isRunning():
+                    break
+
+                if not msgs:
+                    progress.append('*')
+                    cb(''.join(progress))
+
+                time.sleep(1)
+                continue
+
+            msgs.append(read)
+            cb(''.join(msgs))
+
+        os.close(fd)
+        return cb(''.join(msgs), True)
+
     def doUpdate(self, cb, params):
         """
         Execute the update
-- 
1.9.1




More information about the Kimchi-devel mailing list