Setting tag Mom-2.3-2
[mom.git] / pl_mop.sh
1 #!/bin/bash
2 #
3 # Runs once a day to "fix" nodes in various ways
4 #
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2005 The Trustees of Princeton University
7 #
8 # $Id$
9 #
10
11 PATH=/sbin:/usr/sbin:$PATH
12
13 # Parse PLC configuration
14 if [ -r /etc/planetlab/plc_config ] ; then
15     . /etc/planetlab/plc_config
16 else
17     PLC_SLICE_PREFIX="pl"
18 fi
19
20 PIDFILE=/var/run/pl_mop.pid
21
22 # Record PID
23 if [ -f $PIDFILE ] ; then
24     if kill -0 `cat $PIDFILE` >/dev/null 2>&1 ; then
25         logger -p info -t pl_mom "$0 (`cat $PIDFILE`) already running"
26         exit 1
27     fi
28 fi
29 echo $$ > $PIDFILE
30
31 # Clean up stale lock files
32 trap "rm -f $PIDFILE" EXIT
33
34 # Run a command and log its output to syslog
35 run() {
36     eval $* 2>&1 | logger -p info -t "pl_mom: $1"
37 }
38
39 # OpenSSH server 3.8 and above refuse login for "locked"
40 # accounts. Replace "!!" with "*" in /etc/shadow for all VServer
41 # accounts.
42 fix_etc_shadow() {
43     echo "* Fixing /etc/shadow"
44
45     shopt -s nullglob
46     for file in /etc/vservers/*.conf pl_admin.conf site_admin.conf ; do
47         slice=$(basename ${file%*.conf})
48         if grep -q "$slice:\!\!" /etc/shadow ; then
49             sed -i -e "s/$slice:\!\!:\(.*\)/$slice:*:\1/" /etc/shadow
50         fi
51     done
52 }
53
54 # keep essential services running
55 restart_services() {
56     for service in sshd pl_sshd swapmon nm fprobe-ulog codemux; do
57         chkconfig --list $service | grep -q 3:on || continue
58         echo "* Checking $service"
59         status=$(service $service status)
60         if [ $? -ne 0 ] || echo $status 2>&1 | grep -q stopped ; then
61             echo "* Restarting $service"
62             service $service start
63         fi
64     done
65 }
66
67 # kill all the processes running in slice contexts
68 vkillall() {
69     vps -A | awk '(int($2) > 1) { system("vkill -c " $2 " -s 9 " $1); }'
70     # unmounts all the /proc and /dev/pts mounts in each vserver
71     tries=10
72     while grep -q /vservers/ /proc/mounts && [ $tries -gt 0 ] ; do
73         tries=$(($tries -1))
74         awk '(/vservers\//) { sub(/\\040.*$/, ""); print "Unmounting " $2; system("umount " $2); }' /proc/mounts
75     done
76 }   
77
78 # /vservers gets re-mounted read-only by the kernel if an ext3 journal
79 # transaction aborts
80 fix_vservers() {
81     echo "* Fixing /vservers"
82
83     # test to see if /vservers is mounted read-only
84     mkdir -p /vservers/.vtmp
85     tmp=$(mktemp /vservers/.vtmp/fixit.XXXXXX)
86     if [ $? -eq 0 ] ; then
87         rm -f $tmp
88         return 0
89     fi
90
91     # kill all processes running in slice contexts
92     vkillall
93
94     # stop vcached
95     pidfile=/var/run/vcached.pid
96     if [ -r "$pidfile" ] ; then
97         kill $(cat $pidfile)
98     fi
99     touch $pidfile
100
101     # unmounts /vservers
102     if umount /vservers ; then
103         # install expect if necessary
104         if ! rpm -q expect ; then
105             yum -y install expect
106         fi
107
108         # tell expect to hit the 'y' key every time fsck asks
109         expect -c 'set timeout 3600; spawn fsck /dev/mapper/planetlab-vservers; expect "<y>?" { send "y\r"; exp_continue }'
110
111         # blow away the vserver cache
112         rm -rf /vservers/.vcache/*
113
114         # XXX re-mount /vservers
115         # mount /vservers
116
117         # shutdown instead to avoid clearing disk quotas
118         shutdown -r now "/vservers filesystem repaired, rebooting"
119     else
120         echo "Unable to unmount /vservers!" >&2
121     fi
122
123     # allow vcached to run again
124     rm -f $pidfile
125 }
126
127 kill_duplicate_ssh() {
128     echo "* Killing stale duplicate SSH instances"
129
130     # count the number of SSH instances started by each slice
131     ps -C sshd -o command= |
132     grep " \[priv\]" |
133     sort | uniq -c |
134     while read instances sshd slice priv ; do
135     # kill all old instances
136     if [ $instances -gt 10 ] ; then
137         ps -C sshd -o pid=,start_time=,command= |
138         grep "$slice \[priv\]" |
139         while read pid start_time command ; do
140             start_time=$(date -d "$start_time" +%s)
141             min=$(date -d "6 hours ago" +%s)
142             if [ $start_time -lt $min ] ; then
143                 echo "* Killing $slice sshd pid $pid"
144                 kill -9 $pid
145             fi
146         done
147     fi
148     done
149 }
150
151 kill_nm_inslice(){
152     pids=$(vps aux | awk '$1 != "root" && $14 == "/usr/share/NodeManager/nm.py" {print $2}')
153     for pid in $pids ; do
154         line=$(vps aux | grep $pid)
155         echo NM found in slice. Killing PID $pid
156         echo $line
157         vkill -9 $pid
158     done
159 }
160
161 kill_nonroot_nm(){
162     # For whatever reason, Some NM's, after fork and chcontext...don't chcontext.  Kill them.
163     pids=$(ps aux | awk '$1 != "root" && $12 == "/usr/share/NodeManager/nm.py" {print $2}')
164     for pid in $pids ; do
165         line=$(ps aux | grep $pid)
166         echo NM found not belonging to root. Killing PID $pid
167         echo $line
168         kill -9 $pid
169     done
170 }
171
172 kill_multi_nm(){
173     # if there is more than one nm running around, kill them, then nm restart
174     pids=$(ps aux | awk '$1 == "root" && $12 == "/usr/share/NodeManager/nm.py" {print $2}')
175     i=0
176     for pid in $pids ; do
177         i=$[$i+1]
178     done
179     if [ $i -gt 1 ] ; then
180         # stop nm
181         echo "More than 1 NM found belonging to root.  Restarting NM."
182         /etc/init.d/nm stop 
183         pids=$(ps aux | awk '$1 == "root" && $12 == "/usr/share/NodeManager/nm.py" {print $2}')
184         for pid in $pids ; do
185             kill -9 $pid
186         done
187         /etc/init.d/nm start
188     fi
189 }
190 # XXX kill zombie slices
191
192 run restart_services
193
194
195 run kill_nonroot_nm
196
197 run kill_nm_inslice
198
199 run kill_multi_nm
200
201 run fix_vservers
202
203 run fix_etc_shadow
204
205 run kill_duplicate_ssh