#!/usr/bin/python # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # import sys import os import getopt import subprocess import commands import time import tempfile import string def disk_get_size(disk): command = ['/usr/sbin/fdisk', '-g', '/dev/rdsk/' + disk + 'p0'] try: p = subprocess.Popen(command, stdin=open("/dev/null"), stdout=subprocess.PIPE, stderr=open("/dev/null")) rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to run fdisk" return None except: print >> sys.stderr, "ERROR: unable to run fdisk" return None output = p.stdout for line in output: list = line.lstrip(" \t").rstrip(" \n\t\r").split() if len(list) < 7: continue try: if list[0] == "*": continue # PCYL NCYL ACYL BCYL NHEAD NSECT SECSIZ # diskSize = NCYL * NHEAD * NSECT * SECSIZ diskSize = int(list[1]) * int(list[4]) * int(list[5]) * int(list[6]) break except: continue return diskSize def disk_get_all(): diskDimensions={} diskList=[] disk=[] command = ['/usr/sbin/format'] try: p = subprocess.Popen(command, stdin=open("/dev/null"), stdout=subprocess.PIPE, stderr=open("/dev/null")) # ignore return value for wait() p.wait() except: print >> sys.stderr, "ERROR: unable to run format" return None output = p.stdout for line in output: list = line.lstrip(" \t").rstrip(" \n\t\r").split(" ") if len(list) < 2: continue try: diskNum = int(list[0].rstrip(".")) except: diskNum = -1 if diskNum != -1: disk = [diskNum, list[1], disk_get_size(list[1])] diskList.append(disk) return diskList def disk_get(): diskList=[] diskList = disk_get_all() if diskList == None: print >> sys.stderr, "ERROR: no disks found" return None waitForSelection = True while waitForSelection: print >> sys.stdout, "Please Select Install Disk\n" print >> sys.stdout, " AVAILABLE DISK SELECTIONS:" for disk in diskList: print >> sys.stdout, "\t" + str(disk[0]) + "." + " /dev/dsk/" + disk[1] + "p0 " + str(disk[2]) + " bytes" selection=raw_input("Specify disk (enter its number or 'q' to quit): ") if selection == "q": print >> sys.stdout, "\n\n" return None try: diskNum = int(selection) except: print >> sys.stdout, "\n ERROR: invalid disk selection\n" continue for disk in diskList: if (diskNum == disk[0]): waitForSelection = False break if waitForSelection: print >> sys.stdout, "\n ERROR: invalid disk selection\n" print >> sys.stdout, "\nNOTE: ALL DATA ON THIS DISK WILL BE DESTROYED.\n" waitForSelection = True while waitForSelection: selection=raw_input("Install on /dev/rdsk/" + disk[1] + "p0 (yes or no): ") if selection == "no": print >> sys.stdout, "\n\n" return None if selection == "yes": waitForSelection = False continue print >> sys.stdout, "\nYou must type is yes or no\n" return disk[1] def disk_get_default_label(disk): command = ['/usr/sbin/fdisk', '-g', '/dev/rdsk/' + disk + 'p0'] try: p = subprocess.Popen(command, stdin=open("/dev/null"), stdout=subprocess.PIPE, stderr=open("/dev/null")) rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to run fdisk" return None except: print >> sys.stderr, "ERROR: unable to run fdisk" return None output = p.stdout sectorCount = -1 for line in output: list = line.lstrip(" \t").rstrip(" \n\t\r").split() if len(list) < 7: continue try: if list[0] == "*": continue # PCYL NCYL ACYL BCYL NHEAD NSECT SECSIZ sectorsPerCylinder = int(list[5]) * int(list[4]) sectorCount = sectorsPerCylinder * int(list[1]) break except: continue if (sectorCount == -1): print >> sys.stderr, "ERROR: internal error building label" return None label = "0 2 00 " + str(sectorsPerCylinder) + " " + str(sectorCount - sectorsPerCylinder) + " " + str(sectorCount -1) + "\n" + \ "2 5 00 0 " + str(sectorCount) + " " + str(sectorCount -1) + "\n" + \ "8 1 01 0 " + str(sectorsPerCylinder) + " " + str(sectorsPerCylinder - 1) + "\n" return label def disk_fdisk_format(disk): rawDisk = '/dev/rdsk/' + disk + 'p0' command = ['/usr/sbin/fdisk', '-n', '-B', rawDisk] try: p = subprocess.Popen(command, stdin=open("/dev/null"), stdout=open("/dev/null"), stderr=open("/dev/null")) rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to fdisk" return False except: print >> sys.stderr, "ERROR: unable to fdisk" return False label = disk_get_default_label(disk) if (label == None): return False command = ['/usr/sbin/fmthard', '-s', '-', rawDisk] try: p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=open("/dev/null"), stderr=open("/dev/null")) p.stdin.write(label) p.stdin.close() rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to format disk" return False except: print >> sys.stderr, "ERROR: unable to format disk" return False return True def create_zfs_root(disk, swapSize=512, dumpSize=512): diskDev = "/dev/dsk/" + disk + "s0" mountDir = tempfile.mkdtemp() cmdList = [ "/usr/sbin/zpool create -R " + mountDir + " -f rpool " + diskDev, "/usr/sbin/zfs umount rpool", "/usr/sbin/zfs create rpool/ROOT", "/usr/sbin/zfs set mountpoint=legacy rpool/ROOT", \ "/usr/sbin/zfs set canmount=off rpool/ROOT", \ "/usr/sbin/zfs create rpool/ROOT/opensolaris", \ "/usr/sbin/zfs set canmount=noauto rpool/ROOT/opensolaris", \ "/usr/sbin/zfs set mountpoint='/' rpool/ROOT/opensolaris", \ "/usr/sbin/zfs mount rpool/ROOT/opensolaris", \ "/usr/sbin/zfs set mountpoint='/rpool' rpool", \ "/usr/sbin/zfs mount rpool", \ "/usr/sbin/zpool set bootfs='rpool/ROOT/opensolaris' rpool", \ "/usr/sbin/zfs create rpool/export", \ "/usr/sbin/zfs set mountpoint='/export' rpool/export", ] if swapSize > 0: cmdList.append("/usr/sbin/zfs create -b 4k -V " + str(swapSize) + "m rpool/swap") if dumpSize > 0: cmdList.append("/usr/sbin/zfs create -b 128k -V " + str(dumpSize) + "m rpool/dump") sys.stdout.write("Configuring ZFS Root:") sys.stdout.flush() for cmd in cmdList: sys.stdout.write(".") sys.stdout.flush() (s, o) = commands.getstatusoutput(cmd) if (s != 0): print >> sys.stderr, "ERROR: Failure in ", cmd return None print >> sys.stdout, " COMPLETE" return mountDir def get_package_list(profile): xvm_min = [ "entire", "SUNWcsd", "SUNWcs", "SUNWcarx", "SUNWcakrx", "SUNWos86r", "SUNWkvm", "SUNWrmodr", "SUNWpsdcr", "SUNWpsdir", "SUNWcnetr", "SUNWesu", "SUNWkey", "SUNWuprl", "SUNWkrb", "SUNWbip", "SUNWzfskr", "SUNWbash", "SUNWipf", "SUNWgrub", "SUNWtoo", "SUNWbind", "SUNWrcmdc", "SUNWmkcd", "SUNWPython", "SUNWPython-extra", "SUNWipkg", "SUNWinstall", "SUNWbeadm", "SUNWadmap", "SUNWadmlib-sysid", "SUNWadmr"] vbox_min = [ "entire", "SUNWcsd", "SUNWcs", "SUNWcar", "SUNWcakr", "SUNWos86r", "SUNWkvm", "SUNWrmodr", "SUNWpsdcr", "SUNWpsdir", "SUNWcnetr", "SUNWesu", "SUNWkey", "SUNWuprl", "SUNWkrb", "SUNWbip", "SUNWzfskr", "SUNWbash", "SUNWipf", "SUNWgrub", "SUNWtoo", "SUNWbind", "SUNWrcmdc", "SUNWmkcd", "SUNWPython", "SUNWPython-extra", "SUNWipkg", "SUNWinstall", "SUNWbeadm", "SUNWadmap", "SUNWadmlib-sysid", "SUNWadmr", "SUNWintgige", "SUNWahci", "SUNWpsdcr", "SUNWpsdpr", "SUNWos86r", "SUNWusb"] slim = [ "entire", "SUNWcsd", "slim_install"] if profile == "xvm-guest": return xvm_min if profile == "vbox-guest": return vbox_min if profile == "slim": return slim return None def install_packages(mountDir, profile="minimal-xvm-guest", repo="http://pkg.opensolaris.org/"): print >> sys.stdout, "Installing packages..." command = ['/bin/pkg', 'image-create', '-f', '-F', '-a', 'opensolaris.org=' + repo, mountDir] try: p = subprocess.Popen(command) rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to setup repo" return None except: print >> sys.stderr, "ERROR: unable to setup repo" return None pkgList = get_package_list(profile) if pkgList == None: print >> sys.stderr, "ERROR: Invalid profile: ", profile return False command = ['/bin/pkg', '-R', mountDir, 'install'] + pkgList try: p = subprocess.Popen(command) rc = p.wait() if rc != 0: print >> sys.stderr, "ERROR: unable to install packages" return None except: print >> sys.stderr, "ERROR: unable to install packages" return None print >> sys.stdout, " COMPLETE" return True def configure_root(mountDir, disk, swap): diskDev = "/dev/rdsk/" + disk + "s0" cmdList = [ "/bin/rm -rf " + mountDir + "/var/pkg/download/*", "/usr/bin/cp " + mountDir + "/lib/svc/seed/global.db " + mountDir + "/etc/svc/repository.db", "/bin/chown root:sys " + mountDir + "/etc/svc/repository.db", "/bin/chmod 600 " + mountDir + "/etc/svc/repository.db", "/usr/sbin/devfsadm -R " + mountDir, "/bin/mkdir -p " + mountDir + "/rpool/boot/grub/bootsign", "/bin/mkdir -p " + mountDir + "/rpool/etc", "/bin/touch " + mountDir + "/rpool/boot/grub/bootsign/pool_rpool", "/bin/cp " + mountDir + "/boot/grub/capability " + mountDir + "/rpool/boot/grub/", "/sbin/installgrub " + mountDir + "/boot/grub/stage1 " + mountDir + "/boot/grub/stage2 " + diskDev, "/bin/touch " + mountDir + "/etc/.UNCONFIGURED", ] sys.stdout.write("Configuring OS:") sys.stdout.flush() for cmd in cmdList: sys.stdout.write(".") sys.stdout.flush() (s, o) = commands.getstatusoutput(cmd) if (s != 0): print >> sys.stderr, "ERROR: Failure in ", cmd return False if swap: vfstabSwap = "/dev/zvol/dsk/rpool/swap - - swap - no" f = open(mountDir + "/etc/vfstab", "a") f.write(vfstabSwap) f.close() f = open(mountDir + "/rpool/etc/bootsign\n", "w") f.write("pool_rpool") f.close() sysid = "/lib/svc/method/sshd\n" +\ "/usr/sbin/sysidkbd\n" +\ "/usr/sbin/sysidpm\n" +\ "/lib/svc/method/net-nwam\n" +\ "/usr/lib/cc-ccr/bin/eraseCCRRepository\n" f = open(mountDir + "/etc/.sysidconfig.apps", "w") f.write(sysid) f.close() grubMenu = "default 0\n\n" +\ "title OpenSolaris 2009.06\n" +\ "findroot (pool_rpool,0,a)\n" +\ "bootfs rpool/ROOT/opensolaris\n" +\ "kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS\n" +\ "module$ /platform/i86pc/$ISADIR/boot_archive\n" f = open(mountDir + "/rpool/boot/grub/menu.lst", "w") f.write(grubMenu) f.close() origCwd = os.getcwd() os.chdir(mountDir + "/var/svc/profile/") os.symlink("generic_limited_net.xml", "generic.xml") os.symlink("ns_files.xml", "name_service.xml") os.symlink("inetd_generic.xml", "inetd_services.xml") os.symlink("platform_none.xml", "platform.xml") os.chdir(origCwd) print >> sys.stdout, " COMPLETE" cmdList = [ "/usr/sbin/sys-unconfig -R " + mountDir, "/usr/sbin/bootadm update-archive -R " + mountDir, ] sys.stdout.write("Building boot archive:") sys.stdout.flush() for cmd in cmdList: sys.stdout.write(".") sys.stdout.flush() (s, o) = commands.getstatusoutput(cmd) if (s != 0): print >> sys.stderr, "ERROR: Failure in ", cmd return False print >> sys.stdout, " COMPLETE" return True def usage(): print >> sys.stderr, "\nUSAGE:", sys.argv[0], "[--profile=] [--repo=] [--swap=] [--dump=]\n" # # main() # if __name__ == "__main__": # defaults repo="http://pkg.opensolaris.org/" profile="xvm-guest" swapSize = 512 dumpSize = 512 try: opts, args = getopt.getopt(sys.argv[1:], "", ["profile=", "swap=", "dump=", "repo="]) for o, a in opts: if o == "--profile": profile = a elif o == "--repo": repo = a elif o == "--swap": swapSize = int(a) elif o == "--dump": dumpSize = int(a) else: print >> sys.stdout, o, a usage() sys.exit(-1) except: usage() sys.exit(-1) print >> sys.stdout, "\nThanks for choosing to install the OpenSolaris OS! Before you start, review\nthe Release Notes for this release for a list of known problems. The release\nnotes can be found at\n http://opensolaris.org/os/project/indiana/resources/relnotes/200906/x86\n" print >> sys.stdout, "****\nNOTICE: THIS INSTALLER ONLY SUPPORTS INSTALLING TO A WHOLE DISK. ALL DATA\nON THE DISK YOU INSTALL TO WILL BE DESTROYED.\n****\n" installDisk = disk_get() if installDisk == None: sys.exit(0) if not disk_fdisk_format(installDisk): sys.exit(-1) mountDir = create_zfs_root(installDisk, swapSize=swapSize, dumpSize=dumpSize) if (mountDir == None): sys.exit(-1) if not install_packages(mountDir, profile, repo): sys.exit(-1) if (swapSize > 0): swap = True else: swap = False if not configure_root(mountDir, installDisk, swap): sys.exit(-1) print >> sys.stdout, "*** INSTALL COMPLETE ***"