o
    Ìv›a2€  ã                
   @   sþ   d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZmZ zddlZW n eyZ Z zd	Ze d
 e¡¡ W Y dZ[ndZ[ww dZddddœgZg d¢ZG dd„ deƒZG dd„ dejƒZdd„ ZdS )zDocker plugin.é    N)Údeepcopy)Úlogger)ÚiterkeysÚ
itervaluesÚ	nativestr)ÚgetTimeSinceLastUpdate)ÚGlancesPlugin)Ú
sort_statsÚglances_processesTz?Error loading Docker Python Lib. Docker plugin is disabled ({})FÚcpu_percentzContainer CPU consumption in %ú%)ÚnameÚdescriptionZy_unit)ÚcpuÚioÚmemoryÚnetworkc                       s¸   e Zd ZdZd%‡ fdd„	Z‡ fdd„Zdd„ Zd	d
„ Zdd„ Zdd„ Z	e
je
jdd„ ƒƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡ fdd„Zd%dd „Zd!d"„ Zd#d$„ Z‡  ZS )&ÚPluginz\Glances Docker plugin.

    stats is a dict: {'version': {...}, 'containers': [{}, {}]}
    Nc                    sP   t t| ƒj||td || _|| _d| _|  ¡ | _i | _	|  
¡  | j d¡ dS )zInit the plugin.)ÚargsÚconfigÚitems_history_listTr   N)Úsuperr   Ú__init__r   r   r   Zdisplay_curseÚconnectÚdocker_clientÚthread_listÚupdateZrefresh_timerÚset)Úselfr   r   ©Ú	__class__© ú@/usr/lib/python3/dist-packages/glances/plugins/glances_docker.pyr   P   s   þ
zPlugin.__init__c                    s*   t | jƒD ]}| ¡  qtt| ƒ ¡  dS )z+Overwrite the exit method to close threads.N)r   r   Ústopr   r   Úexit)r   Útr   r!   r"   r$   k   s   
zPlugin.exitc                 C   s   dS )zReturn the key of the list.r   r!   ©r   r!   r!   r"   Úget_keyr   s   zPlugin.get_keyc              
   C   sn   z	t | jd ƒ}W n ty% } zt d |¡¡ g }W Y d}~nd}~ww |D ]}tD ]}| |¡ q,q(|S )z~Overwrite the default export method.

        - Only exports containers
        - The key is the first container name
        Ú
containersz&docker plugin - Docker export error {}N)r   ÚstatsÚKeyErrorr   ÚdebugÚformatÚexport_exclude_listÚpop)r   ÚretÚeÚ	containerÚir!   r!   r"   Ú
get_exportv   s   €þÿzPlugin.get_exportc              
   C   sJ   zt  ¡ }W |S  ty$ } zt d |¡¡ d}W Y d}~|S d}~ww )zConnect to the Docker server.z.docker plugin - Can not connect to Docker ({})N)ÚdockerZfrom_envÚ	Exceptionr   Úerrorr,   )r   r/   r0   r!   r!   r"   r   ‰   s   
ü€üzPlugin.connectc                 C   s*   |   d¡}t|ƒdkrdS |d  ¡ dkS )z×Return the all tag of the Glances/Docker configuration file.

        # By default, Glances only display running containers
        # Set the following key to True to display all containers
        all=True
        Úallr   FÚtrue)Zget_conf_valueÚlenÚlower)r   Zall_tagr!   r!   r"   Ú_all_tag–   s   
zPlugin._all_tagc           	   
   C   sT  |   ¡ }ts| jdu r| jS | jdkrz	| j ¡ |d< W n- tyJ } z!t d 	| j
