i'dWc@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z m Z mZddlmZddlmZddlmZmZmZmZddlmZmZdd lmZmZdd lmZm Z m!Z!m"Z"m#Z#dd l$m%Z%dd l&m'Z'dd l(m)Z*ddl+m,Z-ddl.m/Z/m0Z0ddl1m2Z2ddl3m4Z4m5Z5m6Z6m7Z7m8Z8ddl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAddlBmCZCdZDdZEdZFdZGdZHdZIdZJdZKdZLdZMdZNdZOd ZPd!ZQd"ZRd#ZSd$ZTd%ZUd&ZVd'ZWd(ZXd)ZYd*ZZd+Z[d,Z\d-Z]d.e*fd/YZ^e_d0krd1Z`d2Zad3Zbd4Zcd5Zdd6Zed7Zfe`\ZgZhegjr<efegji r9ejjnne'd8eYe^d9Zkekjld:emegjnr~eaekjonegjprebekjonegjqrecekjonegjrredekjonegjsreeekjonegjtrekjojuGHnndS(;s discovery.py - target discovery checkpoint. Attempts to find all target devices on the given system. The Data Object Cache is populated with the information. iN(tSystemFirmware(t getmntanyt mnttab_opent mnttab_close(tBootPool(tget_curr_bootdisk(tALIAStBUSt CONTROLLERtDRIVE(tdescriptors_by_typetdescriptor_from_key(tefi_freetefi_read(tApplicationDatatCalledProcessErrortPopentis_install_envtrun(tDataObjectDict(t InstallEngine(tAbstractCheckpoint(tINSTALL_LOGGER_NAME(t CRO_LABELtTarget(tbe_list(tBEt FilesystemtLogicaltZpooltZvol(tDisktDiskPropt DiskGeometryt DiskKeywordtIscsit GPTPartitiont PartitiontSlice(tSizes/usr/sbin/biosdevs /boot/solaris/bin/create_diskmaps/usr/sbin/croinfos/usr/sbin/devfsadms/sbin/dhcpinfos/usr/sbin/dladms/usr/sbin/eeproms/usr/sbin/fstyps/usr/sbin/iscsiadms/usr/sbin/mounts/usr/lib/fs/pcfs/mounts/usr/sbin/prtvtocs /usr/bin/svcss/usr/sbin/svcadms/usr/sbin/umounts /usr/sbin/zfss/usr/sbin/zpools /dev/zvol/dsks/dev/zvol/rdsktdisktzpools/system/volatile/discovery.logs%/system/volatile/solaris_grubdisk.mapsc\d+(?:t\w+)?d\d+cCs|yFtjt|tjr6tt|}|j}ntt|}Wn/tt fk rw}t d||fnX|S(s@ function to return a drive object based on a specific name sUnable to look up %s - %s( tretmatchtDISK_REtIR RtdriveR tKeyErrortOSErrort RuntimeError(tnametaliasR.terr((s discovery.pytretrieve_driveas cCstjt}yttgdtWntk r:dSXtjj t sctt gdtnt t d}|j }WdQXx|jD]}y|j\}}}Wntk rqnXt|}|jr|jdjjdkr|jd||qq|SqWdS(sa function to collect all of the device paths returned by biosdev as possible boot disks. tloggertrNitusbs1skipping USB drive as an invalid boot disk: %s %s(tloggingt getLoggertILNRtBIOSDEVRtNonetostpathtexiststDISKMAPtCREATE_DISKMAPtopentreadt splitlinestsplitt ValueErrorR5t controllerst attributesttypetdebug(R6tfhtdatatlinet_indextctdtdevpathR.((s discovery.pytget_bios_boot_diskrs*   "  tTargetDiscoverycBseZdZddeedZdZdZdZdZ dZ dZ dZ d Z d d Zd Zddd ZedZdZdZedZdZRS(s> Discover all logical and physical devices on the system. c Cswtt|j|t|_tj|_|jj|_ t t j |_ ||_ ||_||_||_t|_t|_t|_tj|_t|_d|_g|_t|_|j jjdt }|r|j|_n|jss|jdkr6t!j"j#dkr6t$|_n9yt%|_Wn&t&k rn}|j'j(|j)nX|jdkr|jdkrt*dg}t+|} | j,j-ddj.j/dkr|j'j0d qnt1j2|_|j'j(d |jt+t3d g} xU| j,j4D]A} | j5d r+| j6dd krl|jj7| qlq+q+WndS(Nt class_typeti386tbiostsparcs diag-switch?t=ittrues eeprom diag-switch? is set to 'true'. This setting prevents the reading of the OBP boot-device setting. The use of the AI manifest disk keyword 'boot_device' can not be supported with this setting. To correct this issue set eeprom diag-switch? to false and reboot.s(Firmware dedicated boot pool devices: %ss-ps/devs/.cdrom(8tsuperRSt__init__tFalsetdry_runRt get_instancetengtdata_object_cachetdocRt DISCOVEREDtroott search_namet search_typet do_croinfotdo_iscsitlistt swap_listt dump_listtdedicated_bootpool_diskstplatformt processortarchtdicttcro_dictR=tbootdiskt mount_devst live_installt persistenttget_first_childRRtgettfw_nameRRRR0R6RKtstrerrortEEPROMRtstdoutt partitiontstriptlowertwarnRtplatform_devicestMOUNTREt startswithRFtappend( tselfR2RdReRfRgtapp_dataR4tcmdtpRN((s discovery.pyR[sR              $  (   cCsdS(Ni ((R((s discovery.pytget_progress_estimatescCstddt}|j}|j}|dkrK|jjd|jdS|jdkru|jjd|jdSt |j djdd}|dk rt |j djdd}|dk rd ||f|_ q||_ n|j dkr |j dj|_ nxU|j D]J}|j |j|jjrM|jj|jq|jj|jqW|jr|j r|jjd |jdS|jd|_ |j|_|j|_|j|_tjj|jrd|jjd r tjtj|j}ntj|j}d |krdd |krd|jd djd d}||_qdn|jdk r|j |jkrt|_ t!r|j"r|j"djj#dkr|j|j$krd|j _%qqnd|j |j&krt'|_(nt)|_*|j"r}|j"djj#|j*_+xJ|j,j-dt.D]0} |j | j/krFd|j*_+| |_0qFqFWn|j1|j*_2|j r|j |j3kr|j3|j d|j*_4|j3|j d|_5n|j} |j6| |}g} |j7dkrN|j8rN|j9 rN|jjd  rN|j:dkrNd|_;|S|j:dkrax|j9D]}} |j<| | j} |j=| xR| jj8D]D}|j>|| j}| j?r| j=|n| j|jqWqgWx)|j8D]h}|jjd r&t@jAd|j r&qn|j| kr|j>|| j}|j=|qqWn|j:dkrtjB|jtjCtjDB}zqtE|}zSxL|j8D]A}|jFjG|jjH}|jI|| j|}|j=|qWWdtJ|XWdtjK|Xn|S(s discover_disk - method to discover a physical disk's attributes, partitions and slices drive - which physical drive to parse R(tvalidate_childrensdisk '%s' has no mediatDOWNsdisk '%s' is offlineitwwntluns%s,%ds"disk '%s' only has passive aliasess/dev/dids/devicest:iR8tcurrent_boot_devices /dev/dsk/RTtiSCSIiRUtGPTtVTOCs/dev/did/dsk/d\d+(?=s)N(LRR\RItmediaR=R6RKR2tstatustgetattrtaliasesRRPtverify_disk_readt blocksizet active_ctdsRt passive_ctdstdevidtcdromtiscdromtopathR>R?tislinkRtreadlinkR{t rpartitionRQRqR"t disk_keywordRRHRJRrtkeyRktTruet isdedicatedR t disk_proptdev_typeRatget_descendantsR#tctd_listtiscsit vendor_idt dev_vendorRpt dev_chassist receptaclet set_geometryRntslicest partitionstlabelt_labeltdiscover_partitiontinsert_childrentdiscover_slicet is_solarisR*R+RCtO_RDONLYtO_NDELAYR tcontentst efi_partstindextdiscover_gptpartitionR tclose(RR.tnew_disktdrive_attributest drive_mediaRRR3tlinkRtdrive_media_attributestvisited_slicesR{t new_partitiontslct new_sliceRLtgptptefi_partt new_gpart((s discovery.pyt discover_disks                                  cCsd|}|d}x||gD]}d}zlyQtj|tjtjB}ytj||}Wntk r{w!nXtSWntk rw!nXWd|dk rtj|nXq!Wt S(sg verify_disk_read() - method to verify a low-level read from the raw ctd path. s /dev/rdsk/%sts2N( R=R>RCRRRDR0RRR\(RRPRtrawtraw2traw_disktfdt_none((s discovery.pyRs"      cCsd}|jdkrptt|jtj|j|j_t |jd}|j rd|_ t |_ qnd|_ |j |_ |j}|j}|j}tt|jtj|j|j_t |j||}||_||_||_||_|S(s set_geometry() - method to set the geometry of the Disk DOC object from the libdiskmgt drive object. dma - the drive's media attributes as returned by libdiskmgt new_disk - Disk DOC object RRN(R=t ncylindersR'tstrtsizet sector_unitsRRtdev_sizeR!tefiRRtvolidtnheadstnsectorst naccessibletncyltgeometry(RtdmaRt new_geometryRtnheadtnsect((s discovery.pyRs.           cCsx|jD]}x|jjD]}|j}d|kr|dddkr{|jjtr{|jj|jdq{n|dddkr|jjtr|j j|jdqqqqWq WdS(sp discover_psuedo - method to discover pseudo controller information, usually zvol swap and dump tused_byt used_nameitdumpitswapN( tdrivesRRt use_statsR2Rt ZVOL_PATHRjRRi(Rt controllerR.Rtstats((s discovery.pytdiscover_pseudos  c Cs|j}|jjd\}}}t|dt}d|_|j|_|jtjdkry-|d}t |g} t | dt j Wqt k rt|_qXntt|jtjd||_t|j|_|j|_|jr|j|j|_n|S(s discover_partition - method to discover a physical disk's partition layout partition - partition object as discovered by ldm blocksize - blocksize of the disk RRtpreservesSolaris/Linux swapRRzR(RIR2R{R%R\tactiontidt part_typet name_to_numtPRTVTOCRRtDEVNULLRRt is_linux_swapR'RRRRtlongtrelsectt start_sectortsize_in_sectorst is_efi_systemtis_pcfs_formattedt_is_pcfs_formatted( RR{Rtpartition_attributest root_pathRRRtslice2R((s discovery.pyR&s(        cCs|j}tt|j}d|_tt|jtjd||_t|j |_ |j|_ |j }d|kr||_ ndt|j|_tj|j|_tj|j|_|j|_|jr|j|j|_n|S(s discover_gptpartition - method to discover a physical disk's GPT partition layout. # Note that libdiskmgmt terminology treats GPT partitions as slices # as does the Solaris cXtYdZsN notation # We shall refer to them as GPT partitions though, like the rest of # the world does. partition - object as discovered by ldm blocksize - blocksize of the disk efipart - DK_PART EFI cstruct RRRs{%s}(RIR$RRRR'RRRtstartRRRtin_usetp_guidRtcopytguidtp_uguidtuguidtp_flagtflagRRR2R(RR{Rtefiparttgpart_attributesRR((s discovery.pyR[s"         cCs|j}tt|j}d|_|j|_|j|_tt|jtj d||_t |j |_ |j|_ |j}d|kr||_n|S(s discover_slices - method to discover a physical disk's slice layout. slc - slice object as discovered by ldm blocksize - blocksize of the disk RRR(RIR&RRRttagRR'RRRRRRRR(RRRtslc_attributesRR((s discovery.pyRs         tc Cstd}t|_t|_tddddg}t|}|jj}x|D]}|rs||krsqUn|jj d|t |}d|_ |j |tdddd|g}t|}|jj d krt|_ntd ddd d |g}t|}|jj|_|j|tdd ddddd|g }t|didd6}xj|jj jddD]L}y"|jdd\} } } } Wn@tk r} |jj d||jj t| qnX| j|dd} | dkr0t| }| |_n| dkrt| }t| |_tjj|| |jkrd|_ t!|_ntjj|| |j"krd|_ t!|_qnd|_ |j |qWqUW|S(s discover_zpools - method to walk zpool list output to create Zpool objects. Returns a logical DOC object with all zpools populated. tlogicalRhs-Hs-oR2sPopulating DOC for zpool: %sRtbootfst-Rvtvaluet mountpoints-rs-tsfilesystem,volumesname,type,used,mountpointtenvtCtLC_ALLs iisUnable to process dataset: %rt/it filesystemtvolumeRRN(#RRtnoswaptnodumptZPOOLRRzRER6RKRRRtrstriptis_roottZFSR|Rt set_vdev_mapRFR=RGRR{RRR'RR>R?tjoinRituseR\Rj(RRdR RRt zpool_listt zpool_nameR)tdatasetR2tds_typetds_sizeRR4tobj((s discovery.pytdiscover_zpoolss`             #"          c Cs|jjdt}|j}xt|jD]f\}}d|j|f}|dkrl|jdd}n|}|j||x |D]\}} |jdr|j j d||j d\} } } } }|j d \}}}|s|}t } nd |}d d d dg}t|}|jsN|j jd|qnx|jjj dD]}|jj \} }| |krg|j d\} } }}|}|r|d||f}|j j d||fnPqgqgWn|j dd}| rbx}|D]G}|j|jd ddkr|j|_||_t |_PqqWq|j d \}}}|s|j d\}}}|sqqnx|D]}t|dr|j|kr|d kr)|jdkr|jdt}qJ|jdkrJ|jdt}qJn!|dkrJ|jdt}nx5|D]-}|j|krQ|j|_||_qQqQWPqqqWqWq+WdS(s set_vdev_map() - walk the vdev_map to set the zpool's vdev entries and update existing physical DOC entries with the proper in_zpool and in_vdev attributes. zpool - zpool DOC object RTs%s-%stnoneR is/dev/dids#Converting disk '%s' to ctd format Rtss/dev/did/rdsk/%ss/usr/sbin/didadms-ls-os fullname,paths&Command '%s' failed to find DID devices s%s%ssDisk '%s' converted to '%s's /dev/dsk/iiRRPRRN(Rct get_childrenRtvdevst iteritemsR2R{tadd_vdevRR6tinfoRFRRRRztwarningR|RRPtrsplittin_zpooltin_vdevt _whole_diskthasattrRRR&R$R%( RR)tdisklisttvdev_mapt vdev_typet vdev_entriest in_vdev_labelt redundancyt full_entryt whole_disktblanktdevtdidtdsktdev_idtdev_dskt dev_lettert dev_indext did_rdsk_devRRtrowRPtrdsktdid_ctdtentryR(tvdev_ctdt vdev_lettert vdev_indext child_listtchild((s discovery.pyRs                           c Cst||}x|jjdtD]i}|rF||jkrFq%nxE|D]=\}}}}} } ||jkrM|jt|qMqMWq%WdS(s^ discover_BEs - method to discover all Boot Environments (BEs) on the system. RTN(RRcRRR2RR( RRR2tbe_lstR)tbe_nametbe_pooltroot_dst is_activetds_lsttss_lst((s discovery.pyt discover_BEsvscCsxttD]}|jr"q n|jdkrG|rG|j|q xT|jD]I}|j|}|dksQ|jrqQn|rQ|j j |qQqQWq Wg|j j dt D]}|j ^q}|jjdxttD]}|jrqn|jjjtrqn|j|}|dks|js|jdkrSqn|j |krhqn|r|j j |qqWdS(s discover_entire_system - populates the root node of the DOC tree with the entire physical layout of the system. add_physical - boolean value to signal if physical targets should be added to the DOC. s/pseudoRTs,Adding drives without controllers to the DOCRN(R Rtfloppy_controllerR2RRRR=RRcRRRRQR6RKR RHRIRRt ZVOL_RPATHRP(Rt add_physicalRR.RR(t devpath_list((s discovery.pytdiscover_entire_systems4  ( $cCs|jjdt}|sdSxw|D]o}|jsmy|jWqmttfk ri|jqmXnt|j t r&|jd|j _ q&q&WdS(s set up the iSCSI initiator appropriately (if specified) such that any physical/logical iSCSI devices can be discovered. RTNi( RaRR#Rt setup_iscsiRR1tteardownt isinstancetparentRRP(Rt iscsi_listR((s discovery.pyRYs    cCstdddg}t|}|js+dSd}xa|jjD]P}|jd\}}}|skqAn||pwd|f|j|<|d7}qAW|jr|jjj t t |jdt ndS(sX set up a DataObjectDict representing the output from /usr/sbin/croinfo s-hs-OtcARNiRt generate_xml( tCROINFORRzRERFR=RpRaRtRRRR(RRRtiRNRPR3R((s discovery.pyt setup_croinfos    cCs||_|jjjdtj}|jr:|jn|jrP|j n|j t krt |j trx|j D]@}t|}|j|}|dk r{|jj|q{q{Wqzt|j }|j|}|dk rz|jj|qznx|j tkrP|jdt|jj|j|j |j|j n*|j|jj|j|j|s|jjj|jn.|d}x!|jjD]}|j|qWdS(s; primary execution checkpoint for Target Discovery R2RViN(R]RaRtRRRbRfRbRgRYRetDISK_SEARCH_NAMER[RdRhR5RR=RcRtZPOOL_SEARCH_NAMERXR\R$RStchildren(RR]t discoveredR2R.RRK((s discovery.pytexecutes<            cCsC|jddd}|jdr2d|}n d|}tjj|tkrgtd|nd }ztt d|}Wd t X|d k r|j d d krt StSnt jd d dd|}zPy7t||g}t|t|g}t|t SWntk r(tSXWd tj|XtSd S(s is_pcfs_formatted() Return a Boolean value of True if the GPT partition guid is already formatted with a pcfs filesystem. This test is useful in conjuction with the is_efi_system property to determine if an existing EFI system partition can be reused to store the Solaris UEFI boot program. If False, a format using mkfs on the partition would be required. Riis/dev/dids/dev/did/dsk/%ss /dev/dsk/%ssNo such block device exists: %st mnt_specialNt mnt_fstypetpcfstdirs/system/volatiletprefixsesp_%s_(R-RR>R?R@R\R1R=RRRRvRttempfiletmkdtempt PCFSMOUNTRtUMOUNTRtrmdir(Rtdev_pathtctdnR?tmntmatcht mount_pointt mount_cmdt umount_cmd((s discovery.pyR8s8          N(t__name__t __module__t__doc__R=RR[RRRRRRRRR$RRSRXRYRbR\RgR(((s discovery.pyRSs&S   0  5 +  ] y <   15} | {1:>5} | {2:>40} |s {0:>15} |it t|i*is| {0:>5} | {1:>40} |R iCs disk nameRsin use?RRs used by: %sRs (%s)Ns s ( RtR'RRtformatRPRR$RR=R2( RaRRRt disk_formatRt disk_linet entry_lineR(t gpart_listtgpartR((s discovery.pytprint_gptpartitions.      c Cs7dGH|jjdtd}|jdt}d}dddd}dd }d d }|GH|jd ddddgGH|GHx|D]}|j|jGH|jdt}xt|D]l} | jtjkrd} nd} | j rd} nd} |j| j j dd| | j | gGHqW|GHqWdS(s0 prints the output from the -p argument sPartition discoveryRTis.{0:>15} | {1:>5} | {2:>7} | {3:>5} | {4:>11} |s {0:>15} |i'RRis&| {0:>5} | {1:>7} | {2:>5} | {3:>11} |R i9t disk_nameRsactive?tIDs Linux Swap?RRRiNs ( RtR'RRRRPR%tbootidtACTIVERR2RFR( RaRRRRt line_formatRR(tpartition_listR{tactivet linux_swap((s discovery.pytprint_partitions2         c Cs^dGH|jjdtd}|jdt}d}dddd dd}dd }d d }|d}|GH|jdddgGH|GHx|D]}|j|jGH|jdt} x| D]} | jdkrd} nRd| jkr6d| jdd} d| jkr6| d| jdd7} q6n|j| j | gGHqW|GHqWdS(s0 prints the output from the -s argument sSlice discoveryRTis{0:>15} | {1:>5} | {2:>40} |s {0:>15} |iRRi*is| {0:>5} | {1:>40} |R iCs disk nameRsin use?RRs used by: %sRs (%s)Ns s ( RtR'RRRRPRR&RR=R2( RaRRRRRRRR(t slice_listRR((s discovery.pyt print_slices.      cCs/dGH|jjdtd}|jdtd}|jdt}d}dd}|GH|jddd d d gGH|GHx|D]}d d d|jg}tj|dtj dtj }g|j j ddd!D]} | j d^q\} } } } |j|j| | | | gGHqW|GHdS(s0 prints the output from the -z argument sZpool discoveryRTis/{0:>10} | {1:>20} | {2:>20} | {3:>7} | {4:>8} |R iOR2R RRtcapacitys/usr/sbin/zpoolRvsbootfs,guid,size,capacityRztstderrs iiiN( RtR'RRRRR2Rt check_calltSTORERzRF(RaRR Rt print_formatt zpool_lineR)RRRNR RRR((s discovery.pyt print_zpool s$     !Bc Csd}d}xttD]}||t|GH|d7}x|jD]}||t|GH|d7}x%|jD]}||t|GHqxWx7|jD],}||t|GH|d7}x%|jD]}||t|GHqWx%|jD]}||t|GHqW|j}|dk r||t|GH|j }|d7}|j sb|j rx(|j D]} ||t| GHqlWnx%|j D]} ||t| GHqW|d8}n|d8}qW|d8}qJW|d8}qWdS(sA prints drive information from the --libdiskmgt argument cSs.djg|jD]}d||^qS(s2 function to print an indented string s s (RRE(tleveltstringRN((s discovery.pyt indent_str-siiN(R RRRHtpathsRRRR=RIRtfdiskRR( RtindenttbusRR?R.R3RRtpartR((s discovery.pytprint_libdiskmgt)s>         t default_logsTest TDR](vRzRR9RR>RlR*tsysRmtbootmgmt.bootinfoRtbootmgmt.pysolRRRtbootmgmt.versabootRt libdevinfoRtlibdiskmgt.constRRRR RR R tlibefiR R tsolaris_installRRRRRt%solaris_install.data_object.data_dictRtsolaris_install.engineRt!solaris_install.engine.checkpointRt Checkpointtsolaris_install.loggerRR;tsolaris_install.targetRRtsolaris_install.target.libbeRtsolaris_install.target.logicalRRRRRtsolaris_install.target.physicalRR R!R"R#R$R%R&tsolaris_install.target.sizeR'R<RBR`tDEVFSADMtDHCPINFOtDLADMRytFSTYPtISCSIADMRRoRtSVCStSVCADMRpRRRRURcRdtCLI_DEFAULT_LOGRAR,R5RRRSRxRRRRRRRRRRtexittTDRgRR(RaRR{RR)Rtget_xml_tree_str(((s discovery.pyts        "((:  )  "  #  -