From: Redouane Kachach Date: Fri, 4 Feb 2022 12:28:51 +0000 (+0100) Subject: mgr/cephadm: Adding AGE field to device ls cmd X-Git-Tag: v18.0.0~1347^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=1c5b3e86f9b8ae0ca3ae41798dfa18e9ffe9fcb7;p=ceph.git mgr/cephadm: Adding AGE field to device ls cmd Fixes: https://tracker.ceph.com/issues/53540 Signed-off-by: Redouane Kachach --- diff --git a/src/pybind/mgr/orchestrator/module.py b/src/pybind/mgr/orchestrator/module.py index 2d73361fc6b22..ed183bb55a82b 100644 --- a/src/pybind/mgr/orchestrator/module.py +++ b/src/pybind/mgr/orchestrator/module.py @@ -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) ) ) diff --git a/src/pybind/mgr/test_orchestrator/dummy_data.json b/src/pybind/mgr/test_orchestrator/dummy_data.json index 1f0698aa73036..b6096d25fa2a2 100644 --- a/src/pybind/mgr/test_orchestrator/dummy_data.json +++ b/src/pybind/mgr/test_orchestrator/dummy_data.json @@ -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", @@ -134,6 +136,7 @@ { "available": true, "device_id": "", + "created": "2022-02-11T10:58:23.177450Z", "human_readable_type": "ssd", "lvs": [], "path": "/dev/vdb", @@ -190,6 +193,7 @@ { "available": true, "device_id": "", + "created": "2022-02-11T10:58:23.177450Z", "human_readable_type": "hdd", "lvs": [], "path": "/dev/vdd", diff --git a/src/python-common/ceph/deployment/inventory.py b/src/python-common/ceph/deployment/inventory.py index d0a885668c090..880881b2a0580 100644 --- a/src/python-common/ceph/deployment/inventory.py +++ b/src/python-common/ceph/deployment/inventory.py @@ -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' } diff --git a/src/python-common/ceph/tests/c-v-inventory.json b/src/python-common/ceph/tests/c-v-inventory.json index f9425ee735534..c243455254c08 100644 --- a/src/python-common/ceph/tests/c-v-inventory.json +++ b/src/python-common/ceph/tests/c-v-inventory.json @@ -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" ], @@ -150,4 +152,4 @@ ], "path": "/dev/sda" } -] \ No newline at end of file +]