4 from random import Random
7 NODEUPDATE_PID_FILE= "/var/run/NodeUpdate.pid"
9 # variables for cron file creation
10 TARGET_SCRIPT = '(echo && date && echo && /usr/bin/NodeUpdate.py start) >>/var/log/NodeUpdate.log 2>&1'
11 TARGET_DESC = 'Update node RPMs periodically'
13 TARGET_SHELL = '/bin/bash'
14 CRON_FILE = '/etc/cron.d/NodeUpdate.cron'
16 YUM_PATH = "/usr/bin/yum"
20 RPM_GPG_PATH = "/etc/pki/rpm-gpg"
23 # location of file containing http/https proxy info, if needed
24 PROXY_FILE = '/etc/planetlab/http_proxy'
26 # this is the flag that indicates an update needs to restart
27 # the system to take effect. it is created by the rpm that requested
29 REBOOT_FLAG = '/etc/planetlab/update-reboot'
31 # location of directory containing boot server ssl certs
32 SSL_CERT_DIR='/mnt/cdrom/bootme/cacert/'
34 # file containing list of extra groups to attempt to update,
36 EXTRA_GROUPS_FILE= '/etc/planetlab/extra-node-groups'
38 # file containing a list of rpms that we should attempt to delete
39 # before we updating everything else. this list is not
40 # removed with 'yum remove', because that could accidently remove
41 # dependency rpms that were not intended to be deleted.
42 DELETE_RPM_LIST_FILE= '/etc/planetlab/delete-rpm-list'
45 # print out a message only if we are displaying output
51 # print out a message only if we are displaying output
56 # create an entry in /etc/cron.d so we run periodically.
57 # we will be run once a day at a 0-59 minute random offset
58 # into a 0-23 random hour
62 randomMinute= Random().randrange( 0, 59, 1 );
63 randomHour= Random().randrange( 0, 11, 1 );
65 f = open( CRON_FILE, 'w' );
66 f.write( "# %s\n" % (TARGET_DESC) );
67 f.write( "MAILTO=%s\n" % (TARGET_USER) );
68 f.write( "SHELL=%s\n" % (TARGET_SHELL) );
69 f.write( "%s %s,%s * * * %s %s\n\n" %
70 (randomMinute, randomHour, randomHour + 12, TARGET_USER, TARGET_SCRIPT) );
73 print( "Created new cron.d entry." )
75 print( "Unable to create cron.d entry." )
78 # simply remove the cron file we created
81 os.unlink( CRON_FILE )
82 print( "Deleted cron.d entry." )
84 print( "Unable to delete cron.d entry." )
90 def __init__( self, doReboot ):
92 os.environ['http_proxy']= self.HTTP_PROXY
93 os.environ['HTTP_PROXY']= self.HTTP_PROXY
95 self.doReboot= doReboot
99 def CheckProxy( self ):
100 Message( "Checking existance of proxy config file..." )
102 if os.access(PROXY_FILE, os.R_OK) and os.path.isfile(PROXY_FILE):
103 self.HTTP_PROXY= string.strip(file(PROXY_FILE,'r').readline())
104 Message( "Using proxy %s." % self.HTTP_PROXY )
107 Message( "Not using any proxy." )
111 def InstallKeys( self ):
112 Message( "\nRemoving any existing GPG signing keys from the RPM database" )
113 os.system( "%s --allmatches -e gpg-pubkey" % RPM_PATH )
115 Message( "\nInstalling all GPG signing keys in %s" % RPM_GPG_PATH )
116 os.system( "%s --import %s/*" % (RPM_PATH, RPM_GPG_PATH) )
119 def ClearRebootFlag( self ):
120 os.system( "/bin/rm -rf %s" % REBOOT_FLAG )
123 def CheckForUpdates( self ):
125 Message( "\nRemoving any existing reboot flags" )
126 self.ClearRebootFlag()
128 if self.doReboot == 0:
129 Message( "\nIgnoring any reboot flags set by RPMs" );
131 Message( "\nChecking if yum supports SSL certificate checks" )
132 if os.system( "%s --help | grep -q sslcertdir" % YUM_PATH ) == 0:
133 Message( "Yes, using --sslcertdir option" )
134 sslcertdir = "--sslcertdir=" + SSL_CERT_DIR
136 Message( "No, not using --sslcertdir option" )
139 Message( "\nUpdating PlanetLab group" )
140 os.system( "%s %s -y groupupdate \"PlanetLab\"" %
141 (YUM_PATH, sslcertdir) )
143 Message( "\nUpdating rest of system" )
144 os.system( "%s %s -y update" %
145 (YUM_PATH, sslcertdir) )
147 Message( "\nChecking for extra groups to update" )
148 if os.access(EXTRA_GROUPS_FILE, os.R_OK) and \
149 os.path.isfile(EXTRA_GROUPS_FILE):
150 extra_groups_contents= file(EXTRA_GROUPS_FILE).read()
151 extra_groups_contents= string.strip(extra_groups_contents)
152 if extra_groups_contents == "":
153 Message( "No extra groups found in file." )
155 for group in string.split(extra_groups_contents,"\n"):
156 Message( "\nUpdating %s group" % group )
157 os.system( "%s %s -y groupupdate \"%s\"" %
158 (YUM_PATH, sslcertdir, group) )
160 Message( "No extra groups file found" )
162 if os.access(REBOOT_FLAG, os.R_OK) and os.path.isfile(REBOOT_FLAG) and self.doReboot:
163 Message( "\nAt least one update requested the system be rebooted" )
164 self.ClearRebootFlag()
165 os.system( "/sbin/shutdown -r now" )
167 def RebuildRPMdb( self ):
168 Message( "\nRebuilding RPM Database." )
169 try: os.system( "rm /var/lib/rpm/__db.*" )
170 except Exception, err: print "RebuildRPMdb: %s" % err
171 try: os.system( "%s --rebuilddb" % RPM_PATH )
172 except Exception, err: print "RebuildRPMdb: %s" % err
174 def RemoveRPMS( self ):
176 Message( "\nLooking for RPMs to be deleted." )
177 if os.access(DELETE_RPM_LIST_FILE, os.R_OK) and \
178 os.path.isfile(DELETE_RPM_LIST_FILE):
179 rpm_list_contents= file(DELETE_RPM_LIST_FILE).read()
180 rpm_list_contents= string.strip(rpm_list_contents)
182 if rpm_list_contents == "":
183 Message( "No RPMs listed in file to delete." )
186 rpm_list= string.join(string.split(rpm_list_contents))
188 Message( "Deleting these RPMs:" )
189 Message( rpm_list_contents )
191 rc= os.system( "%s -ev %s" % (RPM_PATH, rpm_list) )
194 Error( "Unable to delete RPMs, continuing. rc=%d" % rc )
196 Message( "RPMs deleted successfully." )
199 Message( "No RPMs list file found." )
203 if __name__ == "__main__":
205 # if we are invoked with 'start', display the output. this
206 # is usefull for running something under cron and as a service
207 # (at startup), so the cron only outputs errors and doesn't
208 # generate mail when it works correctly
212 # if we hit an rpm that requests a reboot, do it if this is
213 # set to 1. can be turned off by adding noreboot to command line
218 if "start" in sys.argv:
221 if "noreboot" in sys.argv:
224 if "updatecron" in sys.argv:
225 # simply update the /etc/cron.d file for us, and exit
229 if "removecron" in sys.argv:
234 # see if we are already running by checking the existance
235 # of a PID file, and if it exists, attempting a test kill
236 # to see if the process really does exist. If both of these
239 if os.access(NODEUPDATE_PID_FILE, os.R_OK):
240 pid= string.strip(file(NODEUPDATE_PID_FILE).readline())
242 if os.system("/bin/kill -0 %s > /dev/null 2>&1" % pid) == 0:
243 Message( "It appears we are already running, exiting." )
246 # write out our process id
247 pidfile= file( NODEUPDATE_PID_FILE, 'w' )
248 pidfile.write( "%d\n" % os.getpid() )
252 nodeupdate= NodeUpdate(doReboot)
254 Error( "Unable to initialize." )
256 nodeupdate.RebuildRPMdb()
257 nodeupdate.RemoveRPMS()
258 nodeupdate.InstallKeys()
259 nodeupdate.CheckForUpdates()
260 Message( "\nUpdate complete." )
262 # remove the PID file
263 os.unlink( NODEUPDATE_PID_FILE )