Changeset 28 for trunk/provisioner.py

Show
Ignore:
Timestamp:
26/11/07 20:14:17 (4 years ago)
Author:
daedalus
Message:

* Refactored code to permit more flexible templating of changes. You can now

define a <changetemplate/> in 95% the same way as a <change/>, and then
refer to a <changetemplate/> when defining a <change/> to allow you to
combine change templates as a change flow, using namespaces and iterators
for each one.

* Some work on manual bailout in authoritarian mode, but it isn't completely

bailing out immediately yet, due to some complexities in the deferred chains
that I haven't quite unravelled.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/provisioner.py

    r27 r28  
    5454        Back out a change that was applied to a specific device. 
    5555        """ 
     56 
     57class UserBailout(Exception): 
     58    """ 
     59    User denied a change command from executing in Authoritarian mode. 
     60    This causes the program to bail out complete at exactly that point. 
     61    """ 
    5662 
    5763class Provisioner: 
     
    6874        self.namespace = namespace 
    6975        self.authoritarian = authoritarian 
     76 
     77        log.debug("My namespace is: %s", self.namespace) 
    7078 
    7179    def parse_config_node(self, node): 
     
    148156 
    149157        log.error("Change '%s' failed to apply", change.name) 
    150         e = failure.check( ChangeConditionFailure ) 
     158        e = failure.check( ChangeConditionFailure, UserBailout ) 
    151159        if e: 
    152160            log.error("  failure was: %s", failure.value ) 
     161            if isinstance(e, UserBailout): 
     162                log.info("User bailout detected.") 
     163                return defer.succeed('bailout') 
    153164        else: 
    154165            tlog.err(failure) 
     
    504515            else: 
    505516                log.info(" Bailing out at your command.") 
    506                 self.waitingForCommand.errback("User requested manual bailout.") 
     517                raise UserBailout("Bailing out at your command") 
     518                #self.waitingForCommand.errback("User requested manual bailout.") 
    507519                return 
    508520            pass 
     
    572584        for (expr, cmdstring) in expectset: 
    573585 
    574             # Perform variable substitution on the command string 
    575             log.debug("determining commandstring from template: %s", cmdstring) 
    576             cmdstring = str(util.substituteVariables(cmdstring, namespace)) 
    577             log.debug("commandstring is: %s", cmdstring) 
    578  
    579             # add the cmdstring to the namespace 
    580             namespace['command.send'] = cmdstring 
    581  
    582             log.debug("Determining command base from template: %s", self.command) 
    583             command = str(util.substituteVariables(self.command, namespace)) 
    584  
     586            try: 
     587                # Perform variable substitution on the command string 
     588                log.debug("determining commandstring from template: %s", cmdstring) 
     589                cmdstring = str(util.substituteVariables(cmdstring, namespace)) 
     590                log.debug("commandstring is: %s", cmdstring) 
     591 
     592                # add the cmdstring to the namespace 
     593                namespace['command.send'] = cmdstring 
     594 
     595                log.debug("Determining command base from template: %s", self.command) 
     596                command = str(util.substituteVariables(self.command, namespace)) 
     597            except KeyError, e: 
     598                log.error("KeyError in commands: %s" % e) 
     599                self.all_commands_defer.errback( e ) 
     600                return self.all_commands_defer 
     601             
    585602            #log.debug("checking expr: %s" % expr) 
    586603            log.debug("cmdstring is: %s" % command) 
     
    605622        log.debug("spawning command...") 
    606623        self.waitingForCommand = defer.Deferred() 
     624 
    607625        # If we're in authoritarian mode, wait for confirmation 
    608626        # that we should execute the command. 
     
    617635                self.exitcode = -1 
    618636                self.cmdoutput = 'User requested manual bailout' 
    619                 self.waitingForCommand.errback( Exception("User requested manual bailout.") ) 
     637                log.critical("User requested manual bailout") 
     638                self.waitingForCommand.errback( UserBailout("User requested manual bailout.") ) 
    620639                return self.waitingForCommand 
    621640            pass 
     
    638657        self.cmdoutput += result[1] 
    639658        log.debug("current results: exit '%d', output: %s", self.exitcode, self.cmdoutput) 
    640         log.error("Process: %s", self.p) 
    641659         
    642660    def command_failed(self, failure): 
    643661        errorstr = "%s: %s" % (self.exitcode, self.cmdoutput) 
    644662        log.error("Command failed: %s", errorstr) 
    645         log.error("Process: %s", self.p) 
    646         self.exitcode = result[0] 
    647         self.cmdoutput += result[1] 
    648663        #self.all_commands_defer.errback( Exception(errorstr) ) 
    649664 
     
    704719                self.parent.waitingForCommand.callback( (self.exitCode, self.databuf) ) 
    705720                pass 
     721 
     722        except AlreadyCalled, AlreadyCancelled: 
     723            pass 
    706724                 
    707725        except Exception, e: 
     
    713731 
    714732    def timedOut(self): 
     733        # FIXME: If the command times out, we need to ignore anything that comes 
     734        # back from the process, or we'll notify of error conditions more than once 
     735        # I'm hoping the AlreadyCalled an AlreadyCancelled catch above will take care of this. 
    715736        log.error("Timed out waiting for command to exit") 
    716737        self.transport.loseConnection()