|¡¡ d| jv r8| jd= g | jd< | jW  Y d}~S d}~ww z| jjj|  ¡ dpWg }W n$ ty} } zt d 	| j
|¡¡ g | jd< | jW  Y d}~S d}~ww |D ]%}|j| jvr¥t d 	| j
|jdd	… ¡¡ t|ƒ}|| j|j< | ¡  q€tt| jƒƒtd
d„ |D ƒƒ }|D ]}t d 	| j
|dd	… ¡¡ | j|  ¡  | j|= q¸g |d< |D ]>}|  t|jƒ¡sæqÚ|  t|jƒ¡rïqÚi }|  ¡ |d< t|jƒ|d< t|jƒg|d< |j|d< |jj|d< |jd d |d< g |d< |jd  dd¡r6|d  |jd  dg ¡¡ |jd  dd¡rN|d  |jd  dg ¡¡ |d sWd|d< |d dv rê|   |j| j|j j¡|d< |d  dd¡|d< |  !|j| j|j j¡|d< |d  dd¡|d< |d  dd¡dur¥|d  |d d 8  < |  "|j| j|j j¡|d < |d   d!d¡|d"< |d   d#d¡|d$< |  #|j| j|j j¡|d%< |d%  d&d¡|d'< |d%  d(d¡|d)< n(i |d< d|d< i |d< d|d*< i |d < d|d"< d|d$< i |d%< d|d'< d|d)< |d  $|¡ qÚn| jd+kr"	 t%|ƒ| _| jS ),z+Update Docker stats using the input method.NZlocalÚversionz*{} plugin - Cannot get Docker version ({})r(   )r7   z+{} plugin - Cannot get containers list ({})z*{} plugin - Create thread for container {}é   c                 S   s   g | ]}|j ‘qS r!   )Úid)Ú.0Úcr!   r!   r"   Ú
<listcomp>Ü   s    z!Plugin.update.<locals>.<listcomp>z,{} plugin - Stop thread for old container {}Úkeyr   ZNamesZIdZImageÚStateÚStatusÚCommandZConfigZ
EntrypointZCmd)ÚrunningZpausedr   Útotalr   r   ÚusageÚmemory_usageÚcacher   ÚiorZio_rÚiowZio_wr   ÚrxZ
network_rxÚtxZ
network_txZmemory_percentZsnmp)&Zget_init_valueÚimport_error_tagr   r)   Zinput_methodr<   r5   r   r6   r,   Zplugin_namer(   Úlistr;   r>   r   r+   ÚThreadDockerGrabberÚstartr   r   r#   Zis_showr   r   Zis_hider'   ZimageZtagsZattrsÚgetÚextendÚget_docker_cpuÚget_docker_memoryÚget_docker_ioÚget_docker_networkÚappendr	   )	r   r)   r0   r(   r1   r%   Znonexisting_containersÚcontainer_idZcontainer_statsr!   r!   r"   r   £   s¦   

€ù

€ü€ 



ÀB
zPlugin.updatec           	   
   C   s|  ddi}i }i }zS|d d   dd¡|d< |d d   dd¡|d< |d   dd¡|d	< |d   dd¡|d	< d
|d v rL|d d
 durL|d d
 |d< nt|d d d pVg ƒ|d< W n! ty| } zt d ||¡¡ t |¡ W Y d}~|S d}~ww z|d |d  }|d	 |d	  }|| |d  d |d< W |S  ty½ } zt d ||¡¡ t |¡ W Y d}~|S d}~ww )zÈReturn the container CPU usage.

        Input: id is the full container id
               all_stats is the output of the stats method of the Docker API
        Output: a dict {'total': 1.49}
        rG   g        Z	cpu_statsZ	cpu_usageZtotal_usageNZprecpu_statsZsystem_cpu_usageÚsystemZonline_cpusZnb_coreZpercpu_usagez;docker plugin - Cannot grab CPU usage for container {} ({})g      Y@z>docker plugin - Cannot compute CPU usage for container {} ({}))rS   r9   r*   r   r+   r,   Ú	TypeError)	r   rZ   Ú	all_statsr/   Zcpu_newZ
