summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDieter Plaetinck <dieter@plaetinck.be>2009-03-29 18:16:42 +0200
committerDieter Plaetinck <dieter@plaetinck.be>2009-03-29 18:16:42 +0200
commitef2290b0e31c285267bba9dde3634b628df0ebf0 (patch)
treede627bb47c87f535ad7eea5d7b3da9bc2cbef3c7
parent71f5510aaaa20ae5ae9c773dca12028bd96aafdf (diff)
parentff1bc0cd6060d0a23911f1ef25633f706a9af619 (diff)
Merge branch 'experimental'2009.03.29
-rw-r--r--README9
-rw-r--r--TODO28
-rw-r--r--examples/generic-install-on-sda28
-rwxr-xr-xsrc/aif.sh253
-rw-r--r--src/core/libs/lib-blockdevices-filesystems.sh155
-rwxr-xr-xsrc/core/libs/lib-flowcontrol.sh216
-rw-r--r--src/core/libs/lib-misc.sh86
-rw-r--r--src/core/libs/lib-network.sh2
-rw-r--r--src/core/libs/lib-pacman.sh29
-rw-r--r--src/core/libs/lib-software.sh29
-rw-r--r--src/core/libs/lib-ui-interactive.sh293
-rw-r--r--src/core/libs/lib-ui.sh300
-rw-r--r--src/core/procedures/automatic116
-rw-r--r--src/core/procedures/base40
-rw-r--r--src/core/procedures/interactive14
-rw-r--r--src/core/procedures/partial-keymap7
-rw-r--r--src/core/procedures/quickinst140
-rwxr-xr-xtests/test-check_is_in.sh7
-rwxr-xr-x[-rw-r--r--]tests/test-menus.sh23
-rw-r--r--unofficial/dieter-desktop-a7n8x.automaticprofile (renamed from examples/deployconfig-dieter)38
-rw-r--r--unofficial/modules/dieter/procedures/dieter-automatic27
21 files changed, 1011 insertions, 829 deletions
diff --git a/README b/README
index fbffaa4..780c6fc 100644
--- a/README
+++ b/README
@@ -15,7 +15,6 @@ AIF is based on the old installer, but the code has been madly refactored, reorg
AIF comes by default with these procedures:
- interactive: A port of /arch/setup. Should work okay if you don't try too hard to break it ;-)
-- quickinst: A port of /arch/quickinst. Work in progress. Don't use this yet.
- automatic: An automated, deploy-tool-alike procedure. Work in progress. Don't use this yet.
AIF may or may not bring much additional value for you when compared with the previous
@@ -34,7 +33,7 @@ installer, it depends on what you want to do:
works. It is built for hacking, reusing code, changing the behaviour in
specific places and making writing custom installers as easy as possible.
-Keep in mind that AIF is still in ALPHA phase.
+Keep in mind that AIF is still in beta phase.
There are some known issues (see the TODO file and various TODO's in the source code)
If you encounter issues, please report them at the Arch Linux bugtracker under the "Release Engineering" project.
@@ -43,8 +42,7 @@ If you encounter issues, please report them at the Arch Linux bugtracker under t
You can also get in touch with the release engineers / aif developers on the arg-releng
mailing list, http://www.archlinux.org/mailman/listinfo/arch-releng
-AIF is expected to become the new official installer in the not too distant
-future, so go ahead and try it !
+AIF will soon become the new official installer so go ahead and try it !
@@ -53,7 +51,7 @@ future, so go ahead and try it !
The goal of this project is
1) to make the code of the Arch Linux installer more clean, DRY, modular and maintainable.
2) providing complete, easily-reusable libraries for disk partitioning, UI, package management, etc
-3) provide some sensible default installation methods (eg interative, quickinst, automatic (prescripted), ..)
+3) provide some sensible default installation methods (eg interative, automatic (prescripted), ..)
4) allowing power users to easily override certain aspects of the installation procedures
or creating customized procedures, leveraging the available code.
@@ -79,7 +77,6 @@ A module can have 2 directories: libs, and procedures.
core/base: basic, little-interactivity installation with some common defaults. You probably don't
want to run this one, although it's useful for other procedures to inherit from.
core/interactive: interactive, reasonably flexible/featured installer (port of /arch/setup)
-core/quickinst: mostly DIY. port of /arch/quickinst
core/automatic: automatic installer/deployment tool, can use config files
** Partial Procedures **
diff --git a/TODO b/TODO
index f46ae0f..1a87c65 100644
--- a/TODO
+++ b/TODO
@@ -1,18 +1,17 @@
-See also the FIXME's and TODO's in the code.
-
+See also the FIXME's and TODO's in the code, and http://bugs.archlinux.org/toplevel/proj6
CURRENT ISSUES:
-* when invoking /arch/aif -p interactive on a "normal" pc, it always wants to abort
+* use traps and initiate rollback when user wants to abort. see also http://www.davidpashley.com/articles/writing-robust-shell-scripts.html
+* differentiate between framework and installer in src/aif.sh, some things should be in base
* check everywhere that if users cancels something, we return 1, empty string behavior etc
-* core/interactive: fix workaround needed for installpkg exitcode
-* core/interactive: keymap from installer don't not go in $target/etc/rc.conf
* dm_crypt unlock at boot is in qwerty.
* after unlocking dm_crypt, FS check fails (reiserfs, must try other)
+* lib-software line19: [ $mkinitcpio_exitcode -ne 0 ] unary operator expected when running automatic procedure (prolly otherwise too)
* find a way to make _cli_ask_checklist still userfriendly for long lists.. maybe we should just propose/ask to use dia if the list is too long
-* lib things sometimes call die_error but we go back to the menu.. or something.. i think
+* sometimes we call die_error but we go back to the menu.. eg when we run as non-root and can't log
* automatically configure grub for dm_crypt and lvm
+* fs_params in partition editor: do we really need to show them? isn't this where we store our "own" stuff?
* move "/tmp/pacman.conf" to runtime directory and variablize everywhere
-* hmm wasn't there a hwdetect/hwd or something in /arch/setup? this seems to have disappeared.
* a nice way to be able to "inject" functions/logic without:
* needing to redefine phases with only 1 entry different (duplicate code is not nice, less maintainable etc)
* override worker functions which are 90% copy-pasted because the parent functionality is mostly okay, but not exactly what we want
@@ -25,29 +24,25 @@ CURRENT ISSUES:
-> too. although that's only good for separate functions, not the 'copypaste 90% and add 10% to the same worker scenario'
-> phases are arrays.. adding elements at the back is easy. for in the middle, we could maybe write some functions to add a worker before/after another in a phase
* mirrorlist config doesn't change after selecting mirror
+* show_report does not show workers.
* 'keep in mind trottled' not on separate screen
+* look if you can hook into bash so that on any syntax/.. error you can bind the debug/log function
+* when you have 2 LV's and you delete one, both are erased from the VG, but there is still the entry for the other one as blockdevice
* in usage, procedure specific opts points to parent profile when using inheritance
* we may have an issue with ftp based installation where package installation works fine, however it tries to die instead of 'package installation complete' but it can't die because the --textbox fails in show_warning
-* ( only in experimental?) grub sedding sometimes does, and sometimes doesn't work. default config remains (eg /dev/hda3)
-* debug "categories" (ui, disk,flowcontrol,...) so you can grep (-v) on what you want + make sure enough+correct debugging is everywhere
* the old installer asked a lot of questions before actually configuring the system, eg like 'do you need support for booting from nfs/softraid/lvm2/encrypted, custom dst file?' etc.\
do we still need this? why (not)?, and a select tag thingie would be nicer imho
* refactor all pacman stuff (modularize/functionize etc)
-* in lvm VG editor you can press "cancel" (when 'new' is selected, maybe otherwise too) and create a new LV which will get a block entry, but no fs entry on the VG block!
* aif : na "mijn" partitielayout: bij grub ( nog voor text editor op menu.lst) zegt iets ( op foreground van ncurses) Can't remove.. ik denk zelfs 'Grub: Can't remove..' en daarna een gewone entry, geen uuid's gewoon /dev/sda3 ro
-* port from /arch/setup: grub install chroot thing (waiting for ticket), 2 patches from foutrelis @ http://bugs.archlinux.org/task/12949
+* port from /arch/setup: grub install chroot thing (http://projects.archlinux.org/?p=installer.git;a=commitdiff;h=4565577dbd2182dd49612f1e0b68288f5573bf7b) (waiting for ticket http://bugs.archlinux.org/task/13277)
* ext4 default options? -O dir_index,extent,uninit_bg ?
* find a way to not have to preload libs and stuff, only load them when needed. -> faster start of install program
-* if dhcpd already runs for $reason, the installer will try again @ configure network and fail.
- i tried killall dhcpd, killall -9 dhcpd first but that didn't help: it can't kill the process or something...
- I can also add something like for iface in `moo` (or only the one selected iface); do ifconfig $iface down;
- ifconfig $iface up; done, and then dhcpd again
* core/interactive: do not check hard for the dependencies. a user could really know what he's doing or need to reboot after partitioning a disk and
skip that check or something. Alternatively, maybe just show which steps are done successfully in the main menu
* support maybe ntp to set clock
* auto-configure mkinitcpio.conf for dm_crypt and lvm
* core/quickinst: figure out what needs to be done and do it.
-
+* right at the end of package installation something happens :/ also at configure system, before generation of locales
SOMEDAY/MAYBE/RANDOM THOUGHTS:
@@ -72,6 +67,7 @@ configuring the system (mkinitcpio.conf). can we optimize this?
WORRIES FOR MAYBE NO GOOD REASON
+* dont load libs twice if not needed
* base procedure is mostly to serve other procedures. If we need to do much
work to implement something in the base procedure that we will probably
never use in other procedures, we're doing something wrong. If that ever
diff --git a/examples/generic-install-on-sda b/examples/generic-install-on-sda
new file mode 100644
index 0000000..9d25776
--- /dev/null
+++ b/examples/generic-install-on-sda
@@ -0,0 +1,28 @@
+# these variables are optional, here are the defaults (feel free to omit them)
+
+SOURCE=cd
+FILE_URL=file:///src/core/pkg
+SYNC_URL=
+
+# Do you want to have additional pacman repositories or packages available at runtime (during installation)?
+RUNTIME_REPOSITORIES=
+RUNTIME_PACKAGES=
+
+# packages to install
+TARGET_GROUPS=base #all packages in this group will be installed (defaults to base if no group and no packages are specified)
+TARGET_PACKAGES=openssh # you can also specify separate packages (this is empty by default)
+
+# you can optionally also override some functions...
+worker_intro () {
+ infofy "Automatic procedure running the generic-install-on-sda example config. THIS WILL ERASE AND OVERWRITE YOUR /DEV/SDA. IF YOU DO NOT WANT THIS PRESS CTRL+C WITHIN 10 SECONDS"
+ sleep 10
+}
+
+
+# These variables are mandatory
+
+GRUB_DEVICE=/dev/sda
+PARTITIONS='/dev/sda 100:ext2:+ 512:swap *:ext4'
+BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
+/dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
+/dev/sda3 raw no_label ext4;yes;/;target;no_opts;no_label;no_params' \ No newline at end of file
diff --git a/src/aif.sh b/src/aif.sh
index b2662eb..a4f2d8b 100755
--- a/src/aif.sh
+++ b/src/aif.sh
@@ -11,259 +11,22 @@ LOG_DIR=/var/log/aif
LOGFILE=$LOG_DIR/aif.log
-###### Miscalleaneous functions ######
-
-usage ()
-{
- #NOTE: you can't use dia mode here yet because lib-ui isn't sourced yet. But cli is ok for this anyway.
- msg="aif -p <procedurename> Select a procedure # If given, this *must* be the first option
- -i <dia/cli> Override interface type (optional)
- -d Explicitly enable debugging (optional)
- -l Explicitly enable logging to file (optional)
- -h Help: show usage (optional)\n
-If the procedurename starts with 'http://' it will be wget'ed. Otherwise it's assumed to be a procedure in the VFS tree
-If the procedurename is prefixed with '<modulename>/' it will be loaded from user module <modulename>.\n
-For more info, see the README which you can find in /usr/share/aif/docs\n
-Available procedures:
-==core==
-`find $LIB_CORE/procedures -type f | sed \"s#$LIB_CORE/procedures/##\"`
-==user==
-`find $LIB_USER/*/procedures -type f 2>/dev/null | sed \"s#$LIB_USER/\(.*\)/procedures/#\1/#\"`"
- [ -n "$procedure" ] && msg="$msg\nProcedure ($procedure) specific options:\n$var_ARGS_USAGE"
-
- echo -e "$msg"
-
-}
-
-##### TMP functions that we need during early bootstrap but will be overidden with decent functions by libraries ######
-
-
-notify ()
-{
- echo -e "$@"
-}
-
-
-log ()
-{
- mkdir -p $LOG_DIR || die_error "Cannot create log directory"
- str="[LOG] `date +"%Y-%m-%d %H:%M:%S"` $@"
- echo -e "$str" > $LOG
- [ "$LOG_TO_FILE" = 1 ] && echo -e "$str" >> $LOGFILE
-}
-
-
-debug ()
-{
- mkdir -p $LOG_DIR || die_error "Cannot create log directory"
- str="[DEBUG] $@"
- if [ "$DEBUG" = "1" ]
- then
- echo -e "$str" > $LOG
- [ "$LOG_TO_FILE" = 1 ] && echo -e "$str" >> $LOGFILE
- fi
-}
-
-
-###### Core functions ######
-
-
-# $1 module name
-load_module ()
-{
- [ -z "$1" ] && die_error "load_module needs a module argument"
- log "Loading module $1 ..."
- path=$LIB_USER/"$1"
- [ "$1" = core ] && path=$LIB_CORE
-
- for submodule in lib #procedure don't load procedures automatically!
- do
- if [ ! -d "$path/${submodule}s" ]
- then
- # ignore this problem for not-core modules
- [ "$1" = core ] && die_error "$path/${submodule}s does not exist. something is horribly wrong with this installation"
- else
- shopt -s nullglob
- for i in "$path/${submodule}s"/*
- do
- load_${submodule} "$1" "`basename "$i"`"
- done
- fi
- done
-
-}
-
-
-# $1 module name
-# $2 procedure name
-load_procedure()
-{
- [ -z "$1" ] && die_error "load_procedure needs a module as \$1 and procedure as \$2"
- [ -z "$2" ] && die_error "load_procedure needs a procedure as \$2"
- if [ "$1" = 'http:' ]
- then
- log "Loading procedure $2 ..."
- procedure=$RUNTIME_DIR/procedure-downloaded-`basename $2`
- wget "$2" -q -O $procedure >/dev/null || die_error "Could not download procedure $2"
- else
- log "Loading procedure $1/procedures/$2 ..."
- procedure=$LIB_USER/"$1"/procedures/"$2"
- [ "$1" = core ] && procedure=$LIB_CORE/procedures/"$2"
- fi
- [ -f "$procedure" ] && source "$procedure" || die_error "Something went wrong while sourcing procedure $procedure"
-}
-
-
-# $1 module name
-# $2 library name
-load_lib ()
-{
- [ -z "$1" ] && die_error "load_library needs a module als \$1 and library as \$2"
- [ -z "$2" ] && die_error "load_library needs a library as \$2"
- log "Loading library $1/libs/$2 ..."
- lib=$LIB_USER/"$1"/libs/"$2"
- [ "$1" = core ] && lib=$LIB_CORE/libs/"$2"
- source $lib || die_error "Something went wrong while sourcing library $lib"
-}
-
-
-# $1 phase/worker
-# $2 phase/worker name
-# $3... extra args for phase/worker (optional)
-execute ()
-{
- [ -z "$1" -o -z "$2" ] && debug "execute $@" && die_error "Use the execute function like this: execute <type> <name> with type=phase/worker"
- [ "$1" != phase -a "$1" != worker ] && debug "execute $@" && die_error "execute's first argument must be a valid type (phase/worker)"
- PWD_BACKUP=`pwd`
- object=$1_$2
-
- if [ "$1" = worker ]
- then
- log "*** Executing worker $2"
- if type -t $object | grep -q function
- then
- shift 2
- $object "$@"
- ret=$?
- exit_var=exit_$object
- read $exit_var <<< $ret # maintain exit status of each worker
- else
- die_error "$object is not defined!"
- fi
- elif [ "$1" = phase ]
- then
- log "******* Executing phase $2"
- exit_var=exit_$object
- read $exit_var <<< 0
- # TODO: for some reason the hack below does not work (tested in virtualbox), even though it really should. Someday I must get indirect array variables working and clean this up...
- # debug "\$1: $1, \$2: $2, \$object: $object, \$exit_$object: $exit_object"
- # debug "declare: `declare | grep -e "^${object}=" | cut -d"=" -f 2-`"
- # props to jedinerd at #bash for this hack.
- # eval phase=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
- #debug "\$phase: $phase - ${phase[@]}"
- unset phase
- [ "$2" = preparation ] && phase=( "${phase_preparation[@]}" )
- [ "$2" = basics ] && phase=( "${phase_basics[@]}" )
- [ "$2" = system ] && phase=( "${phase_system[@]}" )
- [ "$2" = finish ] && phase=( "${phase_finish[@]}" )
- # worker_str contains the name of the worker and optionally any arguments
- for worker_str in "${phase[@]}"
- do
- debug "Loop iteration. \$worker_str: $worker_str"
- execute worker $worker_str || read $exit_var <<< $? # assign last failing exit code to exit_phase_<phasename>, if any.
- done
- ret=${!exit_var}
- fi
-
- debug "Execute(): $object exit state was $ret"
- cd $PWD_BACKUP
- return $ret
-}
-
-
-# check if a phase/worker executed sucessfully
-# returns 0 if ok, the phase/workers' exit state otherwise (and returns 1 if not executed yet)
-# $1 phase/worker
-# $2 phase/worker name
-ended_ok ()
-{
- [ -z "$1" -o -z "$2" ] && die_error "Use the ended_ok function like this: ended_ok <type> <name> with type=phase/worker"
- [ "$1" != phase -a "$1" != worker ] && die_error "ended_ok's first argument must be a valid type (phase/worker)"
- object=$1_$2
- exit_var=exit_$object
- debug "Ended_ok? -> Exit state of $object was: ${!exit_var} (if empty. it's not executed yet)"
- [ "${!exit_var}" = '0' ] && return 0
- [ "${!exit_var}" = '' ] && return 1
- return ${!exit_var}
-}
-
-
-depend_module ()
-{
- load_module "$1"
-}
-
-
-depend_procedure ()
-{
- load_procedure "$1" "$2"
-}
-
-
-start_process ()
-{
- execute phase preparation
- execute phase basics
- execute phase system
- execute phase finish
-}
-
-
-show_report () #TODO: abstract UI method (cli/dia)
-{
- echo "Execution Report:"
- echo "-----------------"
- for phase in preparation basics system finish
- do
- object=phase_$phase
- exit_var=exit_$object
- ret=${!exit_var}
- echo -n "Phase $phase: "
- [ "$ret" = "0" ] && echo "Success" || echo "Failed"
- eval phase_array=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
- for worker_str in "${phase_array[@]}"
- do
- worker=${worker_str%% *}
- exit_var=exit_worker_$worker
- ret=${!exit_var}
- echo -n " > Worker $worker: "
- [ "$ret" = "0" ] && echo "Success" || echo "Failed"
- done
- done
-}
+###### Early bootstrap ######
+# load the lib-ui, it is one we need everywhere so we must load it early.
+source $LIB_CORE/libs/lib-ui.sh || ( echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-ui.sh" >&2 && exit 2)
+# load the lib-flowcontrol. we also need some of it's functions early (like usage()).
+source $LIB_CORE/libs/lib-flowcontrol.sh || ( echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-flowcontrol.sh" >&2 && exit 2)
+# lib-misc. we need it early, at least for check_is_in whis is used by the debug function.
+source $LIB_CORE/libs/lib-misc.sh || ( echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-misc.sh" >&2 && exit 2)
+# default function to process additional arguments. can be overridden by procedures.
process_args ()
{
true
}
-start_installer ()
-{
- log "################## START OF INSTALLATION ##################"
- cleanup_runtime
-}
-
-
-# use this function to stop the installation procedure.
-# $1 exit code (optional)
-stop_installer ()
-{
- log "-------------- STOPPING INSTALLATION ----------"
- cleanup_runtime
- exit $1
-}
###### perform actual logic ######
diff --git a/src/core/libs/lib-blockdevices-filesystems.sh b/src/core/libs/lib-blockdevices-filesystems.sh
index 3b43541..c1316f0 100644
--- a/src/core/libs/lib-blockdevices-filesystems.sh
+++ b/src/core/libs/lib-blockdevices-filesystems.sh
@@ -3,33 +3,37 @@
# FORMAT DEFINITIONS:
-# MAIN FORMAT FOR $TMP_BLOCKDEVICES (format used to interface with this library): one line per blockdevice, multiple fs'es in 1 'fs-string'
-# $TMP_BLOCKDEVICES entry.
-# <blockdevice> type label/no_label <FS-string>/no_fs
-# FS-string:
-# type;recreate(yes/no);mountpoint;mount?(target,runtime,no);opts;label;params[|FS-string|...] where opts/params have _'s instead of whitespace if needed
-# NOTE: the 'mount?' for now just matters for the location (if 'target', the target path gets prepended and mounted in the runtime system)
-# NOTE: filesystems that span multiple underlying filesystems/devices (eg lvm VG) should specify those in params, separated by colons. \
-# the <blockdevice> in the beginning doesn't matter much, it can be pretty much any device, or not existent, i think. But it's probably best to make it one of the devices listed in params
-# no '+' characters allowed for devices in $fs_params (eg use the real names)
-
-
-# ADDITIONAL INTERNAL FORMAT FOR $TMP_FILESYSTEMS: each filesystem on a separate line, so block devices can appear multiple times be on multiple lines (eg LVM volumegroups with more lvm LV's)
+# -- formats used to interface with this library --
+# $TMP_PARTITIONS
+# one line per partition, blockdevice + partioning string for sfdisk. See docs for function partition for more info.
+# $TMP_BLOCKDEVICES
+# one line per blockdevice, multiple fs'es in 1 'fs-string'
+# $TMP_BLOCKDEVICES entry.
+# <blockdevice> type label/no_label <FS-string>/no_fs
+# FS-string:
+# type;recreate(yes/no);mountpoint;mount?(target,runtime,no);opts;label;params[|FS-string|...] where opts/params have _'s instead of whitespace if needed
+# NOTE: the 'mount?' for now just matters for the location (if 'target', the target path gets prepended and mounted in the runtime system)
+# NOTE: filesystems that span multiple underlying filesystems/devices (eg lvm VG) should specify those in params, separated by colons. \
+# the <blockdevice> in the beginning doesn't matter much, it can be pretty much any device, or not existent, i think. But it's probably best to make it one of the devices listed in params
+# no '+' characters allowed for devices in $fs_params (eg use the real names)
+
+
+# -- ADDITIONAL INTERNAL FORMATS --
+# $TMP_FILESYSTEMS: each filesystem on a separate line, so block devices can appear multiple times be on multiple lines (eg LVM volumegroups with more lvm LV's)
# part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
-#TODO: this should be fixed on the installcd.
-modprobe dm-crypt || show_warning modprobe 'Could not modprobe dm-crypt. no support for disk encryption'
-modprobe aes-i586 || show_warning modprobe 'Could not modprobe aes-i586. no support for disk encryption'
+modprobe -q dm-crypt || show_warning modprobe 'Could not modprobe dm-crypt. no support for disk encryption'
+modprobe -q aes-i586 || modprobe -q aes-x86-64 || show_warning modprobe 'Could not modprobe aes-i586 or aes-x86-64. no support for disk encryption'
-TMP_DEV_MAP=$RUNTIME_DIR/dev.map
-TMP_FSTAB=$RUNTIME_DIR/.fstab
-TMP_PARTITIONS=$RUNTIME_DIR/.partitions
-TMP_FILESYSTEMS=$RUNTIME_DIR/.filesystems # Only used internally by this library. Do not even think about using this as interface to this library. it won't work
-TMP_BLOCKDEVICES=$RUNTIME_DIR/.blockdata
+TMP_DEV_MAP=$RUNTIME_DIR/aif-dev.map
+TMP_FSTAB=$RUNTIME_DIR/aif-fstab
+TMP_PARTITIONS=$RUNTIME_DIR/aif-partitions
+TMP_FILESYSTEMS=$RUNTIME_DIR/aif-filesystems # Only used internally by this library. Do not even think about using this as interface to this library. it won't work
+TMP_BLOCKDEVICES=$RUNTIME_DIR/aif-blockdata
@@ -271,10 +275,10 @@ target_configure_fstab()
# partitions a disk. heavily altered
# $1 device to partition
-# $2 a string of the form: <partsize>:<fstype>[:+] (the + is bootable flag)
+# $2 a string of the form: <partsize in MiB>:<fstype>[:+] (the + is bootable flag)
partition()
{
- debug "Partition called like: partition '$1' '$2'"
+ debug 'FS' "Partition called like: partition '$1' '$2'"
[ -z "$1" ] && die_error "partition() requires a device file and a partition string"
[ -z "$2" ] && die_error "partition() requires a partition string"
@@ -313,7 +317,7 @@ partition()
sfdisk_input=$(printf "$sfdisk_input") # convert \n to newlines
# invoke sfdisk
- debug "Partition calls: sfdisk $DEVICE -uM >$LOG 2>&1 <<< $sfdisk_input"
+ debug 'FS' "Partition calls: sfdisk $DEVICE -uM >$LOG 2>&1 <<< $sfdisk_input"
printk off
sfdisk $DEVICE -uM >$LOG 2>&1 <<EOF
$sfdisk_input
@@ -329,10 +333,6 @@ EOF
}
-# file layout:
-#TMP_PARTITIONS
-# disk partition-scheme
-
# go over each disk in $TMP_PARTITIONS and partition it
process_disks ()
{
@@ -349,6 +349,19 @@ process_disk ()
partition $1 "$2"
}
+# $1 fs_string
+parse_filesystem_string ()
+{
+ fs="$1"
+ fs_type=` cut -d ';' -f 1 <<< $fs`
+ fs_create=` cut -d ';' -f 2 <<< $fs`
+ fs_mountpoint=` cut -d ';' -f 3 <<< $fs`
+ fs_mount=` cut -d ';' -f 4 <<< $fs`
+ fs_opts=` cut -d ';' -f 5 <<< $fs`
+ fs_label=` cut -d ';' -f 6 <<< $fs`
+ fs_params=` cut -d ';' -f 7 <<< $fs`
+}
+
generate_filesystem_list ()
{
@@ -359,13 +372,7 @@ generate_filesystem_list ()
then
for fs in `sed 's/|/ /g' <<< $fs_string` # this splits multiple fs'es up, or just takes the one if there is only one (lvm vg's can have more then one lv)
do
- fs_type=` cut -d ';' -f 1 <<< $fs`
- fs_create=` cut -d ';' -f 2 <<< $fs`
- fs_mountpoint=` cut -d ';' -f 3 <<< $fs`
- fs_mount=` cut -d ';' -f 4 <<< $fs`
- fs_opts=` cut -d ';' -f 5 <<< $fs`
- fs_label=` cut -d ';' -f 6 <<< $fs`
- fs_params=` cut -d ';' -f 7 <<< $fs`
+ parse_filesystem_string "$fs"
echo "$part $part_type $part_label $fs_type $fs_create $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params" >> $TMP_FILESYSTEMS
done
fi
@@ -377,7 +384,7 @@ generate_filesystem_list ()
# process all entries in $TMP_BLOCKDEVICES, create all blockdevices and filesystems and mount them correctly
process_filesystems ()
{
- debug "process_filesystems Called. checking all entries in $TMP_BLOCKDEVICES"
+ debug 'FS' "process_filesystems Called. checking all entries in $TMP_BLOCKDEVICES"
rm -f $TMP_FSTAB
generate_filesystem_list
returncode=0
@@ -397,26 +404,26 @@ process_filesystems ()
then
if check_is_in "$fs_id" "${done_filesystems[@]}"
then
- debug "$fs_id ->Already done"
+ debug 'FS' "$fs_id ->Already done"
else
# We can't always do -b on the lvm VG. because the devicefile sometimes doesn't exist for a VG. vgdisplay to the rescue!
if [ "$part_type" = lvm-vg ] && vgdisplay $part | grep -q 'VG Name' # $part is a lvm VG and it exists. note that vgdisplay exists 0 when the requested vg doesn't exist.
then
- debug "$fs_id ->Still need to do it: Making the filesystem on a vg volume"
+ debug 'FS' "$fs_id ->Still need to do it: Making the filesystem on a vg volume"
infofy "Making $fs_type filesystem on $part" disks
process_filesystem $part $fs_type $fs_create $fs_mountpoint no_mount $fs_opts $fs_label $fs_params && done_filesystems+=("$fs_id") || returncode=1
elif [ "$part_type" != lvm-pv -a -b "$part" ] # $part is not a lvm PV and it exists
then
- debug "$fs_id ->Still need to do it: Making the filesystem on a non-pv volume"
+ debug 'FS' "$fs_id ->Still need to do it: Making the filesystem on a non-pv volume"
infofy "Making $fs_type filesystem on $part" disks
process_filesystem $part $fs_type $fs_create $fs_mountpoint no_mount $fs_opts $fs_label $fs_params && done_filesystems+=("$fs_id") || returncode=1
elif [ "$part_type" = lvm-pv ] && pvdisplay ${fs_params//:/ } >/dev/null # $part is a lvm PV. all needed lvm pv's exist. note that pvdisplay exits 5 as long as one of the args doesn't exist
then
- debug "$fs_id ->Still need to do it: Making the filesystem on a pv volume"
+ debug 'FS' "$fs_id ->Still need to do it: Making the filesystem on a pv volume"
infofy "Making $fs_type filesystem on $part" disks
process_filesystem ${part/+/} $fs_type $fs_create $fs_mountpoint no_mount $fs_opts $fs_label $fs_params && done_filesystems+=("$fs_id") || returncode=1
else
- debug "$fs_id ->Cannot do right now..."
+ debug 'FS' "$fs_id ->Cannot do right now..."
open_items=1
fi
fi
@@ -431,7 +438,7 @@ process_filesystems ()
# phase 2: mount all filesystems in the vfs in the correct order. (also swapon where appropriate)
infofy "Phase 2: Mounting filesystems" disks
- sort -t \ -k 6 $TMP_FILESYSTEMS | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+ while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
do
if [ "$fs_mountpoint" != no_mountpoint ]
then
@@ -442,7 +449,7 @@ process_filesystems ()
infofy "Swaponning $part" disks
process_filesystem $part $fs_type no $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params || returncode=1
fi
- done
+ done < <(sort -t \ -k 6 $TMP_FILESYSTEMS)
BLOCK_ROLLBACK_USELESS=0
[ $returncode -eq 0 ] && infofy "Done processing filesystems/blockdevices" disks 1 && return 0
@@ -463,7 +470,7 @@ rollback_filesystems ()
infofy "Phase 1: Umounting all specified mountpoints" disks
done_umounts= # We translate some devices back to their original (eg /dev/sda3+ -> /dev/sda3 for lvm PV's). No need to bother user twice for such devices.
- sort -t \ -k 6 $TMP_FILESYSTEMS | tac | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+ while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
do
if [ "$fs_type" = swap ]
then
@@ -487,7 +494,7 @@ rollback_filesystems ()
fi
fi
fi
- done
+ done < <(sort -t \ -k 6 $TMP_FILESYSTEMS | tac)
# phase 2: destruct blockdevices listed in $BLOCK_DATA if they would exist already, in the correct order (first lvm LV, then VG, then PV etc)
@@ -512,7 +519,7 @@ rollback_filesystems ()
then
if pvdisplay $real_part &>/dev/null
then
- debug "$part ->Cannot do right now..."
+ debug 'FS' "$part ->Cannot do right now..."
open_items=1
else
infofy "Attempting destruction of device $part (type $part_type)" disks
@@ -523,7 +530,7 @@ rollback_filesystems ()
fi
fi
else
- debug "Skipping destruction of device $part (type $part_type) because it doesn't exist"
+ debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
fi
elif [ "$part_type" = lvm-pv ] # Can be in use for: lvm-vg
then
@@ -531,7 +538,7 @@ rollback_filesystems ()
then
if vgdisplay -v 2>/dev/null | grep -q $real_part # check if it's in use
then
- debug "$part ->Cannot do right now..."
+ debug 'FS' "$part ->Cannot do right now..."
open_items=1
else
infofy "Attempting destruction of device $part (type $part_type)" disks
@@ -542,7 +549,7 @@ rollback_filesystems ()
fi
fi
else
- debug "Skipping destruction of device $part (type $part_type) because it doesn't exist"
+ debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
fi
elif [ "$part_type" = lvm-vg ] #Can be in use for: lvm-lv
then
@@ -551,7 +558,7 @@ rollback_filesystems ()
open_lv=`vgdisplay -c $part 2>/dev/null | cut -d ':' -f6`
if [ $open_lv -gt 0 ]
then
- debug "$part ->Cannot do right now..."
+ debug 'FS' "$part ->Cannot do right now..."
open_items=1
else
infofy "Attempting destruction of device $part (type $part_type)" disks
@@ -562,7 +569,7 @@ rollback_filesystems ()
fi
fi
else
- debug "Skipping destruction of device $part (type $part_type) because it doesn't exist"
+ debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
fi
elif [ "$part_type" = lvm-lv ] #Can be in use for: dm_crypt or raw. we don't need to care about raw (it will be unmounted so it can be destroyed)
then
@@ -570,7 +577,7 @@ rollback_filesystems ()
then
if cryptsetup isLuks $part &>/dev/null
then
- debug "$part ->Cannot do right now..."
+ debug 'FS' "$part ->Cannot do right now..."
open_items=1
else
infofy "Attempting destruction of device $part (type $part_type)" disks
@@ -581,7 +588,7 @@ rollback_filesystems ()
fi
fi
else
- debug "Skipping destruction of device $part (type $part_type) because it doesn't exist"
+ debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
fi
else
die_error "Unrecognised partition type $part_type for partition $part. This should never happen. please report this"
@@ -597,6 +604,7 @@ rollback_filesystems ()
fi
[ -n "$warnings" ] && infofy "Rollback failed" disks 1 && show_warning "Rollback problems" "Some problems occurred while rolling back: $warnings.\n Thisk needs to be fixed before retrying disk/filesystem creation or restarting the installer" && return 1
infofy "Rollback succeeded" disks 1
+ done_filesystems=
BLOCK_ROLLBACK_USELESS=1
return 0
}
@@ -616,7 +624,7 @@ process_filesystem ()
{
[ "$2" != lvm-lv ] && [ -z "$1" -o ! -b "$1" ] && die_error "process_filesystem needs a partition as \$1" # Don't do this for lv's. It's a hack to workaround non-existence of VG device files.
[ -z "$2" ] && die_error "process_filesystem needs a filesystem type as \$2"
- debug "process_filesystem $@"
+ debug 'FS' "process_filesystem $@"
part=$1
fs_type=$2
fs_create=${3:-yes}
@@ -674,16 +682,17 @@ process_filesystem ()
BLOCK_ROLLBACK_USELESS=0
if [ "$fs_type" = swap ]
then
- debug "swaponning $part"
+ debug 'FS' "swaponning $part"
swapon $part >$LOG 2>&1 || ( show_warning 'Swapon' "Error activating swap: swapon $part" ; return 1 )
else
[ "$fs_mount" = runtime ] && dst=$fs_mountpoint
[ "$fs_mount" = target ] && dst=$var_TARGET_DIR$fs_mountpoint
- debug "mounting $part on $dst"
+ debug 'FS' "mounting $part on $dst"
mkdir -p $dst &>/dev/null # directories may or may not already exist
mount -t $fs_type $part $dst >$LOG 2>&1 || ( show_warning 'Mount' "Error mounting $part on $dst" ; return 1 )
if [ "$fs_mount" = target -a $fs_mountpoint = '/' ]
then
+ debug FS "setting \$PART_ROOT to $part"
PART_ROOT=$part
fi
fi
@@ -736,24 +745,30 @@ get_filesystem_program ()
# $1 blockdevice
-# $2 standard SI for 1000*n, IEC for 1024*n (optional. defaults to SI)
-# --> Note that if you do SI on a partition, you get the size of the entire disk, so for now you need IEC for single partitions
-# output will be in $BLOCKDEVICE_SIZE in MB/MiB
-# WARNING: hdparm works - by design - only for ide/sata. not scsi et al
-# TODO: clean up all disk size related stuff. see http://bugs.archlinux.org/task/12949
+# $2 unit: B, KiB, kB, MiB, MB, GiB or GB. defaults to B (we follow IEEE 1541-2002 )
+# output will be in $BLOCKDEVICE_SIZE
get_blockdevice_size ()
{
[ -b "$1" ] || die_error "get_blockdevice_size needs a blockdevice as \$1 ($1 given)"
- standard=${2:-SI}
-
- if [ "$standard" = SI ]
+ unit=${2:-B}
+ allowed_units=(B KiB kB MiB MB GiB GB)
+ if ! check_is_in $unit "${allowed_units[@]}"
then
- BLOCKDEVICE_SIZE=$(hdparm -I $1 | grep -F '1000*1000' | sed "s/^.*:[ \t]*\([0-9]*\) MBytes.*$/\1/")
- elif [ "$standard" = IEC ]
- then
- #NOTE: unreliable method: on some interwebs they say 1 block = 512B, on other internets they say 1 block = 1kiB. 1kiB seems to work for me. don't sue me if it doesn't for you
- #blocks=`fdisk -s $1` || show_warning "Fdisk problem" "Something failed when trying to do fdisk -s $1"
- #BLOCKDEVICE_SIZE=$(($blocks/1024))
- BLOCKDEVICE_SIZE=$((`fdisk -l $1 | sed -n '2p' | cut -d' ' -f5`/1024))
+ die_error "Unrecognized unit $unit!"
fi
+
+ # NOTES about older, deprecated methods:
+ # - BLOCKDEVICE_SIZE=$(hdparm -I $1 | grep -F '1000*1000' | sed "s/^.*:[ \t]*\([0-9]*\) MBytes.*$/\1/") # if you do this on a partition, you get the size of the entire disk ! + hdparm only supports sata and ide. not scsi.
+ # - unreliable method: on some interwebs they say 1 block = 512B, on other internets they say 1 block = 1kiB. 1kiB seemed to work for me.
+ # blocks=`fdisk -s $1` || show_warning "Fdisk problem" "Something failed when trying to do fdisk -s $1"
+ # BLOCKDEVICE_SIZE=$(($blocks/1024))
+
+ bytes=$((`fdisk -l $1 2>/dev/null | sed -n '2p' | cut -d' ' -f5`))
+ [ $unit = B ] && BLOCKDEVICE_SIZE=$bytes
+ [ $unit = KiB ] && BLOCKDEVICE_SIZE=$((bytes/2**10)) # /1024
+ [ $unit = kB ] && BLOCKDEVICE_SIZE=$((bytes/10**3)) # /1000
+ [ $unit = MiB ] && BLOCKDEVICE_SIZE=$((bytes/2**20)) # ...
+ [ $unit = MB ] && BLOCKDEVICE_SIZE=$((bytes/10**6))
+ [ $unit = GiB ] && BLOCKDEVICE_SIZE=$((bytes/2**30))
+ [ $unit = GB ] && BLOCKDEVICE_SIZE=$((bytes/10**9))
}
diff --git a/src/core/libs/lib-flowcontrol.sh b/src/core/libs/lib-flowcontrol.sh
new file mode 100755
index 0000000..8106310
--- /dev/null
+++ b/src/core/libs/lib-flowcontrol.sh
@@ -0,0 +1,216 @@
+#!/bin/bash
+
+usage ()
+{
+ msg="aif -p <procedurename> Select a procedure # If given, this *must* be the first option
+ -i <dia/cli> Override interface type (optional)
+ -d Explicitly enable debugging (optional)
+ -l Explicitly enable logging to file (optional)
+ -h Help: show usage (optional)\n
+If the procedurename starts with 'http://' it will be wget'ed. Otherwise it's assumed to be a procedure in the VFS tree
+If the procedurename is prefixed with '<modulename>/' it will be loaded from user module <modulename>.\n
+For more info, see the README which you can find in /usr/share/aif/docs\n
+Available procedures:
+==core==
+`find $LIB_CORE/procedures -type f | sed \"s#$LIB_CORE/procedures/##\" | sort`
+==user==
+`find $LIB_USER/*/procedures -type f 2>/dev/null | sed \"s#$LIB_USER/\(.*\)/procedures/#\1/#\" | sort`"
+ [ -n "$procedure" ] && msg="$msg\nProcedure ($procedure) specific options:\n$var_ARGS_USAGE"
+
+ echo -e "$msg"
+}
+
+
+# $1 module name
+load_module ()
+{
+ [ -z "$1" ] && die_error "load_module needs a module argument"
+ log "Loading module $1 ..."
+ path=$LIB_USER/"$1"
+ [ "$1" = core ] && path=$LIB_CORE
+
+ for submodule in lib #procedure don't load procedures automatically!
+ do
+ if [ ! -d "$path/${submodule}s" ]
+ then
+ # ignore this problem for not-core modules
+ [ "$1" = core ] && die_error "$path/${submodule}s does not exist. something is horribly wrong with this installation"
+ else
+ shopt -s nullglob
+ for i in "$path/${submodule}s"/*
+ do
+ # I have the habit of editing files while testing, don't source my backup files!
+ [[ "$i" == *~ ]] && continue
+
+ load_${submodule} "$1" "`basename "$i"`"
+ done
+ fi
+ done
+
+}
+
+
+# $1 module name
+# $2 procedure name
+load_procedure()
+{
+ [ -z "$1" ] && die_error "load_procedure needs a module as \$1 and procedure as \$2"
+ [ -z "$2" ] && die_error "load_procedure needs a procedure as \$2"
+ if [ "$1" = 'http:' ]
+ then
+ log "Loading procedure $2 ..."
+ procedure=$RUNTIME_DIR/aif-procedure-downloaded-`basename $2`
+ wget "$2" -q -O $procedure >/dev/null || die_error "Could not download procedure $2"
+ else
+ log "Loading procedure $1/procedures/$2 ..."
+ procedure=$LIB_USER/"$1"/procedures/"$2"
+ [ "$1" = core ] && procedure=$LIB_CORE/procedures/"$2"
+ fi
+ [ -f "$procedure" ] && source "$procedure" || die_error "Something went wrong while sourcing procedure $procedure"
+}
+
+
+# $1 module name
+# $2 library name
+load_lib ()
+{
+ [ -z "$1" ] && die_error "load_library needs a module als \$1 and library as \$2"
+ [ -z "$2" ] && die_error "load_library needs a library as \$2"
+ log "Loading library $1/libs/$2 ..."
+ lib=$LIB_USER/"$1"/libs/"$2"
+ [ "$1" = core ] && lib=$LIB_CORE/libs/"$2"
+ source $lib || die_error "Something went wrong while sourcing library $lib"
+}
+
+
+# $1 phase/worker
+# $2 phase/worker name
+# $3... extra args for phase/worker (optional)
+execute ()
+{
+ [ -z "$1" -o -z "$2" ] && debug 'MAIN' "execute $@" && die_error "Use the execute function like this: execute <type> <name> with type=phase/worker"
+ [ "$1" != phase -a "$1" != worker ] && debug 'MAIN' "execute $@" && die_error "execute's first argument must be a valid type (phase/worker)"
+ PWD_BACKUP=`pwd`
+ object=$1_$2
+
+ if [ "$1" = worker ]
+ then
+ log "*** Executing worker $2"
+ if type -t $object | grep -q function
+ then
+ shift 2
+ $object "$@"
+ ret=$?
+ exit_var=exit_$object
+ read $exit_var <<< $ret # maintain exit status of each worker
+ else
+ die_error "$object is not defined!"
+ fi
+ elif [ "$1" = phase ]
+ then
+ log "******* Executing phase $2"
+ exit_var=exit_$object
+ read $exit_var <<< 0
+ # TODO: for some reason the hack below does not work (tested in virtualbox), even though it really should. Someday I must get indirect array variables working and clean this up...
+ # debug 'MAIN' "\$1: $1, \$2: $2, \$object: $object, \$exit_$object: $exit_object"
+ # debug 'MAIN' "declare: `declare | grep -e "^${object}=" | cut -d"=" -f 2-`"
+ # props to jedinerd at #bash for this hack.
+ # eval phase=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
+ #debug 'MAIN' "\$phase: $phase - ${phase[@]}"
+ unset phase
+ [ "$2" = preparation ] && phase=( "${phase_preparation[@]}" )
+ [ "$2" = basics ] && phase=( "${phase_basics[@]}" )
+ [ "$2" = system ] && phase=( "${phase_system[@]}" )
+ [ "$2" = finish ] && phase=( "${phase_finish[@]}" )
+ # worker_str contains the name of the worker and optionally any arguments
+ for worker_str in "${phase[@]}"
+ do
+ debug 'MAIN' "Loop iteration. \$worker_str: $worker_str"
+ execute worker $worker_str || read $exit_var <<< $? # assign last failing exit code to exit_phase_<phasename>, if any.
+ done
+ ret=${!exit_var}
+ fi
+
+ debug 'MAIN' "Execute(): $object exit state was $ret"
+ cd $PWD_BACKUP
+ return $ret
+}
+
+
+# check if a phase/worker executed sucessfully
+# returns 0 if ok, the phase/workers' exit state otherwise (and returns 1 if not executed yet)
+# $1 phase/worker
+# $2 phase/worker name
+ended_ok ()
+{
+ [ -z "$1" -o -z "$2" ] && die_error "Use the ended_ok function like this: ended_ok <type> <name> with type=phase/worker"
+ [ "$1" != phase -a "$1" != worker ] && die_error "ended_ok's first argument must be a valid type (phase/worker)"
+ object=$1_$2
+ exit_var=exit_$object
+ debug 'MAIN' "Ended_ok? -> Exit state of $object was: ${!exit_var} (if empty. it's not executed yet)"
+ [ "${!exit_var}" = '0' ] && return 0
+ [ "${!exit_var}" = '' ] && return 1
+ return ${!exit_var}
+}
+
+
+depend_module ()
+{
+ load_module "$1"
+}
+
+
+depend_procedure ()
+{
+ load_procedure "$1" "$2"
+}
+
+
+start_process ()
+{
+ execute phase preparation
+ execute phase basics
+ execute phase system
+ execute phase finish
+}
+
+
+show_report () #TODO: abstract UI method (cli/dia)
+{
+ echo "Execution Report:"
+ echo "-----------------"
+ for phase in preparation basics system finish
+ do
+ object=phase_$phase
+ exit_var=exit_$object
+ ret=${!exit_var}
+ echo -n "Phase $phase: "
+ [ "$ret" = "0" ] && echo "Success" || echo "Failed"
+ eval phase_array=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
+ for worker_str in "${phase_array[@]}"
+ do
+ worker=${worker_str%% *}
+ exit_var=exit_worker_$worker
+ ret=${!exit_var}
+ echo -n " > Worker $worker: "
+ [ "$ret" = "0" ] && echo "Success" || echo "Failed"
+ done
+ done
+}
+
+
+start_installer ()
+{
+ log "################## START OF INSTALLATION ##################"
+ cleanup_runtime
+}
+
+
+# use this function to stop the installation procedure.
+# $1 exit code (optional)
+stop_installer ()
+{
+ log "-------------- STOPPING INSTALLATION ----------"
+ cleanup_runtime
+ exit $1
+}
diff --git a/src/core/libs/lib-misc.sh b/src/core/libs/lib-misc.sh
index 01c291f..1acebac 100644
--- a/src/core/libs/lib-misc.sh
+++ b/src/core/libs/lib-misc.sh
@@ -1,9 +1,38 @@
#!/bin/bash
+# runs a process and makes sure the output is shown to the user. sets the exit state of the executed program ($<identifier>_exitcode) so the caller can show a concluding message.
+# when in dia mode, we will run the program and a dialog instance in the background (cause that's just how it works with dia)
+# when in cli mode, the program will just run in the foreground. technically it can be run backgrounded but then we need tail -f (cli_follow_progress), and we miss the beginning of the output if it goes too fast, not to mention because of the sleep in run_background
+# $1 identifier
+# $2 command (will be eval'ed)
+# $3 logfile
+# $4 title to show while process is running
+run_controlled ()
+{
+ [ -z "$1" ] && die_error "run_controlled: please specify an identifier to keep track of the command!"
+ [ -z "$2" ] && die_error "run_controlled needs a command to execute!"
+ [ -z "$3" ] && die_error "run_controlled needs a logfile to redirect output to!"
+ [ -z "$4" ] && die_error "run_controlled needs a title to show while your process is running!"
+
+ if [ "$var_UI_TYPE" = dia ]
+ then
+ run_background $1 "$2" $3
+ follow_progress " $4 " $3 $BACKGROUND_PID # dia mode ignores the pid. cli uses it to know how long it must do tail -f
+ wait_for $1 $FOLLOW_PID
+ else
+ notify "$4"
+ var_exit=${1}_exitcode
+ eval "$2" >>$3 2>&1
+ read $var_exit <<< $?
+ fi
+}
+
+
# run a process in the background, and log it's stdout and stderr to a specific logfile
# returncode is stored in $<identifier>_exitcode
-# $1 identifier
+# pid of the backgrounded wrapper process is stored in BACKGROUND_PID (this is _not_ the pid of $2)
+# $1 identifier -> WARNING: do never ever use -'s or other fancy characters here. only numbers, letters and _ please. (because $<identifier>_exitcode must be a valid bash variable!)
# $2 command (will be eval'ed)
# $3 logfile
run_background ()
@@ -12,47 +41,50 @@ run_background ()
[ -z "$2" ] && die_error "run_background needs a command to execute!"
[ -z "$3" ] && die_error "run_background needs a logfile to redirect output to!"
- debug "run_background called. identifier: $1, command: $2, logfile: $3"
+ debug 'MISC' "run_background called. identifier: $1, command: $2, logfile: $3"
( \
- touch $RUNTIME_DIR/.$1-running
- debug "run_background starting $1: $2 >>$3 2>&1"
+ touch $RUNTIME_DIR/aif-$1-running
+ debug 'MISC' "run_background starting $1: $2 >>$3 2>&1"
[ -f $3 ] && echo -e "\n\n\n" >>$3
echo "STARTING $1 . Executing $2 >>$3 2>&1\n" >> $3;
var_exit=${1}_exitcode
eval "$2" >>$3 2>&1
- read $var_exit <<< $? #TODO: bash complains about 'not a valid identifier'
- debug "run_background done with $1: exitcode (\$$1_exitcode): "${!var_exit}" .Logfile $3" #TODO ${!var_exit} doesn't show anything --> maybe fixed now
+ read $var_exit <<< $?
+ debug 'MISC' "run_background done with $1: exitcode (\$$1_exitcode): ${!var_exit} .Logfile $3"
echo >> $3
- rm -f $RUNTIME_DIR/.$1-running
+ rm -f $RUNTIME_DIR/aif-$1-running
) &
+ BACKGROUND_PID=$!
sleep 2
}
# wait until a process is done
-# $1 identifier
+# $1 identifier. WARNING! see above
+# $2 pid of a process to kill when done (optional). useful for dialog --no-kill --tailboxbg's pid.
wait_for ()
{
[ -z "$1" ] && die_error "wait_for needs an identifier to known on which command to wait!"
- while [ -f $RUNTIME_DIR/.$1-running ]
+ while [ -f $RUNTIME_DIR/aif-$1-running ]
do
- #TODO: follow_progress dialog mode = nonblocking (so check and sleep is good), cli mode (tail -f )= blocking? (so check is probably not needed as it will be done)
sleep 1
done
- kill $(cat $ANSWER) #TODO: this may not work when mode = cli
+ [ -n "$2" ] && kill $2
}
-# $1 set (array) haystack
-# $2 needle
+# $1 needle
+# $2 set (array) haystack
check_is_in ()
{
- [ -z "$1" ] && debug "check_is_in $1 $2" && die_error "check_is_in needs a non-empty needle as \$2 and a haystack as \$1!" # haystack can be empty though
+ [ -z "$1" ] && die_error "check_is_in needs a non-empty needle as \$1 and a haystack as \$2!(got: check_is_in '$1' '$2'" # haystack can be empty though
+ NEEDLE=$1
+ HAYSTACK=$2
- local pattern="$1" element
+ local pattern="$NEEDLE" element
shift
for element
do
@@ -66,5 +98,27 @@ check_is_in ()
cleanup_runtime ()
{
mkdir -p $RUNTIME_DIR || die_error "Cannot create $RUNTIME_DIR"
- rm -rf $RUNTIME_DIR/.dia* &>/dev/null
+ rm -rf $RUNTIME_DIR/aif-dia* &>/dev/null
+}
+
+
+dohwclock() {
+ infofy "Syncing hardwareclock to systemclock ..."
+ if [ "$HARDWARECLOCK" = "UTC" ]; then
+ HWCLOCK_PARAMS="$HWCLOCK_PARAMS --utc"
+ else
+ HWCLOCK_PARAMS="$HWCLOCK_PARAMS --localtime"
+ fi
+
+ [ ! -d /var/lib/hwclock ] && mkdir -p /var/lib/hwclock
+ if [ ! -f /var/lib/hwclock/adjtime ]; then
+ echo "0.0 0 0.0" > /var/lib/hwclock/adjtime # what the hell is this for???
+ fi
+ hwclock $HWCLOCK_PARAMS #tpowa does it without, but i would add --noadjtime here
}
+
+target_configure_initial_keymap_font ()
+{
+ [ -n "$var_KEYMAP" ] && sed -i "s/^KEYMAP=.*/KEYMAP=\"$var_KEYMAP\"/" ${var_TARGET_DIR}/etc/rc.conf
+ [ -n "$var_CONSOLEFONT" ] && sed -i "s/^CONSOLEFONT=.*/CONSOLEFONT=\"$var_CONSOLEFONT\"/" ${var_TARGET_DIR}/etc/rc.conf
+} \ No newline at end of file
diff --git a/src/core/libs/lib-network.sh b/src/core/libs/lib-network.sh
index 9ed96b2..85e597c 100644
--- a/src/core/libs/lib-network.sh
+++ b/src/core/libs/lib-network.sh
@@ -17,7 +17,6 @@ target_configure_network()
sed -i "s#$INTERFACE 192.168.0.2#$INTERFACE $IPADDR#g" ${var_TARGET_DIR}/etc/rc.conf
sed -i "s#netmask 255.255.255.0#netmask $SUBNET#g" ${var_TARGET_DIR}/etc/rc.conf
sed -i "s#broadcast 192.168.0.255#broadcast $BROADCAST#g" ${var_TARGET_DIR}/etc/rc.conf
- sed -i "s#INTERFACES=(eth0)#INTERFACES=($INTERFACE)#g" ${var_TARGET_DIR}/etc/rc.conf
if [ "$GW" != "" ]; then
sed -i "s#gw 192.168.0.1#gw $GW#g" ${var_TARGET_DIR}/etc/rc.conf
sed -i "s#!gateway#gateway#g" ${var_TARGET_DIR}/etc/rc.conf
@@ -26,6 +25,7 @@ target_configure_network()
else
sed -i "s#eth0=\"eth0.*#$INTERFACE=\"dhcp\"#g" ${var_TARGET_DIR}/etc/rc.conf
fi
+ sed -i "s#INTERFACES=(eth0)#INTERFACES=($INTERFACE)#g" ${var_TARGET_DIR}/etc/rc.conf
if [ "$PROXY_HTTP" != "" ]; then
echo "export http_proxy=$PROXY_HTTP" >> ${var_TARGET_DIR}/etc/profile.d/proxy.sh;
diff --git a/src/core/libs/lib-pacman.sh b/src/core/libs/lib-pacman.sh
index 4497074..a104cee 100644
--- a/src/core/libs/lib-pacman.sh
+++ b/src/core/libs/lib-pacman.sh
@@ -78,7 +78,7 @@ do
then
add_pacman_repo target ${repo} "Include = $var_MIRRORLIST"
else
- add_pacman_repo target ${repo} "Server = ${serverurl/\/\$repo\//\/$repo\/}" # replace literal '/$repo/' in the serverurl string by "/$repo/" where $repo is our variable.
+ add_pacman_repo target ${repo} "Server = ${serverurl/\$repo/$repo}" # replace literal '$repo' in the serverurl string by "$repo" where $repo is our variable.
fi
done
# Set up the necessary directories for pacman use
@@ -132,3 +132,30 @@ pacman_what_is_this_for ()
! [ -d /var/lib/pacman ] && mkdir -p /var/lib/pacman
}
+list_package_groups ()
+{
+ $PACMAN_TARGET -Sg
+}
+
+
+# List the packages in one or more repos or groups. output is one or more lines, each line being like this:
+# <repo/group name> packagename [version, if $1=repo]
+# $1 repo or group
+# $2 one or more repo or group names
+# TODO: check the validity of the specified names in $2
+list_packages ()
+{
+ [ "$1" = repo -o "$1" = group ] || die_error "list_packages \$1 must be repo or group. not $1!"
+ [ "$1" = repo ] && $PACMAN_TARGET -Sl $2
+ [ "$1" = group ] && $PACMAN_TARGET -Sg $2
+}
+
+# find out the group to which one or more packages belong
+# $1 packages separated by spaces
+# output format: multiple lines, each line like:
+# <pkgname> <group>
+# TODO: check $1
+which_group ()
+{
+ PACKAGE_GROUPS=`$PACMAN_TARGET -Si $1| awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }'`
+}
diff --git a/src/core/libs/lib-software.sh b/src/core/libs/lib-software.sh
index 726d20f..384cab4 100644
--- a/src/core/libs/lib-software.sh
+++ b/src/core/libs/lib-software.sh
@@ -1,7 +1,7 @@
#!/bin/bash
-TMP_MKINITCPIO_LOG=$RUNTIME_DIR/mkinitcpio.log
-TMP_PACMAN_LOG=$RUNTIME_DIR/pacman.log
+TMP_MKINITCPIO_LOG=$LOG_DIR/mkinitcpio.log
+TMP_PACMAN_LOG=$LOG_DIR/pacman.log
# run_mkinitcpio() taken from setup. adapted a lot
# runs mkinitcpio on the target system, displays output
@@ -9,9 +9,7 @@ run_mkinitcpio()
{
target_special_fs on
- run_background mkinitcpio "chroot $var_TARGET_DIR /sbin/mkinitcpio -p kernel26" $TMP_MKINITCPIO_LOG
- follow_progress "Rebuilding initcpio images ..." $TMP_MKINITCPIO_LOG
- wait_for mkinitcpio
+ run_controlled mkinitcpio "chroot $var_TARGET_DIR /sbin/mkinitcpio -p kernel26" $TMP_MKINITCPIO_LOG "Rebuilding initcpio images ..."
target_special_fs off
@@ -24,16 +22,20 @@ run_mkinitcpio()
# installpkg(). taken from setup. modified bigtime
# performs package installation to the target system
installpkg() {
- notify "Package installation will begin now. You can watch the output in the progress window. Please be patient."
+ ALL_PACKAGES=$var_TARGET_PACKAGES
+ [ -n "$TARGET_GROUPS" ] && ALL_PACKAGES="$ALL_PACKAGES "`list_packages group "$TARGET_GROUPS" | awk '{print $2}'`
+ ALL_PACKAGES=`echo $ALL_PACKAGES`
+ [ -z "$ALL_PACKAGES" ] && die_error "No packages/groups specified to install"
+
target_special_fs on
- run_background pacman-installpkg "$PACMAN_TARGET --noconfirm -S $TARGET_PACKAGES" $TMP_PACMAN_LOG #TODO: There may be something wrong here. See http://projects.archlinux.org/?p=installer.git;a=commitdiff;h=f504e9ecfb9ecf1952bd8dcce7efe941e74db946 ASKDEV (Simo)
- follow_progress " Installing... Please Wait " $TMP_PACMAN_LOG
- wait_for pacman-installpkg
-
+ notify "Package installation will begin now. You can watch the output in the progress window. Please be patient."
+
+ #TODO: There may be something wrong here. See http://projects.archlinux.org/?p=installer.git;a=commitdiff;h=f504e9ecfb9ecf1952bd8dcce7efe941e74db946 ASKDEV (Simo)
+ run_controlled pacman_installpkg "$PACMAN_TARGET --noconfirm -S $ALL_PACKAGES" $TMP_PACMAN_LOG "Installing... Please Wait"
local _result=''
- if [ ${pacman-installpkg_exitcode} -ne 0 ]; then
+ if [ ${pacman_installpkg_exitcode} -ne 0 ]; then
_result="Installation Failed (see errors below)"
echo -e "\nPackage Installation FAILED." >>$TMP_PACMAN_LOG
else
@@ -46,14 +48,13 @@ installpkg() {
target_special_fs off
sync
- #return ${pacman-installpkg_exitcode} TODO: fix this. there is something wrong here
- return 0
+ return ${pacman_installpkg_exitcode}
}
# auto_locale(). taken from setup
# enable glibc locales from rc.conf and build initial locale DB
-target_configure_inital_locale()
+target_configure_initial_locale()
{
for i in $(grep "^LOCALE" ${var_TARGET_DIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
sed -i -e "s/^#$i/$i/g" ${var_TARGET_DIR}/etc/locale.gen
diff --git a/src/core/libs/lib-ui-interactive.sh b/src/core/libs/lib-ui-interactive.sh
index 8fdc5dc..cb80c11 100644
--- a/src/core/libs/lib-ui-interactive.sh
+++ b/src/core/libs/lib-ui-interactive.sh
@@ -26,9 +26,9 @@ interactive_configure_system()
while true; do
DEFAULT=no
[ -n "$FILE" ] && DEFAULT="$FILE"
- helptext=
- grep -q '^/dev/mapper' $TMP_FSTAB && helptext="Don't forget to add the appropriate modules for your /dev/mapper devices to mkinitcpio.conf" #TODO: we can improve this a bit
- ask_option $DEFAULT "Configuration" "$helptext" \
+ helptext="Note that if you want to change any file not listed here (unlikely) you can go to another tty and update ${var_TARGET_DIR}/etc/<filename> yourself"
+ grep -q '^/dev/mapper' $TMP_FSTAB && helptext="$helptext\nDon't forget to add the appropriate modules for your /dev/mapper devices to mkinitcpio.conf" #TODO: we can improve this a bit
+ ask_option $DEFAULT "Configuration" "$helptext" required \
"/etc/rc.conf" "System Config" \
"/etc/fstab" "Filesystem Mountpoints" \
"/etc/mkinitcpio.conf" "Initramfs Config" \
@@ -38,12 +38,13 @@ interactive_configure_system()
"/etc/hosts.deny" "Denied Network Services" \
"/etc/hosts.allow" "Allowed Network Services" \
"/etc/locale.gen" "Glibc Locales" \
+ "/etc/pacman.conf" "Pacman.conf" \
"$var_MIRRORLIST" "Pacman Mirror List" \
"Root-Password" "Set the root password" \
- "Return" "Return to Main Menu" || FILE="Return"
+ "Done" "Return to Main Menu" || return 1
FILE=$ANSWER_OPTION
- if [ "$FILE" = "Return" -o -z "$FILE" ]; then # exit
+ if [ "$FILE" = "Done" ]; then # exit
break
elif [ "$FILE" = "Root-Password" ]; then # non-file
while true; do
@@ -52,60 +53,78 @@ interactive_configure_system()
else #regular file
$EDITOR ${var_TARGET_DIR}${FILE}
fi
+
+ # if user edited /etc/rc.conf, add the hostname to /etc/hosts if it's not already there.
+ # note that if the user edits rc.conf several times to change the hostname more then once, we will add them all to /etc/hosts. this is not perfect, but to avoid this, too much code would be required (feel free to prove me wrong :))
+ if [ "$FILE" = "/etc/rc.conf" ]
+ then
+ HOSTNAME=`sed -n '/^HOSTNAME/s/HOSTNAME=//p' ${var_TARGET_DIR}${FILE} | sed 's/"//g'`
+ if ! grep '127\.0\.0\.1' ${var_TARGET_DIR}/etc/hosts | grep -q "$HOSTNAME"
+ then
+ sed -i "s/127\.0\.0\.1.*/& $HOSTNAME/" ${var_TARGET_DIR}/etc/hosts
+ fi
+ fi
done
+ # temporary backup files are not useful anymore past this point.
+ find "${var_TARGET_DIR}/etc/" -name '*~' -delete &>/dev/null
+ return 0
}
-# set_clock()
-# prompts user to set hardware clock and timezone
-#
-# params: none
-# returns: 1 on failure
-interactive_set_clock()
-{
- # utc or local?
- ask_option no "Clock configuration" "Is your hardware clock in UTC or local time?" "UTC" " " "local" " " || return 1
- HARDWARECLOCK=$ANSWER_OPTION
-
- # timezone?
+interactive_timezone () {
ask_timezone || return 1
- TIMEZONE=$ANSWER_TIMEZONE
+ TIMEZONE=$ANSWER_TIMEZONE
+ infofy "Setting Timezone to $TIMEZONE"
+ [ -e /etc/localtime ] && rm -f /etc/localtime #why do we do this?? tpowa?
+ dohwclock
+}
+
+
+
+interactive_time () {
+ # utc or localtime?
+ ask_option no "Clock configuration" "Is your hardware clock in UTC or local time?" required "UTC" " " "localtime" " " || return 1
+ HARDWARECLOCK=$ANSWER_OPTION
+
+ dohwclock
+
+ if which ntpdate >/dev/null && ask_yesno "'ntpdate' was detected on your system.\n\nDo you want to use 'ntpdate' for syncing your clock,\nby using the internet clock pool?\n(You need a working internet connection for doing this!)" yes #TODO: only propose if network ok.
+ then
+ if ntpdate pool.ntp.org >/dev/null
+ then
+ notify "Synced clock with internet pool successfully.\n\nYour current time is now:\n$(date)"
+ else
+ show_warning 'Ntp failure' "An error has occured, time was not changed!"
+ fi
+ fi
+
+ # display and ask to set date/time
+ ask_datetime
- # set system clock from hwclock - stolen from rc.sysinit
- local HWCLOCK_PARAMS=""
- if [ "$HARDWARECLOCK" = "UTC" ]
- then
- HWCLOCK_PARAMS="$HWCLOCK_PARAMS --utc"
- else
- HWCLOCK_PARAMS="$HWCLOCK_PARAMS --localtime"
- fi
if [ "$TIMEZONE" != "" -a -e "/usr/share/zoneinfo/$TIMEZONE" ]
then
/bin/rm -f /etc/localtime
/bin/cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
fi
- /sbin/hwclock --hctosys $HWCLOCK_PARAMS --noadjfile
-
- # display and ask to set date/time
- ask_datetime
# save the time
date -s "$ANSWER_DATETIME" || show_warning "Date/time setting failed" "Something went wrong when doing date -s $ANSWER_DATETIME"
- /sbin/hwclock --systohc $HWCLOCK_PARAMS --noadjfile
-
- return 0
+ dohwclock
}
+
+
+
interactive_autoprepare()
{
DISCS=$(finddisks)
if [ $(echo $DISCS | wc -w) -gt 1 ]
then
notify "Available Disks:\n\n$(_getavaildisks)\n"
- ask_option no 'Harddrive selection' "Select the hard drive to use" $(finddisks 1 _) || return 1
+ ask_option no 'Harddrive selection' "Select the hard drive to use" required $(finddisks 1 _) || return 1
DISC=$ANSWER_OPTION
else
DISC=$DISCS
@@ -113,7 +132,7 @@ interactive_autoprepare()
DISC=${DISC// /} # strip all whitespace. we need this for some reason.TODO: find out why
- get_blockdevice_size $DISC SI
+ get_blockdevice_size $DISC MiB
FSOPTS=
which `get_filesystem_program ext2` &>/dev/null && FSOPTS="$FSOPTS ext2 Ext2"
which `get_filesystem_program ext3` &>/dev/null && FSOPTS="$FSOPTS ext3 Ext3"
@@ -123,12 +142,12 @@ interactive_autoprepare()
which `get_filesystem_program jfs` &>/dev/null && FSOPTS="$FSOPTS jfs JFS"
which `get_filesystem_program vfat` &>/dev/null && FSOPTS="$FSOPTS vfat VFAT"
- ask_number "Enter the size (MB) of your /boot partition. Recommended size: 100MB\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 16 $BLOCKDEVICE_SIZE || return 1
+ ask_number "Enter the size (MiB) of your /boot partition. Recommended size: 100MiB\n\nDisk space left: $BLOCKDEVICE_SIZE MiB" 16 $BLOCKDEVICE_SIZE 100 || return 1
BOOT_PART_SIZE=$ANSWER_NUMBER
BLOCKDEVICE_SIZE=$(($BLOCKDEVICE_SIZE-$BOOT_PART_SIZE))
- ask_number "Enter the size (MB) of your swap partition. Recommended size: 256MB\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 1 $BLOCKDEVICE_SIZE || return 1
+ ask_number "Enter the size (MiB) of your swap partition. Recommended size: 256MiB\n\nDisk space left: $BLOCKDEVICE_SIZE MiB" 1 $BLOCKDEVICE_SIZE 256 || return 1
SWAP_PART_SIZE=$ANSWER_NUMBER
BLOCKDEVICE_SIZE=$(($BLOCKDEVICE_SIZE-$SWAP_PART_SIZE))
@@ -136,15 +155,15 @@ interactive_autoprepare()
ROOT_PART_SET=""
while [ "$ROOT_PART_SET" = "" ]
do
- ask_number "Enter the size (MB) of your / partition. Recommended size:7500. The /home partition will use the remaining space.\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 1 $BLOCKDEVICE_SIZE || return 1
+ ask_number "Enter the size (MiB) of your / partition. Recommended size:7500. The /home partition will use the remaining space.\n\nDisk space left: $BLOCKDEVICE_SIZE MiB" 1 $BLOCKDEVICE_SIZE 7500 || return 1
ROOT_PART_SIZE=$ANSWER_NUMBER
- ask_yesno "$(($BLOCKDEVICE_SIZE-$ROOT_PART_SIZE)) MB will be used for your /home partition. Is this OK?" yes && ROOT_PART_SET=1 #TODO: when doing yes, cli mode prints option JFS all the time, dia mode goes back to disks menu
+ ask_yesno "$(($BLOCKDEVICE_SIZE-$ROOT_PART_SIZE)) MiB will be used for your /home partition. Is this OK?" yes && ROOT_PART_SET=1 #TODO: when doing yes, cli mode prints option JFS all the time, dia mode goes back to disks menu
done
CHOSEN_FS=""
while [ "$CHOSEN_FS" = "" ]
do
- ask_option no 'Filesystem selection' "Select a filesystem for / and /home:" $FSOPTS || return 1
+ ask_option no 'Filesystem selection' "Select a filesystem for / and /home:" required $FSOPTS || return 1
FSTYPE=$ANSWER_OPTION
ask_yesno "$FSTYPE will be used for / and /home. Is this OK?" yes && CHOSEN_FS=1
done
@@ -152,9 +171,6 @@ interactive_autoprepare()
ask_yesno "$DISC will be COMPLETELY ERASED! Are you absolutely sure?" || return 1
- # we assume a /dev/hdX format (or /dev/sdX)
- PART_ROOT="${DISC}3"
-
echo "$DISC $BOOT_PART_SIZE:ext2:+ $SWAP_PART_SIZE:swap $ROOT_PART_SIZE:$FSTYPE *:$FSTYPE" > $TMP_PARTITIONS
echo "${DISC}1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params" > $TMP_BLOCKDEVICES
@@ -191,7 +207,7 @@ interactive_partition() {
DISC=""
while true; do
# Prompt the user with a list of known disks
- ask_option no 'Disc selection' "Select the disk you want to partition (select DONE when finished)" $DISCS || return 1
+ ask_option no 'Disc selection' "Select the disk you want to partition (select DONE when finished)" required $DISCS || return 1
DISC=$ANSWER_OPTION
if [ "$DISC" = "OTHER" ]; then
ask_string "Enter the full path to the device you wish to partition" "/dev/sda" || return 1
@@ -249,7 +265,7 @@ interactive_filesystem ()
local old_fs_params=$fs_params
ask_option edit "Alter this $fs_type filesystem on $part ?" \
- "Alter $fs_type filesystem (label:$fs_label, mountpoint:$fs_mountpoint) on $part (type:$part_type, label:$part_label) ?" \
+ "Alter $fs_type filesystem (label:$fs_label, mountpoint:$fs_mountpoint) on $part (type:$part_type, label:$part_label) ?" required \
edit EDIT delete DELETE #TODO: nicer display if label is empty etc
# Don't alter, and return if user cancels
@@ -302,7 +318,7 @@ interactive_filesystem ()
else
default=
[ -n "$fs_type" ] && default="--default-item $fs_type"
- ask_option no "Select filesystem" "Select a filesystem for $part:" $FSOPTS || return 1
+ ask_option no "Select filesystem" "Select a filesystem for $part:" required $FSOPTS || return 1
fs_type=$ANSWER_OPTION
fi
@@ -351,10 +367,11 @@ interactive_filesystem ()
fi
if [ "$fs_type" = lvm-lv ]
then
- [ -z "$fs_params" ] && default='5G'
+ [ -z "$fs_params" ] && default='5000'
[ -n "$fs_params" ] && default="$fs_params"
- ask_string "Enter the size for this $fs_type on $part (suffix K,M,G,T,P,E. default is M)" "$default" || return 1
- fs_params=$ANSWER_STRING
+ ask_number "Enter the size for this $fs_type on $part in MiB" 1 0 "$default" || return 1 #TODO: can we get the upperlimit from somewhere?
+ # Lvm tools use binary units but have their own suffixes ( K,M,G,T,P,E, but they mean KiB, MiB etc)
+ fs_params="${ANSWER_NUMBER}M"
fi
if [ "$fs_type" = dm_crypt ]
then
@@ -412,7 +429,7 @@ remove_blockdevice ()
declare target_escaped=${target//\//\\/} # note: apparently no need to escape the '+' sign for sed.
declare target_escawk=${target_escaped/+/\\+} # ...but that doesn't count for awk
fs_string=`awk "/^$target_escawk / { print \$4}" $TMP_BLOCKDEVICES` #TODO: fs_string is the entire line, incl part?
- debug "Cleaning up partition $part (type $part_type, label $part_label). It has the following FS's on it: $fs_string"
+ debug 'UI-INTERACTIVE' "Cleaning up partition $part (type $part_type, label $part_label). It has the following FS's on it: $fs_string"
sed -i "/$target_escaped/d" $TMP_BLOCKDEVICES || show_warning "blockdevice removal" "Could not remove partition $part (type $part_type, label $part_label). This is a bug. please report it"
for fs in `sed 's/|/ /g' <<< $fs_string`
do
@@ -435,7 +452,7 @@ interactive_filesystems() {
ALLOK=0
while [ "$ALLOK" = 0 ]
do
- # Let the user make filesystems and mountpoints
+ # Let the user make filesystems and mountpoints. USERHAPPY becomes 1 when the user hits DONE.
USERHAPPY=0
while [ "$USERHAPPY" = 0 ]
@@ -449,16 +466,16 @@ interactive_filesystems() {
fs_display=${fs//;target/}
[ "$label" != no_label ] && label_display="($label)"
[ "$label" = no_label ] && label_display=
- if [ -b "${part/+/}" ] && get_blockdevice_size ${part/+/} IEC # test -b <-- exit's 0, test -b '' exits >0.
+ if [ -b "${part/+/}" ] && get_blockdevice_size ${part/+/} MiB # test -b <-- exit's 0, test -b '' exits >0.
then
- infostring="${type},${BLOCKDEVICE_SIZE}MB${label_display}->$fs_display" # add size in MB for existing blockdevices (eg not for mapper devices that are not yet created yet) #TODO: ${BLOCKDEVICE_SIZE} is empty sometimes?
+ infostring="${type},${BLOCKDEVICE_SIZE}MiB${label_display}->$fs_display" # add size in MiB for existing blockdevices (eg not for mapper devices that are not yet created yet)
else
infostring="${type}${label_display}->$fs_display"
fi
menu_list="$menu_list $part $infostring" #don't add extra spaces, dialog doesn't like that.
done < $TMP_BLOCKDEVICES
- ask_option no "Manage filesystems" "Here you can manage your filesystems, block devices and virtual devices (device mapper). Note that you don't *need* to specify opts, labels or extra params if you're not using lvm, dm_crypt, etc." $menu_list DONE _
+ ask_option no "Manage filesystems" "Here you can manage your filesystems, block devices and virtual devices (device mapper). Note that you don't *need* to specify opts, labels or extra params if you're not using lvm, dm_crypt, etc." required $menu_list DONE _
[ $? -gt 0 ] && USERHAPPY=1 && break
[ "$ANSWER_OPTION" == DONE ] && USERHAPPY=1 && break
@@ -479,53 +496,52 @@ interactive_filesystems() {
then
for lv in `sed 's/|/ /g' <<< $fs`
do
- label=$( cut -d ';' -f 6 <<< $lv)
- size=$(cut -d ';' -f 7 <<< $lv)
+ label=$(cut -d ';' -f 6 <<< $lv)
+ size=$( cut -d ';' -f 7 <<< $lv)
list="$list $label $size"
done
- else
- list="XXX no-LV's-defined-yet-make-a-new-one"
fi
list="$list empty NEW"
- ask_option empty "Manage LV's on this VG" "Edit/create new LV's on this VG:" $list
- EDIT_VG=$ANSWER_OPTION
- if [ "$ANSWER_OPTION" = XXX -o "$ANSWER_OPTION" = empty ]
- then
- # a new LV must be created on this VG
- if interactive_filesystem $part $part_type $part_label ''
+ ask_option empty "Manage LV's on this VG" "Edit/create new LV's on this VG:" required $list && {
+ EDIT_VG=$ANSWER_OPTION
+ if [ "$ANSWER_OPTION" = empty ]
then
- if [ "$NEW_FILESYSTEM" != no_fs ]
+ # a new LV must be created on this VG
+ if interactive_filesystem $part $part_type $part_label ''
then
- [ -n "$fs" ] && fs="$fs|$NEW_FILESYSTEM"
- [ -z "$fs" ] && fs=$NEW_FILESYSTEM
+ if [ "$NEW_FILESYSTEM" != no_fs ]
+ then
+ [ -n "$fs" ] && fs="$fs|$NEW_FILESYSTEM"
+ [ -z "$fs" ] && fs=$NEW_FILESYSTEM
+ fi
fi
+ else
+ # an existing LV will be edited and it's settings updated
+ for lv in `sed 's/|/ /g' <<< $fs`
+ do
+ label=$(cut -d ';' -f 6 <<< $lv)
+ [ "$label" = "$EDIT_VG" ] && found_lv="$lv"
+ done
+ interactive_filesystem $part $part_type $part_label "$found_lv"
+ newfs=
+ for lv in `sed 's/|/ /g' <<< $fs`
+ do
+ label=$(cut -d ';' -f 6 <<< $lv)
+ if [ "$label" != "$EDIT_VG" ]
+ then
+ add=$lv
+ elif [ $NEW_FILESYSTEM != no_fs ]
+ then
+ add=$NEW_FILESYSTEM
+ else
+ add=
+ fi
+ [ -n "$add" -a -n "$newfs" ] && newfs="$newfs|$add"
+ [ -n "$add" -a -z "$newfs" ] && newfs=$add
+ done
+ fs=$newfs
fi
- else
- # an existing LV will be edited and it's settings updated
- for lv in `sed 's/|/ /g' <<< $fs`
- do
- label=$(cut -d ';' -f 6 <<< $lv)
- [ "$label" = "$EDIT_VG" ] && found_lv="$lv"
- done
- interactive_filesystem $part $part_type $part_label "$found_lv"
- newfs=
- for lv in `sed 's/|/ /g' <<< $fs`
- do
- label=$(cut -d ';' -f 6 <<< $lv)
- if [ "$label" != "$EDIT_VG" ]
- then
- add=$lv
- elif [ $NEW_FILESYSTEM != no_fs ]
- then
- add=$NEW_FILESYSTEM
- else
- add=
- fi
- [ -n "$add" -a -n "$newfs" ] && newfs="$newfs|$add"
- [ -n "$add" -a -z "$newfs" ] && newfs=$add
- done
- fs=$newfs
- fi
+ }
else
interactive_filesystem $part $part_type "$part_label" "$fs"
[ $? -eq 0 ] && fs=$NEW_FILESYSTEM
@@ -550,7 +566,14 @@ interactive_filesystems() {
str="The following issues have been detected:\n"
[ -n "$errors" ] && str="$str\n - Errors: $errors"
[ -n "$warnings" ] && str="$str\n - Warnings: $warnings"
- ask_yesno "$str\n Do you want to back to fix (one of) these issues?" || ALLOK=1 # TODO: we should ask the user if he wants to continue, return or abort.
+ [ -n "$errors" ] && str="$str\nIt is highly recommended you go back to fix at least the errors."
+ str="$str\nIf you hit cancel, we will abort here and go back to the menu"
+ if ask_option back "Issues detected. what do you want to do?" "$str" required back "go back to fix the issues" ignore "continue, ignoring the issues"
+ then
+ [ "$ANSWER_OPTION" == ignore ] && ALLOK=1
+ else
+ return 1
+ fi
else
ALLOK=1
fi
@@ -571,42 +594,43 @@ interactive_filesystems() {
# returns: 1 on error
interactive_select_packages() {
- notify "Package selection is split into two stages. First you will select package categories that contain packages you may be interested in. Then you will be presented with a full list of packages for each category, allowing you to fine-tune.\n\n"
+ # set up our install location if necessary and sync up so we can get package lists
+ target_prepare_pacman || ( show_warning 'Pacman preparation failure' "Pacman preparation failed! Check $LOG for errors." && return 1 )
- # set up our install location if necessary and sync up
- # so we can get package lists
- target_prepare_pacman || ( show_warning 'Pacman preparation failure' "Pacman preparation failed! Check $LOG for errors." && return 1 )
+ repos=`list_pacman_repos target`
+ notify "Package selection is split into two stages. First you will select package groups that contain packages you may be interested in. Then you will be presented with a full list of packages for each group, allowing you to fine-tune.\n\n
+Note that right now the packages (and groups) selection is limited to the repos available at this time ($repos). One you have your Arch system up and running, you have access to more repositories and packages."
# show group listing for group selection, base is ON by default, all others are OFF
- local _catlist="base ^ ON"
- for i in $($PACMAN_TARGET -Sg | sed "s/^base$/ /g"); do
- _catlist="${_catlist} ${i} - OFF"
+ local _grouplist="base ^ ON"
+ for i in $(list_package_groups | sed "s/^base$/ /g"); do
+ _grouplist="${_grouplist} ${i} - OFF"
done
- ask_checklist "Select Package Categories\nDO NOT deselect BASE unless you know what you're doing!" $_catlist || return 1
- _catlist=$ANSWER_CHECKLIST # _catlist now contains all categories (the tags from the dialog checklist)
+ ask_checklist "Select Package groups\nDO NOT deselect BASE unless you know what you're doing!" $_grouplist || return 1
+ _grouplist=$ANSWER_CHECKLIST # _grouplist now contains all groups (the tags from the dialog checklist)
# assemble a list of packages with groups, marking pre-selected ones
# <package> <group> <selected>
- local _pkgtmp="$($PACMAN_TARGET -Sl core | awk '{print $2}')" # all packages in core repository
+ local _pkgtmp="$(list_packages repo core | awk '{print $2}')" # all packages in core repository
local _pkglist=''
- $PACMAN_TARGET -Si $_pkgtmp | awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }' > $ANSWER
- while read pkgname pkgcat; do
+ which_group "$_pkgtmp"
+ while read pkgname pkggroup; do
# check if this package is in a selected group
# slightly ugly but sorting later requires newlines in the variable
- if [ "${_catlist/"\"$pkgcat\""/XXXX}" != "${_catlist}" ]; then
- _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} ON")"
+ if [ "${_grouplist/"\"$pkggroup\""/XXXX}" != "${_grouplist}" ]; then
+ _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkggroup} ON")"
else
- _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} OFF")"
+ _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkggroup} OFF")"
fi
- done < $ANSWER
+ done <<< "$PACKAGE_GROUPS"
- # sort by category
+ # sort by group
_pkglist="$(echo "$_pkglist" | sort -f -k 2)"
ask_checklist "Select Packages To Install." $_pkglist || return 1
- TARGET_PACKAGES=$ANSWER_CHECKLIST # contains now all package names
+ var_TARGET_PACKAGES=$ANSWER_CHECKLIST # contains now all package names
return 0
}
@@ -626,23 +650,23 @@ interactive_runtime_network() {
return 1
fi
- ask_option no "Interface selection" "Select a network interface" $ifaces || return 1 #TODO: code used originaly --nocancel here. what's the use? + make ok button 'select'
+ ask_option no "Interface selection" "Select a network interface" required $ifaces || return 1 #TODO: code used originaly --nocancel here. what's the use? + make ok button 'select'
INTERFACE=$ANSWER_OPTION
- ask_yesno "Do you want to use DHCP?"
- if [ $? -eq 0 ]; then
+ if ask_yesno "Do you want to use DHCP?"
+ then
infofy "Please wait. Polling for DHCP server on $INTERFACE..."
- killall dhcpd
- killall -9 dhcpd
- sleep 1
- dhcpcd $INTERFACE >$LOG 2>&1
- if [ $? -ne 0 ]; then
- notify "Failed to run dhcpcd. See $LOG for details."
+ dhcpcd -k $INTERFACE >$LOG 2>&1
+ if ! dhcpcd $INTERFACE >$LOG 2>&1
+ then
+ show_warning "Dhcpcd problem" "Failed to run dhcpcd. See $LOG for details."
return 1
fi
- if [ ! $(ifconfig $INTERFACE | grep 'inet addr:') ]; then
- notify "DHCP request failed." || return 1
+ if ! ifconfig $INTERFACE | grep -q 'inet addr:'
+ then
+ show_warning "Dhcpcd problem" "DHCP request failed. dhcpcd returned 0 but no ip configured for $INTERFACE"
+ return 1
fi
S_DHCP=1
else
@@ -669,16 +693,20 @@ interactive_runtime_network() {
esac
done
echo "running: ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up" >$LOG
- ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up >$LOG 2>&1 || notify "Failed to setup $INTERFACE interface." || return 1
- if [ "$GW" != "" ]; then
+ if ! ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up >$LOG 2>&1
+ then
+ show_warning "Ifconfig problem" "Failed to setup interface $INTERFACE"
+ return 1
+ fi
+ if [ -n "$GW" ]; then
route add default gw $GW >$LOG 2>&1 || notify "Failed to setup your gateway." || return 1
fi
- if [ "$PROXY_HTTP" = "" ]; then
+ if [ -z "$PROXY_HTTP" ]; then
unset http_proxy
else
export http_proxy=$PROXY_HTTP
fi
- if [ "$PROXY_FTP" = "" ]; then
+ if [ -z "$PROXY_FTP" ]; then
unset ftp_proxy
else
export ftp_proxy=$PROXY_FTP
@@ -696,6 +724,7 @@ interactive_install_grub() {
[ ! -f $grubmenu ] && show_warning "No grub?" "Error: Couldn't find $grubmenu. Is GRUB installed?" && return 1
# try to auto-configure GRUB...
+ debug 'UI-INTERACTIVE' "install_grub \$PART_ROOT $PART_ROOT \$GRUB_OK $GRUB_OK"
if [ -n "$PART_ROOT" -a "$GRUB_OK" != '1' ] ; then
GRUB_OK=0
grubdev=$(mapdev $PART_ROOT)
@@ -758,7 +787,7 @@ EOF
notify "No hard drives were found"
return 1
fi
- ask_option no "Boot device selection" "Select the boot device where the GRUB bootloader will be installed (usually the MBR and not a partition)." $DEVS || return 1
+ ask_option no "Boot device selection" "Select the boot device where the GRUB bootloader will be installed (usually the MBR and not a partition)." required $DEVS || return 1
ROOTDEV=$ANSWER_OPTION
infofy "Installing the GRUB bootloader..."
cp -a $var_TARGET_DIR/usr/lib/grub/i386-pc/* $var_TARGET_DIR/boot/grub/
@@ -780,7 +809,7 @@ EOF
fi
ask_yesno "Do you have your system installed on software raid?\nAnswer 'YES' to install grub to another hard disk." no
if [ $? -eq 0 ]; then
- ask_option no "Boot partition device selection" "Please select the boot partition device, this cannot be autodetected!\nPlease redo grub installation for all partitions you need it!" $DEVS || return 1
+ ask_option no "Boot partition device selection" "Please select the boot partition device, this cannot be autodetected!\nPlease redo grub installation for all partitions you need it!" required $DEVS || return 1
bootpart=$ANSWER_OPTION
fi
bootpart=$(mapdev $bootpart)
@@ -827,7 +856,7 @@ interactive_select_source()
var_FILE_URL="file:///src/core/pkg"
var_SYNC_URL=
- ask_option no "Source selection" "Please select an installation source" \
+ ask_option no "Source selection" "Please select an installation source" required \
"1" "CD-ROM or OTHER SOURCE" \
"2" "FTP/HTTP" || return 1
@@ -861,7 +890,7 @@ interactive_select_mirror() {
notify "Keep in mind ftp.archlinux.org is throttled.\nPlease select another mirror to get full download speed."
# FIXME: this regex doesn't honor commenting
MIRRORS=$(egrep -o '((ftp)|(http))://[^/]*' "${var_MIRRORLIST}" | sed 's|$| _|g')
- ask_option no "Mirror selection" "Select an FTP/HTTP mirror" $MIRRORS "Custom" "_" || return 1
+ ask_option no "Mirror selection" "Select an FTP/HTTP mirror" required $MIRRORS "Custom" "_" || return 1
local _server=$ANSWER_OPTION
if [ "${_server}" = "Custom" ]; then
ask_string "Enter the full URL to core repo." "ftp://ftp.archlinux.org/core/os/$var_ARCH" || return 1
@@ -884,7 +913,7 @@ interactive_get_editor() {
which nano &>/dev/null && EDITOR_OPTS+=("nano" "nano (easier)")
which joe &>/dev/null && EDITOR_OPTS+=("joe" "joe's editor")
which vi &>/dev/null && EDITOR_OPTS+=("vi" "vi (advanced)")
- ask_option no "Text editor selection" "Select a Text Editor to Use" "${EDITOR_OPTS[@]}"
+ ask_option no "Text editor selection" "Select a Text Editor to Use" required "${EDITOR_OPTS[@]}"
#TODO: this code could be a little bit cleaner.
case $ANSWER_OPTION in
"nano") EDITOR="nano" ;;
diff --git a/src/core/libs/lib-ui.sh b/src/core/libs/lib-ui.sh
index 2315394..50d087a 100644
--- a/src/core/libs/lib-ui.sh
+++ b/src/core/libs/lib-ui.sh
@@ -1,24 +1,38 @@
#!/bin/bash
+# Note that $var_UI_TYPE may not be set here. especially if being loaded in the "early bootstrap" phase
+
# TODO: implement 'retry until user does it correctly' everywhere
# TODO: at some places we should check if $1 etc is only 1 word because we often depend on that
# TODO: standardize. eg everything $1= question/title, $2=default
# TODO: figure out something to make dia windows always big enough, yet fit nicely in the terminal
-# Taken from setup. we store dialog output in a file. TODO: can't we do this with variables? ASKDEV
-ANSWER=$RUNTIME_DIR/.dialog-answer
+# Taken from setup. we store dialog output in a file. TODO: a variable would be cleaner
+ANSWER=$RUNTIME_DIR/aif-dialog-answer
DIA_MENU_TEXT="Use the UP and DOWN arrows to navigate menus. Use TAB to switch between buttons and ENTER to select."
-DIA_SUCCESSIVE_ITEMS=$RUNTIME_DIR/.dia-successive-items
+DIA_SUCCESSIVE_ITEMS=$RUNTIME_DIR/aif-dia-successive-items
+
+
+# get keymap/font (maybe configured by aif allready in another process or even in another shell)
+# otherwise, take default keymap and consolefont as configured in /etc/rc.conf. can be overridden
+# Note that the vars in /etc/rc.conf can also be empty!
+[ -e $RUNTIME_DIR/aif-keymap ] && var_KEYMAP=` cat $RUNTIME_DIR/aif-keymap`
+[ -e $RUNTIME_DIR/aif-consolefont ] && var_CONSOLEFONT=`cat $RUNTIME_DIR/aif-consolefont`
+[ -z "$var_KEYMAP" ] && source /etc/rc.conf && var_KEYMAP=$KEYMAP
+[ -z "$var_CONSOLEFONT" ] && source /etc/rc.conf && var_CONSOLEFONT=$CONSOLEFONT
+
+
### Functions that your code can use. Cli/dialog mode is fully transparant. This library takes care of it ###
+
# display error message and die
+# Do not call other functions like debug, notify, .. here because that might cause loops!
die_error ()
{
- debug "die_error: ERROR: $@"
- notify "ERROR: $@"
- exit 2
+ echo "ERROR: $@" >&2
+ exit 2
}
@@ -28,32 +42,32 @@ die_error ()
# $3 type of item. msg or text if it's a file. (optional. defaults to msg)
show_warning ()
{
- [ -z "$1" ] && die_error "show_warning needs a title"
- [ -z "$2" ] && die_error "show_warning needs an item to show"
- [ -n "$3" -a "$3" != msg -a "$3" != text ] && die_error "show_warning \$3 must be text or msg"
- type=msg
- [ -n "$3" ] && type=$3
- debug "show_warning '$1': $2 ($type)"
- if [ "$var_UI_TYPE" = dia ]
- then
- _dia_DIALOG --title "$1" --exit-label "Continue" --${type}box "$2" 18 70 || die_error "dialog could not show --${type}box $2. often this means a file does not exist"
- else
- echo "WARNING: $1"
- [ "${type}" = msg ] && echo -e "$2"
- [ "${type}" = text ] && (cat $2 || die_error "Could not cat $2")
- fi
+ [ -z "$1" ] && die_error "show_warning needs a title"
+ [ -z "$2" ] && die_error "show_warning needs an item to show"
+ [ -n "$3" -a "$3" != msg -a "$3" != text ] && die_error "show_warning \$3 must be text or msg"
+ type=msg
+ [ -n "$3" ] && type=$3
+ debug 'UI' "show_warning '$1': $2 ($type)"
+ if [ "$var_UI_TYPE" = dia ]
+ then
+ _dia_DIALOG --title "$1" --exit-label "Continue" --${type}box "$2" 0 0 || die_error "dialog could not show --${type}box $2. often this means a file does not exist"
+ else
+ echo "WARNING: $1"
+ [ "${type}" = msg ] && echo -e "$2"
+ [ "${type}" = text ] && (cat $2 || die_error "Could not cat $2")
+ fi
return 0
}
-
-
+
+
#notify user
notify ()
{
- debug "notify: $@"
+ debug 'UI' "notify: $@"
if [ "$var_UI_TYPE" = dia ]
then
- _dia_DIALOG --msgbox "$@" 20 50
+ _dia_DIALOG --msgbox "$@" 0 0
else
echo -e "$@"
fi
@@ -70,7 +84,7 @@ infofy () #TODO: when using successive things, the screen can become full and yo
{
successive=${2:-0}
succ_last=${3:-0}
- debug "infofy: $1"
+ debug 'UI' "infofy: $1"
if [ "$var_UI_TYPE" = dia ]
then
str="$1"
@@ -80,44 +94,47 @@ infofy () #TODO: when using successive things, the screen can become full and yo
str=`cat $DIA_SUCCESSIVE_ITEMS-$successive`
fi
[ "$succ_last" = 1 ] && rm $DIA_SUCCESSIVE_ITEMS-$successive
- _dia_DIALOG --infobox "$str" 20 50
+ _dia_DIALOG --infobox "$str" 0 0
else
echo -e "$1"
fi
}
-
# logging of stuff
log ()
{
+ mkdir -p $LOG_DIR || die_error "Cannot create log directory"
str="[LOG] `date +"%Y-%m-%d %H:%M:%S"` $@"
- if [ "$var_UI_TYPE" = dia ]
- then
- echo -e "$str" >$LOG
- else
- echo -e "$str" >$LOG
- fi
+ echo -e "$str" > $LOG || die_error "Cannot log $str to $LOG"
- [ "$LOG_TO_FILE" = 1 ] && echo -e "$str" >> $LOGFILE
+ [ "$LOG_TO_FILE" = 1 ] && ( echo -e "$str" >> $LOGFILE || die_error "Cannot log $str to $LOGFILE" )
}
+# $1 = one or more categories (separated by spaces) from: MAIN, PROCEDURE, UI, UI-INTERACTIVE, FS, MISC, NETWORK, PACMAN, SOFTWARE
+# You should always at least specify where you are (main, procedure or the name of the lib) and optionally further specification: eg in a ui function that works with pacman.
+# This is very useful in ui-interactive where we always work with something else.
+# $2 = string to log
debug ()
{
- str="[DEBUG] $@"
+ valid_cats=(MAIN PROCEDURE UI UI-INTERACTIVE FS MISC NETWORK PACMAN SOFTWARE)
+ for cat in $1
+ do
+ check_is_in $cat "${valid_cats[@]}" || die_error "debug \$1 contains a value ($cat) which is not a valid debug category"
+ done
+ [ -n "$2" ] || die_error "debug \$2 cannot be empty"
+
+ mkdir -p $LOG_DIR || die_error "Cannot create log directory"
if [ "$DEBUG" = "1" ]
then
- if [ "$var_UI_TYPE" = dia ]
- then
- echo -e "$str" > $LOG
- else
- echo -e "$str" > $LOG
- fi
- [ "$LOG_TO_FILE" = 1 ] && echo -e "$str" >> $LOGFILE
- fi
+ str="[DEBUG $1 ] $2"
+ echo -e "$str" > $LOG || die_error "Cannot debug $str to $LOG"
+ [ "$LOG_TO_FILE" = 1 ] && ( echo -e "$str" >> $LOGFILE || die_error "Cannot debug $str to $LOGFILE" )
+ fi
}
+
# taken from setup
printk()
{
@@ -129,14 +146,17 @@ printk()
# TODO: pass disks as argument to decouple backend logic
-# Get a list of available disks for use in the "Available disks" dialogs. This
-# will print the disks as follows, getting size info from hdparm:
-# /dev/sda: 640133 MBytes (640 GB)
-# /dev/sdb: 640135 MBytes (640 GB)
+# Get a list of available disks for use in the "Available disks" dialogs.
+# Something like:
+# /dev/sda: 640133 MiB (640 GiB)
+# /dev/sdb: 640135 MiB (640 GiB)
_getavaildisks()
{
- # NOTE: to test as non-root, stick in a 'sudo' before the hdparm call
- for i in $(finddisks); do echo -n "$i: "; hdparm -I $i | grep -F '1000*1000' | sed "s/.*1000:[ \t]*\(.*\)/\1/"; echo "\n"; done
+ for i in $(finddisks)
+ do
+ get_blockdevice_size $i MiB
+ echo "$i: $BLOCKDEVICE_SIZE MiB ($(($BLOCKDEVICE_SIZE/2**10)) GiB)\n"
+ done
}
@@ -147,7 +167,7 @@ _getavaildisks()
ask_checklist ()
{
[ -z "$1" ] && die_error "ask_checklist needs a question!"
- [ -z "$4" ] && debug "ask_checklist args: $@" && die_error "ask_checklist makes only sense if you specify at least 1 thing (tag,item and ON/OFF switch)"
+ [ -z "$4" ] && debug 'UI' "ask_checklist args: $@" && die_error "ask_checklist makes only sense if you specify at least 1 thing (tag,item and ON/OFF switch)"
[ "$var_UI_TYPE" = dia ] && { _dia_ask_checklist "$@" ; return $? ; }
[ "$var_UI_TYPE" = cli ] && { _cli_ask_checklist "$@" ; return $? ; }
}
@@ -163,17 +183,18 @@ ask_datetime ()
# ask for a number.
# $1 question
# $2 lower limit (optional)
-# $3 upper limit (optional)
-# $4 default : TODO implement in cli
-# echo's the number the user said
+# $3 upper limit (optional. set 0 for none)
+# $4 default (optional)
+# sets $ANSWER_NUMBER to the number the user specified
# returns 1 if the user cancelled or did not enter a numeric, 0 otherwise
ask_number ()
{
[ -z "$1" ] && die_error "ask_number needs a question!"
- [ -n "$2" ] && [[ $2 = *[^0-9]* ]] && die_error "ask_number \$2 must be a number! not $2"
- [ -n "$3" ] && [[ $3 = *[^0-9]* ]] && die_error "ask_number \$3 must be a number! not $3"
- [ "$var_UI_TYPE" = dia ] && { _dia_ask_number "$1" "$2" "$3" ; return $? ; }
- [ "$var_UI_TYPE" = cli ] && { _cli_ask_number "$1" "$2" "$3" ; return $? ; }
+ [ -n "$2" ] && [[ "$2" = *[^0-9]* ]] && die_error "ask_number \$2 must be a number! not $2"
+ [ -n "$3" ] && [[ "$3" = *[^0-9]* ]] && die_error "ask_number \$3 must be a number! not $3"
+ [ -n "$4" ] && [[ "$4" = *[^0-9]* ]] && die_error "ask_number \$4 must be a number! not $4"
+ [ "$var_UI_TYPE" = dia ] && { _dia_ask_number "$1" $2 $3 $4; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_ask_number "$1" $2 $3 $4; return $? ; }
}
@@ -181,9 +202,11 @@ ask_number ()
# $1 default item (set to 'no' for none)
# $2 title
# $3 additional explanation (default: '')
-# shift;shift; $@ list of options. first tag. then name. (eg tagA itemA "tag B" 'item B' )
-# the response will be echoed to stdout. but also $ANSWER_OPTION will be set. take that because the former method seems to not work.
-# $? if user cancelled. 0 otherwise
+# $4 type (required or optional). '' means required. cancel labels will be 'Cancel' and 'Skip' respectively.
+# shift 4 ; $@ list of options. first tag. then name. (eg tagA itemA "tag B" 'item B' )
+
+# $ANSWER_OPTION : selected answer (if none selected: default (if available), or empty string otherwise). if user hits cancel or skip, this is an empty string.
+# $? : 0 if the user selected anything or skipped (when optional), when user cancelled: 1
ask_option ()
{
[ "$var_UI_TYPE" = dia ] && { _dia_ask_option "$@" ; return $? ; }
@@ -239,12 +262,14 @@ ask_yesno ()
# follow the progress of something by showing it's log, updating real-time
# $1 title
# $2 logfile
+# $3 pid to monitor. if process stopped, stop following (only used in cli mode)
follow_progress ()
{
[ -z "$1" ] && die_error "follow_progress needs a title!"
[ -z "$2" ] && die_error "follow_progress needs a logfile to follow!"
- [ "$var_UI_TYPE" = dia ] && { _dia_follow_progress "$1" "$2" ; return $? ; }
- [ "$var_UI_TYPE" = cli ] && { _cli_follow_progress "$1" "$2" ; return $? ; }
+ FOLLOW_PID=
+ [ "$var_UI_TYPE" = dia ] && { _dia_follow_progress "$@" ; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_follow_progress "$@" ; return $? ; }
}
@@ -280,10 +305,10 @@ _dia_ask_checklist ()
list="$list $1 $2 $3"
shift 3
done
- _dia_DIALOG --checklist "$str" 30 60 20 $list 2>$ANSWER
+ _dia_DIALOG --checklist "$str" 0 0 0 $list 2>$ANSWER
ret=$?
ANSWER_CHECKLIST=`cat $ANSWER`
- debug "_dia_ask_checklist: user checked ON: $ANSWER_CHECKLIST"
+ debug 'UI' "_dia_ask_checklist: user checked ON: $ANSWER_CHECKLIST"
return $ret
}
@@ -295,7 +320,7 @@ _dia_ask_datetime ()
local _date="$(cat $ANSWER)" # form like: 07/12/2008
dialog --timebox "Set the time.\nUse <TAB> to navigate and up/down to change values." 0 0 2> $ANSWER || return 1
local _time="$(cat $ANSWER)" # form like: 15:26:46
- debug "Date as specified by user $_date time: $_time"
+ debug 'UI' "Date as specified by user $_date time: $_time"
# DD/MM/YYYY hh:mm:ss -> MMDDhhmmYYYY.ss (date default format, set like date $ANSWER_DATETIME) Not enabled because there is no use for it i think.
# ANSWER_DATETIME=$(echo "$_date" "$_time" | sed 's#\(..\)/\(..\)/\(....\) \(..\):\(..\):\(..\)#\2\1\4\5\3\6#g')
@@ -310,17 +335,17 @@ _dia_ask_number ()
while true
do
str="$1"
- [ -n "$2" ] && str2="min $2"
- [ -n "$3" ] && str2="$str2 max $3"
+ [ -n $2 ] && str2="min $2"
+ [ -n $3 -a $3 != '0' ] && str2="$str2 max $3"
[ -n "$str2" ] && str="$str ( $str2 )"
- _dia_DIALOG --inputbox "$str" 8 65 "$4" 2>$ANSWER
+ _dia_DIALOG --inputbox "$str" 0 0 $4 2>$ANSWER
ret=$?
ANSWER_NUMBER=`cat $ANSWER`
if [[ $ANSWER_NUMBER = *[^0-9]* ]] #TODO: handle exit state
then
show_warning "$ANSWER_NUMBER is not a number! try again."
else
- if [ -n "$3" -a $ANSWER_NUMBER -gt $3 ]
+ if [ -n "$3" -a $3 != '0' -a $ANSWER_NUMBER -gt $3 ]
then
show_warning "$ANSWER_NUMBER is bigger then the maximum,$3! try again."
elif [ -n "$2" -a $ANSWER_NUMBER -lt $2 ]
@@ -331,7 +356,7 @@ _dia_ask_number ()
fi
fi
done
- debug "_dia_ask_number: user entered: $ANSWER_NUMBER"
+ debug 'UI' "_dia_ask_number: user entered: $ANSWER_NUMBER"
[ -z "$ANSWER_NUMBER" ] && return 1
return $ret
}
@@ -343,16 +368,21 @@ _dia_ask_option ()
[ "$1" != 'no' ] && DEFAULT="--default-item $1"
[ -z "$2" ] && die_error "ask_option \$2 must be the title"
# $3 is optional more info
- [ -z "$5" ] && debug "_dia_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least one option (with tag and name)" #nothing wrong with only 1 option. it still shows useful info to the user
+ TYPE=${4:-required}
+ [ "$TYPE" != required -a "$TYPE" != optional ] && debug 'UI' "_dia_ask_option args: $@" && die_error "ask option \$4 must be required or optional or ''. not $TYPE"
+ [ -z "$6" ] && debug 'UI' "_dia_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least one option (with tag and name)" #nothing wrong with only 1 option. it still shows useful info to the user
DIA_MENU_TITLE=$2
EXTRA_INFO=$3
- shift 3
- _dia_DIALOG $DEFAULT --colors --title " $DIA_MENU_TITLE " --menu "$DIA_MENU_TEXT $EXTRA_INFO" 20 80 16 "$@" 2>$ANSWER
+ shift 4
+ CANCEL_LABEL=Cancel
+ [ $TYPE == optional ] && CANCEL_LABEL='Skip'
+ _dia_DIALOG $DEFAULT --cancel-label $CANCEL_LABEL --colors --title " $DIA_MENU_TITLE " --menu "$DIA_MENU_TEXT $EXTRA_INFO" 0 0 0 "$@" 2>$ANSWER
ret=$?
ANSWER_OPTION=`cat $ANSWER`
- debug "dia_ask_option: User choose $ANSWER_OPTION ($DIA_MENU_TITLE)"
- return $ret
+ debug 'UI' "dia_ask_option: ANSWER_OPTION: $ANSWER_OPTION, returncode (skip/cancel): $ret ($DIA_MENU_TITLE)"
+ [ $TYPE == required ] && return $ret
+ return 0 # TODO: check if dialog returned >0 because of an other reason then the user hitting 'cancel/skip'
}
@@ -372,7 +402,7 @@ _dia_ask_password ()
[ -n "$type_u" ] && read ${type_u}_PASSWORD < $ANSWER
[ -z "$type_u" ] && read PASSWORD < $ANSWER
cat $ANSWER
- debug "_dia_ask_password: user entered <<hidden>>"
+ debug 'UI' "_dia_ask_password: user entered <<hidden>>"
return $ret
}
@@ -380,10 +410,10 @@ _dia_ask_password ()
_dia_ask_string ()
{
exitcode=${3:-1}
- _dia_DIALOG --inputbox "$1" 8 65 "$2" 2>$ANSWER
+ _dia_DIALOG --inputbox "$1" 0 0 "$2" 2>$ANSWER
ret=$?
ANSWER_STRING=`cat $ANSWER`
- debug "_dia_ask_string: user entered $ANSWER_STRING"
+ debug 'UI' "_dia_ask_string: user entered $ANSWER_STRING"
[ -z "$ANSWER_STRING" ] && return $exitcode
return $ret
}
@@ -391,7 +421,25 @@ _dia_ask_string ()
_dia_ask_timezone ()
{
- ANSWER_TIMEZONE=`tzselect` #TODO: implement nicer then this
+ REGIONS=""
+ SET_ZONE=""
+ for i in $(grep ^[A-Z] /usr/share/zoneinfo/zone.tab | cut -f 3 | sed -e 's#/.*##g'| sort -u); do
+ REGIONS="$REGIONS $i -"
+ done
+ while [ "$SET_ZONE" != "1" ]; do
+ SET_REGION=""
+ ask_option no "Please select a region" '' required $REGIONS
+ region=ANSWER_OPTION
+ if [ $? -eq 0 ]; then
+ ZONES=""
+ for i in $(grep ^[A-Z] /usr/share/zoneinfo/zone.tab | grep $region/ | cut -f 3 | sed -e "s#$region/##g"| sort -u); do
+ ZONES="$ZONES $i -"
+ done
+ ask_option no "Please select a timezone" '' required $ZONES
+ zone=$ANSWER_OPTION
+ [ $? -gt 0 ] && ANSWER_TIMEZONE="$region/$zone" && return
+ fi
+ done
}
@@ -403,8 +451,8 @@ _dia_ask_yesno ()
[ -n "$2" ] && str="$str (default: $2)"
dialog --yesno "$str" $height 55 # returns 0 for yes, 1 for no
ret=$?
- [ $ret -eq 0 ] && debug "dia_ask_yesno: User picked YES"
- [ $ret -gt 0 ] && debug "dia_ask_yesno: User picked NO"
+ [ $ret -eq 0 ] && debug 'UI' "dia_ask_yesno: User picked YES"
+ [ $ret -gt 0 ] && debug 'UI' "dia_ask_yesno: User picked NO"
return $ret
}
@@ -413,7 +461,7 @@ _dia_follow_progress ()
{
title=$1
logfile=$2
- _dia_DIALOG --title "$1" --no-kill --tailboxbg "$2" 18 70 2>$ANSWER
+ FOLLOW_PID=`_dia_DIALOG --title "$1" --no-kill --tailboxbg "$2" 0 0 2>&1 >/dev/null`
}
@@ -444,7 +492,7 @@ _cli_ask_datetime ()
{
ask_string "Enter date [YYYY-MM-DD hh:mm:ss]"
ANSWER_DATETIME=$ANSWER_STRING
- debug "Date as picked by user: $ANSWER_STRING"
+ debug 'UI' "Date as picked by user: $ANSWER_STRING"
}
@@ -454,8 +502,9 @@ _cli_ask_number ()
while true
do
str="$1"
- [ -n "$2" ] && str2="min $2"
- [ -n "$3" ] && str2="$str2 max $3"
+ [ -n $2 ] && str2="min $2"
+ [ -n $3 -a $3 != '0' ] && str2="$str2 max $3"
+ [ -n $4 ] && str2=" default $4"
[ -n "$str2" ] && str="$str ( $str2 )"
echo "$str"
read ANSWER_NUMBER
@@ -463,10 +512,18 @@ _cli_ask_number ()
then
show_warning "$ANSWER_NUMBER is not a number! try again."
else
- break
+ if [ -n "$3" -a $3 != '0' -a $ANSWER_NUMBER -gt $3 ]
+ then
+ show_warning "$ANSWER_NUMBER is bigger then the maximum,$3! try again."
+ elif [ -n "$2" -a $ANSWER_NUMBER -lt $2 ]
+ then
+ show_warning "$ANSWER_NUMBER is smaller then the minimum,$2! try again."
+ else
+ break
+ fi
fi
done
- debug "cli_ask_number: user entered: $ANSWER_NUMBER"
+ debug 'UI' "cli_ask_number: user entered: $ANSWER_NUMBER"
[ -z "$ANSWER_NUMBER" ] && return 1
return 0
}
@@ -476,15 +533,17 @@ _cli_ask_option ()
{
#TODO: strip out color codes
#TODO: if user entered incorrect choice, ask him again
- DEFAULT=""
+ DEFAULT=
[ "$1" != 'no' ] && DEFAULT=$1 #TODO: if user forgot to specify a default (eg all args are 1 pos to the left, we can end up in an endless loop :s)
[ -z "$2" ] && die_error "ask_option \$2 must be the title"
# $3 is optional more info
- [ -z "$5" ] && debug "_dia_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least one option (with tag and name)" #nothing wrong with only 1 option. it still shows useful info to the user
+ TYPE=${4:-required}
+ [ "$TYPE" != required -a "$TYPE" != optional ] && debug 'UI' "_dia_ask_option args: $@" && die_error "ask option \$4 must be required or optional or ''. not $TYPE"
+ [ -z "$6" ] && debug 'UI' "_dia_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least one option (with tag and name)" #nothing wrong with only 1 option. it still shows useful info to the user
MENU_TITLE=$2
EXTRA_INFO=$3
- shift 3
+ shift 4
echo "$MENU_TITLE"
[ -n "$EXTRA_INFO" ] && echo "$EXTRA_INFO"
@@ -493,14 +552,20 @@ _cli_ask_option ()
echo "$1 ] $2"
shift 2
done
- echo "CANCEL ] CANCEL"
+ CANCEL_LABEL=CANCEL
+ [ $TYPE == optional ] && CANCEL_LABEL=SKIP
+ echo "$CANCEL_LABEL ] $CANCEL_LABEL"
[ -n "$DEFAULT" ] && echo -n " > [ $DEFAULT ] "
[ -z "$DEFAULT" ] && echo -n " > "
read ANSWER_OPTION
+ ret=0
[ -z "$ANSWER_OPTION" -a -n "$DEFAULT" ] && ANSWER_OPTION="$DEFAULT"
- debug "cli_ask_option: User choose $ANSWER_OPTION ($MENU_TITLE)"
- [ "$ANSWER_OPTION" = CANCEL ] && return 1
- return 0
+ [ "$ANSWER_OPTION" == CANCEL ] && ret=1 && ANSWER_OPTION=
+ [ "$ANSWER_OPTION" == SKIP ] && ret=0 && ANSWER_OPTION=
+ [ -z "$ANSWER_OPTION" -a "$TYPE" == required ] && ret=1
+
+ debug 'UI' "cli_ask_option: ANSWER_OPTION: $ANSWER_OPTION, returncode (skip/cancel): $ret ($MENU_TITLE)"
+ return $ret
}
@@ -532,7 +597,7 @@ _cli_ask_string ()
[ -n "$2" ] && echo "(Press enter for default. Default: $2)"
echo -n ">"
read ANSWER_STRING
- debug "cli_ask_string: User entered: $ANSWER_STRING"
+ debug 'UI' "cli_ask_string: User entered: $ANSWER_STRING"
if [ -z "$ANSWER_STRING" ]
then
if [ -n "$2" ]
@@ -562,10 +627,10 @@ _cli_ask_yesno ()
answer=`tr '[:upper:]' '[:lower:]' <<< $answer`
if [ "$answer" = y -o "$answer" = yes ] || [ -z "$answer" -a "$2" = yes ]
then
- debug "cli_ask_yesno: User picked YES"
+ debug 'UI' "cli_ask_yesno: User picked YES"
return 0
else
- debug "cli_ask_yesno: User picked NO"
+ debug 'UI' "cli_ask_yesno: User picked NO"
return 1
fi
}
@@ -576,6 +641,43 @@ _cli_follow_progress ()
title=$1
logfile=$2
echo "Title: $1"
- tail -f $2
- #TODO: don't block anymore when it's done
+ [ -n "$3" ] && tail -f $2 --pid=$3
+ [ -z "$3" ] && tail -f $2
+}
+
+set_keymap ()
+{
+ KBDDIR="/usr/share/kbd"
+
+ KEYMAPS=
+ for i in $(find $KBDDIR/keymaps -name "*.gz" | sort); do
+ KEYMAPS="$KEYMAPS ${i##$KBDDIR/keymaps/} -"
+ done
+ ask_option "${var_KEYMAP:-no}" "Select A Keymap" '' optional $KEYMAPS
+ if [ -n "$ANSWER_OPTION" ]
+ then
+ loadkeys -q $KBDDIR/keymaps/$ANSWER_OPTION
+ var_KEYMAP=$ANSWER_OPTION
+ echo "$var_KEYMAP" > $RUNTIME_DIR/aif-keymap
+ fi
+
+ FONTS=
+ # skip .cp.gz and partialfonts files for now see bug #6112, #6111
+ for i in $(find $KBDDIR/consolefonts -maxdepth 1 ! -name '*.cp.gz' -name "*.gz" | sed 's|^.*/||g' | sort); do
+ FONTS="$FONTS $i -"
+ done
+ ask_option "${var_CONSOLEFONT:-no}" "Select A Console Font" '' optional $FONTS
+ if [ -n "$ANSWER_OPTION" ]
+ then
+ var_CONSOLEFONT=$ANSWER_OPTION
+ for i in 1 2 3 4
+ do
+ if [ -d /dev/vc ]; then
+ setfont $KBDDIR/consolefonts/$var_CONSOLEFONT -C /dev/vc/$i
+ else
+ setfont $KBDDIR/consolefonts/$var_CONSOLEFONT -C /dev/tty$i
+ fi
+ done
+ echo "$var_CONSOLEFONT" > $RUNTIME_DIR/aif-consolefont
+ fi
}
diff --git a/src/core/procedures/automatic b/src/core/procedures/automatic
index 3c93167..b0e327a 100644
--- a/src/core/procedures/automatic
+++ b/src/core/procedures/automatic
@@ -1,24 +1,32 @@
#!/bin/bash
-# This procedure is EARLY in development!!
# This is a procedure for automatic deployment/installation/configuration of systems. # TODO: document! (readme, notes about deployment profiles, examples, ...)
+# check /usr/share/aif/examples for some example config files.
+# This procedure can easily replace the old quickinst script if you look at the "generic install" config file
+# Look at the base procedure to see the phases and which workers they'll execute.
+# It should be:
+# phase_preparation=(configure intro sysprep select_source runtime_network runtime_repositories runtime_packages)
+# phase_basics=(set_clock prepare_disks)
+# phase_system=(package_list install_packages auto_fstab auto_networkTODO auto_locale auto_keymap_font configure_system mkinitcpio locales install_bootloader)
+# phase_finish=(msg_report)
# In theory, the only manual thing should maybe be configuring the runtime network and putting the configfile in place
# TODO: I don't know if you can do non-interactive dm_crypt stuff.. maybe by pulling luks keyfiles from svn/git/..?
+# TODO: for worker_configure_system, we probably want the user to specify hostname, root pass etc.
+# TODO: implement setting hostname, keymap, consolefont, network settings
+# for a list of recognized variables, see examples/generic-install-on-sda
depend_procedure core base
var_OPTS_STRING="c:"
-var_ARGS_USAGE="-c <config>: Specify a configfile (profile) to be used (optional)" #if we need some settings that we're missing, we'll ask for them
-
-phase_preparation+=(runtime_settings)
-phase_preparation+=(msg_automatic) # this can happen probably a bit earlier..
-phase_preparation+=(fetch_configs)
+var_ARGS_USAGE="-c <config>: Specify a configfile (profile) to be used"
+var_AUTOMATIC_PROFILE=""
+# TODO: if the user does aif -p automatic -c, then $1 is ":-" ??? if you do -c <something> then it's ok.
process_args ()
{
if [ "$1" = '-c' ]
then
[ -z "$2" ] && die_error "You must specify a config"
- source $2 || die_error "Could not source config $2"
+ var_AUTOMATIC_PROFILE=$2
else
usage
exit 5
@@ -28,69 +36,51 @@ process_args ()
worker_intro ()
{
- notify "Automatic procedure running..."
+ notify "Automatic procedure running profile $var_AUTOMATIC_PROFILE ..."
}
worker_configure ()
{
var_UI_TYPE=${arg_ui_type:-cli}
+ [ -z "$var_AUTOMATIC_PROFILE" ] && die_error "You must specify a config file to use this procedure"
+ source $var_AUTOMATIC_PROFILE || die_error "Could not source config $var_AUTOMATIC_PROFILE"
+ # Check mandatory options
+ [ -z "$PARTITIONS" ] && die_error "You did not specify a partition scheme"
+ [ -z "$BLOCKDATA" ] && die_error "You did not specify a partition scheme"
+ [ -z "$GRUB_DEVICE" ] && die_error "You did not specify a grub device"
+ # initialize internal variables based on variables set by the user (some of the vars are handled in other workers):
+ var_RUNTIME_REPOSITORIES=$RUNTIME_REPOSITORIES
+ var_RUNTIME_PACKAGES=$RUNTIME_PACKAGES
+ var_GRUB_DEVICE=$GRUB_DEVICE
+ var_PARTITIONS=$PARTITIONS
+ var_BLOCKDATA=$BLOCKDATA
}
-
-# not used
-worker_msg_manual ()
-{
- notify "A few manual things need to happen first..."
-}
-
-
-worker_msg_automatic ()
-{
- notify "**** From now on. everything will be automatic. Enjoy the show!" # not true: you need pass for dm_crypt
-}
-
-
-worker_fetch_configs ()
+worker_select_source ()
{
- true
+ var_PKG_SOURCE_TYPE=${SOURCE:-cd}
+ var_FILE_URL=${FILE_URL:-file:///src/core/pkg}
+ var_SYNC_URL=${SYNC_URL:-}
}
-
worker_runtime_network ()
{
- if ask_yesno "Do you want to (re)-configure your networking?"
- then
- interactive_runtime_network
- else
- infofy "Ok. skipping network config"
- fi
-}
-
-
-# Check if we have all needed settings loaded from the profile
-worker_runtime_settings ()
-{
- if check_is_in $var_RUNTIME_PACKAGES svn
- then
- [ -z "$SVN_USERNAME" ] && ask_string "Please enter your svn username" && SVN_USERNAME=$ANSWER_STRING
- [ -z "$SVN_PASSWORD" ] && ask_password svn #TODO: if user entered incorrect password, the install process will just fail..
- [ -z "$SVN_BASE" ] && ask_string "What's the base path of your svn repo? (no ending /) " && SVN_BASE=$ANSWER_STRING
- [ -z "$DEPLOY_CLASS" ] && ask_string "Which hostclass are you installing? (optional)" '' 0 && DEPLOY_CLASS=$ANSWER_STRING
- SVN="svn --username $SVN_USERNAME --password $SVN_PASSWORD"
- elif check_is_in $var_RUNTIME_PACKAGES moo
- then
- # Maybe more stuff later
- true
- fi
- [ -z "$HOSTNAME" ] && ask_string "Hostname of target system?" && HOSTNAME=$ANSWER_STRING
-
- return 0
+ true # for now. we assume the user has taken care of this himself already. doing this interactively wouldn't be a good default anyway.
+ # maybe check if network works, if not, try dhcp. let user override by using a static config in his config file
+ #if ask_yesno "Do you want to (re)-configure your networking?"
+ #then
+ # interactive_runtime_network
+ #else
+ # infofy "Ok. skipping network config"
+ #fi
}
worker_prepare_disks ()
{
+ echo "$var_PARTITIONS" > $TMP_PARTITIONS
+ echo "$var_BLOCKDATA" > $TMP_BLOCKDEVICES
process_disks || die_error "Could not process_disks"
if ! process_filesystems
then
@@ -105,31 +95,35 @@ worker_prepare_disks ()
true
}
+worker_package_list ()
+{
+ var_TARGET_PACKAGES=$TARGET_PACKAGES
+ var_TARGET_GROUPS=$TARGET_GROUPS
+ [ -z "$var_TARGET_PACKAGES" -a -z "$var_TARGET_GROUPS" ] && var_TARGET_GROUPS=base
+}
+
worker_install_packages ()
{
target_prepare_pacman core extra community #TODO: it would be better if this was a separate worker, i think
- [ -z "$TARGET_PACKAGES" ] && die_error "No packages listed to be installed!"
installpkg
}
worker_set_clock ()
{
- #timezone="Europe/Brussels"
- #Not doing anything. hwclock is set already and configs are coming from svn anyway..
+ #TODO implement this
true
}
-worker_install_bootloader ()
-{
- install-grub /dev/sda
+worker_auto_network () {
+ # temporary override because i need to implement this
+ true
}
-worker_runtime_yaourt ()
+worker_install_bootloader ()
{
- _yaourt_replace_pacman
+ grub-install $var_GRUB_DEVICE --root-directory=/mnt
}
-
diff --git a/src/core/procedures/base b/src/core/procedures/base
index c22a01c..6d99421 100644
--- a/src/core/procedures/base
+++ b/src/core/procedures/base
@@ -5,7 +5,7 @@ var_DEFAULTFS="/boot:32:ext2:+ swap:256:swap /:7500:ext3 /home:*:ext3"
var_TARGET_DIR="/mnt" # When overriding this, do _not_ add a trailing /. It's not needed and maybe you could even break something
var_RUNTIME_REPOSITORIES= # array like this ('name1' 'location of repo 1' ['name2' 'location of repo2',..])
var_RUNTIME_PACKAGES=
-var_PKG_FILE=$RUNTIME_DIR/package-list # not used by default in base/interactive. can be used by custom procedures or profiles for the automatic procedure
+var_PKG_FILE=$RUNTIME_DIR/aif-package-list # not used by default in base/interactive. can be used by custom procedures or profiles for the automatic procedure
var_MIRRORLIST="/etc/pacman.d/mirrorlist"
var_UI_TYPE="cli" # set to cli or dia for dialog
var_ARCH=`uname -m` #i686 or x86_64. NOTE: this assumes you want to install the same arch as the installation environment you're using. maybe we could decouple those someday..
@@ -31,6 +31,7 @@ phase_system=(\
auto_fstab \
auto_network \
auto_locale \
+ auto_keymap_font \
configure_system \
mkinitcpio \
locales \
@@ -101,7 +102,29 @@ worker_runtime_packages ()
worker_set_clock ()
{
- interactive_set_clock
+ while true; do
+ default=no
+ [ -n "$NEXTITEM" ] && default="$NEXTITEM"
+ ask_option $default "Date/time configuration" '' required \
+ "1" "Select region and timezone" \
+ "2" "Set time and date" \
+ "3" "Return to Main Menu"
+ [ "$ANSWER_OPTION" = 1 ] && execute worker interactive_timezone && NEXTITEM=2
+ [ "$ANSWER_OPTION" = 2 ] && check_depend worker interactive_timezone && execute worker interactive_time && NEXTITEM=3
+ [ "$ANSWER_OPTION" = 3 ] && break
+ done
+}
+
+
+worker_interactive_timezone ()
+{
+ interactive_timezone
+}
+
+
+worker_interactive_time ()
+{
+ interactive_time
}
@@ -112,18 +135,16 @@ worker_prepare_disks ()
}
-# Put the list of packages to be installed in $TARGET_PACKAGES
+# Put the list of packages to be installed in $var_TARGET_PACKAGES and $var_TARGET_GROUPS
worker_package_list ()
{
- #TODO: sensible list of packages. maybe just 'base'
- true
+ var_TARGET_GROUPS=base
}
worker_install_packages ()
{
target_prepare_pacman core #TODO: it would be better if this was a separate worker, i think
- [ -z "$TARGET_PACKAGES" ] && die_error "No packages listed to be installed!"
installpkg
}
@@ -143,10 +164,15 @@ worker_auto_network ()
worker_auto_locale ()
{
- target_configure_inital_locale
+ target_configure_initial_locale
}
+worker_auto_keymap_font ()
+{
+ target_configure_initial_keymap_font
+}
+
worker_configure_system ()
{
#TODO: what to do here?
diff --git a/src/core/procedures/interactive b/src/core/procedures/interactive
index 051d187..86e3d63 100644
--- a/src/core/procedures/interactive
+++ b/src/core/procedures/interactive
@@ -53,7 +53,7 @@ mainmenu()
[ -n "$NEXTITEM" ] && default="$NEXTITEM"
#TODO: why does a '2' appear instead of '' ??
- ask_option $default "MAIN MENU" '' \
+ ask_option $default "MAIN MENU" '' required \
"1" "$worker_select_source_title" \
"2" "$worker_set_clock_title" \
"3" "$worker_prepare_disks_title" \
@@ -78,7 +78,8 @@ mainmenu()
check_depend worker package_list && \
check_depend worker select_source && execute worker install_packages && { execute worker auto_fstab ; \
ended_ok worker runtime_network && execute worker auto_network ; \
- execute worker auto_locale ; } && NEXTITEM=6 ;;
+ execute worker auto_locale ; \
+ execute worker auto_keymap_font; } && NEXTITEM=6 ;;
"6")
check_depend worker install_packages && execute worker configure_system && { execute worker mkinitcpio ; \
execute worker locales ;
@@ -96,7 +97,7 @@ mainmenu()
select_source_extras_menu ()
{
while true; do
- ask_option no "FTP Installation" 'Make sure the network is ok before continuing the installer' \
+ ask_option no "FTP Installation" 'Make sure the network is ok before continuing the installer' required \ #TODO: display the "make sure network is okay" in a better way
"1" "$worker_runtime_network_title" \
"2" "$worker_select_mirror_title" \
"3" "Return to Main Menu"
@@ -114,7 +115,7 @@ worker_configure_system()
# /etc/pacman.d/mirrorlist
# add installer-selected mirror to the top of the mirrorlist
if [ "$var_PKG_SOURCE_TYPE" = "ftp" -a "${var_SYNC_URL}" != "" ]; then
- debug "Adding choosen mirror (${var_SYNC_URL}) to ${var_TARGET_DIR}/$var_MIRRORLIST"
+ debug 'PROCEDURE' "Adding choosen mirror (${var_SYNC_URL}) to ${var_TARGET_DIR}/$var_MIRRORLIST"
mirrorlist=`awk "BEGIN { printf(\"# Mirror used during installation\nServer = "${var_SYNC_URL}"\n\n\") } 1 " "${var_TARGET_DIR}/$var_MIRRORLIST"`
echo "$mirrorlist" > "${var_TARGET_DIR}/$var_MIRRORLIST" #TODO: test this, this may not work
fi
@@ -147,7 +148,8 @@ worker_prepare_disks()
default=no
[ -n "$NEXTITEM" ] && default="$NEXTITEM"
- ask_option $default "Prepare Hard Drive" '' \
+ #TODO: inform user (using dialog's --item-help or so) that autoprepare uses 1 disk and uses it in a "fairly regular" (though somewhat customizable) manner.
+ ask_option $default "Prepare Hard Drive" '' required \
"1" "Auto-Prepare (erases the ENTIRE hard drive and sets up partitions and filesystems)" \
"2" "Partition Hard Drives" \
"3" "Configure block devices, filesystems and mountpoints" \
@@ -246,7 +248,7 @@ worker_select_mirror ()
worker_install_bootloader ()
{
- ask_option Grub "Choose bootloader" "Which bootloader would you like to use? Grub is the Arch default." \
+ ask_option Grub "Choose bootloader" "Which bootloader would you like to use? Grub is the Arch default." required \
"Grub" "Use the GRUB bootloader (default)" \
"None" "\Zb\Z1Warning\Z0\ZB: you must install your own bootloader!"
diff --git a/src/core/procedures/partial-keymap b/src/core/procedures/partial-keymap
new file mode 100644
index 0000000..ad81727
--- /dev/null
+++ b/src/core/procedures/partial-keymap
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+start_process ()
+{
+ var_UI_TYPE=dia
+ set_keymap
+}
diff --git a/src/core/procedures/quickinst b/src/core/procedures/quickinst
deleted file mode 100644
index b95bfa4..0000000
--- a/src/core/procedures/quickinst
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/bin/bash
-depend_procedure core base
-
-# This is a port of the original /arch/quickinst script.
-
-# TODO: nowhere rely on /tmp
-
-
-# TODO: find a way to make profilespecific arguments and usage function work (see src/aif.sh)
-usage() {
- echo "quickinst <install_mode> <destdir> <package_directory|server_url>"
- echo
- echo "This script is for users who would rather partition/mkfs/mount their target"
- echo "media manually than go through the routines in the setup script."
- echo
- echo "First make sure you have all your filesystems mounted under <destdir>."
- echo "e.g. mount -t iso9660 /dev/sdc or /dev/sr0 (for new naming sheme) /src "
- echo "Then run this script to install all base packages to <destdir>."
- echo
- if [ -e /usr/bin/wget ]; then
- echo "<install_mode> must be either 'ftp' or 'cd'"
- else
- echo "<install_mode> must be 'cd'"
- fi
- echo
- echo "Examples:"
- if [ -e /usr/bin/wget ]; then
- echo " quickinst ftp /mnt ftp://ftp.archlinux.org/core/os/$var_ARCH"
- fi
-
- echo " quickinst cd /mnt /src/core/pkg"
- echo ""
- exit 0
-}
-
-
-# TODO: implement correctly
-worker_configure ()
-{
-# var_PKG_SOURCE_TYPE
-# var_TARGET_DIR
-# var_FILE_URL or var_SYNC_URL
-}
-
-# TODO: clean up everything below this
-
-PACMAN=
-[ -f /tmp/usr/bin/pacman.static ] && PACMAN=/tmp/usr/bin/pacman.static
-[ -f /usr/bin/pacman.static ] && PACMAN=/usr/bin/pacman.static
-if [ "$PACMAN" = "" ]; then
- cd /tmp
- if [ "$INSTMODE" = "ftp" ]; then
- echo "Downloading pacman..."
- wget $PKGARG/pacman*.pkg.tar.gz
- if [ $? -gt 0 ]; then
- echo "error: Download failed"
- exit 1
- fi
- tar -xzf pacman*.pkg.tar.gz
- elif [ "$INSTMODE" = "cd" ]; then
- echo "Unpacking pacman..."
- tar -xzf $PKGARG/pacman*.pkg.tar.gz
- fi
-fi
-[ -f /tmp/usr/bin/pacman.static ] && PACMAN=/tmp/usr/bin/pacman.static
-if [ "$PACMAN" = "" ]; then
- echo "error: Cannot find the pacman.static binary!"
- exit 1
-fi
-
-if [ "$INSTMODE" = "ftp" ]; then
- echo "[core]" >/tmp/pacman.conf
- echo "Server = $PKGARG" >>/tmp/pacman.conf
- mkdir -p $DESTDIR/var/cache/pacman/pkg /var/cache/pacman >/dev/null 2>&1
- rm -f /var/cache/pacman/pkg >/dev/null 2>&1
- ln -sf $DESTDIR/var/cache/pacman/pkg /var/cache/pacman/pkg >/dev/null 2>&1
-fi
-
-if [ "$INSTMODE" = "cd" ]; then
- echo "[core]" >/tmp/pacman.conf
- echo "Server = file://$PKGARG" >>/tmp/pacman.conf
- mkdir -p $DESTDIR/var/cache/pacman/pkg /var/cache/pacman >/dev/null 2>&1
- rm -f /var/cache/pacman/pkg >/dev/null 2>&1
- ln -sf $PKGARG /var/cache/pacman/pkg >/dev/null 2>&1
-fi
-
-! [ -d $DESTDIR/var/lib/pacman ] && mkdir -p $DESTDIR/var/lib/pacman
-! [ -d /var/lib/pacman ] && mkdir -p /var/lib/pacman
-# mount proc/sysfs first, so mkinitrd can use auto-detection if it wants
-! [ -d $DESTDIR/proc ] && mkdir $DESTDIR/proc
-! [ -d $DESTDIR/sys ] && mkdir $DESTDIR/sys
-! [ -d $DESTDIR/dev ] && mkdir $DESTDIR/dev
-mount -t proc none $DESTDIR/proc
-mount -t sysfs none $DESTDIR/sys
-mount -o bind /dev $DESTDIR/dev
-$PACMAN -r $DESTDIR --config /tmp/pacman.conf -Sy base
-umount $DESTDIR/proc $DESTDIR/sys $DESTDIR/dev
-if [ $? -gt 0 ]; then
- echo
- echo "Package installation FAILED."
- echo
- exit 1
-fi
-
-echo
-echo "Package installation complete."
-echo
-echo "Please install a bootloader. Edit the appropriate config file for"
-echo "your loader, and chroot into your system to install it into the"
-echo "boot sector:"
-echo " # mount -o bind /dev $DESTDIR/dev"
-echo " # mount -t proc none $DESTDIR/proc"
-echo " # mount -t sysfs none $DESTDIR/sys"
-echo " # chroot $DESTDIR /bin/bash"
-echo
-echo "For GRUB:"
-echo " # install-grub /dev/sda /dev/sdaX (replace with your boot partition)"
-echo " (or install manually by invoking the GRUB shell)"
-echo "HINT XFS FILESYSTEM:"
-echo "If you have created xfs filesystems, freeze them before and unfreeze them after"
-echo "installing grub (outside the chroot):"
-echo "- freeze:"
-echo " # xfs_freeze -f $DESTDIR/boot"
-echo " # xfs_freeze -f $DESTDIR/"
-echo "- unfreeze:"
-echo " # xfs_freeze -u $DESTDIR/boot"
-echo " # xfs_freeze -u $DESTDIR/"
-echo
-echo "For LILO:"
-echo " # lilo"
-echo
-echo "Next step, initramfs setup:"
-echo "Edit your /etc/mkinitcpio.conf and /etc/mkinitcpio.d/kernel26-fallback.conf"
-echo "to fit your needs. After that run:"
-echo "# mkinitcpio -p kernel26"
-echo
-echo "Then exit your chroot shell, edit $DESTDIR/etc/fstab and"
-echo "$DESTDIR/etc/rc.conf, and reboot!"
-echo
-exit 0
diff --git a/tests/test-check_is_in.sh b/tests/test-check_is_in.sh
new file mode 100755
index 0000000..0d97361
--- /dev/null
+++ b/tests/test-check_is_in.sh
@@ -0,0 +1,7 @@
+basedir=$(dirname "`dirname $0`")
+source $basedir/src/core/libs/lib-ui.sh #dependency needed
+source $basedir/src/core/libs/lib-misc.sh
+
+vars=(A B C D E F)
+check_is_in C "${vars[@]}" && echo 'ok C was in there' || echo 'wtf'
+check_is_in AOEUAU "${vars[@]}" && echo wtf || echo 'ok it was not in there'
diff --git a/tests/test-menus.sh b/tests/test-menus.sh
index 9288ff6..b8dd99c 100644..100755
--- a/tests/test-menus.sh
+++ b/tests/test-menus.sh
@@ -1,12 +1,15 @@
basedir=$(dirname "`dirname $0`")
source $basedir/src/core/libs/lib-ui.sh
-ANSWER="/tmp/.dialog-answer"
-
-
-var_UI_TYPE=dia
-ask_option no 'menu title is this yes yes' 'extra explanation is here mkay' tagA itemA "tag B" 'item B' tag-c item\ C
-echo "return code was $?"
-
-var_UI_TYPE=cli
-ask_option tag-c 'menu title is this yes yes' 'extra explanation is here mkay' tagA itemA "tag B" 'item B' tag-c item\ C
-echo "return code was $?" \ No newline at end of file
+ANSWER="/tmp/aif-test-dialog-answer"
+for ui in dia cli
+do
+ for type in required optional
+ do
+ for default in no tag-c
+ do
+ var_UI_TYPE=$ui
+ ask_option $default 'menu title ($2)' 'extra explanation ($3)'" settings: type: $type, default:$default" $type tagA itemA "tag B" 'item B' tag-c item\ C
+ notify "RETURN CODE: $?\nANSWER: $ANSWER_OPTION"
+ done
+ done
+done
diff --git a/examples/deployconfig-dieter b/unofficial/dieter-desktop-a7n8x.automaticprofile
index 396de45..2e63a78 100644
--- a/examples/deployconfig-dieter
+++ b/unofficial/dieter-desktop-a7n8x.automaticprofile
@@ -1,6 +1,9 @@
#!/bin/bash
# An example config for the deployment procedure
+# Use var_* for "standard" variables recognized by the automatic procedure. these should work for everyone.
+# use all other variable names for your own stuff. (eg i use them to define some things needed to pull my stuff from svn.)
+
# TODO: install ruby-gems too
# TODO * dieter/automatic: wait for yaourt --config fix ( http://forums.archlinux.fr/post23171.html#23171 )
# TODO:* dieter/automatic: put config files from svn in place first, so that if a package has an update, it can do it's thing.
@@ -15,16 +18,29 @@ SVN_USERNAME=dieter
SVN_PASSWORD=
SVN_BASE=https://192.168.1.2/svn/repos
+var_PARTITIONS='/dev/sda 100:ext2:+ 2048:swap *:xfs'
+var_BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
+/dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
+/dev/sda3 raw no_label dm_crypt;yes;no_mountpoint;target;no_opts;sda3crypt;-c_aes-xts-plain_-y_-s_512
+/dev/mapper/sda3crypt dm_crypt no_label lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
+/dev/mapper/sda3crypt+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;cryptpool;/dev/mapper/sda3crypt
+/dev/mapper/cryptpool lvm-vg cryptpool lvm-lv;yes;no_mountpoint;target;no_opts;cryptroot;5G|lvm-lv;yes;no_mountpoint;target;no_opts;crypthome;5G
+/dev/mapper/cryptpool-cryptroot lvm-lv no_label xfs;yes;/;target;no_opts;no_label;no_params
+/dev/mapper/cryptpool-crypthome lvm-lv no_label xfs;yes;/home;target;no_opts;no_label;no_params'
+
+
+
phase_preparation=(accept_ssl_cert "${phase_preparation[@]}") # make accept_ssl_cert the very first thing. it needs to go before fetch_configs and it's not easy to put it somewhere in the middle, so...
phase_system+=(configure_home)
+# Deprecated. I try to keep everything in 1 config file now. that's cooler.
+#worker_fetch_configs ()
+#{
+# $SVN export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.blockdata $RUNTIME_DIR/aif-blockdata || die_error "Could not svn export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.blockdata to $RUNTIME_DIR/aif-blockdata"
+# $SVN export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.partitions $RUNTIME_DIR/aif-partitions || die_error "Could not svn export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.partitions to $RUNTIME_DIR/aif-partitions"
+#}
-worker_fetch_configs ()
-{
- $SVN export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.blockdata $RUNTIME_DIR/.blockdata || die_error "Could not svn export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.blockdata to $RUNTIME_DIR/.blockdata"
- $SVN export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.partitions $RUNTIME_DIR/.partitions || die_error "Could not svn export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/disks/.partitions to $RUNTIME_DIR/.partitions"
-}
worker_package_list ()
@@ -85,3 +101,15 @@ worker_configure_home ()
# PACMAN=$PACMAN_BACKUP
# PACMAN_TARGET=$PACMAN_TARGET_BACKUP
#}
+
+
+worker_set_clock ()
+{
+ #Not doing anything. hwclock is set already, configs are coming from svn anyway and we'll use ntp.
+ true
+}
+
+worker_runtime_yaourt ()
+{
+ _yaourt_replace_pacman
+}
diff --git a/unofficial/modules/dieter/procedures/dieter-automatic b/unofficial/modules/dieter/procedures/dieter-automatic
new file mode 100644
index 0000000..09e8972
--- /dev/null
+++ b/unofficial/modules/dieter/procedures/dieter-automatic
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Dieters personal procedure, adds a bit on top of the official automatic procedure.
+# TODO: implement this.
+
+depend_procedure core automatic
+
+
+# Check if we have all needed settings loaded from the profile
+worker_runtime_settings () #TODO: add to a phase
+{
+ if check_is_in svn $var_RUNTIME_PACKAGES
+ then
+ [ -z "$SVN_USERNAME" ] && ask_string "Please enter your svn username" && SVN_USERNAME=$ANSWER_STRING
+ [ -z "$SVN_PASSWORD" ] && ask_password svn #TODO: if user entered incorrect password, the install process will just fail..
+ [ -z "$SVN_BASE" ] && ask_string "What's the base path of your svn repo? (no ending /) " && SVN_BASE=$ANSWER_STRING
+ [ -z "$DEPLOY_CLASS" ] && ask_string "Which hostclass are you installing? (optional)" '' 0 && DEPLOY_CLASS=$ANSWER_STRING
+ SVN="svn --username $SVN_USERNAME --password $SVN_PASSWORD"
+ elif check_is_in moo $var_RUNTIME_PACKAGES
+ then
+ # Maybe more stuff later
+ true
+ fi
+ [ -z "$HOSTNAME" ] && ask_string "Hostname of target system?" &&
+ HOSTNAME=$ANSWER_STRING
+
+ return 0
+}