o
    w7e.                     @   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	2	3	2	2d:d4d5Zd6d7 Z d8d9 Z!dS );    N)subputil)uses_systemddelta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   
successfulfailure	containerc                 C   sT   t  D ]\}}|| v r!|dv r| |d| } q| |d| } q| jdi |S )N)r   r   r   z
{%s:08.5f}z{%s}r   )
format_keyitemsr   r   )msgeventijr   r   r   format_record9   s   r$   c                 C      | r|  dS d S )Nr   getr!   r   r   r   
event_nameD      
r)   c                 C   r%   )Nr   r&   r(   r   r   r   r   J   r*   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   r0   c                 C   s   t j t| S N)datetimeutcfromtimestampr0   r(   r   r   r   event_datetimeZ   s   r4   c                 C   s   ||    S r1   )total_seconds)t1t2r   r   r   delta_seconds^   s   r8   c                 C   s   t t| t|S r1   )r8   r4   )startfinishr   r   r   event_durationb   s   r;   c              	   C   sH   |  }|t||t| t|ddt|dd   d d |S )N|r   r+      z`->)r   r   r	   )copyupdater;   r8   r4   r)   count)
start_timer9   r:   recordr   r   r   event_recordf   s   rC   c                 C   s   d|  S )NzTotal Time: %3.5f seconds
r   )r   r   r   r   total_time_records   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   sD   d | _ tddg| _|r| j| | jd|g |  | _d S )N	systemctlshowz-p)epochr   whichargsappendextendr   )selfproperty	parameterr   r   r   __init__|   s   zSystemctlReader.__init__c              
   C   sT   zt j | jdd\}}|r|W S || _W dS  ty) } z|W  Y d}~S d}~ww )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captureN)r   rJ   rH   	Exception)rM   valueerr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 ({})=r=   i@B )r   RuntimeErrorr   rH   r,   r/   )rM   r   r   r   r   parse_epoch_as_float   s   	z$SystemctlReader.parse_epoch_as_floatr1   )__name__
__module____qualname____doc__rP   r   rY   r   r   r   r   rE   w   s
    
rE   c                   C   s2   t  rt S t sdt d  v 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.
    gentoosystem)r   gather_timestamps_using_systemdr   
is_FreeBSDsystem_infolowergather_timestamps_using_dmesgTIMESTAMP_UNKNOWNr   r   r   r   dist_check_timestamp   s
   
rf   c            	      C   s   zMt j dgdd\} }| d  }|D ]7}|dddkrJ|d }|d d	}t|}tt tt	  }|| }t
|||f  W S qW tS  tyW   Y tS w )
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
    dmesgTrQ   r   zUTF-8userr   r=   ])r   
splitlinesdecodefindr,   stripr/   timer   uptimeSUCCESS_CODErS   re   )	data_split_entriesr"   splitupstrippeduser_space_timestampkernel_start
kernel_endr   r   r   rd      s$   rd   c            
   
   C   s   t t t t  } zLtd }tdd }| }t}t rOt t t t  }z
t	
d}|j} W n tyL } ztd||d}~ww t}|| }|| }W n typ }	 zt|	 tW  Y d}	~	S d}	~	ww || ||fS )z
    Gather timestamps that corresponds to kernel begin initialization,
    kernel finish initialization. and cloud-init systemd unit activation

    :return: the three timestamps
    UserspaceTimestampMonotonicInactiveExitTimestampMonotoniczcloud-init-localz/proc/1/cmdlinezBCould not determine container boot time from /proc/1/cmdline. ({})N)r/   rn   r   ro   rE   rY   rp   is_container	monotonicosstatst_atimeOSErrorrX   r   CONTAINER_CODErS   printre   )
rw   delta_k_end
delta_ci_s	base_timestatus	file_statrU   rx   cloudinit_sysder   r   r   r`      sJ   

r`   F(%n) %d seconds in %I%Dc              	   C   s  t | dd d}g }d}d}i }	g }
g }tdt|D ]}| | }z| |d  }W n ty4   d}Y nw t|dkr|rV|d	d
krV|t| |
| g }d}d}|du rdt|}||	t	|< t
|t
|krt|dkr~|t|t||| q|d|d	  || q| }t
|t
|krt|||}|td|d  ||d7 }q|| q|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>$  s    z"generate_records.<locals>.<lambda>)keyNg        r   r=   r9   r   z
init-localr:   zStarting stage: %szFinished stage: (%n) %d seconds
r   )sortedrangelen
IndexErrorr   r'   rK   rD   r4   r-   r)   r$   rC   pop)events
blame_sortprint_format
dump_fileslog_datafilessorted_eventsrecordsrA   r   stage_start_timeboot_recordsunprocessedr   r!   next_evtprev_evtrB   r   r   r   generate_records  sb   



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_events_  s   
r   c                 C   s4   |   }zt||fW S  ty   d|f Y S w )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)infilerq   r   r   r   load_events_infilel  s   r   )Fr   FF)"r2   r   r}   rn   	cloudinitr   r   cloudinit.distrosr   r   joinr   formatting_helprp   	FAIL_CODEr   re   r$   r)   r   r-   r0   r4   r8   r;   rC   rD   rE   rf   rd   r`   r   r   r   r   r   r   r   <module>   s\   50
P