summaryrefslogtreecommitdiff
path: root/install
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-04-07 21:33:26 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-04-07 21:33:26 +0000
commitbfb1de5aa23a49b9414c1145c2cd65de2f03b35f (patch)
tree68a23932e11af4aafac3b08038bd0e4cda3a228d /install
parent63cb3d4f5f41186d99ebad7d5021f5a61b2aa9e7 (diff)
downloadlive-bfb1de5aa23a49b9414c1145c2cd65de2f03b35f.tar.gz
Creating rpool
Diffstat (limited to 'install')
-rwxr-xr-xinstall220
1 files changed, 166 insertions, 54 deletions
diff --git a/install b/install
index 3aa1192..0b430a6 100755
--- a/install
+++ b/install
@@ -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: