""" # Copyright 1999-2005 Gentoo Foundation # This source code is distributed under the terms of version 2 of the GNU # General Public License as published by the Free Software Foundation, a copy # of which can be found in the main directory of this project. Gentoo Linux Installer $Id: GLIClientController.py,v 1.84 2006/07/17 18:18:27 agaffney Exp $ Copyright 2004 Gentoo Technologies Inc. Steps (based on the ClientConfiguration): 1. Load any modules? (this may have to be done manually, using a shell - not implemented) 2. Set the root password (may need to generate one. GLIUtility.generate_random_password()) 3. Add users? (not implemented yet) 4. Start ssh 5. Network setup 6. Start the ArchTemplate doing it's thing. - maybe.. this might get called from elsewhere """ import os, sys, Queue, traceback, platform from threading import Thread, Event import GLILogger import GLINotification from GLIException import * # Global constants for notifications NEXT_STEP_READY = 1 TEMPLATE_DIR = 'templates' LOGFILE = '/var/log/install.log' ## # This class provides an interface between the backend and frontend class GLIClientController(Thread): ## # Initialization function for the GLIClientController class # @param install_profile=None GLIInstallProfile object # @param pretend=False Pretend mode. If pretending, no steps will actually be performed def __init__(self,install_profile=None,pretend=False,verbose=True): Thread.__init__(self) self.set_install_profile(install_profile) self._install_event = Event() self._notification_queue = Queue.Queue(50) self._next_install_step = "" self._install_steps = None self._verbose = verbose self._pretend = pretend self._thread_pid = 0 self.setDaemon(True) self._logger = GLILogger.Logger(LOGFILE) self._arch_template = None subarches = { 'i386': 'x86', 'i486': 'x86', 'i586': 'x86', 'i686': 'x86', 'x86_64': 'amd64', 'parisc': 'hppa' } self.arch = platform.machine() if self.arch in subarches: self.arch = subarches[self.arch] self.start() ## # Sets the GLIInstallProfile object # @param install_profile GLIInstallProfile object def set_install_profile(self, install_profile): self._install_profile = install_profile ## # Returns the GLIInstallProfile object def get_install_profile(self): return self._install_profile ## # Returns the architecture we're running on def get_arch(self): return self.arch ## # This function runs as a second thread to do the actual installation (only used internally) def run(self): self._thread_pid = os.getpid() if self._install_profile.get_verbose(): self._logger.log("DEBUG: secondary thread PID is " + str(self._thread_pid)) # Log installer version version_file = os.path.abspath(os.path.dirname(__file__)) + "/version-stamp" try: installer_version = open(version_file, "r").readline().strip() except: installer_version = "(unknown)" self._logger.log("Gentoo Linux Installer version " + installer_version) templates = { 'x86': 'x86ArchitectureTemplate', 'sparc': 'sparcArchitectureTemplate', 'amd64': 'amd64ArchitectureTemplate', 'mips': 'mipsArchitectureTemplate', 'hppa': 'hppaArchitectureTemplate', 'alpha': 'alphaArchitectureTemplate', 'ppc': 'ppcArchitectureTemplate', 'ppc64': 'ppc64ArchitectureTemplate' } if self._install_profile.get_verbose(): self._logger.log("DEBUG: arch is %s" % self.arch) if self.arch not in templates: self.addNotification("exception", GLIException("UnsupportedArchitectureError", "fatal", "run", self.arch + ' is not supported by the Gentoo Linux Installer!')) try: template = __import__(TEMPLATE_DIR + '/' + templates[self.arch]) self._arch_template = getattr(template, templates[self.arch])(self._install_profile, self) except ImportError: self.addNotification("exception", GLIException("UnsupportedArchitectureError", 'fatal', 'run', 'The Gentoo Linux Installer could not import the install template for this architecture!')) except AttributeError: self.addNotification("exception", GLIException("UnsupportedArchitectureError", 'fatal', 'run', 'This architecture template was not defined properly!')) self._install_steps = self._arch_template.get_install_steps() while 1: self._install_event.wait() try: if not self._pretend: func = getattr(self._arch_template, self._next_install_step) func() self._install_event.clear() self.addNotification("int", NEXT_STEP_READY) except GLIException, error: etype, value, tb = sys.exc_info() s = traceback.format_exception(etype, value, tb) self._logger.log("Exception received during '%s': %s" % (self._install_steps[self._next_install_step], str(error))) for line in s: line = line.strip() self._logger.log(line) self.addNotification("exception", error) self._install_event.clear() except Exception, error: # Something very bad happened etype, value, tb = sys.exc_info() s = traceback.format_exception(etype, value, tb) self._logger.log("This is a bad thing. An exception occured outside of the normal install errors. The error was: '%s'" % str(error)) for line in s: line = line.strip() self._logger.log(line) self.addNotification("exception", error) self._install_event.clear() # This keeps the thread running until the FE exits self._install_event.clear() self._install_event.wait() ## # Returns information about the next install step def get_step_info(self, step): return self._install_steps[step] ## # Performs the next install step def run_step(self, step): self._next_install_step = step if self._install_profile.get_verbose(): self._logger.log("DEBUG: next_step(): setting Event() flag...starting step %s, %s" % (self._next_install_step, self._install_steps[self._next_install_step])) self._install_event.set() ## # Returns a notification object from the queue def getNotification(self): notification = None try: notification = self._notification_queue.get_nowait() except: pass return notification ## # Adds a notification object to the queue # @param type Notification type # @param data Notification contents def addNotification(self, type, data): notification = GLINotification.GLINotification(type, data) try: self._notification_queue.put_nowait(notification) except: # This should only ever happen if the frontend is not checking for notifications pass