15
15
# Description: A service to automatically install DKMS modules for new kernels.
18
#use LSB functions for logging on Debian/Ubuntu
18
test -f /usr/sbin/dkms || exit 0
20
#We only have these functions on debian/ubuntu
21
# so on other distros just stub them out
19
22
if [ -f /lib/lsb/init-functions ]; then
20
23
. /lib/lsb/init-functions
21
if [ -f /etc/debian_version ]; then
22
DEBIAN_STYLE_LOGGING="yes"
24
if [ ! -f /etc/debian_version ]; then
25
alias log_daemon_msg=echo
26
log_end_msg() { if [ "$1" = "0" ]; then echo " Done. "; else echo " Failed. "; fi }
27
alias log_action_begin_msg=log_daemon_msg
28
alias log_action_end_msg=log_end_msg
26
test -f /usr/sbin/dkms || exit 0
28
function invoke_command ()
31
35
local exitval_file=`mktemp /tmp/dkms.XXXXXX`
32
[ -z "$verbose" ] && echo -en "$2..." >>$output_loc || echo -e "$1" >>$output_loc
33
if [ "$3" == background ] && [ -z "$verbose" ]; then
34
(eval $1 >/dev/null 2>&1; echo "exitval=$?" >> "$exitval_file") &
35
while [ -e "$exitval_file" ] && ! [ -s "$exitval_file" ]; do
37
echo -en "." >>$output_loc
36
if [ "$3" = background ] && [ -z "$verbose" ]; then
37
(eval $1 >/dev/null 2>&1; echo "exitval=$?" >> "$exitval_file") &
38
while [ -e "$exitval_file" ] && ! [ -s "$exitval_file" ]; do
43
[ $exitval -gt 0 ] && echo -en "(bad exit status: $exitval)" >>$output_loc
45
[ $exitval -gt 0 ] && logger -t dkms_autoinstaller "(bad exit status: $exitval)"
44
46
rm -f "$exitval_file"
45
echo -en "\n" >>$output_loc
52
#$1 is the signal to emit (successful|failed)
53
#$2 is the module name in question
54
if [ -x /sbin/initctl ]; then
55
initctl emit build-$1 MODULE=$2 2>/dev/null
51
output_loc="/var/log/dkms_autoinstaller"
52
[ -n "$2" ] && kernel=$2 && output_loc="/dev/stdout" || kernel=`uname -r`
53
kernelver_rpm=`rpm -qf "/lib/modules/$kernel" 2>/dev/null | grep -v "not owned by any package" | grep kernel | head -1`
54
if ! arch=`rpm -q --queryformat "%{ARCH}" "$kernelver_rpm" 2>/dev/null`; then
55
[ `uname -m` == "x86_64" ] && [ `cat /proc/cpuinfo | grep -c "Intel"` -gt 0 ] && [ `ls $install_tree/$kernel/build/configs 2>/dev/null | grep -c "ia32e"` -gt 0 ] && arch="ia32e" || arch=`uname -m`
61
[ -n "$2" ] && kernel=$2 || kernel=${uname% *}
57
63
kernel_preparation_done=""
58
64
dkms_tree="/var/lib/dkms"
59
65
. /etc/dkms/framework.conf 2>/dev/null
61
67
# See how we were called.
64
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
65
log_daemon_msg "Running DKMS auto installation service for kernel $kernel"
70
log_daemon_msg "Running DKMS auto installation service for kernel $kernel"
72
# Iterate over the modules
73
for modulepath in $(find "$dkms_tree" -maxdepth 1 -mindepth 1 -type d); do
75
module_in_tree=${modulepath##*/}
76
# Determine which versions to show status for
80
already_installed_version=""
81
for versioned_path in $(find "$modulepath" -maxdepth 1 -mindepth 1 -type d -a -not -name original_module); do
82
version_count=$(($version_count + 1))
83
version_in_tree="${versioned_path##*/}"
85
if [ -f $versioned_path/source/dkms.conf ]; then
86
do_autoinstall=$(sed -n -e 's/^\(str *\)\?AUTOINSTALL=\(.*\)$/\2/gp;' $versioned_path/source/dkms.conf)
88
current_state="broken"
92
# Get the current state
93
# a mod can be both built and installed-weak (stupid, but could be)
94
# but installed-weak comes last, so use tail
95
current_state=`dkms status -m $module_in_tree -v $version_in_tree -k $kernel -a $arch 2>/dev/null | awk {'print $5'} | tail -n 1`
96
[ "$current_state" = "installed" -o "$current_state" = "installed-weak" ] && already_installed="true" && already_installed_version=$version_in_tree
99
log_action_begin_msg " $module_in_tree ($version_in_tree)"
101
# Based on what we know, either do it or not
102
if [ "$current_state" = "broken" ]; then
103
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): Unable to locate $versioned_path/source/dkms.conf"
104
logger -t dkms_autoinstaller " DKMS tree must be manually fixed"
107
elif [ -n "$already_installed" ]; then
108
emit_module_status successful $module_in_tree
110
elif [ -z "$do_autoinstall" ]; then
111
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): AUTOINSTALL not set in its dkms.conf."
113
elif [ -n "$do_autoinstall" ] && [ "$version_count" -gt 1 ]; then
114
logger -t dkms_autoinstaller "$module_in_tree: Multiple versions in DKMS. Unsure what to do. Resolve manually."
115
emit_module_status failed $module_in_tree
67
echo "Running DKMS auto installation service for kernel $kernel"
71
for filename in `ls "$dkms_tree"`; do
72
if [ -d "$dkms_tree/$filename" ] && ! [ -h "$dkms_tree/$filename" ]; then
73
modules_needing_status="$modules_needing_status $filename"
77
# Iterate over the modules
78
for module_in_tree in $modules_needing_status; do
80
# Make sure its in the tree
81
if [ -d "$dkms_tree/$module_in_tree" ]; then
83
# Determine which versions to show status for
87
already_installed_version=""
88
for filename in `ls "$dkms_tree/$module_in_tree"`; do
89
if [ -d "$dkms_tree/$module_in_tree/$filename" ] && ! [ -h "$dkms_tree/$module_in_tree/$filename" ] && [ "$filename" != "original_module" ]; then
90
version_count=$(($version_count + 1))
91
version_in_tree="$filename"
93
# Source in its dkms.conf to see if we should autoinstall
95
if [ -f $dkms_tree/$module_in_tree/$version_in_tree/source/dkms.conf ]; then
96
. $dkms_tree/$module_in_tree/$version_in_tree/source/dkms.conf
98
current_state="broken"
101
[ `echo "$AUTOINSTALL" | grep -ic "^y"` -gt 0 ] && do_autoinstall="yes"
103
# Get the current state
104
# a mod can be both built and installed-weak (stupid, but could be)
105
# but installed-weak comes last, so use tail
106
current_state=`dkms status -m $module_in_tree -v $version_in_tree -k $kernel -a $arch 2>/dev/null | awk {'print $5'} | tail -n 1`
107
[ "$current_state" == "installed" -o "$current_state" == "installed-weak" ] && already_installed="true" && already_installed_version=$version_in_tree
111
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
112
log_action_begin_msg " $module_in_tree ($version_in_tree)"
115
# Based on what we know, either do it or not
116
if [ "$current_state" = "broken" ]; then
117
echo "$module_in_tree ($version_in_tree): Unable to locate $dkms_tree/$module_in_tree/$version_in_tree/source/dkms.conf" >>$output_loc
118
echo -e "\tDKMS tree must be manually fixed." >>$output_loc
119
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
123
elif [ -n "$already_installed" ]; then
124
echo "$module_in_tree ($already_installed_version): Already installed on this kernel." >>$output_loc
125
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
128
elif [ -z "$do_autoinstall" ]; then
129
echo "$module_in_tree ($version_in_tree): AUTOINSTALL not set in its dkms.conf." >>$output_loc
130
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
133
elif [ -n "$do_autoinstall" ] && [ "$version_count" -gt 1 ]; then
134
echo "$module_in_tree: Multiple versions in DKMS. Unsure what to do. Resolve manually." >>$output_loc
135
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
139
echo "$module_in_tree ($version_in_tree): Installing module." >>$output_loc
140
if [ "$current_state" != "built" ] && ! [ -e /lib/modules/$kernel/build/include ]; then
141
echo " Kernel headers for $kernel are not installed. Cannot install this module." >>$output_loc
142
echo " Try installing linux-headers-$kernel or equivalent." >>$output_loc
144
elif [ "$current_state" != "built" ] && [ -e /lib/modules/$kernel/build/include ]; then
146
if [ -z "$kernel_preparation_done" ]; then
147
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q --no-clean-kernel >>$output_loc" "." background
149
kernel_preparation_done="true"
151
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch --no-prepare-kernel --no-clean-kernel -q >>$output_loc" "." background
154
if [ "$return_status" -eq 0 ]; then
155
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q >>$output_loc" "." background
156
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
162
echo " Build failed. Installation skipped." >>$output_loc
163
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
170
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q >>$output_loc" "." background
172
if [ "$return_status" -eq 101 ]; then
173
echo " A newer module version than this already exists in this kernel." >>$output_loc
174
echo " Skipping install... (you can manually install later with --force)" >>$output_loc
175
elif [ "$return_status" -ne 0 ]; then
176
echo " Installation failed!" >>$output_loc
182
if [ -z "$modules_needing_status" ]; then
183
if [ ! -z "$DEBIAN_STYLE_LOGGING" ]; then
118
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): Installing module on kernel $kernel."
119
if [ "$current_state" != "built" ] && ! [ -e /lib/modules/$kernel/build/include ]; then
120
logger -t dkms_autoinstaller " Kernel headers for $kernel are not installed. Cannot install this module."
121
logger -t dkms_autoinstaller " Try installing linux-headers-$kernel or equivalent."
123
elif [ "$current_state" != "built" ] && [ -e /lib/modules/$kernel/build/include ]; then
125
if [ -z "$kernel_preparation_done" ]; then
126
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q --no-clean-kernel" "." background
128
kernel_preparation_done="true"
130
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch --no-prepare-kernel --no-clean-kernel -q" "." background
133
if [ "$return_status" -eq 0 ]; then
134
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch" "." background
135
emit_module_status successful $module_in_tree
138
logger -t dkms_autoinstaller " Build failed. Installation skipped."
139
emit_module_status failed $module_in_tree
143
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q" "." background
145
if [ "$return_status" -eq 0 ]; then
146
emit_module_status successful $module_in_tree
147
elif [ "$return_status" -eq 101 ]; then
148
logger -t dkms_autoinstaller " A newer module version than this already exists in kernel."
149
logger -t dkms_autoinstaller " Skipping install... (you can manually install later with --force)"
150
emit_module_status successful $module_in_tree
151
elif [ "$return_status" -ne 0 ]; then
152
logger -t dkms_autoinstaller " Installation failed!"
153
emit_module_status failed $module_in_tree
158
if [ -z "$modules_needing_status" ]; then
162
stop|restart|force-reload|status|reload)
206
echo $"Usage: $0 {start|stop}"
166
echo "Usage: $0 {start}"