o m[hi @s ddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZddlmZddlmZmZddl m!Z!ddl"m#Z#ddl$m%Z%ddl&m'Z'dd l(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6dd l7m8Z8ddl9Z9dd l:m;Z;mZ>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEdd lFmGZGdd lHmIZIe*rddlJmKZKdaLe MeNZOe jPdiZQdejRejSZTdZUdZVddZWe#ddZXe#ddZYdede5eZe[fdeZfddZ\dede5eZe[fde[fdd Z]e?^d!d"e[de[fd#d$Z_d%d&Z`Gd'd(d(ZaGd)d*d*ebZcGd+d,d,ebZdd-d.Zedfd/d0Zfdfd1d2Zgdfd3d4Zhdgd6d7Zidfd8d9Zjdd:de.fd;d<Zkd=d>Zld?d@ZmdAdBZndhdDdEZodFdGZpdHeZdeqfdIdJZre#dKdLZse#dMdNZte#dOdPZue#dQdRZve#dSdTZwe#dUdVZxdidXdYZydfdZd[Zzdjd\d]Z{dfd^d_Z|e#d`daZ}dbdcZ~e#dddeZdfdfdgZdfdhdiZdjdkZdkdldmZdidne4e1deqfdodpZejdqdrZejdsdtZdudvZdwdxZdld{d|Zdfd}d~ZdeqffddZdmddZdd:deqfddZdd:deqfddZdfddZdfddZddZGddde2ZdiddZdnddZe?^ddefddZddZddZddZddZ doddZ doddZ doddZ doddZ doddZdpddZddZddWdde5eZe jfde3e,egdfdede[fddZddWdde5eZe jfde3e,egdfdedeZfddZe#ddZddZdefddZdqddZdkddZdkddÄZde.eZe+fde3eZde0e3eZfddDŽZde.eZe+ffddɄZdfdeZdeZfdd̄Zdd΄ZddЄZdd҄ZdrddՄZe?^d֡eqffdd؄ZddڄZdsdd܄ZejddބZddZ    CdtddZddZddZdiddZddZddZddZe#ddZddZddZ dudWddededdfddZddZddZdeZdefddZĐdeZdefddZŐdeZdeZfddZƐdeZdeZfddZǐdeZde0eZfd d Ze?^d   WdvdCddd dedefddZɐddZʐdwddZːdxddZ̐dkddZ͐ddZΐddZϐdd ZАd!d"Ze#d#d$ZҐd%d&ZӐ 'dyd(eZd)eZde.eZeZffd*d+ZԐd,d-ZՐd.d/Z֐d0d1ZeOdWfd2d3Zؐd4d5Zِd6d7Zڐd8d9Zېd:d;Zܐdid<d=ZeOdWfd>d?Zސd@eZdefdAdBZߐdCdDZdde jjPfdEdFZdzdHdIZdJdKZdfdLdMZdNdOZdPdQZdRdSZdTdUZd{dVdWZd|dYdZZd[d\Zdkd]d^Zd_d`deqfdadbZede/de+dffdcddZdS(}N) b64decode)deque)contextmanagersuppress)ENOENT) lru_cache)Path) ModuleType)IO TYPE_CHECKINGAnyCallableDequeDict GeneratorListMapping NamedTupleOptionalSequenceUnioncast)parse) featuresimportermergersnet performancesettingssubp temp_utils type_utils url_helperversion)logexc) CFG_BUILTIN)Paths_z_-.())true1onyes)off0nofalsecCs"ttttjdddS)N.)tuplemapintosunamereleasesplitr9r90/usr/lib/python3/dist-packages/cloudinit/util.pykernel_version`s"r;cCstjddgdd}|jS)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. dpkgz--print-architectureTcapture)rstdoutstrip)outr9r9r:get_dpkg_architectureds rBc sddddd}izAtjddgdd }|jD]}|d \}}}||vr.|||<qfd d |D}|rHtd d|WSWStj yo}ztd|t dd|DWYd}~Sd}~ww)Ncodename descriptionidr7)Codename DescriptionzDistributor IDRelease lsb_releasez--allTr=:csg|]}|vr|qSr9r9).0kdatar9r: szlsb_release..z.Missing fields in lsb_release --all output: %s,z#Unable to get lsb_release --all: %scss|]}|dfVqdS) UNAVAILABLENr9rKvr9r9r: szlsb_release..) rr? splitlines partitionr@valuesLOGwarningjoinProcessExecutionErrordict)fmaprAlinefnamer'valmissingerrr9rMr:rIos8    rIutf-8blobreturncCt|tr|S|j|dSN)encoding) isinstancestrdecode)rdrhr9r9r: decode_binaryrltextcCrfrg)ribytesencode)rnrhr9r9r: encode_textrmrqzBase64 decodingrNcCsBt|ts tdt|zt|ddWStjy |YSw)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)validate)riro TypeErrortyperbinasciiErrorrMr9r9r:maybe_b64decodes rwcCsP|jdd}|dkr&t|tr&|}|r|jr|j}nd}||dS|S)NT)rkrnrcsurrogateescape) get_payloadget_content_maintyperiro get_charset input_codecrk)part cte_payloadcharsetrhr9r9r:fully_decoded_payloads   rc@s&eZdZd ddZddZddZdS) SeLinuxGuardFcCs>|ztd|_Wn tyd|_Ynw||_||_dS)Nselinux)r import_moduler ImportErrorpath recursive)selfrrr9r9r:__init__s   zSeLinuxGuard.__init__cCs|jr |jr dSdSNTF)ris_selinux_enabled)rr9r9r: __enter__szSeLinuxGuard.__enter__c Cs|jr|js dStj|jsdStj|j}zt|}|j||tj Wn t y5YdSwt d||j z |jj||j dWdSt yf}zt d||j |WYd}~dSd}~ww)Nz,Restoring selinux mode for %s (recursive=%s)rz,restorecon failed on %s,%s maybe badness? %s)rrr5rlexistsrealpathlstat matchpathconstatST_MODEOSErrorrXdebugr restoreconrY)r excp_type excp_valueexcp_tracebackrstatser9r9r:__exit__s6  zSeLinuxGuard.__exit__NF)__name__ __module__ __qualname__rrrr9r9r9r:rs  rc@ eZdZdS)MountFailedErrorNrrrr9r9r9r:rrc@r)DecompressionErrorNrr9r9r9r:rrrc Osxt}|dkr0z||i|tdWdSty/ttdt|tdYdSwtd|t|dS)Nrz&Failed forking and calling callback %sz(Forked child %s who will run callback %s) r5fork_exit Exceptionr$rXr!obj_namer)child_cbargskwargsfidr9r9r:fork_cbs$ rcCsBt|tr |duSt}|rt||}t||vrdSdSr)ribool TRUE_STRINGSlistrjlowerr@r`addons check_setr9r9r:is_true  rcCsBt|tr |duSt}|rt||}t||vrdSdS)NFT)rir FALSE_STRINGSrrjrr@rr9r9r:is_falserrcCs |sdSt|tr |St||SNF)rirr)r`rr9r9r:translate_bools   r cs6ts tjtjdfddt|DS)Ncsg|]}qSr9)choice)rK_xr select_fromr9r:rO,szrand_str..)random SystemRandomstring ascii_lettersdigitsrZrange)strlenrr9rr:rand_str(s rcCs,|sd} tddd|}||vr |Sq)NrT)rr')r) dictionarypostfixnewkeyr9r9r: rand_dict_key/srinstance_data_filec Csddlm}m}m}m}zt|}Wn tyiYSw|rrtj |rrz||||}t d||Wn<|yN}z t d||WYd}~n(d}~w|yVYn|yq}zt d||t |WYd}~nd}~wwt|idS)z>Read a yaml config with optional template, and convert to dictr)JinjaLoadErrorJinjaSyntaxParsingException NotJinjaErrorrender_jinja_payload_from_filez?Applied instance data in '%s' to configuration loaded from '%s'z4Failed to render templated yaml config file '%s'. %sNz:Could not apply Jinja template '%s' to '%s'. Exception: %sdefault)!cloudinit.handlers.jinja_templaterrrrload_text_fileFileNotFoundErrorr5rexistsrXrrYrepr load_yaml)r_rrrrr config_filerr9r9r: read_conf9sJ    rcGs tt|SN)sorted uniq_merge)listsr9r9r:uniq_merge_sortedm rcGsFg}|D]}t|tr|d}dd|D}||qt|S)NrPcSg|]}|r|qSr9r9)rKar9r9r:rOzuniq_merge..)rirjr@r8extend uniq_list)r combined_lista_listr9r9r:rys  rcCs`tD] \}}|||}qg}|D] }|tvr||q|D]}||d}q!|}|S)Nr)FN_REPLACEMENTSitemsreplace FN_ALLOWEDappendr@)fnrLrSremovalsr9r9r:clean_filenames rTc CszWtt|E}tddd|+}|r)t|WdWdWS|WdWdWS1s?wYWdWdS1sPwYWdStyt}z|ri|WYd}~Stt ||d}~ww)Nrbr) ioBytesIOrqgzipGzipFilerlreadrrrj)rNquietrkbufghrr9r9r: decomp_gzips   XrcCs~|sdS|dd}|d}t|dkr|d}nd}|r+|dks+|dkr-d}|r9|dks9|dkr;d}||fS)NNNrJrrr1z-1none)r8r@lenr)ug_pair ug_partedugr9r9r:extract_usergroups   rroot_dircCsht}ttj|dD]$}tj|sq tj|dd}|}|r1|ddkr1|||<q |S)Nz*.pyrr0) r\globr5rrZisfilebasenamer@find)rentriesr_modnamer9r9r:get_modules_from_dirs rcCs dtvS)adeprecated: prefer Distro object's `is_linux` property Multiple sources of truth is bad, and already know whether we are working with Linux from the Distro class. Using Distro offers greater code reusablity, cleaner code, and easier maintenance. Linuxplatformsystemr9r9r9r:is_Linuxs rcCs$dtvrdStdkrdSdS)NBSDT DragonFlyFrr9r9r9r:is_BSDs  rcCtddkS)Nvariantfreebsd system_infor9r9r9r: is_FreeBSDrcCr)Nr dragonflyrr9r9r9r:is_DragonFlyBSDrr!cCr)Nrnetbsdrr9r9r9r: is_NetBSDrr#cCr)Nropenbsdrr9r9r9r: is_OpenBSDrr%FcCs||vr|St||Sr)ryobjkeyrr9r9r:get_cfg_option_bools r)cCs*||vr|S||}t|tst|}|Sr)rirj)r'r(rr`r9r9r:get_cfg_option_strs  r*cCtt|||dS)Nr)r4r*r&r9r9r:get_cfg_option_intsr,cCs|sd}tj|s iSt|}d}d|vrd}t||}|rS|}d|dvr0|d|d<|ddd|d<|dd krGd |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[^)]+)\) Virtuozzoz)(?P.+) release (?P[\d\.]+)namerCz linuxrzred hat enterpriseredhatr#)ID VERSION_IDVERSION_CODENAME) r5rrrrematch groupdictrrV) release_fileredhat_release redhat_regexr4groupr9r9r:_parse_redhat_releases,     r:c Csd}d}d}i}d}tjdrttd}|sd}t}|ru|dd}|dd}d|vs3d|vr8t}n6|d ks@|d krG|d d}n'|d krT|sT|d d}n|d d}|snt d|dd}|rn| d}|dkrtd}nJt rt }t}n[^)]+)\)VERSIONrCrhelr/)rrrrzPUnable to determine distribution, template expansion may have unexpected results)r5rrload_shell_contentrr:getrmachiner3r4r5rrrr7distrrXrY) distro_namedistro_versionflavor os_releaseos_release_rhelr4rGfoundentryr9r9r:get_linux_distro sz              rOcCs|d}d}|dkr8|dd}|dvr|}|S|dvr$d}|S|d kr,d }|S|d vr4d }|Sd}|S|d vr>|}|S)NrunknownlinuxrGr) almalinuxr>aoscarch azurelinuxcentos cloudlinuxdebian eurolinuxfedoramariner miraclelinux openeuler opencloudos openmandrivar?rCrockyr= tencentosrA)ubuntu linuxmintmintrbr/rC)opensusez opensuse-leapzopensuse-microoszopensuse-tumbleweedsle_hpcz sle-micror<r=)windowsdarwinrr"r$r )r)inforr linux_distr9r9r: _get_variant^s*    rkcCs<tttttttd}t||d<|S)N)rrr7pythonr6rGr)rrr7python_versionrr6rOrk)rir9r9r:rs  rcCsX||vr|S||durgS||}t|tr dd|D}|St|ts)t|}|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|]}|qSr9r9rRr9r9r:rOsz'get_cfg_option_list..)rirrj)r'r(rr`cvalr9r9r:get_cfg_option_lists    rocCs>t|tr |d}|}|D]}||vr|S||}q|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./)rirjr8)r'keyprcurtokr9r9r:get_cfg_by_paths   rtcCs t||\}}t||||fSr)get_output_cfgredirect_output)cfgmodeoutfmterrfmtr9r9r: fixup_outputs r{c CsttjdrtddS|stj}|stj}dd}|rtd||| dd\}}|dks6|d krDd }|dkr>d }t ||}n|d kr[t j |d t j |d} ttt| j}ntd||rmt||||krtd||t||dS|rtd||| dd\}}|dks|d krd }|dkrd }t ||}n|d krt j |d t j |d} ttt| j}ntd||rt||dSdSdS)N_CLOUD_INIT_SAVE_STDOUTz5Not redirecting output due to _CLOUD_INIT_SAVE_STDOUTcSs>tdztdj}Wn tyYdSwt|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) admN)r5umaskgrpgetgrnamgr_gidKeyErrorsetgid)group_idr9r9r:set_subprocess_umask_and_gids  z5redirect_output..set_subprocess_umask_and_gidzRedirecting %s to %s r>>>abwb|T)shellstdin preexec_fnz"Invalid type for output format: %sz!Invalid type for error format: %s)rr5environrErXrsysr?stderrr8open subprocessPopenPIPErr r rrsdup2fileno) ryrzo_outo_errrrxargowithnew_fpprocr9r9r:rvsh     rvsourcescCsR|rtt|}i}|D]}|r&t|}|st}t|}|||}q |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, } )rreversedrdict_extract_mergersdefault_mergers constructmerge)rreverse merged_cfgrwmergers_to_applymergerr9r9r: mergemanydict@s*    rc cs8t}zt||VWt|dSt|wr)r5getcwdchdir)ndircurrr9r9r:rxs  rc cs0t|}z |VWt|dSt|wr)r5r)n_mskoldr9r9r:rs  rcCsdj||d|dS)Nz{0:{fill}{align}{size}}^)fillalignsize)format)rnrmax_lenr9r9r:centersrcCstd|t|dS)NzRecursively deleting %s)rXrshutilrmtreerr9r9r:del_dirs rrc Cstzt|||d\}}}}||d<||d<||d<||d<WdStjy9}z|jtjkr4WYd}~dSd}~ww) z returns boolean indicating success or failure (presense of files) if files are present, populates 'fill' dictionary with 'user-data' and 'meta-data' entries )baseexttimeout user-data vendor-data meta-dataznetwork-configTNF) read_seededr"UrlErrorcode NOT_FOUND) rrrrmdudvdnetworkrr9r9r:read_optional_seeds rcCsi}|s ddg}ntj|ddtj|ddg}t|}dd|D}d}|D]}tjtj|drBtj|d}nq,d}|D]}tjtj|dr]tj|d}nqG|rl|rl||d <||d <|S|rr||d <|S) Nz/var/lib/cloud/data/sslz /var/lib/cloud/instance/data/sslrNsslcSs g|] }|rtj|r|qSr9)r5risdir)rKdr9r9r:rOs z%fetch_ssl_details..zcert.pemzkey.pem cert_filekey_file)r5rrZ get_ipath_cur get_cpathrr )paths ssl_detailsssl_cert_pathsrrrr9r9r:fetch_ssl_detailss:rc Cs |}t|}z/tdt||t|}|dur!td|}nt||s1td|t |f|}W|Stj tt fy}zJd}d}t |drUt |drUt |d}nt |drdt |drdt |d}|rw|dj|jd|jd|d 7}n|d j|d 7}t|WYd}~|Sd}~ww) 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 blob context_mark problem_markz5. Invalid format at line {line} column {col}: "{err}"r)r^colrbz. {err})rb)rlrXrryaml safe_loadrirsr!r YAMLError ValueErrorhasattrgetattrrr^columnrY)rdrallowedloaded convertedrmsgmarkr9r9r:rsL      r c CsV|ddkr |dd|}|dd|}|dd|}n*tjr5|ddkr5t|jdkr5|d7}d |d|f}d |d|f}d |d|f}d}tj|||d }d} | rat |j id } tj|||d } d} | rr| j } d} z tj|||d } Wntj y}z t d |WYd}~nd}~ww| r| j } nt d | | | |fS)Nz%srrrrr rprz%s%s%s)rretriesrz!Error in vendor-data response: %szError in vendor-data response)r rr%NOCLOUD_SEED_URL_APPEND_FORWARD_SLASHrurlparsequeryr"read_file_or_urlokrcontentsrrXr)rrrrud_urlvd_urlmd_urlrmd_resprud_resprrvd_resprr9r9r:rsH   rc sttdd}dd|D}fdd|D}g}|D];}tj|}z |t||dWqty@t d|Yqt yX}z t d||WYd }~qd }~wwt |S) zRead configuration directory.TrcSg|] }|dr|qS)z.cfg)endswithrKfr9r9r:rO$zread_conf_d..cs&g|]}tjtj|r|qSr9)r5rr rZrconfdr9r:rO's&r1REDACTED config part %s, insufficient permissionsError accessing file %s: [%s]N) rr5listdirrrZrrPermissionErrorrXrYrr)rrconfscfgsrrrr9rr: read_conf_ds, rc Cst}i}zt||d}Wn'tytd|Ynty4}z td||WYd}~n d}~ww||d}d|vr]|d}|r\t|tsVt d|t |ft| }nt j|drk|d}|r~t j|r~t||d}||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. rrrNrconf_dz8Config file %s contains 'conf_d' with non-string type %sz.d)rrrrXrYrrrirjrsr!rr@r5rrr appendleftr)cfgfilerrrwrr confd_cfgr9r9r:read_conf_with_confd>s>         rcCstt|dS)Ncmdline)rread_cc_from_cmdlinerr9r9r:read_conf_from_cmdlinemrr c Cs|durt}d|}d}d}t|}t|}t|}g}||}|dkrU||||}|dkr5|}|t||||dd||||}|dks'd|S)Nrz cc:end_ccrz\n ) get_cmdlinerr rrunquotelstriprrZ) r tag_begintag_endbegin_lend_lclentokensbeginendr9r9r:r rs,    r cCs2|d}|dks||ddkr|S|ddS)Nr rr z )r r)rposr9r9r:dos2unixs  rc@s&eZdZUeed<eed<eed<dS)HostnameFqdnInfohostnamefqdn is_defaultN)rrrrj__annotations__rr9r9r9r:rs  rcCsd}d|vrt|d}t|d|dd}n6d|vr5|dddkr5|d}|dd|d}n|jd|dj}d|vrF|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 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. Frrr0rNT)r metadata_only)r )rjr*r8r  get_hostnamerr)rwcloudr rrrr9r9r:get_hostname_fqdns$   r# /etc/hostscCsd}z=t|D]3}|d}|dkr|d|}|}|s!q |}t|dkr,q ||ddvr<|d}W|Sq W|StyIY|Sw)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#rr1r)rrUr r@r8rIOError)rfilenamerr^hashpostoksr9r9r:get_fqdn_from_hostss.    r+z Resolving URLc CsPt|}|j}tdur_t}d}i}|D]?}z0t|dddtjtj}g||<|D]\}} } } } || d| | df| | dq*Wqtj tj fyTYqw|a|r_t d|z:ttt|jdrx WdWdSWdn1swYt|d}|ddd} | tvWStj tj fyYd Sw) 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. N)zdoes-not-exist.example.com.zexample.invalid.!__cloud_init_expected_not_found__rz%s: %szdetected dns redirection: %sz[]TF)rrr_DNS_REDIRECT_IPsetsocket getaddrinfo SOCK_STREAM AI_CANONNAMEraddgaierrorerrorrXrrrr is_ip_addressnetlocr@)url parsed_urlr.badipsbadnames badresultsinameresult_fam_stype_protocnamesockaddraddrr9r9r: is_resolvablesF     rFcCs t}|Sr)r0 gethostname)rr9r9r:r!*sr!cCs(zt|dWStjyYdSwNr)r0 gethostbyaddrherror)ipr9r9r:rI/s rIcCst|S)z5determine if this url is resolvable (existing or ip).)rF)r9r9r9r:is_resolvable_url6srLc CsZ|durdStd||D]}zt|r td||WSWqty*YqwdS)zc Search through a list of mirror urls for one that works This needs to return quickly. Nz%search for mirror in candidates: '%s'zfound working mirror: '%s')rXrrLr) candidatescandr9r9r:search_for_mirror;s    rOdevicecCszg}|stdtdS|dr'|d}ddd|d|fD}|S|dkr2td}|S|d kr;td}|S) Nz/dev/msdosfs/*z/dev/iso9660/*LABEL=cSg|] }tj|r|qSr9r5rr)rKpr9r9r:rOVs  z*find_devs_with_freebsd..z /dev/msdosfs/z /dev/iso9660/ TYPE=vfat TYPE=iso9660)r  startswithr)criteriaoformattagno_cacherdevlistlabelr9r9r:find_devs_with_freebsdNs     r^c Csg}d}d}d}|r|dr|d}|dr|d}tjgddgd} | jD]5} |s3|r@tjd| gddgd\}} |rId ||vrIq-|d krRd |vrRq-|d kr[d |vr[q-|d | q-|S)NrrQzTYPE=sysctl-nz hw.disknamesrrcs mscdlabelrz label "%s"iso9660zISO filesystemvfat/dev/)rWrrr?r8r) rXrYrZr[rr\r]_type mscdlabel_outrAdevr'r9r9r:find_devs_with_netbsdbs*    rkcCstjgddgd}g}|jdD](}|dsq|dkr!q||ddd|d s<||ddd qd d |DS) Nr_rrbrPrJzfd0:r rcdicSg|]}d|qSrgr9rKrmr9r9r:rOrz*find_devs_with_openbsd..)rr?rstripr8rrrW)rXrYrZr[rrAr\rNr9r9r:find_devs_with_openbsd|s  rrcCs~tjgddgd}ddt|jddD}|dkr$d d|D}n|d vr0d d|D}n|r8td |d d|DS)N)r`raz kern.disksrrbcSs$g|]}|ds|ds|qS)rvnrWrpr9r9r:rOsz/find_devs_with_dragonflybsd..TrrVcSr)rlacdrtrpr9r9r:rOr)zLABEL=CONFIG-2rUcSsg|] }|ds|qSrurtrpr9r9r:rOrzUnexpected criteria: %scSrnror9rpr9r9r:rOr)rrr?r8rXr)rXrYrZr[rrAr\r9r9r:find_devs_with_dragonflybsds rwc Cs@tr t|||||Strt|||||Str!t|||||Str,t|||||Sdg}g}|r:|d||rC|d||rL| ddg|rU|d||r\||||}z t j |ddgd \}} Wnt j y} z| j t kr~d }nWYd } ~ nd } ~ wwg} |D] } | } | r| | q| S) z find devices matching given criteria (via blkid) criteria can be *one* of: TYPE= LABEL=