a Ü““iÐýã@süddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z ddl m Z ddl m Z ddlmZddlmZddlmZddlmZdd lmZmZdd lmZdd lmZdd lmZdd lm Z dZ!Gdd„deƒZ"dS)éN)Údatetime)ÚThreadPoolExecutor)Úgetpass)ÚPath)Úquote)Ú SoSCleaner)ÚSosNode)Ú ClusterOptionÚ str_to_bool)Ú SoSComponent)Úbold)Ú __version__)Ú SoSUploadz/etc/sos/groups.dcOseZdZdZdZdddddddgddgggddddddgdd gddddd dd dddgdddddgddgddddddddgggdd d d ddddgddddddddddddddddœNZ‡fdd„Zdd„Zedd„ƒZ edd„ƒZ edd„ƒZ dd„Z edd„ƒZ edd „ƒZdad!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„Zd-d.„Zd/d0„Zd1d2„Zd3d4„Zd5d6„Zd7d8„Zd9d:„Zd;d<„Zd=d>„Zd?d@„ZdAdB„ZdCdD„Z dEdF„Z!dGdH„Z"dIdJ„Z#dKdL„Z$dMdN„Z%dOdP„Z&dQdR„Z'dSdT„Z(dUdV„Z)dWdX„Z*dYdZ„Z+d[d\„Z,d]d^„Z-d_d`„Z.‡Z/S)bÚ SoSCollectoraÐ sos collect, or SoS Collector, is the formerly standalone sos-collector project, brought into sos natively in 4.0 and later. It is meant to collect sos reports from an arbitrary number of remote nodes, as well as the localhost, at the same time. These nodes may be either user defined, defined by some clustering software, or both. For cluster defined lists of nodes, cluster profiles exist that not only define how these node lists are generated but may also influence the sos report command run on nodes depending upon their role within the cluster. Nodes are connected to via a 'transport' which defaults to the use of OpenSSH's Control Persist feature. Other transport types are available, and may be specifically linked to use with a certain cluster profile (or, at minimum, a node within a certain cluster type even if that profile is not used). sos collect may be run from either a node within the cluster that is capable of enumerating/discovering the other cluster nodes, or may be run from a user's workstation and instructed to first connect to such a node via the --primary option. If run in the latter manner, users will likely want to use the --no-local option, as by default sos collect will also collect an sos report locally. Users should expect this command to result in a tarball containing one or more sos report archives on the system that sos collect was executed on. z8Collect an sos report from multiple nodes simultaneouslyFÚautoNÚTérú /etc/sos/cleaner/default_mappingéÚrootÚsudoiXÚ obfuscate)NÚall_logsÚ alloptionsZallow_system_changesÚ become_rootÚcase_idÚchrootÚcleanÚcluster_optionsÚ cluster_typeZcontainer_runtimeÚdomainsÚdisable_parsersZenable_pluginsZ encrypt_keyZ encrypt_passÚgroupZimageZinherit_config_fileZforce_pull_imageÚskip_cleaning_filesÚjobsZ journal_sizeÚkeywordsÚ keyword_fileÚkeep_binary_filesÚlabelÚ list_optionsÚlog_sizeZ low_priorityÚmap_fileÚprimaryZ namespacesZnode_config_fileÚnodesZ no_env_varsÚno_localÚ nopasswd_sudoZ no_pkg_checkÚ no_updateZ only_pluginsÚpasswordÚpassword_per_nodeÚplugoptsZplugin_timeoutZ cmd_timeoutÚpresetZ registry_userZregistry_passwordZregistry_authfileÚ save_groupZsinceÚ skip_commandsÚ skip_filesZ skip_pluginsÚssh_keyZssh_portÚssh_userZ sudo_binaryÚtimeoutÚ transportÚtreat_certificatesÚverifyÚ usernamesÚuploadZ upload_urlZupload_directoryZ upload_userZ upload_passZ upload_methodZupload_no_ssl_verifyZupload_protocolÚupload_s3_endpointZupload_s3_regionZupload_s3_bucketZupload_s3_access_keyZupload_s3_secret_keyZupload_s3_object_prefixZ upload_targetcsjtƒ |||¡t d¡g|_g|_d|_d|_d|_d|_ |j j   d¡|j j j |_|j dd¡|j d¡t|jddƒt ¡|_z$td d „t t ¡d¡Dƒƒ|_Wn$tyÒ| d ¡d g|_Yn0| ¡| ¡|_|jj�sfzT| ¡|  ¡| !d d "dd„t#j$Dƒ¡›�¡| !d|j %¡›�¡| &¡Wn t'�yd| (dd¡Yn0dS)Né?rÚcollectrÚnoneÚ node_listÚsudo_pwrcSsh|]}|dd’qS)rr©©Ú.0ÚirFrFú:/usr/lib/python3.9/site-packages/sos/collector/__init__.pyÚ ±sz(SoSCollector.__init__..zkCould not get a list of IP addresses from this hostnamne. This may indicate a DNS issue in your environmentz 127.0.0.1z Executing ú css|] }|VqdS©NrF)rHÚsrFrFrJÚ Äóz(SoSCollector.__init__..zFound cluster profiles: úExiting on user cancelé‚))ÚsuperÚ__init__ÚosÚumaskÚ client_listrDr,Ú retrievedÚclusterrÚmanifestÚ componentsÚ add_sectionrBÚ collect_mdÚ add_fieldÚadd_listÚsetattrÚoptsÚsocketZ gethostnameÚhostnameÚlistZ getaddrinfoÚip_addrsÚ ExceptionÚ log_errorÚ_parse_optionsÚ load_clustersÚclustersr)Úparse_node_stringsÚparse_cluster_optionsÚ log_debugÚjoinÚsysÚargvÚkeysÚverify_cluster_optionsÚKeyboardInterruptÚexit)ÚselfÚparserZ parsed_argsZ cmdline_args©Ú __class__rFrJrTšsH    ÿ ÿ  "ÿ zSoSCollector.__init__cCsDddl}|jj}i}| |d¡}|D]}|d|jƒ||d<q$|S)zmLoads all cluster types supported by the local installation for future comparison and/or use rNrjé)Zsos.collector.clustersZ collectorrjÚ _load_modulesÚcommons)ruÚsosÚpackageZsupported_clustersrjrYrFrFrJriÌs zSoSCollector.load_clusterscCs2g}|jD]"}tj |¡r | | ||¡¡q |S)z'Helper to import cluster and host types)Ú__path__rUÚpathÚisdirÚextendÚ_find_modules_in_path)Úclsr}ZsubmodÚmodulesrrFrFrJrzØs   zSoSCollector._load_modulescCsng}tj |¡rjtt |¡ƒD]J}| d¡s.qd|vr8qtj |¡\}}d|›d|›�}| | |¡¡q|S)aXGiven a path and a module name, find everything that can be imported and then import it path - the filesystem path of the package modulename - the name of the module in the package E.G. a path of 'clusters', and a modulename of 'ovirt' equates to importing sos.collector.clusters.ovirt z.pyÚ__zsos.collector.Ú.) rUrÚexistsÚsortedÚlistdirÚendswithÚsplitextr�Ú_import_modules)rƒrZ modulenamer„ZpyfileÚfnameÚ_ÚmodnamerFrFrJr‚ás   z"SoSCollector._find_modules_in_pathc Csž| d¡d}zt|tƒtƒ|gƒ}Wn@tyf}z(td|›d|jj›�ƒ|‚WYd}~n d}~00t  |tj ¡}|  ¡D]}|ddvr~|  |¡q~|S)z/Import and return all found classes in a moduler†éz"Error while trying to load module z: Nr)ZSosHostÚCluster) ÚsplitÚ __import__ÚglobalsÚlocalsÚ ImportErrorÚprintrxÚ__name__ÚinspectZ getmembersZisclassÚcopyÚremove)rƒr�Zmod_short_nameÚmoduleÚer„ÚmodrFrFrJrŒøs ÿ   zSoSCollector._import_modulesc Cs|jjs dSg}t|jjtƒs,|jjg|j_|jjD]¾}dd„t|ƒDƒ}| t|ƒ¡d}d}|D]j}zL|}|||…}t t  |¡¡d|vržd|vržWqd| |  d¡¡|}Wqdtj yÌYqdYqd0qd|t|ƒkr4| ||dd…¡q4||j_dS) arParses the given --nodes option(s) to properly format the regex list that we use. We cannot blindly split on ',' chars since it is a valid regex character, so we need to scan along the given strings and check at each comma if we should use the preceeding string by itself or not, based on if there is a valid regex at that index. NcSsg|]\}}|dkr|‘qS)ú,rF)rHrIÚmrFrFrJÚ rPz3SoSCollector.parse_node_strings..rú[ú]rŸry) rar-Ú isinstancerdÚ enumerateÚappendÚlenÚreÚcompileÚescapeÚlstripÚerror)rur-ÚnodeZidxsÚstartÚposÚidxZregrFrFrJrks0    zSoSCollector.parse_node_stringsc Csh| dd¡}|jddddd�|jddd d�|jd dd d d �|jddgd¢dd�|jdddd�|jddddd�|jdtddd�|jdd d!dd"d#d$�|jd%dtd&d'�|jd(dd d)d �|jd*d+dd,d�|jd-d.dgd/d �|jd0dd1d�|jd2dd d3d �|jd4tdd5d�|jd6tdd7d�|jd8dd9d�|jd:gdd;dgdd?d@d=�|jdAddBd�| dCdD¡}|jdEdFddGdHd$�|jdIdJdK�|jdLd ddMdN�|jdOtddPd�|jdQdRdK�|jdSdTdUdVdWdX�|jdYddZd�|jd[dd\d�|jd]d^dK�|jd_d`dadbtdcdd�|jdeddfd�|jdgddhd�|jdiddjd�|jdkdldmdK�|jdndodptdqd'�|jdrdsddtd�|jdudvdK�|jdwdxdydzdd{d|�|jd}dd~d�|jddVd€d�|jd�dd‚d�|jdƒdd„d�|jd…d†td‡dˆ�|jd‰dd dŠd �|jd‹dd dŒd �|jd�dd dŽd��|jd�d‘dK�|jd’d“td”d'�|jd•td d–d—�|jd˜dtd™d'�|jdšdd d›d �|jdœdd�d�|jdžddŸd�|jd dd¡d�|jd¢dd£d�|jd¤dgd¥¢d¦d�|jd§d dd¨dN�|jd©ddªd�|jd«dd¬d�|jd­dd®d�|jd¯dd°d�|jd±dd²d�|jd³dd´d�|jdµdgd¶¢d·d�| d¸d¹¡}|jdºd»d¼d½d dd¾d¿�|jdÀd ddÁdÂd=�|jdÃdÄgddÅd¿�|jdÆdgdÇdÈdÉ�|jdÊdËdgdÌdÍdÉ�|jdÎdgdÏdÐdÉ�|jdÑddÒdÓdÔ�|jdÕdd dÖd×dÉ�|jdØdÙdÚdÛd|�|jdÜdÝgddÞd¿�|jdßdàgdá¢dâdãdä�dS)åNzReport Passthru Optionsz0These options control how report is run on nodesz-az --alloptionsÚ store_truezEnable all sos report options)ÚactionÚhelpz --all-logszCollect logs regardless of sizez--allow-system-changesFzzList of usernames to obfuscatez--treat-certificatesr)rZkeepr›r<z˜How to treat the certificate files [.csr .crt .pem]. Defaults to "obfuscate" after convert the file to text. "Key" certificate files are always removed.)r´r·r¹r³)Úadd_argument_groupÚ add_argumentÚintÚstrr )rƒrvZsos_grpZ collect_grpZ cleaner_grprFrFrJÚadd_parser_options)sþ ÿÿþþÿ ÿ ÿ þ ÿÿ ÿ þÿþ ÿ ÿÿ þ þÿþ þþþÿþÿÿÿýÿÿÿ ÿ ÿÿ þÿÿÿÿ ÿþþ ÿÿ ÿ ÿ ÿþÿÿÿÿþþÿÿÿÿÿÿýþ ýþ þþý þþþþ þüzSoSCollector.add_parser_optionscCsh| d¡| |j¡dddddœ}| d¡| ¡D],\}}|jdd ›t|ƒd ›|d ›�d d �q6dS)NzSoS Collect Detailed HelpzInformation on cluster profileszSpecific profile informationz'Information on how connections are madezSpecific transport information)zcollect.clusterszcollect.clusters.$clusterzcollect.transportszcollect.transports.$transportz8The following help sections may be of further interest: rLz>8z<40z<30F)Únewline)Z set_titleÚadd_textÚ__doc__Úitemsr )rƒÚsectionZ hsectionsZhsecÚvaluerFrFrJÚ display_helps  üÿþzSoSCollector.display_helpcCsv|jr|j ¡|r| |¡z | ¡WntyF| d¡Yn0|dkrX| ¡|sht |¡n t  |¡dS)a Used to terminate and ensure all cleanup is done, setting the exit code as specified if required. :param msg: Log the provided message as an error :type msg: ``str`` :param error: The exit code to use when terminating :type error: ``int`` :param force: Use os.exit() to break out of nested threads if needed :type force: ``bool`` z/Warning: Failed to close all remote connectionsrRN) rYZcleanuprgÚclose_all_connectionsrfÚlog_warnrortrUÚ_exit)ruÚmsgr¬ÚforcerFrFrJrt)s      zSoSCollector.exitcCs8|j|jjdk|jtt|jjƒt|jƒƒ|jdœ|_dS)zxFrom commandline options, defaults, etc... build a set of commons to hand to other collector mechanisms r)Z cmdlineoptsÚ need_sudoÚtmpdirÚhostlenÚpolicyN) rar9rÐÚmaxr§r,rcrÒr{©rurFrFrJrhGs  ûzSoSCollector._parse_optionsc Cs°g}t|jjtƒs |jjg|j_|jjr¤|jjD]r}| d¡d}| d¡d d¡d}z| d¡d ¡d}WntyŠd}Yn0| t|||j|ƒ¡q0||j_dS)Nr†rryú=ÚTrue) r¤rarrdr’Ú IndexErrorr¦r rx)ruraÚoptionrYÚnamerÈrFrFrJrlSs   ÿz"SoSCollector.parse_cluster_optionscCsŠ|jjr†|jjD]T}d}|j ¡D]@\}}|jD]0}|j|jkr0|j|kr0d}| ||¡|_q"q0q"q|s†|  d|j›d|j›�d¡dS)z+Verify that requested cluster options existFTz!Unknown cluster option provided: r†ryN) rarrjrÆÚoptionsrÙrYÚ_validate_optionrÈrt)ruÚoptÚmatchÚclustrÈrØrFrFrJrrhs"   ÿÿÿz#SoSCollector.verify_cluster_optionscCsl|jtks<|j|jks6d}| ||j|j|jfd¡|jS|j ¡}|dvrdd}| ||jd¡|dvS)aCChecks to make sure that the option given on the CLI is valid. Valid in this sense means that the type of value given matches what a cluster profile expects (str for str, bool for bool, etc). For bool options, this will also convert the string equivalent to an actual boolean value z.Invalid option type for %s. Expected %s got %sry)ÚtrueÚonÚyesZfalseZoffÚnozUInvalid value for %s. Accepted values are: 'true', 'false', 'on', 'off', 'yes', 'no'.)rßràrá)Úopt_typeÚboolrtrÙrÈÚlower)rur´ZclirÍÚvalrFrFrJrÛws   zSoSCollector._validate_optioncCs|j |¡dS)z.Log info messages to both console and log fileN)ÚsoslogÚinfo©rurÍrFrFrJÚlog_infoŒszSoSCollector.log_infocCs|j |¡dS)z.Log warn messages to both console and log fileN)rçZwarningrérFrFrJrË�szSoSCollector.log_warncCs|j |¡dS)z/Log error messages to both console and log fileN)rçr¬rérFrFrJrg”szSoSCollector.log_errorcCs0t ¡dd}d|›d|›�}|j |¡dS)z.Log debug message to both console and log fileryéz[sos_collector:z] N)r™ÚstackrçÚdebug)rurÍZcallerrFrFrJrm˜szSoSCollector.log_debugc sŠtj d¡tj d¡t|jƒD]*}tj d|d›d|j|jd›d�¡q"i‰|j ¡D]X\}}|jD]H}|jˆvr„|ˆ|j<qj|j D]&}|ˆ|jj vrŠˆ|jj   |¡qŠqjq\tj d¡tj ddd ›dd d ›dd d ›ddd›ddd›d� ¡tˆ‡fdd„d�D]l}ˆ|}dd  dd„t|j ƒDƒ¡d ›d|jd ›d|j j d ›dt|jƒd ›d|jd ›d� }tj |¡�q tj d¡dS)z&Display options for available clustersz; The following clusters are supported by this installation z@Use the short name with --cluster-type or cluster options (-c) rLz<15Z30Ú z/ The following cluster options are available: r‘Z25z Option NameZ15ÚTypez<10ZDefaultZ10Z DescriptionúºrPz+SoSCollector.list_options..©Úkeyz z, css|] }|VqdSrMrF)rHÚcrFrFrJrO½rPz,SoSCollector.list_options..zh Options take the form of cluster.name=value E.G. "ovirt.no-database=True" or "pacemaker.offline=False" N)roÚstdoutÚwriterˆrjZ cluster_namerÆrÚrÙrYr¦rnrãr˜rÁrÈÚ description)rurYrŽrÈrÜrÞZ_optZoptlnrFròrJr)žsD  ÿ     "ÿÿ ÿÿ þþÿzSoSCollector.list_optionscCst |j¡dS)z8Removes the temp directory and all collected sos reportsN)ÚshutilÚrmtreerÐrÔrFrFrJÚdelete_tmp_dirÆszSoSCollector.delete_tmp_dirc Cs¶d}|jjr|d|jj›�7}|jjr8|d|jj›�7}t t ¡d¡}z tjt_Wn4t yˆ}z|  d|›�¡WYd}~n d}~00d  dd„t d ƒDƒ¡}|›d|›d|›�S) z(Generates a name for the tarball archivez sos-collectorú-z%Y-%m-%dz#Could not cast to ascii_lowercase: Nrcss|]}t tj¡VqdSrM)ÚrandomÚchoiceÚstringÚ lowercase)rHrñrFrFrJrOØrPz1SoSCollector._get_archive_name..é) rar(rrÚstrftimeZnowrZascii_lowercaserÚ NameErrorrmrnÚrange)ruZnstrZdtÚerrZrandrFrFrJÚ_get_archive_nameÊs &zSoSCollector._get_archive_namecCs&| ¡|_d}|jd|jd|S)zvReturns the path, including filename, of the tarball we build that contains the collected sos reports Úgzú/z.tar.)rÚarc_namerÐ)ruZcomprrFrFrJÚ_get_archive_pathÛs zSoSCollector._get_archive_pathc Cs(|jj}|tj t ¡d|›�¡tj t|¡g}d}|D]}tj |¡r8|}qRq8|durht d|›�ƒ‚|  d|›�¡t |ddd��Œ}t   |¡}dD]:}||r–|  d |›d ||›d �¡t|j|||ƒq–|d �r|  d |d ›d�¡|jj |d ¡Wdƒn1�s0YdS)a  Attempts to load the host group specified on the command line. Host groups are defined via JSON files, typically saved under /etc/sos/groups.d/, although users can specify a full filepath on the commandline to point to one existing anywhere on the system Host groups define a list of nodes and/or regexes and optionally the primary and cluster-type options. z.config/sos/groups.d/Nzno group definition for zLoading host group Úrúutf-8©Úencoding)r,rzSetting option 'z' to 'z'per host groupr-zAdding ú to node list)rar"rUrrnrÚhomeÚCOLLECTOR_CONFIG_DIRr‡ÚOSErrorrmÚopenÚjsonÚloadr`r-r�)ruÚgrpÚpathsr�rÚhfÚ_grouprõrFrFrJÚ_load_group_configãs,  ý   zSoSCollector._load_group_configcCs²|jj|jj|jjdt|jƒdœ}t ¡dkrRtj   t   ¡d¡}tj |dd�nt}tj   ||d¡}t|ddd ��}t ||¡Wd ƒn1s˜0Yt |d ¡|S) a Saves the results of this run of sos collect to a host group file on the system so it can be used later on. The host group will save the options primary, cluster_type, and nodes as determined by sos collect prior to execution of sos reports. r)rÙr,rr-z.config/sos/groups.dT)Úexist_okrÙÚwr rNi€)rar5r,rYrrdrDrUÚgetuidrrnrrÚmakedirsrrrÚdumpÚchmod)ruZcfgZ group_pathr�rrFrFrJÚwrite_host_group s  ü * zSoSCollector.write_host_groupc Cs |j |j¡|jjs>|jjs>| d¡d}|j |  |¡¡z´|jjsX|jjrˆ|jj rˆ|jj sˆ| d¡d|jj ›d�}t |d�|j_|jdrð|jjsð|jj sð|jjsÜ|jjsÜ| d¡d |jj ›d �}t |d�|j_n|jjsð|jj|j_Wn t�y| d d ¡Yn0|jj�rŒ|jj d k�sz|jj �rFd}| |d¡| d¡d|jj ›d�}t |d�|j_d|jd<n| d¡d|j_|jj�rêz | ¡WnFt�yè}z,d|jj›d|›�}| |d¡WYd}~n d}~00z|j ¡Wn t�y| dd ¡Yn0|jj �r6| ¡d|j_nàzœd}d}d}|jj�s¼t ¡dk�r¼|jj�s¼|jj �s¤d}t |ƒ}|dk�r¼|j |¡d}d|j_d}n|j |¡d}d|j_td|j||d�|_ WnBt�y}z(| d|›�¡| dd¡WYd}~n d}~00|j d |j j ¡|j !d!¡|jj" !|j j ¡|j  #t$|jj"|j j ƒ¡|jj%�r¬|jj%d"k�r†|j&d#|_'n|j&|jj%|_'|jj%|_%|j |j'_ n| (¡|j'du�rÜ|jj"�sÜd$}| |d¡n2|j'du�r|jj"�r| d%¡|j&d#|_'d"|_%|j d&|j%¡|j'�rŒ|j'|j _'|jj)d'k�rL|j' *¡|j_)|j' +¡|j'j,�rŒ|jj-�sŒ| d(|j'j,›d)�¡|j'j,|j_-| .¡|jj/�r|jj/}z"| 0¡}| d*|›d+|›�¡Wn<t�y}z"| 1d,|›d|›�¡WYd}~n d}~00dS)-Nz)password not specified, assuming SSH keyszgsos collect ASSUMES that SSH keys are installed on all nodes unless the --password option is provided. z&password specified, not using SSH keysz"Provide the SSH password for user ú: )ÚpromptrÏz3non-root user specified, will request sudo passwordz=A non-root user has been provided. Provide sudo password for z on remote nodes: z Exiting on user cancel rRrzkCannot become root without obtaining root password. Do not use --batch if you need to become root remotely.ryz,non-root user asking to become root remotelyzUser z5 will attempt to become root. Provide root password: FzSOption to become root but ssh user is root. Ignoring request to change user on nodezCould not load specified group úExiting on user cancel Tz¸Local sos report generation forcibly skipped due to lack of root privileges. Either use --nopasswd-sudo, run as root, or do not use --batch so that you will be prompted for a password rz8Enter local sudo password to generate local sos report: rÚ localhost)Ú local_sudoZ load_factsz(Unable to determine local installation: zsUnable to determine local installation. Use the --no-local option if localhost should not be included. Aborting... r,r-rCZjbonzFCluster type could not be determined and no nodes provided Aborting...zCluster type could not be determined, but --nodes is provided. Attempting to continue using JBON cluster type and the node listrrzUpdating SSH key to z per clusterz Wrote group 'z' to zCould not save group )2rÒZ set_commonsr{rar1r2rmÚui_logrèÚ_fmt_msgr,Úbatchr9rr/rErsrtrZ root_passwordrêr"rrfZpre_workÚconnect_to_primaryr.rUrrr]r^Úaddressr\r-Úset_node_manifestÚgetattrrrjrYÚdetermine_clusterr;Zset_transport_typeZsetupZcluster_ssh_keyr8Ú get_nodesr5r"rg)rurÍrZ can_run_localr'Zskip_local_msgÚgnamer�rFrFrJÚprep#sþÿ ÿþ ÿÿ ÿ         ÿ"  ÿÿ    þ ÿþ ÿ         ÿ  zSoSCollector.prepc Cs8|j d¡|js&|jjs&| dd¡|j d¡|jjr‚|jjdur‚|jjrV|jj s‚|j j s‚|j d|jjd|j d›�›�¡t |jƒD]$}|j d|d|j d›�›�¡qŒ|j d¡|jj�s4ztd ƒ|j d¡WnRtyþ| d d ¡Yn6t�y2}z| t|ƒd¡WYd}~n d}~00dS) zuPrints a list of nodes to collect from, if available. If no nodes are discovered or provided, abort. rzGNo nodes were detected, or nodes do not have sos installed. Aborting...ryz1The following is a list of nodes to collect from:Nú rðrÑzC Press ENTER to continue with these nodes, or press CTRL-C to quit rQrR)r(rèrDr,Ú connectedrtrcÚlocalrar.rYÚstrict_node_listr{rˆr*ÚinputrsrfÚrepr)rur­r�rFrFrJÚ display_nodes¸s0 ÿ ÿÿ"   zSoSCollector.display_nodescCsd}i}|jjr t|jjƒ|d<|jjr0d|d<|jjr@d|d<|jjrPd|d<|jjrltt|jjƒƒ|d<|jjr„t|jjƒ|d<|jj rœt|jj ƒ|d <|jj d kr¸t|jj ƒ|d <|  ¡D]\}}|d |›d |›d �7}qÀ|  ¡}|  d|›�¡d|jd<||jd<|j d|¡dS)z:Configures the sos report command that is run on the nodeszsosreport --batch zcase-idrrzall-logsr=zlog-sizeÚsysrootrrzcompression-typez--rLzInitial sos cmd set to Úsos_cmdÚ sos_optionsZinitial_sos_cmdN)rarrrrr=r*rÁr:rÚcompression_typerÆÚrstriprmr{r]r^)rur;r<ÚkÚvrFrFrJÚconfigure_sos_cmdØs2   zSoSCollector.configure_sos_cmdc Cstz.t|jj|jƒ|_|j d|jj›d�¡Wn@tyn}z(| d|›�¡| dd¡WYd}~n d}~00dS)zgIf run with --primary, we will run cluster checks again that instead of the localhost. z Connected to z, determining cluster type...z#Failed to connect to primary node: z.Could not connect to primary node. Aborting...ryN) rrar,r{r(rèrfrmrt)rur�rFrFrJr+÷s zSoSCollector.connect_to_primaryc Csìt|j ¡ƒ}|j ¡D]Î}| |¡|j|_| ¡r|jj}| d|›d�¡|D]\}t |j|jƒrT|jj}| d|›d�¡|j|_| ¡rT| d|›d|›d�¡|}q²qT||_ |  ¡|_ |j |j d<|j d |j ›�¡qèqd S) a@This sets the cluster type and loads that cluster's cluster. If no cluster type is matched and no list of nodes is provided by the user, then we abort. If a list of nodes is given, this is not run, however the cluster can still be run if the user sets a --cluster-type manually zInstallation matches z, checking for layered profileszLayered profile z found. Checking installationz*Installation matches both layered profile z and base profile z), setting cluster type to layered profilerYzCluster type set to N)rdrjÚvaluesr›r,Z check_enabledrxr˜rmÚ issubclassrYrÙrr{r(rè)ruZchecksrYZcnameZ remainingZrnamerFrFrJr/s6  ÿþ    ÿzSoSCollector.determine_clustercCs(|jr$|j ¡}| d|›�¡|SgS)z>Collects the list of nodes from the determined cluster clusterz Node list: )rrYZ _get_nodesrm)rur-rFrFrJÚget_nodes_from_cluster(s  z#SoSCollector.get_nodes_from_clustercCsÊ|j|jvr"|jjr"|j |j¡|jjsL|jD]}||jvr0|j |¡q0|jdurŠ|jjsŠ|jD]$}||jj|jjfvrd|j |¡qdt t dd„|jDƒƒƒ|_|  d|j›�¡|j   d|j¡dS)zSReduce duplicate entries of the localhost and/or primary node if applicableNcss|]}|r|VqdSrMrF©rHÚnrFrFrJrO?rPz0SoSCollector.reduce_node_list..zNode list reduced to rD)rcrDrar.r›rYr6rer,rdÚsetrmr]r_)rurIrFrFrFrJÚreduce_node_list0s   zSoSCollector.reduce_node_listc Cst|jjD]f}z"t |¡}t ||¡r,WdSWqtjyl}z$d}| ||||f¡WYd}~qd}~00qdS)z�Compares a discovered node name to a provided list of nodes from the user. If there is not a match, the node is removed from the listTz0Error comparing %s to provided node regex %s: %sNF)rar-ÚfnmatchÚ translater¨rÝr¬rm)rur­ZregexrrÍrFrFrJÚcompare_node_to_regexCs    ,z"SoSCollector.compare_node_to_regexc sú|js|jsd}| |d¡z<| ¡}|jjrP|D]‰| ˆ¡r2|j ˆ¡q2n||_Wnvt yÎ}z^|  d|›�¡|  d¡|jj|_|jD]&‰t ‡fdd„dDƒƒr’|j  ˆ¡q’WYd}~n d}~00|jj�r(|jjD]D‰t ‡fd d„d Dƒƒrþqâˆ|jvrâ|  d ˆ›d �¡|j ˆ¡qâ|j�s†|j  d ¡d}|jD]&‰|ˆ d ¡dk�rF|j  ˆ¡�qF|jj�s†|j |j ¡| ¡z,tt|jtd�ƒ}t||jdƒ|jd<Wn:ttf�yô}z|  d|›�¡WYd}~n d}~00dS)z4 Sets the list of nodes to collect sos reports from zaCould not determine a cluster type and no list of nodes or primary node was provided. Aborting...ryzError parsing node list: z#Setting node list to --nodes optionc3s|]}|ˆvVqdSrMrFrG©r­rFrJrOerPz)SoSCollector.get_nodes..)Ú*ú\ú?ú(ú)r Nc3s|]}|ˆvVqdSrMrFrGrLrFrJrOkrPz*\?()/[]z Force adding rr†rrôrÑzCould not set UI spacing: )r,rYrtrDrar-rKrDr¦rfrmÚanyr›rcr’r6rHr§rÓr{Ú TypeErrorÚ ValueError)rurÍr-r�ÚhostZ _node_maxrrFrLrJr0PsJ       $     zSoSCollector.get_nodescCs†znt|d|j|dd�}| |j¡|jrd|j |¡|jj  |d¡|  t |jj|dƒ¡n|  ¡Wnt y€Yn0dS)zîTry to connect to the node, and if we can add to the client list to run sos report on Positional arguments node - a tuple specifying (address, password). If no password, set to None rry)r1N)rr{Z set_clusterrYr4rWr¦r]r-r\r-r.Ú disconnectrf)rur­ÚclientrFrFrJÚ_connect_to_node€s   ÿ  zSoSCollector._connect_to_nodec Csªd}|j dt›d�¡| ||j¡}|j |¡d}|jjs¦zt|ƒ|j d¡WnLtyv|  dd¡Yn0t y¤}z|  |d¡WYd }~n d }~00d S) zmPrint the intro message and prompts for a case ID if one is not provided on the command line ahThis utility is used to collect sos reports from multiple nodes simultaneously. Remote connections are made and/or maintained to those nodes via well-known transport protocols such as SSH. An archive of sos report tarballs collected from the nodes will be generated in %s and may be provided to an appropriate support representative. The generated archive may contain data considered sensitive and its content should be reviewed by the originating organization before being passed to any third party. No configuration changes will be made to the system running this utility or remote systems that it connects to. z sos collect (version z) z, Press ENTER to continue, or CTRL-C to quit rrQrRryN) r(rèr r)rÐrar*r7rsrtrf)ruZ disclaimerZ intro_msgr$r�rFrFrJÚintro–s  zSoSCollector.introcCsš|jjr| ¡| ¡| ¡|jjr<|jjr<| dd¡| ¡| ¡| ¡|  ¡|_ |j |j d�|j   ¡|_|j  dd¡| ¡| ¡dS)Nzƒ sos-collector was called with incompatible options --batch and --password. If you need to use --password, please omit batch mode. ry)rÙÚsos_logsií)rar)rtrYr*r1rAr2r9rÚ archive_nameZ setup_archiveÚarchiveZget_archive_pathÚ archive_pathrrBrÔrFrFrJÚexecute·s$ü  zSoSCollector.executec sTt|jj|jjgƒ‰|jjrBˆ t|jƒ¡s4|jjsB|j   |j¡|j   d¡‡fdd„|jDƒ}|j jr°g}|D]8}d|j j›d|d›d�}t|ƒ}|  |d|f¡qr|}�zt|j jƒ}|j|j|dd �|jd d �|j j�r|j djd k�r|j  d¡t|j ƒ|_|jdk�r,| d d¡n*|jdk�rV|j djd k�rV| dd¡|j   d|j›d|j j›d�¡t|j jƒ}|j|j|j dd �|jd d �t|j jƒ}|j|j|j dd �|jd d �Wnbt�yô|jddd d�Yn@t�y2}z&d|›�}|j|dd d�WYd}~n d}~00t|jdƒ�rj|j   d¡|j  ¡} | �rj|j !| ¡d}| "||j#|jf¡| $¡|j#dk�r¤| %¡|_&nd}| |d¡|j j'�sÈ|j j(�rPzN|j)|j*|j+|j |j,dœ} t-|j.|j/|j0d | |j&d�} |  1¡|j   d¡Wn8t�yN}z|j  2d|›�¡WYd}~n d}~00dS)zY For each node, start a collection thread and then tar all collected sos reports z Connecting to nodes...csg|]}|ˆvr|df‘qSrMrFrE©ÚfiltersrFrJr¡árPz(SoSCollector.collect..zPlease enter the password for ú@rr#ry)Z chunksizeT)Úwaitr&zNo nodes connected. Aborting...z±Collection would only gather from localhost due to failure to either enumerate or connect to cluster nodes. Assuming single collection from localhost is not desired. Aborting...z* Beginning collection of sos reports from z nodes, collecting a maximum of z concurrently r%rR)rÎzCould not connect to nodes: NZ run_extra_cmdz/Collecting additional data from primary node...z+ Successfully captured %s of %s sos reportsz4No sos reports were collected, nothing to archive...©rÒrÐÚsys_tmprÚrZ)rvÚargsÚcmdlineÚin_placeÚ hook_commonsr\zUploaded archive successfullyzUpload attempt failed: )3rGr,r,rcr4Ú intersectionrDrYr6rWr¦r(rèrar2r9rrr$ÚmaprXZshutdownr.Úpopr§Z report_numrtÚ_finalize_sos_cmdÚ_collectrsrfÚhasattrZ_run_extra_cmdZcollect_extra_cmdrêrXrÊÚcreate_cluster_archiver r?r@rÒrÐrdrZrrvrerfr^r¬) rur-Z_nodesr­rÍZnode_pwdZpoolZnpoolrÚfilesrhZuploaderrFr_rJrBÒs¨ÿþ  ÿ   ÿ    ûÿþ     &       ÿûûzSoSCollector.collectc CsNz | ¡Wn<tyH}z$| d|j›d|›�¡WYd}~n d}~00dS)z‰Calls finalize_sos_cmd() on each node so that we have the final command before we thread out the actual execution of sos z#Could not finalize sos command for r#N)Zfinalize_sos_cmdrfrgr,©rurWrrFrFrJrl7s ÿÿzSoSCollector._finalize_sos_cmdc Csrz8|js| ¡n|jjs"| ¡|jr6|jd7_Wn4tyl}z| d|›�¡WYd}~n d}~00dS)zRuns sos report on each noderyzError running sos report: N)r5Z sosreportrar.rXrfrgrqrFrFrJrmAs zSoSCollector._collectcCs0|jD]$}|jr| d|j›�¡| ¡qdS)zClose all sessions for nodeszClosing connection to N)rWr4rmr,rV)rurWrFrFrJrÊNs z"SoSCollector.close_all_connectionsc Csd}g}|jD]}|jD]}| |¡qqd}|jjrÀ|j|j|j|j|jdœ}z8|j   d¡t d|d�}|  |j¡|  ¡\}}d}Wn6ty¾}z|j  d|›�¡WYd}~n d}~00�z | d¡|D]€}| d ¡d } |rò| | ¡} tj |j|¡} |jj| | d �|rÒ| |¡} | rÒtj d | d ¡d ¡} | d 7} |j | | ¡qÒ|jj|jtj dd¡d �|jj|jtj dd¡d �|jdu�r¨|j |jj¡| ¡|�r tj |j|jj¡} |  tj | dd¡¡|  tj | dd¡¡|  tj | dd¡¡|jj!dd�} tj |jtj "| ¡¡}|�rJ| | #dd¡¡}t $| |¡|�r˜| tj |j|j%›d�¡¡}t $||¡|j   d|›�¡|j&  d|›�¡|j   d¡|j   d|›d�¡|WSt�y}z,d|›d|j'›�}| (|d¡WYd}~dSd}~00dS) zcCalls for creation of tar archive then cleans up the temporary files created by sos collectNFrcrT)rgrhz$ERROR: unable to obfuscate reports: z"Creating archive of sos reports...r éÿÿÿÿ)r¹Z checksumsz.sha256rZzsos.logzui.logZ sos_reportsz manifest.json)Úmethodz.tarz-obfuscated.tarZ _private_mapz2A mapping of obfuscated elements is available at zArchive created as zP The following archive has been created. Please provide it to your support team.r3rîzCould not finalize archive: z. Data may still be available uncompressed at r�z Archive error))rWZ file_listr¦rarrÒrÐrdrZr(rèrZset_target_pathr^rfr¬rêr’Zobfuscate_stringrUrrnr\Zadd_fileZget_new_checksumZ add_stringZ sos_log_fileZsos_ui_log_fileZadd_final_manifest_datar=Z_obfuscate_upload_passwordsÚ_nameZobfuscate_fileÚfinalizeÚbasenameÚreplaceÚrenamer[rçr]rt)rur+Z arc_pathsrUr�Zdo_cleanrhZcleanerrr¹rÙZchecksumZ_dirr Ú final_nameZmap_namerÍrFrFrJroUs¬  û ÿ  (     ÿ  ÿ ÿÿÿÿ ÿ   ÿÿ ÿ ÿ z#SoSCollector.create_cluster_archive)NrF)0r˜Ú __module__Ú __qualname__rÅZdescZ arg_defaultsrTriÚ classmethodrzr‚rŒrkrÂrÉrtrhrlrrrÛrêrËrgrmr)rürr rr"r2r9rAr+r/rDrHrKr0rXrYr^rBrlrmrÊroÚ __classcell__rFrFrwrJr(s²Q 2    ! l   (&  % 0!e  r)#rIr™rrUrþr¨rrbrúrorÚconcurrent.futuresrrÚpathlibrZshlexrZ sos.cleanerrZsos.collector.sosnoderZ sos.optionsr r Z sos.componentr Z sos.utilitiesr r|r Z sos.uploadrrrrFrFrFrJÚ s.