1
- import dbus
1
+ import enum
2
+
3
+ from sdbus import sd_bus_open_system
2
4
from yunohost .utils .system import binary_to_human
5
+ from yunohost .utils .udisks2_interfaces import Udisks2Manager
3
6
4
7
UDISK_DRIVE_PATH = "/org/freedesktop/UDisks2/drives/"
5
8
UDISK_DRIVE_IFC = "org.freedesktop.UDisks2.Drive"
6
-
7
-
8
- def _query_udisks () -> list [tuple [str , dict ]]:
9
- bus = dbus .SystemBus ()
10
- manager = dbus .Interface (
11
- bus .get_object ("org.freedesktop.UDisks2" , "/org/freedesktop/UDisks2" ),
12
- "org.freedesktop.DBus.ObjectManager" ,
13
- )
14
-
15
- return sorted (
16
- (
17
- (name .removeprefix (UDISK_DRIVE_PATH ), dev [UDISK_DRIVE_IFC ])
18
- for name , dev in manager .GetManagedObjects ().items ()
19
- if name .startswith (UDISK_DRIVE_PATH )
20
- ),
21
- key = lambda item : item [1 ]["SortKey" ],
22
- )
23
-
24
-
25
- def _disk_infos (name : str , drive : dict , human_readable = False ):
9
+ UDISK_DRIVE_ATA_IFC = "org.freedesktop.UDisks2.Drive.Ata"
10
+ UDISK_DRIVE_NVME_IFC = "org.freedesktop.UDisks2.Manager.NVMe"
11
+
12
+
13
+ class DiskState (enum .StrEnum ):
14
+ """https://github.com/storaged-project/udisks/issues/1352#issuecomment-2678874537"""
15
+ @staticmethod
16
+ def _generate_next_value_ (name , start , count , last_values ):
17
+ return name .upper ()
18
+
19
+ SANE = enum .auto ()
20
+ CRITICAL = enum .auto ()
21
+ UNKNOWN = enum .auto ()
22
+
23
+ @staticmethod
24
+ def parse (drive : dict ) -> "DiskState" :
25
+ match drive :
26
+ case {"smart_failing" : failing }:
27
+ # ATA disk, see https://storaged.org/doc/udisks2-api/latest/gdbus-org.freedesktop.UDisks2.Drive.Ata.html#gdbus-property-org-freedesktop-UDisks2-Drive-Ata.SmartFailing
28
+ return DiskState .SANE if not failing else DiskState .CRITICAL
29
+ case {"smart_critical_warning" : failing }:
30
+ # NVME; see https://storaged.org/doc/udisks2-api/latest/gdbus-org.freedesktop.UDisks2.NVMe.Controller.html#gdbus-property-org-freedesktop-UDisks2-NVMe-Controller.SmartCriticalWarning
31
+ return DiskState .SANE if not failing else DiskState .CRITICAL
32
+ case _:
33
+ return DiskState .UNKNOWN
34
+
35
+
36
+ def _disk_infos (name : str , drive : dict , ** kwargs ):
37
+ human_readable = kwargs .get ("human_readable" , False )
38
+ human_readable_size = kwargs .get ("human_readable_size" , human_readable )
26
39
result = {
27
40
"name" : name ,
28
- "model" : drive ["Model" ],
29
- "serial" : drive ["Serial" ],
30
- "removable" : bool (drive ["MediaRemovable" ]),
31
- "size" : binary_to_human (drive ["Size" ]) if human_readable else drive ["Size" ],
41
+ "model" : drive ["model" ],
42
+ "serial" : drive ["serial" ],
43
+ "removable" : bool (drive ["media_removable" ]),
44
+ "size" : binary_to_human (drive ["size" ]) if human_readable_size else drive ["size" ],
45
+ "smartStatus" : DiskState .parse (drive ),
32
46
}
33
47
34
- if connection_bus := drive [ "ConnectionBus" ] :
35
- result ["connection_bus " ] = connection_bus
48
+ if " connection_bus" in drive :
49
+ result ["connectionBus " ] = drive [ " connection_bus" ]
36
50
37
- if (rotation_rate := drive ["RotationRate " ]) == - 1 :
51
+ if (rotation_rate := drive ["rotation_rate " ]) == - 1 :
38
52
result .update (
39
53
{
40
54
"type" : "HDD" ,
@@ -54,25 +68,29 @@ def _disk_infos(name: str, drive: dict, human_readable=False):
54
68
return result
55
69
56
70
57
- def disk_list (with_info = False , human_readable = False ):
58
- if not with_info :
59
- return [name for name , _ in _query_udisks ()]
71
+ def disk_list (** kwargs ):
72
+ bus = sd_bus_open_system ()
73
+ disks = Udisks2Manager (bus ).get_disks ()
74
+
75
+ with_info = kwargs .get ("with_info" , False )
60
76
61
- result = []
77
+ if not with_info :
78
+ return list (disks .keys ())
62
79
63
- for name , drive in _query_udisks ():
64
- result .append (_disk_infos (name , drive , human_readable ))
80
+ result = [
81
+ _disk_infos (name , disk .props , ** kwargs ) for name , disk in disks .items ()
82
+ ]
65
83
66
84
return {"disks" : result }
67
85
68
86
69
- def disk_info (name , human_readable = False ):
70
- bus = dbus . SystemBus ()
71
- drive = dbus . Interface (
72
- bus . get_object (
73
- "org.freedesktop.UDisks2" , f"/org/freedesktop/UDisks2/drives/ { name } "
74
- ),
75
- dbus . PROPERTIES_IFACE ,
76
- ). GetAll ( "org.freedesktop.UDisks2.Drive" )
87
+ def disk_info (name , ** kwargs ):
88
+ bus = sd_bus_open_system ()
89
+ disk = Udisks2Manager ( bus ). get_disks (). get ( name )
90
+
91
+ human_readable = kwargs . get ( "human_readable" , False )
92
+
93
+ if not disk :
94
+ return f"Unknown disk with name { name } " if human_readable else None
77
95
78
- return _disk_infos (name , drive , human_readable )
96
+ return _disk_infos (name , disk . props , ** kwargs )
0 commit comments