def groupMessage(self, command, signatureKey): """Given a command string and signature create a signed payload""" digest = DIGEST_INIT() keyID = signatureKey.id magicStr = packify(self.value) timestamp = int(time.time()) payload = str(magicStr) + str(timestamp) + str(command) digest.update(payload) signature = signatureKey.encrypt(digest.hexdigest()) if '.' in signatureKey.id: keyID = signatureKey.id.split('.', 1)[0] args = command.split() action = args.pop(0) argstr = "" if args: argstr = " ".join(args) #group payload msgDict = { 'action': action, 'argstr': argstr, 'magic': magicStr, 'time': timestamp, 'key': keyID, 'signature': signature, } proto = Serialize() return urllib.quote(proto.execute(self.MIME, msgDict))
def startInstance(self, label): """Starts an Application Instances based on our models rules @param label: (string) - app instance label @return defer.Deferred - be prepared for Failures() """ start = dictwrapper(copy.deepcopy(self.STARTUP_INFO)) #configure our protocol if 'debug' not in self.startProtoKwargs: self.startProtoKwargs['debug'] = False if 'timeout' not in self.startProtoKwargs: self.startProtoKwargs['timeout'] = self.DEFAULT_TIMEOUT if 'logger' not in self.startProtoKwargs: self.startProtoKwargs['logger'] = self.log #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # # !! READ THIS COMMENT BLOCK !! # # the callback result from your protocol should return a dictionary # with a KEY 'pid' included and 'pid' should be an integer otherwise # the injected callback immediately following 'command' will fail to # update your instance state. You have been warned. #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! result = None try: thisInst = self.getInstance(label) TIME = str(time.time()) anchor = DIGEST_INIT() anchor.update(self.name) anchor.update(label) anchor.update(TIME) #add some randomness anchor = str(anchor.hexdigest()) #inject some env variables that we may want to retrieve later ENV = { 'DRONED_IDENTIFIER': anchor, 'DRONED_STARTTIME': TIME, 'DRONED_LABEL': label, 'DRONED_APPLICATION': self.name, 'DRONED_LOGDIR': config.LOG_DIR, } if thisInst.version: ENV['DRONED_VERSION'] = thisInst.version #add these vars to the start env of the contained application start.START_ENV.update(ENV) d = command(start.START_CMD, start.START_ARGS, start.START_ENV, start.START_PATH, start.START_USEPTY, start.START_CHILDFD, self.startProtocol, *self.startProtoArgs, **self.startProtoKwargs) wfd = defer.waitForDeferred(d) yield wfd result = wfd.getResult() #we probably might not know the pid yet #if allowed by config search for the instance after some delay pid = result.get('pid', 0) #just in case the protocol knows it if isinstance(self.SEARCH_DELAY, (int, float)) and not pid: d = defer.Deferred() self.reactor.callLater(self.SEARCH_DELAY, d.callback, None) wfd = defer.waitForDeferred(d) yield wfd wfd.getResult() #don't care about this result d = self.findProcesses() wfd = defer.waitForDeferred(d) yield wfd data = wfd.getResult() if data: data = data.pop(0)[1] #we are just going to take the first result.update(data) #we should have the pid captured #this is the proper way to notify the AppInstance that we are running thisInst.pid = int(result.get('pid', 0)) except: result = Failure() yield result