o
    f
+                     @   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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
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} )
format_keyitemsreplaceformat)msgeventijr   r   8/usr/lib/python3/dist-packages/cloudinit/analyze/show.pyformat_record6   s   r   c                 C      | r|  dS d S )Nr   getr   r   r   r   
event_nameA      
r#   c                 C   r   )Nr   r    r"   r   r   r   r   G   r$   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| S N)datetimeutcfromtimestampr*   r"   r   r   r   event_datetimeW   s   r.   c                 C   s   ||    S r+   )total_seconds)t1t2r   r   r   delta_seconds[   s   r2   c                 C   s   t t| t|S r+   )r2   r.   )startfinishr   r   r   event_duration_   s   r5   c              	   C   sH   |  }|t||t| t|ddt|dd   d d |S )N| r%      z`->)r   r   r	   )copyupdater5   r2   r.   r#   count)
start_timer3   r4   recordr   r   r   event_recordc   s   r>   c                 C   s   d|  S )NzTotal Time: %3.5f seconds
r   )r   r   r   r   total_time_recordp   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 )N	systemctlshowz-p)epochr   whichargsappendextendr   )selfproperty	parameterr   r   r   __init__y   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   rE   rC   	Exception)rH   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 ({})=r8   i@B )r   RuntimeErrorr   rC   r&   r)   )rH   r   r   r   r   parse_epoch_as_float   s   	z$SystemctlReader.parse_epoch_as_floatr+   )__name__
__module____qualname____doc__rK   r   rT   r   r   r   r   r@   t   s
    
r@   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
   
ra   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
    dmesgTrL   r   zUTF-8userr   r8   ])r   
splitlinesdecodefindr&   stripr)   timer   uptimeSUCCESS_CODErN   r`   )	data_split_entriesr   splitupstrippeduser_space_timestampkernel_start
kernel_endr   r   r   r_      s$   r_   c               
   C   s   t t t t  } z!td }tdd }| }t}t r$t}|| }|| }W n t	yE } 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-localN)r)   ri   r   rj   r@   rT   rk   is_containerCONTAINER_CODErN   printr`   )rr   delta_k_end
delta_ci_s	base_timestatusrs   cloudinit_sysder   r   r   r[      s0   r[   (%n) %d seconds in %I%Dc              	   C   s  t | dd d}g }d}d}i }g }g }tt|D ]}	| |	 }
z| |	d  }W n ty3   d}Y nw t|
dkr|rU|
dd	krU|t| || g }d}d}|du rct|
}||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 )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>  s    z"generate_records.<locals>.<lambda>)keyNg        r8   r3   r   z
init-localr4   zStarting stage: %szFinished stage: (%n) %d seconds
r   )sortedrangelen
IndexErrorr   r!   rF   r?   r.   r'   r#   r   r>   pop)eventsprint_formatsorted_eventsrecordsr<   r   stage_start_timeboot_recordsunprocessedr~   r   next_evtprev_evtr=   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_eventsI  s   
r   c                 C   sX   |   }| stjd| j  td 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
    zEmpty file %s
r8   N)
readrh   sysstderrwriter   exitjsonloads
ValueError)infilerl   r   r   r   load_events_infileV  s   
r   )r   )r,   r   r   ri   	cloudinitr   r   cloudinit.distrosr   r   rk   	FAIL_CODErw   r`   r   r#   r   r'   r*   r.   r2   r5   r>   r?   r@   ra   r_   r[   r   r   r   r   r   r   r   <module>   sP   5#
J