
"T`j2                 @   s  d  d l  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 d  d l	 m
 Z
 d d d d d	 d
 d d d d d d d d d d d d d d d d i Z d j d d   e j   D  Z d Z d Z d  Z e dG dH dI f Z d" d#   Z d$ d%   Z d& d'   Z d( d   Z d) d*   Z d+ d,   Z d- d.   Z d/ d0   Z d1 d2   Z d3 d4   Z d5 d6   Z Gd7 d8   d8 e  Z d9 d:   Z  d; d<   Z! d= d>   Z" d? d@ d? d? dA dB  Z# dC dD   Z$ dE dF   Z% d S)J    N)subp)util)uses_systemdz%ddeltaz%DZdescriptionz%Eelapsedz%e
event_typez%Iindentz%llevelz%nnamez%ooriginz%rresultz%t	timestampz%T
total_time c             C   s4   g  |  ]* \ } } d  j  | j d d  |   q S)z{0}: {1}%z%%)formatreplace).0kv r   8/usr/lib/python3/dist-packages/cloudinit/analyze/show.py
<listcomp>3   s   	r   Z
successfulfailureZ	container   c             C   sq   xa t  j   D]S \ } } | |  k r | d k rJ |  j | d |  }  q |  j | d |  }  q W|  j |   S)Nr   r   r   z
{%s:08.5f}z{%s})r   zelapsedz	timestamp)
format_keyitemsr   r   )msgeventijr   r   r   format_record;   s    r!   c             C   s   t  d d   |  j   D  } | d } g  } xc | D][ } | d } t j j |  } t j | d  j d  } t j	 | |  | j
 |  q6 W| S)Nc             s   s-   |  ]# \ } } | d k r | | f Vq d S)contentN)zcontentr   )r   r   r   r   r   r   	<genexpr>G   s    z#dump_event_files.<locals>.<genexpr>filespathr"   ascii)dictr   osr%   basenamebase64Z	b64decodedecoder   Z
write_fileappend)r   r"   r$   ZsavedffnameZfn_localZfcontentr   r   r   dump_event_filesF   s    

r/   c             C   s   |  r |  j  d  Sd  S)Nr
   )get)r   r   r   r   
event_nameT   s    r1   c             C   s   |  r |  j  d  Sd  S)Nr   )r0   )r   r   r   r   r   Z   s    c             C   s!   |  r t  |   j d  d Sd  S)N/r   )r1   split)r   r   r   r   event_parent`   s    r4   c             C   s   t  |  j d   S)Nr   )floatr0   )r   r   r   r   event_timestampf   s    r6   c             C   s   t  j  j t |    S)N)datetimeZutcfromtimestampr6   )r   r   r   r   event_datetimej   s    r8   c             C   s   | |  j    S)N)Ztotal_seconds)Zt1Zt2r   r   r   delta_secondsn   s    r9   c             C   s   t  t |   t |   S)N)r9   r8   )startfinishr   r   r   event_durationr   s    r<   c          
   C   sf   | j    } | j d t | |  d t |  t |   d d d t |  j d  d d i  | S)	Nr   r   r   |r   r2   r   z`->)copyupdater<   r9   r8   r1   count)
start_timer:   r;   recordr   r   r   event_recordv   s    ,rC   c             C   s   d |  S)NzTotal Time: %3.5f seconds
r   )r   r   r   r   total_time_record   s    rD   c               @   s=   e  Z d  Z d Z d d d  Z d d   Z d d   Z d S)	SystemctlReaderzQ
    Class for dealing with all systemctl subp calls in a consistent manner.
    Nc             C   sW   d  |  _  d d g |  _ | r. |  j j |  |  j j d | g  |  j   |  _ d  S)Nz/bin/systemctlZshowz-p)epochargsr,   extendr   r   )selfpropertyZ	parameterr   r   r   __init__   s    	zSystemctlReader.__init__c             C   si   y9 t  j  |  j d d \ } } | r+ | S| |  _ d SWn) t k
 rd } z	 | SWYd d } ~ Xn Xd S)z
        Make a subp call based on set args and handle errors by setting
        failure code

        :return: whether the subp call failed or not
        captureTN)r   rG   rF   	Exception)rI   valueerrZsystemctl_failr   r   r   r      s    	zSystemctlReader.subpc             C   sE   |  j  r! t d j |  j     |  j j d  d } t |  d S)z{
        If subp call succeeded, return the timestamp from subp as a float.

        :return: timestamp as a float
        zBSubprocess call to systemctl has failed, returning error code ({})=r   i@B )r   RuntimeErrorr   rF   r3   r5   )rI   r   r   r   r   parse_epoch_as_float   s
    			z$SystemctlReader.parse_epoch_as_float)__name__
__module____qualname____doc__rK   r   rR   r   r   r   r   rE      s   rE   c               C   sC   t    r t   St j   s8 d t j   d j   k r? t   St S)a2  
    Determine which init system a particular linux distro is using.
    Each init system (systemd, upstart, etc) has a different way of
    providing timestamps.

    :return: timestamps of kernelboot, kernelendboot, and cloud-initstart
    or TIMESTAMP_UNKNOWN if the timestamps cannot be retrieved.
    Zgentoosystem)r   gather_timestamps_using_systemdr   Z
