U
    Ld.                     @   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
dd e	 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d0d1 Zd:d4d5Zd6d7 Z d8d9 Z!dS );    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%T c                 C   s$   g | ]\}}d  |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>1   s     r   Z
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itemsr   r   )msgeventijr   r   r   format_record9   s    r!   c                 C   s   | r|  dS d S )Nr
   getr   r   r   r   
event_nameD   s    
r%   c                 C   s   | r|  dS d S )Nr   r"   r$   r   r   r   r   J   s    
c                 C   s   | rt | dd S d S )N/r   )r%   splitr$   r   r   r   event_parentP   s    r(   c                 C   s   t | dS Nr   )floatr#   r$   r   r   r   event_timestampV   s    r+   c                 C   s   t j t| S N)datetimeZutcfromtimestampr+   r$   r   r   r   event_datetimeZ   s    r.   c                 C   s   ||    S r,   )Ztotal_seconds)t1t2r   r   r   delta_seconds^   s    r1   c                 C   s   t t| t|S r,   )r1   r.   )startfinishr   r   r   event_durationb   s    r4   c              	   C   sH   |  }|t||t| t|ddt|dd   d d |S )N|r   r&      z`->)r   r   r   )copyupdater4   r1   r.   r%   count)
start_timer2   r3   recordr   r   r   event_recordf   s    r<   c                 C   s   d|  S )NzTotal Time: %3.5f seconds
r   )r   r   r   r   total_time_records   s    r=   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)rC   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 ({})=r6   i@B )r   RuntimeErrorr   r?   r'   r*   )rC   r   r   r   r   parse_epoch_as_float   s    	z$SystemctlReader.parse_epoch_as_float)N)__name__
__module____qualname____doc__rE   r   rL   r   r   r   r   r>   w   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
    
rV   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dmesgTrF   r   zUTF-8userr   r6   ])r   
splitlinesdecodefindr'   stripr*   timer   uptimeSUCCESS_CODErG   rU   )	data_Zsplit_entriesr   ZsplitupstrippedZuser_space_timestampkernel_start
kernel_endr   r   r   rT      s    rT   c            
   
   C   s   t t t t  } ztd }tdd }| }t}t rt t t t  }zt	
d}|j} W n2 tk
r } ztd||W 5 d}~X Y nX t}|| }|| }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-localz/proc/1/cmdlinezBCould not determine container boot time from /proc/1/cmdline. ({})N)r*   r]   r   r^   r>   rL   r_   Zis_container	monotonicosstatst_atimeOSErrorrK   r   CONTAINER_CODErG   printrU   )
rc   Zdelta_k_endZ
delta_ci_sZ	base_timeZstatusZ	file_statrI   rd   Zcloudinit_sysder   r   r   rR      s>     

rR   F(%n) %d seconds in %I%Dc              	   C   s  t | dd d}g }d}d}i }	g }
g }tdt|D ]F}| | }z| |d  }W n tk
rl   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	  || q6q6| }t
|t
|krtt|||}|td|d  ||d7 }q6|| q6|t| |
| |
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
    c                 S   s   | d S r)   r   )xr   r   r   <lambda>$      z"generate_records.<locals>.<lambda>)keyNg        r   r6   r2   r
   z
init-localr3   zStarting stage: %szFinished stage: (%n) %d seconds
r   )sortedrangelen
IndexErrorr   r#   rA   r=   r.   r(   r%   r!   r<   pop)eventsZ
blame_sortprint_formatZ
dump_filesZlog_datafilesZsorted_eventsZrecordsr:   r   Zstage_start_timeZboot_recordsZunprocessedrl   r   Znext_evtZprev_evtr;   r   r   r   generate_records  s^    




rz   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
    )ry   )rz   )rx   ry   r   r   r   show_events_  s    
r{   c                 C   s:   |   }zt||fW S  tk
r4   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
    N)readjsonloads
ValueError)Zinfiler`   r   r   r   load_events_infilel  s
    r   )Frm   FF)"r-   r}   rf   r]   Z	cloudinitr   r   Zcloudinit.distrosr   r   joinr   Zformatting_helpr_   Z	FAIL_CODErj   rU   r!   r%   r   r(   r+   r.   r1   r4   r<   r=   r>   rV   rT   rR   rz   r{   r   r   r   r   r   <module>   sZ   50    
P