
    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)zRun 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
#S7; 	3vF 3$;$(JJL$:$:3$?MCE"'++c"2F3K3	3 F""("7D"JJt,[!'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 &??;/djjl1o.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syy{#B	B
 #J/E'NV#!'!7E+ 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    !!$'ejj%**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    BMMO$$^$ 	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 	7F*0021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    EC&&v'9'9';T6>>R 	 DGGDGAJ	 
}}V^^V->->?*+  "1%&

 @s@@@ ??   s%   AC( !A5D (C>=C>	DDc                      y)zPlaceholder 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;!1IE<<Q'+DLL5$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;   