precpu_newr0   Z	cpu_deltaZsystem_cpu_deltar!   r!   r"   rU   2  s^   ÿÿÿÿÿ€
ÿ€ïÿ
ÿú
ÿ€úzPlugin.get_docker_cpuc              
   C   sò   i }zSd|d d v r|d d d |d< nd|d d v r)|d d d |d< nd|d< |d d   dd¡|d< |d   dd¡|d< |d d |d< |d d	 |d	< W |S  ttfyx } zt d
 ||¡¡ t |¡ W Y d}~|S d}~ww )zøReturn the container MEMORY.

        Input: id is the full container id
               all_stats is the output of the stats method of the Docker API
        Output: a dict {'rss': 1015808, 'cache': 356352,  'usage': ..., 'max_usage': ...}
        ZrssZmemory_statsr)   Z	total_rssNrJ   Z	max_usagerH   Úlimitz;docker plugin - Cannot grab MEM usage for container {} ({}))rS   r*   r\   r   r+   r,   )r   rZ   r]   r/   r0   r!   r!   r"   rV   g  s,   ÿÿû€ûzPlugin.get_docker_memoryc              
   C   sŠ  i }z|d }W n" t y* } zt d ||¡¡ t |¡ |W  Y d}~S d}~ww t| dƒsFi | _z|| j|< W n ttfyE   Y nw || jvr`z|| j|< W |S  ttfy_   Y |S w z=td |¡ƒ|d< |d d | j| d d  |d	< |d d
 | j| d d
  |d< |d d |d< |d d
 |d< W n  t y½ } zt d ||¡¡ t |¡ W Y d}~nd}~ww || j|< |S )az  Return the container network usage using the Docker API (v1.0 or higher).

        Input: id is the full container id
        Output: a dict {'time_since_update': 3000, 'rx': 10, 'tx': 65}.
        with:
            time_since_update: number of seconds elapsed between the latest grab
            rx: Number of bytes received
            tx: Number of bytes transmitted
        Znetworksz;docker plugin - Cannot grab NET usage for container {} ({})NÚnetcounters_oldzdocker_net_{}Útime_since_updateZeth0Zrx_bytesrM   Ztx_bytesrN   Zcumulative_rxZcumulative_txzIdocker plugin - Cannot grab network interface usage for container {} ({}))	r*   r   r+   r,   Úhasattrr_   ÚIOErrorÚUnboundLocalErrorr   )r   rZ   r]   Znetwork_newZnetcountersr0   r!   r!   r"   rX   ‡  sJ   
