
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
;j+                 @   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Zd dlmZ d dl	m
Z
mZmZmZmZmZ d dlmZ dd ZG dd deZG d	d
 d
eZdS )    N)NamedTemporaryFile)authconfig
http_utilsipv6_support	log_utilsutils)run_commandc             C   s<   t | }x(dD ] }|dk r&dj||S |d }qW dj|S )	zBRender a byte count as a short human-readable string for the logs.BKiBMiBGiBg      @z{0:.1f} {1}z{0:.1f} TiB)r
   r   r   r   )floatformat)Z	num_bytessizeZunit r   2/usr/libexec/kcare/python/kcarectl/delivery_kit.pyformat_size   s    
r   c               @   s   e Zd ZdZdZdZdd Zedd Zedd Z	d	d
 Z
d(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ejejd!d"d# Zd$d% Zd&d' ZdS ))DataPackagezGeneric archive package for the patch server uploads pipeline.

    Based on DataPackage from eportal (delivery_kit.py). Subclasses
    supply the manifest `data_type`, the `upload_uri` to PUT the
    archive to and the `max_size` payload limit.
     c             C   s   d | _ g | _d| _d S )Nr   )_tar_errors_buffer_total_payload_size)selfr   r   r   __init__-   s    zDataPackage.__init__c             C   s   t d S )N)NotImplementedError)r   r   r   r   max_size3   s    zDataPackage.max_sizec             C   s   | j  }t|jS )N)_ensure_tar_createdstrname)r   tarr   r   r   archive_path8   s    zDataPackage.archive_pathc             C   s   d }d }yt tj|ddd\}}}W n* tk
rP } zt|}W Y d d }~X nX |rh| jdj|| |d k	r| j|tj	|ddd d S )NT)catch_stdoutcatch_stderrz!failed to dump stdout of {0}:
{1}zutf-8)encoding)
data_bytes)
r	   shlexsplit	Exceptionr   	log_errorr   add_filer   bstr)r   arcnamecmdstdoutstderr_er   r   r   
add_stdout>   s    zDataPackage.add_stdoutNFc       	      C   sh  |d kr|d krt d| j }d}|d k	rZtjj|sL| jdj| d S tjj|}nt|}| j	|s| jdj| d S | r| j
| r| jdj|t|t| jt| j d S yp|r|j||d n"tj|}||_|j|tj| |s*|  j|7  _tjdj|t|t| jdd	 W n6 tk
rb } z| jd
j|| W Y d d }~X nX d S )Nz"No src_path or data_bytes providedr   zfile not found: {0}z no available space to store: {0}zPskipping {0}: {1} would exceed the {2} report size limit (already collected {3}))r,   z%collected {0}: {1} (report total {2})F)	print_msgzfailed to store {0}: {1})
ValueErrorr   ospathexistsr)   r   getsizelen_check_required_space_check_total_payload_limitlog_warningr   r   r   addtarfileTarInfor   addfileioBytesIOr   loginfor(   )	r   r,   src_pathr%   skip_limit_checkr    
entry_sizeinfor1   r   r   r   r*   N   sJ    


zDataPackage.add_filec             C   sb   yt jtj|dddd}W n2 tk
rN } z| jdj|| d S d }~X nX | j||d d S )N   )indentzutf-8)r$   zfailed to dump {0}:
{1})r%   )r   r+   jsondumps	TypeErrorr)   r   r*   )r   r,   datar%   r1   r   r   r   add_json   s    zDataPackage.add_jsonc             C   s   t j| j}|j|j |kS )N)r5   statvfsr!   f_frsizef_bfree)r   rF   rO   r   r   r   r:      s    z!DataPackage._check_required_spacec             C   s   | j | j| kS )N)r   r   )r   rF   r   r   r   r;      s    z&DataPackage._check_total_payload_limitc             C   s   d| j ttj dS )N   )Zschema_versiontypeZtime_created)	data_typeinttime)r   r   r   r   make_manifest   s    zDataPackage.make_manifestc             C   sN   t jtj| j dddd}| j }tjd}t||_	|j
|tj| d S )NrH   )rI   zutf-8)r$   zmanifest.json)r   r+   rJ   rK   rW   r   r>   r?   r9   r   r@   rA   rB   )r   r%   r    rG   r   r   r   _add_manifest   s
    

zDataPackage._add_manifestc             C   s&   |j  }tj|dd | jj| d S )NF)r3   )stripr   logerrorr   append)r   Z	error_msgr   r   r   r)      s    zDataPackage.log_errorc             C   s&   |j  }tj|dd | jj| d S )NF)r3   )rY   r   logwarnr   r[   )r   Zwarning_msgr   r   r   r<      s    zDataPackage.log_warningc             C   s   xdD ]}t dj|dd  dd}|j  y6tjdj|jdd	 tj|j|d
d| _| j	  | S  t
k
r } zb| jd k	ry| jj  W n t
k
r   Y nX d | _tjj|jrtj|j t|tjsЂ W Y d d }~X qX qW tjdd S )Nw:xzw:bz2w:gzz.tar.{0}   F)suffixdeletezCreating DataPackage: {0})r3   T)r   modeZdereferencez%No supported compression method found)r]   r^   r_   )r   r   closer   rC   r   r>   openr   rX   r(   r5   r6   r7   unlink
isinstanceZCompressionError)r   Zcompression_modeZtmpfileerrr   r   r   	__enter__   s(    

zDataPackage.__enter__c             C   sP   | j r,dj| j d }| jdtj|dd | jrL| jj  |rL| j  dS dS )N
z
errors.logT)r%   rE   F)r   joinr*   r   r+   r   rd   remove_archive)r   exc_typeZexc_valexc_tberrorsr   r   r   __exit__   s    
zDataPackage.__exit__)loggerc             C   s$   | j r tjj| jr tj| j d S )N)r   r5   r6   r7   r!   rf   )r   r   r   r   rl      s    zDataPackage.remove_archivec             C   s   | j std| j S )Nz/DataPackage should be used as a context manager)r   RuntimeError)r   r   r   r   r      s    zDataPackage._ensure_tar_createdc             C   st   | j  j  tjj| j}d|kr4||jdd nd}ttj	 | }t
j | j | }tj| j|tj d |S )a  Send the package archive to the patch server.

        Upload errors propagate to the caller (see the eportal
        precedent): wrap with utils.catch_errors where a silent
        failure is acceptable.

        :return: Upload name (package identifier)
        .Nr   )
upload_urlZauth_string)r   rd   r5   r6   basenamer!   findr   uuidZuuid4r   get_patch_server
upload_urir   Zupload_filer   get_http_auth_string)r   ru   extupload_namert   r   r   r   send   s    zDataPackage.send)NNF)__name__
__module____qualname____doc__rT   ry   r   propertyr   r!   r2   r*   rN   r:   r;   rW   rX   r)   r<   ri   rp   r   catch_errorsr   r\   rl   r   r}   r   r   r   r   r   "   s(   
;
	 r   c               @   s    e Zd ZdZdZedd ZdS )KernelAnomalyPackagezkernel-anomalyz/upload/kernel-anomaly/c             C   s   t jS )N)r   Z$KERNEL_ANOMALY_REPORT_MAX_SIZE_BYTES)r   r   r   r   r     s    zKernelAnomalyPackage.max_sizeN)r~   r   r   rT   ry   r   r   r   r   r   r   r     s   r   )rA   rJ   r5   r&   r>   rV   rw   tempfiler   kcarectlr   r   r   r   r   r   Zkcarectl.process_utilsr	   r   objectr   r   r   r   r   r   <module>   s     y