sWc@s%dZddkiZddkiZddkZddkZddk Z ddk Z ddk i Z ddkZddkZddkZddklZlZlZlZlZlZlZlZlZddklZddklZddkl Z ddk!l"Z"ddkl#Z#l$Z$l%Z%l&Z&l'Z'l(Z(l)Z)dd k*l+Z+l,Z,dd k-l.Z.l/Z/l0Z0ddk1Z1ei2d Z3ei2d Z4ei2d Z5dZ6dZ7dZ8dZ9dZ:dZ;ye i<ddde=i Z>Wnei?i Z>nXdZ@ddZBdZCdZDdZEdZFdZGdddZHddZIdd ZJddd!ZKddd"ZLddd#ZMdeNd$ZOddeNd%ZPe=d&ZQdddd'ZRdddd(ZSd)ZTd*ZUd+ZVd,ZWdd-ZXd.ZYd/ZZd0Z[dddd1Z\dddd2Z]ddddd3Z^ddd4Z_d5Z`d6ZadeNd7Zbd8Zcd9Zdd:Zed;Zfd<Zgd=ZheNd>Zid?Zjd@ZkdAZldBZmdCZneodDjo enndS(Es Helper module to support menu and bootloader bootadm operations. This helper acts as a bridge between bootadm C code and pybootmgmt/libbe. iN( t BootmgmtUnsupportedPropertyErrort"BootmgmtInsufficientDiskSpaceErrortBootmgmtConfigWriteErrortBootmgmtBootPoolFailureErrortBootmgmtZFSErrortBootmgmtInvalidParameterErrort"BootmgmtInvalidParameterValueErrortBootmgmtAddCredentialErrort BootmgmtError(tDiskBootConfig(twrite_temp_file(tGRUB2BootLoader(tLegacyGRUBBootLoader(tget_boot_configt get_active_betset_bootloader_versiont spawn_commandtget_default_benamet beActivatetbe_make_root_ds(tzpool_get_bootfstzfs_get_user_prop(t mnttab_opent getmntentt mnttab_closes^[\.A-Za-z0-9_-]+$s^[\x20-\x7E]+$s ^(.*?)=(.*?)$isSolaris bootenv rctSolaris_reboot_transients%/boot/.bootadm_transient_save_defaultsRFormat is property=: use "" to include whitespace (e.g. property="val val2").tSUNW_OST_OSCMDs/usr/lib/localetfallbackcCs|igdS(s Write the menu to disk. N(tcommit_boot_config(tboot_cfg((sbootadm-helper.pyt_bootadm_commit_menu\scCs|o3|o,d|jo||jot|dfSny|idd\}}Wn5tj o)td|tttddfSXt||fS(sGiven a string, return the prop/value pair separated. If there is no value portion, return successfully, but return None for the valuet=isError attempting to parse: %sN(t BAM_SUCCESStNonetsplitt ValueErrortbootadm_perrortBAM_PROPERTY_FORMATt BAM_ERROR(tentrytprops_allowed_to_have_no_valuetproptval((sbootadm-helper.pyt_bootadm_parse_propval`s  cCspd|}t|d}d}xI|iiD]5}|ii\}}||jo |}q3q3W|S(s Get the mountpoint the root pool is mounted at. This function is always called from situations where the 'rpool' is guaranteed to be mounted (e.g. by get_boot_config). s+/usr/sbin/zfs list -H -o name,mountpoint %siN(RR!trstript splitlinesR"(trpooltcmdt cmd_stdoutt pool_pathtlinetnametmntpt((sbootadm-helper.pyt_bootadm_get_rpool_mntptqs  cCs6x/t|D]!\}}|io ||fSq WdS(sY Returns what entry is currently set as default and the associated instance. iN(Ni(t enumeratetdefaultR!(t boot_listtidxtinst((sbootadm-helper.pyt_bootadm_find_defaults   c Cst|d}t|}yKt||dii}z$|~}|it|tSWdQXWn$tj ot t dt SXdS(sH Take the index of the current default entry and dump it to a file. itwNsCouldn't save the default entry to the temporary file. bootadm -m update_temp will not be able to restore the correct default entry( R;R5topent__exit__t __enter__twritetstrR tIOErrorR$t_R&(tzpoolR8t dest_filetindext rpool_mntptt_[1]ttarget((sbootadm-helper.pyt_bootadm_save_default_to_files * c Cst|}||}yt|dii}zx|~}|i}y!t|}ti||SWn;tj ot t d|dSt j o|SXWdQXWn(t j ot t d|dSXdS(sA Open in_file and grab the to-be-set-to-default entry index. trssMalformed entry found while trying to restore the default entry from %s. Default entry is now the first in the menuiNs_Couldn't find/read %s to restore the default entry. Default entry is now the first in the menu.( R5R=R>R?treadtinttostremoveR#R$RCtOSErrorRB(RDtin_fileRGtpathRHRIRFR9((sbootadm-helper.pyt_bootadm_get_default_from_files*  &   cCsxd|iGHt|tipdSd|iGHd|iGHd|iGHt|ddod|i GHn d|GHdS( sY Given an instance output its key entries (kernel, boot_archive, bootfs, title). s title: %sNs kernel: %sskernel arguments: %ssboot archive: %stbootfss bootfs: %ssZFS root pool: %s( ttitlet isinstancetbctSolarisDiskBootInstancetkerneltkargst boot_archivetgetattrR!RT(t boot_instanceRD((sbootadm-helper.pyt_bootadm_pretty_prints    tcCst}t|ii}zY|~}|itiijo|Sd}d}|djoti t i i ot i }|djottdqti|pttdqt i d} || jo d}qttdq,ttdn|d jotii|o^t|d } | i} | id } | }ti|pttdqd}q,ttd |n|d jod}ttdn[|djot|ii} zr| ~ }|iio dGHndGHxGt|iD]6\} }d| |iditt|ifGHq-WWdQXn|djoHt|ii}z(|~}|iio dGHndGHWdQXng|djoqt|ii}zQ|~}xAt|iD]0\} }d| ditt|ifGHqWWdQXn|djo|i d}x|D]}yt!|}|i|}Wn_t"j o$ttd|t#}qgn1t$j o$ttd|t#}qgnXd|ditt|ifGHqgWnttd||oBt%|d||t&|t'}t'}t(|||d}nWdQX|S( s Set entire menu password. R_t set_prompts#Please specify a non-empty passwordsAPassword must only contain printable characters (ASCII 0x20-0x7E)sRe-enter password: s menu-passwordsPassword does not matchs2Please use option -f to supply the passwordtsetRKs sfile %s does not existtdelsMenu password is removedtlistsThe entire menulock is onsThe entire menulock is offs%d %s users: %ss, Ntlist_parse_globalsentire_menulock:onsentire_menulock:offt list_parses%d:%stlist_parse_entryt,s(Invalid index passed for an instance: %ss&No menu entry can be found at index %dsError: Unknown command %st/()R R R>R?t boot_classRWt BootConfigtBOOT_CLASS_DISKRNtisattytsyststdouttfilenotgetpassR$RCtPASSWD_CRITERIAtmatchRRtexistsR=treadlineR,t credentialtpasswordR6tboot_instancesRUtjointmapRAt cred_listR"RMR#R&t IndexErrort_bootadm_set_username_passwordRtFalsetbootadm_install_bootloader(tset_cmdt pw_file_pathtindexstrRDtretvalRHtmybctset_propRvtpassword_reenteredtfpR2t_[2]tiR:t_[3]t_[4]t indexlistRFt boot_insttforcetverbose((sbootadm-helper.pytbootadm_set_menu_passwords#          #    , #   # 2   & cCst}tid}tid}tid}tid}|djottdtStii |pttd|tSt |i i }z|~}|i tiijo|St|d} x| D]} | id} g} d } | id } g} | D]}|d jo | |qq~ } | pqn| d d d joqn|i| ottd qn|i| oZ|i| }t|id} | pttdqnd| d<| | d.*?)$sset-menu-password +-s *$s9set-menu +add-user\=(?P.*?) +password\=(?P.*?)$s%set-menu +add-user\=(?P.*?) *$s!Please provide an input file pathsFile %s does not exist RKs R_t it#sBError - format in batch file: set-menu-password -s password= tpws#Error - Failed to set menu passwords-fiisFError - format in batch file: set-menu add-user= password= tuserRs#Error - Failed to set user passwords auth-file=s-PtbootadmRntstderrsError while invoking %s: %sN("R tretcompileR!R$RCR&RNRRRsR R>R?RiRWRjRkR=R,R"RrR tgrouptpoptinsertt subprocesstPopentPIPEt communicateRmRnRARPRO(tbatch_file_pathRDRtSET_MENU_PASSWD_CMDtSET_MENU_PASSWD_CMD_NO_PWtSET_MENU_ADD_USER_CMDtSET_MENU_ADD_USER_CMD_NO_PWRHRRR2tcommandttemp_file_nameRtitemtmotproctoutterrtoserr((sbootadm-helper.pytbootadm_use_batch+s     #2     c CsYt|ii}z9|~}|i}|djp|idjottd|tS|ii }|ii }|ii }|ii }g}xW|ii D]I} y-d| |ii| f} |i| Wqtj oqXqWtd|iidi|di|di|di|di|fGHWdQXtS(s s8Boot pool operations are not applicable to root pool %s.s%s=%ssBoot pool name: %s Parameters: %s Current: %s Pending: %s Platform-specified devices excluded: %s Platform-specified (auto-added, unless excluded): %st:s, N(R R>R?t versabootR!t boot_poolR$RCR&tcurrent_membershiptpending_membershiptexcluded_devicestplatform_devicestsettable_parameterst get_paramtappendRt pool_nameRxR ( R.RHRtmyvbtcur_listt pend_listt excl_listt plat_listt param_listtparamt param_str((sbootadm-helper.pytbootadm_bootpool_lists.#     $c Cst|ii}zh|~}|i}|djp|idjottd|tSx|D]}|i ddjottd|n|i d\}}|i }|i }y|ii ||Wqit j o!}ttd|itStj o!} ttd| itSXqiWy|iWn,ttfj o} tt| tSXWdQXtS(s s8Boot pool operations are not applicable to root pool %s.RisInvalid parameter syntax: %ssInvalid parameter: %ssIllegal value: %sN(R R>R?RR!RR$RCR&tcountR"tlowert set_paramRtmsgRtcommitRRRAR ( R.RRHRRtkeyvaluetkeytvaluet param_errt param_val_errte((sbootadm-helper.pytbootadm_bootpool_set_paramss8#      c Cst|ii}zp|~}|i}|d jp|id jottd|tSt |ii }|i |ii g}x|D]}t |djo|ddjod|}ntii| o0tii|d ottd|q||jottd|q||jo|i|qqWd}xg|D]_}y|ii||d7}Wqjtj o,} ttd ||ii| fqjXqjW|djotSyx|it |ii } | i |ii | |} t | }td ||djod nd fGHWn,ttfj o} tt| tSXWd QXtS(s s8Boot pool operations are not applicable to root pool %s.iRhs /dev/dsk/ts0s$Not adding %s: device does not exists)Not adding %s: device is already a memberis$Could not add %s to boot pool %s: %ssAdded %d device%s successfullytsR_N(R R>R?RR!RR$RCR&RaRtunionRtlenRNRRRsRt add_deviceRRRRRRAR ( R.tdeviceRHRRt cur_memberstadd_listtdevRtbmzet new_memberst diff_membersR((sbootadm-helper.pytbootadm_bootpool_add_devicessX#  $,     #     ! c Csgt|ii}zG|~}|i}|d jp|id jottd|tS|ii }t |ii }|i |d}x|D]}|ii } t |djo,|ddjo||jod|}n||jo$ttd||iifqt | djottd|q||ii|jod|GH|ii|n|ii||d7}qW|djotSyx|it |ii } | i |ii || } t | }td ||djod nd fGHWn,ttfj o} tt| tSXWd QXtS( s s8Boot pool operations are not applicable to root pool %s.iRhs /dev/dsk/sCCouldn't remove %s from %s: device is not a member of the boot poolis5Not allowing removal of the last boot pool device: %ss EXCLUDE: %ss!Removed %s device%s successfully.RR_N(R R>R?RR!RR$RCR&RRaRRRRRtexclude_devicet remove_deviceRRRRAR ( R.tdevicesRHRRRRRRt new_pend_listRRR((sbootadm-helper.pytbootadm_bootpool_remove_devicessT#   1         ! c Cs|t|d|ii}zV|~}|i}|djp|idjottd|tSd}g}|i D]}|i o ||q|q|~}|ot |ddd}n|djot |}n|pttd|tS|i} y<| i o| in| i|d|| iWn,ttfj o} tt| tSXWdQXdS(s Rs8Boot pool operations are not applicable to root pool %s.iRTs/Could not determine default bootfs for pool "s"N(R R>R?RR!RR$RCR&RwR7R\Rtsynch_membership_neededtsynch_membershiptsynch_rpool_datasetRRRRA( R.RRHRRtdsnameRtxtdefaultstbpoolR((sbootadm-helper.pyt"bootadm_bootpool_resynch_active_be<s4)  2     c Cst|d|ii}z|~}|i}|djp|idjottd|tS|i}|i o|i nt }t }|ox|D]v} t i| } t| | } y|i| d|t}Wqttfj o } tt| t}PqXqWnMy |idtd|t}Wn)tj ott| t}nX|oQy|iWqtj o0} |tjott| t}qqXn|SWdQXdS(s Rs8Boot pool operations are not applicable to root pool %s.t clear_firstN(R R>R?RR!RR$RCR&RRR}R tlibbe_pytgetzpoolbybenameRRtTrueRRRAt full_resynchR( R.tbe_listRRHRRRt need_committrettbetbe_rpoolRR((sbootadm-helper.pytbootadm_bootpool_resynch_bes^sL)        c Cs|id}|d}|d}t|ii}z|~}|i}|djp|idjo$|ottd|nt S|ii }y2td|||fGH|ii |d|Wn,t t fj o} tt| tSXWdQXt S(s Rhiis8Boot pool operations are not applicable to root pool %s.s$updating files on boot pool %s:%s/%sRN(R"R R>R?RR!RR$RCR RRRRRAR&( tdatasetRtdssplitR.tbe_nameRHRRtbpnameR((sbootadm-helper.pytbootadm_update_bootpool_datasets(  #      c Cst}g}g}|o|id}n|o|id}nt|ii}zD|~}|io3t|ido |iiodG|iiGHn|djo|djot|i \}} |dj o d| GHnxf|ii D]X} y<|ii | } | dj od| t | fGHnWqtj oqXqWxEt|i D]\} }d| |ifGHqhWnt|||}WdQX|S( s# Print the current menu on screen. Rgt config_dirs7the location of the boot loader configuration files is:R_s default %ds%s %ss%d %sN(R R"R R>R?t boot_loaderthasattrRR;RwR!tSUPPORTED_PROPStgetpropRARR6RUt_show_entry_util( RDtinststrRRtinstlistRRHRR:RFtpropnametpropvalR((sbootadm-helper.pytbootadm_list_menus:#       c CsD|djo g}n|djo g}nt}t|ii}z|~}x|D]}yt|}|i|}Wn_tj o$tt d|t }q^n1t j o$tt d|t }q^nXt ||q^WxC|D];}x2|iD]'}||i jot ||q q WqWWdQX|S(s( Print the specified entries on screen. s(Invalid index passed for an instance: %ss&No menu entry can be found at index %dN(R!R R R>R?RMRwR#R$RCR&R{R^RU( RDRRRRHRR:RFR((sbootadm-helper.pyRs:    #  cCsVy|ii|Wn(tj ottd|tSX|ii||tS(s Set a boot loader property. s%s is not a valid property(RRRR$RCR&tsetpropR (RR)R*((sbootadm-helper.pyt_bootadm_set_propertyscCsvy t|}t|i|_WnOtj ottd|tStj ottd|tSXt S(s; Set the entry at index 'val' as the default entry to boot s:The passed value (%s) is not an integer. Integer expected.sNo entry at index: %d( RMRRwR7R#R$RCR&R{R (RR*RF((sbootadm-helper.pyt_bootadm_handle_set_defaults  cCs&yt|}|i|itjp.|i|itjp|i|idjot|i|_t |n^t |i|i}|o,t |}|ot t dtSnt t dtSWnOtj ot t d|tStj ot t d|tSXtS(s) Handles bootadm set-menu default=. sActivate failed.s The BE name provided is invalid.s:The passed value (%s) is not an integer. Integer expected.sNo entry at index: %dN(RMRwRUtBAM_BOOTENVRC_ENTRYtBAM_TRANSIENT_ENTRYRTR!RR7RRRR$RCR&R#R{R (RR*RFtbenameR((sbootadm-helper.pyt_bootadm_activate_defaults.    c sqt}|didd}g}|iD]!}|itjo ||q.q.~}|o|djo|djo|diGHn_|djo3|dipdn |di}ti |IJnt t dt |t StS|djo%t t d tt |ft S|p+tidd d d |d t} t} n_|d} t} t|djo;|d } x.| D]"|ifddtqWn|djowt|djot t dt S|ddjo1t|| i\} | _| _| ot SqL|| _n|djo || _nt| _| o|i| ntS(Ntroot_dsRhiRYitargsR_sUnknown attribute: %ss2Could not find a "%s" boot entry to retrieve "%s".tfstypetzfsR.RUics |jS(((R(tdelinst(sbootadm-helper.pytdstallsInvalid (empty) kernel name(RR"RwRURR!RYRZRmRR$RCRAR&R RWRXRR}Rtdelete_boot_instancet_handle_kernelR7tadd_boot_instance( RR)R*t active_betpoolnameRHRt inst_listt printargsR:tis_newtdel_listterror((R sbootadm-helper.pyt_bootadm_handle_legacy>sV $  "      $ !     c Cs?t}ddg}t|ii}z |~}x|D]}t||\}}} |tjotS|djot|| }q<|d jot||| }q<||jot||| }q<t ||| }q<W| d j o@|tjot t d q5|djot |q5nWd QX|S( s Set a menu-wide property. All properties all handled through BootConfig.boot_loader.setprop(), except 'default' which is an instance-level property and kernel= | args= which have legacy meaning (used by 'eeprom'). RYR R7sadd-usersdel-users del-superusers add-superusers auth-files:The boot loader configuration files have not been changed.N(sadd-usersdel-users del-superusers add-superusers auth-file(R R R>R?R+R&Rt_handle_password_propertyRRR!R$RCR( tproplistRDRt LEGACY_PROPSRHRR'RR)R*((sbootadm-helper.pytbootadm_set_menu{s, #       cCst}d}d}d}h}|djo|}|}ti|pttddStitii ot i }|djottdqt i|pttdqt i d}||jot ||||}qttdqttd n|djo0|}|}|ot ||||}qnj|d jo\|} |}ti i| ot| d} x| D]} | id} ti| o| idd} | d}ti|pttd| dS| d}t i|pttd| qn|ih||6qttd| qW| inttd| x3|iD]!\} }t || ||}qWn|S(s) Handle setting the password properties. R_sadd-users5Username must contain alphanumeric '-', '_', and '.'NsCannot have empty passwords<Password must contain printable characters (ASCII 0x20-0x7E)sRe-enter password: sPassword does not matchsZUse -auth-file= to supply the password. File format is = pairs.sdel-users del-superusers add-superusers auth-fileRKs RiisEInvalid line %s. Username must contain alphanumeric '-', '_', and '.'sMInvalid line %s. Password must contain printable characters (ASCII 0x20-0x7E)s4Invalid line %s. File format is "username=password".sfile %s does not exist(sdel-users del-superusers add-superuser(R tUSERNAME_CRITERIARrR$RCRNRlRmRnRoRpRqR|RRRsR=R,tPASSWD_FILE_CRITERIAR"tupdatetcloset iteritems(RR)R*RtusernameRvRt temp_dictRtfileRR2t split_lineRR((sbootadm-helper.pyRsv               cCsMt}|djp |djoCy|ii||WqItj o}tt|qIXn|djo@y|ii|WqItj o}tt|qIXn|djoJy|ii|WqItj o#}ttd|t }qIXnC|djo|ii |n"|djo|ii |n|S(s Set username and password. sadd-users auth-filesdel-users add-superusers2%s. Add user with the 'bootadm add-user' command.s del-superusers menu-password( R Rutadd_userRR$RAt remove_usert add_superuserRCR&tremove_superusert set_password(RR$RvRRR((sbootadm-helper.pyR|s.     cCs8t||ot|||nttddS(NsSInvalid property passed. Use bootadm help for a list of valid properties.(RtsetattrR$RC(R:R)R*((sbootadm-helper.pyt_set_instance_property scCst}g}g}|djo|djo dGHnG|o|id}n|o|id}nt|||}|S(s Given an instance (or a list of comma-separated instances), either through an index (indexstr) or through titles (inststr), display the instance details. R_sNo target entry specified.Rg(R R"R(RDRRRRR((sbootadm-helper.pytbootadm_show_entrys c st}g}g}|o|id}n|o|id}nt|ii}z|~xw|D]o}|djoBt|t|djottdtSdt n(t |\} | tjotSx|D]yt } i | } Wnht j o$ttdt}qn:tj o-ttd| ft}qnXdjoGyii| Wq tj o} ttd | q Xqd joii| qt| qWx|D]djoYy)ifd fd Wqtj o} ttd | qXqd jo)ifd fdqifdfdqWqpW|tjotnWdQX|S(s Given an instance (or a list of comma separated instances), either through an index (indexstr) or through titles (inststr), set the given property (or list of space-separated properties) to it. E.g.: bootadm_change_entry(b, 'kargs="-kd -v" splashimage='boot/background.png', indexstr='2,4') will modify the kargs and splashimage parameters of instances 2 and 4 in the menu. Rgs set-defaultis(Only one entry may be set as the defaultR7s5The value "%s" is not a number. A number is required.s8No menu entry can be found at index %d, cannot set %s=%ssadd-auths2%s. Add user with the 'bootadm add-user' command.sdel-authcs |ijS((RU(R(R:(sbootadm-helper.pyRoscsii|S((Rutadd_auth_to_instance(R(R*R(sbootadm-helper.pyRps cs |ijS((RU(R(R:(sbootadm-helper.pyRvscsii|S((Rutdel_auth_from_instance(R(R*R(sbootadm-helper.pyRws cs |ijS((RU(R(R:(sbootadm-helper.pyRzscst|S((R.(R(R*R)(sbootadm-helper.pyR{sN(R R"R R>R?RR$RCR&RR+RMRwR#R{RuR0RR1R.tmodify_boot_instanceR( RRDRRRRRRHR'RRFRR((R)R*RR:sbootadm-helper.pytbootadm_change_entry+s| #           cs gg}|dj okt|ii}zK|~}|iddt}|djottdtSt SWdQXn|o|i dn|o|i d}nd}t|ii} zB| ~ }x|D]} yAt | } | t |i jottd| wnWn(tj ottd| tSX|i | |ifd dt} || 7}qW|ifd dt} | |}|djottdtS|d jotd GHntd |GHt|t SWdQXtS(s Given an instance or a list of instances either through an index or a title (or a list of indexes/titles), remove the matching entries. cSstS((R(R((sbootadm-helper.pyRsRisNo entry removed.NRgsIgnoring invalid index: %ss(Invalid index passed for an instance: %scs |jS(((R(tdel_bi(sbootadm-helper.pyRscs |ijS((RU(R(R(sbootadm-helper.pyRsis1 entry removed.s%d entries removed.(R!R R>R?RRR$RCR&R R"RMRRwR#R}R(RDt delete_allRRRRHRRtretidxRR:RFt retidx_temptretstrttotal((R4Rsbootadm-helper.pytbootadm_remove_entrysV # #         c Cstidd|d|}t|ii}z~|~}|oOyt|}Wn(tj ott d|t SX|i ||n|i |t |t SWdQXdS(sGiven a name and, optionally, a position, create a new entry in the menu with title==name and, optionally, placed at the reqested position RUR.sInvalid index passed: %sN(RWRXR!R R>R?RMR#R$RCR&RRR (t entry_nameRDt entry_post new_entryRHRRF((sbootadm-helper.pytbootadm_add_entrys#  cCst|dtiitiitiigii}zM|~}| o.ti i |i i jot tdtSt|WdQXdS(sV Build a new menu configuration based on the available Boot Environments. tflagssNBoot loader configuration has customizations. Use -f to force menu generation.N(R RWRjt BCF_AUTOGENtBCF_NO_LOAD_BOOT_INSTANCEStBCF_LOAD_SILENT_FAILURER>R?tblt BootLoadertARTIFACT_BOOTLOADER_CONFIGFILESRt artifactsR$RCR&R(RDRRHR((sbootadm-helper.pytbootadm_generate_menus ) cCs*x#|D]}|i|jo|SqWdS(s[ Given a list of boot instances, find the one that matches the specified name. N(RUR!(tbisR3R:((sbootadm-helper.pyt_find_bi_by_names  cCskt|ii}zK|~}|ipttdtSyti|}||i_ t |idy0|djo|i } nt i|} Wn0tj o$} ttdt| tSXd} |o ti} n|ohttii6} nd} |ii| d|d| d| Wn&tij o} t| itSXtSWdQXdS(s` Install the bootloader to disk from either the current root or an arbitrary mountpoint.s*Unable to determine the system boot loadersNUnable to determine the list of boot devices for boot loader installation (%s)Rt verbose_filetplatdictN(R R>R?RR$RCR&RWtSolarisBootInstancetdata_source_boot_instanceRR!tget_boot_device_listR t_complete_boot_device_listRRARmRRRCRDt PLATOPT_MBRtinstalltBootLoaderInstallErrorRR (RRRDtsrc_pathtdevlistt write_mbrRHRtfake_bit target_listtbmet dest_outputRKtexc((sbootadm-helper.pyR~s<#      cCsfd|}ti|tio|Sd|d}ti|tio|Sttd|dS(s: Apply expansion rules to a partial path for update_temp. s/platform/i86pc/s /amd64/unixs(Unable to derive the kernel path from %sR_(RNtaccesstR_OKR$RC(t partial_pathtnew_path((sbootadm-helper.pyt _expand_kpath&s cCsr|djo7tidddi}|o|d}qed}n"t|}|ptddfSd||fS(NtkmdbR.tunuseds -ks-ki(RWRXR!RYR_R&(t new_kernelt base_kargs((sbootadm-helper.pyR6s   cCst|dt}|tjoft|t}t|ii}z7|~}t||}|tjot |nWdQXn|S(NR( R:RR RStBAM_TRANSIENT_SAVEFILER R>R?RR(RDRRFRHR((sbootadm-helper.pytbootadm_remove_transient_entryIs # c CsK|iddjon|idd}t|ii}z;|~}t||}|tjot|n|SWdQXnd}t }t|ii}z|~}t |i t }t |i t } | djo%tiddt d|} t}nd} d} |dj o|i| _|i| _n|ddjo |} n;|id } | d jo|| } || } n|} | oF| dd jo(t| | \} } } | o| Sn| | _n| dj o | | _n|o6t| _t| _t||i t|i| nt|WdQXtS( Nsentry=iRiRUR.R_t-RiRh(tfindR"R R>R?RR RR!R}RIRwRRRWRXRRYRZRt transientR7RJRdR(tentrystrRDR*RHRRtbirct new_transientRt transient_bittransient_kernelttransient_kargst kernel_endR((sbootadm-helper.pytbootadm_add_transient_entryTsZ# #                 cCstitdIJttdoJtidIJtidIx-tiD]}tid|IqGWtiJnttdoJtidIJtidIx-tiD]}tid|IqWtiJndS(s- List valid properties for bootadm set-prop. s&Valid bootadm set-menu properties are:Rs GRUB Legacy:R7s%ssGRUB2:N(RmRRCRR RR (R)((sbootadm-helper.pytbootadm_print_bootloader_propss       c Cstii|}yktii|pti|nt|dii}z$|~}|it |t SWdQXWn*t t fj ot tdtSXdS(s9 Writes the specified UUID to the specified path sw+NsCould not set UUID(RNRRtdirnameRstmakedirsR=R>R?R@RAR RBRPR$RCR&(RRtuuid_strt directoryRHtfobj((sbootadm-helper.pytbootadm_set_uuids&cCsKyt|dSWn3tj o'|ottd|ndSXdS(s7 Returns the UUID for the specified BE dataset sorg.opensolaris.libbe:uuids*WARNING: Could not get UUID for dataset %sN(RRR$RCR!(trootdsR((sbootadm-helper.pytbootadm_get_uuids cCs<t}|o|do |dSttddSdS(s3 Returns the UUID string for the active BE Rts!Could not get UUID from active BEN(RR$RCR!(R((sbootadm-helper.pytbootadm_get_active_be_uuids   cCsCt|}|djo t}n|ot||StSdS(s Creates /boot/solaris/BE_uuid file whose content is the value of org.opensolaris.libbe:uuid property of the root dataset. N(RyR!RzRwR&(RxRRRt((sbootadm-helper.pytbootadm_create_BE_uuids    c Cs|iddjodS|idd}yt|dhtti6ii}z||~}|i}|djp|i djodS|i }|i pdS|i |}| p|i |odSWdQXWntj onXdS(sChecks to see if a dataset synch is required for the given root dataset. This function also implicitly checks for the existence of the boot pool. If the boot pool does NOT exist, we do NOT create it here (since this function may be called as part of the check in early boot on a systems with GIZ (Global Immutable Zone)). This is different from all other instances when we instantiate the pybootmgmt DiskBootConfig. In this function, we explicitly request that the BootPool NOT be autocreated. Returns: 0: If the boot pool exists and no synch is needed 1: If the boot pool is missing and need to be created 2: If the boot pool exists and a ds synch is needed Rhiit init_argdictiN(RR"R RR tARG_NO_CREATE_BOOTPOOLR>R?RR!Rtimportedtboot_pool_cached_datasettdataset_synch_requiredR(RxR.RHRRRtcached_dataset_exists((sbootadm-helper.pyt!bootadm_bootpool_ds_sync_requireds& *   cCstid|IJdS(Ns bootadm: (RmR(R((sbootadm-helper.pyR$scCstddttdgddtdgddtddgddtdgddtdgddd d d d td gddd d d d dS(NRDR.s add-user=roots add-user=usersadd-user=user1sauth-file=/root/password.txtsadd-superuser=roots add-auth=userRR_Rt0s del-auth=user(RRqRR3(((sbootadm-helper.pytmain$s t__main__(pt__doc__tbootmgmt.bootconfigt bootconfigRWtbootmgmt.bootloadert bootloaderRCtlibbeRptgettextRNtpkg.pkgsubprocesst pkgsubprocessRRt solaris.misctsolarisRmtbootmgmtRRRRRRRRRR tbootmgmt.bootutilR tbootmgmt.backend.loader.grub2R t"bootmgmt.backend.loader.legacygrubR R RRRRRRt bootmgmt.zfsRRtbootmgmt.pysolRRRRRRRqR R&R RRRdR%t translationRRCtmiscRR!R+R5R;RJRSR^RRRRRRR}RRRRRRRRRRRR|R.R/R3R:R>RGRIR~R_RReRpRqRwRyRzR{RR$Rt__name__(((sbootadm-helper.pyt$s       @4       ` a "78"1 *$  & = ( M  X?   1   Q   .