ó
    ŸUAj  ã                  ó"  • S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSKJr  \" S5      rSrSS jrSS	 jrSS
 jrSS jrSS jrSS jrSS jrSS S jjrSS!S jjrS"S jrSS jrS#S jrS$S jrS%S jrS&S jrS'S jrS'S jrg)(a   Read-only system facts and a safe subprocess helper.

Everything here is strictly read-only: no service is touched, nothing is
written to the server. On non-Linux dev machines functions degrade gracefully
and return None / empty values instead of raising.
é    )ÚannotationsN)ÚAny)Ú
get_loggerzdiscovery.systemé
   c                ó.  • [         R                  " U S   5      (       d  g [        R                  " U SS[        SS9nUR
                  S:w  a  gUR                  $ ! [        R                  [        4 a   n[        R                  SX5         SnAgSnAff = f)zÀRun a read-only command and return stdout, or None on any failure.

Never raises. Used for inspection commands only (systemctl list, ss, etc.).
Destructive commands must never be passed here.
r   NTF)Úcapture_outputÚtextÚtimeoutÚcheckzcommand failed %s: %s)ÚshutilÚwhichÚ
subprocessÚrunÚ_CMD_TIMEOUTÚ
returncodeÚstdoutÚSubprocessErrorÚOSErrorÚlogÚdebug)ÚcmdÚresultÚexcs      Ú:D:\Programs\laragon\www\wolf\agent\src\discovery\system.pyÚrun_readonlyr      s†   € ô �<Š<˜˜A™×ÑØðÜ—’ØØØÜ Øñ
ˆð ×Ñ Ó!ØØ�}‰}ÐøÜ×&Ñ&¬Ð0ó Ü�	‰	Ð)¨3Ô4Üûðús   ¡,A ÁA ÁBÁ4BÂBc                 óî  • [         R                  " 5       [         R                  " 5       [         R                   " 5       S.n  [        SSSS9 n0 nU H@  nSU;   d  M  UR	                  5       R                  S5      u  pEnUR	                  S5      X$'   MB     SSS5        S	W;   a  US	   U S
'   UR                  S5      U S'   UR                  S5      U S'   U $ ! , (       d  f       NF= f! [         a     U $ f = f)zDOperating system name/version, reading /etc/os-release when present.)ÚsystemÚreleaseÚpretty_namez/etc/os-releaseÚrúutf-8©ÚencodingÚ=Ú"NÚPRETTY_NAMEr   ÚIDÚ	distro_idÚ
VERSION_IDÚdistro_version)Úplatformr   r   ÚopenÚstripÚ	partitionÚgetr   )ÚinfoÚhandleÚfieldsÚlineÚkeyÚ_Úvalues          r   Úos_infor7   1   sî   € ô —/’/Ó#Ü×#Ò#Ó%Ü×(Ò(Ó*ñ€Dð
ÜÐ# S°7Ò;¸vØˆFÛ�Ø˜$•;Ø$(§J¡J£L×$:Ñ$:¸3Ó$?‘M�C˜EØ"'§+¡+¨cÓ"2�F“Kñ ÷ <ð ˜FÓ"Ø"(¨Ñ"7ˆD�ÑØ"ŸJ™J tÓ,ˆˆ[ÑØ!'§¡¨LÓ!9ˆÐÑð €K÷ <Õ;ûô ó ØØ€Kðús0   ÁC& ÁCÁ9CÂ>C& Ã
C#ÃC& Ã&
C4Ã3C4c                 ó,   • [         R                  " 5       $ ©N)r+   r   © ó    r   Úkernelr<   H   ó   € Ü×ÒÓÐr;   c                 ó,   • [         R                  " 5       $ r9   )r+   Úmachiner:   r;   r   Úarchitecturer@   L   r=   r;   c                 ó>   • [         R                  " 5       =(       d    S$ )Nr   )ÚosÚ	cpu_countr:   r;   r   rC   rC   P   s   € Ü�<Š<‹>×˜QÐr;   c                 ó  •  [        SSSS9 n U  HE  nUR                  S5      (       d  M  [        UR                  5       S   5      nUS-  s  sSSS5        $    SSS5        g! , (       d  f       g= f! [        [
        4 a     gf = f)	z9Total RAM in bytes from /proc/meminfo (Linux), else None.ú/proc/meminfor    r!   r"   z	MemTotal:é   é   N)r,   Ú
