iVc@sdZddlmZmZmZmZmZmZmZm Z m Z m Z m Z m Z mZmZmZmZmZmZddlmZmZddlmZddlmZmZmZmZmZmZm Z m!Z!m"Z"ddl#m$Z$ddl%m&Z&m'Z'm(Z(m)Z)ddl*Z*ddl+j,Z,ddl-j,j.j/Z/ddl0j,j.j1Z1ddl2Zdd l2m3Z3dd l4m4Z4ddl5Z5ddl6Z6ddl7Z7ddl8Z8ddl9Z9ddl:Z:ddl;Z;ddl<Z<ddl=Z=d Z>d efd YZ?defdYZ@defdYZAdefdYZBdefdYZCdeDfdYZEdeDfdYZFdeFfdYZGdeFfdYZHdeFfdYZId eEfd!YZJd"eEfd#YZKd$eEfd%YZLd&eEfd'YZMd(eEfd)YZNd*eCeJeKeLeMfd+YZOd,eCeJeNfd-YZPd.efd/YZQdS(0s VersaBoot Implementation i(tBootmgmtInvalidPropertyErrort$BootmgmtMissingRequiredPropertyErrort#BootmgmtMalformedPropertyValueErrortBootmgmtNotSupportedErrortBootmgmtPropertyReadErrortBootmgmtZFSErrortBootmgmtZFSPoolNotFoundErrort!BootmgmtUnsupportedOperationErrortBootmgmtConfigReadErrortBootmgmtConfigWriteErrort"BootmgmtInsufficientDiskSpaceErrort BootmgmtErrort"BootmgmtVersabootNotSupportedErrortBootmgmtInvalidParameterErrort"BootmgmtInvalidParameterValueErrortBootmgmtReadOnlyStateErrortBootmgmtBootPoolCreationErrortBootmgmtBootPoolFailureError(t LoggerMixintget_current_arch_string(tSystemFirmware( t platform_nametsynch_file_am_timestcompare_usec_file_mtimetprom_get_bootdev_listtdevfs_bootdev_set_listtprom_devfs_to_prom_pathstprom_get_chosen_proptBOOTDEV_OVERWRITEtBOOTDEV_LITERAL(tcontextmanager(tRawConfigParsert NoOptionErrortMissingSectionHeaderErrort ParsingErrorN(tSolarisDiskBootInstance(tdatetimecCs-|jd}t|dkr%dS|dS(Nt/ii(tsplittlentNone(tdsnamet components((s"../../common/bootmgmt/versaboot.pytpool_from_dsname;st RecoveryFilecBsqeZdZdZddZdZdZdZdZdZ d Z d Z d Z d Z RS( s0 A simple-to-parse text file format used to hold property values for recovery purposes. Secure properties are stored with property names prepended with SECURE_PROP_PREFIX + ":". A simpler format than ConfigParser allows the kernel's early-boot parser to remain straightforward. tsecureicCs_||_||_||_||_i|_i|_d|_t|_ t|_ |j dS(s N( t_dirnamet _filenamet _file_ownt _file_permst _propdictt _spropdictR(t_fileobjtFalset_dirtytreadonlyt_load(tselftdirnametfilenamet ownershiptperms((s"../../common/bootmgmt/versaboot.pyt__init__Ls         cCs|jr|jjny+ttjj|j|jd|_WnUtk r}|j d|j t j krydS|j t j krt |_dSnX|jri|_i|_x*|jD]}|j|jdqWnt|_dS(s( Load the recovery file trsNo recovery file foundNs (R4tclosetopentostpathtjoinR.R/tIOErrort_debugterrnotENOENTtEPERMtTrueR7R2R3t _parse_linetstripR5R6(R9tioerrtline((s"../../common/bootmgmt/versaboot.pyR8Zs$      cCs"|jr"|jjd |_nytjd|jdt}Wn/tk rr}td|j|j fnXx:|j j D])\}}d||f}|j |qWx@|j j D]/\}}dtj||f}|j |qW|jtjj|j|j}|jd|j|fytj|j|yJtj||jd|jd|jd krtj||jnWn,tk r}|jd ||j fnXWnZtk r}ytj|jWntk rnXtd |j||j fnXd S( s tdirtdeletes1Couldn't create temporary recovery file in %s: %ss%s=%s s %s:%s=%s sTrying to rename %s to %siiis4OSError when setting ownership/permissions of %s: %ss/Couldn't rename temp recovery file %s to %s: %sN(R4R@R(ttempfiletNamedTemporaryFileR.R5tOSErrorR tstrerrorR2titemstwriteR3R,tSECURE_PROP_PREFIXRBRCRDR/RFtnametrenametchownR0R1tchmodtunlink(R9ttmpftoserrtkeytvalRNtdestfile((s"../../common/bootmgmt/versaboot.pyt_writersB    !  cCs|jdd}|dj}|dj|d<|djd}|dkr|jd||d|f||j|d= secure:= t=iit:isParsed `%s' to %s=%ss Malformed line `%s' (bad prefix)N(R&RLtfindRFR2R,RWR3(R9RNt equal_splittvaluetcolonR_((s"../../common/bootmgmt/versaboot.pyRKs cCsH|jj|dks+|j||kr7t|_n||j||j||krJt|_n||j|R8RbRKRlRnRoRqR@Rr(((s"../../common/bootmgmt/versaboot.pyR,As   /     tBootPoolConfigcBseZdZdZdZdZdZdZeegZiee6Z iee6Z e dZ dZ dZd Zed Zed Zd Zd ZedZRS(s sbpool-device-listsbpool-exclude-listteviction_algorithmtnonetlruc Cs$|jtjjjkr'tdn|jdkrEtdntjj |j ||_ ||_ ||_ tjj |j ||_||_||_|jd|jd|_g|_g|_i|_g|_g|_i|_tj|jtj<||_| r |jndS(s sABootPools are supported on disk-based BootConfig subclasses onlytzfssKBootPools are supported on ZFS-based disk-based BootConfig subclasses onlysConfig file is %sN(t boot_classtbootmgmtt bootconfigt BootConfigtBOOT_CLASS_DISKRt boot_fstypeRBRCRDtzfstopt_cfg_dirt _cfg_dir_ownt_cfg_dir_permst _cfg_filet _cfg_file_ownt_cfg_file_permsRFR(t_cfgt _device_listt _exclude_listt_BootPoolConfig__paramst device_listt exclude_listt_paramsRvtBPC_EVICT_ALGO_LRUtBPC_PROP_EVICTION_ALGOt bpool_nameR8( R9tbootcfgRtcfgdirtcfgdir_ownershipt cfgdir_permst cfgfilenametcfgfile_ownershipt cfgfile_permstloadnow((s"../../common/bootmgmt/versaboot.pyR>s,            cCs:t|j|_t|j|_t|j|_dS(s N(tlistRRRRtdictRR(R9((s"../../common/bootmgmt/versaboot.pyt_update_shadowssc Cst|_y|jj|jWnltk r]}d|_td|j|jfn5tt fk r}td|j|j fnX|j d|j |jj |j sdSy|jj|j tj}Wntk rd}nXy|jj|j tj}Wntk r/d}nXtj}xtjD]}yl|jj|j |}tj|}||kr|j d||f|||j|tj|j|jd|jdtj|j|jWn/tk r}|jd|j|jfnX|jWn/tk r }td|j|jfnXdS(s RtwNiis(OSError when setting ownership of %s: %ss5Couldn't create boot pool configuration file (%s): %s(RRRJRRt add_sectiontsetRvRRDRRRRRRt _make_cfg_dirRARRVRBRZRR[RRSRFRTRRER (R9taddsectRRtfileobjR^RM((s"../../common/bootmgmt/versaboot.pyt_save_s@    "$  cCs|j}|rdSy,tjj|s>tj||jnWn,tk rm}td||jfnXy%tj ||j d|j dWn,tk r}|j d||jfnXdS(s@Create the parent directories of the configuration file Ns,Couldn't create boot data directory (%s): %siis*OSError when changing owner/perm of %s: %s( RRBRCtexiststmakedirsRRSR RTRZRRF(R9R7tdatadirtdiroserrR^((s"../../common/bootmgmt/versaboot.pyRs % cCstjS(s (RvR(R9((s"../../common/bootmgmt/versaboot.pytsettable_parametersscCsQ|tjkrt|n|tj|kr@t|n||j|RR8RR5RtpropertyRRRRr(((s"../../common/bootmgmt/versaboot.pyRvs$    #  A ,  tBootPoolcBseZdZdZejdjZej dj Z dZ dZ ejdjZej dj ZdZdZejdjZej dj ZdZdZdOdPgZdQgZied6Zied6ed6ZddedRedZdZdZdZ e!dZ"dZ#e$dZ%e$dZ&eedZ'dZ(dZ)e*dZ+e!dRdZ,d Z-d!Z.d"Z/d#Z0d$Z1e!d%Z2d&Z3d'Z4d(Z5e$d)Z6ed*Z7d+Z8d,Z9d-Z:d.Z;d/Z<d0Z=d1Z>d2Z?dRed3Z@d4ZAee*e*ed5ZBd6ZCed7ZDeeed8ZEd9ZFeGd:ZHeGdRdRd;ZId<ZJd=ZKe!d>ZLd?ZMd@ZNdAZOe$dBZPdCZQdDZRedRdRdRdEZSdFZTedGZUdRedRdRdHZVdIZWdJZXdRdKZYeGedLZZdMZ[dNZ\RS(Ss The BootPool class encapsulates knowledge of a VersaBoot boot pool, which is a ZFS pool whose function is to store boot archives that are used to boot the system. tboottrootis bpool.confis recovery.kvpiscom.oracle:boot-poolsplatform/i86pc/kernel/amd64tunixsplatform/i86pc/amd64t boot_archivesplatform/%(platformname)st platformnametx86tsparctbpooltautocCst|jtjjjkr'tdn||_||_||_t j ||_ |j r|j d|t j |ryt j|t|_ Wqtk r}|j d|qXqng|_g|_g|_d|_d|_t|_t|_|r|j||_n|jg|_|jrxN|jD]@}|j||jkr>||jkr>|jj|q>q>Wn|dkr|j} nddl} t || j!rt"|} n |g} |j#t|_$|j%|j} g| D]} | | kr| ^q} | r;|j$j&j'| ng| D]} | | krB| ^qB}|r|j$j(j'||j d|n|j d| | |_)|j r|j*\}}}|j d ||f||_||_||_+nl|r |j,n|rc|j rcy|j-d t.d t.Wqct/k r_}|j d t0|qcXnd t1j2ds~                  %%         cCs)|jr%|j}|j|ndS(s N(Rt_get_default_boot_instancest"_complete_boot_pool_loader_install(R9R((s"../../common/bootmgmt/versaboot.pyt deferred_initJs  cCsyPtj|j}tj|}tj|}tj|}|||fSWn0tk r|jd|jtjfnXgdfS(s s*Couldn't get boot pool (%s) disk list (%s)N( Rztzpool_get_configRtzpool_config_to_disklisttzpool_config_to_partlisttzpool_config_to_healthlistRRFtzfs_error_stringR((R9t confignvlRRR((s"../../common/bootmgmt/versaboot.pyRQs  cCstj|j|j}y(|jd|j||ddfWntk rSnXy(tj||_tj||_ Wn#tk r}|jd|nXdS(sh Imports the boot pool using the membership list as the set of devices to scan. sESuccessfully imported boot pool `%s' with the following config: %s %st vdev_treetchildrens0Error getting current disk list from boot pool: N( Rzt zpool_importRRRFtKeyErrorRRRR(R9Rtkeyerr((s"../../common/bootmgmt/versaboot.pyt_import_boot_poolas    cCstj|tj}|S(s Returns the name of the boot pool associated with the specified root pool (if any), or None is there are none. (Rztzfs_get_user_propRtZFS_PROP_BOOTPOOL_LINKAGE(tclst rpoolnametprop((s"../../common/bootmgmt/versaboot.pyRws  cCsmg|D]}tj|r|^q}t|t|}t|dkri|jdt|n|S(s is!Filtered out nonexistent pools %s(RzRRR'RFR(R9tpoolstpooltnewlisttdiffset((s"../../common/bootmgmt/versaboot.pyRs (cCs|jS(s (R(R9((s"../../common/bootmgmt/versaboot.pytimportedscCs|jS(s (R(R9((s"../../common/bootmgmt/versaboot.pyt pool_namesc Cs|jr|jjrt}nt}y\|jd|j|jf|r`tjd|jIJnt j |j|jt|_ WnAt k r}|j tjkrt|_dSt|jnXys|jt|_|j\}}}|jd|j|f||_||_||_|jd|jWn&t k r_}|jd|nX|j|stdS|rtjdIJn|j}|jdtd td t|rtjd IJn|s|j|ndS( se Create the boot pool and add linkage to any root pool currently associated. s%Creating boot pool %s with members %ssCreating boot pool %s...Ns/[post-create] Current disks in boot pool %s: %ss!successfully created boot pool %ss'Exception during boot pool creation: %ss(Synchronizing essential BE boot files...t clear_firsttverboset noevict_onlys&Installing boot loader on boot pool...(RRRJR5RFRRtsyststderrRztcreate_boot_poolRRt zfs_errnotconstt EZFS_PERMR7Rtmsgt_boot_pool_update_linkageRRRRRt_synch_plat_boot_ordert_synch_default_boot_instancet full_resynchR( R9RRRtzfserrRRRR((s"../../common/bootmgmt/versaboot.pyRsN            c Cs|jr|jjrt}nt}|jj|j}d }d }|r|d}|j}|r|jddkr|j dd}n|r|rddl m }||j|||jj |}qn|rt j} nd } z |jd|dtd| Wd |r|rtj|} | dkrJtd |nytj|Wqtk r~|jd |qXnXd S( s iR%ii(t#prep_be_for_bootloader_installationt boot_devicesRt verbose_fileNsUnable to unmount BE %ssCouldn't remove mountpoint %s(RRRJR5t_complete_boot_device_listtboot_device_listR(tbootfstcountR&tlibbeR'RRRt_boot_pool_install_loadertlibbe_pyt beUnmountR RBtrmdirRSRF( R9RRR(tmntpttbe_nametbinsttroot_dsR't verb_filetret((s"../../common/bootmgmt/versaboot.pyRs<          cCsy*|jt|_|jd|jWnOtk rP|jd|jn,tk r{}|jd|j|fnXdS(s If the boot pool doesn't exist on the system, try to use zfs to import it. If that fails, we're out of luck. s"Successfully imported boot pool %ssCouldn't find boot pool %ss#Error while trying to import %s: %sN(R RJRRFRRR(R9R((s"../../common/bootmgmt/versaboot.pyRs    c CsOt|j|jtjtjtjftjtjtj tj ftj d|S(s R( RvRRRtBOOT_POOL_CFG_SUBDIRtBOOT_POOL_CFG_SUBDIR_OWNERtBOOT_POOL_CFG_SUBDIR_GRPtBOOT_POOL_CFG_SUBDIR_PERMStBOOT_POOL_CFG_FILEtBOOT_POOL_CFG_FILE_OWNERtBOOT_POOL_CFG_FILE_GRPtBOOT_POOL_CFG_FILE_PERMS(R9R((s"../../common/bootmgmt/versaboot.pyRs   cCsy|r-|jr-|jjr-|jj}n tj}|jtj}t|tri|j}n|dkr~g}nWn$t k r|j dg}nXxGt |D]9\}}|j |j||<|j d||qW|S(Ns.Couldn't get list of boot pool members from FWs$boot pool list item normalized to %s(t boot_loadertfirmwareRRiRotPROP_BOOT_POOL_LISTRt basestringR&R(RRFt enumeratet_whole_disk_devRL(RRtfwtbplisttindextitem((s"../../common/bootmgmt/versaboot.pyR#s"       cCs|j|j}g}y|j|_t|jj}|jj}|jd||jd|xF|D]>}||kr|j|n||kro|j |qoqoW|j |Wn6t k r}|jd|j d|_|}nX|S(s Loads the set of devices that should be in the boot pool. First, we consult the firmware device list, then add devices from the OSdb, and finally we prune devices excluded by the OSdb. sBPC device list is %ssBPC exclude list is %ss'Loading the boot pool config failed: %sN(RRRRRRRRFtremoveRRRRTR((R9RHt final_listtbpc_listRRJtbcre((s"../../common/bootmgmt/versaboot.pyRBs(        cCs|jdS(s Create the boot pool and add linkage to each of the passed root pools to the created boot pool, but does NOT synch any boot artifacts from the root pools, NOR does it install the bootloader. N(R(R9((s"../../common/bootmgmt/versaboot.pyRmscCs t|jS(s (RR(R9((s"../../common/bootmgmt/versaboot.pytpending_membershipvscCs t|jS(s (RR(R9((s"../../common/bootmgmt/versaboot.pytcurrent_membership|scCs|jrt|jSdSdS(s N(RRR((R9((s"../../common/bootmgmt/versaboot.pyR+s  cCs?|jd}|dkr|S||djr;|| S|S(s tsii(trfindtisdigit(Rtdevnametlast_s((s"../../common/bootmgmt/versaboot.pyRFs  cCs|j|}||jkr2|jd|dS|jj||jd|j|jjj|y6|jjj|}|jd||jj|=Wntk rnXdS(s s#%s already in boot pool member listNs New boot pool members list: `%s's$Found %s in exclude list -- removing( RFRRFRRRRRIt ValueError(R9tdevpatht found_index((s"../../common/bootmgmt/versaboot.pyt add_devices cCs|j|dS(s N(t_remove_device(R9RW((s"../../common/bootmgmt/versaboot.pyt remove_devicescCs|j|dtdS(s texcludeN(RZRJ(R9RW((s"../../common/bootmgmt/versaboot.pytexclude_devicescCst|jjS(N(RRR(R9((s"../../common/bootmgmt/versaboot.pytexcluded_devicesscCs|j|}|ra||jjkr;|jd|dS|jjj||jd|ny0|jj|}|jd||j|=Wntk rnXy6|jjj|}|jd||jj|=Wntk rnXdS(s s&%s already in boot pool exclusion listNs$%s added to boot pool exclusion lists(Found %s in _bp_members list -- removings#Found %s in device list -- removing( RFRRRFRRRIRVR(R9RWR\t found_idx((s"../../common/bootmgmt/versaboot.pyRZs&  cCs6|j\}}|dkr.|dkr.tStSdS(s Returns True of a membership change on the boot pool is needed based on the current state (current members vs. desired members) of the instance. N(t_compute_membership_changesR(R5RJ(R9taddlistt removelist((s"../../common/bootmgmt/versaboot.pytsynch_membership_neededscCs |jS(s (t_do_synch_membership(R9((s"../../common/bootmgmt/versaboot.pytsynch_membershipscCst|j}t|j}|j|}|s7dSg|D]}||kr>|^q>}t|t|}|jd||f||fS(s sAdd set = %s | Remove set = %sN(NN(RRRtsymmetric_differenceR(RRF(R9t curmembsett pendmembsettdevstdevtadd_listt remove_list((s"../../common/bootmgmt/versaboot.pyR`s%cCsl|j\}}|rD| rD|j rD|jd|jdS|ry5tj|j|\}}|jd||fWqtk r|jd|jtjfqXn|rytj |j|Wqtk r|jd|jtjfqXn|s|rh|j \}}}|rM||_ ||_ ||_ n |jd|jtStS(s s*Creating boot pool due to membership synchNsadd: success=%s | failed=%ss)Error adding devices to boot pool %s (%s)s-Error removing devices from boot pool %s (%s)s#Problem getting boot pool disk list(R`RRFRRztadd_devices_to_poolRRRtremove_devices_from_poolRRRRR#RJR5(R9RkRltsuccesstfailedRRR((s"../../common/bootmgmt/versaboot.pyRds:            c Cstjtjt}x9t|D]+\}}|d|j|df||s(twalk_be_datasetstsort(R9RRtargdict((R9s"../../common/bootmgmt/versaboot.pyt_build_mru_list^s  cCs|j}x|D]}|d}|drC|jd|qn||kre|jd|qny~|jd||df|rtjd||dfIJntj|}|dkr||d8}|dkrtSnWqtk r|jd|qXqWtS( sj Tries to evict enough boot pool datasets to satisfy the space_needed constraint. R)Rs[noevict] NOT evicting %ssNuking dataset %s for %d bytesRs.Evicting boot pool dataset %s [%d bytes freed]isCannot destroy dataset %s( RRFRRRztdestroy_datasetRJRR5(R9Rt space_neededRRtmruR)tretval((s"../../common/bootmgmt/versaboot.pyt_evict_boot_pool_datasetss.           cCstj|}|j|j}|d 7}tj|tj} | dkr|jd|| ||| f|| 8}|dkrd}qn|||j} | dkrd} n| d|j } | dkr4d| |j d} | |j} |jd| | f|r't j d| | fIJn|| 7}n|jd ||f||kr|r|g}|rt t |jt |}n|j|||d |S||kr| rtStS( sS Returns True is enough space is available to store [space_required] under the bpdmountpt mount point. If initially insufficient space exists in the boot pool, datasets will be discarded in accordance with the boot pool eviction policy, namely: Eliminate oldest datasets first, ignoring datasets corresponding to BEs that are "noevict" (whose zfs property `com.oracle.boot-pool:eviction-policy' includes "noevict".) If, after processing the maximum number of evictions, there is still insufficient space, we return False. iisOSpace already used by dataset %s: %d (subtracting from %d => %d really requiredidiisSBoot pool free space is below min threshold (at %d%%). Adding %d to space requiredsVBoot pool free space would be below threshold (at %d%%). Adding %d to space required.s#Free space: %d | Space required: %dRi(RBtstatvfstf_frsizetf_bfreeRzRRRRFtf_blocksRRRRtunionRR5RJ(R9t bpdmountptt bpdatasettspace_requiredtevictt noevictlistRRt freespacetspace_in_datasettnew_freespace_blockst new_freepctt need_blockst addl_spacet donotevict((s"../../common/bootmgmt/versaboot.pyt_space_availablesH                    $ cCsTxMt|D]?\}} | djtjj} g} g} xntdt| D]W} tjjj| | }| jtjj||| jtjj||qTWtjj|| d}tjj|| d| d}tjj|| d}|s| ry||}tj |}t ||r|j |j kr|rkt j d||fIJn|jd||fw n |rdSWqttfk r|rdSqXn|jd||fytj|Wn;tk r}|jtjkrtd||qnXxt| | D]}\}}yHtj |}tj|t j|jtj||j|jWq.tk r}|jd|jq.Xq.W|rt j d||fIJnytj||Wn,tk r}td ||f|nXyt||Wq tk rK}|jd |jq Xq Wd S( s Copies the essential boot files from rpdmountpt to bpdmountpt. Raises BootmgmtInsufficientDiskSpaceError (and tries to undo all items copied up until that error) if there's not enough space on the destination filesystem. iis)[NOT COPYING] unchanged file %s (vs. %s).s%[NOT COPYING] unchanged file %s -> %ssCopying %s -> %ss)Couldn't create directory %s on boot pools#[IGNORED] attribute copy failed: %ss0Copying %s (from root pool) to %s (on boot pool)s.Couldn't copy essential boot file `%s' to `%s's1[IGNORED] Could not set file access/mod times: %sN( RER&RBRCtseptxrangeR'RDRRuRRvRRRFRSRERRGtEEXISTR tzipR[tS_IMODEtst_modeRZtst_uidtst_gidRTtshutiltcopy2R(R9tftupsR|RwRRRt checkonlyRIRytpath_componentstrpathstbpathsRtpathsegtbparenttrfiletbfileR}tbsbR^trpathtbpathtstRM((s"../../common/bootmgmt/versaboot.pyt_copy_boot_filessp            cCs^|jd|}|jdd}|s?tj|d}n|r|jr|j} | jtjtjkrt }|j dqn| r|r|r|jd|} | g} nd } |j |3} |rt jd|| fIJn|j| \} }}|s+tj|i|d6ny|j |}|r`t jd||fIJn|s|j||| || |r|j||| |||rt nt|}|r|Sntd||fWd QXWn!tk rtj|nXWd QX|rt jd |IJn||krZ|j d ||ftj|jd|nd S( s Does the heavy lifting of synchronizing a BE's bootable files from the rpool to the boot pool. - Creates the boot pool dataset, if needed - Mounts the boot pool dataset - Mounts the root pool dataset, if needed - Copies essential boot files (boot archive [+ kernel]) to the boot pool dataset if sufficient free space exists on the boot pool. Tries to avoid copying files that are the same size with the same last-modification time as those on the root pool IFF opt==True. - If there is insufficient space, datasets on the boot pool are deleted in accordance with the boot pool eviction policy ("noevict" datasets are deleted last, and others are deleted in LRU order (if eviction is enabled).) - Once sufficient space has been freed, we retry copying the essential boot files. - The root pool dataset is unmounted - The boot pool dataset is unmounted R%iR,s2Overriding eviction to False due to policy settings#Root pool dataset %s mounted on %s.scom.oracle:rootfss#Boot pool dataset %s mounted on %s.scInsufficient disk space: Could not update boot pool dataset %s with boot files from root dataset %sNsRoot pool dataset %s unmounted.s6rpool bootfs set to %s; setting boot pool bootfs to %s(RR&Rztzpool_prop_getRRRvRRR5RFR(t_mount_datasetRRR~tcreate_datasetRRRJR Rtzpool_prop_set(R9tdatasetRRtoptRRRt rpool_bootfstbpct bpool_bootfsRRwRRR|Rt check_value((s"../../common/bootmgmt/versaboot.pytsynch_rpool_dataset8s\             cCs|j|dtS(s Returns True if the specified root dataset is out of synch with the cached dataset (boot files) on the boot pool. R(RRJ(R9R((s"../../common/bootmgmt/versaboot.pytdataset_synch_requiredscsfd}g}|r+tjdIJnj|||r[tjdt|IJnxu|D]m}y;|rtjd|IJntj|jd|Wqbtk r}jd||fqbXqbWdS(s9Deletes ALL cached BE datasets on the boot pool. cs!jd||j|dS(NsAppending %s to listi(RFR(Rtytz(R9(s"../../common/bootmgmt/versaboot.pyt_append_to_lists s*Searching for boot pool cached datasets...sFound %d cached dataset(s)s Destroying %s...sDestroyed boot pool dataset %ss)Failure deleting boot pool dataset %s: %sN(RRRR'RzRRFR(R9RRt to_be_deletedtbpdsnametbpze((R9s"../../common/bootmgmt/versaboot.pytdelete_all_cached_be_datasetss"    cCsd}|jr'|jjr't}ntj\}}|dkrXtd|ng}x|D]}|jd} | d krqen|j| \} } | d krt j | t j } t j| } |jd| n|tks| re|ji| d6| d6| d6qeqeW|s6|jd d S|jd |d t|jd ||r|rxtjdIJn|j|ny2x+|D]#} |j| ddtd|qWWntk rnXd S(s cSs@t|d|d}|dkr'|St|d|dSdS(NRiR(tcmp(RRt noevict_cmp((s"../../common/bootmgmt/versaboot.pyt cmp_mruents is%Couldn't get full BE list (code = %d)R6sUsing creation time for ds %sR)RRs mrulist is empty: Nothing to do.NRtreversesSORTED: [[ %s ]] s)Clearing all boot pool cached datasets...RR(RRRJR0tbeListR RiR(RRzRRRR$RRFR5RRRRRRR (R9RRRRR8tbelistRtbetrootdsRRRtmruent((s"../../common/bootmgmt/versaboot.pyR%sD         cCs&||jkr"|jj|ndS(sxAdds the specified root pool to the pending list of root pools that are associated with this boot pool. N(RR(R9R((s"../../common/bootmgmt/versaboot.pyt link_rootpoolsccs7|j%}|jd|j|f|VWdQXdS(sJ Mounts the top-level dataset and returns the mount point s Top dataset for %s mounted on %sN(RRFR(R9tmountpt((s"../../common/bootmgmt/versaboot.pyt top_datasets ccs.|dkr|jn|}tj|}|rO|jd||f|VdS|svtjdddd}t}n |}t}|jd||ftj ||z |VWdyO|jd|tj ||ryt j |Wqt k rqXnWn#tk r(}|jd |nXXdS( s Creates a temporary mount point if none is specified and mounts the top-level dataset of the boot pool there. Yields the mointpoint. s&Found dataset %s already mounted on %sNtsuffixs-bpoolROs/system/volatiles#Mounting boot pool dataset %s on %ssUnmounting boot pool dataset %ss'Error unmounting top-level dataset (%s)(R(RRztdataset_mountpointRFRQtmkdtempRJR5t zfs_mountt zfs_unmountRBR2RSR(R9RRt dataset_namet mounted_ont mountpointtcleanuptbmzerr((s"../../common/bootmgmt/versaboot.pyRs8          cCstjj|tj}tjj|s0|r4dSy,tjj|s_tj|tjnWn,tk r}t d||j fnXytj |tj tj Wn,tk r}|jd||j fnXdS(s Ns,Couldn't create boot data directory (%s): %ss*OSError when changing owner/perm of %s: %s(RBRCRDRR9RRR<RSR RTRZR:R;RF(R9tbasedirR7RRR^((s"../../common/bootmgmt/versaboot.pyt_do_create_boot_datadir!s cCs|j|j|_g}x|jD]z}|jd||jfytj|tj|jWn.tk r|jd|tj fnX|j |q%Wt ||_ dS(s Update boot pool linkage property on all root pools, then update _bp_cur_rpool_list to the list of root pools on which it was set successfully. s$Linking root pool %s to boot pool %ss3Failed to add boot pool linkage property to %s (%s)N( RRRFRRzt zfs_set_propRRRRRRR(R9t success_listR((s"../../common/bootmgmt/versaboot.pyR"7s   cCs |d|S(s R%((Rtrpdstbpname((s"../../common/bootmgmt/versaboot.pytrpool_ds_to_bpool_dsNscCs(|jd|}tj|r$|SdS(s R%N(RRztdataset_existsR((R9R)tbpoolds((s"../../common/bootmgmt/versaboot.pytboot_pool_cached_datasetTscCs2x+|jjD]}|jr |jjdd}|r*|jd|}|jd|j}tj|jd|r'ytj |d|jWn2t k r}|j d||j|fnXy*tj |||j d||fWq$t k r }|j d|||fq$Xq'q*q q WdS(slRename boot pool datasets according to any changes made to the corresponding root datasets. R,R%scom.oracle:rootfss>Couldn't update boot pool dataset rootfs property %s -> %s: %ss'Renamed boot pool dataset from %s -> %ss3Couldn't rename boot pool dataset from %s -> %s: %sN( Rtboot_instancestoriginal_valuesRiR(RR,RzRRRRFtrename_dataset(R9tinstt orig_bootfsRt new_bpdsnameR((s"../../common/bootmgmt/versaboot.pyt_commit_renamesas0      cCs{g}|j|j|x[|D]S}y!tj||jd|Wq tk rr}|jd||fq Xq WdS(s|Find boot pool datasets that must be deleted based on the presence of the corresponding root pool datasets. s(Destroyed now-stale boot pool dataset %ss)Failure deleting boot pool dataset %s: %sN(Rt_walk_rootds_deletedRzRRFR(R9RRR((s"../../common/bootmgmt/versaboot.pyt_commit_deletionss     cCs|jr|jjSdS(s N(RRR((R9((s"../../common/bootmgmt/versaboot.pyRs  cCs/|jr|jj||n tddS(s~ Raises: BootmgmtInvalidParameterError(key) BootmgmtInvalidParameterValueError(value) sNo BootPoolConfig existsN(RRR (R9R_Rg((s"../../common/bootmgmt/versaboot.pyRs cCs)|jr|jj|StddS(sH Raises: BootmgmtInvalidParameterError(key) sNo BootPoolConfig existsN(RRR(R9R_((s"../../common/bootmgmt/versaboot.pyRs cCs^|jr|jddS|jr6|jj|n|sZt|jt|jkry|jWqtk r}|jd|qXny|j r|j nWn%t k r}t dd|nXy\|j |j|j|jjr|dkrtj}n|j||||Wn%t k rY}t dd|nXdS(s s)Instance data is read only: CANNOT COMMITNs$Error updating boot pool linkage: %ssGeneral boot pool failuretxcpt(R7RFRRrRRRR"R RcReRRRRR$RRR(RRR/(R9RR(R)tplatdicttbmerrR((s"../../common/bootmgmt/versaboot.pyRrs6   $         cCsV|jj}g|jjD]9}t|tr|jrt|j|kr|^qS(s (RRRRR#tdefaultR+R,(R9RR((s"../../common/bootmgmt/versaboot.pyRs   cCse|j}|jr*|jjr*t}nx4|D],}|jd|j|j|j|q1W|S(s s-Synching default boot instance with bootfs=%s(RRRRJRFR,R(R9RRR((s"../../common/bootmgmt/versaboot.pyR$s     c Csk|jj}|sdS|s%i}n|j|d<|j'}||d<|j||||WdQXdS(s Nt bi_accessort topdatadir(RRAt_boot_inst_accessorRtinstall(R9R(RR)Rtbloadertbptopdir((s"../../common/bootmgmt/versaboot.pyR/s    cCs=d}i}||d<||d|j|j}|s:|jd|jn|St|||S(sA function used by the boot loader to get the appropriate fields from a BootInstance instance, when writing the configuration to the boot pool. R,s+%s not present in boot pool; bootfs -> None(RR,RFtgetattr(R9RtfieldtdefvalueR,((s"../../common/bootmgmt/versaboot.pyR 3s   c cs|jv}tjj|tj}|j||t|tjtj tj ftj |_ z |j VWd|j j XWdQXdS(s{ Returns a context manager that holds open the recovery data file and allows it to be manipulated. N(RRBRCRDRR9RR,tRECOVERY_FILENAMEtRECOVERY_FILE_OWNERtRECOVERY_FILE_GRPtRECOVERY_FILE_PERMSRR@(R9R7Rtdestdir((s"../../common/bootmgmt/versaboot.pyt recovery_data@s cCstdkrdS|jS(sSynchronize the platform boot device list such that all members of the boot pool are placed in the boot order. We try to honor user modification of the boot order, we do not insert new members at the front of the boot order. Instead, we look for the first occurrence of an existing boot pool member, and append members not in the boot order after that member. If there are no members in the boot order, all boot pool members are added at the front of the boot order list. RN(Rt_synch_sparc_boot_order(R9((s"../../common/bootmgmt/versaboot.pyR#Xs csd}t\}|dkr%tSt|}|jd||jd|jg}xZ|jD]O}yt|}|j|Wqdtk r}|jd||fqdXqdW|s|jdtSyyt d}|r@t d|j d}xE|D]4} y|j | } || =Wqt k r8qXqWng}Wntk r`g}nXd } g} xo||D]c} | |kr| j| qxnx;t|D]-\} }| |kr| | kr| } qqWqxW| r| d kr| d } n| || | +n|jd | | f||kr5tSttd |t|d }||kr|jrt|j}ng}g}|jd |xB|D]7}yt|}|j|Wqtk rqXqWnx||kruy|j}|j |} Wnt tfk r0d } nX|jd|| || =ttd|t|d }qWtfd|}|jd|t|ttB}|d krtS|jd||ftS(s isOriginal plat_bootlist = %ssdevice list = %ss!Error getting prompath for %s: %ss:No boot devices could be derived: not setting boot-device s tboot-listcSs |dkS(NR((R((s"../../common/bootmgmt/versaboot.pyRsRiis!paths_to_add = %s, last_path = %dcSs t|S(N(R'(R((s"../../common/bootmgmt/versaboot.pyRssHealthlist = %ss+New boot-device too long. Pruning entry %scSs t|S(N(R'(R((s"../../common/bootmgmt/versaboot.pyRscsj||S(N(Ri(R(t aliasdict(s"../../common/bootmgmt/versaboot.pyRssNew plat_bootlist = %ss devfs_bootdev_set_list(%s) => %dN(RR(R5RRFRRRRERtfilterR&RIRVRRERJtsumtmapR'Rtpopt IndexErrorRRR(R9tBOOT_DEVICE_MAXLENGTHt plat_bootlisttorig_plat_bootlistt bpool_devlistRjt bp_promdevsRMt tbootlistRCtidxt last_patht paths_to_addtjt plat_pathtlengthRt prunelisttpromdevsttrypathR8((Rs"../../common/bootmgmt/versaboot.pyRfs                    &          *    (splatform/i86pc/kernel/amd64R(splatform/i86pc/amd64R(splatform/%(platformname)sRN(]RsRtRuR9tpwdtgetpwnamtpw_uidR:tgrptgetgrnamtgr_gidR;R<R=R>R?R@RRRRRt BOOTFILES_X86tBOOTFILES_SPARCRRtRsR5R(R>RRR t classmethodRRRRRRRRRJRRRRRORPR+RFRYR[R]R^RZRcReR`RdR~RRRRRRRRR%RRRRRR"RRRRRRRRrRR$R/RRR RR#R(((s"../../common/bootmgmt/versaboot.pyRs  `    < .   +          2   * 'A H  S   9  )   %   1    t VersaBootcBseZdZdZd edZdZdZe dZ e dZ e edZdZd Zd Ze d d d d ZRS( s" The main VersaBoot abstraction. Includes: - One or more VersaBootRoot instances, each of which describes a single (long) property string that fully describes how to prepare the boot device and filesystem before mountroot() in early boot. - One or more RootPool instances, each of which describes a Solaris root pool (usually there's only a single root pool) - One BootPool instance that describes the VersaBoot boot pool, the storage pool that is used to cache boot archives from the root pool(s) sos-root-devicecCs]|jtjjjks'|jdkr6tdn||_g|_d |_ g|_ |ri|}nLt j |j}|rt |d|d|dt}ntd|j||_t|_t|_y|jWnxtk r}|jd|nVtk rX}|jtjtjtjgkrRt|_|jd|jqYnXd S( s RzsHVersaBoot is supported on disk-based boot configurations using ZFS only.RRRs+VersaBoot is not supported for root pool %ss'Ignoring failure to load properties: %ssError loading properties: %sN(R{R|R}R~RRRRtvbrootsR(t_recovery_vbrootst_vbroots_committedRRRRJt boot_poolR5trecovery_neededR7t_load_propertiesRRFRSRGRItEACCEStEROFSRT(R9Rtbootpooltautocreate_bootpoolR>t bpoolnameRR^((s"../../common/bootmgmt/versaboot.pyR>s8         ! cCs=|jr9|jjr9|j r9|jj|jndS(s N(R>RR7Rtwrite_recovery(R9((s"../../common/bootmgmt/versaboot.pyRs c CsWtj}y|jjjj|}Wn!tk rHtd|nXd}|j r|j j r|j j t L}y+|j|}|rt j|}nWntk rd}nXWdQXn|rt j||_|jd|jt|j|_n|rS|j|j|sG|jd|||ft |_n||_ndS(s Creates and adds one or more VersaBootRoot instances based on the value of the source property (VersaBoot.ROOT_DEVICE_PROPNAME) s'No platform support for the %s variableNsvbroots after load are: %ss_[WARN] Mismatch between platform %s property and its value in the recovery data ["%s" vs. "%s"](R:tROOT_DEVICE_PROPNAMERRARBRoRR R(R>RRRJtVersaBootRootFactorytget_from_propstrR R;RFRR=t_compare_vbrootsR?R<(R9Rtrootdevicesproptrecovery_vbrootstrecoverytrecovery_rootdevprop((s"../../common/bootmgmt/versaboot.pyR@ s8       cCs|jrt|jSgSdS(N(R<R(R9((s"../../common/bootmgmt/versaboot.pyRLKs  cCsVt|t|krtSx3t||D]"\}}|j|jkr,tSq,WtS(s (R'R5RtvbpropsRJ(tlistatlistbtvbrootatvbrootb((s"../../common/bootmgmt/versaboot.pyRJSs c Cs d}g}g}|sr|j|jkrrtg|jD]}|jr7|^q7dkro|jddSqrnx|jD]}|j|dtj|jf}x|j D]} x| j D]|\} } |j j | } | j tk r| r|tj7}|d| | f7}q| j r| r|j| | fqqWqW|tj7}||7}q|W|dkr|jddS|ttj }|jd||s|s|j|jkr |j|||x|D]}|jqWt|j|_n|S(s Ris8No changes to VersaBootRoot list; not writing propertiesNs%s=%sspropstr is emptysdirtylist => %s(R=R;R'tdirtyRFRt VersaBootRoottROOT_TECH_PROPNAMERXtget_metaprop_dictsRURORit sensitiveRJtPROP_DELIMITERtROOTSPEC_DELIMITERR(t _store_propstcleanR( R9Rtwrite_fwtpropstrtsensitive_prop_listt dirtylistRtvbroottoneproptpropdictRjtproptypetlocalval((s"../../common/bootmgmt/versaboot.pyt_write_propertiesasB 1         c Cs tj}|rA|jd||f|jjjj||n|jdkra|jddS|jj t }|jdtj|f|jtj||r|jd||j |ny|j Wn&t k r}|jd|jnXWdQXdS(s sSetting %s property to `%s's!No boot pool -- not storing propsNs&[RECOVERY] Setting %s property to `%s's,[RECOVERY] Setting sensitive properties (%s)s+[WARNING] Failed to write recovery data: %s(R:RGRFRRARBRlR>R(RR5RnRrRERT(R9R^tsensitive_propsR]trdpropRMRM((s"../../common/bootmgmt/versaboot.pyR[s(     cCs#|jrt|j|_tStS(s (R<RR;RJR5(R9((s"../../common/bootmgmt/versaboot.pytrecover_vbrootss cCsFy|jdtdtWn%tk rA}tdd|nXdS(s RR]sGeneral boot pool failureRN(RfRJR5RR(R9R((s"../../common/bootmgmt/versaboot.pyRFs  cCsx|jD]}|jq W|jsy6|jrO|jj||||n|j|SWqtk r}tdd|qXn tddS(s sGeneral boot pool failureRs<This VersaBoot instance is read-only and cannot be committedN( R;tvalidateR7R>RrRfRRR(R9RR(R)RRaR((s"../../common/bootmgmt/versaboot.pyRrs    N(RsRtRuRGR(RJR>RR@RRLt staticmethodRJR5RfR[RiRFRr(((s"../../common/bootmgmt/versaboot.pyR:s /  +> #  RUcBseZdZdZdZdZddZedZ dZ dZ dZ d Z d Zd Zd Zd ZedZRS(s s osroot-typet;s;;cCsddl}g|j|jD]%}t|d|jtr|^q|_i|_t|_|r|j d|x$|D]\}}|j ||q|W|j dt|_ndS(s iNs _%s__vbpropssInitting from KV pair list: %ssClearing _dirty( tinspecttgetmrot __class__RRsR5t _mixin_basesROR6RFRl(R9tkvplistRmRR_R`((s"../../common/bootmgmt/versaboot.pyR>s (   cCs|jS(s (R6(R9((s"../../common/bootmgmt/versaboot.pyRT scCs|jdt|_dS(s sClearing _dirtyN(RFR5R6(R9((s"../../common/bootmgmt/versaboot.pyR\ s cCs |jS(s (t_get_all_metapropdicts(R9((s"../../common/bootmgmt/versaboot.pyRW scCs(g|jD]}|jd|j^q S(s s _%s__vbprops(Rpt__dict__Rs(R9tmixin((s"../../common/bootmgmt/versaboot.pyRr scCs t|jS(s (RRO(R9((s"../../common/bootmgmt/versaboot.pytgetprops" scCs.||jkr|j|Std|dS(s sUnknown property `%s'N(ROR(R9RX((s"../../common/bootmgmt/versaboot.pyRo( s cCs/x(|jD]}||kr ||Sq WdS(s N(RrR((R9RXtmixin_metapropdict((s"../../common/bootmgmt/versaboot.pyt_prop_type_lookup0 s  cCs|j|}|dk }|r4|j||n|jj||kr~||j|<|js~|jdt|_q~ndS(s sSetting _dirtyN(RwR(RjRORiR6RFRJ(R9RXRgt prop_type_objRj((s"../../common/bootmgmt/versaboot.pyRl9 s    cCsrxk|jD]]}xT|jD]F\}}|jj|}|jr |dkr td|q q Wq WdS(s s"Missing a required property (`%s')N(RrRURORitrequiredR(R(R9RcRjRdRe((s"../../common/bootmgmt/versaboot.pyRjH s cCs;djg|jD]$}t|ddr|j^qS(s R%tcomponent_nameN(RDt __bases__RR(Rz(RR((s"../../common/bootmgmt/versaboot.pyRXT sN(RsRtRuRVRYRZR(R>RRTR\RWRrRuRoRwRlRjR9RX(((s"../../common/bootmgmt/versaboot.pyRUs        tVersaBootMixincBseZdZdZRS(s cCsdS(s N((R9((s"../../common/bootmgmt/versaboot.pyR>c s(RsRtRuR>(((s"../../common/bootmgmt/versaboot.pyR|_ stVersaBootPropertyTypecBsGeZdZdeedZdZedZedZ RS(s cCs||_||_||_dS(s N(t_maxlent _requiredt _sensitive(R9ttypelenRyRX((s"../../common/bootmgmt/versaboot.pyR>m s  cCsdS(s N((R9RXRg((s"../../common/bootmgmt/versaboot.pyRju scCs|jS(s (R(R9((s"../../common/bootmgmt/versaboot.pyRy{ scCs|jS(s (R(R9((s"../../common/bootmgmt/versaboot.pyRX sN( RsRtRuR(R5R>RjRRyRX(((s"../../common/bootmgmt/versaboot.pyR}i s  tStringVersaBootPropTypecBseZdZRS(cCsX|dkr!t||dn|jrTt||jkrTt||dndS(Nscannot be Nonestoo long(R(RR~R'(R9RXRg((s"../../common/bootmgmt/versaboot.pyRj s    (RsRtRj(((s"../../common/bootmgmt/versaboot.pyR stIBSpecVersaBootPropTypecBs>eZedZedZedZdZRS(cCs;t||kr't||dntj||dS(s stoo longN(R'RRt_ibspec_path_to_tuplelist(RXRgt maxlength((s"../../common/bootmgmt/versaboot.pyt_ibspec_validator sc Cs|jd}g}xr|D]j}|jd}t|dkrXt||dnt|dkr|j|dd fqni}x|djdD]}|j}|dkrt||d ||dfn|jd }|dj|d<|ddkr8t||d ||dfnt|dkrW|d} nd } | ||d       cCst|dkrdSd}x|D]}|d|d7}|ddk r#g}xW|djD]E\}}|dkr|t|g7}qb|d||fg7}qbW|dtd|7}q#q#W|S( s iRR%is%s=%sRdcSsd||fS(Ns%s,%s((RR((s"../../common/bootmgmt/versaboot.pyR sN(R'R(RURtreduce(t tuplelistRWttuplt kvstringsR_R`((s"../../common/bootmgmt/versaboot.pyt_ibpath_tuplelist_to_devpath s   cCs|j|||jdS(N(RR~(R9RXRg((s"../../common/bootmgmt/versaboot.pyRj s(RsRtRkRRRRj(((s"../../common/bootmgmt/versaboot.pyR s 0tIP4AddrVersaBootPropTypecBseZdZRS(cCsPddl}y|j|j|Wn&|jk rKt||dnXdS(s iNsInvalid IPv4 address(tsockett inet_ptontAF_INETterrorR(R9RXRgR((s"../../common/bootmgmt/versaboot.pyRj s  (RsRtRj(((s"../../common/bootmgmt/versaboot.pyR stZFS_VersaBootMixincBs0eZdZiedd6ZedZRS(s is zfs-rootfscCsdS(s tZFS((((s"../../common/bootmgmt/versaboot.pyRz s(RsRtRuRt_ZFS_VersaBootMixin__vbpropsRkRz(((s"../../common/bootmgmt/versaboot.pyR stiSCSI_VersaBootMixincBseZdZi eded6edded6edd6edd6edd6ed d 6ed d 6edd ed 6edd ed6ZedZRS(s Rysosroot-iscsi-target-ipisosroot-iscsi-target-namesosroot-iscsi-initiator-idisosroot-iscsi-portsosroot-iscsi-tpgti sosroot-iscsi-lunsosroot-iscsi-partitionRXsosroot-chap-usersosroot-chap-passwordcCsdS(s tiSCSI((((s"../../common/bootmgmt/versaboot.pyRz s( RsRtRuRRJRt_iSCSI_VersaBootMixin__vbpropsRkRz(((s"../../common/bootmgmt/versaboot.pyR s            tIPv4_VersaBootMixincBsQeZdZieded6ed6ed6ed6ZedZRS(s Rysosroot-host-ipsosroot-router-ipsosroot-subnet-masksosroot-hostnamecCsdS(s tIPv4((((s"../../common/bootmgmt/versaboot.pyRz0 s(RsRtRuRRJt_IPv4_VersaBootMixin__vbpropsRkRz(((s"../../common/bootmgmt/versaboot.pyR& s     tIPoIB_VersaBootMixincBs3eZdZieded6ZedZRS(s is osroot-pathcCsdS(s tIPoIB((((s"../../common/bootmgmt/versaboot.pyRz> s(RsRtRuRRJt_IPoIB_VersaBootMixin__vbpropsRkRz(((s"../../common/bootmgmt/versaboot.pyR6 stLocalDisk_VersaBootMixincBs3eZdZieded6ZedZRS(s is osroot-pathcCsdS(s t LocalDisk((((s"../../common/bootmgmt/versaboot.pyRzK s(RsRtRuRRJt"_LocalDisk_VersaBootMixin__vbpropsRkRz(((s"../../common/bootmgmt/versaboot.pyRE stZFS_iSCSI_IPv4oIB_VersaBootRootcBseZdZRS(s (RsRtRu(((s"../../common/bootmgmt/versaboot.pyRR stZFS_LocalDisk_VersaBootRootcBseZdZRS(s (RsRtRu(((s"../../common/bootmgmt/versaboot.pyR[ sRHcBsGeZdZeegZedZedZedZ RS(s cCs&g|jD]}|j|f^q S(s (t(_VersaBootRootFactory__root_technologiesRX(RR((s"../../common/bootmgmt/versaboot.pytget_root_technologiesj scCs@g|jD]}|j|kr |^q }|r<|dSdS(s iN(RRXR((RRXRtvbrs((s"../../common/bootmgmt/versaboot.pytget_root_technology_by_nameq s.c Cs!|jd||sgSg}|jtj}x|D]}|jtj}d}g}x|D]}|jddkrd|jdd\} } nqd| tjkr| rtj | }|jd|qd| tjkrd|j | | fqdqdW|r9|j ||q9q9W|S(s Attempts to generate a list of VersaBootRoot instances based on the property passed in. The property is of the form: ((k=v;)+;;)*(k=v;)+ s>Trying to parse potential VersaBoot root descriptor: [[ %s ]]Rciis vbr -> %sN( RFR&RURZRYR(ReRVRHRR( RRRtpropstrootpropt rootprop_listtvbrt rootprop_kvpst rootprop_elemR_R`((s"../../common/bootmgmt/versaboot.pyRI{ s,   ( RsRtRuRRRR9RRRI(((s"../../common/bootmgmt/versaboot.pyRHd s   (RRuR|RRRRRRRRRR R R R R RRRRtbootmgmt.bootutilRRtbootmgmt.bootinfoRtbootmgmt.pysolRRRRRRRRRt contextlibRt ConfigParserRR R!R"R0t bootmgmt.zfsRztbootmgmt.zfs.libzfs.cfunctlibzfsRtbootmgmt.zfs.libzfs.constRtbootmgmt.bootconfigR#R$R1R4RGRBRRuRRQRqR+R,RvRR:RUtobjectR|R}RRRRRRRRRRRH(((s"../../common/bootmgmt/versaboot.pytsf v@"            u   Z