i'dWc@sdZddkZddkZddkZddkZddkZddkZddkZddkl Z ddk l Z ddk l Z ddklZddklZlZlZlZlZddklZdd klZdd klZlZdd klZl Z l!Z!l"Z"dd k#l$Z$l%Z%l&Z&l'Z'dd k(l)Z)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6dZ7dZ8dZ9de:fdYZ;d e<fd!YZ=d"e<fd#YZ>d$e<fd%YZ?d&Z@d'ZAd(ZBd)ZCd*ZDd+ZEd,ZFd-ZGd.ZHd/ZIdd0ZKd1ZLd2ZMd3ZNd4ZOd5ZPd6ZQdd7ZRd8ZSd9ZTd:ZUd;ZVdd<ZWdd=ZXdd>ZYdd?ZZdd@Z[ddAZ\ddBZ]dCZ^dDZ_dEZ`ddFZae dGdHdIdJdKgZbdLZcdMZddNZedOZfdddddPZgdddddQZhdddddRZidSZjdTZkdUZldS(Vs+ Utility functions for the archive library iN(tDiskBootConfig(t namedtuple(tetree(t attrgetter(tPopentruntCalledProcessErrort SetUIDasEUIDt_(t InstallEngine(tINSTALL_LOGGER_NAME(tlibbetvdevs(tZpooltZvolt FilesystemtBE(tDiskt GPTPartitiont PartitiontSlice(tSizes/usr/sbin/beadms /usr/bin/curls#/usr/lib/brand/shared/get_active_bes/usr/sbin/labeladms /usr/bin/pkgs/usr/sbin/prtconfs/usr/sbin/prtdiags/usr/sbin/virtinfos/usr/sbin/zlogins/usr/sbin/zonecfgs/usr/bin/zonenames /usr/sbin/zfss/usr/sbin/zpools/usr/sbin/zoneadms/usr/sbin/zonep2vchkcCstiid|dS(s~Utility to write to stdout while spinner is in play. Drops a ' ' on the front of output and writes it out to stdout. s N(tsyststdouttwrite(toutput((s ../util.pyt spinwriteEst ArchiveErrorcBseZdZRS(s,General exception class for archive library.(t__name__t __module__t__doc__(((s ../util.pyRMst SystemInfocBseZdZddZedZeidZedZeidZedZ e idZ edZ e id Z e d d Z ed Z e id Z edZeidZRS(sbUtility class which organizes and encodes system-related information such as hardware resources and software components. Optional 'zone' constructor argument will derive information from a zone, otherwise it is the executing environment. Attributes: hostname hostname of the system (nodename) system_type system model or virtual system type os_name e.g. 'Solaris 11.2' os_version branch of osnet-incorporation arch ISA ('sparc' or 'i386') trusted boolean, True if labeling is enabled (global only) cCs|dj o9t|tptdn||_t|_nd|_d|_d|_d|_d|_ d|_ d|_ d|_ dS(s9Construct a new SystemInfo object. If the optional 'zone' argument is passed, the system information is based upon that particular zone. Otherwise, it's based upon the executing environment. Arguments: zone An optional zone to base the instance upon. s!'zone' argument is zonename (str)N( tNonet isinstancetstrt ValueErrort_zonet get_zonenamet _exec_zonet _hostnamet _system_typet_os_namet _os_versiont_archt_trusted(tselftzone((s ../util.pyt__init__`s         cCs*|idjoti|_n|iS(N(R+R tplatformt processor(R-((s ../util.pytarchzscCs ||_dS(N(R+(R-tvalue((s ../util.pyR2scCs|idjo|i|ijoti|_qt|idjoItii zt t |idg}WdQX|i i |_qd|_n|iS(Ntrunningthostnames (R'R R$R&tsockett gethostnametget_zone_stateRt__exit__t __enter__RtZLOGINRtstrip(R-tp((s ../util.pyR5s cCs ||_dS(N(R'(R-R3((s ../util.pyR5scCs|idjo|idjoybtid}ttdti}t t t |i |i ididi|_Wqttdddd d g}|i i|_qXqt|id jo d |_qd |_n|iS(Ntglobals!^System\s+Configuration\:\s+(.*)$t check_resultiis-ctcurrenttlists-Hotnames solaris-kzs kernel-zonesnon-global-zone(R(R R$tretcompileRtPRTDIAGRtANYtfiltertbooltmaptmatchRt splitlinestgroupR<tVIRTINFOtget_zone_brand(R-trxR=((s ../util.pyt system_types 5  cCs ||_dS(N(R((R-R3((s ../util.pyRPsc Cs|idjo|i|ijpt|idjoOtddii}z,|~}|ii di |_WdQXq t |idjoVt iizt t|iddg}WdQX|ii di |_q ttdn|iS(Ns solaris-kzs /etc/releasetriR4tcats solaris-kz zones must be running(R)R R$R&RNtopenR9R:treadRKR<R8RRR;Rt RuntimeErrorR(R-t_[1]tfR=((s ../util.pytos_names&)! cCs ||_dS(N(R)(R-R3((s ../util.pyRXst _OSVersionsversion, branchc Cs|idjot|idjod}d}nd}|i|ijpt|idjo&ttd|gdhdd 6}nst|id joJti i z/tt |itd|gdhdd 6}WdQXnt t d tid }ttt|ig}|iiD]}|ti|q/~d id}tid}ttt|ig} |iiD]}| ti|q~ d id}ti|||_n|iS(Nt solaris10s5.10sN/As'consolidation/osnet/osnet-incorporations solaris-kztinfotenvtCtLC_ALLR4s solaris-kz zones must be runnings^Version: (\S+)$iis^Branch: (\S+)$(R*R RNR$R&RtPKGR8RR9R:R;RURRCRDRGRHRIRJRRKR"R<RLRRY( R-tversiontbranchtonR=t version_reRVtlt branch_ret_[2]((s ../util.pyt os_versions. & F FcCs0t|tpttii||_dS(N(R!ttupletAssertionErrorRRYt_makeR*(R-R3((s ../util.pyRgscCs7|idjo |idjot|_n|iS(NR>(R&R,R ttrusted_enabled(R-((s ../util.pyttrusteds cCs ||_dS(N(R,(R-R3((s ../util.pyRlsN(RRRR R/tpropertyR2tsetterR5RPRXRRYRgRl(((s ../util.pyRRs  %tBootEnvcBs_eZdZddZedZeidZdZdZ dZ dZ RS( s+Utility class for Solaris Boot Environment creation and management during archive preparation and creation. Attributes: name BE name mountpoint BE mountpoint mounted True if mounted datasets list of datasets by name which comprise the BE Methods: create() Create a new BE 'name', cloned from the active BE mount() Mount the BE on 'mountpoint' unmount() Unmount the BE destroy() Destroy the BE cCsn||_tiid||_t|_g|_|ig}ti D]}||dqJ~j|_ dS(scConstruct an instance of BootEnv. Arguments: name BE name s/system/volatileiN( RBtostpathtjoint mountpointtFalsetmountedt _datasetsR tbe_listt_exists(R-RBRVtbe((s ../util.pyR/s    cCsx|iog|i o\ttddd|ig}g}|iiD]}||iddqG~|_n|iS(NRAs-ds-Ht;i(RxRvRtBEADMRBRRKtsplit(R-R=RVtds((s ../util.pytdatasetss>cCs ||_dS(N(Rv(R-R3((s ../util.pyR~&scCs_|iotd|intiizttd|igWdQXt|_dS(s Create the BEsBE '%s' existstcreateN( RxR#RBRR9R:RR{tTrue(R-((s ../util.pyR*s  c CsDtiiz ttd|i|igWdQXt|_dS(s Mount the BEtmountN( RR9R:RR{RBRsRRu(R-((s ../util.pyR2s"c CsJtiiz&ttdd|igdtiWdQXt|_ dS(sUnmount the BEtunmounts-ftstderrN( RR9R:RR{RBRtDEVNULLRtRu(R-((s ../util.pyR8s(c CsStiiz&ttdd|igdtiWdQXt|_ g|_ dS(sDestroy the BEtdestroys-fFRN( RR9R:RR{RBRRRtRxRv(R-((s ../util.pyR>s( N( RRRR R/RmR~RnRRRR(((s ../util.pyRos    tZoneInfocBseZdZddZedZeidZedZedZ edZ edZ edZ ed Z ed Zeid Zed Zed ZedZeidZedZeidZdZRS(s Utility class which organizes and encodes zone-related information such as brand and configuration data. Attributes: name zonename brand zone brand (e.g. 'solaris', 'solaris-kz', etc) state state of zone (e.g. 'installed', etc) zonepath zonepath zonepath_dataset zonepath dataset rpool_dataset zone's rpool dataset varshare_dataset zone's varshare dataset delegated_datasets list of a non-global zone's delegated datasets zonetype type of zone ('global' or 'non-global') is_global boolean, True if global ip_type IP type of zone ('shared' or 'exclusive') zonecfg zone configuration (in XML) devices list of device resources (solaris-kz) Methods: update_zonecfg(exclude) Update the zonecfg by removing any dataset elements which are in the 'exclude' list. cCs|dj o9t|tptdn||_t|_n d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_dS(sConstruct an instance of ZoneInfo. Arguments: zone The zone which is described by this instance. s!'zone' argument is zonename (str)N(R R!R"R#RBR%R&t_brandt_statet _zonepatht_zonepath_datasett_rpool_datasett_varshare_datasett_delegated_datasetst _zonetypet_ip_typet_zonecfgt_devices(R-R.((s ../util.pyR/_s"             cCs-|idjot|i|_n|iS(N(RR RNRB(R-((s ../util.pytbrandzscCs ||_dS(N(R(R-R3((s ../util.pyRscCs-|idjot|i|_n|iS(N(RR R8RB(R-((s ../util.pytstatescCs8|idjo!|i ot|i|_n|iS(N(RR t is_globalt get_zonepathRB(R-((s ../util.pytzonepathscCs8|idj o!|i ot|i|_n|iS(N(RR Rtget_zonepath_datasetRBR(R-((s ../util.pytzonepath_datasetscCs=|idjo&|idjot|i|_n|iS(NR>(RR RBtget_zone_rpool_dataset(R-((s ../util.pyt rpool_datasets cCs-|idjot|i|_n|iS(N(RR tget_varshare_datasetRB(R-((s ../util.pytvarshare_datasetscCs|idjo|iS|idjo|idjog|_ti|i}x~|idD]i}tt |i |i }d|djo!|di d|i|ds .//datasets %{zonename}RB(RRR RBRt fromstringtzonecfgtfindalltdicttziptkeystvaluestreplacetappend(R-tetelemR}((s ../util.pytdelegated_datasetss  !!cCsQ|idjo:|idjp|idjo d|_qJd|_n|iS(NR>s solaris-kzs non-global(RR RBR(R-((s ../util.pytzonetypes    cCs ||_dS(N(R(R-R3((s ../util.pyRscCs |idjS(NR>(R(R-((s ../util.pyRscCs|idjo}|idjom|i|ijo"ttdgii|_qtt d|iddg}|ii d|_n|iS(Ns solaris-kzs-ts-zR[sip-typei( RR RRBR&RtZONENAMERR<tZONECFGR|(R-R=((s ../util.pytip_types  "cCs=|idjo&|idjot|i|_n|iS(NR>(RR R&t get_zonecfgRB(R-((s ../util.pyRs cCs ||_dS(N(R(R-R3((s ../util.pyRscCs=|idjo&|idjot|i|_n|iS(Ns solaris-kz(RR Rtget_kz_devicesRB(R-((s ../util.pytdevicess cCs ||_dS(N(R(R-R3((s ../util.pyRscCs)|idjodS|idjoog}tii}x>|idtD]*}|i|jo|i|iqMqMWt |i||_ nt i |i}xj|i dD]Y}|id}d|jo|id|i}n||jo|i|qqWt i||_ dS(sUpdate this zone's configuration by removing any datasets which are present in the config and also in the 'exclude' list. If the zonecfg is unset, update_zonecfg() returns. NR>t class_typetdatasetRBs %{zonename}(RR RBR t get_instancetdoctget_descendantsR RRRRRtitertgetRtremovettostring(R-texcludetexcluded_poolsRtpoolRR}RB((s ../util.pytupdate_zonecfgs&  N(RRRR R/RmRRnRRRRRRRRRRRR(((s ../util.pyRFs&   cCsttddgiiS(s%Return a list of all installed zones.RAs-i(RtZONEADMRR|(((s ../util.pytget_all_installed_zonesscCst}|id|S(s5Return a list of all installed zones except 'global'.R>(RR(tzones((s ../util.pytget_installed_zoness  cCsttddgiiS(s&Return a list of all configured zones.RAs-c(RRRR|(((s ../util.pytget_configured_zonesscCst}|id|S(s-Return a list of configured non-global zones.R>(RR(R((s ../util.pytget_configured_ngzs  cCsh}ttddgii}xh|D]`}|iddd!\}}|i|}|djot||(RR(R((s ../util.pytget_ngz_with_state+s  cCsPt}g}tD]}||jo ||qq~}h|d6|d6S(sReturn a dict, each key of 'installed' and 'configured' with a list of installed and configured non-global zones, respectively. t installedt configured(RR(RRVtzR((s ../util.pytget_embedded_zones5s 5cCsFt}x6|D].}|i|}|o||jo|SqWdS(s:Return state of zone (e.g. 'running', 'unavailable', etc).N(RR(R.RRR((s ../util.pyR8?s  cCsttgiidS(s-Return the executing environment's zone name.i(RRRR|(((s ../util.pyR%HscCs)ttd|ddgiiddS(s$Return the brand of the zone passed.s-zRAs-pRi(RRRR|(R.((s ../util.pyRNMsc Cstiiz|djoTtodStdg}x(|pgD]}|id|gqKWt|iStt d|ddgiSWdQXdS(sReturn the zonecfg of the zone passed. If this is a global zone, a list of pools to exclude from the dataset's configuration elements may be passed. For global zones, a zonecfg is derived. If a global zone is trusted, no zonecfg is derived and None is returned. R>s-Xs-Zs-ztdetachs-nN( RR9R:RkR t ZONEP2VCHKtextendRRR(R.t exclude_poolstcmdR((s ../util.pyRRs   cCs[|djp#t|djptdjodSttd|ddgiidS(s&Return zonepath for a non-global zone.R>s solaris-kzs-zR[RiN(RNR%R RRRR|(tzonename((s ../util.pyRes cCsc|djp#t|djptdjodSt|}ttddd|giiS(s7Return the zonepath dataset name for a non-global zone.R>s solaris-kzRAs-HoRBN(RNR%R RRtZFSRR<(RR((s ../util.pyRms   cCsC|djp#t|djptdjodSt|dS(s Return the zone's rpool dataset.R>s solaris-kzs/rpoolN(RNR%R R(R((s ../util.pyRvs cCs|djptt|}ttddd|ig}|ii\}}||ijottd|i n|d}tt |i gii }|d|S(sBReturn the root dataset of the active ZBE tied to the active GZBE.R>RAs-Hosname,mountpoints,cannot prepare zone %s, zonepath not mounteds /rpool/ROOTt/( RiRRRRRR|RURRBt GET_ACTIVE_BER<(RR.R=t zonepath_dstzonepath_mountpointt zoneroot_dst active_be((s ../util.pytget_active_zbe_root_ds~s   c Cs~d}y]|djo*tdjodt||f}nttddd|giiSWntj odSXdS(s@Return the name of the VARSHARE dataset, or None if not present.srpool/VARSHARER>s%s/%sRAs-HoRBN(R%RRRRR<RR (R.tds_name((s ../util.pyRs&c Csttd|ddgdhdd6}g}xg}|iiD]}||iqE~D]\}t|id|idgpq_n|id d joq_n|i|q_Wt i d }g}t |i |D](}|d j o||id qq~S(sReturn the list of devices for the kernel zone passed. If the zone is not a kernel zone, None is returned. Only devices matching: '/dev/zvol/dsk/...' or '/dev/zvol/rdsk/...' will be returned. s-zR[tdeviceR\R]R^RJtstorages not specifiedis\/dev\/zvol\/r?dsk\/(\S+)iN(RRRRKR<tanyt startswithtfindRRCRDRItsearchR tgroups( R.R=RRVRdtlineRORftm((s ../util.pyRs(1%cCstddd|g}|dj oT|idt|id|tiizt|ii }WdQXnt|ii }t d|}|ot t t t|SdS(sRecursively get versions for this and all descendant datasets and return the highest file system version amongst them. This may be alternatively executed in the 'kz' passed. RAs-rHoR`iiNcSs |djS(t-((tv((s ../util.pyts(RR tinsertR;RR9R:RRR|RGR"tmaxRItint(RtkzRtversions((s ../util.pytget_max_zfs_versions cCsttdddgiiS(s!Return list of ZFS pools by name.RAs-HoRB(RtZPOOLRR|(((s ../util.pytget_all_zpoolsscCsQtii}g}|idtD]}|io||iq&q&~iS(s!Return the name of the root pool.R(R RRRR tis_rootRBtpop(RRVR=((s ../util.pyt get_root_poolscCsRt}tgd|dd|}|io|iio|iiiSndS(s!Return the name of the boot pool.trpnamettldpathRN(RRt versaboott boot_poolt pool_nameR (t root_pooltbootcfg((s ../util.pyt get_boot_pools    cCsJ|tjotd|nttddd|giidS(s>Return the health (as documented in ZFS literature) of 'pool'.sZFS pool not found: %sRAs-Hothealthi(RR#RRRR|(R((s ../util.pytget_zpool_healthscCstdd|g}|dj of|idt|id|tiiz+t|ii ddi d}WdQXn(t|ii ddi d}t |S(sURetrieve the version of ZFS pool 'pool', alternatively in kernel zone 'kz'. RR`iiiN( RR RR;RR9R:RRRKR|R(RRRR`((s ../util.pytget_zpool_versions 1'c Cstd||g}|dj oX|idt|id|tiizt|ii d}WdQXnt|ii d}|i \}}}}|S(s'Get value of prop passed and return it.RiiN( RR RR;RR9R:RRRKR|( tpoolnametpropRRtoutt_poolt_proptvalt_source((s ../util.pytzpool_get_props #cCs^|dj o@t|ddg}|id|tit|iiSti |SdS(sCReturn the vdev mapping for poolname, from remote 'kz' if provided.s/usr/bin/pythons-csR'from solaris_install.target.vdevs import _get_vdev_mapping as gv; print gv("%s")'N( R R;Rtastt literal_evalRRR<R t_get_vdev_mapping(RRR((s ../util.pytzpool_get_vdev_mappings   c Csg}tdd|g}|dj oX|idt|id|tiizt|ii d}WdQXnt|ii d}xD|D]<}|i \}}}}|djo|i |qqW|S(s8Return a list of all local properties set on 'poolname'.RtalliiNtlocal( RR RR;RR9R:RRRKR|R( RRt local_propsRt prop_linesRt_nonetpropnametsource((s ../util.pytzpool_get_local_propss # cCstdddddg}|dj oR|idt|id|tiizt|ii SWdQXnt|ii SdS( s=Return a list of all snapshots on the system, by datasetname.RAs-HoRBs-ttsnapiiN( RR RR;RR9R:RRRK(RR((s ../util.pytzfs_get_all_snapshotss cCsr|id\}}|g}xMt|D]?}|i|do%|id|o|i|q+q+W|S(s?Return a list of snapshots heirarchically rooted at 'snapshot'.t@R(R|RRtendswithR(tsnapshotRttop_dstsnapnametsnaplistR((s ../util.pytzfs_snapshot_and_descendants's  (c Csd}xt||D]}tdddd|g}|d j oe|idt|id|tiiz*t|dhdd 6i i d}Wd QXn't|dhdd 6i i d}|t |i 7}qW|S( sUsing 'snapshot' as a top level, get the 'referred' value on all snapshots in the heirarchy downward. return the total sum, in bytes. this serves as an estimate for the amount of space the stream will take up in a pool when deployed. iRs-HoR3treferiR\R]R^N( RRR RR;RR9R:RRR|Rt byte_value(RRttotal_size_in_bytestsRR((s ../util.pytzfs_get_all_snapshot_referred1s 0&c Cs4tddddddd|g }t|iiS(sReturn a list of all filesystems and volumes in this pool, by name. Note snapshots, while datasets, are not returned. RAs-Hs-tsfilesystem,volumes-oRBs-r(RRRR|(RR((s ../util.pytget_pool_datasetsFs c CsMtii}g}t|ittttd|idt|S(s~Return a list of all Filesystem and Volume datasets on the system. Note snapshots, while datasets, are not returned. RBR( R RRRIRR!RRR (Rtds_list((s ../util.pytget_all_datasetsPs c Cstit}ttddgdhdd6}g}|iiD]}||idqE~}tddd d d d d dddg }t|dhdd6ii}g}x<|D]4}||jo!|id||i |qqW|S(sCheck the host global zone's platform portability by determining if any key support software packages are missing. Return a list of packages by name which are found to be missing. RAs-asR\R]R^itcontentss-rs-Hs-otfmris-ttdepends-as type=groups'pkg:/group/system/solaris-core-platforms^UnifiedArchive: portability notice, '%s' is notinstalled. This may affect archive portability.( tloggingt getLoggertILNRR_RRKR|tdebugR( tloggerR=RVRdRt get_contenttcontenttmissingtpkg((s ../util.pytlist_missing_platform_support]s"4"  cCs|djotddg}ntd|ddg}t}xAt|dhdd6iiD]}|i|idqaW|S( s/Return set of publishers that are currently sett publishers-Hs-RR\R]R^iN(R R_tsetRRRKtaddR|(t be_mountpointRt publishersR((s ../util.pytpkg_get_publishersws  #t OriginInfoturitproxytkeytcertc Csg}d\}}}}ttd|gdhdd6}x2|iidD]}|i}|idoJ|o |it||||n|i d}d\}}}qN|ido+|i d}|d jo d }qkqN|id o+|i d}|d jo d }qkqN|id o+|i d}|d jo d }qkqNqNW|o |it||||n|pt t d |n|S(sReturn a list of this publisher's origins. Each origin item is a namedtuple that consists of its URI, Proxy, SSL Key and Cert.R1R\R]R^is Origin URI:isProxy:R sSSL Key:s SSL Cert:s5unable to determine repository URI for publisher '%s'N(NNNN(NNN( R RR_RRKR<RRR7R|RUR(R1toriginsR8R9R:R;R=R((s ../util.pytpkg_get_originss:"       cCs*|ddjo|S|d|dSdS(sBReturn the next-largest header-aligned (i.e. 512b-aligned) offset.iiN((toffset((s ../util.pyttar_header_alignscCsFy7ttdgiidid}|djSWntSXdS(s_Return True if current environment has labeling enabled. Valid in a global zone only. R[iitenabledN(RtLABELADMRRKR|Rt(R((s ../util.pyRks )cCs2t}tgd|dd|}|idj S(s9Return True if current environment has VersaBoot enabled.RRRN(RRRR (RR((s ../util.pytversaboot_enableds cCsYt||||}td|g}x(|D] }|it|d|q+Wt|S(Ns--headi(tcurl_build_credential_optstCURLRtlenR(turlR:R;tcacertthttp_auth_tokentcredential_optsttest_cmdtarg((s ../util.pyt_curl_get_heads  c CsQ|p|o|o| otdnyt|||||}Wntj otdnXx|iiD]2}|ido|ididj Sq{Wt ||||}t dddd |g}x(|D] } |i t |d| qWy9t |}|iid } d | jotStSWntSXd S( sReturn True if server passed in 'url' accepts ranges. Optionally pass crendentials in key, cert, cacert and http_auth_token. skey and cert must be pairedsunable to reach hosts Accept-Rangesitnones-sSs--heads-rs0-32is206 Partial ContentN(R#RLRRURRKRR|tlowerRCRDRRERRRt( RFR:R;RGRHR=RRIRJRKtresponse((s ../util.pytserver_accepts_rangess0     c Cs@yt|||||Wntj otdnXdS(sVerify the credentials passed in. Valid combinations are key and cert, cacert, or all three. Raises RuntimeError if credentials are invalid. scredentials invalidN(RLRRU(RFR:R;RGRH((s ../util.pytverify_credentialsscCsg}|dj o|id|gn|dj o|id|gn|dj o|id|gn|dj o'd|}|iddd|gn|S( sUtility routine to set up an array of credentials options for curl. Returns an empty list of no credentials are passed in. s--keys--certs--cacertsX-Auth-Token: %ss-XtGETs--headerN(R R(R:R;RGRHt cred_optstx_http_auth_token((s ../util.pyRC s     c Cst|i|i|i|i}dd }ytdd||ig}x(|D] }|it|d|qPWt |i i dd}yt |d }Wn#t td |inXWn-tj o!}t t|iinX|S( Ns%s-%si|is-sSs-ritiis!%s is not a valid Unified Archive(i|i(RCR:R;RGRHRDtgeturlRRERRR|RRURRtpopenR( R8t credentialsRIt range_strtget_sizeRKtdatatdescriptor_sizeR((s ../util.pytget_descriptor_sizes&    c Cst}xu|idtD]a}|i|jo|iqnx'tttgD]}|id|qSW|i |iqWdddg}t t t tg}xX|D]P}xG|id|D]3}t |do|i|jo d|_qqWqWt t t g}x|idtD]} t| _t} | i|joqnxR|D]J}| oPnx5| id|D]!}|i|jo t} PqwqwWqRW| p| iqqW|iS(sPrune an existing Target object to contain only the ZFS pools and their respective physical components for use during AI deployment. Rtpreservet use_existingtuse_existing_solaris2tactionR(RARR RBtdeleteRRRtdelete_childrenRRRRthasattrRaRRtall_names_to_xmlRttin_zpoolt get_childrentget_xml_tree_str( troott zpool_listtzpoolstzptchildtactionstobjstobjt child_listtdisktdisk_participates((s ../util.pytcreate_origin_target=sJ     (mRRR'RpR0RCR6Rtbootmgmt.bootconfigRt collectionsRtlxmlRtoperatorRtsolaris_installRRRRRtsolaris_install.engineR tsolaris_install.loggerR R)tsolaris_install.targetR R tsolaris_install.target.logicalR RRRtsolaris_install.target.physicalRRRRtsolaris_install.target.sizeRR{RDRRAR_tPRTCONFRERMR;RRRRRRRt ExceptionRtobjectRRoRRRRRRRRR8R%RNR RRRRRRRRRRRRRRR RRRR R!R#R0R6R7R=R?RkRBRLRPRQRCR]Rt(((s ../util.pyts       ("" I                        )     %