3 \me @s6 ddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZ ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZddlmZmZddlm Z ddl!m"Z"m#Z#ddlm$Z$m%Z%ddl&m'Z'ddl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0dd l1m2Z2dd l3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mm?Z?da@e jAeBZCe jDd iZEd ejFejGZHd}ZId~ZJddZKe$dddZLe$dddZMdddZNddd ZOePePd!d"d#ZQd$d%ZRGd&d'd'ZSGd(d)d)eTZUGd*d+d+eTZVd,d-ZWdd.d/ZXdd0d1ZYdd2d3ZZdd5d6Z[dd7d8Z\dd9e+d:d;d<Z]d=d>Z^d?d@Z_dAdBZ`ddDdEZadFdGZbeceddHdIdJZedKdLZfdCdCde jgdCfdMdNZhe$dOdPZie$dQdRZje$dSdTZke$dUdVZle$dWdXZme$dYdZZndd\d]Zodd^d_Zpdd`daZqddbdcZre$dddeZsdfdgZte$dhdiZuddjdkZvddldmZwdndoZxddpdqZyde/e-eddrdsdtZzej{dudvZ|ej{dwdxZ}dydzZ~d{d|ZdddZdddZdedffddZdddZdd9edd:ddZdd9edd:ddZdddZdddZddZeddddgZdddZdddZed:ddZddZddZddZddZddZdddZdddZdddZdddZdddZdddZddZdddZe$ddZddZed:ddZdddZddd„ZdddĄZddƄZddȄZddʄZdececd˜dd̈́Ze jePdΜddЄZdd҄ZddԄZddքZdddلZedffddۄZdd݄Zddd߄Zej{ddZddZdddZddZddZdddZddZddZddZe$ddZddZddZdd[deeddddZddZddZecedddZecedddZececdddZececdd d Zece,ecd d d ZddCdddddZddZÐdddZĐdddZŐdddZƐddZǐddZȐd d!Zɐd"d#Ze$d$d%Zːd&d'Z̐dd)d*Z͐d+d,Zΐd-d.Zϐd/d0ZeCd[fd1d2Zѐd3d4ZҐd5d6ZӐd7d8ZԐd9d:ZՐd;d<Z֐dd=d>ZeCd[fd?d@ZecedAdBdCZe0dDZڐde)dEefeڐdFdGdHZېdIdJZdde jjDfdKdLZސddNdOZߐdPdQZddRdSZdTdUZddVdWZdXdYZdZd[Zdd\d]Zdd_d`ZdadbZddcddZdedfZdgdhZdidjZddmdnZe%GdodpdpedpdqdrdsdtgZdd~d[duecece.eceedvdwdxZd~dyececedzd{d|ZdS(N) b64decode)deque namedtuple)suppress)EACCESENOENT) lru_cachetotal_ordering)Path)CallableDequeDictListMappingOptionalSequenceTypeVar)parse) featuresimportermergersnetsafeyamlsubp temp_utils type_utils url_helperversion) CFG_BUILTIN_z_-.()true1onyesoff0nofalsecCs"ttttjjjdddS)N.)tuplemapintosunamereleasesplitr1r1/usr/lib/python3.6/util.pykernel_versionRsr3cCstjddgd|d}|jjS)zReturn the sanitized string output by `dpkg --print-architecture`. N.B. This function is wrapped in functools.lru_cache, so repeated calls won't shell out every time. Zdpkgz--print-architectureT)capturetarget)rstdoutstrip)r5outr1r1r2get_dpkg_architectureVsr9c sddddd}iytjddgd|d }x:|jjD],}|jd \}}}||kr4|j||<q4Wfd d |jD}t|rtjd dj |WnFtj k r}z(tjd|t dd|jDWYdd}~XnXS)Ncodename descriptionidr/)ZCodenameZ DescriptionzDistributor IDZRelease lsb_releasez--allT)r4r5:csg|]}|kr|qSr1r1).0k)datar1r2 sszlsb_release..z.Missing fields in lsb_release --all output: %s,z#Unable to get lsb_release --all: %scss|]}|dfVqdS)Z UNAVAILABLENr1)r?vr1r1r2 |szlsb_release..) rr6 splitlines partitionr7valueslenLOGwarningjoinProcessExecutionErrordict) r5Zfmapr8linefnamervalmissingerrr1)rAr2r=cs( (r=utf-8cCst|tr|S|j|S)N) isinstancestrdecode)blobencodingr1r1r2 decode_binarys rZcCst|tr|S|j|S)N)rUbytesencode)textrYr1r1r2 encode_texts r^)rAreturnc CsBt|tstdt|y t|ddStjk r<|SXdS)zbase64 decode data If data is base64 encoded bytes, return b64decode(data). If not, return data unmodified. @param data: data as bytes. TypeError is raised if not bytes. zdata is '%s', expected bytesT)ZvalidateN)rUr[ TypeErrortyperbinasciiError)rAr1r1r2maybe_b64decodes   rdcCsP|jdd}|jdkrLt|trL|j}|r<|jr<|j}nd}|j|dS|S)NT)rWr]zutf-8surrogateescape)Z get_payloadZget_content_maintyperUr[Z get_charsetZ input_codecrW)partZ cte_payloadcharsetrYr1r1r2fully_decoded_payloads   rhc@s&eZdZd ddZddZddZdS) SeLinuxGuardFc Cs<ytjd|_Wntk r*d|_YnX||_||_dS)Nselinux)r import_modulerj ImportErrorpath recursive)selfrmrnr1r1r2__init__s  zSeLinuxGuard.__init__cCs|jr|jjrdSdSdS)NTF)rjis_selinux_enabled)ror1r1r2 __enter__szSeLinuxGuard.__enter__cCs|j s|jj rdStjj|js*dStjj|j}y"tj|}|jj||tj Wnt k rndSXt j d||j y|jj||j dWn4t k r}zt jd||j |WYdd}~XnXdS)Nz,Restoring selinux mode for %s (recursive=%s))rnz,restorecon failed on %s,%s maybe badness? %s)rjrqr-rmlexistsrealpathlstatZ matchpathconstatST_MODEOSErrorrJdebugrnZ restoreconrK)roZ excp_typeZ excp_valueZexcp_tracebackrmZstatser1r1r2__exit__s, zSeLinuxGuard.__exit__N)F)__name__ __module__ __qualname__rprrr{r1r1r1r2ris ric@s eZdZdS)MountFailedErrorN)r|r}r~r1r1r1r2rsrc@s eZdZdS)DecompressionErrorN)r|r}r~r1r1r1r2rsrc Osttj}|dkr\y|||tjdWqptk rXttdtj|tjdYqpXntjd|tj|dS)Nrz&Failed forking and calling callback %sz(Forked child %s who will run callback %s) r-fork_exit ExceptionlogexcrJrobj_namery)Zchild_cbargskwargsZfidr1r1r2fork_cbs  rcCsBt|tr|dkSt}|r&t||}t|jj|kr>dSdS)NTF)rUbool TRUE_STRINGSlistrVlowerr7)rQaddons check_setr1r1r2is_trues  rcCsBt|tr|dkSt}|r&t||}t|jj|kr>dSdS)NFT)rUr FALSE_STRINGSrrVrr7)rQrrr1r1r2is_falses  rcCs |sdSt|tr|St||S)NF)rUrr)rQrr1r1r2translate_bools  r cs8tjstjtjdjfddtd|DS)Ncsg|]}jqSr1)Zchoice)r?Z_x)r select_fromr1r2rB"szrand_str..r)randomZ SystemRandomstring ascii_lettersdigitsrLrange)strlenrr1)rrr2rand_strs rcCs.|sd}x tddd|}||kr Pq W|S)Nr)rr)r)Z dictionaryZpostfixZnewkeyr1r1r2 rand_dict_key%sr)instance_data_file)r_c Csddlm}m}m}y t|}Wn2tk rR}z|jtkr@iSWYdd}~XnX|rtj j |ry||||}t j d||WnH|k rYn6|k r}zt j d||t|WYdd}~XnX|dkriSt|idS)z>Read a yaml config with optional template, and convert to dictr)JinjaLoadError NotJinjaErrorrender_jinja_payload_from_fileNz?Applied instance data in '%s' to configuration loaded from '%s'z:Could not apply Jinja template '%s' to '%s'. Exception: %s)default)Z!cloudinit.handlers.jinja_templaterrr load_fileIOErrorerrnorr-rmexistsrJryrKrepr load_yaml)rPrrrrZ config_filerzr1r1r2 read_conf/s8   rcGs tt|S)N)sorted uniq_merge)listsr1r1r2uniq_merge_sortedasrcGsJg}x<|D]4}t|tr4|jjd}dd|D}|j|q Wt|S)NrCcSsg|] }|r|qSr1r1)r?ar1r1r2rBsszuniq_merge..)rUrVr7r0extend uniq_list)rZ combined_lista_listr1r1r2rms  rcCslx tjD]\}}|j||}q Wg}x|D]}|tkr,|j|q,Wx|D]}|j|d}qLW|j}|S)Nr)FN_REPLACEMENTSitemsreplace FN_ALLOWEDappendr7)fnr@rDZremovalsr1r1r2clean_filenamexs  rTcCsyLtjt|}tjtjddd|}|r8t|jS|jSWdQRXWn8t k r}z|rf|St t ||WYdd}~XnXdS)Nrbr) ioBytesIOr^ contextlibclosinggzipZGzipFilerZreadrrrV)rAquietrWbufZghrzr1r1r2 decomp_gzips rcCs|sdS|jdd}|dj}t|dkr:|dj}nd}| sX|dksX|jdkr\d}| sv|dksv|jdkrzd}||fS)Nr>rrr)z-1Znone)NN)r0r7rIr)Zug_pairZ ug_partedugr1r1r2extract_usergroups   r)root_dirr_cCslt}x`tjtjj|dD]H}tjj|s.qtjj|dd}|j}|r|jddkr|||<qW|S)Nz*.pyrr(r) rNglobr-rmrLisfilebasenamer7find)rentriesrPmodnamer1r1r2get_modules_from_dirs  rc Cs,t|d}|j||jWdQRXdS)Nw)openwriteflush)conpathr]Zwfhr1r1r2write_to_consoles  rc Cs|rtjj||rd}d}tjj|rxyt||d}Wn<tk rvd}tjj|d|rr|j t j |YnX|r| rtjj||r|ddkr|j ||ddn |j ||dS) Nz /dev/consoleFTzFailed to write to /dev/console rrr) sysstderrrr-rmrrrxr6logloggingZWARNING) r]ZconsolerrZ log_levelZfallback_to_stdoutrZwriting_to_console_workedZ console_errorr1r1r2 multi_logs(     rcCs dtjkS)NZLinux)platformsystemr1r1r1r2is_LinuxsrcCs$dtjkrdStjdkr dSdS)NZBSDTZ DragonFlyF)rrr1r1r1r2is_BSDs   rcCstddkS)Nvariantfreebsd) system_infor1r1r1r2 is_FreeBSDsrcCstddkS)Nr dragonfly)rr1r1r1r2is_DragonFlyBSDsrcCstddkS)Nrnetbsd)rr1r1r1r2 is_NetBSDsrcCstddkS)Nropenbsd)rr1r1r1r2 is_OpenBSDsrFcCs||kr |St||S)N)r)yobjkeyrr1r1r2get_cfg_option_boolsrcCs*||kr |S||}t|ts&t|}|S)N)rUrV)rrrrQr1r1r2get_cfg_option_str s  rcCstt|||dS)N)r)r,r)rrrr1r1r2get_cfg_option_intsrcCs|sd}tjj|siSt|}d}d|kr0d}tj||}|r|j}d|dkr`|d|d<|djjdd|d<|dd krd |d<|d|d |dd SiS) zReturn a dictionary of distro info fields from /etc/redhat-release. Dict keys will align with /etc/os-release keys: ID, VERSION_ID, VERSION_CODENAME z/etc/redhat-releasezA(?P.+) release (?P[\d\.]+) \((?P[^)]+)\)Z Virtuozzoz)(?P.+) release (?P[\d\.]+)namer:z linuxrzred hat enterpriseredhatr)ID VERSION_IDVERSION_CODENAME) r-rmrrrematch groupdictrrG)Z release_fileZredhat_releaseZ redhat_regexrgroupr1r1r2_parse_redhat_releases(      rc Csvd}d}d}i}d}tjjdr,ttd}|s:d}t}|r|jdd}|jdd}d|ksfd|krptj}nn|d ks|d kr|jd d}nP|d kr| r|jd d}n4|jd d}|st j d|jdd}|r|j d}|dkrd}nt r tj j}tj}nbd}z(y tj}Wntk r2YnXWdd}x|D]}|rBd}qBW|sftjdX|S|||fS)NrFz/etc/os-releaseTrrslessusealpinephotonZ PRETTY_NAME virtuozzorz[^ ]+ \((?P[^)]+)\)VERSIONr:rhelrrzPUnable to determine distribution, template expansion may have unexpected results)rrr)r-rmrload_shell_contentrrgetrmachinerrrrrrr/distrrJrK) Z distro_nameZdistro_versionZflavorZ os_releaseZos_release_rhelrrfoundentryr1r1r2get_linux_distro@sZ             r cCsv|dj}d}|dkrf|ddj}|d*kr6|}qr|d+krDd}qr|dkrRd}qr|d,kr`d}qrd}n |d-krr|}|S).Nrunknownlinuxrr almalinuxrarchcentos cloudlinuxdebian eurolinuxfedoramariner miraclelinux openeuler opencloudos openmandrivarrrockyr tencentosrubuntu linuxmintmintropensuse opensuse-leapopensuse-microosopensuse-tumbleweedsle_hpc sle-microrwindowsdarwinrrrr)r rrrrrrrrrrrrrrrrrr)rrr)rrr r!r"r#r)r$r%rrrr)r)inforrZ linux_distr1r1r2 _get_variant~s` r'cCs<tjtjtjtjttjtd}t||d<|S)N)rrr/pythonr.rr)rrr/Zpython_versionrr.r r')r&r1r1r2rs   rcCsX||kr |S||dkrgS||}t|tr@dd|D}|St|tsRt|}|gS)a Gets the C{key} config option from C{yobj} as a list of strings. If the key is present as a single string it will be returned as a list with one string arg. @param yobj: The configuration object. @param key: The configuration key to get. @param default: The default to return if key is not found. @return: The configuration option as a list of strings or default if key is not found. NcSsg|]}|qSr1r1)r?rDr1r1r2rBsz'get_cfg_option_list..)rUrrV)rrrrQZcvalr1r1r2get_cfg_option_lists    r)cCs>t|tr|jd}|}x |D]}||kr.|S||}qW|S)aReturn the value of the item at path C{keyp} in C{yobj}. example: get_cfg_by_path({'a': {'b': {'num': 4}}}, 'a/b/num') == 4 get_cfg_by_path({'a': {'b': {'num': 4}}}, 'c/d') == None @param yobj: A dictionary. @param keyp: A path inside yobj. it can be a '/' delimited string, or an iterable. @param default: The default to return if the path does not exist. @return: The value of the item at keyp." is not found./)rUrVr0)rZkeyprZcurtokr1r1r2get_cfg_by_paths    r,cCs t||\}}t||||fS)N)get_output_cfgredirect_output)cfgmodeoutfmterrfmtr1r1r2 fixup_outputs r3c CsttjjdrtjddS|s(tj}|s2tj}dd}|rtjd|||j dd\}}|dksn|d krd }|dkr~d }t ||}n0|d krt j |d t j |d} | j}n td||rtj|j|j||krtjd||tj|j|jdS|rtjd|||j dd\}}|dks:|d krXd }|dkrLd }t ||}n2|d kr~t j |d t j |d} | j}n td||rtj|j|jdS)NZ_CLOUD_INIT_SAVE_STDOUTz5Not redirecting output due to _CLOUD_INIT_SAVE_STDOUTc Ss>tjdytjdj}Wntk r.Yn Xtj|dS)aReconfigure umask and group ID to create output files securely. This is passed to subprocess.Popen as preexec_fn, so it is executed in the context of the newly-created process. It: * sets the umask of the process so created files aren't world-readable * if an adm group exists in the system, sets that as the process' GID (so that the created file(s) are owned by root:adm) ZadmN)r-umaskgrpgetgrnamgr_gidKeyErrorsetgid)Zgroup_idr1r1r2set_subprocess_umask_and_gids z5redirect_output..set_subprocess_umask_and_gidzRedirecting %s to %s r>z>>abwb|T)shellstdinZ preexec_fnz"Invalid type for output format: %sz!Invalid type for error format: %s)rr-environrrJryrr6rr0r subprocessPopenPIPErBr`dup2fileno) r1r2Zo_outZo_errr;r0argZowithZnew_fpprocr1r1r2r. s`        r.)sourcesr_cCsV|rtt|}i}x<|D]4}|rtj|}|s8tj}tj|}|j||}qW|S)aFMerge multiple dicts according to the dict merger rules. Dict merger rules can be found in cloud-init documentation. If no mergers have been specified, entries will be recursively added, but no values get replaced if they already exist. Functionally, this means that the highest priority keys must be specified first. Example: a = { "a": 1, "b": 2, "c": [1, 2, 3], "d": { "a": 1, "b": 2, }, } b = { "a": 10, "c": [4], "d": { "a": 3, "f": 10, }, "e": 20, } mergemanydict([a, b]) results in: { 'a': 1, 'b': 2, 'c': [1, 2, 3], 'd': { 'a': 1, 'b': 2, 'f': 10, }, 'e': 20, } )rreversedrZdict_extract_mergersZdefault_mergersZ constructmerge)rKreverseZ merged_cfgr/Zmergers_to_applyZmergerr1r1r2 mergemanydictZs*    rOc cs.tj}ztj||VWdtj|XdS)N)r-getcwdchdir)ZndirZcurrr1r1r2rQs   rQc cs&tj|}z |VWdtj|XdS)N)r-r5)Zn_mskoldr1r1r2r5s  r5cCsdj||d|dS)Nz{0:{fill}{align}{size}}^)fillZalignsize)format)r]rTZmax_lenr1r1r2centersrWcCstjd|tj|dS)NzRecursively deleting %s)rJryshutilZrmtree)rmr1r1r2del_dirs rYrcCsjy.t|||\}}}||d<||d<||d<dStjk rd}z|jtjkrRdSWYdd}~XnXdS)Nz user-dataz vendor-dataz meta-dataTF) read_seededrUrlErrorcodeZ NOT_FOUND)rTbaseexttimeoutmdudvdrzr1r1r2read_optional_seeds rdcCsi}|sddg}n(tjj|jddtjj|jddg}t|}dd|D}d}x2|D]*}tjjtjj|drZtjj|d}PqZWd}x2|D]*}tjjtjj|drtjj|d}PqW|r|r||d <||d <n |r||d <|S) Nz/var/lib/cloud/data/sslz /var/lib/cloud/instance/data/sslrAZsslcSs g|]}|rtjj|r|qSr1)r-rmisdir)r?dr1r1r2rBsz%fetch_ssl_details..zcert.pemzkey.pem cert_filekey_file)r-rmrLZ get_ipath_curZ get_cpathrr)pathsZ ssl_detailsZssl_cert_pathsrgrfrhr1r1r2fetch_ssl_detailss0   rjcCs |}t|}y\tjdt||tj|}|dkrBtjd|}n t||sbtd|tj |f|}Wntj tt fk r}zd}d}t |drt |drt |d}nt |drt |drt |d}|r|dj|jd|jd|d 7}n|d j|d 7}tj|WYdd}~XnX|S) NzKAttempting to load yaml from string of length %s with allowed root types %sz-loaded blob returned None, returning default.z2Yaml load allows %s root types, but got %s insteadzFailed loading yaml blobZ context_markZ problem_markz5. Invalid format at line {line} column {col}: "{err}"r)rOcolrSz. {err})rS)rZrJryrIrloadrUr`rrZ YAMLError ValueErrorhasattrgetattrrVrOcolumnrK)rXrZallowedZloadedZ convertedrzmsgZmarkr1r1r2rs<     r cCsV|jddkr@|jdd|}|jdd|}|jdd|}nTtjrj|ddkrjtj|jdkrj|d7}d |d|f}d |d|f}d |d|f}tj|||d }d} |j rt t |j id } tj|||d } d} | j r| j } d} ytj|||d } Wn2tj k r.}ztjd |WYdd}~XnX| j rB| j } n tjd | | | fS)Nz%srz user-dataz vendor-dataz meta-datarr*rz%s%s%s)r`retries)rz!Error in vendor-data response: %szError in vendor-data responser)rrrZ%NOCLOUD_SEED_URL_APPEND_FORWARD_SLASHrurlparseZqueryrZread_file_or_urlokrrZcontentsr\rJry)r^r_r`rsZ file_retriesZud_urlZvd_urlZmd_urlZmd_respraZud_resprbrcZvd_resprzr1r1r2r[ s<    r[csttjdd}dd|D}fdd|D}g}xh|D]`}y |jttjj||dWq<tk r}z|jt krt j d|WYdd}~Xq.cs&g|]}tjjtjj|r|qSr1)r-rmrrL)r?rx)confdr1r2rB>s)rz,REDACTED config part %s/%s for non-root userN) rr-listdirrrrmrLrxrrrJrKrO)ryrZconfscfgsrrzr1)ryr2 read_conf_d5s    r|cCst}i}yt||d}Wn8tk rR}z|jtkrBtjd|WYdd}~Xn X|j|d}d|kr|d}|rt|t st d|t j |fqt |j }ntjj|dr|d}|rtjj|rt||d}|j|t|S)aRead yaml file along with optional ".d" directory, return merged config Given a yaml file, load the file as a dictionary. Additionally, if there exists a same-named directory with .d extension, read all files from that directory in order and return the merged config. The template file is optional and will be applied to any applicable jinja file in the configs. For example, this function can read both /etc/cloud/cloud.cfg and all files in /etc/cloud/cloud.cfg.d and merge all configs into a single dict. )rz)REDACTED config part %s for non-root userNrZconf_dz8Config file %s contains 'conf_d' with non-string type %sz.d)rrrxrrrJrKrrUrVr`rrr7r-rmrer| appendleftrO)Zcfgfilerr{r/rzryZ confd_cfgr1r1r2read_conf_with_confdSs.       r~cCstt|dS)N)cmdline)rread_cc_from_cmdline)rr1r1r2read_conf_from_cmdlinesrc Cs|dkrt}d|}d}d}t|}t|}t|}g}|j|}x`|dkr|j|||}|dkrl|}|jtj||||jjdd|j|||}qHWdj|S)Nr<z cc:Zend_ccrz\nr) get_cmdlinerIrrrZunquotelstriprrL) rZ tag_beginZtag_endZbegin_lZend_lZclentokensZbeginendr1r1r2rs&     rcCs2|jd}|dks"||ddkr&|S|jddS)Nrrr z )rr)rvposr1r1r2dos2unixs rHostnameFqdnInfohostnamefqdn is_defaultcCsd}d|kr,|d}t|d|jdd}nld|krf|djddkrf|d}|dd|jd}n2|jd|dj}d|kr|d}n|j|d \}}t|||S) aGet hostname and fqdn from config if present and fallback to cloud. @param cfg: Dictionary of merged user-data configuration (from init.cfg). @param cloud: Cloud instance from init.cloudify(). @param metadata_only: Boolean, set True to only query cloud meta-data, returning None if not present in meta-data. @return: a namedtuple of , , (str, str, bool). Values can be none when metadata_only is True and no cfg or metadata provides hostname info. is_default is a bool and it's true only if hostname is localhost and was returned by util.get_hostname() as a default. This is used to differentiate with a user-defined localhost hostname. Frrr(rNT)r metadata_only)r)rr0r get_hostnamerr)r/Zcloudrrrrr1r1r2get_hostname_fqdns   r /etc/hostsc Csd}yvxpt|jD]`}|jd}|dkr6|d|}|j}|sDq|j}t|dkrZq||ddkr|d}PqWWntk rYnX|S)a For each host a single line should be present with the following information: IP_address canonical_hostname [aliases...] Fields of the entry are separated by any number of blanks and/or tab characters. Text from a "#" character until the end of the line is a comment, and is ignored. Host names may contain only alphanumeric characters, minus signs ("-"), and periods ("."). They must begin with an alphabetic character and end with an alphanumeric character. Optional aliases provide for name changes, alternate spellings, shorter hostnames, or generic hostnames (for example, localhost). N#rrr)r)rrFrr7r0rIr)rfilenamerrOZhashpostoksr1r1r2get_fqdn_from_hostss$    rcCs<tj|}|j}tdkrt}d }i}x|D]}ydtj|dddtjtj}g||<x>|D]6\}} } } } ||j d| | df|j | dqXWWq,tj tj fk rYq,Xq,W|a|rt jd|yNtttj|jjdrd SWdQRXtj|d}|dd d} | tkStj tj fk r6d SXdS) adetermine if a url's network address is resolvable, return a boolean This also attempts to be resilent against dns redirection. Note, that normal nsswitch resolution is used here. So in order to avoid any utilization of 'search' entries in /etc/resolv.conf we have to append '.'. The top level 'invalid' domain is invalid per RFC. And example.com should also not exist. The '__cloud_init_expected_not_found__' entry will be resolved inside the search list. Ndoes-not-exist.example.com.example.invalid.!__cloud_init_expected_not_found__rz%s: %szdetected dns redirection: %sz[]TF)rrr)rrtr_DNS_REDIRECT_IPsetsocketZ getaddrinfoZ SOCK_STREAMZ AI_CANONNAMEraddZgaierrorerrorrJryrrmrZ is_ip_addressZnetlocr7)urlZ parsed_urlrZbadipsZbadnamesZ badresultsZinameresultZ_famZ_stypeZ_protoZcnameZsockaddrZaddrr1r1r2 is_resolvables<      rcCs tj}|S)N)rZ gethostname)rr1r1r2r;src Cs*ytj|dStjk r$dSXdS)Nr)r gethostbyaddrZherror)Zipr1r1r2r@srcCsttjd|t|fdS)z5determine if this url is resolvable (existing or ip).zResolving URL: )logfuncrqfuncr)log_timerJryr)rr1r1r2is_resolvable_urlGs rc Cs\|dkr dStjd|x>|D]6}yt|r.z /dev/msdosfs/z /dev/iso9660/z TYPE=vfatz TYPE=iso9660)r startswithr)criteriaoformattagno_cachermdevlistlabelr1r1r2find_devs_with_freebsdrs    rc Csg}d}d}|r8|jdr$|jd}|jdr8|jd}tjdddgdgd}xx|jjD]j} |sf|rtjd| gdd gd\} } |rd || krqZ|d krd | krqZ|d krd | krqZ|jd| qZW|S)NzLABEL=zTYPE=sysctlz-nz hw.disknamesr)rcsZ mscdlabelrz label "%s"iso9660zISO filesystemvfatz/dev/)rrrr6r0r) rrrrrmrr_typer8devZ mscdlabel_outrr1r1r2find_devs_with_netbsds(    rcCstjdddgdgd}g}xd|jjjdD]P}|jdszfd0:rrcdicSsg|] }d|qS)z/dev/r1)r?rr1r1r2rBsz*find_devs_with_openbsd..rr)rr6rstripr0rwrr)rrrrrmr8rr r1r1r2find_devs_with_openbsds  rcCstjdddgdgd}ddt|jjdd D}|d krJd d|D}n(|dkrbdd|D}n|rrtjd|dd|DS)Nrz-nz kern.disksr)rcSs(g|] }|jd r|jd r|qS)raZvn)r)r?rr1r1r2rBsz/find_devs_with_dragonflybsd..T)rNz TYPE=iso9660cSsg|]}|jdr|qS)racd)rr)r)r?rr1r1r2rBsLABEL=CONFIG-2 TYPE=vfatcSsg|]}|jds|qS)rr)rr)r)r?rr1r1r2rBszUnexpected criteria: %scSsg|] }d|qS)z/dev/r1)r?rr1r1r2rBs)rr)rrr6r0rJry)rrrrrmr8rr1r1r2find_devs_with_dragonflybsds rc CsJtrt|||||Str,t|||||StrBt|||||StrXt|||||Sdg}g}|rt|jd||r|jd||r|j ddg|r|jd||r|j|||}yt j |ddgd \}} Wn:t j k r} z| j t krd }nWYd d } ~ XnXg} x*|jD]} | j} | r$| j| q$W| S) z find devices matching given criteria (via blkid) criteria can be *one* of: TYPE= LABEL=