782 |
783 |
784 | Search each package in the sync databases for names or descriptions that match
785 | regexp.
786 |
787 | * Display specific package info from the repository database
788 |
789 |
790 | # pacman --sync --info foo
791 |
792 | # pacman -Si foo
793 |
794 |
795 | Displays information from the repository database on package foo (size,
796 | build date, dependencies, conflicts, etc.)
797 |
798 | * Adding a package from the repositories
799 |
800 |
801 | # pacman --sync foo
802 |
803 | # pacman -S foo
804 |
805 |
806 | Retrieve and install package foo, complete with all dependencies it requires.
807 | Before using any sync option, make sure you refreshed the package list.
808 |
809 | * List installed packages
810 |
811 |
812 | # pacman --query
813 |
814 | # pacman -Q
815 |
816 |
817 | Displays a list of all installed packages in the system.
818 |
819 | * Check if a specific package is installed
820 |
821 |
822 | # pacman --query foo
823 |
824 | # pacman -Q foo
825 |
826 |
827 | This command will display the name and version of the foo package if it is
828 | installed, nothing otherwise.
829 |
830 | * Display specific package info
831 |
832 |
833 | # pacman --query --info foo
834 |
835 | # pacman -Qi foo
836 |
837 |
838 | Displays information on the installed package foo (size, install date, build
839 | date, dependencies, conflicts, etc.)
840 |
841 | * Display list of files contained in package
842 |
843 |
844 | # pacman --query --list foo
845 |
846 | # pacman -Ql foo
847 |
848 |
849 | Lists all files belonging to package foo.
850 |
851 | * Find out which package a specific file belongs to
852 |
853 |
854 | # pacman --query --owns /path/to/file
855 |
856 | # pacman -Qo /path/to/file
857 |
858 |
859 | This query displays the name and version of the package which contains the
860 | file referenced by its full path as a parameter.
861 |
862 | ## APPENDIX
863 |
864 | See [General Recommendations](https://wiki.archlinux.org/index.php/General_Recommendations)
865 | for some related unofficial documentation, new users may find useful.
866 |
--------------------------------------------------------------------------------
/examples/fancy-install-on-sda:
--------------------------------------------------------------------------------
1 | # this config is like generic-install-on-sda (check out that file first), but more fancy
2 |
3 | if [ -d /repo/core ]; then
4 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
5 | else
6 | MIRROR='ftp://mirrors.kernel.org/archlinux/$repo/os/$arch'
7 | TARGET_REPOSITORIES=(core $var_MIRRORLIST)
8 | fi
9 |
10 |
11 | RUNTIME_REPOSITORIES=
12 | RUNTIME_PACKAGES=
13 |
14 | # packages to install
15 | TARGET_GROUPS=base
16 | TARGET_PACKAGES_EXCLUDE='reiserfsprogs'
17 | TARGET_PACKAGES='openssh e2fsprogs cryptsetup lvm2 xfsprogs'
18 |
19 | # you can optionally also override some functions...
20 | worker_intro () {
21 | inform "Automatic procedure running the fancy-install-on-sda example config. this will install a system with lvm on top of dm_crypt. THIS WILL ERASE AND OVERWRITE YOUR /DEV/SDA. IF YOU DO NOT WANT THIS PRESS CTRL+C WITHIN 10 SECONDS"
22 | sleep 10
23 | }
24 |
25 | worker_configure_system () {
26 | preconfigure_target
27 | sed -i 's/^HOSTNAME="myhost"/HOSTNAME="arch-fancy-install"/' $var_TARGET_DIR/etc/rc.conf
28 | postconfigure_target
29 | }
30 |
31 | PART_ACCESS=
32 |
33 | # These variables are mandatory
34 |
35 | PARTITIONS='/dev/sda 100:ext2:+ *:ext4'
36 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
37 | /dev/sda2 raw no_label dm_crypt;yes;no_mountpoint;target;no_opts;sda2crypt;-c__aes-xts-plain__-y__-s__512
38 | /dev/mapper/sda2crypt dm_crypt no_label lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
39 | /dev/mapper/sda2crypt+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;cryptpool;/dev/mapper/sda2crypt
40 | /dev/mapper/cryptpool lvm-vg cryptpool lvm-lv;yes;no_mountpoint;target;no_opts;cryptswap;1G|lvm-lv;yes;no_mountpoint;target;no_opts;cryptroot;5G|lvm-lv;yes;no_mountpoint;target;no_opts;crypthome;5G
41 | /dev/mapper/cryptpool-cryptswap lvm-lv no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
42 | /dev/mapper/cryptpool-cryptroot lvm-lv no_label xfs;yes;/;target;no_opts;no_label;no_params
43 | /dev/mapper/cryptpool-crypthome lvm-lv no_label xfs;yes;/home;target;no_opts;no_label;no_params'
44 |
--------------------------------------------------------------------------------
/examples/generic-install-on-sda:
--------------------------------------------------------------------------------
1 | # this config explains the (all) available options.
2 | # the variables are optional and we define their defaults here (so you could omit the
3 | # definitions), unless otherwise specified.
4 |
5 | # Add all repositories you want to use here. Same style as for pacman.conf:
6 | # Local: file://...
7 | # Remote: something like ftp://ftp.belnet.be/mirror/archlinux.org/$repo/os/$arch
8 | # You should list both the name of the repo as well as the location, as separate
9 | # elements.
10 | # You can add multiple repositories and even mix remote and local ones.
11 | # The order they are in here, will be the order in pacman.conf
12 | # This is a mandatory variable, which should contain at least 1 core repository
13 | # This example will do the most sensible thing on both core and netinstall images:
14 | if [ -d /repo/core ]; then
15 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
16 | else
17 | MIRROR='ftp://mirrors.kernel.org/archlinux/$repo/os/$arch'
18 | TARGET_REPOSITORIES=(core $var_MIRRORLIST) # $var_MIRRORLIST is set by AIF
19 | fi
20 |
21 | HARDWARECLOCK=localtime # UTC is the better option, but some OS'es don't support it (i.e. Windows)
22 | TIMEZONE=Canada/Pacific
23 | # Do you want to have additional pacman repositories or packages available at runtime (during installation)?
24 | # RUNTIME_REPOSITORIES same format as TARGET_REPOSITORIES
25 | RUNTIME_REPOSITORIES=
26 | # space separated list
27 | RUNTIME_PACKAGES=
28 |
29 | # packages to install
30 | TARGET_GROUPS=base # all packages in this group will be installed (defaults to base if no group and no packages are specified)
31 | TARGET_PACKAGES_EXCLUDE= # Exclude these packages if they are member of one of the groups in TARGET_GROUPS. example: 'nano reiserfsprogs' (they are in base)
32 | TARGET_PACKAGES='openssh e2fsprogs' # you can also specify separate packages to install (this is empty by default)
33 |
34 | # you can optionally also override some functions...
35 | # This way you can change/extend/remove pretty much all functionality in AIF !
36 | worker_intro () {
37 | inform "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"
38 | sleep 10
39 | }
40 |
41 | worker_configure_system () {
42 | preconfigure_target
43 | sed -i 's/^HOSTNAME="myhost"/HOSTNAME="arch-generic-install"/' $var_TARGET_DIR/etc/rc.conf
44 | postconfigure_target
45 | }
46 |
47 | PART_ACCESS= # can be set to 'uuid', 'dev', 'label', or leave empty for 'dev'
48 |
49 | # These variables are mandatory
50 |
51 | # '*' means all the remaining space
52 | # '+' means the bootable flag
53 | PARTITIONS='/dev/sda 100:ext2:+ 512:swap *:ext4'
54 | # if you wanted everything other than swap and boot on an extended partition, you can do like this:
55 | # PARTITIONS='/dev/sda 100:ext2:+ 512:swap :extended *:ext4'
56 |
57 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
58 | /dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
59 | /dev/sda3 raw no_label ext4;yes;/;target;no_opts;no_label;no_params'
60 |
--------------------------------------------------------------------------------
/examples/simple-lvm-install-on-sda:
--------------------------------------------------------------------------------
1 | # this config is like generic-install-on-sda (check out that file first), but installs a very simple LVM setup
2 |
3 | if [ -d /repo/core ]; then
4 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
5 | else
6 | MIRROR='ftp://mirrors.kernel.org/archlinux/$repo/os/$arch'
7 | TARGET_REPOSITORIES=(core $var_MIRRORLIST)
8 | fi
9 |
10 |
11 | RUNTIME_REPOSITORIES=
12 | RUNTIME_PACKAGES=
13 |
14 | # packages to install
15 | TARGET_GROUPS=base
16 | TARGET_PACKAGES_EXCLUDE='reiserfsprogs'
17 | TARGET_PACKAGES='openssh e2fsprogs lvm2 xfsprogs'
18 |
19 | # you can optionally also override some functions...
20 | worker_intro () {
21 | inform "Automatic procedure running the simple-lvm-install-on-sda example config. this will install an LVM system. THIS WILL ERASE AND OVERWRITE YOUR /DEV/SDA. IF YOU DO NOT WANT THIS PRESS CTRL+C WITHIN 10 SECONDS"
22 | sleep 10
23 | }
24 |
25 | worker_configure_system () {
26 | preconfigure_target
27 | sed -i 's/^HOSTNAME="myhost"/HOSTNAME="arch-simple-lvm-install"/' $var_TARGET_DIR/etc/rc.conf
28 | postconfigure_target
29 | }
30 |
31 | PART_ACCESS=
32 |
33 |
34 | # very simple LVM setup:
35 | # sda1 gets an 100MB ext2 for /boot
36 | # sda2 becomes a PV, which hosts a VG named 'myvg', which hosts 1 5GB LV named myroot, which gets an ext4 mounted at /
37 | # These variables are mandatory
38 | GRUB_DEVICE=/dev/sda
39 | PARTITIONS='/dev/sda 100:ext2:+ *:ext4'
40 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
41 | /dev/sda2 raw no_label lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
42 | /dev/sda2+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;myvg;/dev/sda2
43 | /dev/mapper/myvg lvm-vg myvg lvm-lv;yes;no_mountpoint;target;no_opts;myroot;5G
44 | /dev/mapper/myvg-myroot lvm-lv no_label ext4;yes;/;target;no_opts;no_label;no_params'
45 |
--------------------------------------------------------------------------------
/make-doc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | which markdown &>/dev/null || echo "Need markdown utility!" >&2
3 |
4 | echo "generating html..."
5 | for i in doc/official_installation_guide_??
6 | do
7 | echo $i
8 | # convert markdown to html, convert html links to wiki ones.
9 | cat $i | markdown | sed 's|]*>\([^<]*\)|[\1 \2]|g' > $i.html
10 | # turn code markup into a syntax that mediawiki understands
11 | sed -i 's###g' $i.html
12 | sed -i 's#
##g' $i.html
13 |
14 | done
15 |
16 | echo "adding special wiki thingies..."
17 |
18 | i=doc/official_installation_guide_en
19 | echo $i
20 |
21 |
22 | summary_begin='Article summary<\/strong><\/p>'
23 | summary_end_plus_one='Related articles<\/strong><\/p>'
24 | related_begin='Related articles<\/strong><\/p>'
25 | related_end_plus_one='Introduction<\/h1>'
26 |
27 | summary=`sed -n "/$summary_begin/, /$summary_end_plus_one/p;" $i.html | sed "/$summary_begin/d; /$summary_end_plus_one/d"`
28 | related=`sed -n "/$related_begin/, /$related_end_plus_one/p;" $i.html | sed "/$related_begin/d; /$related_end_plus_one/d"`
29 |
30 | # prepare $related for wikiing.
31 | # note that like this we always keep the absulolute url's even if they are on the same subdomain eg: {{Article summary wiki|http://foo/bar bar}} (note).
32 | # wiki renders absolute url a bit uglier. always having absolute url's is not needed if the page can be looked up on the same wiki, but like this it was simplest to implement..
33 | related=`echo "$related"| sed -e 's#
\[\(.*\)\] \(.*\)<\/p>#{{Article summary wiki|\1}} \2#'`
34 |
35 | # preare $summary for wiiking: replace email address by nice mailto links
36 | summary=`echo "$summary" | sed 's/\([^"|, ]*@[-A-Za-z0-9_.]*\)/[mailto:\1 \1]/'`
37 |
38 |
39 | echo -e "[[Category:Getting and installing Arch (English)]]\n[[Category:HOWTOs (English)]]
40 | [[Category:Accessibility (English)]]
41 | [[Category:Website Resources]]
42 | {{Article summary start}}\n{{Article summary text| 1=$summary}}\n{{Article summary heading|Available Languages}}\n
43 | {{i18n_entry|English|Official Arch Linux Install Guide}}\n
44 | {{Article summary heading|Related articles}}
45 | $related
46 | {{Article summary end}}" | cat - $i.html > $i.html.tmp && mv $i.html.tmp $i.html
47 |
48 | # remove summary and related articles from actual content
49 | sed "/$summary_end_plus_one/p; /$summary_begin/, /$summary_end_plus_one/d" $i.html > $i.html.tmp && mv $i.html.tmp $i.html
50 | sed "/$related_end_plus_one/p; /$related_begin/, /$related_end_plus_one/d" $i.html > $i.html.tmp && mv $i.html.tmp $i.html
51 |
--------------------------------------------------------------------------------
/src/aif-report-issues.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | RUNTIME_DIR=/tmp/aif
3 | LOG_DIR=/var/log/aif
4 | source /usr/lib/libui.sh
5 | cat - </dev/null
13 | ls -lh $LOG_DIR/* 2>/dev/null
14 | if ! ping -c 1 sprunge.us >/dev/null
15 | then
16 | msg="Please setup your networking using one of
17 | * dhcpcd eth0 # or whatever your interface is
18 | * aif -p partial-configure-network
19 |
20 | If your networking works fine and you think sprunge.us is down, please upload the files to another pastebin"
21 | show_warning "Connection error" "Cannot ping sprunge.us (pastebin server). $msg"
22 | die_error "cannot reach pastebin"
23 | fi
24 | report="Uploaded data:"
25 | if ask_yesno "Send these files?"
26 | then
27 | shopt -s nullglob
28 | for i in $RUNTIME_DIR/* $LOG_DIR/*
29 | do
30 | bin=$(cat $i | curl -sF 'sprunge=<-' http://sprunge.us)
31 | bin=${bin/ /} # for some reason there is a space in the beginning
32 | report="$report\n$i $bin"
33 | done
34 | shopt -u nullglob
35 | fi
36 |
37 | echo "It can also be useful to upload a list of currently mounted filesystems:"
38 | df -hT
39 | if ask_yesno "Is this ok?"
40 | then
41 | bin=$(df -hT | curl -sF 'sprunge=<-' http://sprunge.us)
42 | bin=${bin/ /}
43 | report="$report\ndf -hT $bin"
44 | fi
45 | echo -e "$report"
46 | echo "For your convenience, I will paste the report online"
47 | echo "So you just need to give the following url:"
48 | echo -e "$report" | curl -sF 'sprunge=<-' http://sprunge.us
49 |
--------------------------------------------------------------------------------
/src/aif-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # make sure you install aif onto the target system so you can use its testing libraries
4 |
5 | echo "Aif-test: a 'unit-testing' tool for AIF"
6 | echo " for a list of available tests: ls -l /usr/share/aif/tests/runtime"
7 | [ "$1" != runtime ] && echo "\$1: type of test to execute (runtime. no support for buildtime yet)" >&2 && exit 1
8 | [ -z "$2" ] && echo "\$2: name of test to execute" >&2 && exit 1
9 |
10 | test_dir="/usr/share/aif/tests/$1/$2"
11 |
12 | [ ! -d "$test_dir" ] && echo "No such test found: $test_dir" >&2 && exit 2
13 |
14 | echo "Running test $test_dir. THIS WILL PROBABLY ERASE DATA ON ONE OR MORE OF YOUR HARD DISKS. TO ABORT PRESS CTRL-C WITHIN 10 SECONDS"
15 | sleep 10
16 |
17 | # this script should install the system
18 | $test_dir/install.sh || fail=1
19 |
20 | # this script does any additional things such as touching files that we should recognize later
21 | $test_dir/setup_test.sh || fail=1
22 |
23 | # this script will do the actual testing (network check, recognize filesystems and files, ..)
24 | cp $test_dir/perform_test.sh /mnt/etc/rc.d/perform_test || fail=1
25 |
26 | # make sure the test will run on the target system
27 | sed -i 's#^DAEMONS=(\(.*\))#DAEMONS=(\1 perform_test)#' /mnt/etc/rc.conf || fail=1
28 |
29 | # and that /etc/issue won't blank the screen
30 | sed -i 's/^H//' /mnt/etc/issue
31 |
32 | [ "$fail" == '1' ] && echo "Something failed. will not reboot" >&2 && exit 3
33 |
34 | reboot
35 |
--------------------------------------------------------------------------------
/src/aif.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | ###### Set some default variables ######
5 | TITLE="Arch Linux Installation Framework"
6 | LOG="/dev/tty7"
7 | LIB_CORE=/usr/lib/aif/core
8 | LIB_USER=/usr/lib/aif/user
9 | RUNTIME_DIR=/tmp/aif
10 | LOG_DIR=/var/log/aif
11 | LOGFILE=$LOG_DIR/aif.log
12 | DISCLAIMER="Note that despite our careful coding and proper testing there may still be bugs in this software.\n
13 | When you are doing this installation on a system where some data must be preserved, we suggest you make a backup first"
14 | export LC_COLLATE=C # for consistent sorting behavior
15 | shopt -s extglob # used in find_usable_blockdevices() and useful in general. (shopt statement cannot be put inside function)
16 |
17 | ###### Early bootstrap ######
18 |
19 | # load the lib-ui, it is one we need everywhere so we must load it early.
20 | source $LIB_CORE/libs/lib-ui.sh || { echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-ui.sh" >&2 ; exit 2; }
21 | ui_init
22 | # load the lib-flowcontrol. we also need some of it's functions early (like usage()).
23 | source $LIB_CORE/libs/lib-flowcontrol.sh || { echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-flowcontrol.sh" >&2 ; exit 2; }
24 | # lib-misc. we need it early, at least for check_is_in whis is used by the debug function.
25 | source $LIB_CORE/libs/lib-misc.sh || { echo "Something went wrong while sourcing library $LIB_CORE/libs/lib-misc.sh" >&2 ; exit 2; }
26 |
27 | # default function to process additional arguments. can be overridden by procedures.
28 | process_args ()
29 | {
30 | true
31 | }
32 |
33 |
34 |
35 |
36 | ###### perform actual logic ######
37 | echo "Welcome to $TITLE"
38 |
39 | [[ $EUID -ne 0 ]] && die_error "You must have root privileges to run AIF"
40 |
41 | mount -o remount,rw / &>/dev/null
42 | cleanup_runtime
43 | needed_pkgs_fs= # will hold extra needed packages for blockdevices/filesystems, populated when the Fs'es are created
44 |
45 | ### Set configuration values ###
46 | # note : you're free to use or ignore these in your procedure. probably you want to use these variables to override defaults in your configure worker
47 |
48 | #DEBUG: don't touch it. it can be set in the env
49 | arg_ui_type=
50 | LOG_TO_FILE=0
51 | module=
52 | procedure=
53 |
54 |
55 |
56 | # in that case -p needs to be the first option, but that's doable imho
57 | # an alternative would be to provide an argumentstring for the profile. eg aif -p profile -a "-a a -b b -c c"
58 |
59 | # you can override these variables in your procedures
60 | var_OPTS_STRING=""
61 | var_ARGS_USAGE=""
62 |
63 | # Processes args that were not already matched by the basic rules.
64 | process_args ()
65 | {
66 | # known options: we don't know any yet
67 | # return 0
68 |
69 | # if we are still here, we didn't return 0 for a known option. hence this is an unknown option
70 | usage
71 | exit 5
72 | }
73 |
74 |
75 | # Check if the first args are -p . If so, we can load the procedure, and hence $var_OPTS_STRING and process_args can be overridden
76 | if [ "$1" = '-p' ]
77 | then
78 | [ -z "$2" ] && usage && exit 1
79 | # note that we allow procedures like http://foo/bar. module -> http:, procedure -> http://foo/bar.
80 | if [[ $2 =~ ^http:// ]]
81 | then
82 | module=http
83 | procedure="$2"
84 | elif grep -q '\/' <<< "$2"
85 | then
86 | #user specified module/procedure
87 | module=`dirname "$2"`
88 | procedure=`basename "$2"`
89 | else
90 | module=core
91 | procedure="$2"
92 | fi
93 |
94 | shift 2
95 | fi
96 |
97 | # If no procedure given, bail out
98 | [ -z "$procedure" ] && usage && exit 5
99 |
100 | load_module core
101 | [ "$module" != core -a "$module" != http ] && load_module "$module"
102 | # this is a workaround for bash <4.2, where associative arrays are inherently local,
103 | # so we must source these variables in the main scope
104 | source $LIB_CORE/libs/lib-blockdevices-filesystems.sh
105 |
106 | load_procedure "$module" "$procedure"
107 |
108 | while getopts ":i:dlp:$var_OPTS_STRING" OPTION
109 | do
110 | case $OPTION in
111 | i)
112 | [ -z "$OPTARG" ] && usage && exit 1 #TODO: check if it's necessary to do this. the ':' in $var_OPTS_STRING might be enough
113 | [ "$OPTARG" != cli -a "$OPTARG" = !dia ] && die_error "-i must be dia or cli"
114 | arg_ui_type=$OPTARG
115 | ui_init
116 | ;;
117 | d)
118 | export DEBUG=1
119 | LOG_TO_FILE=1
120 | ;;
121 | l)
122 | LOG_TO_FILE=1
123 | ;;
124 | p)
125 | die_error "If you pass -p , it must be the FIRST option"
126 | ;;
127 | h)
128 | usage
129 | exit
130 | ;;
131 | ?)
132 | # If we hit something elso, call process_args
133 | process_args -$OPTION $OPTARG # you can override this function in your profile to parse additional arguments and/or override the behavior above
134 | ;;
135 | esac
136 |
137 | done
138 |
139 |
140 | # Set pacman vars. allow procedures to have set $var_TARGET_DIR (TODO: look up how delayed variable substitution works. then we can put this at the top again)
141 | # flags like --noconfirm should not be specified here. it's up to the procedure to decide the interactivity
142 | # NOTE: Pacman will run with currently active locale, if you want to parse output, you should prefix with LANG=C
143 | PACMAN=pacman
144 | PACMAN_TARGET="pacman --root $var_TARGET_DIR --config /tmp/pacman.conf"
145 |
146 | start_installer
147 |
148 | start_process
149 |
150 | stop_installer $?
151 |
--------------------------------------------------------------------------------
/src/core/libs/lib-blockdevices-filesystems.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # FORMAT DEFINITIONS:
4 |
5 | # -- formats used to interface with this library --
6 | # these files will persist during the entire aif session (and even after stopping aif)
7 | # so you can use them to retrieve data from them (or use functions in this library to do that for you)
8 | # $TMP_PARTITIONS
9 | # one line per partition, blockdevice + partioning string for sfdisk. See docs for function partition for more info.
10 | # $TMP_BLOCKDEVICES
11 | # one line per blockdevice, multiple fs'es in 1 'fs-string'
12 | # $TMP_BLOCKDEVICES entry.
13 | # type label/no_label /no_fs
14 | # FS-string:
15 | # type;recreate(yes/no);mountpoint;mount?(target,runtime,no);opts;label;params[|FS-string|...] where opts/params have _'s instead of whitespace if needed
16 | # NOTE: the 'mount?' for now just matters for the location (if 'target', the target path gets prepended and mounted in the runtime system)
17 | # NOTE: filesystems that span multiple underlying filesystems/devices (eg lvm VG) should specify those in params, separated by colons. \
18 | # the 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
19 | # no '+' characters allowed for devices in $fs_params (eg use the real names)
20 | # NOTE: if you want spaces in params or opts, you must "encode" them by replacing them with 2 underscores.
21 |
22 | # -- ADDITIONAL INTERNAL FORMATS --
23 | # $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)
24 | # uses spaces for separation (so you can easily do 'while.. read' loops. so fs_params and fs_opts are encoded here also
25 | # part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
26 |
27 |
28 |
29 | modprobe -q dm-crypt || show_warning modprobe 'Could not modprobe dm-crypt. no support for disk encryption'
30 | 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'
31 |
32 | TMP_DEV_MAP=$RUNTIME_DIR/aif-dev.map
33 | TMP_FSTAB=$RUNTIME_DIR/aif-fstab
34 | TMP_PARTITIONS=$RUNTIME_DIR/aif-partitions
35 | 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
36 | TMP_BLOCKDEVICES=$RUNTIME_DIR/aif-blockdata
37 |
38 | declare -A filesystem_programs=(["swap"]="mkswap" ["reiserfs"]="mkreiserfs" ["lvm-pv"]="pvcreate" ["lvm-vg"]="vgcreate" ["lvm-lv"]="lvcreate" ["dm_crypt"]="cryptsetup")
39 | for simple in ext2 ext3 ext4 nilfs2 xfs jfs vfat btrfs
40 | do
41 | filesystem_programs+=([$simple]=mkfs.$simple)
42 | done
43 |
44 | declare -A label_programs=(["swap"]="swaplabel" ["xfs"]="xfs_admin" ["jfs"]="jfs_tune" ["reiserfs"]="reiserfstune" ["nilfs2"]="nilfs-tune" ["vfat"]="dosfslabel")
45 | for ext in ext2 ext3 ext4
46 | do
47 | label_programs+=([$ext]=tune2fs)
48 | done
49 |
50 | # names for filesystems (which are shown to users in dialogs etc, don't use spaces!)
51 | declare -A filesystem_names=(["nilfs2"]="Nilfs2 (EXPERIMENTAL)" ["btrfs"]="Btrfs (EXPERIMENTAL)" ["vfat"]="vFat" ["dm_crypt"]="dm_crypt (LUKS)" ["lvm-pv"]="lvm Physical Volume" ["lvm-vg"]="lvm Volume Group" ["lvm-lv"]="lvm Logical Volume")
52 | for i in ext2 ext3 ext4 reiserfs xfs jfs swap
53 | do
54 | name=$(echo $i | capitalize)
55 | filesystem_names+=([$i]=$name)
56 | done
57 |
58 | # specify which filesystems can be stored on which blockdevices
59 | fs_on_raw=(swap ext2 ext3 ext4 reiserfs nilfs2 xfs jfs vfat dm_crypt lvm-pv btrfs)
60 | fs_on_lvm_lv=(swap ext2 ext3 ext4 reiserfs nilfs2 xfs jfs vfat dm_crypt btrfs)
61 | fs_on_dm_crypt=(swap ext2 ext3 ext4 reiserfs nilfs2 xfs jfs vfat lvm-pv btrfs)
62 | fs_on_lvm_pv=(lvm-vg)
63 | fs_on_lvm_vg=(lvm-lv)
64 |
65 | # the following is useful to do checks like check_is_in $fs_type ${fs_on[$part_type]} (or iterate it)
66 | # bash does not allow lists (array) in associative arrays, but this seems to work.
67 | # maybe it stores them as strings, which in this case is ok (no spaces in elements)
68 | declare -A fs_on
69 | fs_on[raw]=${fs_on_raw[@]}
70 | fs_on[lvm-lv]=${fs_on_lvm_lv[@]}
71 | fs_on[lvm-pv]=${fs_on_lvm_pv[@]}
72 | fs_on[lvm-vg]=${fs_on_lvm_vg[@]}
73 | fs_on[dm_crypt]=${fs_on_dm_crypt[@]}
74 |
75 | fs_mountable=(btrfs ext2 ext3 ext4 nilfs2 xfs jfs vfat reiserfs)
76 | fs_label_mandatory=('lvm-vg' 'lvm-lv' 'dm_crypt')
77 | fs_label_optional=('swap' 'ext2' 'ext3' 'ext4' 'reiserfs' 'nilfs2' 'xfs' 'jfs' 'vfat')
78 |
79 | # list needed packages per filesystem
80 | declare -A filesystem_pkg=(["lvm-pv"]="lvm2" ["xfs"]="xfsprogs" ["jfs"]="jfsutils" ["reiserfs"]="reiserfsprogs" ["nilfs2"]="nilfs-utils" ["vfat"]="dosfstools" ["dm_crypt"]="cryptsetup" ["btrfs"]=btrfs-progs-unstable)
81 | for i in ext2 ext3 ext4
82 | do
83 | filesystem_pkg+=([$i]=e2fsprogs)
84 | done
85 |
86 | # returns which filesystems you can create based on the locally available utilities
87 | get_possible_fs () {
88 | possible_fs=
89 | local fs
90 | for fs in "${!filesystem_programs[@]}"
91 | do
92 | which ${filesystem_programs[$fs]} &>/dev/null && possible_fs=("${possible_fs[@]}" $fs)
93 | done
94 | true
95 | }
96 |
97 | syslinux_supported_fs=('ext2' 'ext3' 'ext4' 'btrfs' 'vfat')
98 | supported_bootloaders=('syslinux')
99 |
100 | # procedural code from quickinst functionized and fixed.
101 | # there were functions like this in the setup script too, with some subtle differences. see below
102 | # NOTE: why were the functions in the setup called CHROOT_mount/umount? this is not chrooting ? ASKDEV
103 | target_special_fs ()
104 | {
105 | [ "$1" = on -o "$1" = off ] || die_error "special_fs needs on/off argument"
106 | if [ "$1" = on ]
107 | then
108 | # mount proc/sysfs first, so mkinitrd can use auto-detection if it wants
109 | ! [ -d $var_TARGET_DIR/proc ] && mkdir $var_TARGET_DIR/proc
110 | ! [ -d $var_TARGET_DIR/sys ] && mkdir $var_TARGET_DIR/sys
111 | ! [ -d $var_TARGET_DIR/dev ] && mkdir $var_TARGET_DIR/dev
112 | #mount, if not mounted yet
113 | mount | grep -q "$var_TARGET_DIR/proc" || mount -t proc proc $var_TARGET_DIR/proc || die_error "Could not mount $var_TARGET_DIR/proc"
114 | mount | grep -q "$var_TARGET_DIR/sys" || mount -t sysfs sysfs $var_TARGET_DIR/sys || die_error "Could not mount $var_TARGET_DIR/sys"
115 | mount | grep -q "$var_TARGET_DIR/dev" || mount -o bind /dev $var_TARGET_DIR/dev || die_error "Could not mount $var_TARGET_DIR/dev"
116 | elif [ "$1" = off ]
117 | then
118 | umount $var_TARGET_DIR/proc || die_error "Could not umount $var_TARGET_DIR/proc"
119 | umount $var_TARGET_DIR/sys || die_error "Could not umount $var_TARGET_DIR/sys"
120 | umount $var_TARGET_DIR/dev || die_error "Could not umount $var_TARGET_DIR/dev"
121 | fi
122 | }
123 |
124 |
125 | # taken from setup #TODO: we should be able to not need this function. although it may still be useful. but maybe we shouldn't tie it to $var_TARGET_DIR, and let the user specify the base point as $1
126 | # Disable swap and umount all mounted filesystems for the target system in the correct order. (eg first $var_TARGET_DIR/a/b/c, then $var_TARGET_DIR/a/b, then $var_TARGET_DIR/a until lastly $var_TARGET_DIR
127 | target_umountall()
128 | {
129 | inform "Disabling all swapspace..." disks
130 | swapoff -a >/dev/null 2>&1
131 | declare target=${var_TARGET_DIR//\//\\/} # escape all slashes otherwise awk complains
132 | for mountpoint in $(mount | awk "/\/$target/ {print \$3}" | sort | tac )
133 | do
134 | inform "Unmounting mountpoint $mountpoint" disks
135 | umount $mountpoint >/dev/null 2>$LOG
136 | done
137 | }
138 |
139 | # tells you which blockdevice is configured for the specific mountpoint
140 | # $1 mountpoint
141 | get_device_with_mount () {
142 | ANSWER_DEVICE=`grep ";$1;" $TMP_BLOCKDEVICES 2>/dev/null | cut -d ' ' -f1`
143 | [ -n "$ANSWER_DEVICE" ] # set correct exit code
144 | }
145 |
146 | # gives you a newline separated list of the blockdevice that hosts a certain filesystem, and below it, all underlying blockdevices supporting it, with also the blockdevice type.
147 | # example:
148 | # get_anchestors_mount ';/;' (suppose '/' is a filesystem on top of lvm on top of dm_crypt, you will get something like):
149 | # /dev/cryptpool/cryptroot lvm-lv
150 | # /dev/mapper/cryptpool lvm-vg
151 | # /dev/mapper/sda2crypt+ lvm-pv
152 | # /dev/mapper/sda2crypt dm_crypt
153 | # /dev/sda2 raw
154 | # $1 a "recognizer": a string that will match the filesystem section uniquely (using egrep), such as ';;' or other specific attributes of the hosted filesystem(s)
155 | get_anchestors_mount () {
156 | debug 'FS' "Finding anchestor for: $1"
157 | local buffer=
158 | read block type leftovers <<< `egrep "$1" $TMP_BLOCKDEVICES 2>/dev/null`
159 | [ -z "$type" ] && return 1
160 | buffer="$block $type"
161 | if [ $type != 'raw' ]
162 | then
163 | if [ $type == lvm-lv ]
164 | then
165 | lv=$(basename $block) # /dev/cryptpool/cryptroot -> cryptroot.
166 | recognizer="lvm-lv;(yes|no);no_mountpoint;[^;]{1,};[^;]{1,};$lv;[^;]{1,}"
167 | elif [ $type == lvm-vg ]
168 | then
169 | recognizer="lvm-vg;(yes|no);no_mountpoint;[^;]{1,};[^;]{1,};`basename $block`;[^;]{1,}"
170 | elif [ $type == lvm-pv ]
171 | then
172 | # here we cheat a bit: we cannot match the FS section because usually we don't give a PV recognizable attributes, but since we name a PV as blockdevice + '+' we can match the blockdevice
173 | recognizer="^${block/+/} .* lvm-pv;"
174 | elif [ $type == dm_crypt ]
175 | then
176 | recognizer="dm_crypt;(yes|no);no_mountpoint;[^;]{1,};[^;]{1,};`basename $block`;[^;]{1,}"
177 | fi
178 | get_anchestors_mount "$recognizer" && buffer="$buffer
179 | $ANSWER_DEVICES"
180 | fi
181 | ANSWER_DEVICES=$buffer
182 | debug 'FS' "Found anchestors: $ANSWER_DEVICES"
183 | [ -n "$ANSWER_DEVICES" ]
184 | }
185 |
186 |
187 | # parameters: device file
188 | # outputs: UUID on success
189 | # nothing on failure
190 | # returns: 0 if the attribute is found, 1 otherwise
191 | getuuid() {
192 | [ -n "$1" -a -b "$1" ] || die_error "getuuid needs a device file argument"
193 | uuid=$(blkid -s UUID -o value ${1})
194 | echo $uuid
195 | [ -n "$uuid" ]
196 | }
197 |
198 | # parameters: device file
199 | # outputs: LABEL on success
200 | # nothing on failure
201 | # returns: 0 if the attribute is found, 1 otherwise
202 | getlabel() {
203 | [ -n "$1" -a -b "$1" ] || die_error "getlabel needs a device file argument"
204 | label=$(blkid -s LABEL -o value ${1})
205 | echo "$label"
206 | [ -n "$label" ]
207 | }
208 |
209 | # find partitionable blockdevices
210 | # $1 extra things to echo for each device (optional) (backslash escapes will get interpreted)
211 | finddisks() {
212 | shopt -s nullglob
213 |
214 | # Block Devices
215 | for dev in /sys/block/*; do
216 | # devices without a size are no good
217 | [[ -e $dev/size ]] || continue
218 |
219 | # size <= 0 is stuff like empty card reader
220 | read -r size < "$dev/size"
221 | (( size )) || continue
222 |
223 | # type 5 is a CDROM
224 | if [[ -e $dev/device/type ]]; then
225 | read -r type < "$dev/device/type"
226 | (( type == 5 )) && continue
227 | fi
228 |
229 |
230 | unset DEVTYPE
231 | . "$dev/uevent"
232 | dev_used_by_environment /dev/$DEVNAME && continue
233 | [[ $DEVTYPE = disk || $DEVTYPE = vbd ]] && echo -ne "/dev/$DEVNAME $1"
234 | done
235 |
236 | # cciss controllers
237 | for dev in /dev/cciss/*; do
238 | if [[ $dev != *[[:digit:]]p[[:digit:]]* ]]; then
239 | dev_used_by_environment $dev && continue
240 | echo "$dev $1"
241 | fi
242 | done
243 |
244 | # Smart 2 Controller
245 | for dev in /dev/ida/*; do
246 | if [[ $dev != *[[:digit:]]p[[:digit:]]* ]]; then
247 | dev_used_by_environment $dev && continue
248 | echo "$dev $1"
249 | fi
250 | done
251 |
252 | shopt -u nullglob
253 | }
254 |
255 |
256 | # find usable blockdevices: RAID + LVM volumes, partitioned and unpartitioned devices
257 | # $1 extra things to echo for each device (optional) (backslash escapes will get interpreted)
258 | # $2,$3,$4 control whether the following should be included in output (in that order):
259 | # * devices/partitions that are part of a RAID or LVM volume
260 | # (although we strongly encourage users to setup LVM in AIF, we want to make
261 | # life a bit easier for those who have setup LVM/softraid before running AIF)
262 | # * root block devices (ex. sda) that are partitioned
263 | # * extended partitions
264 | # options: 1, 0 (default)
265 | find_usable_blockdevices() {
266 | shopt -s nullglob
267 | local include_dm=${2:-0}
268 | local include_root=${3:-0}
269 | local include_ext=${4:-0}
270 |
271 | local has_parts
272 |
273 | for devpath in $(finddisks); do
274 | has_parts=0
275 |
276 | # Deal with partitions first
277 | # Glob allows for following matches (not device itself):
278 | # /dev/sda -> /dev/sda1
279 | # /dev/cciss/c0d1 -> /dev/cciss/c0d1p1
280 | for dev in ${devpath}*[[:digit:]]*; do
281 | has_parts=1
282 | if ((include_ext)) || ! dev_is_extended_partition $dev; then
283 | dev_used_by_environment $dev && continue
284 | echo -ne "$dev $1"
285 | fi
286 |
287 | if ((include_dm)) || ! dev_is_in_softraid_or_lvmpv $dev; then
288 | dev_used_by_environment $dev && continue
289 | echo -ne "$dev $1"
290 | fi
291 | done
292 |
293 | # Then deal with the "parent" device
294 | if ((include_dm)) || ! dev_is_in_softraid_or_lvmpv $devpath; then
295 | if ((include_root)) || ((! has_parts)); then
296 | echo -ne "$devpath $1"
297 | fi
298 | fi
299 | done
300 |
301 | # mapped devices
302 | for devpath in /dev/mapper/*; do
303 | dev_used_by_environment $devpath && continue
304 | # Exclude /control directory and other non-block files (such as??)
305 | if [[ -b $devpath ]]; then
306 | echo -ne "$devpath $1"
307 | fi
308 | done
309 |
310 | # raid md devices
311 | for devpath in /dev/md[0-9]*; do
312 | dev_used_by_environment $devpath && continue
313 | if grep -qw "${devpath//\/dev\//}" /proc/mdstat; then
314 | echo -ne "$devpath $1"
315 | fi
316 | done
317 |
318 | shopt -u nullglob
319 | }
320 |
321 | # if the environment in which AIF runs consists of block devices which AIF has no business with,
322 | # they can be listed in /run/aif/ignore_block_devices (example: archiso does this)
323 | # most likely this is just some loop files, some /dev/mapper/arch_* files and maybe /dev/sr0
324 | # but in theory, could be anything
325 | dev_used_by_environment () {
326 | local dev=$1
327 | grep -q "^$dev$" /run/aif/ignore_block_devices 2>/dev/null
328 | }
329 |
330 | dev_is_extended_partition () {
331 | local dev=$1
332 | local disk="${dev%%[[:digit:]]*}"
333 | local partnum="${dev##*[[:alpha:]]}"
334 | [ "$(sfdisk -c "$disk" "$partnum" 2>/dev/null)" = 5 ]
335 | }
336 |
337 | dev_is_in_softraid_or_lvmpv () {
338 | local dev=$1
339 | grep -qsw "${dev##*/}" /proc/mdstat || { pvscan -s 2>/dev/null | grep -q "$dev"; }
340 | }
341 |
342 |
343 | # preprocess fstab file
344 | # comments out old fields and inserts new ones
345 | # according to $TMP_FSTAB, set through process_filesystem calls
346 | target_configure_fstab()
347 | {
348 | [ -f $TMP_FSTAB ] || return 0 # we can't do anything, but not really a failure
349 | sed -i 's!^\(/dev/\|LABEL=\|UUID=\)!#\1!' $var_TARGET_DIR/etc/fstab || return 1
350 | sort $TMP_FSTAB >> $var_TARGET_DIR/etc/fstab || return 1
351 | return 0
352 | }
353 |
354 |
355 | # partitions a disk. heavily altered
356 | # $1 device to partition
357 | # $2 a string of the form: :[:+] (the + is bootable flag)
358 | partition()
359 | {
360 | debug 'FS' "Partition called like: partition '$1' '$2'"
361 | [ -z "$1" ] && die_error "partition() requires a device file and a partition string"
362 | [ -z "$2" ] && die_error "partition() requires a partition string"
363 |
364 | DEVICE=$1
365 | STRING=$2
366 |
367 | # validate DEVICE
368 | if [ ! -b "$DEVICE" ]; then
369 | notify "Device '$DEVICE' is not valid"
370 | return 1
371 | fi
372 |
373 | target_umountall
374 |
375 | # setup input var for sfdisk
376 | # format: each line=1 part. [ ]
377 |
378 | read -r -a fsspecs <<< "$STRING" # split up like this otherwise '*' will be globbed. which usually means an entry containing * is lost
379 | sfdisk_input=
380 | for fsspec in "${fsspecs[@]}"; do
381 | fssize=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
382 | fssize_spec=",$fssize"
383 | [ "$fssize" = "*" ] && fssize_spec=';'
384 |
385 | fstype=$(echo $fsspec | tr -d ' ' | cut -f2 -d:)
386 | fstype_spec=","
387 | [ "$fstype" = "swap" ] && fstype_spec=",S"
388 | [ "$fstype" = "extended" ] && fstype_spec=",E"
389 |
390 | bootflag=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
391 | bootflag_spec=""
392 | [ "$bootflag" = "+" ] && bootflag_spec=",*"
393 |
394 | sfdisk_input="${sfdisk_input}${fssize_spec}${fstype_spec}${bootflag_spec}\n"
395 | done
396 |
397 | sfdisk_input=$(printf "$sfdisk_input") # convert \n to newlines
398 |
399 | # invoke sfdisk
400 | debug 'FS' "Partition calls: sfdisk $DEVICE -uM >$LOG 2>&1 <<< $sfdisk_input"
401 | printk off
402 | sfdisk -D $DEVICE -uM >$LOG 2>&1 < $TMP_FILESYSTEMS
487 | while read part part_type part_label fs_string
488 | do
489 | if [ "$fs_string" != no_fs ]
490 | then
491 | local fs
492 | 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)
493 | do
494 | parse_filesystem_string "$fs"
495 | echo "$part $part_type $part_label $fs_type $fs_create $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params" >> $TMP_FILESYSTEMS
496 | done
497 | fi
498 | done < $TMP_BLOCKDEVICES
499 |
500 | }
501 |
502 | # $1: part_type of underlying device
503 | # $2: name of underlying device
504 | # $3: fs_params (needed because VG's have a list of needed lvm-pv's in there)
505 | underlying_exists () {
506 | local part_type=$1
507 | local part=$2
508 | local fs_params=$3
509 | if [ "$part_type" = lvm-vg ]; then
510 | # We can't always do -b on the lvm VG. because the devicefile sometimes doesn't exist for a VG. vgdisplay to the rescue!
511 | # we can't use vgdisplay because that exists 0 when the requisted VG doesn't exist
512 | vgdisplay $part | grep -q 'VG Name'
513 | return
514 | elif [ "$part_type" = lvm-pv ]; then
515 | # check if all needed pv's exist. note that pvdisplay exits 5 as long as one of the args doesn't exist
516 | pvdisplay ${fs_params//__/ } >/dev/null
517 | return
518 | fi
519 | # part type is raw (a physical disk), or dm_crypt or lvm-pv
520 | [ -b "$part" ]
521 | return
522 | }
523 |
524 | # process all entries in $TMP_BLOCKDEVICES, create all blockdevices and filesystems and mount them correctly
525 | process_filesystems ()
526 | {
527 | debug 'FS' "process_filesystems Called. checking all entries in $TMP_BLOCKDEVICES"
528 | rm -f $TMP_FSTAB
529 | generate_filesystem_list
530 | local ret=0
531 |
532 | # phase 1: create all blockdevices and filesystems in the correct order (for each fs, the underlying block/lvm/devicemapper device must be available so dependencies must be resolved. for lvm:first pv's, then vg's, then lv's etc)
533 | # don't let them mount yet. we take care of all that ourselves in the next phase
534 |
535 | inform "Phase 1: Creating filesystems & blockdevices" disks
536 | done_filesystems=
537 | for i in `seq 1 10`
538 | do
539 | open_items=0
540 | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
541 | do
542 | fs_id="$part $fs_type $fs_mountpoint $fs_opts $fs_label $fs_params"
543 | if [ "$fs_create" = yes ]
544 | then
545 | if check_is_in "$fs_id" "${done_filesystems[@]}"
546 | then
547 | debug 'FS' "phase 1 iteration $i: $fs_id ->Already done"
548 | elif underlying_exists $part_type $part $fs_params
549 | then
550 | debug 'FS' "phase 1 iteration $i: Creating $fs_type on $part_type $part ($fs_id)"
551 | inform "Making $fs_type filesystem on $part" disks
552 | needs_pkg=${filesystem_pkg[$fs_type]}
553 | [ -n "$needs_pkg" ] && check_is_in $needs_pkg "${needed_pkgs_fs[@]}" || needed_pkgs_fs+=($needs_pkg)
554 | BLOCK_ROLLBACK_USELESS=0
555 | if process_filesystem ${part/+} $fs_type $fs_create $fs_mountpoint no_mount $fs_opts $fs_label $fs_params; then
556 | done_filesystems+=("$fs_id")
557 | else
558 | debug 'FS' "phase 1 iteration $i: FAILED to reating $fs_type on $part_type $part ($fs_id)"
559 | ret=1
560 | break 2
561 | fi
562 | else
563 | debug 'FS' "phase 1 iteration $i: Cannot create $fs_type yet on $part_type $part, because it is not yet available ($fs_id)"
564 | open_items=1
565 | fi
566 | fi
567 | done < $TMP_FILESYSTEMS
568 | [ $open_items -eq 0 ] && break
569 | done
570 | if ((open_items||ret)); then
571 | show_warning "Filesystem/blockdevice processor problem" "Warning: Could not create all needed filesystems. Either the underlying blockdevices didn't appear in 10 iterations, or process_filesystem failed"
572 | return 1
573 | fi
574 |
575 | # phase 2: mount all filesystems in the vfs in the correct order. (also swapon where appropriate)
576 |
577 | inform "Phase 2: Mounting filesystems" disks
578 | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
579 | do
580 | if [[ $fs_mountpoint != no_mountpoint || $fs_type = swap ]]; then
581 | debug 'FS' "phase 2: swapon/mounting $part - $fs_type"
582 | [[ $fs_mountpoint != no_mountpoint ]] && inform "Mounting $part ($fs_type) on $fs_mountpoint" disks
583 | [[ $fs_type = swap ]] && inform "Swaponning $part" disks
584 | BLOCK_ROLLBACK_USELESS=0
585 | if ! process_filesystem $part $fs_type no $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params; then
586 | debug 'FS' "phase 2: FAILED to swapon/mount $part - $fs_type"
587 | ret=1
588 | break
589 | fi
590 | else
591 | debug 'FS' "phase 2: no need to mount: $part - $fs_type"
592 | fi
593 | done < <(sort -t \ -k 6 $TMP_FILESYSTEMS)
594 |
595 | [ $ret -eq 0 ] && inform "Done processing filesystems/blockdevices" disks 1 && return 0
596 | return $ret
597 | }
598 |
599 |
600 | # Roll back all "filesystems" (normal ones and dm-mapper based stuff) specified in $BLOCK_DATA. Not partitions. Doesn't restore data after you erased it, of course.
601 | rollback_filesystems ()
602 | {
603 | inform "Rolling back filesystems..." disks
604 | generate_filesystem_list
605 | local warnings=
606 | rm -f $TMP_FSTAB
607 |
608 | # phase 1: destruct all mounts in the vfs and swapoff swap volumes who are listed in $BLOCK_DATA
609 | # re-order list so that we umount in the correct order. eg first umount /a/b/c, then /a/b. we sort alphabetically, which has the side-effect of sorting by stringlength, hence by vfs dependencies.
610 |
611 | inform "Phase 1: Umounting all specified mountpoints" disks
612 | 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.
613 | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
614 | do
615 | if [ "$fs_type" = swap ]
616 | then
617 | inform "(Maybe) Swapoffing $part" disks
618 | swapoff $part &>/dev/null # could be that it was not swappedon yet. that's not a problem at all.
619 | elif [ "$fs_mountpoint" != no_mountpoint ]
620 | then
621 | part_real=${part/+/}
622 | if ! check_is_in "$part_real" "${done_umounts[@]}"
623 | then
624 | inform "(Maybe) Umounting $part_real" disks
625 | if mount | grep -q "^$part_real " # could be that this was not mounted yet. no problem, we can just skip it then.
626 | then
627 | if umount $part_real >$LOG
628 | then
629 | done_umounts+=("$part_real")
630 | else
631 | warnings="$warnings\nCould not umount umount $part_real . Probably device is still busy. See $LOG"
632 | show_warning "Umount failure" "Could not umount umount $part_real . Probably device is still busy. See $LOG" #TODO: fix device busy things
633 | fi
634 | fi
635 | fi
636 | fi
637 | done < <(sort -t \ -k 6 -r $TMP_FILESYSTEMS)
638 |
639 |
640 | # 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)
641 | # targets are device-mapper devices such as any lvm things, dm_crypt devices, etc and lvm PV's.
642 |
643 | # Possible approach 1 (not implemented): for each target in $TMP_BLOCKDEVICES, check that it has no_fs or has a non-lvm/dm_crypt fs. (egrep -v ' lvm-pv;| lvm-vg;| lvm-lv;| dm_crypt;' ) and clean it
644 | # -> requires updating of underlying block device string when you clean something, on a copy of .block_data etc. too complicated
645 | # Approach 2 : iterate over all targets in $TMP_BLOCKDEVICES as much as needed, until a certain limit, and in each loop check what can be cleared by looking at the real, live usage of / dependencies on the partition.
646 | # -> easier (implemented)
647 |
648 |
649 | inform "Phase 2: destructing relevant blockdevices" disks
650 | for i in `seq 1 10`
651 | do
652 | open_items=0
653 | while read part part_type part_label fs_string
654 | do
655 | check_is_in "$part_type" dm_crypt lvm-pv lvm-vg lvm-lv || continue
656 |
657 | real_part=${part/+/}
658 |
659 | # do not destroy a blockdevice if it hosts one or more filesystems that were set to not recreate
660 | # fs_string = one or more "$fs_type;$fs_create;$fs_mountpoint;target;$fs_opts;$fs_label;$fs_params", separated by ':'
661 | # there is probably a nice regex to check this but i'm bad at regexes.
662 | if echo "$fs_string" | grep -q ';yes;/' || echo "$fs_string" | grep -q ';yes;no_mountpoint'
663 | then
664 | inform "Skipping destruction of $part ($part_type) because one of the filesystems on it contains data you want to keep"
665 | # TODO: it's possible that if we don't clear a blockdevice here because there is something on it with valuable data, that this blockdevice itself is hosted on some other blockdevice (eg lvm VG,PV or dm_crypt), \
666 | # that blockdevice cannot be cleared as well because it depends on this one, so after 10 iterations the user will get a warning that not everything is cleared. so we should fix this someday.
667 | elif [ "$part_type" = dm_crypt ] # Can be in use for: lvm-pv or raw. we don't need to care about raw (it will be unmounted so it can be destroyed)
668 | then
669 | if [ -b $real_part ] && cryptsetup status $real_part &>/dev/null # don't use 'isLuks' it only works for the "underlying" device (eg in /dev/sda1 -> luksOpen -> /dev/mapper/foo, isLuks works only on the former. status works on the latter too)
670 | then
671 | if pvdisplay $real_part &>/dev/null
672 | then
673 | debug 'FS' "$part ->Cannot do right now..."
674 | open_items=1
675 | else
676 | inform "Attempting destruction of device $part (type $part_type)" disks
677 | if ! cryptsetup luksClose $real_part &>$LOG
678 | then
679 | warnings="$warnings\nCould not cryptsetup luksClose $real_part"
680 | show_warning "process_filesystems blockdevice destruction" "Could not cryptsetup luksClose $real_part"
681 | fi
682 | fi
683 | else
684 | debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
685 | fi
686 | elif [ "$part_type" = lvm-pv ] # Can be in use for: lvm-vg
687 | then
688 | if [ -b $real_part ] && pvdisplay $real_part &>/dev/null
689 | then
690 | if vgdisplay -v 2>/dev/null | grep -q $real_part # check if it's in use
691 | then
692 | debug 'FS' "$part ->Cannot do right now..."
693 | open_items=1
694 | else
695 | inform "Attempting destruction of device $part (type $part_type)" disks
696 | if ! pvremove $real_part &>$LOG
697 | then
698 | warnings="$warnings\nCould not pvremove $part"
699 | show_warning "process_filesystems blockdevice destruction" "Could not pvremove $part"
700 | fi
701 | fi
702 | else
703 | debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
704 | fi
705 | elif [ "$part_type" = lvm-vg ] #Can be in use for: lvm-lv
706 | then
707 | if vgdisplay $part 2>/dev/null | grep -q 'VG Name' # workaround for non-existing lvm VG device files
708 | then
709 | open_lv=`vgdisplay -c $part 2>/dev/null | cut -d ':' -f6`
710 | if [ $open_lv -gt 0 ]
711 | then
712 | debug 'FS' "$part ->Cannot do right now..."
713 | open_items=1
714 | else
715 | inform "Attempting destruction of device $part (type $part_type)" disks
716 | if ! vgremove $part &>$LOG # we shouldn't need -f because we clean up the lv's first.
717 | then
718 | warnings="$warnings\nCould not vgremove $part"
719 | show_warning "process_filesystems blockdevice destruction" "Could not vgremove $part"
720 | fi
721 | fi
722 | else
723 | debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
724 | fi
725 | 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)
726 | then
727 | if lvdisplay $part &>/dev/null && ! vgdisplay $part 2>/dev/null | grep -q 'VG Name' # it exists: lvdisplay works, and it's not a volume group (you can do lvdisplay $volumegroup)
728 | then
729 | if cryptsetup isLuks $part &>/dev/null
730 | then
731 | debug 'FS' "$part ->Cannot do right now..."
732 | open_items=1
733 | else
734 | inform "Attempting destruction of device $part (type $part_type)" disks
735 | if ! lvremove -f $part &>$LOG
736 | then
737 | warnings="$warnings\nCould not lvremove -f $part"
738 | show_warning "process_filesystems blockdevice destruction" "Could not lvremove -f $part"
739 | fi
740 | fi
741 | else
742 | debug 'FS' "Skipping destruction of device $part (type $part_type) because it doesn't exist"
743 | fi
744 | else
745 | die_error "Unrecognised partition type $part_type for partition $part. This should never happen. please report this"
746 | fi
747 | done < $TMP_BLOCKDEVICES
748 | [ $open_items -eq 0 ] && break
749 | done
750 |
751 | if [ $open_items -eq 1 ]
752 | then
753 | warnings="$warnings\nCould not destruct all filesystems/blockdevices. It appears some depending filesystems/blockdevices could not be cleared in 10 iterations"
754 | show_warning "Filesystem/blockdevice processor problem" "Warning: Could not destruct all filesystems/blockdevices. It appears some depending filesystems/blockdevices could not be cleared in 10 iterations"
755 | fi
756 | [ -n "$warnings" ] && inform "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
757 | inform "Rollback succeeded" disks 1
758 | done_filesystems=
759 | needed_pkgs_fs=
760 | BLOCK_ROLLBACK_USELESS=1
761 | return 0
762 | }
763 |
764 |
765 | # make a filesystem on a blockdevice and mount if needed.
766 | # parameters: (all encoded)
767 | # $1 partition
768 | # $2 fs_type
769 | # $3 fs_create (optional. defaults to yes)
770 | # $4 fs_mountpoint (optional. defaults to no_mountpoint)
771 | # $5 fs_mount (optional. defaults to no_mount)
772 | # $6 fs_opts (optional. defaults to no_opts)
773 | # $7 fs_label (optional. defaults to no_label or for lvm volumes who need a label (VG's and LV's) vg1,vg2,lv1 etc). Note that if there's no label for a VG you probably did something wrong, because you probably want LV's on it so you need a label for the VG.
774 | # $8 fs_params (optional. defaults to no_params)
775 |
776 | process_filesystem ()
777 | {
778 | [ "$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.
779 | [ -z "$2" ] && die_error "process_filesystem needs a filesystem type as \$2"
780 | debug 'FS' "process_filesystem $@"
781 | local ret=0
782 | part=$1
783 | parse_filesystem_string "$2;$3;$4;$5;$6;$7;$8" '' ''
784 |
785 | # Create the FS
786 | if [ "$fs_create" = yes ]
787 | then
788 | if ! check_is_in $fs_type "${!filesystem_programs[@]}"
789 | then
790 | show_warning "process_filesystem error" "Cannot determine filesystem program for $fs_type on $part. Not creating this FS"
791 | return 1
792 | fi
793 | [ -z "$fs_label" ] && [ "$fs_type" = lvm-vg -o "$fs_type" = lvm-pv ] && fs_label=default #TODO. implement the incrementing numbers label for lvm vg's and lv's
794 |
795 | #TODO: health checks on $fs_params etc
796 | program="${filesystem_programs[$fs_type]}"
797 | case ${fs_type} in
798 | xfs)
799 | $program -f $part $fs_opts >$LOG 2>&1; ret=$? ;;
800 | jfs|reiserfs)
801 | yes | $program $part $fs_opts >$LOG 2>&1; ret=$? ;;
802 | swap|ext2|ext3|ext4|nilfs2|vfat|btrfs)
803 | $program $part $fs_opts >$LOG 2>&1; ret=$? ;;
804 | dm_crypt)
805 | [ -z "$fs_params" ] && fs_params='-c aes-xts-plain -y -s 512';
806 | inform "Please enter your passphrase to encrypt the device (with confirmation)"
807 | $program $fs_params $fs_opts luksFormat -q $part >$LOG 2>&1 < /dev/tty ; ret=$? #hack to give cryptsetup the approriate stdin. keep in mind we're in a loop (see process_filesystems where something else is on stdin)
808 | inform "Please enter your passphrase to unlock the device"
809 | $program luksOpen $part $fs_label >$LOG 2>&1 < /dev/tty; ret=$? || ( show_warning 'cryptsetup' "Error luksOpening $part on /dev/mapper/$fs_label" ) ;;
810 | lvm-pv)
811 | $program $fs_opts $part >$LOG 2>&1; ret=$? ;;
812 | lvm-vg)
813 | # $fs_params: list of PV's
814 | $program $fs_opts $fs_label $fs_params >$LOG 2>&1; ret=$? ;;
815 | lvm-lv)
816 | # $fs_params = size string (eg '5G')
817 | $program -L $fs_params $fs_opts -n $fs_label $(basename $part) >$LOG 2>&1; ret=$? ;; #$fs_opts is usually something like -L 10G # Strip '/dev/mapper/' part because device file may not exist. TODO: do i need to activate them?
818 | *)
819 | die_error "AIF error. somebody needs to update process_filesystem() to support $fs_type"
820 | esac
821 | # The udevadm settle is a workaround for a bug/racecondition in cryptsetup. See:
822 | # http://mailman.archlinux.org/pipermail/arch-releng/2010-April/000974.html
823 | # It may not be needed (anymore), or not after every type of FS, but we're rather safe then sorry. and it seems to always return in less then a second
824 | udevadm settle
825 | BLOCK_ROLLBACK_USELESS=0
826 | [ "$ret" -gt 0 ] && { show_warning "process_filesystem error" "Error creating filesystem $fs_type on $part."; return 1; }
827 | sleep 2
828 | fi
829 |
830 | if [ -n "$fs_label" ] && check_is_in $fs_type "${!label_programs[@]}"
831 | then
832 | program="${label_programs[$fs_type]}"
833 | case ${fs_type} in
834 | swap|xfs|jfs|nilfs2|ext2|ext3|ext4|btrfs)
835 | $program -L $fs_label $part >$LOG 2>&1; ret=$?;;
836 | reiserfs)
837 | $program -l $fs_label $part >$LOG 2>&1; ret=$?;;
838 | vfat)
839 | $program $part $fs_label >$LOG 2>&1; ret=$?;;
840 | *)
841 | die_error "AIF error. somebody needs to update process_filesystem() to support $fs_type"
842 | esac
843 | [ "$ret" -gt 0 ] && { show_warning "process_filesystem error" "Error setting label $fs_label on $part." ; return 1; }
844 | fi
845 |
846 | # Mount it, if requested. Note that it's your responsability to figure out if you want this or not before calling me. This will only work for 'raw' filesystems (ext,reiser,xfs, swap etc. not lvm stuff,dm_crypt etc)
847 | if [ "$fs_mount" = runtime -o "$fs_mount" = target ]
848 | then
849 | BLOCK_ROLLBACK_USELESS=0
850 | if [ "$fs_type" = swap ]
851 | then
852 | debug 'FS' "swaponning $part"
853 | swapon $part >$LOG 2>&1 || ( show_warning 'Swapon' "Error activating swap: swapon $part" ; ret=1 )
854 | fs_mountpoint="none"
855 | else
856 | [ "$fs_mount" = runtime ] && dst=$fs_mountpoint
857 | [ "$fs_mount" = target ] && dst=$var_TARGET_DIR$fs_mountpoint
858 | debug 'FS' "mounting $part on $dst"
859 | mkdir -p $dst &>/dev/null # directories may or may not already exist
860 | mount -t $fs_type $part $dst >$LOG 2>&1 || ( show_warning 'Mount' "Error mounting $part on $dst" ; ret=1 )
861 | fi
862 | fi
863 |
864 |
865 | # Add to temp fstab, if not already there.
866 | if [ -n "$fs_mountpoint" -a "$fs_mount" = target ]
867 | then
868 | case "$PART_ACCESS" in
869 | label)
870 | local label
871 | label="$(getlabel $part)" && part="LABEL=$label";;
872 | uuid)
873 | local uuid
874 | uuid="$(getuuid $part)" && part="UUID=$uuid";;
875 | esac
876 | fs_passno=2
877 | [[ $fs_mountpoint = "/" ]] && fs_passno=1
878 | [[ $fs_type = "swap" ]] && fs_passno=0
879 | line="$part $fs_mountpoint $fs_type defaults 0 $fs_passno"
880 | # the file $TMP_FSTAB might not exist yet
881 | grep -q "$line" $TMP_FSTAB 2>/dev/null || echo "$line" >> $TMP_FSTAB
882 | fi
883 |
884 | return $ret
885 |
886 | #TODO: if target has LVM volumes, copy /etc/lvm/backup to /etc on target (or maybe it can be regenerated with a command, i should look that up)
887 |
888 | }
889 |
890 |
891 | # $1 blockdevice
892 | # $2 unit: B, KiB, kB, MiB, MB, GiB or GB. defaults to B (we follow IEEE 1541-2002 )
893 | # output will be in $BLOCKDEVICE_SIZE
894 | get_blockdevice_size ()
895 | {
896 | [ -b "$1" ] || die_error "get_blockdevice_size needs a blockdevice as \$1 ($1 given)"
897 | unit=${2:-B}
898 | allowed_units=(B KiB kB MiB MB GiB GB)
899 | if ! check_is_in $unit "${allowed_units[@]}"
900 | then
901 | die_error "Unrecognized unit $unit!"
902 | fi
903 |
904 | # NOTES about older, deprecated methods:
905 | # - 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.
906 | # - unreliable method: on some interwebs they say 1 block = 512B, on other internets they say 1 block = 1kiB. 1kiB seemed to work for me.
907 | # blocks=`fdisk -s $1` || show_warning "Fdisk problem" "Something failed when trying to do fdisk -s $1"
908 | # BLOCKDEVICE_SIZE=$(($blocks/1024))
909 |
910 | bytes=$((`fdisk -l $1 2>/dev/null | sed -n '2p' | cut -d' ' -f5`))
911 | [[ $bytes = *[^0-9]* ]] && die_error "Could not parse fdisk -l output for $1"
912 | [ $unit = B ] && BLOCKDEVICE_SIZE=$bytes
913 | [ $unit = KiB ] && BLOCKDEVICE_SIZE=$((bytes/2**10)) # /1024
914 | [ $unit = kB ] && BLOCKDEVICE_SIZE=$((bytes/10**3)) # /1000
915 | [ $unit = MiB ] && BLOCKDEVICE_SIZE=$((bytes/2**20)) # ...
916 | [ $unit = MB ] && BLOCKDEVICE_SIZE=$((bytes/10**6))
917 | [ $unit = GiB ] && BLOCKDEVICE_SIZE=$((bytes/2**30))
918 | [ $unit = GB ] && BLOCKDEVICE_SIZE=$((bytes/10**9))
919 | true
920 | }
921 |
922 |
923 | # $1 blockdevice (ex: /dev/md0 or /dev/sda1)
924 | # All MD RAID block devices have a major id of 9
925 | device_is_raid() {
926 | [[ -b "$1" ]] || die_error "device_is_raid needs a blockdevice as \$1 ($1 given)"
927 | [[ -f /proc/mdstast ]] || return 1
928 | local devmajor=$(stat -c %t "$1")
929 | (( devmajor == 9 ))
930 | }
931 |
932 |
933 | # $1 md raid blockdevice (ex: /dev/md0)
934 | # return a list of array members from given md array
935 | # ex: /dev/md0 has slaves: "/dev/sda1 /dev/sdb2 /dev/sdc2"
936 | mdraid_all_slaves ()
937 | {
938 | shopt -s nullglob
939 | local slave=
940 | local slaves=
941 | for slave in /sys/class/block/${1##*/}/slaves/*; do
942 | source "$slave/uevent"
943 | slaves="$slaves/dev/$DEVNAME "
944 | unset DEVNAME
945 | done
946 | shopt -u nullglob
947 | echo $slaves
948 | }
949 |
--------------------------------------------------------------------------------
/src/core/libs/lib-flowcontrol.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | usage ()
4 | {
5 | msg="aif -p Select a procedure # If given, this *must* be the first option
6 | -i Override interface type (optional)
7 | -d Explicitly enable debugging (/var/log/aif/debug.log) (optional)
8 | -l Explicitly enable logging to file (/var/log/aif/aif.log) (optional)
9 | -h Help: show usage (optional)\n
10 | If the procedurename starts with 'http://' it will be wget'ed. Otherwise it's assumed to be a procedure in the VFS tree
11 | If the procedurename is prefixed with '/' it will be loaded from user module .\n
12 | For more info, see the README which you can find in /usr/share/aif/docs\n
13 | Available procedures:
14 | ==core==
15 | `find $LIB_CORE/procedures -type f | sed \"s#$LIB_CORE/procedures/##\" | sort`
16 | ==user==
17 | `find $LIB_USER/*/procedures -type f 2>/dev/null | sed \"s#$LIB_USER/\(.*\)/procedures/#\1/#\" | sort`"
18 | [ -n "$procedure" ] && msg="$msg\nProcedure ($procedure) specific options:\n$var_ARGS_USAGE"
19 |
20 | echo -e "$msg"
21 | }
22 |
23 |
24 | # $1 module name
25 | load_module ()
26 | {
27 | [ -z "$1" ] && die_error "load_module needs a module argument"
28 | log "Loading module $1 ..."
29 | local path=$LIB_USER/"$1"
30 | [ "$1" = core ] && path=$LIB_CORE
31 |
32 | for submodule in lib #procedure don't load procedures automatically!
33 | do
34 | if [ ! -d "$path/${submodule}s" ]
35 | then
36 | # ignore this problem for not-core modules
37 | [ "$1" = core ] && die_error "$path/${submodule}s does not exist. something is horribly wrong with this installation"
38 | else
39 | shopt -s nullglob
40 | local module
41 | for module in "$path/${submodule}s"/*
42 | do
43 | # I have the habit of editing files while testing, don't source my backup files!
44 | [[ "$module" == *~ ]] && continue
45 | module=$(basename "$module")
46 | load_${submodule} "$1" "$module"
47 | done
48 | shopt -u nullglob
49 | fi
50 | done
51 |
52 | }
53 |
54 |
55 | # $1 module name
56 | # $2 procedure name
57 | load_procedure()
58 | {
59 | [ -z "$1" ] && die_error "load_procedure needs a module as \$1 and procedure as \$2"
60 | [ -z "$2" ] && die_error "load_procedure needs a procedure as \$2"
61 | if [ "$1" = 'http' ]
62 | then
63 | log "Loading procedure $2 ..."
64 | local procedure=$RUNTIME_DIR/aif-procedure-downloaded-`basename $2`
65 | wget "$2" -q -O $procedure >/dev/null || die_error "Could not download procedure $2"
66 | else
67 | log "Loading procedure $1/procedures/$2 ..."
68 | local procedure=$LIB_USER/"$1"/procedures/"$2"
69 | [ "$1" = core ] && procedure=$LIB_CORE/procedures/"$2"
70 | fi
71 | [ -f "$procedure" ] && source "$procedure" || die_error "Something went wrong while sourcing procedure $procedure"
72 | }
73 |
74 |
75 | # $1 module name
76 | # $2 library name
77 | load_lib ()
78 | {
79 | [ -z "$1" ] && die_error "load_library needs a module als \$1 and library as \$2"
80 | [ -z "$2" ] && die_error "load_library needs a library as \$2"
81 | log "Loading library $1/libs/$2 ..."
82 | local lib=$LIB_USER/"$1"/libs/"$2"
83 | [ "$1" = core ] && lib=$LIB_CORE/libs/"$2"
84 | source $lib || die_error "Something went wrong while sourcing library $lib"
85 | }
86 |
87 |
88 | # $1 phase/worker
89 | # $2 phase/worker name
90 | # $3... extra args for phase/worker (optional)
91 | execute ()
92 | {
93 | [ -z "$1" -o -z "$2" ] && debug 'MAIN' "execute $@" && die_error "Use the execute function like this: execute with type=phase/worker"
94 | [ "$1" != phase -a "$1" != worker ] && debug 'MAIN' "execute $@" && die_error "execute's first argument must be a valid type (phase/worker)"
95 | local PWD_BACKUP=`pwd`
96 | local object=$1_$2
97 |
98 | if [ "$1" = worker ]
99 | then
100 | log "*** Executing worker $2"
101 | if type -t $object | grep -q function
102 | then
103 | shift 2
104 | $object "$@"
105 | local ret=$?
106 | local exit_var=exit_$object
107 | read $exit_var <<< $ret # maintain exit status of each worker
108 | else
109 | die_error "$object is not defined!"
110 | fi
111 | elif [ "$1" = phase ]
112 | then
113 | log "******* Executing phase $2"
114 | local exit_var=exit_$object
115 | read $exit_var <<< 0
116 | # 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...
117 | # debug 'MAIN' "\$1: $1, \$2: $2, \$object: $object, \$exit_$object: $exit_object"
118 | # debug 'MAIN' "declare: `declare | grep -e "^${object}=" | cut -d"=" -f 2-`"
119 | # props to jedinerd at #bash for this hack.
120 | # eval phase=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
121 | #debug 'MAIN' "\$phase: $phase - ${phase[@]}"
122 | unset phase
123 | [ "$2" = preparation ] && phase=( "${phase_preparation[@]}" )
124 | [ "$2" = basics ] && phase=( "${phase_basics[@]}" )
125 | [ "$2" = system ] && phase=( "${phase_system[@]}" )
126 | [ "$2" = finish ] && phase=( "${phase_finish[@]}" )
127 | # worker_str contains the name of the worker and optionally any arguments
128 | for worker_str in "${phase[@]}"
129 | do
130 | debug 'MAIN' "Loop iteration. \$worker_str: $worker_str"
131 | execute worker $worker_str || read $exit_var <<< $? # assign last failing exit code to exit_phase_, if any.
132 | done
133 | local ret=${!exit_var}
134 | fi
135 |
136 | debug 'MAIN' "Execute(): $object exit state was $ret"
137 | cd $PWD_BACKUP
138 | return $ret
139 | }
140 |
141 |
142 | # check if a phase/worker executed successfully
143 | # returns 0 if ok, the phase/workers' exit state otherwise (and returns 1 if not executed yet)
144 | # $1 phase/worker
145 | # $2 phase/worker name
146 | ended_ok ()
147 | {
148 | [ -z "$1" -o -z "$2" ] && die_error "Use the ended_ok function like this: ended_ok with type=phase/worker"
149 | [ "$1" != phase -a "$1" != worker ] && die_error "ended_ok's first argument must be a valid type (phase/worker)"
150 | object=$1_$2
151 | exit_var=exit_$object
152 | debug 'MAIN' "Ended_ok? -> Exit state of $object was: ${!exit_var} (if empty. it's not executed yet)"
153 | [ "${!exit_var}" = '0' ] && return 0
154 | [ "${!exit_var}" = '' ] && return 1
155 | return ${!exit_var}
156 | }
157 |
158 |
159 | depend_module ()
160 | {
161 | load_module "$1"
162 | }
163 |
164 |
165 | depend_procedure ()
166 | {
167 | load_procedure "$1" "$2"
168 | }
169 |
170 |
171 | start_process ()
172 | {
173 | local ret=0
174 | execute phase preparation || ret=$?
175 | execute phase basics || ret=$?
176 | execute phase system || ret=$?
177 | execute phase finish || ret=$?
178 | return $ret
179 | }
180 |
181 |
182 | show_report ()
183 | {
184 | data="Execution Report:"
185 | data="$data\n-----------------"
186 | for phase in preparation basics system finish
187 | do
188 | object=phase_$phase
189 | exit_var=exit_$object
190 | local ret=${!exit_var}
191 | [ "$ret" = "0" ] && data="$data\nPhase $phase: Success"
192 | [ "$ret" = "0" ] || data="$data\nPhase $phase: Failed"
193 | eval phase_array=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-)
194 | for worker_str in "${phase_array[@]}"
195 | do
196 | worker=${worker_str%% *}
197 | exit_var=exit_worker_$worker
198 | ret=${!exit_var}
199 | case "$ret" in
200 | "") data="$data\n > Worker $worker: Skipped";;
201 | "0") data="$data\n > Worker $worker: Success";;
202 | *) data="$data\n > Worker $worker: Failed";;
203 | esac
204 | done
205 | done
206 | inform "$data"
207 | }
208 |
209 |
210 | start_installer ()
211 | {
212 | log "################## START OF INSTALLATION ##################"
213 | }
214 |
215 |
216 | # use this function to stop the installation procedure.
217 | # $1 exit code (optional, defaults to 0)
218 | stop_installer ()
219 | {
220 | log "-------------- STOPPING INSTALLATION ----------"
221 | cleanup_runtime
222 | [ "$var_UI_TYPE" = dia ] && clear
223 | exit ${1:-0}
224 | }
225 |
--------------------------------------------------------------------------------
/src/core/libs/lib-misc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | # runs a process and makes sure the output is shown to the user. sets the exit state of the executed program ($CONTROLLED_EXIT) so the caller can show a concluding message.
5 | # 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)
6 | # 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
7 | # $1 identifier (no spaces allowed, hyphen and underscore are ok)
8 | # $2 command (will be eval'ed)
9 | # $3 logfile
10 | # $4 title to show while process is running
11 | run_controlled ()
12 | {
13 | [ -z "$1" ] && die_error "run_controlled: please specify an identifier to keep track of the command!"
14 | [ -z "$2" ] && die_error "run_controlled needs a command to execute!"
15 | [ -z "$3" ] && die_error "run_controlled needs a logfile to redirect output to!"
16 | [ -z "$4" ] && die_error "run_controlled needs a title to show while your process is running!"
17 |
18 | log_parent=$(dirname $3)
19 | if [ ! -d $log_parent ]; then
20 | mkdir -p $log_parent || die_error "Could not create $log_parent, we were asked to log $1 to $3"
21 | fi
22 | if [ "$var_UI_TYPE" = dia ]
23 | then
24 | run_background $1 "$2" $3
25 | follow_progress " $4 " $3 $BACKGROUND_PID # dia mode ignores the pid. cli uses it to know how long it must do tail -f
26 | wait_for $1 $FOLLOW_PID || die_error "Internal AIF error, the following call failed: wait_for $1 $FOLLOW_PID. This should never happen"
27 | CONTROLLED_EXIT=$BACKGROUND_EXIT
28 | else
29 | notify "$4"
30 | eval "$2" >>$3 2>&1
31 | CONTROLLED_EXIT=$?
32 | fi
33 | debug 'MISC' "run_controlled done with $1: exitcode (\$CONTROLLED_EXIT): $CONTROLLED_EXIT .Logfile $3"
34 | return $CONTROLLED_EXIT
35 | }
36 |
37 |
38 | # run a process in the background, and log it's stdout and stderr to a specific logfile
39 | # returncode is stored in BACKGROUND_EXIT
40 | # pid of the backgrounded wrapper process is stored in BACKGROUND_PID (this is _not_ the pid of $2)
41 | # $1 identifier
42 | # $2 command (will be eval'ed)
43 | # $3 logfile
44 | run_background ()
45 | {
46 | [ -z "$1" ] && die_error "run_background: please specify an identifier to keep track of the command!"
47 | [ -z "$2" ] && die_error "run_background needs a command to execute!"
48 | [ -z "$3" ] && die_error "run_background needs a logfile to redirect output to!"
49 |
50 | log_parent=$(dirname $3)
51 | if [ ! -d $log_parent ]; then
52 | mkdir -p $log_parent || die_error "Could not create $log_parent, we were asked to log $1 to $3"
53 | fi
54 |
55 | debug 'MISC' "run_background called. identifier: $1, command: $2, logfile: $3"
56 | ( \
57 | touch $RUNTIME_DIR/aif-$1-running
58 | debug 'MISC' "run_background starting $1: $2 >>$3 2>&1"
59 | [ -f $3 ] && echo -e "\n\n\n" >>$3
60 | echo "STARTING $1 . Executing $2 >>$3 2>&1\n" >> $3;
61 | eval "$2" >>$3 2>&1
62 | BACKGROUND_EXIT=$?
63 | debug 'MISC' "run_background done with $1: exitcode (\$BACKGROUND_EXIT): $BACKGROUND_EXIT .Logfile $3"
64 | echo >> $3
65 | echo $BACKGROUND_EXIT > $RUNTIME_DIR/aif-$1-exit
66 | rm -f $RUNTIME_DIR/aif-$1-running
67 | ) &
68 | BACKGROUND_PID=$!
69 |
70 | sleep 2
71 | }
72 |
73 |
74 | # wait until a process - spawned by run_background - is done
75 | # $1 identifier. WARNING! see above
76 | # $2 pid of a process to kill when done (optional). useful for dialog --no-kill --tailboxbg's pid.
77 | # returns 0 unless anything failed in the wait_for logic (not tied to the exitcode of the program we actually wait for)
78 | wait_for ()
79 | {
80 | [ -z "$1" ] && die_error "wait_for needs an identifier to known on which command to wait!"
81 | local ret=0
82 | while [ -f $RUNTIME_DIR/aif-$1-running ]
83 | do
84 | sleep 1
85 | done
86 | BACKGROUND_EXIT=$(cat $RUNTIME_DIR/aif-$1-exit) || ret=1
87 | rm $RUNTIME_DIR/aif-$1-exit || ret=1
88 | if [ -n "$2" ]
89 | then
90 | kill $2 || ret=1
91 | fi
92 | return $ret
93 | }
94 |
95 |
96 | # $1 needle
97 | # $2 set (array) haystack
98 | check_is_in ()
99 | {
100 | [ -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
101 |
102 | local needle="$1" element
103 | shift
104 | for element
105 | do
106 | [[ $element = $needle ]] && return 0
107 | done
108 | return 1
109 | }
110 |
111 |
112 | # cleans up file in the runtime directory who can be deleted, make dir first if needed
113 | cleanup_runtime ()
114 | {
115 | mkdir -p $RUNTIME_DIR || die_error "Cannot create $RUNTIME_DIR"
116 | rm -rf $RUNTIME_DIR/aif-dia* &>/dev/null
117 | }
118 |
119 |
120 | # $1 UTC or localtime (hardwareclock)
121 | # $2 direction (systohc or hctosys)
122 | dohwclock() {
123 | # TODO: we probably only need to do this once and then actually use adjtime on next invocations
124 | inform "Resetting hardware clock adjustment file"
125 | [ -d /var/lib/hwclock ] || mkdir -p /var/lib/hwclock || return 1
126 | if [ ! -f /var/lib/hwclock/adjtime ]; then
127 | echo "0.0 0 0.0" > /var/lib/hwclock/adjtime || return 1
128 | fi
129 |
130 | inform "Syncing clocks ($2), hc being $1 ..."
131 | if [ "$1" = "UTC" ]; then
132 | if ! hwclock --$2 --utc
133 | then
134 | show_warning 'Hwclock failure' "Could not hwclock --$2 --utc"
135 | return 1
136 | fi
137 | else
138 | if ! hwclock --$2 --localtime
139 | then
140 | show_warning 'Hwclock failure' "Could not hwclock --$2 --localtime"
141 | return 1
142 | fi
143 | fi
144 | return 0
145 | }
146 |
147 | target_configure_initial_keymap_font ()
148 | {
149 | local ret=0
150 | if [ -n "$var_KEYMAP" ]; then
151 | sed -i "s/^KEYMAP=.*/KEYMAP=\"`basename $var_KEYMAP .map.gz`\"/" ${var_TARGET_DIR}/etc/rc.conf || ret=$?
152 | fi
153 | if [ -n "$var_CONSOLEFONT" ]; then
154 | sed -i "s/^CONSOLEFONT=.*/CONSOLEFONT=\"${var_CONSOLEFONT/\.*/}\"/" ${var_TARGET_DIR}/etc/rc.conf || ret=$?
155 | fi
156 | return $ret
157 | }
158 |
159 | target_configure_time () {
160 | # /etc/rc.conf
161 | # Make sure timezone and utc info are what we want
162 | # NOTE: If a timezone string never contains more then 1 slash, we can use ${TIMEZONE/\//\\/}
163 | sed -i -e "s/^TIMEZONE=.*/TIMEZONE=\"${TIMEZONE//\//\\/}\"/g" \
164 | -e "s/^HARDWARECLOCK=.*/HARDWARECLOCK=\"$HARDWARECLOCK\"/g" \
165 | ${var_TARGET_DIR}/etc/rc.conf
166 | }
167 |
168 | target_localtime () {
169 | if [ -f /etc/localtime ]
170 | then
171 | cp /etc/localtime ${var_TARGET_DIR}/etc/localtime || return 1
172 | fi
173 | return 0
174 | }
175 |
176 | # apped string after last line matching regex in a file.
177 | # $1 regex
178 | # $2 string (can contain "\n", "\t" etc)
179 | # $3 file
180 | append_after_last ()
181 | {
182 | [ -r "$3" -a -w "$3" ] || return 1
183 | line_no=$(sed -ne "$1=" "$3" | tail -n 1)
184 | [ -n "$line_no" ] || return 1
185 | sed -i ${line_no}a"$2" "$3"
186 | }
187 |
--------------------------------------------------------------------------------
/src/core/libs/lib-network.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # configures network on host system according to installer settings
4 | # if some variables are not set, we handle that transparantly
5 | # however, at least $DHCP must be set, so we know what do to
6 | # we assume that you checked whether networking has been setup before calling us
7 | target_configure_network()
8 | {
9 | # networking setup could have happened in a separate process (eg partial-configure-network),
10 | # so check if the settings file was created to be sure
11 | if [[ -f "$RUNTIME_DIR/aif-network-settings" ]]; then
12 |
13 | debug NETWORK "Configuring network settings on target system according to installer settings"
14 |
15 | source "$RUNTIME_DIR/aif-network-settings" 2>/dev/null || return 1
16 |
17 | IFN=${INTERFACE:-eth0} # new iface: a specified one, or the arch default
18 |
19 | if [[ -f "${var_TARGET_DIR}/etc/profile.d/proxy.sh" ]]; then
20 | sed -i "s/^export/#export/" "${var_TARGET_DIR}/etc/profile.d/proxy.sh" || return 1
21 | fi
22 |
23 | sed -i "s/^\(interface\)=.*/\1=$IFN/" "${var_TARGET_DIR}/etc/rc.conf" || return 1
24 | if (( ! DHCP )); then
25 | sed -i -e "s/^\(address\)=.*/\1=$IPADDR/" \
26 | -e "s/^\(netmask\)=.*/\1=$SUBNET/" \
27 | -e "s/^\(broadcast\)=.*/\1=$BROADCAST/" \
28 | -e "s/^\(gateway\)=.*/\1=$GW/" "${var_TARGET_DIR}/etc/rc.conf" || return 1
29 |
30 | if [[ $DNS ]]; then
31 | for prev_dns in "${auto_added_dns[@]}"; do
32 | sed -i "/nameserver $prev_dns$/d" "${var_TARGET_DIR}/etc/resolv.conf"
33 | done
34 | echo "nameserver $DNS" >> "${var_TARGET_DIR}/etc/resolv.conf" || return 2
35 | auto_added_dns+=("$DNS")
36 | fi
37 | fi
38 |
39 | if [[ $PROXY_HTTP ]]; then
40 | echo "export http_proxy=$PROXY_HTTP" >> "${var_TARGET_DIR}/etc/profile.d/proxy.sh" || return 1
41 | chmod a+x "${var_TARGET_DIR}/etc/profile.d/proxy.sh" || return 1
42 | fi
43 |
44 | if [[ $PROXY_FTP ]]; then
45 | echo "export ftp_proxy=$PROXY_FTP" >> "${var_TARGET_DIR}/etc/profile.d/proxy.sh" || return 1
46 | chmod a+x "${var_TARGET_DIR}/etc/profile.d/proxy.sh" || return 1
47 | fi
48 | else
49 | debug NETWORK "Skipping Host Network Configuration - aif-network-settings not found"
50 | fi
51 | return 0
52 | }
53 |
--------------------------------------------------------------------------------
/src/core/libs/lib-pacman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # target_prepare_pacman():
4 | # configures pacman to run from live environment, but working on target system.
5 | # syncs for the first time on destination system
6 | # Enables all reposities specified by TARGET_REPOSITORIES
7 | # returns: 1 on error
8 | target_prepare_pacman() {
9 | # Setup a pacman.conf in /tmp
10 | echo "[options]" > /tmp/pacman.conf
11 | echo "CacheDir = ${var_TARGET_DIR}/var/cache/pacman/pkg" >> /tmp/pacman.conf
12 | # construct real directory names from pseudonyms like (2 array elements):
13 | # core file:///repo/$repo/$arch
14 | # ideally, we would query those from pacman (which is also who interprets
15 | # these), but pacman does not support something like that, so we do it a bit
16 | # uglier. See https://bugs.archlinux.org/task/25568
17 | arch=$(uname -m)
18 | for line in $(echo ${TARGET_REPOSITORIES[@]} | tr ' ' '\n' | grep -B 1 'file://' | grep -v '\-\-'); do
19 | if ! echo $line | grep -q '^file://'; then
20 | repo=$line
21 | else
22 | cachedir=$(echo $line | sed -e "s#file://##;s#\$repo#$repo#;s#\$arch#$arch#")
23 | [ -d $cachedir ] || die_error "You specified $line (->$cachedir) as a directory to be used as repository, but it does not exist"
24 | echo "CacheDir = $cachedir" >> /tmp/pacman.conf
25 | fi
26 | done
27 | echo "Architecture = auto" >> /tmp/pacman.conf
28 | echo "SigLevel = Never" >> /tmp/pacman.conf
29 |
30 | for i in `seq 0 $((${#TARGET_REPOSITORIES[@]}/2-1))`
31 | do
32 | repo=${TARGET_REPOSITORIES[$(($i*2))]}
33 | location=${TARGET_REPOSITORIES[$(($i*2+1))]}
34 | add_pacman_repo target $repo $location || return 1
35 | done
36 |
37 | if [ -n "$MIRROR" ]; then
38 | configure_mirrorlist runtime || return 1
39 | fi
40 |
41 | # Set up the necessary directories for pacman use
42 | for dir in var/cache/pacman/pkg var/lib/pacman
43 | do
44 | if [ ! -d "${var_TARGET_DIR}/$dir" ]
45 | then
46 | mkdir -m 755 -p "${var_TARGET_DIR}/$dir" || return 1
47 | fi
48 | done
49 |
50 | inform "Refreshing package database..."
51 | $PACMAN_TARGET -Sy >$LOG 2>&1 || return 1
52 | return 0
53 | }
54 |
55 |
56 | # $1 target/runtime
57 | list_pacman_repos ()
58 | {
59 | [ "$1" != runtime -a "$1" != target ] && die_error "list_pacman_repos needs target/runtime argument"
60 | [ "$1" = target ] && conf=/tmp/pacman.conf
61 | [ "$1" = runtime ] && conf=/etc/pacman.conf
62 | grep '\[.*\]' $conf | grep -v options | grep -v '^#' | sed 's/\[//g' | sed 's/\]//g'
63 | }
64 |
65 | # returns all repositories you could possibly use (core, extra, testing, community, ...)
66 | list_possible_repos ()
67 | {
68 | grep -B 2 'Include = /etc/' /etc/pacman.conf | grep '\[' | sed 's/#*\[\(.*\)\]/\1/'
69 | }
70 |
71 |
72 | # $1 target/runtime
73 | # $2 repo name
74 | # $3 string
75 | # automatically knows that if $3 contains the word 'mirrorlist', it should save
76 | # as 'Include = $3', otherwise as 'Server = $3' (for both local and remote)
77 | add_pacman_repo ()
78 | {
79 | [ "$1" != runtime -a "$1" != target ] && die_error "add_pacman_repo needs target/runtime argument"
80 | [ -z "$3" ] && die_error "target_add_repo needs \$2 repo-name and \$3 string (eg Server = ...)"
81 | repo=$2
82 | if echo "$3" | grep -q 'mirrorlist'; then
83 | location="Include = $3"
84 | else
85 | location="Server = $3"
86 | fi
87 | [ "$1" = target ] && conf=/tmp/pacman.conf
88 | [ "$1" = runtime ] && conf=/etc/pacman.conf
89 | cat << EOF >> $conf
90 |
91 | [$repo]
92 | $location
93 | EOF
94 | }
95 |
96 | # not sorted
97 | list_package_groups ()
98 | {
99 | $PACMAN_TARGET -Sg
100 | }
101 |
102 |
103 | # List the packages in one or more repos or groups. output is one or more lines, each line being like this:
104 | # packagename [version, if $1=repo] [installed]
105 | # lines are sorted by packagename, per repo, repos in the order you gave them to us.
106 | # $1 repo or group
107 | # $2 one or more repo or group names
108 | list_packages ()
109 | {
110 | [ "$1" = repo -o "$1" = group ] || die_error "list_packages \$1 must be repo or group. not $1!"
111 | [ "$1" = repo ] && $PACMAN_TARGET -Sl $2
112 | [ "$1" = group ] && $PACMAN_TARGET -Sg $2
113 | }
114 |
115 | # find out the group to which one or more packages belong
116 | # arguments: packages
117 | # output format: multiple lines, each line like:
118 | #
119 | # order is the same as the input
120 | which_group ()
121 | {
122 | PACKAGE_GROUPS=`LANG=C $PACMAN_TARGET -Si "$@" | awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }'`
123 | }
124 |
125 | # get group and packagedesc for packages
126 | # arguments: packages
127 | # output format: multiple lines, each line like:
128 | #
129 | # order is the same as the input
130 | # note that space is used as separator, but desc is the only thing that will contain spaces.
131 | pkginfo ()
132 | {
133 | PACKAGE_INFO=`LANG=C $PACMAN_TARGET -Si "$@" | awk '/^Name/{ printf("%s ",$3) } /^Version/{ printf("%s ",$3) } /^Group/{ printf("%s", $3) } /^Description/{ for(i=3;i<=NF;++i) printf(" %s",$i); printf ("\n")}' | awk '!x[$1]++'`
134 | }
135 |
136 | # $1 target/runtime
137 | configure_mirrorlist () {
138 | local file
139 | [ "$1" != runtime -a "$1" != target ] && die_error "configure_mirrorlist needs target/runtime argument"
140 | # add installer-selected mirror to the top of the mirrorlist, unless it's already at the top. previously added mirrors are kept (a bit lower), you never know..
141 | [ "$1" = 'runtime' ] && file="$var_MIRRORLIST"
142 | [ "$1" = 'target' ] && file="${var_TARGET_DIR}/$var_MIRRORLIST"
143 | if [ -n "$MIRROR" ]; then
144 | if ! grep "^Server =" -m 1 "$file" | grep -q "$MIRROR"
145 | then
146 | debug 'PACMAN PROCEDURE' "Adding choosen mirror ($MIRROR) to $file"
147 | mirrorlist=`awk "BEGIN { printf(\"# Mirror selected during installation\nServer = "$MIRROR"\n\n\") } 1 " "$file"` || return $?
148 | echo "$mirrorlist" > "$file" || return $?
149 | fi
150 | fi
151 | return 0
152 | }
153 |
154 |
--------------------------------------------------------------------------------
/src/core/libs/lib-software.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TMP_MKINITCPIO_LOG=$LOG_DIR/mkinitcpio.log
4 | TMP_PACMAN_LOG=$LOG_DIR/pacman.log
5 |
6 | # runs mkinitcpio on the target system, displays output
7 | # $1 preset name. default: linux
8 | target_run_mkinitcpio()
9 | {
10 | local preset=${1:-linux}
11 | target_special_fs on
12 |
13 | run_controlled mkinitcpio "chroot $var_TARGET_DIR mkinitcpio -p $preset" $TMP_MKINITCPIO_LOG "Rebuilding initcpio images ..."
14 |
15 | target_special_fs off
16 |
17 | # alert the user to fatal errors
18 | [ $CONTROLLED_EXIT -ne 0 ] && show_warning "MKINITCPIO FAILED - SYSTEM MAY NOT BOOT" "$TMP_MKINITCPIO_LOG" text
19 | return $CONTROLLED_EXIT
20 | }
21 |
22 |
23 | # perform package installation to the target system
24 | installpkg() {
25 | ALL_PACKAGES=
26 | [ -n "$var_TARGET_GROUPS" ] && ALL_PACKAGES=`list_packages group "$var_TARGET_GROUPS" | awk '{print $2}'`
27 | if [ -n "$var_TARGET_PACKAGES_EXCLUDE" ]
28 | then
29 | for excl in $var_TARGET_PACKAGES_EXCLUDE
30 | do
31 | ALL_PACKAGES=${ALL_PACKAGES//$excl/}
32 | done
33 | fi
34 |
35 | if [ -n "$var_TARGET_PACKAGES" ]
36 | then
37 | [ -n "$ALL_PACKAGES" ] && ALL_PACKAGES="$ALL_PACKAGES $var_TARGET_PACKAGES"
38 | [ -z "$ALL_PACKAGES" ] && ALL_PACKAGES=$var_TARGET_PACKAGES
39 | fi
40 | ALL_PACKAGES=`echo $ALL_PACKAGES`
41 | [ -z "$ALL_PACKAGES" ] && die_error "No packages/groups specified to install"
42 |
43 | target_special_fs on
44 |
45 | notify "Package installation will begin now. You can watch the output in the progress window. Please be patient."
46 |
47 | run_controlled pacman_installpkg "$PACMAN_TARGET --noconfirm -S $ALL_PACKAGES" $TMP_PACMAN_LOG "Installing... Please Wait"
48 |
49 | local _result=''
50 | if [ $CONTROLLED_EXIT -ne 0 ]; then
51 | _result="Installation Failed (see errors below)"
52 | echo -e "\nPackage Installation FAILED." >>$TMP_PACMAN_LOG
53 | else
54 | _result="Installation Complete"
55 | echo -e "\nPackage Installation Complete." >>$TMP_PACMAN_LOG
56 | fi
57 |
58 | show_warning "$_result" "$TMP_PACMAN_LOG" text || return 1
59 |
60 | target_special_fs off
61 | sync
62 |
63 | return $CONTROLLED_EXIT
64 | }
65 |
66 |
67 | # enable glibc locales from rc.conf and build initial locale DB
68 | target_configure_initial_locale()
69 | {
70 | for i in $(grep "^LOCALE=" ${var_TARGET_DIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
71 | sed -i -e "s/^#$i/$i/g" ${var_TARGET_DIR}/etc/locale.gen
72 | done
73 | target_locale-gen
74 | }
75 |
76 |
77 | target_locale-gen ()
78 | {
79 | inform "Generating glibc base locales..."
80 | chroot ${var_TARGET_DIR} locale-gen >/dev/null
81 | }
82 |
83 | target_configure_initcpio () {
84 | local ret=0
85 | # Give initcpio the encrypt hook when / depends on an encrypted volume
86 | # (other encrypted volumes, not related to / don't need the encrypt hook, afaik)
87 | # If / also depends on lvm, this way the lvm2 hook will also be included in the right place
88 | if get_anchestors_mount ';/;'
89 | then
90 | hooks=`echo "$ANSWER_DEVICES" | cut -d ' ' -f2 | egrep 'lvm-lv|dm_crypt' | sed -e 's/lvm-lv/lvm2/' -e 's/dm_crypt/encrypt/' | tac`
91 | hooks=`echo $hooks` # $hooks is now a space separated, correctly ordered list of needed hooks
92 | if [ -n "$hooks" ]
93 | then
94 | # for each hook we're about to add, remove it first if it's already in
95 | for hook in $hooks
96 | do
97 | sed -i "/^HOOKS/ s/$hook //" ${var_TARGET_DIR}/etc/mkinitcpio.conf || ret=$?
98 | done
99 | # now add the correctly ordered string
100 | sed -i "/^HOOKS/ s/filesystems/$hooks filesystems/" ${var_TARGET_DIR}/etc/mkinitcpio.conf || ret=$?
101 | fi
102 | fi
103 | # The lvm2 hook however is needed for any lvm LV, no matter the involved mountpoints, so include it if we still need to
104 | if grep -q lvm-lv $TMP_BLOCKDEVICES && ! grep -q '^HOOKS.*lvm2' ${var_TARGET_DIR}/etc/mkinitcpio.conf
105 | then
106 | sed -i "/^HOOKS/ s/filesystems/lvm2 filesystems/" ${var_TARGET_DIR}/etc/mkinitcpio.conf || ret=$?
107 | fi
108 |
109 | # if keymap/usbinput are not in mkinitcpio.conf, but encrypt is, we should probably add it
110 | if line=`grep '^HOOKS.*encrypt' ${var_TARGET_DIR}/etc/mkinitcpio.conf`
111 | then
112 | if ! echo "$line" | grep -q keymap
113 | then
114 | sed -i '/^HOOKS/ s/encrypt/keymap encrypt/' ${var_TARGET_DIR}/etc/mkinitcpio.conf || ret=$?
115 | fi
116 | if ! echo "$line" | grep -q usbinput
117 | then
118 | sed -i '/^HOOKS/ s/keymap/usbinput keymap/' ${var_TARGET_DIR}/etc/mkinitcpio.conf || ret=$?
119 | fi
120 | fi
121 | return $ret
122 | }
123 |
--------------------------------------------------------------------------------
/src/core/libs/lib-ui.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Note that $var_UI_TYPE may not be set here. especially if being loaded in the "early bootstrap" phase
3 |
4 | source /usr/lib/libui.sh
5 |
6 | # mandatory to call me when you want to use me. call me again after setting $var_UI_TYPE
7 | ui_init ()
8 | {
9 | cats="MAIN PROCEDURE UI UI-INTERACTIVE FS MISC NETWORK PACMAN SOFTWARE"
10 | if [ "$LOG_TO_FILE" = '1' ]; then
11 | logs="$LOG $LOGFILE"
12 | else
13 | logs=$LOG
14 | fi
15 | if [ "$DEBUG" = '1' ]; then
16 | libui_sh_init "${var_UI_TYPE:-cli}" "$RUNTIME_DIR" "$logs" "$cats"
17 | else
18 | libui_sh_init "${var_UI_TYPE:-cli}" "$RUNTIME_DIR" "$logs"
19 | fi
20 |
21 | # get keymap/font (maybe configured by aif allready in another process or even in another shell)
22 | # otherwise, take default keymap and consolefont as configured in /etc/rc.conf. can be overridden
23 | # Note that the vars in /etc/rc.conf can also be empty!
24 | [ -e $RUNTIME_DIR/aif-keymap ] && var_KEYMAP=` cat $RUNTIME_DIR/aif-keymap`
25 | [ -e $RUNTIME_DIR/aif-consolefont ] && var_CONSOLEFONT=`cat $RUNTIME_DIR/aif-consolefont`
26 | [ -z "$var_KEYMAP" ] && source /etc/rc.conf && var_KEYMAP=$KEYMAP
27 | [ -z "$var_CONSOLEFONT" ] && source /etc/rc.conf && var_CONSOLEFONT=$CONSOLEFONT
28 | }
29 |
30 | # taken from setup
31 | printk()
32 | {
33 | case $1 in
34 | "on") echo 4 >/proc/sys/kernel/printk ;;
35 | "off") echo 0 >/proc/sys/kernel/printk ;;
36 | esac
37 | }
38 |
39 |
40 | # Get a list of available partionable blockdevices for use in ask_option
41 | # populates array $BLOCKFRIENDLY with elements like:
42 | # '/dev/sda' '/dev/sda 640133 MiB (640 GiB)'
43 | listblockfriendly()
44 | {
45 | BLOCKFRIENDLY=()
46 | for i in $(finddisks)
47 | do
48 | get_blockdevice_size $i MiB
49 | size_GiB=$(($BLOCKDEVICE_SIZE/2**10))
50 | BLOCKFRIENDLY+=($i "$i ${BLOCKDEVICE_SIZE} MiB ($size_GiB GiB)")
51 | done
52 | }
53 |
54 | # captitalize first character
55 | function capitalize () {
56 | sed 's/\([a-z]\)\([a-zA-Z0-9]*\)/\u\1\2/g';
57 | }
58 |
59 | set_keymap ()
60 | {
61 | KBDDIR="/usr/share/kbd"
62 |
63 | KEYMAPS=()
64 | local keymap
65 | for keymap in $(find $KBDDIR/keymaps -name "*.gz" | sort); do
66 | KEYMAPS+=("${keymap##$KBDDIR/keymaps/}" -)
67 | done
68 | ask_option "${var_KEYMAP:-no}" "Select a keymap" '' optional "${KEYMAPS[@]}"
69 | if [ -n "$ANSWER_OPTION" ]
70 | then
71 | loadkeys -q $KBDDIR/keymaps/$ANSWER_OPTION
72 | var_KEYMAP=$ANSWER_OPTION
73 | echo "$var_KEYMAP" > $RUNTIME_DIR/aif-keymap
74 | fi
75 |
76 | FONTS=()
77 | local font
78 | for font in $(find $KBDDIR/consolefonts -maxdepth 1 -name "*.gz" | sed 's|^.*/||g' | sort); do
79 | FONTS+=("$font" -)
80 | done
81 | ask_option "${var_CONSOLEFONT:-no}" "Select a console font" '' optional "${FONTS[@]}"
82 | if [ -n "$ANSWER_OPTION" ]
83 | then
84 | var_CONSOLEFONT=$ANSWER_OPTION
85 | local i
86 | for i in 1 2 3 4
87 | do
88 | if [ -d /dev/vc ]; then
89 | setfont $KBDDIR/consolefonts/$var_CONSOLEFONT -C /dev/vc/$i
90 | else
91 | setfont $KBDDIR/consolefonts/$var_CONSOLEFONT -C /dev/tty$i
92 | fi
93 | done
94 | echo "$var_CONSOLEFONT" > $RUNTIME_DIR/aif-consolefont
95 | fi
96 | }
97 |
98 | # $1 "topic"
99 | # shift 1; "$@" list of failed things
100 | warn_failed () {
101 | local topic=$1
102 | shift
103 | if [ -n "$1" ]
104 | then
105 | local list_failed=
106 | while [ -n "$1" ]
107 | do
108 | [ -n "$list_failed" ] && list_failed="$list_failed, "
109 | list_failed="${list_failed}$1"
110 | shift
111 | done
112 | show_warning "Preconfigure failed" "Beware: the following steps failed: $list_failed. Please report this. Continue at your own risk"
113 | fi
114 | return 0
115 | }
116 |
117 | # $1 basedir. default: empty
118 | ask_mkinitcpio_preset () {
119 | local basedir=$1
120 | presets=($(for i in $(ls -1 $basedir/etc/mkinitcpio.d/*.preset | grep -v example\.preset); do basename $i .preset; echo '-'; done))
121 | num_presets=$((${#presets[@]}/2))
122 | if [[ $num_presets -lt 1 ]]; then
123 | die_error "Not a single mkinitcpio preset found in $basedir/etc/mkinitcpio.d/ ? No kernel installed? WTF?"
124 | elif [[ $num_presets -eq 1 ]]; then
125 | # this is the most likely case: the user just installed 1 kernel..
126 | echo ${presets[0]}
127 | else
128 | ask_option 'no' "Build initcpio for which preset/kernel?" '' '' "${presets[@]}"
129 | echo $ANSWER_OPTION
130 | fi
131 | return 0
132 | }
133 |
134 | # $1 default option, or 'no' for none
135 | # $1 name of the filesystem (or partition/device) to ask for
136 | ask_mountpoint () {
137 | local default=$1
138 | local part=$2
139 | local opts=(/ 'root' /boot 'files for booting' /home 'home directories' /var 'variable files' /tmp 'temporary files' custom 'enter a custom mountpoint')
140 | ask_option $default "Select the mountpoint" "Select a mountpoint for $part" required "${opts[@]}" || return 1
141 | if [ "$ANSWER_OPTION" == custom ]; then
142 | [ "$default" == 'no' ] && default=
143 | ask_string "Enter the custom mountpoint for $part" "$default" || return 1
144 | echo $ANSWER_STRING
145 | else
146 | echo $ANSWER_OPTION
147 | fi
148 | }
149 |
--------------------------------------------------------------------------------
/src/core/procedures/automatic:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This is a procedure for automatic deployment/installation/configuration of systems.
3 | # check /usr/share/aif/examples for some example config files.
4 | # This procedure can easily replace the old quickinst script if you look at the "generic install" config file
5 | # Look at the base procedure to see the phases and which workers they'll execute.
6 | # It should be:
7 | # phase_preparation=(configure intro sysprep select_source runtime_network runtime_repositories runtime_packages)
8 | # phase_basics=(set_clock prepare_disks)
9 | # phase_system=(package_list install_packages configure_system install_bootloader)
10 | # phase_finish=(msg_report)
11 |
12 | # In theory, the only manual thing should maybe be configuring the runtime network and putting the configfile in place
13 | # I don't know if you can do non-interactive dm_crypt stuff.. maybe by pulling luks keyfiles from svn/git/..?
14 | # TODO: implement setting hostname, keymap, consolefont, network settings, root pass, etc
15 | # for a list of recognized variables, see examples/generic-install-on-sda
16 |
17 | depend_procedure core base # important, don't be confused when worker/variable definitions seem to be missing here.
18 |
19 | var_OPTS_STRING="c:"
20 | var_ARGS_USAGE="-c : Specify a configfile (profile) to be used"
21 | var_AUTOMATIC_PROFILE=""
22 | # TODO: if the user does aif -p automatic -c, then $1 is ":-" ??? if you do -c then it's ok.
23 | process_args ()
24 | {
25 | if [ "$1" = '-c' ]
26 | then
27 | [ -z "$2" ] && die_error "You must specify a config"
28 | var_AUTOMATIC_PROFILE=$2
29 | else
30 | usage
31 | exit 5
32 | fi
33 | }
34 |
35 |
36 | worker_intro ()
37 | {
38 | notify "Automatic procedure running profile $var_AUTOMATIC_PROFILE ...\n$DISCLAIMER"
39 | }
40 |
41 |
42 | worker_configure ()
43 | {
44 | var_UI_TYPE=${arg_ui_type:-cli}
45 | ui_init
46 | [ -z "$var_AUTOMATIC_PROFILE" ] && die_error "You must specify a config file to use this procedure"
47 | source $var_AUTOMATIC_PROFILE || die_error "Could not source config $var_AUTOMATIC_PROFILE"
48 | # Check mandatory options
49 | [ -z "$PARTITIONS" ] && die_error "You did not specify a partition scheme"
50 | [ -z "$BLOCKDATA" ] && die_error "You did not specify a partition scheme"
51 | [ -z "$TARGET_REPOSITORIES" ] && die_error "You did not specify \$TARGET_REPOSITORIES"
52 | # initialize internal variables based on variables set by the user (some of the vars are handled in other workers):
53 | var_RUNTIME_REPOSITORIES=$RUNTIME_REPOSITORIES
54 | var_RUNTIME_PACKAGES=$RUNTIME_PACKAGES
55 | var_PARTITIONS=$PARTITIONS
56 | var_BLOCKDATA=$BLOCKDATA
57 | HARDWARECLOCK=${HARDWARECLOCK:-localtime}
58 | TIMEZONE=${TIMEZONE:-Canada/Pacific}
59 | }
60 |
61 | worker_select_source ()
62 | {
63 | true # TARGET_REPOSITORIES, MIRROR is already sourced from config
64 | }
65 |
66 | worker_prepare_disks ()
67 | {
68 | get_possible_fs
69 | echo "$var_PARTITIONS" > $TMP_PARTITIONS
70 | echo "$var_BLOCKDATA" > $TMP_BLOCKDEVICES
71 | process_disks || die_error "Could not process_disks"
72 | if ! process_filesystems
73 | then
74 | show_warning 'Disk processing' "Could not process_filesystems"
75 | txt='also failed to execute properly'
76 | rollback_filesystems && txt='ended successfully'
77 | die_error "Something failed while processing the filesystem. A rollback was executed, which $txt"
78 | fi
79 | inform "Partitions and filesystems made successfully"
80 |
81 | # TODO: fstab? auto-add to fstab with libs? auto mkdir's on target_dir?
82 | }
83 |
84 | worker_package_list ()
85 | {
86 | var_TARGET_PACKAGES="$TARGET_PACKAGES syslinux"
87 | var_TARGET_GROUPS=$TARGET_GROUPS
88 | var_TARGET_PACKAGES_EXCLUDE=$TARGET_PACKAGES_EXCLUDE
89 | [ -z "$var_TARGET_PACKAGES" -a -z "$var_TARGET_GROUPS" ] && var_TARGET_GROUPS=base
90 | true
91 | }
92 |
93 |
94 | worker_install_packages ()
95 | {
96 | target_prepare_pacman && installpkg
97 | }
98 |
99 |
100 | worker_set_clock ()
101 | {
102 | # uses $TIMEZONE, clock itself remains untouched.
103 | copy_timezone_file
104 | }
105 |
106 |
107 | worker_install_bootloader ()
108 | {
109 | syslinux-install_update -iam -c "$var_TARGET_DIR" || return 1
110 | }
111 |
--------------------------------------------------------------------------------
/src/core/procedures/base:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # this procedure is meant to be inherited from
4 | var_DEFAULTFS="/boot:32:ext2:+ swap:256:swap /:7500:ext3 /home:*:ext3"
5 | var_TARGET_DIR="/mnt" # When overriding this, do _not_ add a trailing /. It's not needed and maybe you could even break something
6 | var_RUNTIME_REPOSITORIES= # array like this ('name1' 'location of repo 1' ['name2' 'location of repo2',..])
7 | var_RUNTIME_PACKAGES=
8 | 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
9 | var_MIRRORLIST="/etc/pacman.d/mirrorlist"
10 | var_UI_TYPE="cli" # set to cli or dia for dialog
11 | 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..
12 | [ -z "$var_ARCH" ] && die_error "Could not determine your architecture"
13 | syslinuxmenu="$var_TARGET_DIR$syslinuxmenu"
14 |
15 | ###### Phases ( can be overridden by more specific procedures) ######
16 | phase_preparation=(\
17 | configure \
18 | intro \
19 | sysprep \
20 | select_source \
21 | runtime_network \
22 | runtime_repositories \
23 | runtime_packages)
24 |
25 | phase_basics=(\
26 | set_clock \
27 | prepare_disks)
28 |
29 | phase_system=(\
30 | package_list \
31 | install_packages \
32 | configure_system \
33 | install_bootloader)
34 |
35 | phase_finish=(msg_report)
36 |
37 |
38 |
39 | ###### Workers ( can be overridden by more specific procedures) ######
40 | worker_intro ()
41 | {
42 | ask_yesno "This is a low-interactivity 'common defaults' installation, not meant for direct invocation. Do you really want to do this? We may overwrite your data."
43 | if [ $? -gt 0 ]
44 | then
45 | die_error "User aborted base profile execution"
46 | fi
47 | true
48 | }
49 |
50 |
51 | worker_sysprep ()
52 | {
53 | mount -o remount,rw / &>/dev/null
54 | }
55 |
56 |
57 | worker_configure ()
58 | {
59 | var_UI_TYPE=${arg_ui_type:-cli}
60 | ui_init
61 | }
62 |
63 |
64 | # this function must set TARGET_REPOSITORIES, which should contain at least 1
65 | # core repo If you want to use a network mirror, $MIRROR should be
66 | # set, we will populate the needed mirrorlists after select_source. although
67 | # you can also use a remote repository directly without using a mirrorlist but
68 | # either way you should set $MIRROR so that we can know when networking is
69 | # needed, we do this in a few places in the code.
70 | worker_select_source ()
71 | {
72 | true
73 | }
74 |
75 |
76 | worker_runtime_network ()
77 | {
78 | #override if needed
79 | true
80 | }
81 |
82 |
83 | worker_runtime_repositories ()
84 | {
85 | for i in `seq 0 $((${#var_RUNTIME_REPOSITORIES[@]}/2-1))`
86 | do
87 | repo=${var_RUNTIME_REPOSITORIES[$(($i*2))]}
88 | location=${var_RUNTIME_REPOSITORIES[$(($i*2+1))]}
89 | if ! list_pacman_repos runtime | grep -q $repo
90 | then
91 | add_pacman_repo runtime $repo "$location" || return 1
92 | fi
93 | done
94 | return 0
95 | }
96 |
97 |
98 | worker_runtime_packages ()
99 | {
100 | if [ -n "$var_RUNTIME_PACKAGES" ]
101 | then
102 | $PACMAN -Sy --noconfirm --needed $var_RUNTIME_PACKAGES
103 | fi
104 | }
105 |
106 |
107 | worker_set_clock ()
108 | {
109 | local default=no
110 | local timezone_file_copied=0
111 | while true; do
112 | ask_option $default "Date/time configuration" '' required \
113 | "1" "Select region and timezone" \
114 | "2" "Set time and date" \
115 | "3" "Return to Main Menu" || return 1
116 | case $ANSWER_OPTION in
117 | "1") execute worker interactive_timezone && copy_timezone_file && timezone_file_copied=1 && default=2 || return 1 ;;
118 | "2") if check_depend worker interactive_timezone
119 | then
120 | execute worker interactive_time && default=3 || return 1
121 | fi ;;
122 | "3") break ;;
123 | esac
124 | done
125 | [ $timezone_file_copied -eq 1 ] || copy_timezone_file || return 1
126 | return 0
127 | }
128 |
129 |
130 | worker_interactive_timezone ()
131 | {
132 | interactive_timezone
133 | }
134 |
135 |
136 | worker_interactive_time ()
137 | {
138 | interactive_time
139 | }
140 |
141 |
142 | worker_prepare_disks ()
143 | {
144 | partition && get_possible_fs
145 | # in official installer: autoprepare or diy first partitions, then mountpoints
146 | }
147 |
148 |
149 | # Put the list of packages to be installed in $var_TARGET_PACKAGES and $var_TARGET_GROUPS
150 | worker_package_list ()
151 | {
152 | var_TARGET_GROUPS=base
153 | }
154 |
155 |
156 | worker_install_packages ()
157 | {
158 | target_prepare_pacman && installpkg
159 | }
160 |
161 | worker_configure_system ()
162 | {
163 | preconfigure_target && postconfigure_target
164 | }
165 |
166 |
167 | worker_install_bootloader ()
168 | {
169 | true
170 | }
171 |
172 | worker_msg_report ()
173 | {
174 | show_report
175 | }
176 |
--------------------------------------------------------------------------------
/src/core/procedures/interactive:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | depend_procedure core base # esp for auto_network, intro and set_clock workers
3 |
4 |
5 | # This is a port of the original /arch/setup script. It doesn't use aif phases but uses it's own menu-based flow (phase) control
6 |
7 | BLOCK_ROLLBACK_USELESS=1
8 |
9 | # clock
10 | HARDWARECLOCK=
11 | TIMEZONE=
12 |
13 | # default filesystem specs (the + is bootable flag)
14 | # ::[:+]
15 | DEFAULTFS="/boot:32:ext2:+ swap:256:swap /:7500:ext3 /home:*:ext3"
16 |
17 | # this is a workaround for bash <4.2, where associative arrays are inherently local
18 | # once we have 4.2 we can just declare this array global. eval $settitles where needed
19 | settitles="declare -A workertitles
20 | workertitles['select_source']='Select source'
21 | workertitles['set_editor']='Set editor'
22 | workertitles['runtime_network']='Setup network'
23 | workertitles['set_clock']='Set clock'
24 | workertitles['prepare_disks']='Prepare hard drive(s)'
25 | workertitles['package_list']='Select packages'
26 | workertitles['install_packages']='Install packages'
27 | workertitles['configure_system']='Configure system'
28 | workertitles['install_bootloader']='Install bootloader'
29 | workertitles['msg_report']='Exit Install'"
30 |
31 | menu_workers=(select_source set_editor set_clock prepare_disks package_list install_packages configure_system install_bootloader msg_report)
32 |
33 | start_process ()
34 | {
35 | #####################
36 | ## begin execution ##
37 |
38 | execute worker configure
39 | execute worker intro
40 | execute worker sysprep
41 |
42 | mainmenu
43 | }
44 |
45 |
46 | mainmenu()
47 | {
48 | local default=1
49 | while true
50 | do
51 | eval "$settitles"
52 | menu=()
53 | for i in ${!menu_workers[@]}
54 | do
55 | worker=${menu_workers[$i]}
56 | title=${workertitles[$worker]}
57 | let i+=1 # in menu, we count from 1 onwards, not from 0
58 | menu+=($i "$title")
59 | done
60 |
61 | ask_option $default "MAIN MENU" '' required "${menu[@]}"
62 | case $ANSWER_OPTION in
63 | "1") execute worker select_source && \
64 | execute worker runtime_packages && default=2 ;;
65 | "2") execute worker set_editor && default=3 ;;
66 | "3") execute worker set_clock && default=4 ;;
67 | "4") execute worker prepare_disks && default=5 ;;
68 | "5") check_depend worker prepare_disks && \
69 | check_depend worker select_source && execute worker package_list && default=6 ;;
70 | "6") check_depend worker package_list && \
71 | check_depend worker select_source && execute worker install_packages && default=7 ;;
72 | "7") check_depend worker install_packages && execute worker configure_system && default=8 ;;
73 | "8") check_depend worker configure_system && execute worker install_bootloader && default=9 ;;
74 | "9") execute worker msg_report ;;
75 | *) execute worker abort_installer;;
76 | esac
77 | done
78 | }
79 |
80 |
81 | worker_configure_system()
82 | {
83 | interactive_configure_system
84 | }
85 |
86 |
87 | worker_prepare_disks()
88 | {
89 | get_possible_fs && interactive_prepare_disks
90 | }
91 |
92 |
93 | worker_select_source ()
94 | {
95 | interactive_select_source || return $?
96 | if [ -n "$MIRROR" ]; then
97 | if ask_yesno "Make sure the network is ok before continuing the installer. ${workertitles['runtime_network']} now?"; then
98 | execute worker runtime_network || return $?
99 | fi
100 | fi
101 | return 0
102 | }
103 |
104 | worker_set_editor ()
105 | {
106 | seteditor force
107 | }
108 |
109 | worker_intro ()
110 | {
111 | notify "Welcome to the Arch Linux Installation program. The install\
112 | process is fairly straightforward, and you should run through the options in\
113 | the order they are presented. If you are unfamiliar with partitioning/making\
114 | filesystems, you may want to consult some documentation before continuing.\
115 | You can view all output from commands by viewing your VC7 console (ALT-F7).\
116 | ALT-F1 will bring you back here.\n\n$DISCLAIMER"
117 | }
118 |
119 |
120 | worker_configure ()
121 | {
122 | var_UI_TYPE=${arg_ui_type:-dia}
123 | ui_init
124 | }
125 |
126 |
127 | # select_packages()
128 | # prompts the user to select packages to install
129 | worker_package_list() {
130 | # if selection has been done before, warn about loss of input and let the user exit gracefully
131 | ended_ok worker package_list && ! ask_yesno "WARNING: Running this stage again will result in the loss of previous package selections.\n\nDo you wish to continue?" && return 0
132 |
133 | interactive_select_packages
134 | }
135 |
136 |
137 | worker_install_packages ()
138 | {
139 | installpkg
140 | }
141 |
142 |
143 | # Hand-hold through setting up networking
144 | worker_runtime_network() {
145 | interactive_runtime_network
146 | }
147 |
148 | worker_install_bootloader ()
149 | {
150 | interactive_install_bootloader
151 | }
152 |
153 | # override show_report because this procedure does not use phases, but it's own menu
154 | show_report ()
155 | {
156 | eval "$settitles"
157 | data="Execution Report:"
158 | data="$data\n-----------------"
159 | for worker in ${menu_workers[@]}
160 | do
161 | [ "$worker" = 'msg_report' ] && continue # this worker is the one calling show_report, we can't know our exitcode yet
162 | title=${workertitles[$worker]}
163 | exit_var=exit_worker_$worker
164 | local ret=${!exit_var}
165 | case "$ret" in
166 | "") data="$data\n > $title: Skipped";;
167 | "0") data="$data\n > $title: Success";;
168 | *) data="$data\n > $title: Failed";;
169 | esac
170 | done
171 | notify "$data\nIf the install finished successfully, you can type 'reboot' to restart the system." || return $?
172 | }
173 |
174 | worker_msg_report () {
175 | show_report && stop_installer
176 | }
177 |
178 | worker_abort_installer ()
179 | {
180 | local ret=0
181 | ask_yesno "Abort Installation?" || return
182 | maybe_interactive_rollback_filesystems || ret=$?
183 | stop_installer || ret=$?
184 | return $ret
185 | }
186 |
--------------------------------------------------------------------------------
/src/core/procedures/partial-configure-network:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | depend_procedure core interactive
3 |
4 | start_process ()
5 | {
6 | execute worker runtime_network
7 | }
--------------------------------------------------------------------------------
/src/core/procedures/partial-disks:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | depend_procedure core base
3 |
4 | var_OPTS_STRING="o:"
5 | var_ARGS_USAGE="-o process/rollback: Operation: process the blockdevice layer or roll it back?"
6 |
7 | process_args ()
8 | {
9 | if [ "$1" = '-o' ]
10 | then
11 | [ "$2" != process -a "$2" != rollback ] && die_error "You must specify 'process' or 'rollback'"
12 | OPERATION=$2
13 | else
14 | usage
15 | exit 5
16 | fi
17 | }
18 |
19 |
20 | start_process ()
21 | {
22 | [ -z "$OPERATION" ] && usage && exit 5
23 |
24 | if [ "$OPERATION" = process ]
25 | then
26 | process_disks
27 | process_filesystems
28 | elif [ "$OPERATION" = rollback ]
29 | then
30 | rollback_filesystems
31 | fi
32 | }
33 |
--------------------------------------------------------------------------------
/src/core/procedures/partial-keymap:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | start_process ()
4 | {
5 | var_UI_TYPE=dia
6 | ui_init
7 | set_keymap
8 | }
9 |
--------------------------------------------------------------------------------
/src/user/whatsthis.txt:
--------------------------------------------------------------------------------
1 | put user-specific modules here. should be empty in the 'official' version
--------------------------------------------------------------------------------
/tests/buildtime/test-check_is_in.sh:
--------------------------------------------------------------------------------
1 | basedir=$(dirname "`dirname $0`")
2 | source $basedir/src/core/libs/lib-ui.sh #dependency needed
3 | source $basedir/src/core/libs/lib-misc.sh
4 |
5 | vars=(A B C D E F)
6 | check_is_in C "${vars[@]}" && echo 'ok C was in there' || echo 'wtf'
7 | check_is_in AOEUAU "${vars[@]}" && echo wtf || echo 'ok it was not in there'
8 |
--------------------------------------------------------------------------------
/tests/buildtime/test-menus.sh:
--------------------------------------------------------------------------------
1 | basedir=$(dirname "`dirname $0`")
2 | source $basedir/src/core/libs/lib-ui.sh
3 | ANSWER="/tmp/aif-test-dialog-answer"
4 | for ui in dia cli
5 | do
6 | for type in required optional
7 | do
8 | for default in no tag-c
9 | do
10 | var_UI_TYPE=$ui
11 | 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
12 | notify "RETURN CODE: $?\nANSWER: $ANSWER_OPTION"
13 | done
14 | done
15 | done
16 |
--------------------------------------------------------------------------------
/tests/lib/framework-runtime:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | lib="/usr/share/aif/tests/lib"
3 | STATUS=0
4 |
5 | # $1 name of test
6 | # $2... other args
7 | function aiftest () {
8 | name=$1
9 | shift
10 | if [ ! -f $lib/test-$name ]
11 | then
12 | echo "NO SUCH TEST: $lib/test-$1" >&2
13 | return 2
14 | else
15 | $lib/test-$name "$@"
16 | local ret=$?
17 | fi
18 | if [ $ret -eq 0 ]
19 | then
20 | echo "$name $@ : OK"
21 | else
22 | echo "$name $@ : NOT OK ($ret)"
23 | fi
24 | [ $ret -gt $STATUS ] && STATUS=$ret
25 | }
26 |
27 | aiftest-done () {
28 | if [ $STATUS -eq 0 ]
29 | then
30 | echo 'ALL TESTS ENDED SUCCESSFULLY'
31 | exit 0
32 | else
33 | echo 'ONE OR MORE TESTS FAILED!' >&2
34 | exit $STATUS
35 | fi
36 | }
37 |
--------------------------------------------------------------------------------
/tests/lib/setup-file:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | for i in "$@"
3 | do
4 | touch $i/test_file
5 | done
6 |
--------------------------------------------------------------------------------
/tests/lib/test-file:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 filename
3 |
4 | [ -f "$1" ]
5 |
--------------------------------------------------------------------------------
/tests/lib/test-lvm-lv:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 VG
3 | # $2 LV
4 | # $2 SIZE eg '800.00 MB'
5 |
6 | lvdisplay | grep -A 5 "LV Name.*/dev/$1/$2" | grep -q available || exit 1
7 | lvdisplay | grep -A 7 "LV Name.*/dev/$1/$2"| grep -q 'LV Size.*'"$2" || exit 2
8 |
--------------------------------------------------------------------------------
/tests/lib/test-mount:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 mount output string
3 |
4 | mount | grep -q '/dev/cryptpool/crypthome on /home type xfs (rw)'
5 |
--------------------------------------------------------------------------------
/tests/lib/test-nofile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 filename
3 |
4 | [ ! -f "$1" ]
5 |
--------------------------------------------------------------------------------
/tests/lib/test-nopackage:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 packagename
3 |
4 | if pacman -Qi $1 &>/dev/null
5 | then
6 | exit 1
7 | else
8 | exit 0
9 | fi
10 |
--------------------------------------------------------------------------------
/tests/lib/test-ping:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # $1 iterations
3 | # $2 host
4 |
5 | ping -c $1 $2
6 |
--------------------------------------------------------------------------------
/tests/lib/test-swap:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | free -m | grep -q 'Swap:.*'$1'.*'
--------------------------------------------------------------------------------
/tests/runtime/automatic-dmcrypt-lvm-install-sda/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | aif -p automatic -c /usr/share/aif/tests/runtime/automatic-dmcrypt-lvm-install-sda/profile -d
--------------------------------------------------------------------------------
/tests/runtime/automatic-dmcrypt-lvm-install-sda/perform_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /usr/share/aif/tests/lib/framework-runtime
4 |
5 | aiftest swap 19
6 | aiftest lvm-lv mypool root '800.00 MB'
7 | aiftest mount '/dev/mypool/rootcrypt on / type xfs (rw)'
8 | for i in /etc/ / /root/ /home/ /var/
9 | do
10 | aiftest file "$i"test_file
11 | done
12 | aiftest file /usr/bin/ssh
13 | aiftest nofile /sbin/mkfs.reiserfs
14 | aiftest nopackage sudo
15 | aiftest ping 2 archlinux.org
16 |
17 | aiftest-done
18 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-dmcrypt-lvm-install-sda/profile:
--------------------------------------------------------------------------------
1 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
2 | RUNTIME_REPOSITORIES=(testing ftp://mir1.archlinuxfr.org/archlinux/testing/os/$var_ARCH)
3 | RUNTIME_PACKAGES=
4 |
5 | # packages to install
6 | TARGET_GROUPS=base
7 | TARGET_PACKAGES_EXCLUDE='reiserfsprogs'
8 | TARGET_PACKAGES='openssh aif e2fsprogs cryptsetup lvm2 xfsprogs'
9 |
10 | # These variables are mandatory
11 |
12 | PARTITIONS='/dev/sda 40:ext2:+ *:ext4'
13 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
14 | /dev/sda2 raw lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
15 | /dev/sda2+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;mypool;/dev/sda2
16 | /dev/mapper/mypool lvm-vg mypool lvm-lv;yes;no_mountpoint;target;no_opts;root;800M
17 | /dev/mapper/mypool-root lvm-lv no_label dm_crypt;yes;no_mountpoint;target;no_opts;mypool-rootcrypt;-c__aes-xts-plain__-y__-s__512
18 | /dev/mapper/mypool-rootcrypt dm_crypt no_label xfs;yes;/;target;no_opts;no_label;no_params'
19 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-dmcrypt-lvm-install-sda/setup_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for i in /etc/ / /root/ /home/ /var/
4 | do
5 | touch /mnt${i}test_file
6 | done
7 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-lvm-dmcrypt-install-sda/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | aif -p automatic -c /usr/share/aif/tests/runtime/automatic-lvm-dmcrypt-install-sda/profile -d
--------------------------------------------------------------------------------
/tests/runtime/automatic-lvm-dmcrypt-install-sda/perform_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /usr/share/aif/tests/lib/framework-runtime
4 |
5 | aiftest swap 19
6 | aiftest lvm-lv cryptpool cryptroot '800.00 MB'
7 | aiftest mount '/dev/cryptpool/cryptroot on / type xfs (rw)'
8 | aiftest mount '/dev/cryptpool/crypthome on /home type xfs (rw)'
9 | for i in /etc/ / /root/ /home/ /var/
10 | do
11 | aiftest file "$i"test_file
12 | done
13 | aiftest file /usr/bin/ssh
14 | aiftest nofile /sbin/mkfs.reiserfs
15 | aiftest nopackage sudo
16 | aiftest ping 2 archlinux.org
17 |
18 | aiftest-done
19 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-lvm-dmcrypt-install-sda/profile:
--------------------------------------------------------------------------------
1 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
2 | RUNTIME_REPOSITORIES=(testing ftp://mir1.archlinuxfr.org/archlinux/testing/os/$var_ARCH)
3 | RUNTIME_PACKAGES=
4 |
5 | # packages to install
6 | TARGET_GROUPS=base
7 | TARGET_PACKAGES_EXCLUDE='reiserfsprogs'
8 | TARGET_PACKAGES='openssh aif e2fsprogs cryptsetup lvm2 xfsprogs'
9 |
10 | # These variables are mandatory
11 |
12 | PARTITIONS='/dev/sda 40:ext2:+ *:ext4'
13 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
14 | /dev/sda2 raw no_label dm_crypt;yes;no_mountpoint;target;no_opts;sda2crypt;-c__aes-xts-plain__-y__-s__512
15 | /dev/mapper/sda2crypt dm_crypt no_label lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
16 | /dev/mapper/sda2crypt+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;cryptpool;/dev/mapper/sda2crypt
17 | /dev/mapper/cryptpool lvm-vg cryptpool lvm-lv;yes;no_mountpoint;target;no_opts;cryptswap;20M|lvm-lv;yes;no_mountpoint;target;no_opts;cryptroot;800M|lvm-lv;yes;no_mountpoint;target;no_opts;crypthome;50M
18 | /dev/mapper/cryptpool-cryptswap lvm-lv no-label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
19 | /dev/mapper/cryptpool-cryptroot lvm-lv no_label xfs;yes;/;target;no_opts;no_label;no_params
20 | /dev/mapper/cryptpool-crypthome lvm-lv no_label xfs;yes;/home;target;no_opts;no_label;no_params'
21 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-lvm-dmcrypt-install-sda/setup_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for i in /etc/ / /root/ /home/ /var/
4 | do
5 | touch /mnt${i}test_file
6 | done
7 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-reuse-fs-sda/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # sda1 boot, sda2 will be swap, sda3 /, sda4 which will contain the "existing filesystem of the user" with "important data" on it.
4 | sfdisk -D /dev/sda -uM << EOF
5 | ,50,,*
6 | ,20,S
7 | ,800,
8 | ,,
9 | EOF
10 | mke2fs -j /dev/sda4
11 | mkdir /tmp/aif-test-mount
12 | mount /dev/sda4 /tmp/aif-test-mount
13 | touch /tmp/aif-test-mount/important-userdata
14 | umount /tmp/aif-test-mount
15 | aif -p automatic -c /usr/share/aif/tests/runtime/automatic-reuse-fs-sda/profile -d
--------------------------------------------------------------------------------
/tests/runtime/automatic-reuse-fs-sda/perform_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /usr/share/aif/tests/lib/framework-runtime
4 |
5 | aiftest swap 48
6 | aiftest lvm-lv cryptpool cryptroot '800.00 MB'
7 | aiftest mount '/dev/sda3 on / type ext4 (rw)'
8 | aiftest mount '/dev/sda4 on /home type ext3 (rw)'
9 | for i in /etc/ / /root/ /home/ /var/
10 | do
11 | aiftest file "$i"test_file
12 | done
13 | aiftest file /home/important-userdata
14 | aiftest ping 2 archlinux.org
15 |
16 | aiftest-done
17 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-reuse-fs-sda/profile:
--------------------------------------------------------------------------------
1 | TARGET_PACKAGES='aif e2fsprogs'
2 | RUNTIME_REPOSITORIES=(testing ftp://mir1.archlinuxfr.org/archlinux/testing/os/$var_ARCH)
3 |
4 | # modify worker_prepare_disks: we don't want to repartition (process_disks). also we want to do a rollback + setup again
5 |
6 | worker_prepare_disks ()
7 | {
8 | echo "$var_BLOCKDATA" > $TMP_BLOCKDEVICES
9 | if process_filesystems
10 | then
11 | inform "disk processing ok"
12 | else
13 | show_warning 'disks processing' "PROCESSING FAILED"
14 | return 1
15 | fi
16 | if rollback_filesystems
17 | then
18 | inform "rollback ok"
19 | else
20 | show_warning 'disks rollback' "ROLLBACK FAILED"
21 | return 1
22 | fi
23 | if process_filesystems
24 | then
25 | inform "disk processing ok"
26 | else
27 | show_warning 'disk processing' "PROCESSING FAILED"
28 | return 1
29 | fi
30 | }
31 |
32 | PARTITIONS=this_wont_be_used
33 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
34 | /dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
35 | /dev/sda3 raw no_label ext4;yes;/;target;no_opts;no_label;no_params
36 | /dev/sda4 raw no_label ext3;no;/home;target;no_opts;no_label;no_params'
37 |
--------------------------------------------------------------------------------
/tests/runtime/automatic-reuse-fs-sda/setup_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for i in /etc/ / /root/ /home/ /var/
4 | do
5 | touch /mnt${i}test_file
6 | done
7 |
--------------------------------------------------------------------------------
/unofficial/dieter-desktop-a7n8x.automaticprofile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # An example config for the deployment procedure
3 |
4 | # Use var_* for "standard" variables recognized by the automatic procedure. these should work for everyone.
5 | # use all other variable names for your own stuff. (eg i use them to define some things needed to pull my stuff from svn.)
6 |
7 | # TODO: install ruby-gems too
8 | # TODO * dieter/automatic: wait for yaourt --config fix ( http://forums.archlinux.fr/post23171.html#23171 )
9 | # 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.
10 |
11 |
12 | # when checking out /etc, configs may be outdated (meant for older packages), and we have no pacnew/pacsave files. but this should not cause too much problems..
13 | var_RUNTIME_REPOSITORIES=(archlinuxfr http://repo.archlinux.fr/$var_ARCH)
14 | var_RUNTIME_PACKAGES="svn yaourt"
15 |
16 | DEPLOY_CLASS=desktop-a7n8x
17 | HOSTNAME=dieter-ws
18 | SVN_USERNAME=dieter
19 | SVN_PASSWORD=
20 | SVN_BASE=https://192.168.1.2/svn/repos
21 |
22 | var_PARTITIONS='/dev/sda 100:ext2:+ 2048:swap *:xfs'
23 | var_BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
24 | /dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
25 | /dev/sda3 raw no_label dm_crypt;yes;no_mountpoint;target;no_opts;sda3crypt;-c__aes-xts-plain__-y__-s__512
26 | /dev/mapper/sda3crypt dm_crypt no_label lvm-pv;yes;no_mountpoint;target;no_opts;no_label;no_params
27 | /dev/mapper/sda3crypt+ lvm-pv no_label lvm-vg;yes;no_mountpoint;target;no_opts;cryptpool;/dev/mapper/sda3crypt
28 | /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
29 | /dev/cryptpool/cryptroot lvm-lv no_label xfs;yes;/;target;no_opts;no_label;no_params
30 | /dev/cryptpool/crypthome lvm-lv no_label xfs;yes;/home;target;no_opts;no_label;no_params'
31 |
32 |
33 | TARGET_PACKAGES='openssh e2fsprogs cryptsetup lvm2 xfsprogs'
34 |
35 | 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...
36 | phase_system+=(configure_home)
37 |
38 |
39 | # Deprecated. I try to keep everything in 1 config file now. that's cooler.
40 | #worker_fetch_configs ()
41 | #{
42 | # $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"
43 | # $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"
44 | #}
45 |
46 |
47 |
48 | worker_package_list ()
49 | {
50 | $SVN export $SVN_BASE/ddm-configs/$DEPLOY_CLASS/trunk/package-list $var_PKG_FILE || die_error "Could not export package list!"
51 | # cat -> there are newlines in it -> var=`echo $var` -> not anymore :)
52 | TARGET_PACKAGES=`cat $var_PKG_FILE` && TARGET_PACKAGES=`echo $TARGET_PACKAGES` || die_error "Could not cat package list. THIS SHOULD NEVER HAPPEN."
53 | # Strip away all packages not known by pacman. To get all packages, you'll need to do that when the system is installed TODO: don't do this. WAITINGFOR: --config support in yaourt + 'list of md5s of trusted pkgbuilds' support in yaourt
54 | # NOTE: maybe chrooting could be an option too (to avoid --config support, but problem 2 stays)
55 | TARGET_PACKAGES=`$PACMAN_TARGET -Si $TARGET_PACKAGES 2>/dev/null | awk '/Name/ {print $3}'`
56 | TARGET_PACKAGES=`echo $TARGET_PACKAGES` #TODO: some stuff goes wrong here
57 | }
58 |
59 |
60 | worker_accept_ssl_cert ()
61 | {
62 | mkdir -p /root/.subversion/auth/svn.ssl.server
63 | cat > /root/.subversion/auth/svn.ssl.server/1123d3c8b27895efee3848cc779e526a << EOF
64 | K 10
65 | ascii_cert
66 | V 716
67 | MIICFTCCAX6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADBVMRswGQYDVQQKExJBcGFjaGUgSFRUUCBTZXJ2ZXIxIjAgBgNVBAsTGUZvciB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0wNjA3MjQxMjUwMzdaFw0wNzA3MjQxMjUwMzdaMEwxGzAZBgNVBAoTEkFwYWNoZSBIVFRQIFNlcnZlcjEZMBcGA1UECxMQVGVzdCBDZXJ0aWZpY2F0ZTESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDF5PB1NnUve2jkisDTGsxKC9qzpnl+eX8UIR/1s+yX2ZIPNnIryeqTc6sS3cBHz2/AufIr0xbpXkTa4V5Es5bXA7W1D7+ZzuFHjjyi4E2eqYVkhkv1sRL5TpAovfjAA+96iaFHp3yKYiuw/nWwQTSW9M1VrDEym4ODxyJOtNdgQQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABY0bnBf9tL1WMC1sLxB1eDXvs5qNY96mny+EKGAbyQROPaXwsRQB0HrAkuWfHzQlgIdD6AfGsd+YMcEuqSPzIz6t6mA45jl++WvI6we9t3eYChtdPD2xjgHti0aSiDyVLTJbXPnkdgzKvIjYZcXBwbmbQSrg0STO5m+cSYt3chx
68 | K 8
69 | failures
70 | V 2
71 | 14
72 | K 15
73 | svn:realmstring
74 | V 23
75 | https://192.168.1.2:443
76 | END
77 | EOF
78 | }
79 |
80 |
81 | worker_configure_home ()
82 | {
83 | #TODO checkout from svn
84 | true
85 | }
86 |
87 |
88 |
89 | # See http://wiki.archlinux.org/index.php/Yaourt
90 |
91 | # Not needed yet...
92 | #worker_install_packages () #pre_ / post_ callbacks would be useful here
93 | #{
94 | # PACMAN_BACKUP=$PACMAN
95 | # PACMAN_TARGET_BACKUP=$PACMAN_TARGET
96 | # PACMAN=${PACMAN//pacman/yaourt}
97 | # PACMAN_TARGET=${PACMAN_TARGET//pacman/yaourt}
98 |
99 | # target_prepare_pacman core
100 | # [ -z "$TARGET_PACKAGES" ] && die_error "No packages listed to be installed!"
101 | # installpkg
102 |
103 | # PACMAN=$PACMAN_BACKUP
104 | # PACMAN_TARGET=$PACMAN_TARGET_BACKUP
105 | #}
106 |
107 |
108 | worker_set_clock ()
109 | {
110 | #Not doing anything. hwclock is set already, configs are coming from svn anyway and we'll use ntp.
111 | true
112 | }
113 |
114 | worker_runtime_yaourt ()
115 | {
116 | _yaourt_replace_pacman
117 | }
118 |
--------------------------------------------------------------------------------
/unofficial/jdd-generic-install-sda-using-host-packages:
--------------------------------------------------------------------------------
1 | # this config explains the (all) available options.
2 | # the variables are optional and we define their defaults here (so you could omit the
3 | # definitions), unless otherwise specified.
4 |
5 | # Add all repositories you want to use here. Same style as for pacman.conf:
6 | # Local: file://...
7 | # Remote: something like ftp://ftp.belnet.be/mirror/archlinux.org/$repo/os/$arch
8 | # You should list both the name of the repo as well as the location, as separate
9 | # elements.
10 | # You can add multiple repositories and even mix remote and local ones.
11 | # The order they are in here, will be the order in pacman.conf
12 | # This is a mandatory variable, which should contain at least 1 core repository
13 | # This example will do the most sensible thing on both core and netinstall images:
14 | if [ -d /repo/core ]; then
15 | TARGET_REPOSITORIES=(core 'file:///repo/$repo/$arch')
16 | else
17 | MIRROR='ftp://mirrors.kernel.org/archlinux/$repo/os/$arch'
18 | TARGET_REPOSITORIES=(core 'http://10.0.2.2:15678/request/$repo/$arch')
19 | fi
20 |
21 | HARDWARECLOCK=localtime # UTC is the better option, but some OS'es don't support it (i.e. Windows)
22 | TIMEZONE=Canada/Pacific
23 | # Do you want to have additional pacman repositories or packages available at runtime (during installation)?
24 | # RUNTIME_REPOSITORIES same format as TARGET_REPOSITORIES
25 | RUNTIME_REPOSITORIES=
26 | # space separated list
27 | RUNTIME_PACKAGES=
28 |
29 | # packages to install
30 | TARGET_GROUPS=base # all packages in this group will be installed (defaults to base if no group and no packages are specified)
31 | TARGET_PACKAGES_EXCLUDE= # Exclude these packages if they are member of one of the groups in TARGET_GROUPS. example: 'nano reiserfsprogs' (they are in base)
32 | TARGET_PACKAGES='openssh e2fsprogs' # you can also specify separate packages to install (this is empty by default)
33 |
34 | # you can optionally also override some functions...
35 | # This way you can change/extend/remove pretty much all functionality in AIF !
36 | worker_intro () {
37 | inform "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"
38 | sleep 10
39 | }
40 |
41 | worker_configure_system () {
42 | preconfigure_target
43 | sed -i 's/^HOSTNAME="myhost"/HOSTNAME="arch-generic-install"/' $var_TARGET_DIR/etc/rc.conf
44 | postconfigure_target
45 | }
46 |
47 | PART_ACCESS= # can be set to 'uuid', 'dev', 'label', or leave empty for 'dev'
48 |
49 | # These variables are mandatory
50 |
51 | # '*' means all the remaining space
52 | # '+' means the bootable flag
53 | PARTITIONS='/dev/sda 100:ext2:+ 512:swap *:ext4'
54 | # if you wanted everything other than swap and boot on an extended partition, you can do like this:
55 | # PARTITIONS='/dev/sda 100:ext2:+ 512:swap :extended *:ext4'
56 |
57 | BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
58 | /dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
59 | /dev/sda3 raw no_label ext4;yes;/;target;no_opts;no_label;no_params'
60 |
--------------------------------------------------------------------------------
/unofficial/modules/dieter/procedures/dieter-automatic:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Dieters personal procedure, adds a bit on top of the official automatic procedure.
3 | # TODO: implement this.
4 |
5 | depend_procedure core automatic
6 |
7 |
8 | # Check if we have all needed settings loaded from the profile
9 | worker_runtime_settings () #TODO: add to a phase
10 | {
11 | if check_is_in svn $var_RUNTIME_PACKAGES
12 | then
13 | [ -z "$SVN_USERNAME" ] && ask_string "Please enter your svn username" && SVN_USERNAME=$ANSWER_STRING
14 | [ -z "$SVN_PASSWORD" ] && ask_password svn #TODO: if user entered incorrect password, the install process will just fail..
15 | [ -z "$SVN_BASE" ] && ask_string "What's the base path of your svn repo? (no ending /) " && SVN_BASE=$ANSWER_STRING
16 | [ -z "$DEPLOY_CLASS" ] && ask_string "Which hostclass are you installing? (optional)" '' 0 && DEPLOY_CLASS=$ANSWER_STRING
17 | SVN="svn --username $SVN_USERNAME --password $SVN_PASSWORD"
18 | elif check_is_in moo $var_RUNTIME_PACKAGES
19 | then
20 | # Maybe more stuff later
21 | true
22 | fi
23 | [ -z "$HOSTNAME" ] && ask_string "Hostname of target system?" &&
24 | HOSTNAME=$ANSWER_STRING
25 |
26 | return 0
27 | }
28 |
--------------------------------------------------------------------------------