/[gli]/trunk/src/GLIClientController.py
Gentoo

Contents of /trunk/src/GLIClientController.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1172 - (show annotations) (download) (as text)
Sun Dec 18 23:25:00 2005 UTC (13 years ago) by agaffney
File MIME type: text/x-python
File size: 15646 byte(s)
  src/GLIClientController.py:
  change ordering of statements in CC run() while loop to not go past the end
  of the array

1 """
2 # Copyright 1999-2005 Gentoo Foundation
3 # This source code is distributed under the terms of version 2 of the GNU
4 # General Public License as published by the Free Software Foundation, a copy
5 # of which can be found in the main directory of this project.
6 Gentoo Linux Installer
7
8 $Id: GLIClientController.py,v 1.75 2005/12/18 23:25:00 agaffney Exp $
9 Copyright 2004 Gentoo Technologies Inc.
10
11 Steps (based on the ClientConfiguration):
12 1. Load any modules? (this may have to be done manually, using a shell - not implemented)
13 2. Set the root password (may need to generate one. GLIUtility.generate_random_password())
14 3. Add users? (not implemented yet)
15 4. Start ssh
16 5. Network setup
17 6. Start the ArchTemplate doing it's thing. - maybe.. this might get called from elsewhere
18
19 """
20
21 import os, GLIClientConfiguration, GLIInstallProfile, GLIUtility, GLILogger, sys, signal, Queue, GLIArchitectureTemplate, GLINotification, traceback
22 from GLIException import *
23 from threading import Thread, Event
24
25 # Global constants for notifications
26 NEXT_STEP_READY = 1
27 INSTALL_DONE = 2
28
29 TEMPLATE_DIR = 'templates'
30
31 ##
32 # This class provides an interface between the backend and frontend
33 class GLIClientController(Thread):
34
35 ##
36 # Initialization function for the GLIClientController class
37 # @param configuration=None GLIClientConfiguration object
38 # @param install_profile=None GLIInstallProfile object
39 # @param pretend=False Pretend mode. If pretending, no steps will actually be performed
40 def __init__(self,configuration=None,install_profile=None,pretend=False):
41 Thread.__init__(self)
42
43 if configuration == None and os.path.isfile('/etc/gli.conf'):
44 self.output("Using /etc/gli.conf...")
45 configuration = GLIClientConfiguration.ClientConfiguration()
46 configuration.parse('/etc/gli.conf')
47
48 self.set_install_profile(install_profile)
49 self.set_configuration(configuration)
50 self._install_event = Event()
51 self._notification_queue = Queue.Queue(50)
52 self._install_mode = None
53 self._install_step = -1
54 self._install_steps = None
55 self._pretend = pretend
56 self.setDaemon(True)
57
58 ##
59 # Sets the GLIInstallProfile object
60 # @param install_profile GLIInstallProfile object
61 def set_install_profile(self, install_profile):
62 self._install_profile = install_profile
63
64 ##
65 # Returns the GLIInstallProfile object
66 def get_install_profile(self):
67 return self._install_profile
68
69 ##
70 # Sets the GLIClientConfiguration object
71 # @param configuration GLIClientConfiguration object
72 def set_configuration(self, configuration):
73 self._configuration = configuration
74 if self._configuration != None:
75 self._logger = GLILogger.Logger(self._configuration.get_log_file())
76
77 ##
78 # Returns the GLIClientConfiguration object
79 def get_configuration(self):
80 return self._configuration
81
82 ##
83 # This function runs as a second thread to do the actual installation (only used internally)
84 def run(self):
85 interactive = self._configuration.get_interactive()
86
87 if self._configuration == None and not interactive and not self._pretend:
88 print "You can not do a non-interactive install without a ClientConfiguration!"
89 sys.exit(1)
90
91 # Write client configuration profile to disk for debugging purposes
92 configuration = open("/tmp/clientconfiguration.xml", "w")
93 configuration.write(self._configuration.serialize())
94 configuration.close()
95
96 steps = [self.load_kernel_modules, self.set_proxys, self.set_root_passwd, self.configure_networking, self.enable_ssh, self.start_portmap]
97 # Do Pre-install client-specific things here.
98 while len(steps) > 0:
99 try:
100 step = steps.pop(0)
101 if not self._pretend:
102 step()
103 except GLIException, error:
104 if error.get_error_level() != 'fatal':
105 self._logger.log("Error: "+ error.get_function_name() + ": " + error.get_error_msg())
106 self.output("Non-fatal error... continuing...")
107 else:
108 raise error
109 self._logger.log("Completed pre_install steps")
110
111 # Wait for the self._install_event to be set before starting the installation.
112 # start_install() is called to pass here
113 self._install_event.wait()
114 self._install_event.clear()
115
116 if self._install_profile == None and not interactive:
117 print "You can not do a non-interactive install without an InstallProfile!"
118 sys.exit(1)
119
120 #self.output("Starting install now...")
121
122 templates = { 'x86': 'x86ArchitectureTemplate',
123 'sparc': 'sparcArchitectureTemplate',
124 'amd64': 'amd64ArchitectureTemplate',
125 'mips': 'mipsArchitectureTemplate',
126 'hppa': 'hppaArchitectureTemplate',
127 'alpha': 'alphaArchitectureTemplate',
128 'ppc': 'ppcArchitectureTemplate',
129 'ppc64': 'ppc64ArchitectureTemplate'
130 }
131
132 if self._configuration.get_architecture_template() not in templates.keys():
133 self.addNotification("exception", GLIException("UnsupportedArchitectureError", "fatal", "run", self._configuration.get_architecture_template() + ' is not supported by the Gentoo Linux Installer!'))
134
135 try:
136 template = __import__(TEMPLATE_DIR + '/' + templates[self._configuration.get_architecture_template()])
137 self._arch_template = getattr(template, templates[self._configuration.get_architecture_template()])(self._configuration, self._install_profile, self)
138 except ImportError:
139 self.addNotification("exception", GLIException("UnsupportedArchitectureError", 'fatal', 'run', 'The Gentoo Linux Installer could not import the install template for this architecture!'))
140 except AttributeError:
141 self.addNotification("exception", GLIException("UnsupportedArchitectureError", 'fatal', 'run', 'This architecture template was not defined properly!'))
142
143 self._install_mode = self._configuration.get_install_mode()
144 tmp_install_steps = self._arch_template.get_install_steps()
145 self._install_steps = [step for step in tmp_install_steps if self._install_mode in step['modes']]
146
147 if self._configuration.get_verbose(): self._logger.log("DEBUG: install_steps: " + str(self._install_steps))
148
149 self.addNotification("int", NEXT_STEP_READY)
150 # self._install_event.wait()
151
152 # Write install profile to disk for debugging purposes
153 configuration = open("/tmp/installprofile.xml", "w")
154 configuration.write(self._install_profile.serialize())
155 configuration.close()
156
157 while 1:
158 if self._install_step >= len(self._install_steps): break
159 if self._configuration.get_verbose(): self._logger.log("DEBUG: waiting at top of 'while' loop in CC in secondary thread...waiting to start step " + str(self._install_step+1) + ", " + self._install_steps[(self._install_step+1)]['name'])
160 self._install_event.wait()
161 if self._configuration.get_verbose(): self._logger.log("DEBUG: Event() cleared at top of 'while' loop in CC in secondary thread...starting step " + str(self._install_step) + ", " + self._install_steps[(self._install_step)]['name'])
162 # if self._install_step <= (len(self._install_steps) - 1):
163 try:
164 if not self._pretend:
165 self._install_steps[self._install_step]['function']()
166 self._install_event.clear()
167 if self.has_more_steps():
168 self.addNotification("int", NEXT_STEP_READY)
169 else:
170 self.addNotification("int", INSTALL_DONE)
171 except GLIException, error:
172 etype, value, tb = sys.exc_info()
173 s = traceback.format_exception(etype, value, tb)
174 self._logger.log("Exception received during '" + self._install_steps[self._install_step]['name'] + "': " + str(error))
175 for line in s:
176 line = line.strip()
177 self._logger.log(line)
178 self.addNotification("exception", error)
179 self._install_event.clear()
180 except Exception, error:
181 # Something very bad happened
182 etype, value, tb = sys.exc_info()
183 s = traceback.format_exception(etype, value, tb)
184 self._logger.log("This is a bad thing. An exception occured outside of the normal install errors. The error was: '" + str(error) + "'")
185 for line in s:
186 line = line.strip()
187 self._logger.log(line)
188 self.addNotification("exception", error)
189 self._install_event.clear()
190 # else:
191 # break
192
193 # This keeps the thread running until the FE exits
194 self._install_event.clear()
195 self._install_event.wait()
196
197 ##
198 # Returns the number of steps in the install process
199 def get_num_steps(self):
200 return len(self._install_steps)
201
202 ##
203 # Returns information about the next install step
204 def get_next_step_info(self):
205 return self._install_steps[(self._install_step + 1)]['name']
206
207 ##
208 # Performs the next install step
209 def next_step(self):
210 self._install_step = self._install_step + 1
211 if self._configuration.get_verbose(): self._logger.log("DEBUG: next_step(): setting Event() flag...starting step " + str(self._install_step) + ", " + self._install_steps[(self._install_step)]['name'])
212 self._install_event.set()
213
214 ##
215 # Retries the current install step
216 def retry_step(self):
217 self._install_event.set()
218
219 ##
220 # Returns True if there are more install steps remaining
221 def has_more_steps(self):
222 return (self._install_step < (len(self._install_steps) - 1))
223
224 ##
225 # Sets proxy information from the environment
226 def set_proxys(self):
227 if self._configuration.get_ftp_proxy() != "":
228 os.environ['ftp_proxy'] = self._configuration.get_ftp_proxy()
229
230 if self._configuration.get_http_proxy() != "":
231 os.environ['http_proxy'] = self._configuration.get_http_proxy()
232
233 if self._configuration.get_rsync_proxy() != "":
234 os.environ['RSYNC_PROXY'] = self._configuration.get_rsync_proxy()
235
236 ##
237 # Loads kernel modules specified in the GLIClientConfiguration object
238 def load_kernel_modules(self):
239 modules = self._configuration.get_kernel_modules()
240 for module in modules:
241 try:
242 ret = GLIUtility.spawn('modprobe ' + module)
243 if not GLIUtility.exitsuccess(ret):
244 self._logger.log("ERROR! : Could not load module: "+module)
245 # raise GLIException("KernelModuleError", 'warning', 'load_kernel_modules', 'Could not load module: ' + module)
246 else:
247 self._logger.log('kernel module: ' + module + ' loaded.')
248 except KernelModuleError, error:
249 self.output(error)
250 self._logger.log(error.get_error_level() + '! ' + error.get_error_msg())
251
252 ##
253 # Sets the root password specified in the GLIClientConfiguration object
254 def set_root_passwd(self):
255 self._logger.log("Setting root password.")
256 if self._configuration.get_root_passwd() != "":
257 # The password specified in the configuration is encrypted.
258 status = GLIUtility.spawn("echo 'root:" + self._configuration.get_root_passwd() + "' | chpasswd -e")
259
260 if not GLIUtility.exitsuccess(status):
261 self._logger.log("ERROR! : Could not set the root password on the livecd environment!")
262 # raise GLIException("PasswordError", 'warning', 'set_root_passwd', "Could not set the root password!")
263 else:
264 self._logger.log("Livecd root password set.")
265
266 ##
267 # Starts portmap if specified in the GLIClientConfiguration object
268 def start_portmap(self):
269 status = GLIUtility.spawn('/etc/init.d/portmap start') #, display_on_tty8=True)
270 if not GLIUtility.exitsuccess(status):
271 self._logger.log("ERROR! : Could not start the portmap service!")
272 # raise GLIException("PortmapError", 'warning', 'start_portmap', "Could not start the portmap service!")
273 else:
274 self._logger.log("Portmap started.")
275
276 ##
277 # Configures networking as specified in the GLIClientConfiguration object
278 def configure_networking(self):
279 # Do networking setup right here.
280 if self._configuration.get_network_type() != None:
281 type = self._configuration.get_network_type()
282 if type == "null":
283 # don't do anything, it's not our problem if the user specifies this.
284 return
285 if type == "dhcp":
286 # Run dhcpcd.
287 try:
288 interface = self._configuration.get_network_interface()
289 dhcp_options = self._configuration.get_network_dhcp_options()
290 except:
291 self._logger.log("No interface found.. defaulting to eth0.")
292 interface = "eth0"
293 dhcp_options = ""
294
295 if interface and not dhcp_options:
296 status = GLIUtility.spawn("/sbin/dhcpcd -n " + interface)
297 elif interface and dhcp_options:
298 status = GLIUtility.spawn("/sbin/dhcpcd " + dhcp_options + " " + interface)
299 else:
300 status = GLIUtility.spawn("/sbin/dhcpcd -n")
301
302 if not GLIUtility.exitsuccess(status):
303 raise GLIException("DHCPError", 'fatal', 'configure_networking', "Failed to get a dhcp address for " + interface + ".")
304
305 elif type == "manual" and self._configuration.get_interactive():
306 # Drop to bash shell and let them configure it themselves
307 print "Please configure & test your network device."
308 GLIUtility.spawn_bash()
309 elif type == "manual" and not self._interactive.get_interactive():
310 print "You cannot manually configure the network in non-interactive mode!"
311 print "Please fix either the network settings or the interactive mode!"
312 sys.exit(1)
313 elif type == "static":
314 # Configure the network from the settings they gave.
315 net_interface = self._configuration.get_network_interface()
316 net_ip = self._configuration.get_network_ip()
317 net_broadcast = self._configuration.get_network_broadcast()
318 net_netmask = self._configuration.get_network_netmask()
319 if not GLIUtility.set_ip(net_interface, net_ip, net_broadcast, net_netmask):
320 raise GLIException("SetIPError", 'fatal', 'configure_networking', "Could not set the IP address!")
321
322 route = self._configuration.get_network_gateway()
323 if not GLIUtility.set_default_route(route):
324 raise GLIException("DefaultRouteError", 'fatal','configure_networking', "Could not set the default route!")
325
326 ##
327 # Enables SSH if specified in the GLIClientConfiguration object
328 def enable_ssh(self):
329 if self._configuration.get_enable_ssh():
330 status = GLIUtility.spawn("/etc/init.d/sshd start")
331 if not GLIUtility.exitsuccess(status):
332 self._logger.log("ERROR! : Could not start the SSH daemon!")
333 # raise GLIException("SSHError", 'warning','enable_ssh',"Could not start SSH daemon!")
334 else:
335 self._logger.log("SSH Started.")
336
337
338
339 ##
340 # Loads the install profile
341 def load_install_profile(self):
342 install_profile=None
343 if self._install_profile == None:
344 if self._configuration != None:
345 success = GLIUtility.get_uri(self._configuration.get_profile_uri(),'/tmp/install_profile.xml')
346 if success:
347 self._logger.log("Profile downloaded succesfully, loading it now.")
348 self.output("Profile downloaded... loading it now...")
349 install_profile = GLIInstallProfile.InstallProfile()
350 install_profile.parse('/tmp/install_profile.xml')
351 else:
352 raise GLIException("InstallProfileError", 'fatal', 'get_install_profile', 'Could not download/copy the install profile from: ' + self._configuration.get_profile_uri())
353
354 self._install_profile = install_profile
355
356 ##
357 # Starts the install
358 def start_install(self):
359 self._install_event.set()
360
361 ##
362 # Starts the secondary thread running. The thread will wait to continue until start_install() is called
363 def start_pre_install(self):
364 self.start()
365
366 ##
367 # Cleans up after a failed install
368 def start_failure_cleanup(self):
369 self._arch_template.install_failed_cleanup()
370
371 ##
372 # Displays specified output
373 # @param str String to display
374 def output(self, str):
375 print str
376
377 ##
378 # Returns a notification object from the queue
379 def getNotification(self):
380 notification = None
381 try:
382 notification = self._notification_queue.get_nowait()
383 except:
384 pass
385 return notification
386
387 ##
388 # Adds a notification object to the queue
389 # @param type Notification type
390 # @param data Notification contents
391 def addNotification(self, type, data):
392 notification = GLINotification.GLINotification(type, data)
393 try:
394 self._notification_queue.put_nowait(notification)
395 except:
396 # This should only ever happen if the frontend is not checking for notifications
397 pass

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20