
    p
f>                     p   d dl Z d dlZd dlZd dlmZ d dlmZmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ  ed	      Z e ej"                         
      ZdZdZ G d de      Z G d de      Z G d de      Z G d de      Z ej6                  d      Z G d de      Z G d de      Z G d de      Zy)    N)	timedelta)loggerconf)CGroupsException)ustr)
get_osutil)fileutil   )hours)secondszwalinuxagent.servicezazure-walinuxagent-logcollectorc                       e Zd Zy)CounterNotFoundN)__name__
__module____qualname__     ?/usr/lib/python3/dist-packages/azurelinuxagent/common/cgroup.pyr   r   #   s    r   r   c                   j    e Zd ZdZefdZed        Zed        Zed        Z	ed        Z
ed        Zy)	MetricValuezN
    Class for defining all the required metric fields to send telemetry.
    c                 J    || _         || _        || _        || _        || _        y N)	_category_counter	_instance_value_report_period)selfcategorycounterinstancevaluereport_periods         r   __init__zMetricValue.__init__-   s&    !!+r   c                     | j                   S r   )r   r   s    r   r   zMetricValue.category4       ~~r   c                     | j                   S r   )r   r&   s    r   r    zMetricValue.counter8   s    }}r   c                     | j                   S r   )r   r&   s    r   r!   zMetricValue.instance<   r'   r   c                     | j                   S r   )r   r&   s    r   r"   zMetricValue.value@   s    {{r   c                     | j                   S r   )r   r&   s    r   r#   zMetricValue.report_periodD   s    """r   N)r   r   r   __doc___DEFAULT_REPORT_PERIODr$   propertyr   r    r!   r"   r#   r   r   r   r   r   '   sw     J` ,         # #r   r   c                       e Zd ZdZdZy)MetricsCategoryMemoryCPUN)r   r   r   MEMORY_CATEGORYCPU_CATEGORYr   r   r   r0   r0   I   s    OLr   r0   c                   (    e Zd ZdZdZdZdZdZdZdZ	y)	MetricsCounterz% Processor TimezTotal Memory UsagezMax Memory UsagezThrottled TimezSwap Memory UsagezAvailable MByteszUsed MBytesN)
r   r   r   PROCESSOR_PERCENT_TIMETOTAL_MEM_USAGEMAX_MEM_USAGETHROTTLED_TIMESWAP_MEM_USAGEAVAILABLE_MEMUSED_MEMr   r   r   r6   r6   N   s&    /*O&M%N(N&MHr   r6   zuser (\d+)\nsystem (\d+)\nc                   8    e Zd Zd Zd Zd Zd Zd	dZd Zd Z	y)
CGroupc                      || _         || _        y)z
        Initialize _data collection for the Memory controller
        :param: name: Name of the CGroup
        :param: cgroup_path: Path of the controller
        :return:
        N)namepath)r   rA   cgroup_paths      r   r$   zCGroup.__init__\   s     		r   c                 N    dj                  | j                  | j                        S )Nz	{0} [{1}])formatrA   rB   r&   s    r   __str__zCGroup.__str__f   s    !!$))TYY77r   c                 V    t         j                  j                  | j                  |      S r   )osrB   join)r   	file_names     r   _get_cgroup_filezCGroup._get_cgroup_filei   s    ww||DIIy11r   c                 N    | j                  |      }t        j                  |      S )z
        Retrieve the contents to file.

        :param str file_name: Name of file within that metric controller
        :return: Entire contents of the file
        :rtype: str
        )rK   r	   	read_file)r   rJ   parameter_files      r   _get_file_contentszCGroup._get_file_contentsl   s%     ..y9!!.11r   c                    g }	 | j                  |      j                         }|r|d   }|S |}|S # t        $ rP | j                  |      }t	        j
                  dj                  |             t        dj                  |            t        $ rf}t        |t        t        f      r|j                  t        j                  k(  r|| j                  |      }t        dj                  |      |      d}~ww xY w)a[  
        Retrieve the values of a parameter from a controller.
        Returns a list of values in the file.

        :param first_line_only: return only the first line.
        :param str parameter_name: Name of file within that metric controller
        :return: The first line of the file, without line terminator
        :rtype: [str]
        r   z#File {0} is empty but should not be&Exception while attempting to read {0}N)rO   
splitlines
IndexErrorrK   r   errorrE   r   	Exception
isinstanceIOErrorOSErrorerrnoENOENT)r   parameter_namefirst_line_onlyresultvaluesparameter_filenamees          r   _get_parameterszCGroup._get_parametersx   s     	k,,^<GGIF"1VAYF  8>F   	e!%!6!6~!FLL>EEFXYZ"#H#O#OPb#cdd 	k!gw/0QWW5L!%!6!6~!F"#K#R#RSe#fhijj		ks   &0 0 A C6A!C11C6c           
         	 | j                  d      }|rt        |      dk7  S 	 y# t        t        f$ ro}|j                  t        j
                  k(  rnGt        j                  t        j                  dj                  | j                  t        |                   Y d }~yd }~wt        $ rQ}t        j                  t        j                  dj                  | j                  t        |                   Y d }~yd }~ww xY w)Ntasksr   zUCould not get list of tasks from "tasks" file in the cgroup: {0}. Internal error: {1}F)ra   lenrW   rX   rY   rZ   r   periodic_warnEVERY_HALF_HOURrE   rB   r   r   )r   rc   r`   s      r   	is_activezCGroup.is_active   s    	T((1E5zQ&   ! 	Xww%,,&$$V%;%;&<<BF499dSTg<VX 	   	T  !7!7"88>tyy$q'8RT T 		Ts"    % C;A%BC;*AC66C;c                     t               )z
        Retrieves the current value of the metrics tracked for this cgroup and returns them as an array.

        Note: Agent won't track the metrics if the current cpu ticks less than previous value and returns empty array.
        )NotImplementedErrorr   _s     r   get_tracked_metricszCGroup.get_tracked_metrics   s     "##r   NF)
