]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: Adding AGE field to device ls cmd 44896/head
authorRedouane Kachach <rkachach@redhat.com>
Fri, 4 Feb 2022 12:28:51 +0000 (13:28 +0100)
committerRedouane Kachach <rkachach@redhat.com>
Mon, 21 Feb 2022 18:21:06 +0000 (19:21 +0100)
Fixes: https://tracker.ceph.com/issues/53540
Signed-off-by: Redouane Kachach <rkachach@redhat.com>
src/pybind/mgr/orchestrator/module.py
src/pybind/mgr/test_orchestrator/dummy_data.json
src/python-common/ceph/deployment/inventory.py
src/python-common/ceph/tests/c-v-inventory.json

index 2d73361fc6b223f5d7be8bb6671e67266964d279..ed183bb55a82bf00d2e4d8f2685add67131899a3 100644 (file)
@@ -492,17 +492,18 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
                 table = PrettyTable(
                     ['HOST', 'PATH', 'TYPE', 'TRANSPORT', 'RPM', 'DEVICE ID', 'SIZE',
                      'HEALTH', 'IDENT', 'FAULT',
-                     'AVAILABLE', 'REJECT REASONS'],
+                     'AVAILABLE', 'REFRESHED', 'REJECT REASONS'],
                     border=False)
             else:
                 table = PrettyTable(
                     ['HOST', 'PATH', 'TYPE', 'DEVICE ID', 'SIZE',
-                     'AVAILABLE', 'REJECT REASONS'],
+                     'AVAILABLE', 'REFRESHED', 'REJECT REASONS'],
                     border=False)
             table.align = 'l'
             table._align['SIZE'] = 'r'
             table.left_padding_width = 0
             table.right_padding_width = 2
+            now = datetime_now()
             for host_ in sorted(inv_hosts, key=lambda h: h.name):  # type: InventoryHost
                 for d in sorted(host_.devices.devices, key=lambda d: d.path):  # type: Device
 
@@ -526,6 +527,7 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
                                 display_map[led_ident],
                                 display_map[led_fail],
                                 display_map[d.available],
+                                nice_delta(now, d.created, ' ago'),
                                 ', '.join(d.rejected_reasons)
                             )
                         )
@@ -538,6 +540,7 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
                                 d.device_id,
                                 format_dimless(d.sys_api.get('size', 0), 5),
                                 display_map[d.available],
+                                nice_delta(now, d.created, ' ago'),
                                 ', '.join(d.rejected_reasons)
                             )
                         )
index 1f0698aa730361569c38d401952de524ca4803f7..b6096d25fa2a297d643c20cb8c4e3b5a54d3d431 100644 (file)
@@ -6,6 +6,7 @@
         {
           "available": true,
           "device_id": "",
+          "created": "2022-02-11T10:58:23.177450Z",
           "human_readable_type": "ssd",
           "lvs": [],
           "path": "/dev/vdb",
@@ -62,6 +63,7 @@
         {
           "available": true,
           "device_id": "",
+          "created": "2022-02-11T10:58:23.177450Z",
           "human_readable_type": "hdd",
           "lvs": [],
           "path": "/dev/vdd",
         {
           "available": true,
           "device_id": "",
+          "created": "2022-02-11T10:58:23.177450Z",
           "human_readable_type": "ssd",
           "lvs": [],
           "path": "/dev/vdb",
         {
           "available": true,
           "device_id": "",
+          "created": "2022-02-11T10:58:23.177450Z",
           "human_readable_type": "hdd",
           "lvs": [],
           "path": "/dev/vdd",
index d0a885668c090c15d94ae7fe30d7d88e3984cbd2..880881b2a0580db80a47de9fe10da20fa0bb915a 100644 (file)
@@ -3,6 +3,8 @@ try:
 except ImportError:
     pass  # for type checking
 
+from ceph.utils import datetime_now, datetime_to_str, str_to_datetime
+import datetime
 import json
 
 
@@ -16,7 +18,14 @@ class Devices(object):
         self.devices = devices  # type: List[Device]
 
     def __eq__(self, other: Any) -> bool:
-        return self.to_json() == other.to_json()
+        if not isinstance(other, Devices):
+            return NotImplemented
+        if len(self.devices) != len(other.devices):
+            return False
+        for d1, d2 in zip(other.devices, self.devices):
+            if d1 != d2:
+                return False
+        return True
 
     def to_json(self):
         # type: () -> List[dict]
@@ -38,6 +47,7 @@ class Device(object):
         'available',
         'path',
         'sys_api',
+        'created',
         'lvs',
         'human_readable_type',
         'device_id',
@@ -52,6 +62,7 @@ class Device(object):
                  lvs=None,  # type: Optional[List[str]]
                  device_id=None,  # type: Optional[str]
                  lsm_data=None,  # type: Optional[Dict[str, Dict[str, str]]]
+                 created=None  # type: Optional[datetime.datetime]
                  ):
         self.path = path
         self.sys_api = sys_api if sys_api is not None else {}  # type: Dict[str, Any]
@@ -60,11 +71,23 @@ class Device(object):
         self.lvs = lvs
         self.device_id = device_id
         self.lsm_data = lsm_data if lsm_data is not None else {}  # type: Dict[str, Dict[str, str]]
+        self.created = created if created is not None else datetime_now()
+
+    def __eq__(self, other):
+        # type: (Any) -> bool
+        if not isinstance(other, Device):
+            return NotImplemented
+        diff = [k for k in self.report_fields if k != 'created' and (getattr(self, k)
+                                                                     != getattr(other, k))]
+        return not diff
 
     def to_json(self):
         # type: () -> dict
         return {
-            k: getattr(self, k) for k in self.report_fields
+            k: (getattr(self, k) if k != 'created'
+                or not isinstance(getattr(self, k), datetime.datetime)
+                else datetime_to_str(getattr(self, k)))
+            for k in self.report_fields
         }
 
     @classmethod
@@ -74,7 +97,9 @@ class Device(object):
             raise ValueError('Device: Expected dict. Got `{}...`'.format(json.dumps(input)[:10]))
         ret = cls(
             **{
-                key: input.get(key, None)
+                key: (input.get(key, None) if key != 'created'
+                      or not input.get(key, None)
+                      else str_to_datetime(input.get(key, None)))
                 for key in Device.report_fields
                 if key != 'human_readable_type'
             }
index f9425ee735534a47d821f9325b13ecd11aa75ccd..c243455254c087f863c8b5a85f54b3378cdd66a8 100644 (file)
@@ -1,6 +1,7 @@
 [
   {
     "available": false,
+    "created": "2022-02-11T10:58:23.177450Z",
     "rejected_reasons": [
       "locked"
     ],
@@ -57,6 +58,7 @@
   },
   {
     "available": false,
+    "created": "2022-02-11T10:58:23.177450Z",
     "rejected_reasons": [
       "locked"
     ],
     ],
     "path": "/dev/sda"
   }
-]
\ No newline at end of file
+]