€û
ÿ
ëë""€ý
zPlugin.get_docker_networkc                 C   s¼  i }z|d }W n" t y* } zt d ||¡¡ t |¡ |W  Y d}~S d}~ww t| dƒsFi | _z|| j|< W n ttfyE   Y nw || jvr`z|| j|< W |S  ttfy_   Y |S w z9|d }| j| d }dd„ |D ƒd d	 }d
d„ |D ƒd d	 }	dd„ |D ƒd d	 }
dd„ |D ƒd d	 }W n  tt	t t
fy¹ } zt d ||¡¡ W Y d}~|S d}~ww td |¡ƒ|d< ||
 |d< |	| |d< ||d< |	|d< || j|< |S )aq  Return the container IO usage using the Docker API (v1.0 or higher).

        Input: id is the full container id
        Output: a dict {'time_since_update': 3000, 'ior': 10, 'iow': 65}.
        with:
            time_since_update: number of seconds elapsed between the latest grab
            ior: Number of bytes read
            iow: Number of bytes written
        Zblkio_statsz@docker plugin - Cannot grab block IO usage for container {} ({})NÚiocounters_oldZio_service_bytes_recursivec                 S   ó    g | ]}|d    ¡ dkr|‘qS ©ÚopÚread©r:   ©r?   r2   r!   r!   r"   rA   ï  ó     z(Plugin.get_docker_io.<locals>.<listcomp>r   Úvaluec                 S   re   ©rg   Úwriteri   rj   r!   r!   r"   rA   ð  rk   c                 S   re   rf   ri   rj   r!   r!   r"   rA   ñ  rk   c                 S   re   rm   ri   rj   r!   r!   r"   rA   ò  rk   zdocker_io_{}r`   rK   rL   Zcumulative_iorZcumulative_iow)r*   r   r+   r,   ra   rd   rb   rc   r\   Ú
IndexErrorÚAttributeErrorr   )r   rZ   r]   Zio_newZ
iocountersr0   Znew_io_service_bytes_recursiveZold_io_service_bytes_recursiverK   rL   Zior_oldZiow_oldr!   r!   r"   rW   Á  sV   
€û
ÿ
ãã€ò
zPlugin.get_docker_ioc                 C   s   t  t jd ¡S )z:Return the user ticks by reading the environment variable.Ú
SC_CLK_TCK)ÚosÚsysconfÚsysconf_namesr&   r!   r!   r"   Úget_user_ticks  s   zPlugin.get_user_ticksc                 C   s
   | j d S )zZReturn stats for the action.

        Docker will return self.stats['containers']
        r(   )r)   r&   r!   r!   r"   Úget_stats_action  s   
zPlugin.get_stats_actionc                    s<  t t| ƒ ¡  d| jvrdS | jd D ]ˆ}i i dœ| j||  ¡  < d|v rYd|d v rY| j|d d |d d |d d}|d	krL| j|d d dd
}|| j||  ¡   d d< d|v r›d|d v r›| j|d d |d d |d d |d d}|d	krŽ| j|d d |d d dd}|| j||  ¡   d d< qdS )zUpdate stats views.r(   F)r   Úmemr   rG   r   Z_cpu)ÚheaderÚ
action_keyZDEFAULT)rx   Ú
decorationr   rH   r^   Z_mem)Úmaximumrx   ry   rw   )r{   rx   T)r   r   Úupdate_viewsr)   Zviewsr'   Z	get_alert)r   r2   Zalertr   r!   r"   r|     s6   

þ

ý
þ€zPlugin.update_viewsc                 C   s¶  g }| j rd| j vst| j d ƒdks|  ¡ r|S d d¡}| |  |d¡¡ d t| j d ƒ¡}| |  |¡¡ d | j d d	 ¡}| |  |¡¡ | |  ¡ ¡ | |  ¡ ¡ t| jd
urh| jj	ddddndtt
| j d dd„ dd ƒƒ}djd|d}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d¡}| |  |¡¡ d d ¡}| |  |¡¡ d! d"¡}| |  |¡¡ | j d D ]U}| |  ¡ ¡ | |  | j||d#¡¡ |  |d ¡}d |d dd$… ¡}| |  ||¡¡ zd% |d& d' ¡}W n tyN   d d(¡}Y nw | |  || j|d d&d)d*¡¡ zd |  |d+ d, ¡¡}W n ty}   d d(¡}Y nw | |  || j|d d-d)d*¡¡ zd |  |d+ d. ¡¡}W n ty¬   d d(¡}Y nw | |  |¡¡ d/}d0D ]5}	z|  t|d1 |	 |d1 d2  ƒ¡| }
d |
¡}W n tyä   d d(¡}Y nw | |  |¡¡ q¹|jrød3}d4}nd5}d6}d7D ]7}	z|  t|d8 |	 |d8 d2  | ƒ¡| }
d |
¡}W n ty+   d d(¡}Y nw | |  |¡¡ qþ|d" d
urHd d9 |d" ¡¡}nd d(¡}| | j|d:d;¡ q|S )<z2Return the dict to display in the curse interface.r(   r   z{}Z
CONTAINERSZTITLEz {}z (served by Docker {})r<   ZVersionNr4   Zmax_name_sizeé   )Údefaultc                 S   s   t | d ƒS )Nr   )r9   )Úxr!   r!   r"   Ú<lambda>R  s    z"Plugin.msg_curse.<locals>.<lambda>)rB   r   ú {:{width}}ÚName©Úwidthz{:>10}rD   z{:>6}zCPU%z{:>7}ZMEMz/MAXzIOR/szIOW/szRx/szTx/sz {:8}rE   )r1   Ú	max_widthé
   z{:>6.1f}r   rG   Ú_rz   )ÚitemrB   Úoptionr   rH   rw   r^   ÚB)rK   rL   r   r`   é   Ú é   Úb)rM   rN   r   ú T)Z