r   r   r   r$   rF   rK   rO   ra   rg   rl   r   r   r   r?   r?   [   s%     82
22&$r   r?   c                   L     e Zd Z fdZd	dZd Zd Zd Zd Zd
dZ	d Z
 xZS )	CpuCgroupc                     t         t        |   ||       t               | _        d | _        d | _        d | _        d | _        d | _	        d | _
        y r   )superro   r$   r   _osutil_previous_cgroup_cpu_previous_system_cpu_current_cgroup_cpu_current_system_cpu_previous_throttled_time_current_throttled_timer   rA   rC   	__class__s      r   r$   zCpuCgroup.__init__   sM    i'k:!|$(!$(!#' #' (,%'+$r   c                 
   	 | j                  d      }d}|zt        j                  |      }|s*t        dj                  | j                  d      |            t        |j                         d         t        |j                         d         z   }|S # t        $ rf}t        |t        t        f      r|j
                  t
        j                  k7  r#t        dj                  t        |                  |s|d}Y d}~d}~ww xY w)a:  
        Returns the number of USER_HZ of CPU time (user and system) consumed by this cgroup.

        If allow_no_such_file_or_directory_error is set to True and cpuacct.stat does not exist the function
        returns 0; this is useful when the function can be called before the cgroup has been created.
        zcpuacct.statz Failed to read cpuacct.stat: {0}Nr   z$The contents of {0} are invalid: {1}r
   )rO   rU   rV   rW   rX   rY   rZ   r   rE   r   re_user_system_timesmatchrK   intgroups)r   %allow_no_such_file_or_directory_errorcpuacct_statr`   	cpu_ticksr}   s         r   _get_cpu_tickszCpuCgroup._get_cpu_ticks   s    	 22>BL 	# )..|<E&:AA$BWBWXfBgiuvx xELLN1-.U\\^A5F1GGI-  	 a'7!345<<8O&'I'P'PQUVWQX'YZZ8L	 s   B 	DAC==Dc                 z   	 t        t        j                  j                  | j                  d            5 }|D ]`  }t	        j
                  d|      }d}|t	        j
                  d|      }d}|8t        |j                         d   |z        c cd d d        S  t        d      # 1 sw Y   y xY w# t        t        f$ rJ}|j                  t        j                  k(  rY d }~yt        dj                  t        |                  d }~wt        $ r(}t        dj                  t        |                  d }~ww xY w)	Nzcpu.statzthrottled_time\s+(\d+)r
   zthrottled_usec\s+(\d+)d   r   zCannot find throttled_timezFailed to read cpu.stat: {0})openrH   rB   rI   rer}   r~   r   rU   rW   rX   rY   rZ   r   rE   r   )r   cpu_statliner}   
