Ë
    À7j  ã                  óì   — d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ  ed«      ZdZdd„Zdd	„Zdd
„Zdd„Zdd„Zdd„Zdd„Zddd„Zdd d„Zd!d„Zdd„Zd"d„Zd#d„Zd$d„Zd%d„Zd%d„Zy)&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                ó$  — t        j                  | d   «      sy	 t        j                  | ddt        d¬«      }|j
                  dk7  ry|j                  S # t        j                  t        f$ r!}t        j                  d| |«       Y d}~yd}~ww xY w)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      úJ/var/www/downloads.wolfpanel.net/public_html/agent/src/discovery/system.pyÚrun_readonlyr      s…   € ô �<‰<˜˜A™ÔØðÜ—‘ØØØÜ Øô
ˆð ×Ñ Ò!ØØ�}‰}ÐøÜ×&Ñ&¬Ð0ò Ü�	‰	Ð)¨3°Ô4Üûðús   ›-A Á	A ÁBÁ.B
Â
Bc                 óÚ  — t        j                  «       t        j                  «       t        j                   «       dœ} 	 t        ddd¬«      5 }i }|D ]>  }d|v sŒ|j	                  «       j                  d«      \  }}}|j	                  d«      ||<   Œ@ 	 ddd«       d	v r|d	   | d
<   |j                  d«      | d<   |j                  d«      | d<   | S # 1 sw Y   Œ?xY w# t        $ r Y | S w xY w)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   0   sþ   € ô —/‘/Ó#Ü×#Ñ#Ó%Ü×(Ñ(Ó*ñ€Dð
ÜÐ# S°7Ô;ð 	3¸vØˆFØò 3�Ø˜$’;Ø$(§J¡J£L×$:Ñ$:¸3Ó$?‘M�C˜˜EØ"'§+¡+¨cÓ"2�F˜3’Kñ3÷	3ð ˜FÑ"Ø"(¨Ñ"7ˆD�ÑØ"ŸJ™J tÓ,ˆˆ[ÑØ!'§¡¨LÓ!9ˆÐÑð €K÷	3ð 	3ûô ò ØØ€Kðús/   ¾C ÁCÁ9CÂ<C ÃCÃC Ã	C*Ã)C*c                 ó*   — t        j                  «       S ©N)r+   r   © ó    r   Úkernelr<   G   ó   € Ü×ÑÓÐr;   c                 ó*   — t        j                  «       S r9   )r+   Úmachiner:   r;   r   Úarchitecturer@   K   r=   r;   c                 ó2   — t        j                  «       xs dS )Nr   )ÚosÚ	cpu_countr:   r;   r   rC   rC   O   s   € Ü�<‰<‹>Ò˜QÐr;   c                 ó   — 	 t        ddd¬«      5 } | D ]?  }|j                  d«      sŒt        |j                  «       d   «      }|dz  c cddd«       S  	 ddd«       y# 1 sw Y   yxY w# t        t
        f$ r Y yw xY w)	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   S   sŠ   € ðÜ�/ 3°Ô9ð 	&¸VØò &�Ø—?‘? ;Õ/Ü˜dŸj™j›l¨1™oÓ.�CØ ™:Ñ%÷		&ñ 	&ñ&÷	&ð ÷	&ð ûô ”ZÐ ò Ùðús?   ‚A+ �A¨"AÁ
	A+ ÁAÁA+ ÁA(Á$A+ Á(A+ Á+A=Á<A=c                 óV  — i } 	 t        ddd¬«      5 }i }|D ]G  }|j                  d«      \  }}}t        |j                  «       d   «      dz  ||j	                  «       <   ŒI 	 ddd«       d	v r|d	   | d
<   d|v r|d   | d<   | S # 1 sw Y   Œ#xY w# t
        t        t        f$ r Y | S w xY w)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   `   sÖ   € à€EðÜ�/ 3°Ô9ð 	B¸VØˆFØò B�Ø#Ÿ~™~¨cÓ2‘��Q˜Ü&)¨$¯*©*«,°q©/Ó&:¸TÑ&A��s—y‘y“{Ò#ñB÷	Bð
 ˜ÑØ# JÑ/ˆE�'‰NØ˜VÑ#Ø!'¨Ñ!7ˆE�+Ñð €L÷	Bð 	Bûô ”Z¤Ð,ò ØØ€Lðús)   „B ’ABÁ" B ÂBÂ	B ÂB(Â'B(c                ó`   — 	 t        j                  | «      j                  S # t        $ r Y y w xY wr9   )r   Ú
