]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/progress: persist started_at and finished_at timestamps
authorRicardo Dias <rdias@suse.com>
Mon, 15 Jul 2019 14:07:00 +0000 (15:07 +0100)
committerRicardo Dias <rdias@suse.com>
Wed, 17 Jul 2019 10:50:50 +0000 (11:50 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/pybind/mgr/progress/module.py

index e88f7284a54894be1ff4bf2502d057b623132dc4..1a529a8121335503d6bc2e82b1d6bd704f9dfd36 100644 (file)
@@ -4,10 +4,11 @@ import threading
 import datetime
 import uuid
 import time
+
 import json
 
 
-ENCODING_VERSION = 1
+ENCODING_VERSION = 2
 
 # keep a global reference to the module so we can use it from Event methods
 _module = None
@@ -23,13 +24,12 @@ class Event(object):
     objects (osds, pools) this relates to.
     """
 
-    def __init__(self, message, refs, duration="(since 00h 00m 00s)"):
-        self._refs = refs
-        self._duration_str = duration
+    def __init__(self, message, refs, started_at=None):
         self._message = message
-        self.started_at = datetime.datetime.utcnow()
-
+        self._refs = refs
+        self.started_at = started_at if started_at else time.time()
         self.id = None
+        self.update_duration_event()
 
     def _refresh(self):
         global _module
@@ -49,7 +49,7 @@ class Event(object):
     @property
     def progress(self):
         raise NotImplementedError()
-    
+
     @property
     def duration_str(self):
         return self._duration_str
@@ -91,7 +91,7 @@ class Event(object):
     def update_duration_event(self):
         # Update duration of event in seconds/minutes/hours
 
-        duration = (datetime.datetime.utcnow() - self.started_at).seconds
+        duration = time.time() - self.started_at
         self._duration_str = time.strftime("(since %Hh %Mm %Ss)", time.gmtime(duration))
 
 class GhostEvent(Event):
@@ -100,8 +100,9 @@ class GhostEvent(Event):
     after the event is complete.
     """
 
-    def __init__(self, my_id, message, refs, duration="(since 00h 00m 00s)"):
-        super(GhostEvent, self).__init__(message, refs, duration)
+    def __init__(self, my_id, message, refs, started_at, finished_at=None):
+        super(GhostEvent, self).__init__(message, refs, started_at)
+        self.finished_at = finished_at if finished_at else time.time()
         self.id = my_id
 
     @property
@@ -112,7 +113,9 @@ class GhostEvent(Event):
         return {
             "id": self.id,
             "message": self.message,
-            "refs": self._refs
+            "refs": self._refs,
+            "started_at": self.started_at,
+            "finished_at": self.finished_at
         }
 
 
@@ -123,8 +126,8 @@ class RemoteEvent(Event):
     progress information as it emerges.
     """
 
-    def __init__(self, my_id, message, refs, duration="(since 00h 00m 00s)"):
-        super(RemoteEvent, self).__init__(message, refs, duration)
+    def __init__(self, my_id, message, refs):
+        super(RemoteEvent, self).__init__(message, refs)
         self.id = my_id
         self._progress = 0.0
         self._refresh()
@@ -159,7 +162,7 @@ class PgRecoveryEvent(Event):
 
         self._progress = 0.0
 
-        # self._start_epoch = _module.get_osdmap().get_epoch() 
+        # self._start_epoch = _module.get_osdmap().get_epoch()
         self._start_epoch = start_epoch
 
         self.id = str(uuid.uuid4())
@@ -325,7 +328,7 @@ class Module(MgrModule):
             self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
 
     def _osd_in_out(self, old_map, old_dump, new_map, osd_id, marked):
-        # A function that will create or complete an event when an 
+        # A function that will create or complete an event when an
         # OSD is marked in or out according to the affected PGs
         affected_pgs = []
         unmoved_pgs = []
@@ -341,13 +344,13 @@ class Module(MgrModule):
 
                 new_up_acting = new_map.pg_to_up_acting_osds(pool['pool'], ps)
                 new_osds = set(new_up_acting['acting'])
-                
+
                 # Check the osd_id being in the acting set for both old
                 # and new maps to cover both out and in cases
                 was_on_out_or_in_osd = osd_id in old_osds or osd_id in new_osds
                 if not was_on_out_or_in_osd:
                     continue
-                
+
                 self.log.debug("pool_id, ps = {0}, {1}".format(
                     pool_id, ps
                 ))
@@ -366,7 +369,7 @@ class Module(MgrModule):
                 self.log.debug(
                     "new_up_acting: {0}".format(json.dumps(new_up_acting,
                                                            indent=2)))
-                
+
                 if was_on_out_or_in_osd and is_relocated:
                     # This PG is now in motion, track its progress
                     affected_pgs.append(PgId(pool_id, ps))
@@ -383,8 +386,8 @@ class Module(MgrModule):
         self.log.warn("{0} PGs affected by osd.{1} being marked {2}".format(
             len(affected_pgs), osd_id, marked))
 
-           
-        # In the case of the osd coming back in, we might need to cancel 
+
+        # In the case of the osd coming back in, we might need to cancel
         # previous recovery event for that osd
         if marked == "in":
             for ev_id, ev in self._events.items():
@@ -400,11 +403,11 @@ class Module(MgrModule):
                     refs=[("osd", osd_id)],
                     which_pgs=affected_pgs,
                     evacuate_osds=[osd_id],
-                    start_epoch=self.get_osdmap().get_epoch() 
+                    start_epoch=self.get_osdmap().get_epoch()
                     )
             ev.pg_update(self.get("pg_dump"), self.log)
             self._events[ev.id] = ev
-                 
+
     def _osdmap_changed(self, old_osdmap, new_osdmap):
         old_dump = old_osdmap.dump()
         new_dump = new_osdmap.dump()
@@ -473,8 +476,16 @@ class Module(MgrModule):
             raise RuntimeError("Cannot decode version {0}".format(
                                decoded['compat_version']))
 
+        if decoded['compat_version'] < ENCODING_VERSION:
+            # we need to add the "started_at" and "finished_at" attributes to the events
+            for ev in decoded['events']:
+                ev['started_at'] = None
+                ev['finished_at'] = None
+
         for ev in decoded['events']:
-            self._completed_events.append(GhostEvent(ev['id'], ev['message'], ev['refs']))
+            self._completed_events.append(GhostEvent(ev['id'], ev['message'],
+                                                     ev['refs'], ev['started_at'],
+                                                     ev['finished_at']))
 
         self._prune_completed_events()
 
@@ -532,14 +543,14 @@ class Module(MgrModule):
         ev._refresh()
 
     def _complete(self, ev):
-        duration = (datetime.datetime.utcnow() - ev.started_at)
+        duration = (time.time() - ev.started_at)
         self.log.info("Completed event {0} ({1}) in {2} seconds".format(
-            ev.id, ev.message, duration.seconds
+            ev.id, ev.message, int(round(duration))
         ))
         self.complete_progress_event(ev.id)
 
         self._completed_events.append(
-            GhostEvent(ev.id, ev.message, ev.refs, ev.duration_str))
+            GhostEvent(ev.id, ev.message, ev.refs, ev.started_at))
         del self._events[ev.id]
         self._prune_completed_events()
         self._dirty = True