multiplierr`   s         r   get_throttled_timezCpuCgroup.get_throttled_time   s   	Sbggll499j9: >h % CDHH%>EE!"J} ")BD I%(
("5<<>!#4z#ABB+> >C   <==-> >. ! 	Sww%,,&"#A#H#Ha#QRR 	S"#A#H#Ha#QRR	SsR   3B2 :B&0 B&	B2 B&&B/+B2 /B2 2D:D##DD:#D55D:c                 >    | j                   d uxr | j                  d uS r   )ru   rv   r&   s    r   _cpu_usage_initializedz CpuCgroup._cpu_usage_initialized   s$    ''t3\8P8PX\8\\r   c                     | j                         rt        d      | j                  d      | _        | j                  j                         | _        | j                         | _        y)zu
        Sets the initial values of CPU usage. This function must be invoked before calling get_cpu_usage().
        z2initialize_cpu_usage() should be invoked only onceT)r   N)	r   r   r   ru   rr   get_total_cpu_ticks_since_bootrv   r   rx   r&   s    r   initialize_cpu_usagezCpuCgroup.initialize_cpu_usage   sY     &&("#WXX#'#6#6]a#6#b #'<<#N#N#P '+'>'>'@$r   c                    | j                         st        d      | j                  | _        | j                  | _        | j                         | _        | j                  j                         | _        | j                  | j                  z
  }t        d| j                  | j
                  z
        }t        d| j                  j                         z  t        |      z  t        |      z  d      S )ag  
        Computes the CPU used by the cgroup since the last call to this function.

        The usage is measured as a percentage of utilization of 1 core in the system. For example,
        using 1 core all of the time on a 4-core system would be reported as 100%.

        NOTE: initialize_cpu_usage() must be invoked before calling get_cpu_usage()
        zOinitialize_cpu_usage() must be invoked before the first call to get_cpu_usage()r
   g      Y@   )r   r   ru   rs   rv   rt   r   rr   r   maxroundget_processor_coresfloat)r   cgroup_deltasystem_deltas      r   get_cpu_usagezCpuCgroup.get_cpu_usage  s     **,"#tuu$($<$<!$($<$<!#'#6#6#8 #'<<#N#N#P //$2K2KK1d669R9RRSUT\\==??%BUUX]^jXkkmnoor   c                 
   |st        | j                         dz        S | j                         st        d      | j                  | _        | j                         | _        t        | j                  | j
                  z
        dz  S )a  
        Computes the throttled time (in seconds) since the last call to this function.
        NOTE: initialize_cpu_usage() must be invoked before calling this function
        Compute only current throttled time if read_previous_throttled_time set to False
        g    eAzTinitialize_cpu_usage() must be invoked before the first call to get_throttled_time())r   r   r   r   rx   rw   )r   read_previous_throttled_times     r   get_cpu_throttled_timez CpuCgroup.get_cpu_throttled_time  s     ,002S899**,"fh h )-(D(D%'+'>'>'@$T11D4Q4QQRUXXXr   c                    g }| j                         }|t        d      k\  rC|j                  t        t        j
                  t        j                  | j                  |             d|v rt|d   ro| j                         }|t        d      k\  rQ|t        d      k\  rC|j                  t        t        j
                  t        j                  | j                  |             |S )Nr   track_throttled_time)r   r   appendr   r0   r4   r6   r7   rA   r   r:   )r   kwargstracked	cpu_usagethrottled_times        r   rl   zCpuCgroup.get_tracked_metrics/  s    &&(	a NNO88.:_:_aeajajluvx "V+7M0N!88:NE!H$58)C < <n>[>[]a]f]fhvwy r   rm   )T)r   r   r   r$   r   r   r   r   r   r   rl   __classcell__rz   s   @r   ro   ro      s2    	,BS@]Ap,Y$r   ro   c                   <     e Zd Z fdZd Zd Zd Zd Zd Z xZ	S )MemoryCgroupc                 <    t         t        |   ||       d| _        y )Nr   )rq   r   r$   _counter_not_found_error_country   s      r   r$   zMemoryCgroup.__init__@  s    lD*4=./+r   c                    	 t        t        j                  j                  | j                  d            5 }|D ]R  }dj	                  |      }t        j                  ||      }|-t        |j                         d         c cd d d        S  	 d d d        t!        dj	                  |            # 1 sw Y   #xY w# t        t        f$ rF}|j                  t        j                  k(  r t        dj	                  t        |                  d }~wt        $ r(}t        dj	                  t        |                  d }~ww xY w)Nzmemory.statz{0}\s+(\d+)r   zFailed to read memory.stat: {0}zCannot find counter: {0})r   rH   rB   rI   rE   r   r}   r~   r   rW   rX   rY   rZ   r   r   rU   r   )r   counter_namememory_statr   re_memory_counterr}   r`   s          r   _get_memory_stat_counterz%MemoryCgroup._get_memory_stat_counterE  s   	Vbggll499m<= 
