ec2_post_init
Populate STScI EC2 instances with ease
system.inc.sh
Go to the documentation of this file.
1## @file
2## @brief System functions
3
4(( $EC2PINIT_SYSTEM_INCLUDED )) && return
5EC2PINIT_SYSTEM_INCLUDED=1
6source ec2pinit.inc.sh
7
8_sys_user_old=''
9_sys_user_home_old=''
10
11## System uses DNF package manager
12export HAVE_DNF=0
13
14## System uses YUM package manager
15export HAVE_YUM=0
16
17## System uses APT package manager
18export HAVE_APT=0
19
20## System is based on Red Hat
22
23## System is based on Debian
25
26## System is based on Ubuntu
28
29## System is based on Arch
30export HAVE_ARCH=0
31
32## System is supported
34
35## @fn sys_check_admin()
36## @brief Determine if the current user is root
37## @retval true if root
38## @retval 1 if not root
40 if (( $EUID > 0 )); then
41 return 1
42 fi
43 return 0
44}
45
46## @fn sys_user_push()
47## @brief Lazily "become" another user
48## @details This sidesteps sudo's environment limitations allowing
49## one to execute scripts on behalf of the named user. Anything modified
50## while ``sys_user_push()`` is active will need to have its ownership and/or
51## octal permissions normalized. If ``name`` does not exist it will be created.
52## @param name the user to become
54 local name="$1"
55 local current="$(id -n -u)"
56 _sys_user_home_old=$(sys_user_home $current)
57 _sys_user_old=$current
58 HOME=$(sys_user_home $name)
59 if [ -z "$HOME" ]; then
60 useradd -m -s /bin/bash "$name"
61 HOME=/home/"$name"
62 fi
63 export USER=$name
64 pushd "$HOME"
65}
66
67## @fn sys_user_pop()
68## @brief Restore caller environment after ``sys_user_push()``
70 HOME="$_sys_user_home_old"
71 export USER="$_sys_user_old"
72 export _sys_user_home_old=''
73 export _sys_user_old=''
74 popd
75}
76
77## @fn sys_platform()
78## @brief Get system platform (``Linux``, ``Darwin``, etc)
79## @retval platform string
81 local result=$(uname -s)
82 case "$result" in
83 # placeholder - convert platform name to miniconda platform string
84 *)
85 ;;
86 esac
87 echo "$result"
88}
89
90## @fn sys_arch()
91## @brief Get system architecture (``i386``, ``x86_64``, etc)
92## @retval architecture string
94 local result=$(uname -m)
95 case "$result" in
96 # placeholder - convert cpu architecture name to miniconda architecture string
97 *) ;;
98 esac
99 echo "$result"
100}
101
102## @fn sys_user_home()
103## @brief Get account home directory
104## @details This function returns the home directory defined in /etc/passwd unless
105## ``name`` is the caller's account; in which case it will use the value of ``$HOME``.
106## @param user account to inspect
107## @retval home directory path
109 local user="${1:-$USER}"
110
111 if [ -z "$user" ]; then
112 user=$(id -n -u)
113 fi
114
115 # short circuit - if the user is the one we're logged in as, return its home variable
116 if [[ $(id -n -u) == "$user" ]]; then
117 echo "$HOME"
118 return
119 fi
120 getent passwd $user | awk -F: '{ print $6 }'
121}
122
123## @fn sys_reset_home_ownership()
124## @brief Resets ownership of a user (after ``sys_user_push()``/``sys_user_pop()``)
125## @param user account to modify
127 local home
128 local user="${1:-$USER}"
129
130 if [ -z "$user" ]; then
131 io_error "sys_reset_home_ownership: user name required"
132 return 1
133 fi
134
135 home="$(getent passwd $user | awk -F: '{ print $6 }')"
136 if [ -z "$home" ] || (( $(wc -l <<< "$home") > 1 )) ; then
137 io_error "sys_reset_home_ownership: reset failed"
138 return 1
139 fi
140
141 io_info "sys_reset_home_ownership: ${home} will be owned by ${user}"
142 chown -R "${user}": "${home}"
143}
144
145## @fn sys_pkg_get_manager()
146## @brief Get the system package manager
147## @retval result the path to the package manager
149 local managers=(
150 "dnf"
151 "yum"
152 "apt"
153 ""
154 )
155 local result="";
156 for manager in "${managers[@]}"; do
157 local tmp=$(type -p $manager)
158 if [ -x "$tmp" ]; then
159 result="$tmp"
160 break;
161 fi
162 done
163
164 echo "$result"
165}
166
167# Configure package manager globals
168sys_manager_cmd=$(sys_pkg_get_manager)
169case "$sys_manager_cmd" in
170 */dnf)
171 HAVE_DNF=1
173 sys_manager_cmd_install="dnf -y install"
174 sys_manager_cmd_update="dnf -y update"
175 sys_manager_cmd_clean="dnf clean all"
176 sys_manager_cmd_list="rpm -qa"
177 ;;
178 */yum)
179 HAVE_YUM=1
181 sys_manager_cmd_install="yum -y install"
182 sys_manager_cmd_update="yum -y update"
183 sys_manager_cmd_clean="yum clean all"
184 sys_manager_cmd_list="rpm -qa"
185 ;;
186 */apt)
187 HAVE_APT=1
188 DEBIAN_FRONTEND=noninteractive
189 sys_manager_cmd_install="apt update && apt -y install"
190 sys_manager_cmd_update="apt update && apt -y upgrade"
191 sys_manager_cmd_clean="apt -y autoremove && apt -y clean"
192 sys_manager_cmd_list="apt -qq list"
193 ;;
194 *)
196 ;;
197esac
198
199# Distro detection
200if (( HAVE_YUM )) || (( HAVE_DNF )); then
201 if [ -f "/etc/redhat-release" ]; then
203 fi
204elif (( HAVE_APT )); then
205 if [ -L "/etc/dpkg/origins/default" ]; then
206 if [ "$(basename $(readlink -f /etc/dpkg/origins/default))" == "debian" ]; then
208 elif [ "$(basename $(readlink -f /etc/dpkg/origins/default))" == "ubuntu" ]; then
210 fi
211 fi
212else
214fi
215
216if (( HAVE_SUPPORT )); then
217 io_info "system: Detected package manager: $sys_manager_cmd"
218 io_info "system: is based on Red Hat? $(( HAVE_REDHAT ))"
219 io_info "system: is based on Debian? $(( HAVE_DEBIAN ))"
220 io_info "system: is based on Ubuntu? $(( HAVE_UBUNTU ))"
221fi
222
223## @fn sys_pkg_install()
224## @brief Install a system package
225## @param ... a variable length list of packages to install
226## @retval 1 if not supported
227## @retval exit_code of system package manager
228##
229## @code{.sh}
230## # Install vim and nano
231## sys_pkg_install nano
232## if (( $HAVE_REDHAT )); then
233## sys_pkg_install vim
234## elif (( $HAVE_DEBIAN )); then
235## sys_pkg_install vim-common
236## fi
237##
238## # Alternative method using an array to dynamically set dependencies
239## deps=(nano)
240## (( $HAVE_REDHAT )) && deps+=(vim)
241## (( $HAVE_DEBIAN )) && deps+=(vim-common)
242## sys_pkg_install "${deps[@]}"
243## @endcode
245 if (( ! HAVE_SUPPORT )); then
246 io_error "sys_pkg_install: unsupported package manager"
247 return 1
248 fi
249 if (( "$#" < 1 )); then
250 io_error "sys_pkg_install: at least one package name is required"
251 return 1
252 fi
253 io_info "sys_pkg_install: Installing $*"
254 bash -c "$sys_manager_cmd_install $*"
255}
256
257## @fn sys_pkg_update_all()
258## @brief Update all system packages
259## @retval 1 if not supported
260## @retval exit_code of system package manager
262 if (( ! HAVE_SUPPORT )); then
263 io_error "sys_pkg_update_all: unsupported package manager"
264 return 1
265 fi
266 io_info "sys_pkg_update_all: Updating system packages"
267 bash -c "$sys_manager_cmd_update"
268}
269
270## @fn sys_pkg_installed()
271## @brief Test if a system package is installed
272## @param name of a system package
273## @retval 1 if not supported
274## @retval 1 if package is NOT installed
275## @retval 0 if package is installed
277 local output=''
278 local name="$1"
279 if (( ! HAVE_SUPPORT )); then
280 io_error "sys_pkg_installed: unsupported package manager"
281 return 1
282 fi
283
284 if (( "$#" < 1 )); then
285 io_error "sys_pkg_installed: package name is required"
286 return 1
287 fi
288
289 output="$($sys_manager_cmd_list $name | tail -n 1)"
290 if (( $HAVE_YUM )) || (( $HAVE_DNF )); then
291 if grep -E ''^$1\..*'' <<< "$output" &>/dev/null; then
292 return 0
293 fi
294 elif (( $HAVE_APT )); then
295 if grep -E ''^$1/.*\\[installed\\]$'' <<< "$output" &>/dev/null; then
296 return 0
297 fi
298 fi
299
300 return 1
301}
302
303## @fn sys_pkg_clean()
304## @brief Clean the system package manager's cache(s)
306 if (( ! HAVE_SUPPORT )); then
307 io_error "sys_pkg_clean: unsupported package manager"
308 return
309 fi
310 io_info "sys_pkg_clean: Clearing caches"
311 bash -c "$sys_manager_cmd_clean"
312}
313
314## @fn sys_initialize()
315## @brief Install dependencies required by ``ec2_post_init``
316## @retval exit_code value of ``sys_pkg_install()``
317##
318## @code{.sh}
319## if ! sys_pkg_initialize; then
320## io_error "Initialization failed!"
321## else
322## io_info "Initialization succeeded!"
323## fi
324## @endcode
326 local want=(
327 bash
328 git
329 curl
330 gcc
331 make
332 sudo
333 )
334 local need=()
335
336 # Handle barren Debian images
337 (( HAVE_DEBIAN )) && want+=(procps build-essential)
338
339 # NOTE: Aside from the sys_* functions most operations in ec2_post_init
340 # don't strictly require root access.
341 io_info "sys_initialize: Administrator check..."
342 if ! sys_check_admin; then
343 io_warn "sys_initialize: SYSTEM FUNCTIONS REQUIRE ROOT ACCESS!"
344 io_warn "sys_initialize: Beyond this point errors thrown by sys_* functions are NOT bugs!"
345 return
346 else
347 io_info "sys_initialize: User is root!"
348 fi
349
350 io_info "sys_initialize: Checking system requirements..."
351 for x in "${want[@]}"; do
352 if ! sys_pkg_installed "$x"; then
353 io_info "sys_initialize: $x marked for installation"
354 need+=($x)
355 fi
356 done
357 if (( ! ${#need[@]} )); then
358 io_info "sys_initialize: No additional packages required"
359 return 0
360 fi
361
362 io_info "sys_initialize: Installing packages required by ec2_post_init..."
363 sys_pkg_install ${need[@]}
364 return $?
365}
io_info(...)
Print a message.
Definition: io.inc.sh:29
io_error(...)
Print an error message.
Definition: io.inc.sh:59
sys_user_pop()
Restore caller environment after sys_user_push()
Definition: system.inc.sh:69
Exported String HAVE_UBUNTU
System is based on Ubuntu.
Definition: system.inc.sh:27
sys_pkg_install(...)
Install a system package.
Definition: system.inc.sh:244
sys_user_push(name)
Lazily "become" another user.
Definition: system.inc.sh:53
sys_reset_home_ownership(user)
Resets ownership of a user (after sys_user_push()/sys_user_pop())
Definition: system.inc.sh:126
sys_check_admin()
Determine if the current user is root.
Definition: system.inc.sh:39
sys_initialize()
Install dependencies required by ec2_post_init
Definition: system.inc.sh:325
Exported String HAVE_DNF
System uses DNF package manager.
Definition: system.inc.sh:12
Exported String HAVE_SUPPORT
System is supported.
Definition: system.inc.sh:33
sys_pkg_get_manager()
Get the system package manager.
Definition: system.inc.sh:148
Exported String HAVE_YUM
System uses YUM package manager.
Definition: system.inc.sh:15
Exported String HAVE_DEBIAN
System is based on Debian.
Definition: system.inc.sh:24
sys_arch()
Get system architecture (i386, x86_64, etc)
Definition: system.inc.sh:93
sys_user_home(user)
Get account home directory.
Definition: system.inc.sh:108
Exported String HAVE_APT
System uses APT package manager.
Definition: system.inc.sh:18
sys_pkg_installed(name)
Test if a system package is installed.
Definition: system.inc.sh:276
sys_pkg_clean()
Clean the system package manager's cache(s)
Definition: system.inc.sh:305
Exported String HAVE_ARCH
System is based on Arch.
Definition: system.inc.sh:30
sys_pkg_update_all()
Update all system packages.
Definition: system.inc.sh:261
sys_platform()
Get system platform (Linux, Darwin, etc)
Definition: system.inc.sh:80
Exported String HAVE_REDHAT
System is based on Red Hat.
Definition: system.inc.sh:21