splittable)r)   r9   Zis_disabledr,   rY   Zcurse_add_lineZcurse_new_lineÚminr   Zget_int_valueÚmaxÚ	_msg_nameÚcontainer_alertr*   Z	get_viewsZ	auto_unitÚintZbyteÚjoin)r   r   r…   r/   ÚmsgZname_max_widthr1   ÚstatusZunitÚrrl   Zto_bitr!   r!   r"   Ú	msg_curse5  sÚ   ÿÿþ

ýþÿÿü









ÿÿ
þÿ
þÿ&ÿ*ÿ
zPlugin.msg_cursec                 C   sF   |d }t |ƒ|krd|| d d…  }n|d|… }dj||dS )zBuild the container name.r   r‡   r‹   Nr   rƒ   )r9   r,   )r   r1   r…   r   r!   r!   r"   r’   ¨  s
   zPlugin._msg_namec                 C   s(   |dkrdS |dkrdS |dkrdS dS )zAnalyse the container status.rF   ZOKZexitedZWARNINGZdeadZCRITICALZCAREFULr!   )r   r—   r!   r!   r"   r“   ±  s   zPlugin.container_alert)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r$   r'   r3   r   r;   r   Z_check_decoratorZ_log_result_decoratorr   rU   rV   rX   rW   ru   rv   r|   r™   r’   r“   Ú__classcell__r!   r!   r   r"   r   J   s,     5 :B
's	r   c                       sT   e Zd ZdZ‡ fdd„Zdd„ Zedd„ ƒZejdd„ ƒZdd
d„Z	dd„ Z
‡  ZS )rQ   zD
    Specific thread to grab docker stats.

    stats is a dict
    c                    sJ   t t| ƒ ¡  t ¡ | _|| _|jdd| _i | _	t
 d | jj¡¡ dS )zLInit the class.

        container: instance of Docker-py Container
        T)Údecodez.docker plugin - Create thread for container {}N)r   rQ   r   Ú	threadingZEventÚ_stopperÚ
_containerr)   Ú_stats_streamÚ_statsr   r+   r,   r   )r   r1   r   r!   r"   r   Ä  s   
zThreadDockerGrabber.__init__c                 C   sR   z| j D ]}|| _t d¡ |  ¡ r W dS qW dS    t d¡ |  ¡  Y dS )z_Grab the stats.

        Infinite loop, should be stopped by calling the stop() method
        gš™™™™™¹?z+docker plugin - Exception thrown during runN)r£   r¤   ÚtimeÚsleepÚstoppedr   r+   r#   )r   r2   r!   r!   r"   ÚrunÓ  s   

ÿý
zThreadDockerGrabber.runc                 C   s   | j S )zStats getter.©r¤   r&   r!   r!   r"   r)   â  s   zThreadDockerGrabber.statsc                 C   s
   || _ dS )zStats setter.Nr©   )r   rl   r!   r!   r"   r)   ç  s   
Nc                 C   s"   t  d | jj¡¡ | j ¡  dS )zStop the thread.z-docker plugin - Close thread for container {}N)r   r+   r,   r¢   r   r¡   r   )r   Ztimeoutr!   r!   r"   r#   ì  s   zThreadDockerGrabber.stopc                 C   s
   | j  ¡ S )z%Return True is the thread is stopped.)r¡   ZisSetr&   r!   r!   r"   r§   ñ  s   
zThreadDockerGrabber.stopped)N)rš   r›   rœ   r   r   r¨   Úpropertyr)   Úsetterr#   r§   rž   r!   r!   r   r"   rQ   ½  s    


rQ   c                 C   s2   d}d}t j d¡rd}d}t| d ||d | S )Nr   rI   r   r(   )ZsortedbyZsortedby_secondary)r
   Zsort_keyÚ
startswithÚsort_stats_processes)r)   Zsort_byZsort_by_secondaryr!   r!   r"   r	   ö  s   þr	   )r   rr   r    r¥   Úcopyr   Zglances.loggerr   Zglances.compatr   r   r   Zglances.timerr   Zglances.plugins.glances_pluginr   Zglances.processesr	   r­   r
   r4   r5   r0   rO   Zwarningr,   r   r-   r   ZThreadrQ   r!   r!   r!   r"   Ú<module>   s<   €ýþ    w9