summaryrefslogtreecommitdiff
path: root/install
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-04-11 23:44:37 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-04-11 23:44:37 +0000
commit2e123b1261fe6099b4787e2e8ef6637652b9d0f5 (patch)
tree569ed1c148ca8340fc8dde3fa7aeccba020226aa /install
parent9976d0a3088ee314b19d5cc21a89c89a73ec4f7d (diff)
downloadlive-2e123b1261fe6099b4787e2e8ef6637652b9d0f5.tar.gz
Use single-fs BE, install minimal system, create boto archive
Diffstat (limited to 'install')
-rwxr-xr-xinstall147
1 files changed, 131 insertions, 16 deletions
diff --git a/install b/install
index 53c6f1b..98147dd 100755
--- a/install
+++ b/install
@@ -15,9 +15,10 @@ from lib.snack import *
from snack import *
from subprocess import Popen, PIPE, call
from pprint import pprint
-from tempfile import mkstemp
+from tempfile import mkstemp, mkdtemp
from urllib2 import urlopen, URLError, HTTPError
from time import sleep
+from os.path import basename
import os
import re
import sys
@@ -29,6 +30,12 @@ screen = None
# List of disks installed on the system:
hdds = []
+# List of zpools found on system:
+zpools = []
+
+# List of imported zpools, we should export them after installation:
+imported_zpools = []
+
# Name of the root ZFS pool: either existing or newly created
rpool = None
@@ -38,6 +45,9 @@ rslice = None
# Created boot environment, e. g. rpoot/ROOT/osdy-0
bootenv = None
+# Install root dir
+rootdir = None
+
# Version to install:
codename = 'bok'
@@ -51,7 +61,7 @@ mirrors = [
# Stages of debootstraping in order. Debootstrap gives
# progress for each stage, but we need entire progress.
-# Format: mile : (a, z, desc), where:
+# Format: mile : (a, z), where:
# - mile is a stage name, e. g. DOWNDEBS;
# - a, z - the start and the end position on progress bar,
# e. i. a=0 z=100 - entire progress bar (100%);
@@ -63,8 +73,8 @@ miles = {
'DOWNDEBS' : (10, 25), # Downloading packages (*.deb)
'EXTRACTPKGS' : (25, 45), # Extracting core packages
'INSTCORE' : (45, 50), # Installing core packages
- 'UNPACKREQ' : (50, 60), # Unpacking required paclages
- 'CONFREQ' : (60, 70), # Configuring required paclages
+ 'UNPACKREQ' : (50, 60), # Unpacking required packages
+ 'CONFREQ' : (60, 70), # Configuring required packages
'UNPACKBASE' : (70, 85), # Unpacking the base system
'CONFBASE' : (85, 100), # Configuring the base system
}
@@ -102,9 +112,16 @@ befs = [
'setuid' : 'off',
'devices' : 'off',
}},
- {'name':'/var/tmp', 'options':{}},
+ {'name':'/var/tmp', 'options':{
+ 'compression' : 'on',
+ 'setuid' : 'off',
+ 'devices' : 'off',
+ }},
]
+# XXX Not yet.
+befs = []
+
class Abort(Exception):
''' User clicked "Cancel" '''
pass
@@ -198,7 +215,7 @@ def create_root_slice(hdd_name):
ButtonChoiceWindow(screen, title='Creating of root slice failed',
text=err, buttons = ['Ok'], width=70)
return None
- return '{}s0'.format(hdd_name)
+ return hdd_name + 's0'
def create_rpool(hdd):
global rslice
@@ -224,6 +241,7 @@ def create_rpool(hdd):
title='Creating of ZFS root pool failed',
text=err, buttons = ['Ok'], width=70)
return None
+ imported_zpools.append(pool_name)
return pool_name
def pool_is_imported(pool):
@@ -251,6 +269,7 @@ def configure_rpool():
title='Importing of ZFS pool "{}" failed'.format(rpool),
text=err, buttons=['Ok'], width=70)
rpool = None
+ imported_zpools.append(rpool)
def zfs_exists(fs):
fs_exists = call(['zfs', 'list', '-H', fs], stdout=PIPE, stderr=PIPE)
@@ -278,6 +297,7 @@ def zfs_create(fs, zvol=None, options={}):
def configure_zfs():
global bootenv
+ global rootdir
progress = ProgressBar(screen,
title='Creating ZFS filesystems',
top = 4 + len(befs), # 4 for ROOT, /swap, /home, and BE
@@ -286,7 +306,7 @@ def configure_zfs():
root = rpool + '/ROOT'
if not zfs_exists(root):
progress.text = 'Creating ' + root
- zfs_create(root, options={'canmount':'off'})
+ zfs_create(root, options={'canmount':'off', 'mountpoint':'none'})
progress.advance()
swap = rpool + '/swap'
@@ -303,16 +323,16 @@ def configure_zfs():
progress.advance()
# Make sure we are creating new boot environment
- bootenv = None
- for be_no in range(20):
+ for be_no in range(50):
bootenv = root + '/osdy-' + str(be_no)
if not zfs_exists(bootenv):
break
else:
bootenv = None
+ rootdir = mkdtemp(prefix='install-', dir='/mnt/' + rpool)
progress.text = 'Creating ' + bootenv
- zfs_create(bootenv, options={'canmount':'noauto'})
+ zfs_create(bootenv, options={'mountpoint':'/' + basename(rootdir)})
progress.advance()
for fs in befs:
@@ -321,6 +341,8 @@ def configure_zfs():
zfs_create(p, options=fs['options'])
progress.advance()
+ call(['zfs', 'snapshot', '-r', bootenv + '@empty'])
+
def choose_hdd(number_of_zpools = 0):
hdd_items = map(lambda x: '{}: {} {}'.format(x.name, x.capacity, x.description), hdds)
choice = None
@@ -445,7 +467,7 @@ def get_mirror():
def valid_mirror(mirror):
- progress = ProgressMessage(screen, title='Please, wait',
+ progress = ProgressMessage(screen, title='Please, wait...',
text='Checking APT mirror: ' + mirror)
try:
o = urlopen('{mirror}/dists/{codename}/Release'.format(
@@ -482,6 +504,7 @@ def configure_mirror():
global mirror
items = map(lambda x: '{url} ({info})'.format(url=x[0], info=x[1]), mirrors)
items.append(('Enter another mirror', None))
+ mirror = None
while not mirror:
(choice, m) = ListboxChoiceWindow(screen,
title='Choose APT mirror',
@@ -524,9 +547,10 @@ def debootstrap():
os.close(write)
try:
os.execl('/usr/sbin/debootstrap', 'debootstrap',
+ '--exclude=locales,gawk,aptitude,aptitude-common,libboost-iostreams1.48.0,libboost-iostreams1.49.0,libcwidget3',
'--debian-installer', '--no-check-gpg',
'--include=illumos-grub,illumos-kernel',
- codename, '/mnt/' + bootenv, mirror) # bootenv includes zpool name
+ codename, rootdir, mirror)
except OSError as e:
sys.exit(e.errno)
else:
@@ -575,10 +599,100 @@ def debootstrap():
status = os.wait()[1]
return os.WEXITSTATUS(status)
+def install():
+ while True:
+ configure_mirror()
+ code = debootstrap()
+ if code == 0:
+ return
+ choice = ButtonChoiceWindow(screen, title='Installation failed',
+ text='Debootstrap failed.',
+ buttons=[('Try again', 'again'), ('Cancel', 'cancel')],
+ width=40)
+ if choice == 'cancel':
+ raise Abort('debootstrap failed')
+ p = ProgressMessage(screen, title='Please, wait...', text='Undoing previous try...')
+ umount_in_bootenv()
+ call(['zfs', 'rollback', '-r', bootenv + '@empty'])
+
+
+def umount(path):
+ call(['umount', path], stdout=PIPE, stderr=PIPE)
+def umount_in_bootenv():
+ '''unmount all FS mounted in BE on final cleanup.
+ These FS also may be left after interruption or debootstrap failure'''
+ global bootenv
+ global rootdir
+
+ if not bootenv:
+ return
+ fslist = ['/dev/fd', '/proc', '/devices']
+ progress = ProgressBar(screen, title='Unmounting filesystems', top=len(fslist))
+ for fs in fslist:
+ progress.advance()
+ progress.text = 'Unmounting ' + fs
+ umount(rootdir + fs)
def destroy_bootenv():
- pass
+ global bootenv
+ global rootdir
+ if not bootenv:
+ return
+ umount_in_bootenv()
+ progress = ProgressMessage(screen, title='Destroying boot environment',
+ text='Destroying "{}", please wait...'.format(bootenv))
+ call(['zfs', 'destroy', '-r', bootenv], stdout=PIPE, stderr=PIPE)
+ bootenv = None
+ try:
+ os.rmdir(rootdir)
+ rootdir = None
+ except:
+ pass
+
+def in_bootenv(cmd):
+ chroot = ['chroot', rootdir]
+ chroot += cmd
+ return call(chroot, stderr=PIPE, stdout=PIPE)
+
+def configure_bootenv():
+ progress = ProgressBar(screen, title='Configuring Dyson boot environment', width=50)
+ progress.text = 'Preparing chroot ...'
+ call(['mount', '-F' , 'lofs', '/devices', rootdir + '/devices'], stdout=PIPE, stderr=PIPE)
+ call(['mount', '-F' , 'fd', '-', rootdir + '/dev/fd'], stdout=PIPE, stderr=PIPE)
+ call(['mount', '-F' , 'proc', '-', rootdir + '/proc'], stdout=PIPE, stderr=PIPE)
+ progress.progress = 10
+ progress.text = 'Updating devices ...'
+ in_bootenv(['/sbin/devfsadm'])
+ progress.progress = 40
+ progress.text = 'Updating boot archive, please wait ...'
+ in_bootenv(['/sbin/bootadm', 'update-archive'])
+ progress.progress = 80
+
+
+def cleanup():
+ '''Cleanup after successful installation'''
+ umount_in_bootenv()
+ progress = ProgressMessage(screen, title='Cleaning up')
+ progress.text = 'Unmounting boot environment ...'
+ call(['zfs', 'destroy', '-r', bootenv + '@empty'], stdout=PIPE, stderr=PIPE)
+ call(['zfs', 'unmount', bootenv], stdout=PIPE, stderr=PIPE)
+ call(['zfs', 'set', 'canmount=noauto', bootenv], stdout=PIPE, stderr=PIPE)
+ call(['zfs', 'set', 'mountpoint=/', bootenv], stdout=PIPE, stderr=PIPE)
+ try:
+ os.rmdir(rootdir)
+ except:
+ pass
+
+ progress.text = 'Exporting ZFS pools ...'
+ for pool in imported_zpools:
+ call(['zpool', 'export', '-f', pool], stdout=PIPE, stderr=PIPE)
+
+def goodbye():
+ ButtonChoiceWindow(screen, title='Success',
+ text='The Dyson system is successfully installed and configured. '
+ 'Hopefully, it will boot :-)',
+ buttons=['Reboot'])
screen = SnackScreen()
screen.pushHelpLine(' ')
@@ -586,13 +700,14 @@ try:
welcome()
find_hdds()
configure_rpool()
- configure_mirror()
configure_zfs()
- debootstrap()
+ install()
+ configure_bootenv()
+ cleanup()
+ goodbye()
except Abort as e:
destroy_bootenv()
- pass
except NoDisks as e:
print (e)
finally: