U
    Ӈg,+                     @   s  d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ dddddd	d
dddddZ	dZ
dZdZedddfZd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$ Zd%d& ZG d'd( d(Zd)d* Zd+d, Zd-d. Zd6d0d1Zd2d3 Zd4d5 ZdS )7    N)subputil)uses_systemddeltaZdescriptionelapsed
event_typeindentlevelnameoriginresult	timestamp
total_time)z%dz%Dz%Ez%ez%Iz%lz%nz%oz%rz%tz%TZ
successfulfailureZ	containerc                 C   sP   t  D ]:\}}|| kr|dkr2| |d| } q| |d| } q| jf |S )N)r   r   r   z
{%s:08.5f}z{%s})
format_keyitemsreplaceformat)msgeventij r   8/usr/lib/python3/dist-packages/cloudinit/analyze/show.pyformat_record6   s    r   c                 C   s   | r|  dS d S )Nr
   getr   r   r   r   
event_nameA   s    
r   c                 C   s   | r|  dS d S )Nr   r   r   r   r   r   r   G   s    
c                 C   s   | rt | dd S d S )N/r   )r   splitr   r   r   r   event_parentM   s    r"   c                 C   s   t | dS Nr   )floatr   r   r   r   r   event_timestampS   s    r%   c                 C   s   t j t| t jjS N)datetimeZfromtimestampr%   timezoneZutcr   r   r   r   event_datetimeW   s     r)   c                 C   s   ||    S r&   )Ztotal_seconds)t1t2r   r   r   delta_seconds]   s    r,   c                 C   s   t t| t|S r&   )r,   r)   )startfinishr   r   r   event_durationa   s    r/   c              	   C   sH   |  }|t||t| t|ddt|dd   d d |S )N| r       z`->)r   r   r   )copyupdater/   r,   r)   r   count)
start_timer-   r.   recordr   r   r   event_recorde   s    r8   c                 C   s   d|  S )NzTotal Time: %3.5f seconds
r   )r   r   r   r   total_time_recordr   s    r9   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   sD   d | _ tddg| _|r&| j| | jd|g |  | _d S )NZ	systemctlZshowz-p)epochr   Zwhichargsappendextendr   )selfpropertyZ	parameterr   r   r   __init__{   s    zSystemctlReader.__init__c              
   C   sZ   z*t j | jdd\}}|r |W S || _W dS  tk
rT } z| W Y S d}~X Y nX d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
        TZcaptureN)r   r<   r;   	Exception)r?   valueerrZsystemctl_failr   r   r   r      s    zSystemctlReader.subpc                 C   s2   | j rtd| 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 ({})=r2   i@B )r   RuntimeErrorr   r;   r!   r$   )r?   r   r   r   r   parse_epoch_as_float   s    	z$SystemctlReader.parse_epoch_as_float)N)__name__
__module____qualname____doc__rA   r   rH   r   r   r   r   r:   v   s   
r:   c                   C   s2   t  rt S t s(dt d  kr.t S tS )a)  
    Determine which init system a particular linux distro is using.
    Each init system (systemd, 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
    
rR   c            	      C   s   zt j dgdd\} }| d  }|D ]n}|dddkr&|d }|d d	}t|}tt tt	  }|| }t
|||f  W S q&W n tk
r   Y nX t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dmesgTrB   r   zUTF-8userr   r2   ])r   
splitlinesdecodefindr!   stripr$   timer   uptimeSUCCESS_CODErC   rQ   )	data_Zsplit_entriesr   ZsplitupstrippedZuser_space_timestampkernel_start
kernel_endr   r   r   rP      s    rP   c               
   C   s   t t t t  } zBtd }tdd }| }t}t rHt}|| }|| }W n2 t	k
r } zt
| t W Y S d}~X Y n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-localN)r$   rY   r   rZ   r:   rH   r[   Zis_containerCONTAINER_CODErC   printrQ   )r_   Zdelta_k_endZ
delta_ci_sZ	base_timeZstatusr`   Zcloudinit_sysder   r   r   rN      s&     rN   (%n) %d seconds in %I%Dc              	   C   s  t | dd d}g }d}d}i }g }g }tt|D ]F}	| |	 }
z| |	d  }W n tk
rj   d}Y nX t|
dkr(|r|
dd	kr|t| || g }d}d}|dkrt|
}||t	|
< t
|
t
|krt|d
kr&|t|t||
| n |d|
d  ||
 q4q4| }t
|
t
|krrt|||
}|td|d  ||d7 }q4|| q4|t| || |S )as  
    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 print_format: formatting to represent event, time stamp,
    and time taken by the event in one line

    :return: boot records ordered chronologically
    c                 S   s   | d S r#   r   )xr   r   r   <lambda>      z"generate_records.<locals>.<lambda>)keyNg        r2   r-   r
   z
init-localr.   zStarting stage: %szFinished stage: (%n) %d seconds
r   )sortedrangelen
IndexErrorr   r   r=   r9   r)   r"   r   r   r8   pop)eventsprint_formatZsorted_eventsZrecordsr6   r   Zstage_start_timeZboot_recordsZunprocessedrc   r   Znext_evtZprev_evtr7   r   r   r   generate_records  s^    




rq   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
    )rp   )rq   )ro   rp   r   r   r   show_eventsK  s    
rr   c                 C   s^   |   }| s,tjd| j  td zt||fW S  t	k
rX   d|f Y S X d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
    zEmpty file %s
r2   N)
readrX   sysstderrwriter
   exitjsonloads
ValueError)Zinfiler\   r   r   r   load_events_infileX  s    
r{   )rd   )r'   rx   rt   rY   Z	cloudinitr   r   Zcloudinit.distrosr   r   r[   Z	FAIL_CODEra   rQ   r   r   r   r"   r%   r)   r,   r/   r8   r9   r:   rR   rP   rN   rq   rr   r{   r   r   r   r   <module>   sN   5# 
J