uec@sddlZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z yddl Z Wne k rnXddlZejreZndZdZdZdZdefd YZd efd YZd efd YZdS(iN(tLock(tsos_get_command_outputt is_executabletfiletlinktnodetdirtArchivecBseZdZedZejdZdZe Z e Z dZ dZdZdZdZd Zdd Zd d Zd ZdZdZdZdZdZdZdZdZRS(s!Abstract base class for archives.cCs|jS(s6Returns the archive class's name as a string. (t__name__(tcls((s//usr/lib/python2.7/site-packages/sos/archive.pyt archive_type*stsostunsetcCsd|j|fS(Ns[archive:%s] %s(R (tselftmsg((s//usr/lib/python2.7/site-packages/sos/archive.pyt _format_msg7scCs ||_dS(N(t_debug(R tdebug((s//usr/lib/python2.7/site-packages/sos/archive.pyt set_debug:scCs|jj|j|dS(N(tlogterrorR(R R((s//usr/lib/python2.7/site-packages/sos/archive.pyt log_error=scCs|jj|j|dS(N(RtwarningR(R R((s//usr/lib/python2.7/site-packages/sos/archive.pytlog_warn@scCs|jj|j|dS(N(RtinfoR(R R((s//usr/lib/python2.7/site-packages/sos/archive.pytlog_infoCscCs*|js dS|jj|j|dS(N(RRRR(R R((s//usr/lib/python2.7/site-packages/sos/archive.pyt log_debugFs cCs tdS(N(tNotImplementedError(R tsrctdest((s//usr/lib/python2.7/site-packages/sos/archive.pytadd_fileNstwcCs tdS(N(R(R tcontentRtmode((s//usr/lib/python2.7/site-packages/sos/archive.pyt add_stringQscCs tdS(N(R(R R R((s//usr/lib/python2.7/site-packages/sos/archive.pyt add_binaryTscCs tdS(N(R(R tsourcet link_name((s//usr/lib/python2.7/site-packages/sos/archive.pytadd_linkWscCs tdS(N(R(R tpath((s//usr/lib/python2.7/site-packages/sos/archive.pytadd_dirZscCs tdS(N(R(R R'R!tdevice((s//usr/lib/python2.7/site-packages/sos/archive.pytadd_node]scCs tdS(sReturn a temporary directory that clients of the archive may use to write content to. The content of the path is guaranteed to be included in the generated archive.N(R(R ((s//usr/lib/python2.7/site-packages/sos/archive.pyt get_tmp_dir`scCs tdS(sReturn the maximum file name length this archive can support. This is the lesser of the name length limit of the archive format and any temporary file system based cache.N(R(R ((s//usr/lib/python2.7/site-packages/sos/archive.pytname_maxfscCsdS(sTReturn a string representing the path to the temporary archive. For archive classes that implement in-line handling this will be the archive file itself. Archives that use a directory based cache prior to packaging should return the path to the temporary directory where the report content is locatedN((R ((s//usr/lib/python2.7/site-packages/sos/archive.pytget_archive_pathlscCsdS(s:Clean up any temporary resources used by an Archive class.N((R ((s//usr/lib/python2.7/site-packages/sos/archive.pytcleanupuscCs|jdS(sFinalize an archive object via method. This may involve creating An archive that is subsequently compressed or simply closing an archive that supports in-line handling. If method is automatic then the following methods are tried in order: xz, bz2 and gzipN(tclose(R tmethod((s//usr/lib/python2.7/site-packages/sos/archive.pytfinalizeysN(Rt __module__t__doc__t classmethodR tloggingt getLoggerRt_nametFalseRRt _path_lockRRRRRRtNoneRR"R#R&R(R*R+R,R-R.R1(((s//usr/lib/python2.7/site-packages/sos/archive.pyR's.                tFileCacheArchivecBseZdZdZdZdZdZdZdZddZ de dZ ddZ d d Zd Zd Zd ZdZdZdZdZddZdZdZdZdZRS(sd Abstract superclass for archive types that use a temporary cache directory in the file system. tcCs||_||_||_||_||_||_tjj|||_ |j tj |j dWdQX|j d|j fdS(Nis*initialised empty FileCacheArchive at '%s'( R7t_tmp_dirt_policyt_threadstenc_optstsysroottosR'tjoint _archive_rootR9tmakedirsR(R tnamettmpdirtpolicytthreadsR@RA((s//usr/lib/python2.7/site-packages/sos/archive.pyt__init__s        cCs=tjj|r'|jtj}ntjj|j|S(N(RBR'tisabstlstriptsepRCRD(R RF((s//usr/lib/python2.7/site-packages/sos/archive.pyt dest_pathscCsL|j|jr|S|dtjkr6|d}ntjj|j|S(Nii(t startswithRARBRMR'RC(R R'((s//usr/lib/python2.7/site-packages/sos/archive.pyt join_sysroots  icsa|jd||j|}fd}|jdsG|}n7tjj|j|rh|ntjj|d}|}g}xG|dkr|dkrtjj|\}} |j| |}qW|j } d} xp|D]h} tjj | | } || sqntjj | | } tjj | s|jd| tjj | r/tjj| r/tj | } tjj| d}tjj || }|j|d|}tjj|}tjj| rtjj| |} n|jd| | ftj| | qY|jd | tj| || }qqW|S( sCreate leading path components The standard python `os.makedirs` is insufficient for our needs: it will only create directories, and ignores the fact that some path components may be symbolic links. :param src: The source path in the host file system for which leading components should be created, or the path to an sos_* virtual directory inside the archive. Host paths must be absolute (initial '/'), and sos_* directory paths must be a path relative to the root of the archive. :param mode: An optional mode to be used when creating path components. :returns: A rewritten destination path in the case that one or more symbolic links in intermediate components of the path have altered the path destination. sMaking leading paths for %scs|jtjjdS(s>Test whether path ``path`` is inside the archive. R<(RORBR'RC(R'(troot(s//usr/lib/python2.7/site-packages/sos/archive.pyt in_archivest/iR<sMaking path %sR!sMaking symlink '%s' -> '%s'sMaking directory %s(RRDRORBR'tisdirRPtsplittappendtreverseRCtexiststislinktreadlinkt_make_leading_pathstnormpathRKtrelpathtsymlinktmkdir(R RR!RRRtsrc_dirR't path_compstheadttailtabs_pathtsrc_pathtcompttargett target_dirt target_src((RQs//usr/lib/python2.7/site-packages/sos/archive.pyR[sN  !     $  c Cs|p|j|}|tkr*|}ntjj|d}|sJ|Stjj|rtjj| rtd|nJtjj|s|tkr|ntjj|d}|j|nd}|r|Stjj|rtj |}d} |t kr>t j |j  r>t| |dfn|tkrvt j|j  rvt| |dfn|tkr||j  rt| |dfn|tkrt j|j  rt| |dfnd S|S( s4Check a new destination path in the archive. Since it is possible for multiple plugins to collect the same paths, and since plugins can now run concurrently, it is possible for two threads to race in archive methods: historically the archive class only needed to test for the actual presence of a path, since it was impossible for another `Archive` client to enter the class while another method invocation was being dispatched. Deal with this by implementing a locking scheme for operations that modify the path structure of the archive, and by testing explicitly for conflicts with any existing content at the specified destination path. It is not an error to attempt to create a path that already exists in the archive so long as the type of the object to be added matches the type of object already found at the path. It is an error to attempt to re-create an existing path with a different path type (for example, creating a symbolic link at a path already occupied by a regular file). :param src: the source path to be copied to the archive :param path_type: the type of object to be copied :param dest: an optional destination path :param force: force file creation even if the path exists :returns: An absolute destination path if the path should be copied now or `None` otherwise is'path '%s' exists and is not a directorycSs:ttj|tj|tj|tj|gS(N(tanytstattS_ISBLKtS_ISCHRtS_ISFIFOtS_ISSOCK(R!((s//usr/lib/python2.7/site-packages/sos/archive.pyt is_special.s    s path '%s' exists and is not a %ss regular files symbolic links special filet directoryN(RNtP_DIRRBR'RURXRTt ValueErrorR[tlstattP_FILERktS_ISREGtst_modetP_LINKtS_ISLNKtP_NODEtS_ISDIRR:( R Rt path_typeRtforcetdest_dirR`Rptsttve_msg((s//usr/lib/python2.7/site-packages/sos/archive.pyt _check_paths8  % ( c Cs|j|s|}n|j|t}|s5dSt|ddsytj||Wnntk r}|jds|jdrq|j d||fn$t k r}|j d|nXyt j |}|jds|jdr.tj ||t j|d|j|jfntj||t j||j|jWn*tk r}|jd||fnXd|}nI|jd t|d %}x|D]}|j|qWWdQXd }|jd ||jfWdQXdS( Ntreads/sys/s/proc/scaught '%s' copying '%s'sFile not collected: '%s'tnss&caught '%s' setting attributes of '%s's'%s'iRs open files!added %s to FileCacheArchive '%s'(R9RRutgetattrR:tshutiltcopytIOErrorRORtOSErrorRBRktcopymodetutimet st_atime_nst st_mtime_nstcopystattchowntst_uidtst_gidt ExceptionRtseektopentwriteRD(R RRteRkt file_nametftline((s//usr/lib/python2.7/site-packages/sos/archive.pyRJsB  "     Rc Cs|j|}|j|tdt}tj||dd}t|trd|jdd}n|j |t j j |ryt j||Wqtk r}|jd||fqXn|jd||jfWdQXdS(NR}tencodingsutf-8tutf8tignores!Unable to add '%s' to archive: %ss-added string at '%s' to FileCacheArchive '%s'(R9RRutTruetcodecsRt isinstancetbytestdecodeRRBR'RXRRRRRRD(R R RR!RRR((s//usr/lib/python2.7/site-packages/sos/archive.pyR"{s    c Cso|j`|j|t}|s&dStj|ddd}|j||jd||jfWdQXdS(NtwbRs,added binary content at '%s' to archive '%s'( R9RRuRRR:RRRD(R R RR((s//usr/lib/python2.7/site-packages/sos/archive.pyR#s   c Cs>|jd||f|jc|j|t}|s=dStjj|stj|||jd|||jfnWdQX|jd|||ftjj |}tjj tjj ||}|j |}d}tjj |s-tjj|r|}tjj |}tjj |tj|}tjj||}|||r|jd||fdS|jd||f|j||q-tjj|r|jd||j|q-tjj|r|jd||j|q-|jd ||fn|jd dS( Nsadding symlink at '%s' -> '%s's-added symlink at '%s' to '%s' in archive '%s's.Link follow up: source=%s link_name=%s dest=%scSstjj|}tjj|sHtjjtjj||}ntjj|}||krjtSytj|Wn)tk r}|j dkrtSnXt S(sReturn ``True`` if the symbolic link ``link_name`` is part of a file system loop, or ``False`` otherwise. i(( RBR'tdirnameRKtrealpathRCRRkRterrnoR8(R%R$tlink_dirR((s//usr/lib/python2.7/site-packages/sos/archive.pytis_loops$ s#Link '%s' - '%s' loops: skipping...s'Adding link %s -> %s for link follow ups Adding dir %s for link follow ups!Adding file %s for link follow ups)No link follow up: source=%s link_name=%ssleaving add_link()(RR9RRxRBR'tlexistsR^RDRRRCRNRXRYRZR]R&RTR(tisfileR( R R$R%Rt source_dirthost_path_nametdest_path_nameRR~((s//usr/lib/python2.7/site-packages/sos/archive.pyR&sJ   !    cCs$|j|j|tWdQXdS(smCreate a directory in the archive. :param path: the path in the host file system to add N(R9RRr(R R'((s//usr/lib/python2.7/site-packages/sos/archive.pyR(s cCs|j|t}|sdStjj|sytj|||WnLtk r}|jtjkrd}|j d||fdS|nXt j ||ndS(NsOperation not permittedsadd_node: %s - mknod '%s'( RRzRBR'RXtmknodRRtEPERMRRR(R R'R!R)RRR((s//usr/lib/python2.7/site-packages/sos/archive.pyR*s cCs7dtjkr/tjd}tj|j|SdSdS(Nt PC_NAME_MAXi(RBtpathconf_namestpathconfRD(R t pc_name_max((s//usr/lib/python2.7/site-packages/sos/archive.pyR,s cCs|jS(N(RD(R ((s//usr/lib/python2.7/site-packages/sos/archive.pyR+scCs|jS(N(RD(R ((s//usr/lib/python2.7/site-packages/sos/archive.pyR-scCsCtjtjj|j|d||jd||jfdS(ssCreate path, including leading components. Used by sos.sosreport to set up sos_* directories. R!s2created directory at '%s' in FileCacheArchive '%s'N(RBRER'RCRDR(R R'R!((s//usr/lib/python2.7/site-packages/sos/archive.pyRE s% cCs+|j|}tj|dddddS(NtrRsutf-8terrorsR(RNRR(R R'((s//usr/lib/python2.7/site-packages/sos/archive.pyt open_filescCs,tjj|jr(tj|jndS(N(RBR'RTRDRtrmtree(R ((s//usr/lib/python2.7/site-packages/sos/archive.pyR.scCs|jd|j|f|j|j|jd|jtj|jjf||_y|j }Wn7t k r}d}|j d||f|j SX|j dry|j|SWqt k r}d}|j d||f|SXn|SdS(Ns)finalizing archive '%s' using method '%s'sbuilt archive at '%s' (size=%d)s+An error occurred compressing the archive: s%s %stencrypts)An error occurred encrypting the archive:(RRDt_build_archiveR.t _archive_nameRBRktst_sizeR0t _compressRRRFR@t_encrypt(R R0tresRtexp_msg((s//usr/lib/python2.7/site-packages/sos/archive.pyR1s*      cCs,|jdd}|d7}d|}d}|jdr[|d|jd7}||7}n|jdrd|jdjd d }i|d 6}|d 7}d |}||7}nt|ddd|}|ddkr|S|ddkr|jdrd}qd}nd|d}t|dS(sEncrypts the compressed archive using GPG. If encryption fails for any reason, it should be logged by sos but not cause execution to stop. The assumption is that the unencrypted archive would still be of use to the user, and/or that the end user has another means of securing the archive. Returns the name of the encrypted archive, or raises an exception to signal that encryption failed and the unencrypted archive name should be used. s sosreport-ssecured-sosreport-s.gpgsgpg --batch -o %s tkeys--trust-model always -e -r %s tpasswords%ss'"R<tsos_gpgs-c --passphrase-fd 0 s!/bin/bash -c "echo $sos_gpg | %s"ttimeoutitenvtstatusisSpecified key not in keyringsCould not read passphrasesgpg exited with code %sN(treplaceR:R@RR(R tarchivetarc_nametenc_cmdRtpasswdRR((s//usr/lib/python2.7/site-packages/sos/archive.pyR5s,             N(RR2R3R=RDRRJRNRPR[R:R8RRR"R#R&R(R*R,R+R-RERR.R1R(((s//usr/lib/python2.7/site-packages/sos/archive.pyR;s.   \K 1  H       tTarFileArchivecBseeZdZd ZeZdZd dZdZ dZ dZ dZ dZ dZRS( s: archive class using python TarFile to create tar archivescCsPtt|j||||||d|_tjj||j|_dS(Nttar( tsuperRRJt_suffixRBR'RCRFR(R RFRGRHRIR@RA((s//usr/lib/python2.7/site-packages/sos/archive.pyRJgs  cCsn|j|_d|j|jdtget_cmd_for_compress_methodR?RFRRRR( R tmethodsR0Rt last_errortcmdtsuffixtexec_cmdRR((s//usr/lib/python2.7/site-packages/sos/archive.pyRs0     N(RR2R3R:R0R8RRJRRRRFR,RR(((s//usr/lib/python2.7/site-packages/sos/archive.pyRas      (RBRRR5RRRkt threadingRt sos.utilitiesRRRt ImportErrortsixtPY3tinttlongRuRxRzRrtobjectRR;R(((s//usr/lib/python2.7/site-packages/sos/archive.pyt s.           [