summaryrefslogtreecommitdiff
path: root/install
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-04-21 11:03:11 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-04-21 11:03:11 +0000
commitd4ceab0aa7ece6ab924f18f7275aae70645c4df6 (patch)
tree363989369bd7a693cf80d4e27adb41d8554dcb19 /install
parent7668753f391ccc695631277846bcbca7de1bf5d2 (diff)
downloadlive-d4ceab0aa7ece6ab924f18f7275aae70645c4df6.tar.gz
Install GRUB
Diffstat (limited to 'install')
-rwxr-xr-xinstall183
1 files changed, 163 insertions, 20 deletions
diff --git a/install b/install
index bb2eec0..a1d8bb4 100755
--- a/install
+++ b/install
@@ -12,13 +12,14 @@ from __future__ import print_function
from DysonInstaller.hdd import HDD
from DysonInstaller.snack import *
+from DysonInstaller.Network import *
from snack import *
from subprocess import Popen, PIPE, call
from pprint import pprint
from tempfile import mkstemp, mkdtemp
from urllib2 import urlopen, URLError, HTTPError
from time import sleep
-from os.path import basename
+from os.path import basename, exists
import os
import re
import sys
@@ -27,6 +28,9 @@ import math
# Snack screen
screen = None
+# Physical network interfaces
+physlinks = []
+
# List of disks installed on the system:
hdds = []
@@ -40,12 +44,20 @@ imported_zpools = []
rpool = None
# Name of the root slice, where ZFS root pool will be created (e. g. c0t0d0s0)
+# Used for installing GRUB
rslice = None
+# Object, describing solaris partition
+solaris_partition = None
+
+# XXX rslice and solaris_partition aare known only
+# on new clean installations, so we allow installing GRUB
+# only on new installations
+
# Created boot environment, e. g. rpoot/ROOT/osdy-0
bootenv = None
-# Install root dir
+# Install root dir, mount point for bootenv
rootdir = None
# Version to install:
@@ -62,6 +74,26 @@ mirrors = [
('http://mirror-us.osdyson.org/apt/', 'USA'),
]
+# Top of /rpool/boot/grub/menu.lst, if creating new file:
+grub_top = r'''
+foreground 343434
+background F7FbFF
+default 0
+timeout 5
+'''
+
+# Entry in /rpool/boot/grub/menu.lst for newly created boot environment
+# This string must be formatted.
+# 0 is the partition number,
+# a is the slice number; both are not used
+grub_entry = r'''
+title Dyson at {bootenv}
+findroot (pool_{rpool},0,a)
+bootfs {bootenv}
+kernel$ /platform/i86pc/kernel/amd64/unix -B $ZFS-BOOTFS
+module$ /platform/i86pc/amd64/boot_archive
+'''
+
# Stages of debootstraping in order. Debootstrap gives
# progress for each stage, but we need entire progress.
@@ -294,7 +326,7 @@ def zfs_create(fs, zvol=None, options={}):
out, err = zfs_cmd.communicate()
if 0 != zfs_cmd.returncode:
ButtonChoiceWindow(screen,
- title='Creating of ZFS dataset failed',
+ title='Creating of ZFS filesystem failed',
text=err, buttons = ['Ok'], width=70)
return False
return True
@@ -347,9 +379,10 @@ def configure_zfs():
zfs_create(p, options=fs['options'])
progress.advance()
+ # Will rollback if debootstrap fails
call(['zfs', 'snapshot', '-r', bootenv + '@empty'])
-def choose_hdd(number_of_zpools = 0):
+def choose_hdd(number_of_zpools=0):
hdd_items = map(lambda x: '{}: {} {}'.format(x.name, x.capacity, x.description), hdds)
choice = None
@@ -382,7 +415,8 @@ def choose_hdd(number_of_zpools = 0):
return None
raise Abort('HDD choosing')
-def configure_partitions(hdd, number_of_disks = 1):
+def configure_partitions(hdd, number_of_disks=1):
+ global solaris_partition
choice = None
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. \
@@ -394,8 +428,8 @@ will be used.'
part_info += '\n\n'
have_partitions = len(hdd.partitions) > 0
- have_solaris_partition = False
have_gpt = False
+ solaris_partition = None
buttons = []
if have_partitions:
@@ -405,8 +439,8 @@ will be used.'
n = 0
for p in hdd.partitions:
n = n + 1
- if p.id == 0xBF:
- have_solaris_partition = True
+ if p.id == 0xBF and solaris_partition == None:
+ solaris_partition = p
if p.id == 0xEE:
have_gpt = True
part_info += '#{n:<2} {primary} {id:#04x} {system:25} {capacity:10}\n'.format(
@@ -415,7 +449,7 @@ will be used.'
else:
part_info += 'This disk is not partitioned.\n'
- if have_solaris_partition:
+ if solaris_partition != None:
buttons.append(('Use this disk', 'ok'))
if have_gpt:
@@ -471,6 +505,26 @@ def get_mirror():
if choice == 'cancel':
raise Abort('Entering an APT mirror')
+def choose_physlink():
+ pass
+
+def configure_network():
+ global physlinks
+ if not physlinks:
+ physlinks = dladm_show_phys()
+ if not physlinks:
+ choice = ButtonChoiceWindow(screen, title='Network is unreachable',
+ text='No network interfaces found on this system. '
+ 'This mean that public APT repositories cannot be used '
+ 'to install Dyson.',
+ buttons=['Ok'])
+ return
+ while True:
+ if len(physlinks) > 1:
+ link = choose_physlink()
+ else:
+ link = physlinks[0]
+ break
def valid_mirror(mirror):
progress = ProgressMessage(screen, title='Please wait...',
@@ -521,7 +575,7 @@ def configure_mirror():
for m in mirrors:
if len(m[0]) > maxlen:
maxlen = len(m[0])
- items = map(lambda x: '{url: <{0}} ({info})'.format(maxlen, url=x[0], info=x[1]), mirrors)
+ items = map(lambda x: '{url: <{0}} - {info}'.format(maxlen, url=x[0], info=x[1]), mirrors)
items.append(('Enter another mirror', None))
mirror = None
while not mirror:
@@ -547,7 +601,7 @@ def configure_mirror():
def debootstrap():
progress = ProgressBar(screen,
title='Installing base system, please wait...',
- width=76)
+ width=70)
progress.text = ' '
@@ -568,9 +622,9 @@ def debootstrap():
os.execl('/usr/sbin/debootstrap', 'debootstrap',
'--debian-installer', '--no-check-gpg',
'--exclude=gawk,aptitude,aptitude-common,libboost-iostreams1.48.0,libboost-iostreams1.49.0,libcwidget3',
- '--include=illumos-grub,illumos-kernel,locales',
+ '--include=installgrub,illumos-grub,illumos-kernel,locales',
codename, rootdir, mirror)
- except OSError as e:
+ except EnvironmentError as e:
sys.exit(e.errno)
else:
os.close(write)
@@ -667,7 +721,9 @@ def umount_in_bootenv():
def in_bootenv(cmd):
chroot = ['chroot', rootdir]
chroot += cmd
- return call(chroot, stderr=PIPE, stdout=PIPE)
+ pobject = Popen(chroot, stderr=PIPE, stdout=PIPE)
+ out, err = pobject.communicate()
+ return (pobject.returncode, out, err)
def write_vfstab():
@@ -712,9 +768,6 @@ def configure_nodename():
except:
pass
-def configure_network():
- configure_nodename()
-
def configure_packages():
screen.suspend()
call(['chroot', rootdir, '/usr/sbin/dpkg-reconfigure', 'tzdata', 'locales'], stderr=PIPE)
@@ -750,12 +803,101 @@ def set_root_password():
def configure_bootenv():
write_vfstab()
mount_in_bootenv()
- in_bootenv(['/sbin/devfsadm'])
+ in_bootenv(['/usr/sbin/devfsadm'])
configure_packages()
- configure_network()
+ configure_nodename()
set_root_password()
create_bootarchive()
+def configure_grub():
+ entry = grub_entry.format(rpool=rpool, bootenv=bootenv)
+ # write grub menu for references:
+ try:
+ menu = open(rootdir + '/boot/grub/menu.lst', 'w')
+ print('# This file is just for references. It is not used by GRUB', file=menu)
+ print('# Actual menu.lst used by GRUB is {}/boot/grub/menu.lst'.format(rpool), file=menu)
+ print('# where {} is the name of root ZFS pool'.format(rpool), file=menu)
+ print(grub_top, file=menu)
+ print(entry, file=menu)
+ menu.close()
+ except:
+ pass
+
+ items = []
+ text = ''
+ if solaris_partition != None: # New installation:
+ items.append(('Install GRUB to MBR', 'mbr'))
+ text += 'Installing GRUB on the master boot sector (MBR) '
+ text += 'overrides any boot manager currently installed: '
+ text += 'the system will always boot the GRUB in the solaris partition'
+ if not solaris_partition.logical:
+ items.append(('Install GRUB to a partition only', 'partition'))
+ else:
+ text += 'It looks like root ZFS pool "{rpool}" was not created during this installation, '.format(rpool=rpool)
+ text += 'so installing GRUB is not supported. '
+ text += 'You can only update GRUB menu, or completely skip '
+ text += 'this step. Laterly you can configure GRUB using installgrub(1m) '
+ text += 'utility and using /boot/grub/menu.lst as an example.'
+ items.append(('Only update GRUB menu', 'menu'))
+ items.append(('Do nothing', 'skip'))
+ button, install = ListboxChoiceWindow(screen, title='Configure GRUB',
+ text=text, items=items, buttons=['Ok'], width=50)
+ if install == 'skip':
+ return
+ rpool_path = '/mnt/{rpool}/{rpool}'.format(rpool=rpool)
+ try:
+ if not exists(rpool_path + '/boot'):
+ os.mkdir(rpool_path + '/boot')
+ if not exists(rpool_path + '/boot/grub'):
+ os.mkdir(rpool_path + '/boot/grub')
+ if not exists(rpool_path + '/boot/grub/bootsign'):
+ os.mkdir(rpool_path + '/boot/grub/bootsign')
+ if not exists(rpool_path + '/boot/grub/bootsign/pool_'+rpool):
+ open(rpool_path + '/boot/grub/bootsign/pool_'+rpool, 'w').close()
+ if not exists(rpool_path + '/boot/grub/menu.lst'):
+ menu = open(rpool_path + '/boot/grub/menu.lst', 'w')
+ print(grub_top, file=menu)
+ menu.close()
+ re_bootfs = re.compile(r'^bootfs\s+' + bootenv)
+ have_this_bootenv = False
+ menu = open(rpool_path + '/boot/grub/menu.lst', 'r+')
+ for line in menu:
+ if re_bootfs.match(line):
+ have_this_bootenv = True
+ break
+ if not have_this_bootenv:
+ print(entry, file=menu)
+ menu.close()
+ except EnvironmentError as e:
+ text = 'Failed to write GRUB configuration: '
+ if e.filename:
+ text += e.filename + ': '
+ text += e.strerror
+ ButtonChoiceWindow(screen, title='Error',
+ text=text, buttons=['Ok'], width=60)
+ if install == 'menu':
+ return
+
+ # solaris_partition is not known - installing on existing pool,
+ # installing GRUB is not supported.
+ if solaris_partition == None:
+ return
+
+ progress = ProgressMessage(screen, title='Installing GRUB', width=50)
+ installgrub_cmd = ['/usr/sbin/installgrub']
+ if install == 'mbr':
+ progress.text = 'Installing GRUB to the master boot record...'
+ installgrub_cmd += ['-f', '-m']
+ else:
+ progress.text = 'Installing GRUB to partition...'
+
+ installgrub_cmd += ['/boot/grub/stage1', '/boot/grub/stage2',
+ '/dev/rdsk/' + rslice]
+ rc, out, err = in_bootenv(installgrub_cmd)
+ if rc != 0:
+ ButtonChoiceWindow(screen, title='Error',
+ text='Installing of GRUB failed: ' + err, buttons=['Ok'], width=60)
+
def cleanup(destroy_bootenv=False):
global bootenv
@@ -765,7 +907,7 @@ def cleanup(destroy_bootenv=False):
umount_in_bootenv()
call(['umount', rootdir], stdout=PIPE, stderr=PIPE)
if destroy_bootenv:
- progress.text='Destroying "{}", please wait ...'.format(bootenv)
+ progress.text='Destroying {}, please wait ...'.format(bootenv)
call(['zfs', 'destroy', '-r', bootenv], stdout=PIPE, stderr=PIPE)
else:
progress.text = 'Adjusting boot environment "{}" ...'.format(bootenv)
@@ -798,6 +940,7 @@ try:
configure_zfs()
install()
configure_bootenv()
+ configure_grub()
cleanup()
goodbye()