disk_usagerQ   r   )Úpaths    r   Údisk_total_bytesr\   r   s0   € ðÜ× Ñ  Ó&×,Ñ,Ð,øÜò Ùðús   ‚! ¡	-¬-c                ó˜   — 	 t        j                  | «      }|j                  |j                  |j                  dœS # t
        $ r i cY S w xY w)N)rQ   ÚusedÚfree)r   rZ   rQ   r^   r_   r   )r[   rU   s     r   rZ   rZ   y   sD   € ðÜ×!Ñ! $Ó'ˆØŸ™¨e¯j©jÀ%Ç*Á*ÑMÐMøÜò ØŠ	ðús   ‚8; »A	ÁA	c                 ól   — 	 t        t        j                  «       «      S # t        t        f$ r g cY S w xY wr9   )ÚlistrB   Ú
getloadavgr   ÚAttributeErrorr:   r;   r   Úload_averagerd   �   s1   € ðÜ”B—M‘M“OÓ$Ð$øÜ”^Ð$ò ØŠ	ðús   ‚ Ÿ3²3c                 ó*   — t        j                  «       S r9   )ÚsocketÚgethostnamer:   r;   r   Úhostnamerh   ˆ   s   € Ü×ÑÓÐr;   c                 óÔ   — 	 t        ddd¬«      5 } t        | j                  «       j                  «       d   «      cd d d «       S # 1 sw Y   y xY w# t        t
        t        f$ r Y y w xY w)Nz/proc/uptimer    r!   r"   r   )r,   ÚfloatÚreadlinerJ   r   rK   rT   )r1   s    r   Úuptime_secondsrl   Œ   s_   € ðÜ�. #°Ô8ð 	7¸FÜ˜Ÿ™Ó*×0Ñ0Ó2°1Ñ5Ó6÷	7÷ 	7ò 	7ûä”Z¤Ð,ò Ùðús-   ‚A �*Aº	A ÁAÁ	A ÁA ÁA'Á&A'c                 ó   — t        «       } 	 t        j                  t        j                  «       dt        j                  «      D ]  }| j                  |d   d   «       Œ 	 	 t        j                  t        j                  t        j                  «      }|j                  d«       | j                  |j                  «       d   «       |j                  «        t        d„ | D «       «      S # t        j                  $ r Y Œ�w xY w# t        $ r Y Œ6w xY w)z3Best-effort list of local (private) IPv4 addresses.Né   r   )z10.255.255.255rF   c              3  óD   K  — | ]  }|j                  d «      rŒ|–— Œ y­w)z127.N)rH   )Ú.0Úips     r   ú	<genexpr>zprivate_ips.<locals>.<genexpr>¤   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Õñ	 ð
Ü�}‰}œVŸ^™^¬V×->Ñ->Ó?ˆØ�‰Ð*Ô+Ø�‰�× Ñ Ó" 1Ñ%Ô&Ø�
‰
Œô Ñ@˜sÔ@Ó@Ð@øô �?‰?ò Ùðûô ò Ùðús%   ŒAC( Á!A5D Ã(C>Ã=C>Ä	DÄDc                  ó   — y)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                 óÐ   — t        g d¢«      } g }| s|S | j                  «       D ]?  }|j                  «       }t        |«      dk\  sŒ"|j	                  |d   |d   |d   dœ«       ŒA |S )z5Parse `ip -o addr` output when available (read-only).)rq   z-oÚaddrrn   rF   é   é   )Ú	interfaceÚfamilyÚaddress)r   Ú
splitlinesrJ   ÚlenÚappend)ÚoutputÚ
interfacesr3   Úpartss       r   Únetwork_interfacesr�   ®   sw   € äÒ.Ó/€FØ')€JÙØÐØ×!Ñ!Ó#ò `ˆØ—
‘
“ˆÜˆu‹:˜‹?Ø×Ñ¨E°!©HÀÀaÁÐUZÐ[\ÑU]Ñ^Õ_ð`ð Ðr;   c                 óð   — t        ddg«      } g }| s|S | j                  «       D ]O  }|j                  «       }t        |«      dk\  sŒ"|d   }|j	                  dd«      d   }|j                  ||dœ«       ŒQ |S )	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ÙØˆØ×!Ñ!Ó#ò 9ˆØ—‘“ˆÜˆv‹;˜!ÓØ˜1‘IˆEØ—<‘<  QÓ'¨Ñ+ˆDØ�L‰L 5°$Ñ7Õ8ð9ð €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)r™   r˜   )r™   rš   )r™   zlist[dict[str, Any]])Ú__doc__Ú
__future__r   rB   r+   r   rf   r   Útypingr   Úloggerr   r   r   r   r7   r<   r@   rC   rM   rX   r\   rZ   rd   rh   rl   r   r�   r�   r—   r:   r;   r   ú<module>r£      s…   ðñõ #ã 	Û Û Û Û Ý å áÐ#Ó$€à€óó0ó.óóó
óô$ôóó óóAó&ó
ôr;   