svn:keywords
[bootmanager.git] / source / steps / UpdateNodeConfiguration.py
1 #!/usr/bin/python
2 #
3 # $Id$
4 # $URL$
5 #
6 # Copyright (c) 2003 Intel Corporation
7 # All rights reserved.
8 #
9 # Copyright (c) 2004-2006 The Trustees of Princeton University
10 # All rights reserved.
11
12
13 import os
14
15 from Exceptions import *
16 import utils
17
18
19 # if this file is present in the vservers /etc directory,
20 # the resolv.conf and hosts files will automatically be updated
21 # by the bootmanager
22 UPDATE_FILE_FLAG= "AUTO_UPDATE_NET_FILES"
23
24
25 def Run( vars, log ):
26     """
27     Reconfigure a node if necessary, including rewriting any network init
28     scripts based on what PLC has. Also, update any slivers on the machine
29     incase their network files are out of date (primarily /etc/hosts).
30
31     Also write out /etc/planetlab/session, a random string that gets
32     a new value at every request of BootGetNodeDetails (ie, every boot)
33
34     This step expects the root to be already mounted on SYSIMG_PATH.
35     
36     Except the following keys to be set:
37     SYSIMG_PATH              the path where the system image will be mounted
38                              (always starts with TEMP_PATH)
39     ROOT_MOUNTED             the node root file system is mounted
40     INTERFACE_SETTINGS  A dictionary of the values from the network
41                                 configuration file
42     """
43     
44     log.write( "\n\nStep: Updating node configuration.\n" )
45
46     # make sure we have the variables we need
47     try:
48         INTERFACE_SETTINGS= vars["INTERFACE_SETTINGS"]
49         if INTERFACE_SETTINGS == "":
50             raise ValueError, "INTERFACE_SETTINGS"
51
52         SYSIMG_PATH= vars["SYSIMG_PATH"]
53         if SYSIMG_PATH == "":
54             raise ValueError, "SYSIMG_PATH"
55
56         ROOT_MOUNTED= vars["ROOT_MOUNTED"]
57         if ROOT_MOUNTED == "":
58             raise ValueError, "ROOT_MOUNTED"
59
60     except KeyError, var:
61         raise BootManagerException, "Missing variable in vars: %s\n" % var
62     except ValueError, var:
63         raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
64
65     try:
66         ip= INTERFACE_SETTINGS['ip']
67         method= INTERFACE_SETTINGS['method']
68         hostname= INTERFACE_SETTINGS['hostname']
69         domainname= INTERFACE_SETTINGS['domainname']
70     except KeyError, var:
71         raise BootManagerException, \
72               "Missing network value %s in var INTERFACE_SETTINGS\n" % var
73
74     
75     if not ROOT_MOUNTED:
76         raise BootManagerException, "Root isn't mounted on SYSIMG_PATH\n"
77
78     log.write( "Updating vserver's /etc/hosts and /etc/resolv.conf files\n" )
79
80     # create a list of the full directory paths of all the vserver images that
81     # need to be updated.
82     update_path_list= []
83
84     for base_dir in ('/vservers','/vservers/.vref','/vservers/.vcache'):
85         try:
86             full_dir_path= "%s/%s" % (SYSIMG_PATH,base_dir)
87             slices= os.listdir( full_dir_path )
88
89             try:
90                 slices.remove("lost+found")
91             except ValueError, e:
92                 pass
93             
94             update_path_list= update_path_list + map(lambda x: \
95                                                      full_dir_path+"/"+x,
96                                                      slices)
97         except OSError, e:
98             continue
99
100
101     log.write( "Updating network configuration in:\n" )
102     if len(update_path_list) == 0:
103         log.write( "No vserver images found to update.\n" )
104     else:
105         for base_dir in update_path_list:
106             log.write( "%s\n" % base_dir )
107
108
109     # now, update /etc/hosts and /etc/resolv.conf in each dir if
110     # the update flag is there
111     for base_dir in update_path_list:
112         update_vserver_network_files(base_dir,vars,log)
113     
114     return
115
116
117
118 def update_vserver_network_files( vserver_dir, vars, log ):
119     """
120     Update the /etc/resolv.conf and /etc/hosts files in the specified
121     vserver directory. If the files do not exist, write them out. If they
122     do exist, rewrite them with new values if the file UPDATE_FILE_FLAG
123     exists it /etc. if this is called with the vserver-reference directory,
124     always update the network config files and create the UPDATE_FILE_FLAG.
125
126     This is currently called when setting up the initial vserver reference,
127     and later when nodes boot to update existing vserver images.
128
129     Expect the following variables from the store:
130     SYSIMG_PATH        the path where the system image will be mounted
131                        (always starts with TEMP_PATH)
132     INTERFACE_SETTINGS   A dictionary of the values from the network
133                        configuration file
134     """
135
136     try:
137         SYSIMG_PATH= vars["SYSIMG_PATH"]
138         if SYSIMG_PATH == "":
139             raise ValueError, "SYSIMG_PATH"
140
141         INTERFACE_SETTINGS= vars["INTERFACE_SETTINGS"]
142         if INTERFACE_SETTINGS == "":
143             raise ValueError, "INTERFACE_SETTINGS"
144
145     except KeyError, var:
146         raise BootManagerException, "Missing variable in vars: %s\n" % var
147     except ValueError, var:
148         raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
149
150     try:
151         ip= INTERFACE_SETTINGS['ip']
152         method= INTERFACE_SETTINGS['method']
153         hostname= INTERFACE_SETTINGS['hostname']
154         domainname= INTERFACE_SETTINGS['domainname']
155     except KeyError, var:
156         raise BootManagerException, \
157               "Missing network value %s in var INTERFACE_SETTINGS\n" % var
158
159     try:
160         os.listdir(vserver_dir)
161     except OSError:
162         log.write( "Directory %s does not exist to write network conf in.\n" %
163                    vserver_dir )
164         return
165
166     file_path= "%s/etc/%s" % (vserver_dir,UPDATE_FILE_FLAG)
167     update_files= 0
168     if os.access(file_path,os.F_OK):
169         update_files= 1
170
171         
172     if '/.vref/' in vserver_dir or \
173        '/.vcache/' in vserver_dir or \
174        '/vserver-reference' in vserver_dir:
175         log.write( "Forcing update on vserver reference directory:\n%s\n" %
176                    vserver_dir )
177         utils.sysexec_noerr( "echo '%s' > %s/etc/%s" %
178                              (UPDATE_FILE_FLAG,vserver_dir,UPDATE_FILE_FLAG),
179                              log )
180         update_files= 1
181         
182
183     if update_files:
184         log.write( "Updating network files in %s.\n" % vserver_dir )
185         try:
186             # NOTE: this works around a recurring problem on public pl,
187             # suspected to be due to mismatch between 2.6.12 bootcd and
188             # 2.6.22/f8 root environment.  files randomly show up with the
189             # immutible attribute set.  this clears it before trying to write
190             # the files below.
191             utils.sysexec( "chattr -i %s/etc/hosts" % vserver_dir )
192             utils.sysexec( "chattr -i %s/etc/resolv.conf" % vserver_dir )
193         except:
194             pass
195
196         
197         file_path= "%s/etc/hosts" % vserver_dir
198         hosts_file= file(file_path, "w" )
199         hosts_file.write( "127.0.0.1       localhost\n" )
200         if method == "static":
201             hosts_file.write( "%s %s.%s\n" % (ip, hostname, domainname) )
202         hosts_file.close()
203         hosts_file= None
204
205         file_path= "%s/etc/resolv.conf" % vserver_dir
206         if method == "dhcp":
207             # copy the resolv.conf from the boot cd env.
208             utils.sysexec( "cp /etc/resolv.conf %s/etc" % vserver_dir, log )
209         else:
210             # copy the generated resolv.conf from the system image, since
211             # we generated it via static settings
212             utils.sysexec( "cp %s/etc/resolv.conf %s/etc" % \
213                            (SYSIMG_PATH,vserver_dir), log )
214             
215     return