├── README.md ├── distr ├── firefly_boot_archive_configure.py ├── firefly_boot_archive_contents_x86.xml └── firefly_pkg_img_mod.py ├── firefly.xml ├── iso ├── checkrpool ├── nodename ├── nonglobal.db ├── rootpool ├── smf │ ├── console-login │ ├── fs-root │ └── manifest-import └── sulogin └── rootpool ├── Makefile └── rootpool.c /README.md: -------------------------------------------------------------------------------- 1 | # firefly 2 | failsafe image for illumos-based distros 3 | 4 | How To build failsafe image for OmniOS: 5 | 6 | 1. Install distribution-constructor. 7 | 2. Clone git@github.com:alhazred/firefly.git to /opt/firefly 8 | 3. Copy python scripts from the /opt/firefly/distr directory to /usr/lib/python2.6/vendor-packages/solaris_install/distro_const/checkpoints/ 9 | 4. From the /opt/firefly directory, run "distro_const build -v firefly.xml" 10 | -------------------------------------------------------------------------------- /distr/firefly_boot_archive_configure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # CDDL HEADER START 4 | # 5 | # The contents of this file are subject to the terms of the 6 | # Common Development and Distribution License (the "License"). 7 | # You may not use this file except in compliance with the License. 8 | # 9 | # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 | # or http://www.opensolaris.org/os/licensing. 11 | # See the License for the specific language governing permissions 12 | # and limitations under the License. 13 | # 14 | # When distributing Covered Code, include this CDDL HEADER in each 15 | # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 | # If applicable, add the following below this CDDL HEADER, with the 17 | # fields enclosed by brackets "[]" replaced with your own identifying 18 | # information: Portions Copyright [yyyy] [name of copyright owner] 19 | # 20 | # CDDL HEADER END 21 | # 22 | 23 | # 24 | # Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 25 | # Copyright 2015 Nexenta Systems, Inc. All rights reserved. 26 | 27 | """ boot_archive_configure - configure a populated boot archive area into a 28 | usable boot archive. 29 | """ 30 | import os 31 | import os.path 32 | import shutil 33 | import datetime 34 | 35 | from osol_install.install_utils import dir_size 36 | from solaris_install import DC_LABEL, run 37 | from solaris_install.data_object.data_dict import DataObjectDict 38 | from solaris_install.transfer.info import Software, Source, Destination, \ 39 | CPIOSpec, Dir 40 | from solaris_install.transfer.media_transfer import TRANSFER_ROOT, \ 41 | INSTALL_TARGET_VAR 42 | from solaris_install.engine import InstallEngine 43 | from solaris_install.engine.checkpoint import AbstractCheckpoint as Checkpoint 44 | 45 | # load a table of common unix cli calls 46 | import solaris_install.distro_const.cli as cli 47 | cli = cli.CLI() 48 | 49 | 50 | class BootArchiveConfigure(Checkpoint): 51 | """ class to configure the boot archive 52 | """ 53 | 54 | DEFAULT_ARG = {"image_type": None} 55 | 56 | def __init__(self, name, arg=DEFAULT_ARG): 57 | super(BootArchiveConfigure, self).__init__(name) 58 | self.image_type = arg.get("image_type", 59 | self.DEFAULT_ARG.get("image_type")) 60 | 61 | # instance attributes 62 | self.doc = None 63 | self.dc_dict = {} 64 | self.pkg_img_path = None 65 | self.ba_build = None 66 | 67 | # set the file_defaults to the path of this checkpoint/defaultfiles 68 | self.file_defaults = os.path.join( 69 | os.path.dirname(os.path.abspath(__file__)), "defaultfiles") 70 | 71 | def get_progress_estimate(self): 72 | """Returns an estimate of the time this checkpoint will take 73 | """ 74 | return 20 75 | 76 | def configure_system(self): 77 | """ class method for the execution of various, isolated shell commands 78 | needed to configure the boot archive. 79 | """ 80 | self.logger.info("preparing boot archive") 81 | 82 | # configure devices 83 | cmd = [cli.DEVFSADM, "-r", self.ba_build] 84 | run(cmd) 85 | 86 | # etc/dev/.devfsadm_dev.lock gets created every time 87 | # devfsadm is run. remove it since there's no point 88 | # in carrying it forward through to the image 89 | lockfile = os.path.join(self.ba_build, "etc/dev/.devfsadm_dev.lock") 90 | if os.path.exists(lockfile): 91 | self.logger.debug("removing devfsadm lock file") 92 | os.remove(lockfile) 93 | 94 | # Set a marker so that every boot is a reconfiguration boot 95 | cmd = [cli.TOUCH, os.path.join(self.ba_build, "reconfigure")] 96 | run(cmd) 97 | 98 | # go to the ba_build 99 | self.logger.debug("creating symlinks and mountpoints") 100 | os.chdir(self.ba_build) 101 | 102 | # create ./tmp. mkdir and chmod have to be done seperately 103 | self.logger.debug("creating tmp dir and setting it to 01777") 104 | os.mkdir("tmp") 105 | os.chmod("tmp", 01777) 106 | 107 | # create ./proc 108 | self.logger.debug("creating proc directory") 109 | os.mkdir("proc") 110 | 111 | # create ./mnt 112 | self.logger.debug("creating mnt directory") 113 | os.mkdir("mnt") 114 | 115 | # create bin symlink to /usr/bin if needed 116 | self.logger.debug("checking for symlink of bin -> usr/bin") 117 | if not os.path.islink("bin"): 118 | os.symlink("usr/bin", "bin") 119 | 120 | # create mountpoints for misc and pkg zlibs 121 | self.logger.debug("creating mnt/misc and mnt/pkg mountpoints") 122 | #os.mkdir("mnt/misc", 0755) 123 | #os.mkdir("mnt/pkg", 0755) 124 | 125 | # create volume set id file, use system name + date for uniqueness 126 | with open(".volsetid", "w") as v: 127 | volsetid = os.uname()[1] + '-' + \ 128 | datetime.datetime.now().isoformat() 129 | self.logger.debug("setting .volsetid to %s" % volsetid) 130 | v.write(volsetid) 131 | 132 | # chmod it to 444 and set the ownership to root:root (0:0) 133 | os.chmod(".volsetid", 0444) 134 | os.chown(".volsetid", 0, 0) 135 | 136 | # create the file marking the image type (e.g. .autoinstall or 137 | # .livecd) 138 | self.logger.debug("creating image_type file") 139 | with open(self.image_type, "w"): 140 | pass 141 | 142 | # create .cdrom directory 143 | self.logger.debug("creating .cdrom directory") 144 | os.mkdir(".cdrom", 0755) 145 | 146 | # create opt symlink to mnt/misc/opt if needed 147 | #self.logger.debug("checking for symlink of opt -> mnt/misc/opt") 148 | #if not os.path.islink("opt"): 149 | # os.symlink("mnt/misc/opt", "opt") 150 | 151 | tr_uninstall = CPIOSpec() 152 | tr_uninstall.action = CPIOSpec.UNINSTALL 153 | tr_uninstall.contents = ["opt"] 154 | 155 | root_tr_software_node = self.doc.persistent.get_descendants( 156 | name=TRANSFER_ROOT, class_type=Software, not_found_is_err=True)[0] 157 | root_tr_software_node.insert_children(tr_uninstall) 158 | 159 | # copy the SMF repository from pkg_image_path to ba_build 160 | #pkg_img_path_repo = os.path.join(self.pkg_img_path, 161 | # "lib/svc/seed/nonglobal.db") 162 | #ba_build_repo = os.path.join(self.ba_build, 163 | # "etc/svc/repository.db") 164 | #shutil.copy2(pkg_img_path_repo, ba_build_repo) 165 | 166 | shutil.copy2("/opt/firefly/iso/nonglobal.db", self.ba_build + "/etc/svc/repository.db") 167 | shutil.copy2("/opt/firefly/iso/nodename", self.ba_build + "/etc/") 168 | shutil.copy2("/opt/firefly/iso/checkrpool", self.ba_build + "/usr/sbin/") 169 | shutil.copy2("/opt/firefly/iso/smf/console-login", self.ba_build + "/lib/svc/method/") 170 | shutil.copy2("/opt/firefly/iso/smf/fs-root", self.ba_build + "/lib/svc/method/") 171 | shutil.copy2("/opt/firefly/iso/smf/manifest-import", self.ba_build + "/lib/svc/method/") 172 | shutil.copy2("/opt/firefly/iso/rootpool", self.ba_build + "/usr/sbin/") 173 | shutil.copy2("/opt/firefly/iso/sulogin", self.ba_build + "/etc/default/") 174 | shutil.copy2(self.pkg_img_path + "/usr/xpg4/bin/vi", self.ba_build + "/usr/bin/") 175 | shutil.copytree(self.pkg_img_path + "/usr/share/lib/keytables", self.ba_build + "/usr/share/lib/keytables") 176 | shutil.copytree(self.pkg_img_path + "/usr/share/lib/terminfo", self.ba_build + "/usr/share/lib/terminfo") 177 | os.chdir(self.ba_build + "/sbin") 178 | os.unlink("sh") 179 | os.symlink("../usr/bin/bash", "sh") 180 | os.chdir(self.ba_build) 181 | 182 | 183 | def configure_symlinks(self): 184 | """ class method for the configuration of symlinks needed in the boot 185 | archive. 186 | """ 187 | self.logger.debug("Creating additional symlinks in ramdisk") 188 | 189 | self.logger.debug("creating set of files in pkg_img_path: %s" % \ 190 | self.pkg_img_path) 191 | 192 | # change to the pkg_img_path directory 193 | os.chdir(self.pkg_img_path) 194 | 195 | # walk /etc and /var in pkg_img_path and create a list of 196 | # directories 197 | pkg_img_dirs = [] 198 | for rootdir in ["etc", "var"]: 199 | for root, dirs, files in os.walk(rootdir): 200 | for d in dirs: 201 | pkg_img_dirs.append(os.path.join(root, d)) 202 | 203 | # change to the boot_archive directory 204 | os.chdir(self.ba_build) 205 | 206 | # walk the pkg_img_dirs list and create each directory that doesn't 207 | # already exist. Also, copy the directory permissions and metadata 208 | # to the new directory 209 | for d in pkg_img_dirs: 210 | ba_path = os.path.join(self.ba_build, d) 211 | pkg_path = os.path.join(self.pkg_img_path, d) 212 | 213 | # split the directory on / to verify parent directories exist 214 | dir_list = d.split("/") 215 | 216 | # keep a 'path' string for verification 217 | path = "" 218 | for subdir in dir_list: 219 | # extend path 220 | path = os.path.join(path, subdir) 221 | full_path = os.path.join(self.ba_build, path) 222 | 223 | # check to see if it exists and is not already a symlink 224 | if not os.path.exists(full_path) and \ 225 | not os.path.islink(full_path): 226 | 227 | # create the directory 228 | os.mkdir(os.path.join(self.ba_build, path)) 229 | 230 | # copy the metadata from pkg_image to boot_archive 231 | shutil.copystat(os.path.join(self.pkg_img_path, path), 232 | os.path.join(self.ba_build, path)) 233 | 234 | # copy the uid/gid as well 235 | pkg_statinfo = os.stat(os.path.join(self.pkg_img_path, 236 | path)) 237 | 238 | os.chown(os.path.join(self.ba_build, path), 239 | pkg_statinfo.st_uid, pkg_statinfo.st_gid) 240 | 241 | # now that the directory structure is created, create symlinks for 242 | # all the missing files in the boot_archive 243 | 244 | # change to the pkg_img_path directory 245 | os.chdir(self.pkg_img_path) 246 | 247 | # keep track of all the symlinks created 248 | misc_symlinks = [] 249 | for rootdir in ["etc", "var"]: 250 | for root, dirs, files in os.walk(rootdir): 251 | for f in files: 252 | pkg_path = os.path.join(self.pkg_img_path, root, f) 253 | 254 | # skip symlinks 255 | if os.path.islink(pkg_path): 256 | continue 257 | 258 | ba_path = os.path.join(self.ba_build, root, f) 259 | if not os.path.exists(ba_path): 260 | # the file is missing from the boot_archive so 261 | # create a symlink to /mnt/misc/file/path 262 | misc_path = os.path.join("/mnt/misc", root, f) 263 | 264 | # save the cwd 265 | cwd = os.getcwd() 266 | 267 | # changedir to the dirname of the file 268 | os.chdir(os.path.dirname(ba_path)) 269 | 270 | # create the symlink 271 | os.symlink(misc_path, f) 272 | 273 | os.chdir(cwd) 274 | 275 | misc_symlinks.append(os.path.join(root, f)) 276 | 277 | # We don't want readonly ttymon log in misc 278 | os.remove(os.path.join(self.ba_build,"var/saf/zsmon/log")) 279 | 280 | tr_uninstall = CPIOSpec() 281 | tr_uninstall.action = CPIOSpec.UNINSTALL 282 | tr_uninstall.contents = misc_symlinks 283 | 284 | # Add that into the software transfer list. The list of files to 285 | # uninstall MUST go before the contents to be installed from /mnt/misc 286 | root_tr_software_node = self.doc.persistent.get_descendants( 287 | name=TRANSFER_ROOT, class_type=Software, not_found_is_err=True)[0] 288 | 289 | root_tr_software_node.insert_children(tr_uninstall) 290 | 291 | self.logger.debug(str(self.doc.persistent)) 292 | 293 | def parse_doc(self): 294 | """ class method for parsing data object cache (DOC) objects for use by 295 | the checkpoint. 296 | """ 297 | self.doc = InstallEngine.get_instance().data_object_cache 298 | self.dc_dict = self.doc.volatile.get_children(name=DC_LABEL, 299 | class_type=DataObjectDict)[0].data_dict 300 | 301 | try: 302 | self.pkg_img_path = self.dc_dict["pkg_img_path"] 303 | self.ba_build = self.dc_dict["ba_build"] 304 | except KeyError: 305 | raise RuntimeError("Error retrieving a value from the DOC") 306 | 307 | def add_root_transfer_to_doc(self): 308 | """ Adds the list of files of directories to be transferred 309 | to the DOC 310 | """ 311 | if self.doc is None: 312 | self.doc = InstallEngine.get_instance().data_object_cache 313 | 314 | src_path = Dir("/") 315 | src = Source() 316 | src.insert_children(src_path) 317 | 318 | dst_path = Dir(INSTALL_TARGET_VAR) 319 | dst = Destination() 320 | dst.insert_children(dst_path) 321 | 322 | dot_node = CPIOSpec() 323 | dot_node.action = CPIOSpec.INSTALL 324 | dot_node.size = str(dir_size(os.path.join(self.ba_build, ""))) 325 | dot_node.contents = ["."] 326 | 327 | usr_node = CPIOSpec() 328 | usr_node.action = CPIOSpec.INSTALL 329 | usr_node.size = str(dir_size(os.path.join(self.pkg_img_path, "usr"))) 330 | usr_node.contents = ["usr"] 331 | 332 | dev_node = CPIOSpec() 333 | dev_node.action = CPIOSpec.INSTALL 334 | dev_node.size = str(dir_size(os.path.join(self.pkg_img_path, "dev"))) 335 | dev_node.contents = ["dev"] 336 | 337 | software_node = Software(TRANSFER_ROOT, type="CPIO") 338 | software_node.insert_children([src, dst, dot_node, usr_node, dev_node]) 339 | 340 | self.doc.persistent.insert_children(software_node) 341 | 342 | self.logger.debug(str(self.doc.persistent)) 343 | 344 | def execute(self, dry_run=False): 345 | """ Primary execution method used by the Checkpoint parent class. 346 | dry_run is not used in DC 347 | """ 348 | self.logger.info("=== Executing Boot Archive Configuration" + \ 349 | " Checkpoint ===") 350 | 351 | self.parse_doc() 352 | 353 | self.add_root_transfer_to_doc() 354 | 355 | # configure various boot archive files 356 | self.configure_system() 357 | 358 | # configure various symlinks 359 | self.configure_symlinks() 360 | 361 | 362 | class TextBootArchiveConfigure(BootArchiveConfigure, Checkpoint): 363 | """ TextBootArchiveConfigure - class to configure the boot archive 364 | directory specific to the text install media 365 | """ 366 | 367 | DEFAULT_ARG = {"image_type": ".textinstall"} 368 | 369 | def __init__(self, name, arg=DEFAULT_ARG): 370 | """ constructor for class. 371 | image_type - string containing the image_type (.autoinstall, .livecd) 372 | """ 373 | super(TextBootArchiveConfigure, self).__init__(name, arg) 374 | self.image_type = arg.get("image_type", 375 | self.DEFAULT_ARG.get("image_type")) 376 | -------------------------------------------------------------------------------- /distr/firefly_boot_archive_contents_x86.xml: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | sbin 28 | usr/bin/bash 29 | usr/bin/ckitem 30 | usr/bin/logname 31 | usr/bin/nawk 32 | usr/bin/mkdir 33 | usr/bin/loadkeys 34 | usr/bin/cp 35 | usr/bin/head 36 | usr/bin/sort 37 | usr/bin/svcs 38 | usr/bin/amd64/sort 39 | usr/bin/amd64/truss 40 | usr/bin/i386/wget 41 | usr/bin/pkill 42 | usr/bin/mkfifo 43 | usr/bin/egrep 44 | usr/bin/pgrep 45 | usr/sbin/autopush 46 | usr/sbin/beadm 47 | usr/sbin/pmadm 48 | usr/sbin/format 49 | usr/sbin/fdisk 50 | sbin/biosdev 51 | usr/sbin/bootadm 52 | usr/sbin/cryptoadm 53 | sbin/dhcpagent 54 | sbin/dhcpinfo 55 | usr/sbin/dladm 56 | sbin/dlmgmtd 57 | usr/sbin/dlstat 58 | usr/sbin/fdisk 59 | usr/sbin/fiocompress 60 | usr/sbin/flowadm 61 | usr/sbin/flowstat 62 | usr/sbin/hostconfig 63 | usr/sbin/ifconfig 64 | sbin/ifparse 65 | usr/sbin/init 66 | sbin/in.mpathd 67 | usr/sbin/installgrub 68 | usr/sbin/ipadm 69 | usr/sbin/ipmpstat 70 | usr/bin/jsh 71 | usr/sbin/mount 72 | usr/sbin/mountall 73 | usr/sbin/mount_media 74 | sbin/netstrategy 75 | 77 | usr/bin/pfsh 78 | sbin/rc0 79 | sbin/rc1 80 | sbin/rc2 81 | sbin/rc3 82 | sbin/rc5 83 | sbin/rc6 84 | sbin/rcS 85 | usr/sbin/route 86 | usr/sbin/routeadm 87 | sbin/soconfig 88 | sbin/sh 89 | sbin/su 90 | sbin/sulogin 91 | sbin/swapadd 92 | usr/sbin/sync 93 | usr/sbin/tzreload 94 | usr/sbin/uadmin 95 | usr/sbin/umount 96 | usr/sbin/umountall 97 | usr/bin/uname 98 | usr/sbin/wusbadm 99 | usr/sbin/zfs 100 | usr/bin/zonename 101 | usr/sbin/zpool 102 | usr/sbin/svcadm 103 | usr/sbin/svccfg 104 | usr/sbin/prtconf 105 | usr/sbin/amd64/prtconf 106 | 107 | usr/bin/sh 108 | usr/bin/hostname 109 | usr/sbin/ipsecalgs 110 | usr/sbin/fcadm 111 | usr/lib/sysevent/syseventd 112 | usr/lib/libgcc_s.so.1 113 | usr/lib/libxml2.so 114 | usr/lib/libxml2.so.2 115 | usr/lib/libxml2.so.2.9.1 116 | usr/lib/libdiskmgt.so.1 117 | usr/lib/libz.so.1.2.8 118 | usr/lib/libipsecutil.so.1 119 | usr/lib/libHBAAPI.so.1 120 | usr/lib/libfcoe.so.1 121 | usr/lib/amd64/libsaveargs.so.1 122 | usr/lib/libsmbios.so.1 123 | usr/lib/libtecla.so.1 124 | usr/lib/libl.so.1 125 | usr/lib/libexacct.so.1 126 | usr/lib/libpool.so.1 127 | usr/lib/libidmap.so.1 128 | usr/lib/libldap.so.5 129 | usr/lib/libsldap.so.1 130 | usr/lib/libadutils.so.1 131 | usr/lib/libsasl.so.1 132 | usr/lib/mps/libnspr4.so 133 | usr/lib/mps/libplc4.so 134 | usr/lib/mps/libnss3.so 135 | usr/lib/mps/libssl3.so 136 | usr/lib/mps/libnssutil3.so 137 | usr/lib/mps/libplds4.so 138 | usr/sbin/lofiadm 139 | usr/sbin/devfsadm 140 | usr/sbin/modload 141 | usr/sbin/amd64/modload 142 | usr/sbin/mount 143 | usr/sbin/hostconfig 144 | usr/sbin/chroot 145 | usr/sbin/syslogd 146 | usr/sbin/df 147 | usr/bin/coreadm 148 | usr/bin/bash 149 | usr/bin/ksh 150 | usr/bin/cut 151 | usr/bin/sed 152 | usr/bin/more 153 | usr/bin/cat 154 | usr/bin/echo 155 | usr/bin/false 156 | usr/bin/grep 157 | usr/bin/ls 158 | usr/bin/rm 159 | usr/bin/svcprop 160 | usr/bin/true 161 | usr/bin/cd 162 | usr/bin/test 163 | usr/bin/sleep 164 | usr/bin/expr 165 | usr/bin/wget 166 | usr/lib/fs/hsfs/fstyp 167 | usr/lib/fs/hsfs/fstyp.so.1 168 | usr/lib/fs/hsfs/mount 169 | usr/lib/fs/tmpfs/mount 170 | usr/lib/fs/ufs/fstyp 171 | usr/lib/fs/ufs/fstyp.so.1 172 | usr/lib/fs/ufs/mount 173 | usr/lib/libfstyp.so.1 174 | usr/lib/platexec 175 | usr/lib/devfsadm/linkmod/SUNW_cfg_link.so 176 | usr/lib/devfsadm/linkmod/SUNW_disk_link.so 177 | usr/lib/devfsadm/linkmod/SUNW_fssnap_link.so 178 | usr/lib/devfsadm/linkmod/SUNW_ieee1394_link.so 179 | usr/lib/devfsadm/linkmod/SUNW_lofi_link.so 180 | usr/lib/devfsadm/linkmod/SUNW_misc_link.so 181 | usr/lib/devfsadm/linkmod/SUNW_misc_link_i386.so 182 | usr/lib/devfsadm/linkmod/SUNW_port_link.so 183 | usr/lib/devfsadm/linkmod/SUNW_ramdisk_link.so 184 | usr/lib/devfsadm/linkmod/SUNW_sgen_link.so 185 | usr/lib/devfsadm/linkmod/SUNW_tape_link.so 186 | usr/lib/devfsadm/linkmod/SUNW_usb_link.so 187 | usr/lib/devfsadm/linkmod/SUNW_zfs_link.so 188 | usr/lib/devfsadm/devfsadmd 189 | usr/lib/iconv/alias 190 | usr/lib/iconv/646%UTF-8.so 191 | usr/lib/iconv/UTF-8%646.so 192 | usr/lib/libm.so.2 193 | usr/lib/libm.so 194 | usr/lib/libfstyp.so 195 | usr/lib/libz.so 196 | usr/lib/libz.so.1 197 | usr/bin/i86/ksh 198 | usr/bin/i86/ksh93 199 | usr/lib/isaexec 200 | usr/lib/libast.so.1 201 | usr/lib/libcmd.so.1 202 | usr/lib/libdll.so.1 203 | usr/lib/libshell.so.1 204 | usr/lib/libcrypt.so.1 205 | usr/lib/inet/wanboot/netbootinfo 206 | 207 | usr/lib/libwanbootutil.so.1 208 | usr/lib/libwanboot.so.1 209 | usr/lib/libidn.so.11 210 | usr/lib/libidn.so.11.6.13 211 | usr/lib/libmapmalloc.so.1 212 | usr/lib/libcrypto.so.1.0.0 213 | usr/lib/libssl.so.1.0.0 214 | usr/share/lib/xml/dtd/service_bundle.dtd.1 215 | usr/share/lib/termcap 216 | var/sadm/install/admin/default 217 | var/sadm/system/admin/default_java 218 | var/sadm/install/contents 219 | var/adm/utmpx 220 | var/adm/wtmpx 221 | var/adm/aculog 222 | var/log/authlog 223 | var/log/syslog 224 | var/run 225 | var/spool/cron/crontabs/adm 226 | var/spool/cron/crontabs/root 227 | var/yp/aliases 228 | var/yp/nicknames 229 | 230 | usr/lib/fm/libtopo.so.1 231 | usr/lib/fm/amd64/libtopo.so.1 232 | usr/lib/fm/libfmd_agent.so.1 233 | 234 | usr/lib/libipmi.so.1 235 | usr/lib/amd64/libipmi.so.1 236 | usr/lib/libcurl.so.4 237 | usr/lib/libcurl.so.4.3.0 238 | usr/lib/libgss.so.1 239 | 240 | usr/lib/libpkcs11.so.1 241 | usr/lib/amd64/libpkcs11.so.1 242 | usr/lib/fm/topo/plugins/fac_prov_ipmi.so 243 | usr/lib/fm/topo/plugins/disk.so 244 | 245 | usr/lib/fm/topo/plugins/xfp.so 246 | 247 | usr/lib/fm/topo/plugins/ses.so 248 | usr/lib/fm/topo/plugins/ipmi.so 249 | usr/lib/fm/topo/maps/xfp-hc-topology.xml 250 | usr/platform/i86pc/lib/fm/topo/plugins/x86pi.so 251 | usr/platform/i86pc/lib/fm/topo/plugins/pcibus.so 252 | usr/platform/i86pc/lib/fm/topo/plugins/chip.so 253 | usr/platform/i86pc/lib/fm/topo/plugins/hostbridge.so 254 | usr/platform/i86pc/lib/fm/topo/maps/i86pc-hc-topology.xml 255 | usr/platform/i86pc/lib/fm/topo/maps/i86pc-legacy-hc-topology.xml 256 | usr/platform/i86pc/lib/fm/topo/maps/chassis-hc-topology.xml 257 | usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4600-M2-disk-hc-topology.xml 258 | usr/platform/i86pc/lib/fm/topo/maps/chip-hc-topology.xml 259 | usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4500-disk-hc-topology.xml 260 | usr/platform/i86pc/lib/fm/topo/maps/Netra-X4200-M2-disk-hc-topology.xml 261 | usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-Server-disk-hc-topology.xml 262 | usr/platform/i86pc/lib/fm/topo/maps/psu-hc-topology.xml 263 | usr/platform/i86pc/lib/fm/topo/maps/fan-hc-topology.xml 264 | usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-M2-disk-hc-topology.xml 265 | usr/platform/i86pc/lib/fm/topo/maps/SUN-FIRE-X4270-M2-SERVER-disk-hc-topology.xml 266 | usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4540-disk-hc-topology.xml 267 | usr/share/lib/xml/dtd/topology.dtd.1 268 | 269 | 270 | usr/bin/su 271 | usr/lib/libproject.so.1 272 | usr/lib/security/pam_authtok_get.so.1 273 | usr/lib/security/pam_dhkeys.so.1 274 | usr/lib/security/pam_unix_cred.so.1 275 | usr/lib/security/pam_unix_auth.so.1 276 | usr/lib/security/pam_dial_auth.so.1 277 | 278 | -------------------------------------------------------------------------------- /distr/firefly_pkg_img_mod.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # CDDL HEADER START 4 | # 5 | # The contents of this file are subject to the terms of the 6 | # Common Development and Distribution License (the "License"). 7 | # You may not use this file except in compliance with the License. 8 | # 9 | # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 | # or http://www.opensolaris.org/os/licensing. 11 | # See the License for the specific language governing permissions 12 | # and limitations under the License. 13 | # 14 | # When distributing Covered Code, include this CDDL HEADER in each 15 | # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 | # If applicable, add the following below this CDDL HEADER, with the 17 | # fields enclosed by brackets "[]" replaced with your own identifying 18 | # information: Portions Copyright [yyyy] [name of copyright owner] 19 | # 20 | # CDDL HEADER END 21 | # 22 | 23 | # 24 | # Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 25 | # Copyright 2015 Nexenta Systems, Inc. All rights reserved. 26 | 27 | """ pkg_img_mod 28 | 29 | Customizations to the package image area after the boot archive 30 | has been created 31 | 32 | """ 33 | import os 34 | import platform 35 | import shutil 36 | 37 | from osol_install.install_utils import dir_size, file_size 38 | from solaris_install import CalledProcessError, DC_LABEL, Popen, run 39 | from solaris_install.data_object.data_dict import DataObjectDict 40 | from solaris_install.engine import InstallEngine 41 | from solaris_install.engine.checkpoint import AbstractCheckpoint as Checkpoint 42 | from solaris_install.transfer.info import Software, Source, Destination, \ 43 | CPIOSpec, Dir 44 | from solaris_install.transfer.media_transfer import TRANSFER_MEDIA, \ 45 | INSTALL_TARGET_VAR, MEDIA_DIR_VAR, TRANSFER_MANIFEST_NAME, \ 46 | TRANSFER_MISC 47 | from solaris_install.manifest.writer import ManifestWriter 48 | 49 | # load a table of common unix cli calls 50 | import solaris_install.distro_const.cli as cli 51 | cli = cli.CLI() 52 | 53 | 54 | class PkgImgMod(Checkpoint): 55 | """ PkgImgMod - class to modify the pkg_image directory after the boot 56 | archive is built. 57 | """ 58 | 59 | DEFAULT_ARG = {"compression_type": "gzip"} 60 | VALID_COMPRESSION = ["gzip", "lzma"] 61 | 62 | def __init__(self, name, arg=DEFAULT_ARG): 63 | super(PkgImgMod, self).__init__(name) 64 | self.compression_type = arg.get("compression_type", 65 | self.DEFAULT_ARG.get("compression_type")) 66 | 67 | if self.compression_type not in self.VALID_COMPRESSION: 68 | raise RuntimeError("invalid compression_type: " + 69 | self.compression_type) 70 | 71 | self.dist_iso_sort = arg.get("dist_iso_sort") 72 | 73 | # instance attributes 74 | self.doc = None 75 | self.dc_dict = {} 76 | self.pkg_img_path = None 77 | self.ba_build = None 78 | self.tmp_dir = None 79 | 80 | def get_progress_estimate(self): 81 | """Returns an estimate of the time this checkpoint will take""" 82 | return 415 83 | 84 | def parse_doc(self): 85 | """ class method for parsing data object cache (DOC) objects for use by 86 | the checkpoint. 87 | """ 88 | self.doc = InstallEngine.get_instance().data_object_cache 89 | self.dc_dict = self.doc.volatile.get_children(name=DC_LABEL, 90 | class_type=DataObjectDict)[0].data_dict 91 | 92 | try: 93 | self.pkg_img_path = self.dc_dict["pkg_img_path"] 94 | self.tmp_dir = self.dc_dict["tmp_dir"] 95 | self.ba_build = self.dc_dict["ba_build"] 96 | except KeyError, msg: 97 | raise RuntimeError("Error retrieving a value from the DOC: " + 98 | str(msg)) 99 | 100 | def strip_root(self): 101 | """ class method to clean up the root of the package image path 102 | """ 103 | if not os.path.isdir(self.pkg_img_path): 104 | raise RuntimeError("Package Image path " + self.pkg_img_path + 105 | " is not valid") 106 | 107 | # Copy the volsetid to the root of the image 108 | shutil.copy(os.path.join(self.ba_build, ".volsetid"), 109 | self.pkg_img_path) 110 | 111 | # Remove the password lock file left around from user actions 112 | # during package installation; if left in place it becomes a 113 | # symlink into /mnt/misc which causes installer's attempt to 114 | # create a user account to fail 115 | if os.path.exists(os.path.join(self.pkg_img_path, 116 | "etc/.pwd.lock")): 117 | os.remove(self.pkg_img_path + "/etc/.pwd.lock") 118 | 119 | os.chdir(self.pkg_img_path) 120 | 121 | # sbin, kernel and lib are contained within the boot_archive 122 | # Thus, not needed in the pkg_image area 123 | self.logger.info("Removing sbin, kernel and lib from " + 124 | "pkg_image area") 125 | shutil.rmtree("sbin", ignore_errors=True) 126 | shutil.rmtree("kernel", ignore_errors=True) 127 | shutil.rmtree("lib", ignore_errors=True) 128 | os.unlink("bin") 129 | shutil.rmtree("usr", ignore_errors=True) 130 | shutil.rmtree("sbin", ignore_errors=True) 131 | shutil.rmtree("etc", ignore_errors=True) 132 | shutil.rmtree("home", ignore_errors=True) 133 | shutil.rmtree("tmp", ignore_errors=True) 134 | shutil.rmtree("jack", ignore_errors=True) 135 | shutil.rmtree("system", ignore_errors=True) 136 | shutil.rmtree("opt", ignore_errors=True) 137 | shutil.rmtree("root", ignore_errors=True) 138 | shutil.rmtree("proc", ignore_errors=True) 139 | shutil.rmtree("export", ignore_errors=True) 140 | shutil.rmtree("dev", ignore_errors=True) 141 | shutil.rmtree("devices", ignore_errors=True) 142 | shutil.rmtree("var", ignore_errors=True) 143 | shutil.rmtree("save", ignore_errors=True) 144 | shutil.rmtree("mnt", ignore_errors=True) 145 | os.unlink("reconfigure") 146 | 147 | 148 | def strip_x86_platform(self): 149 | """ class method to clean up the package image path for x86 systems 150 | """ 151 | # save the current working directory 152 | cwd = os.getcwd() 153 | 154 | os.chdir(os.path.join(self.pkg_img_path, "platform")) 155 | # walk the directory tree and remove anything other than the kernel 156 | # and boot_archive files 157 | for (root, _none, files) in os.walk("."): 158 | for f in files: 159 | if f == "unix" or f == "boot_archive": 160 | continue 161 | else: 162 | self.logger.debug("removing " + os.path.join(root, f)) 163 | os.unlink(os.path.join(root, f)) 164 | 165 | # copy the platform directory to /boot since grub does not understand 166 | # symlinks 167 | os.chdir(self.pkg_img_path) 168 | shutil.copytree(os.path.join(self.pkg_img_path, "platform"), 169 | os.path.join(self.pkg_img_path, "boot/platform"), 170 | symlinks=True) 171 | 172 | os.chdir(cwd) 173 | 174 | def strip_sparc_platform(self): 175 | """ class method to clean up the package image path for sparc systems 176 | """ 177 | os.chdir(os.path.join(self.pkg_img_path, "platform")) 178 | # walk the directory tree and remove anything other than wanboot 179 | # and boot_archive files 180 | for (root, _none, files) in os.walk("."): 181 | for f in files: 182 | if f == "wanboot" or f == "boot_archive": 183 | continue 184 | else: 185 | self.logger.debug("removing " + os.path.join(root, f)) 186 | os.unlink(os.path.join(root, f)) 187 | 188 | # symlink the platform directory in boot: 189 | # boot/platform -> ../platform 190 | os.chdir(self.pkg_img_path) 191 | os.symlink(os.path.join("..", "platform"), 192 | os.path.join(self.pkg_img_path, "boot/platform")) 193 | 194 | def add_content_list_to_doc(self, content_list): 195 | src_path = Dir(MEDIA_DIR_VAR) 196 | src = Source() 197 | src.insert_children(src_path) 198 | 199 | dst_path = Dir(INSTALL_TARGET_VAR) 200 | dst = Destination() 201 | dst.insert_children(dst_path) 202 | 203 | media_install = CPIOSpec() 204 | media_install.action = CPIOSpec.INSTALL 205 | media_install.contents = content_list 206 | total_size_byte = 0 207 | for content in content_list: 208 | content_path = os.path.join(self.pkg_img_path, content) 209 | # only want to calculate the size of files, since directories 210 | # are traversed and it's files are included in the list. 211 | if not os.path.isdir(content_path): 212 | total_size_byte += file_size(content_path) 213 | media_install.size = str(total_size_byte) 214 | 215 | media_soft_node = Software(TRANSFER_MEDIA, type="CPIO") 216 | media_soft_node.insert_children([src, dst, media_install]) 217 | 218 | # Add that into the software transfer list. 219 | self.doc.persistent.insert_children(media_soft_node) 220 | 221 | # call manifest writer to write out the content of 222 | # the transfer manifest 223 | manifest_out = os.path.join(self.pkg_img_path, TRANSFER_MANIFEST_NAME) 224 | xslt_name = os.path.join(os.path.dirname(os.path.abspath(__file__)), 225 | "xslt", "doc2_media_transfer.xslt") 226 | manifest_writer = ManifestWriter("manifest-writer", 227 | manifest_out, xslt_file=xslt_name) 228 | manifest_writer.write(self.doc) 229 | 230 | def populate_livecd_content(self): 231 | """ class method to populate content of live media's root into DOC 232 | """ 233 | # save the current working directory 234 | cwd = os.getcwd() 235 | 236 | # change to the pkg_img_path 237 | os.chdir(self.pkg_img_path) 238 | 239 | content_list = [] 240 | for root, dirs, files in os.walk("."): 241 | for f in files: 242 | if not f.endswith(".zlib") and not f.endswith(".image_info") \ 243 | and not f.endswith("boot_archive") and not \ 244 | f.endswith(".media-transfer.xml"): 245 | content_list.append(os.path.join(root, f)) 246 | for d in dirs: 247 | content_list.append(os.path.join(root, d)) 248 | 249 | self.add_content_list_to_doc(content_list) 250 | 251 | os.chdir(cwd) 252 | 253 | def populate_save_list(self): 254 | '''Store a list of files under the 'save' directory. Net-booted 255 | text installer uses this list to determine what files it needs from 256 | the boot server 257 | ''' 258 | save_files = [] 259 | save_dir = os.path.join(self.pkg_img_path, "save") 260 | for root, _none, files in os.walk(save_dir): 261 | for f in files: 262 | relpath = os.path.relpath(os.path.join(root, f), 263 | start=self.pkg_img_path) 264 | save_files.append(relpath) 265 | 266 | self.add_content_list_to_doc(save_files) 267 | 268 | def execute(self, dry_run=False): 269 | """Customize the pkg_image area. Assumes that a populated pkg_image 270 | area exists and that the boot_archive has been built 271 | dry_run is not used in DC 272 | """ 273 | self.logger.info("=== Executing Pkg Image Modification Checkpoint ===") 274 | 275 | self.parse_doc() 276 | 277 | # clean up the root of the package image path 278 | self.strip_root() 279 | 280 | 281 | class TextPkgImgMod(PkgImgMod, Checkpoint): 282 | """ TextPkgImgMod - class to modify the pkg_image directory after the boot 283 | archive is built for Text media 284 | """ 285 | 286 | DEFAULT_ARG = {"compression_type": "gzip"} 287 | 288 | def __init__(self, name, arg=DEFAULT_ARG): 289 | super(TextPkgImgMod, self).__init__(name, arg) 290 | 291 | def execute(self, dry_run=False): 292 | """ Customize the pkg_image area. Assumes that a populated pkg_image 293 | area exists and that the boot_archive has been built 294 | """ 295 | self.logger.info("=== Executing Pkg Image Modification Checkpoint ===") 296 | 297 | self.parse_doc() 298 | 299 | # clean up the root of the package image path 300 | self.strip_root() 301 | 302 | # get the platform of the system 303 | arch = platform.processor() 304 | 305 | # save the current working directory 306 | cwd = os.getcwd() 307 | try: 308 | # clean up the package image path based on the platform 309 | if arch == "i386": 310 | self.strip_x86_platform() 311 | else: 312 | self.strip_sparc_platform() 313 | 314 | 315 | # populate live cd's content into DOC 316 | #self.populate_save_list() 317 | finally: 318 | # return to the initial directory 319 | os.chdir(cwd) 320 | 321 | -------------------------------------------------------------------------------- /firefly.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 36 | 37 | 41 | 42 | 43 | 44 | 54 | 55 | 85 | 89 | 90 | 91 | 92 | 93 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 108 | 116 | 117 | 118 | 120 | 121 | 122 | 123 | 124 | 127 | 130 | 131 | 132 | 135 | 142 | 143 | 153 | 154 | pkg:/entire@latest 155 | pkg:/system/install/text-install@latest 156 | pkg:/system/library/install@latest 157 | pkg:/system/install/media/internal@latest 158 | pkg:/system/install/configuration@latest 159 | pkg:/system/install@latest 160 | pkg:/service/storage/media-volume-manager 161 | 162 | 163 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 179 | 180 | 182 | 189 | 190 | 191 | 194 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 206 | 207 | kernel 208 | boot 209 | platform 210 | system 211 | lib 212 | dev 213 | devices 214 | usr/lib/devfsadm/linkmod 215 | root 216 | jack 217 | sbin/ibd_delete_link 218 | sbin/ibd_upgrade 219 | var/svc/manifest 220 | var/svc/profile 221 | var/sadm 222 | etc 223 | 224 | 225 | etc/gconf 226 | etc/brltty 227 | etc/gtk-2.0 228 | etc/notices 229 | var/sadm/pkg 230 | 231 | 232 | 236 | 237 | 241 | 242 | true 243 | 244 | 245 | 249 | 253 | 256 | 260 | 261 | 262 | true 263 | 264 | firefly 265 | 266 | 267 | 268 | 272 | 276 | 277 | 281 | 291 | 292 | gzip 293 | 9 294 | 0 295 | 0 296 | 297 | 298 | 302 | 306 | 311 | 312 | 313 | /usr/share/distro_const/sort/text_x86.sort 314 | lzma 315 | 316 | 317 | 321 | 322 | 327 | 328 | 329 | 334 | 336 | 337 | 338 | 340 | 341 | 342 | 344 | 345 | 346 | 348 | 349 | 350 | 351 | 352 | -------------------------------------------------------------------------------- /iso/checkrpool: -------------------------------------------------------------------------------- 1 | #!/bin/ksh 2 | 3 | # Discover and mount root pool to /a 4 | # Copyright 2015 Nexenta Systems, Inc. All rights reserved. 5 | 6 | rpool_mount() 7 | { 8 | pool=$1 9 | id=$2 10 | 11 | echo "Mounting pool:$pool with guid:$id to /a" 12 | zpool import -f -N -R /a $id > /dev/null 2>&1 13 | zpool list $pool > /dev/null 2>&1 14 | [[ $? == 0 ]] || ( echo "Can't import $pool" && return ) 15 | bootfs=$(zpool get bootfs $pool | grep bootfs | nawk '{ print $3 }') 16 | echo "Mounting $bootfs to /a" 17 | zfs mount $bootfs 18 | [[ $? == 0 ]] || ( echo "Can't mount $bootfs" && return ) 19 | 20 | } 21 | 22 | poolnum=0 23 | pools= 24 | 25 | rootpool > /tmp/rootpool 2>&1 26 | 27 | cat /tmp/rootpool | while read line ; do 28 | if echo $line | egrep "^[a-zA-Z0-9_.-]+;.*" >/dev/null; then 29 | poolnum=`expr $poolnum + 1` 30 | name=$(echo $line | nawk '{ split ($0,a,";"); print a[1] }') 31 | id=$(echo $line | nawk '{ split ($0,a,";"); print a[2] }') 32 | pools="$pools $name:$id" 33 | fi 34 | done 35 | 36 | if [ "$poolnum" -eq 0 ]; then 37 | echo "No operating system found, exiting to shell" 38 | elif [ "$poolnum" -eq 1 ]; then 39 | name=$(echo ${pools%%:*}) 40 | id=$(echo ${pools##*:}) 41 | echo "Found installed operating system at pool:$name" 42 | rpool_mount $name $id 43 | else 44 | echo "Found multiple operating system instances:" 45 | choice=$(ckitem -p "To select which root pool to import, enter a number" ${pools[*]}) 46 | name=$(echo ${choice%%:*}) 47 | id=$(echo ${choice##*:}) 48 | rpool_mount $name $id 49 | fi 50 | -------------------------------------------------------------------------------- /iso/nodename: -------------------------------------------------------------------------------- 1 | firefly 2 | 3 | -------------------------------------------------------------------------------- /iso/nonglobal.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alhazred/firefly/f62b72d0df3d66a1c97d0c333c3c385e5cc1d878/iso/nonglobal.db -------------------------------------------------------------------------------- /iso/rootpool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alhazred/firefly/f62b72d0df3d66a1c97d0c333c3c385e5cc1d878/iso/rootpool -------------------------------------------------------------------------------- /iso/smf/console-login: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2015 Nexenta Systems, Inc. All rights reserved. 4 | 5 | TERM=sun-color 6 | USER=root 7 | HOME=/root 8 | PATH=/sbin:/usr/sbin:/usr/bin 9 | TERMINFO=/usr/share/lib/terminfo 10 | EDITOR=vi 11 | SHELL=bash 12 | PAGER='/usr/bin/less -ins' 13 | PS1="\e[0;32m\u@\h# \e[m" 14 | 15 | export TERM USER HOME PATH TERMINFO EDITOR SHELL PAGER PS1 16 | 17 | /usr/sbin/checkrpool 18 | 19 | /sbin/sulogin 20 | -------------------------------------------------------------------------------- /iso/smf/fs-root: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | . /lib/svc/share/smf_include.sh 4 | . /lib/svc/share/fs_include.sh 5 | 6 | 7 | # Make sure that the libraries essential to this stage of booting can be found. 8 | LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH 9 | 10 | libc_mount() { 11 | # 12 | # If there is an optimized libc available in /usr that fits this 13 | # processor, mount it on top of the base libc. 14 | # 15 | LIBC_MOE_32=`/usr/bin/moe -32 '/usr/lib/libc/$HWCAP'` 16 | if [ -n "$LIBC_MOE_32" ]; then 17 | /usr/sbin/mount | egrep -s "^/lib/libc.so.1 on " 18 | if [ $? -ne 0 ]; then 19 | /usr/sbin/mount -O -F lofs $LIBC_MOE_32 /lib/libc.so.1 20 | fi 21 | fi 22 | 23 | ARCH64=`isainfo | awk '{print $1}'` 24 | LIBC_MOE_64=`/usr/bin/moe -64 /usr/lib/$ARCH64/libc/'$HWCAP'` 25 | if [ -n "$LIBC_MOE_64" ]; then 26 | /usr/sbin/mount | egrep -s "^/lib/$ARCH64/libc.so.1 on " 27 | if [ $? -ne 0 ]; then 28 | /usr/sbin/mount -O -F lofs $LIBC_MOE_64 \ 29 | /lib/$ARCH64/libc.so.1 30 | fi 31 | fi 32 | } 33 | 34 | # 35 | # Update kernel driver.conf cache with any additional driver.conf 36 | # files found on /usr, and device permissions from /etc/minor_perm. 37 | # 38 | /usr/sbin/devfsadm -I -P 39 | 40 | libc_mount 41 | 42 | # Remount root RW 43 | # 44 | echo "\rRemounting root read/write" > /dev/msglog 45 | # x86 label 46 | /sbin/mount -o remount,rw /devices/ramdisk:a / 47 | 48 | # 49 | # Workaround for devfs lazy init. The sd nodes are not 50 | # created till you try to access them. 51 | # 52 | echo "Probing for device nodes ..." > /dev/msglog 53 | 54 | ls -lR /devices/* > /dev/null 55 | 56 | exit $SMF_EXIT_OK 57 | -------------------------------------------------------------------------------- /iso/smf/manifest-import: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | exit 0 3 | 4 | -------------------------------------------------------------------------------- /iso/sulogin: -------------------------------------------------------------------------------- 1 | PASSREQ=NO 2 | -------------------------------------------------------------------------------- /rootpool/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -Wall -o rootpool rootpool.c -lzfs -lnvpair 3 | -------------------------------------------------------------------------------- /rootpool/rootpool.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file and its contents are supplied under the terms of the 3 | * Common Development and Distribution License ("CDDL"), version 1.0. 4 | * You may only use this file in accordance with the terms of version 5 | * 1.0 of the CDDL. 6 | * 7 | * A full copy of the text of the CDDL should have accompanied this 8 | * source. A copy of the CDDL is also available via the Internet at 9 | * http://www.illumos.org/license/CDDL. 10 | * 11 | * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 12 | * 13 | * This hook tries disks for the pool with bootfs property and print 14 | * its name, guid, state and bootfs: 15 | * rpool;9213225939923529766;ONLINE;rpool/ROOT/illumos 16 | */ 17 | 18 | #include 19 | 20 | int 21 | main(int argc, char **argv) 22 | { 23 | char **searchdirs = NULL; 24 | nvlist_t *pools = NULL; 25 | nvpair_t *elem; 26 | nvlist_t *config; 27 | uint64_t searchguid = 0; 28 | char *searchname = NULL; 29 | char *cachefile = NULL; 30 | importargs_t pdata = { 0 }; 31 | libzfs_handle_t *g_zfs; 32 | vdev_stat_t *vs; 33 | char *name; 34 | uint64_t guid; 35 | nvlist_t *nvroot; 36 | const char *health; 37 | uint_t vsc; 38 | char *bootfs; 39 | 40 | if ((g_zfs = libzfs_init()) == NULL) 41 | return (1); 42 | 43 | if ((searchdirs = calloc(1, sizeof (char *))) == NULL) 44 | return (1); 45 | 46 | searchdirs[0] = "/dev/dsk"; 47 | pdata.path = searchdirs; 48 | pdata.paths = 1; 49 | pdata.poolname = searchname; 50 | pdata.guid = searchguid; 51 | pdata.cachefile = cachefile; 52 | 53 | pools = zpool_search_import(g_zfs, &pdata); 54 | if (pools == NULL) { 55 | free(searchdirs); 56 | return (1); 57 | } 58 | 59 | elem = NULL; 60 | while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 61 | verify(nvpair_value_nvlist(elem, &config) == 0); 62 | verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 63 | &name) == 0); 64 | verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 65 | &guid) == 0); 66 | verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 67 | &nvroot) == 0); 68 | verify(nvlist_lookup_uint64_array(nvroot, 69 | ZPOOL_CONFIG_VDEV_STATS, 70 | (uint64_t **)&vs, &vsc) == 0); 71 | if (nvlist_lookup_string(config, ZPOOL_CONFIG_BOOTFS, 72 | &bootfs) != 0) 73 | continue; 74 | 75 | health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 76 | (void) printf("%s;%llu;%s;%s\n", name, 77 | (u_longlong_t)guid, health, bootfs); 78 | } 79 | nvlist_free(pools); 80 | free(searchdirs); 81 | return (0); 82 | } 83 | --------------------------------------------------------------------------------