is_FreeBSDZsystem_infolowergather_timestamps_using_dmesgTIMESTAMP_UNKNOWNr   r   r   r   dist_check_timestamp   s    
	r\   c        	      C   s   y t  j  d g d d \ }  } |  d j   } x | D] } | j d  j d  d	 k r8 | j d  j   } | d j d  } t |  } t t j    t t j	    } | | } t
 | | | f Sq8 WWn t k
 r Yn Xt S)
a  
    Gather timestamps that corresponds to kernel begin initialization,
    kernel finish initialization using dmesg as opposed to systemctl

    :return: the two timestamps plus a dummy timestamp to keep consistency
    with gather_timestamps_using_systemd
    ZdmesgrL   Tr   zUTF-8userr   ])r   
splitlinesr+   findr3   stripr5   timer   uptimeSUCCESS_CODErM   r[   )	data_Zsplit_entriesr   ZsplitupZstrippedZuser_space_timestampkernel_start
kernel_endr   r   r   rZ      s    "
	rZ   c        
      C   s[  t  t j    t  t j    }  y t d  j   } t d d  j   } |  } t } t j   r t j	 d k r t  t j    t  t j
    } y t j d  } | j }  Wn= t k
 r } z t d j |   |  WYd d } ~ Xn Xt } n t } | | } | | } Wn3 t k
 rJ}	 z t |	  t SWYd d }	 ~	 Xn X| |  | | f S)	z
    Gather timestamps that corresponds to kernel begin initialization,
    kernel finish initialization. and cloud-init systemd unit activation

    :return: the three timestamps
    ZUserspaceTimestampMonotonicZInactiveExitTimestampMonotoniczcloud-init-local   z/proc/1/cmdlinezBCould not determine container boot time from /proc/1/cmdline. ({})N)rj   rj   )r5   rc   r   rd   rE   rR   re   Zis_containersysversion_infoZ	monotonicr(   statst_atimeOSErrorrQ   r   CONTAINER_CODE	FAIL_CODErM   printr[   )
rh   Zdelta_k_endZ
delta_ci_sZ	base_timeZstatusZ	file_statrO   ri   Zcloudinit_sysder   r   r   rX      s0    ""	"	

rX   Fz(%n) %d seconds in %I%Dc             C   sI  t  |  d d d   } g  } d } d } i  }	 g  }
 g  } g  } xt d t |   D]} |  | } y |  | d } Wn t k
 r d } Yn Xt |  d k r| j d	  |
 k r | j t |   | j |  g  } d } d } | d k rg  }
 t |  } | |	 t	 |  <t
 |  t
 |  k rkt |  d
 k r| j t | t | | |    q!| j d | j d	   | j |  |
 j | j d	   qX qX | j   } t
 |  t
 |  k rt | | |  } | j t d |  d  | | j d  7} qX | j |  qX W| j t |   | j |  | S)a2  
    Take in raw events and create parent-child dependencies between events
    in order to order events in chronological order.

    :param events: JSONs from dump that represents events taken from logs
    :param blame_sort: whether to sort by timestamp or by time taken.
    :param print_format: formatting to represent event, time stamp,
    and time taken by the event in one line
    :param dump_files: whether to dump files into JSONs
    :param log_datafiles: whether or not to log events generated

    :return: boot records ordered chronologically
    keyc             S   s   |  d S)Nr   r   )xr   r   r   <lambda>/  s    z"generate_records.<locals>.<lambda>Ng        r   r   r:   r
   r;   zStarting stage: %szFinished stage: (%n) %d seconds
r   )sortedrangelen
IndexErrorr   r0   r,   rD   r8   r4   r1   r!   rC   pop)eventsZ
blame_sortprint_formatZ
dump_filesZlog_datafilesZsorted_eventsZrecordsrA   r   Zstage_start_timeZstages_seenZboot_recordsZunprocessedrs   r   Znext_evtZprev_evtrB   r   r   r   generate_records  sZ    
r   c             C   s   t  |  d | S)a<  
    A passthrough method that makes it easier to call generate_records()

    :param events: JSONs from dump that represents events taken from logs
    :param print_format: formatting to represent event, time stamp,
    and time taken by the event in one line

    :return: boot records ordered chronologically
    r~   )r   )r}   r~   r   r   r   show_eventsj  s    
r   c             C   sF   |  j    } y t j |  | f SWn t k
 rA d | f SYn Xd S)z
    Takes in a log file, read it, and convert to json.

    :param infile: The Log file to be read

    :return: json version of logfile, raw file
    N)readjsonloads
ValueError)Zinfilerf   r   r   r   load_events_infilew  s
    r   r_   r_   r_   )&r*   r7   r   r(   rc   rk   Z	cloudinitr   r   Zcloudinit.distrosr   r   joinr   Zformatting_helpre   rq   rp   r[   r!   r/   r1   r   r4   r6   r8   r9   r<   rC   rD   objectrE   r\   rZ   rX   r   r   r   r   r   r   r   <module>   sZ   3 /J