startswithÚintÚsplitr   Ú
ValueError)r1   r3   Úkibs      r   Úmemory_total_bytesrM   T   s‚   € ðÜ�/ 3°Ò9¸VÛ�Ø—?‘? ;×/Ó/Ü˜dŸj™j›l¨1™oÓ.�CØ ™:Ñ%÷	 :Ñ9Ù÷ :ð ÷ :Ô9ð ûô ”ZÐ ó Ùðús?   ‚A3 �A"«"A"Á	A3 ÁA"ÁA3 Á"
A0Á,A3 Á0A3 Á3BÂBc                 ób  • 0 n  [        SSSS9 n0 nU HF  nUR                  S5      u  pEn[        UR                  5       S   5      S-  X$R	                  5       '   MH     SSS5        S	W;   a  US	   U S
'   SU;   a  US   U S'   U $ ! , (       d  f       N,= f! [
        [        [        4 a     U $ f = f)z.Total/available memory in bytes (best effort).rE   r    r!   r"   Ú:r   rG   NÚMemTotalÚtotalÚMemAvailableÚ	available)r,   r.   rI   rJ   r-   r   rK   Ú
IndexError)Úusager1   Úvaluesr3   r4   r5   Úrests          r   Úmemory_usagerX   a   sÀ   € à€EðÜ�/ 3°Ò9¸VØˆFÛ�Ø#Ÿ~™~¨cÓ2‘�˜Ü&)¨$¯*©*«,°q©/Ó&:¸TÑ&A�—y‘y“{Ó#ñ ÷ :ð
 ˜ÓØ# JÑ/ˆE�'‰NØ˜VÓ#Ø!'¨Ñ!7ˆE�+Ñð €L÷ :Õ9ûô ”Z¤Ð,ó ØØ€Lðús)   „B �ABÁ$B Â
BÂB ÂB.Â-B.c                ód   •  [         R                  " U 5      R                  $ ! [         a     g f = fr9   )r   Ú
disk_usagerQ   r   )Úpaths    r   Údisk_total_bytesr\   s   s0   € ðÜ× Ò  Ó&×,Ñ,Ð,øÜó Ùðús   ‚" ¢
/®/c                óœ   •  [         R                  " U 5      nUR                  UR                  UR                  S.$ ! [
         a    0 s $ f = f)N)rQ   ÚusedÚfree)r   rZ   rQ   r^   r_   r   )r[   rU   s     r   rZ   rZ   z   sD   € ðÜ×!Ò! $Ó'ˆØŸ™¨e¯j©jÀ%Ç*Á*ÑMÐMøÜó ØŠ	ðús   ‚9< ¼AÁ
Ac                 óp   •  [        [        R                  " 5       5      $ ! [        [        4 a    / s $ f = fr9   )ÚlistrB   Ú
getloadavgr   ÚAttributeErrorr:   r;   r   Úload_averagerd   ‚   s1   € ðÜ”B—M’M“OÓ$Ð$øÜ”^Ð$ó ØŠ	ðús   ‚   5´5c                 ó,   • [         R                  " 5       $ r9   )ÚsocketÚgethostnamer:   r;   r   Úhostnamerh   ‰   s   € Ü×ÒÓÐr;   c                 óÚ   •  [        SSSS9 n [        U R                  5       R                  5       S   5      sS S S 5        $ ! , (       d  f       g = f! [        [
        [        4 a     g f = f)Nz/proc/uptimer    r!   r"   r   )r,   ÚfloatÚreadlinerJ   r   rK   rT   )r1   s    r   Úuptime_secondsrl   �   sV   € ðÜ�. #°Ò8¸FÜ˜Ÿ™Ó*×0Ñ0Ó2°1Ñ5Ó6÷ 9×8×8ûä”Z¤Ð,ó Ùðús-   ‚A �*A·	A Á
AÁA ÁA ÁA*Á)A*c                óà   •  [         R                  " U 5      nUR                  S:H  =(       a2    UR                  =(       d    UR
                  =(       d    UR                  $ ! [         a     gf = f)zÂTrue only for RFC1918, loopback and link-local IPv4 addresses.

Public addresses must never be labelled private, so we classify with the
stdlib ipaddress module rather than naive prefix checks.
Fé   )Ú	ipaddressÚ
ip_addressrK   ÚversionÚ
is_privateÚis_loopbackÚis_link_local)ÚaddrÚips     r   Ú_is_private_ipv4rw   •   sX   € ðÜ×!Ò! $Ó'ˆð �:‰:˜‰?×T §¡× S°·±× SÀ2×CSÑCSÐTøô ó Ùðús   ‚A  Á 
A-Á,A-c                 ó,  • [        5       n  [        R                  " [        R                  " 5       S[        R                  5       H  nU R                  US   S   5        M      [        R                  " [        R                  [        R                  5      nUR                  S5        U R                  UR                  5       S   5        UR                  5         [        S U  5       5      $ ! [        R                   a     NŸf = f! [         a     N8f = f)zDBest-effort list of local *private* IPv4 addresses (RFC1918 et al.).Nrn   r   )z10.255.255.255rF   c              3  óH   #   • U H  n[        U5      (       d  M  Uv •  M     g 7fr9   )rw   )Ú.0rv   s     r   Ú	<genexpr>Úprivate_ips.<locals>.<genexpr>³   s   é € Ð;™s˜Ô&6°r×&:—"‘"šsùs   ‚"™	")Úsetrf   Úgetaddrinforg   ÚAF_INETÚaddÚgaierrorÚ
SOCK_DGRAMÚconnectÚgetsocknameÚcloser   Úsorted)Úipsr0   Úsocks      r   Úprivate_ipsr‰   ¢   sÖ   € ä“E€CðÜ×&Ò&¤v×'9Ò'9Ó';¸TÄ6Ç>Á>ÖRˆDØ�G‰G�D˜‘G˜A‘JÖñ Sð
Ü�}Š}œVŸ^™^¬V×->Ñ->Ó?ˆØ�‰Ð*Ô+Ø�‰�× Ñ Ó" 1Ñ%Ô&Ø�
‰
Œô Ñ;™sÓ;Ó;Ð;øô �?‰?ó Ùðûô ó Ùðús%   ŒAC, Á$A6D Ã,DÄDÄ
DÄDc                 ó   • g)zÕPlaceholder for v1. The control plane already sees the source IP, and
discovery must stay read-only/local, so we do not call an external echo
service here. TODO(prod): resolve via panel-side observation or opt-in.Nr:   r:   r;   r   Ú	public_ipr‹   ¶   s   € ð r;   c                 óâ   • [        / SQ5      n / nU (       d  U$ U R                  5        HB  nUR                  5       n[        U5      S:¼  d  M$  UR	                  US   US   US   S.5        MD     U$ )z5Parse `ip -o addr` output when available (read-only).)rv   z-oru   rn   rF   é   é   )Ú	interfaceÚfamilyÚaddress)r   Ú
splitlinesrJ   ÚlenÚappend)ÚoutputÚ
interfacesr3   Úpartss       r   Únetwork_interfacesr˜   ½   sp   € äÒ.Ó/€FØ')€JÞØÐØ×!Ñ!Ö#ˆØ—
‘
“ˆÜˆu‹:˜�?Ø×Ñ¨E°!©HÀÀaÁÐUZÐ[\ÑU]Ñ^Ö_ñ $ð Ðr;   c                 ó   • [        SS/5      n / nU (       d  U$ U R                  5        HQ  nUR                  5       n[        U5      S:¼  d  M$  US   nUR	                  SS5      S   nUR                  XES.5        MS     U$ )	zGListening TCP sockets via `ss -tlnH` (read-only). Empty if unavailable.Ússz-tlnHrn   rŽ   rO   rF   éÿÿÿÿ)ÚlocalÚport)r   r’   rJ   r“   Úrsplitr”   )r•   Úportsr3   r2   rœ   r�   s         r   Ú
open_portsr    Ê   s{   € ä˜4 ˜/Ó*€FØ"$€EÞØˆØ×!Ñ!Ö#ˆØ—‘“ˆÜˆv‹;˜!ÕØ˜1‘IˆEØ—<‘<  QÓ'¨Ñ+ˆDØ�L‰L 5Ñ7Ö8ñ $ð €Lr;   )r   ú	list[str]Úreturnú
str | None)r¢   zdict[str, Any])r¢   Ústr)r¢   rI   )r¢   ú
int | None)r¢   údict[str, int])Ú/)r[   r¤   r¢   r¥   )r[   r¤   r¢   r¦   )r¢   zlist[float])r¢   zfloat | None)ru   r¤   r¢   Úbool)r¢   r¡   )r¢   r£   )r¢   zlist[dict[str, Any]]) Ú__doc__Ú
__future__r   ro   rB   r+   r   rf   r   Útypingr   Úloggerr   r   r   r   r7   r<   r@   rC   rM   rX   r\   rZ   rd   rh   rl   rw   r‰   r‹   r˜   r    r:   r;   r   Ú<module>r­      s�   ðñõ #ã Û 	Û Û Û Û Ý å áÐ#Ó$€à€ôô0ô.ôôô
ôö$öôô ôô
Uô<ô(ô
õr;   