6 ( 6D(6(=(=l(K%HH%6=E("5<<>!#455
6 
66
6$ 8??MNN%
6 
6 ! 	Vww%,,&"#D#K#KDQRG#TUU 	V"#D#K#KDQRG#TUU	VsM   3B< /B0%B0	B< B0B< 0B95B< <E ADE #D;;E c                 P    | j                  d      }| j                  d      }||z   S )zx
        Collect RSS+CACHE from memory.stat cgroup.

        :return: Memory usage in bytes
        :rtype: int
        cacherss)r   )r   r   r   s      r   get_memory_usagezMemoryCgroup.get_memory_usage[  s.     --g6++E2s{r   c           	      (   	 | j                  d      S # t        $ ru}| j                  dk  r\t        j                  t        j
                  dj                  t        |      | j                               | xj                  dz  c_        Y d}~yd}~ww xY w)a  
        Collect SWAP from memory.stat cgroup.

        :return: Memory usage in bytes
        :rtype: int
        Note: stat file is the only place to get the SWAP since other swap related file memory.memsw.usage_in_bytes is for total Memory+SWAP.
        swapr
   zs{0} from "memory.stat" file in the cgroup: {1}---[Note: This log for informational purpose only and can be ignored]Nr   )	r   r   r   r   periodic_inforf   rE   r   rB   )r   r`   s     r   try_swap_memory_usagez"MemoryCgroup.try_swap_memory_usageg  s    	0088 	22Q6$$V%;%; &[  &b  &b  cg  hi  cj  lp  lu  lu  &vw33q83	s    	BA+BBc                    d}	 t        | j                  dd            }|S # t        $ rT}t        |t        t
        f      r|j                  t        j                  k(  r t        dj                  d      |      d}~ww xY w)z
        Collect memory.max_usage_in_bytes from the cgroup.

        :return: Memory usage in bytes
        :rtype: int
        r   zmemory.max_usage_in_bytesT)r\   rQ   N)
r~   ra   rU   rV   rW   rX   rY   rZ   r   rE   )r   usager`   s      r   get_max_memory_usagez!MemoryCgroup.get_max_memory_usagex  s     	t,,-HZ^,_`E   	t!gw/0QWW5L"#K#R#RSn#oqrss	ts   " 	A?AA::A?c           	         t        t        j                  t        j                  | j
                  | j                               t        t        j                  t        j                  | j
                  | j                         t              t        t        j                  t        j                  | j
                  | j                         t              gS r   )r   r0   r3   r6   r8   rA   r   r9   r   _REPORT_EVERY_HOURr;   r   rj   s     r   rl   z MemoryCgroup.get_tracked_metrics  s    779W9WY]YbYb--/1779U9UW[W`W`1135GI779V9VX\XaXa2246HJ
 	
r   )
r   r   r   r$   r   r   r   r   rl   r   r   s   @r   r   r   ?  s"    0
O,
""
r   r   ) rY   rH   r   datetimer   azurelinuxagent.commonr   r    azurelinuxagent.common.exceptionr   azurelinuxagent.common.futurer   azurelinuxagent.common.osutilr   azurelinuxagent.common.utilsr	   r   get_cgroup_check_periodr-   AGENT_NAME_TELEMETRYAGENT_LOG_COLLECTORrU   r   objectr   r0   r6   compiler|   r?   ro   r   r   r   r   <module>r      s   "  	 	  / = . 4 1Q' "+G4+G+G+IJ - 7 	i 	#& #Df 
V  "rzz"?@ O$V O$dO OdR
6 R
r   