diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2013-04-07 21:33:26 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2013-04-07 21:33:26 +0000 |
commit | bfb1de5aa23a49b9414c1145c2cd65de2f03b35f (patch) | |
tree | 68a23932e11af4aafac3b08038bd0e4cda3a228d /install | |
parent | 63cb3d4f5f41186d99ebad7d5021f5a61b2aa9e7 (diff) | |
download | live-bfb1de5aa23a49b9414c1145c2cd65de2f03b35f.tar.gz |
Creating rpool
Diffstat (limited to 'install')
-rwxr-xr-x | install | 220 |
1 files changed, 166 insertions, 54 deletions
@@ -1,9 +1,20 @@ #!/usr/bin/python +""" +Written by Igor Pashev <pashev.igor@gmail.com> + +The author has placed this work in the Public Domain, +thereby relinquishing all copyrights. Everyone is free +to use, modify, republish, sell or give away this work +without prior consent from anybody. +""" + from lib.hdd import HDD from snack import * from subprocess import Popen, PIPE, call from pprint import pprint +from tempfile import mkstemp +import os import re import sys @@ -13,14 +24,21 @@ screen = None # List of disks installed on the system: hdds = [] -# Number of HDDs installed on the system: -number_of_disks = 0 +# Name of the root ZFS pool: either existing or newly created +rpool = None -# List of zpools found on the system: -zpools = [] +# Name of the root slice, where ZFS root pool will be created (e. g. c0t0d0s0) +rslice = None + +class Abort(Exception): + ''' User clicked "Cancel" ''' + pass +class NoDisks(Exception): + ''' No Hard Drives found ''' + pass def welcome(): - return ButtonChoiceWindow(screen, "Welcome to Dyson installer", + welcome = ButtonChoiceWindow(screen, "Welcome to the Dyson installer", ''' Dyson is an operating system derived from Debian and based on Illumos core. \ It uses Illumos unix kernel and libc, ZFS file system and SMF to manage system startup. \ @@ -33,21 +51,24 @@ Please note, this system IS VERY EXPERIMENTAL. \ You can LOOSE ALL YOUR DATA which this system can reach ;-) Whould you like to continue?''', - buttons=[('Yes', True), ('No', False)], width=70, help=None) - -def get_imported_zpools(): - zpool_cmd = Popen(['zpool', 'list', '-H', '-o', 'name'], stdout=PIPE) - zpool_list = zpool_cmd.stdout.read().rstrip().split('\n') - return zpool_list - -def get_exported_zpools(): - zpool_cmd = Popen("zpool import | awk '/pool:/ {print $2}'", shell=True, stdout=PIPE) - zpool_list = zpool_cmd.stdout.read().rstrip().split('\n') - return zpool_list + buttons=[('Install Dyson', True), ('Exit the installer', False)], width=70) + if not welcome: + raise Abort('Installation canceled') -def get_hdds(): +def find_zpools(): + global zpools + zpools = [] + zpool_cmd = Popen(['zpool', 'list', '-H', '-o', 'name'], stdout=PIPE, stderr=PIPE) + for line in zpool_cmd.stdout: + zpools.append(line.rstrip()) + zpool_cmd = Popen("zpool import | awk '/pool:/ {print $2}'", shell=True, stdout=PIPE, stderr=PIPE) + for line in zpool_cmd.stdout: + zpools.append(line.rstrip()) + +def find_hdds(): + global hdds hdds = [] - pat = re.compile('\d+\.\s+(\S+)\s+<(\S+)\s*.+>') + pat = re.compile('\d+\.\s+(\S+)\s+<(.+?)(\s+cyl.*)?>') format_cmd = Popen('format </dev/null', shell=True, stdout=PIPE) for line in format_cmd.stdout: m = pat.search(line) @@ -56,38 +77,136 @@ def get_hdds(): desc = m.group(2) hdds.append(HDD(name, desc)) - return hdds +def choose_rpool(): + zpool_items = map(lambda x: (x, x), zpools) + zpool_items.append(('Create new ZFS pool', None)) -def configure_hdd(): - hdd_items = map(lambda x: '{}: {} {}'.format(x.name, x.capacity, x.description), hdds); choice = None + buttons = [('Ok', 'ok'), ('Cancel', 'cancel')] + while not choice in ['ok', 'cancel']: - (choice, hdd) = ListboxChoiceWindow(screen, + (choice, pool) = ListboxChoiceWindow(screen, + title='Choose ZFS pool', + text='Choose ZFS pool where Dyson will be installed.\n' + 'You can selected one of the existing pools or create a new one.', + items=zpool_items, + buttons=buttons, + width=76, + scroll=1, + default=0, + ) + # Enter is pressed: + if choice == None: + choice = 'ok' + if choice == 'ok': + return pool + raise Abort('Pool choosing') + +def create_root_slice(hdd_name): + '''Create root slice (0) over entire Solaris partition''' + fd, path = mkstemp() + os.write(fd, 'partition\nmodify\n1\nyes\n0\n\n\n\n\n\n\nyes\n"{label}"\nquit\nquit\n'.format(label=hdd_name)) + os.close(fd) + format_cmd = Popen(['format', '-f', path, '-d', hdd_name], stderr=PIPE, stdout=PIPE) + out, err = format_cmd.communicate() + os.unlink(path) + if format_cmd.returncode != 0: + ButtonChoiceWindow(screen, title='Creating of root slice failed', + text=err, buttons = ['Ok'], width=70) + return None + return '{}s0'.format(hdd_name) + +def create_rpool(hdd): + global rslice + rslice = create_root_slice(hdd.name) + if not rslice: + return None + pool_name = None + for pool_no in ['', 1, 2, 3, 4, 5, 6, 7]: + pool_name = 'rpool{}'.format(rpool_no) + if not pool_name in zpools: + break + + zpool_cmd = Popen(['zpool', 'create', '-f', pool_name, rslice], + stderr=PIPE, stdout=PIPE) + out, err = zpool_cmd.communicate() + if 0 != zpool_cmd.returncode: + ButtonChoiceWindow(screen, + title='Creating of ZFS root pool failed', + text=err, buttons = ['Ok'], width=70) + return None + return pool + +def pool_is_imported(pool): + rpool_is_imported = call(['zpool', 'status', pool], stdout=PIPE, stderr=PIPE) + return rpool_is_imported == 0 + +def configure_rpool(): + global rpool + find_zpools() + while not rpool: + if len(zpools) > 0: + rpool = choose_rpool() + if not rpool: + hdd = choose_hdd(len(zpools)) + if hdd: + rpool = create_rpool(hdd) + if rpool: + if not pool_is_imported(rpool): + zpool_cmd = Popen(['zpool', 'import', '-f', rpool], stderr=PIPE, stdout=PIPE) + out, err = zpool_cmd.communicate() + if 0 != zpool_cmd.returncode: + ButtonChoiceWindow(screen, + title='Importing of ZFS pool "{}" failed'.format(rpool), + text=err, buttons = ['Ok'], width=70) + rpool = None + + +def configure_zfs(): + pass + + +def choose_hdd(number_of_zpools = 0): + hdd_items = map(lambda x: '{}: {} {}'.format(x.name, x.capacity, x.description), hdds) + choice = None + + buttons = [] + buttons.append(('Use selected disk', 'ok')) + if number_of_zpools > 0: + buttons.append(('Back', 'zpool')) + buttons.append(('Cancel', 'cancel')) + + + while not choice in ['ok', 'zpool', 'cancel']: + (choice, hdd_no) = ListboxChoiceWindow(screen, title='Choose hard disk drive', - text='Choose a hard drive for the root ZFS pool', + text='Choose a disk for the root ZFS pool', items=hdd_items, - buttons=[ - ('Use selected disk', 'ok'), - ('Cancel', 'cancel') - ], + buttons=buttons, width=76, scroll=1, default=0, help=None ) if choice in ['ok', None]: - choice = configure_partitions(hdds[hdd], number_of_disks) + choice = configure_partitions(hdds[hdd_no], len(hdds)) if choice == 'another': choice = None + if choice == 'ok': + return hdds[hdd_no] + if choice == 'zpool': + return None + raise Abort('HDD choosing') + def configure_partitions(hdd, number_of_disks = 1): choice = None - top_text = 'For the root ZFS pool you need a disk containing exactly one solaris partition (id is 0xbf). \ + top_text = 'For the root ZFS pool you need a disk containing a Solaris partition (id 0xbf). \ If this disk includes such a partition and you are happy with it, use this disk. \ -Otherwise you have to change partitioning. \ -' +Otherwise you have to change partitioning. Note that only the first Solaris partition \ +will be used.' while not choice in ['ok', 'another', 'cancel']: part_info = top_text @@ -98,15 +217,17 @@ Otherwise you have to change partitioning. \ buttons = [] if have_partitions: + part_info += 'Partitions on {name} {desc} {size}:\n\n'.format( + name=hdd.name, desc=hdd.description, size=hdd.capacity) + part_info += ' TYPE ID NAME SIZE\n' + n = 0 for p in hdd.partitions: - part_info += '{capacity:10} {system} ({id}) - {primary}\n'.format( - capacity=p.capacity, - system=p.system, - id=hex(p.id), - primary=['primary', 'logical'][p.logical], - ) + n = n + 1 if p.id == 0xBF: have_solaris_partition = True + part_info += '#{n:<2} {primary} {id:#04x} {system:25} {capacity:10}\n'.format( + n=n, capacity=p.capacity, system=p.system, id=p.id, + primary=['primary', 'logical'][p.logical]) else: part_info += 'This disk is not partitioned.\n' @@ -134,38 +255,29 @@ Otherwise you have to change partitioning. \ screen.resume() # end while + if choice == 'cancel': + raise Abort('Partitioning') return choice -class Abort(Exception): - pass -class NoDisks(Exception): - pass - # Begin installation: print("Getting list of hard disk drives ... ") -hdds = get_hdds() -number_of_disks = len(hdds) - +find_hdds() screen = SnackScreen() try: screen.pushHelpLine(' ') - if number_of_disks == 0: + if len(hdds) == 0: raise NoDisks('No disks found') - if not welcome(): - raise Abort('Installation canceled') + welcome() + configure_rpool() + configure_zfs() - zpools = [] - zpools.append(get_imported_zpools()) - zpools.append(get_exported_zpools()) - - configure_hdd() except Abort as e: - print (e) + pass except NoDisks as e: print (e) finally: |