def callDeferredMethod(method, *args): try: conn = yield client.connect(reactor, busAddress="system") robj = yield conn.getRemoteObject(service_name, service_path) result = yield robj.callRemote(method, *args) defer.returnValue(result) except error.DBusException as e: out.err("D-Bus error: {}".format(e)) pass
def write(filename, data, mode="w"): """ Writes out a config file to the specified location. """ try: fd = open(filename, mode) fd.write(data) fd.flush() fd.close() except Exception as e: out.err('Unable to write to file: %s\n' % str(e))
def printFailure(r): # Autobahn cast exceptions if isinstance(r.value, exception.Error): print r.value.args[0] return None else: out.err('Unknown exception: ' + str(r)) return r
def reloadAll(update): # Note: reloading all config files at once seems safer than individual # files because of cross-dependencies. statusString = client.reloadAll() # Check the status to make sure all configuration sections # related to this chute were successfully loaded. status = json.loads(statusString) for section in status: if section['comment'] == update.name: if not section['success']: out.err("Error installing configuration section {} {}".format( section['type'], section['name'])) raise Exception("Error preparing host environment for chute")
def execute(self): """ The function that actually walks through the main process required to create the chute. It follows the executeplan module through the paces of: 1) Generate the plans for each exc module 2) Prioritize the plans 3) Execute the plans If at any point we fail then this function will directly take care of completing the update process with an error state and will close the API connection. """ # Save a timestamp from when we started execution. self.startTime = time.time() # Generate the plans we need to setup the chute if(exc.executionplan.generatePlans(self)): out.warn('Failed to generate plans\n') self.complete(success=False, message=self.failure) return # Aggregate those plans exc.executionplan.aggregatePlans(self) # Execute on those plans if(exc.executionplan.executePlans(self)): # Getting here means we need to abort what we did res = exc.executionplan.abortPlans(self) # Did aborting also fail? This is bad! if(res): ################################################################################### # Getting here means the abort system thinks it wasn't able to get the system # back into the state it was in prior to this update. ################################################################################### out.err('TODO: What do we do when we fail during abort?\n') pass # Report the failure back to the user self.complete(success=False, message=self.failure) return # Now save the new state if we are all ok self.saveState() # Respond to the API server to let them know the result self.complete(success=True, message='Chute {} {} success'.format( self.name, self.updateType))
def saveToDisk(self): """Saves the data to disk.""" out.info("Saving to disk (%s)\n" % (self.filename)) # Make sure they want to save if not self.attrSaveable(): return # Get whatever the data is pyld = self.exportAttr(self.getAttr()) # Write the file to disk, truncate if it exists try: pickle.dump(pyld, pdos.open(self.filename, "wb")) pdos.syncFS() except Exception as e: out.err("Error writing to disk %s\n" % (str(e)))
def writeFile(filename, line, mode="a"): """Adds the following cfg (either str or list(str)) to this Chute's current config file (just stored locally, not written to file.""" try: if(type(line) is list): data = "\n".join(line) + "\n" elif(type(line) is str): data = "%s\n" % line else: out.err("Bad line provided for %s\n" % filename) return fd = open(filename, mode) fd.write(data) fd.flush() fd.close() except Exception as e: out.err('Unable to write file: %s\n' % (str(e)))
def preprocess(self, request, checkThresh, tictoc): """ Check if failure attempts for the user name has met the threshold. Arguments: request : checkThresh : If None, no checking. Tuple of arguments for checking thresholds ip: IP of client in string format token: sessionToken if found, or None username: username if signin, or None failureDict: the dict for failure history ticktoc: If none, do not track the usage. The start time of the API call Return: str: if threshold is met None: if ok """ if(checkThresh): ip, token, key, failureDict = checkThresh # Check if IP is in whitelist ipaddr = apiutils.unpackIPAddr(ip) for ipnet in self.WHITELIST_IP: net = apiutils.unpackIPAddrWithSlash(ipnet) if(apiutils.addressInNetwork(ipaddr, net)): out.verbose('Request from white list: %s\n' % (ip)) return None if(key in failureDict): if(failureDict[key].attempts >= settings.DBAPI_FAILURE_THRESH): out.err('Threshold met: %s %s!\n' % (ip, key)) if(tictoc is None): usage = None else: usage = (tictoc, None) self.failprocess(ip, request, (ip, failureDict), None, usage, pdapi.getResponse(pdapi.ERR_THRESHOLD)) duration = 0 # self.perf.toc(tictoc) # Log the info of this call # TODO self.usageTracker.addTrackInfo(ip, 'Null', request.path, self.usageTracker.FAIL_THRESH, duration, request.content.getvalue()) return "Threshold Met!" # Otherwise everything is ok return None
def default(self, request): """ A dummy catch for all API calls that are not caught by any other module. """ ip = apiutils.getIP(request) uri = request.uri method = request.method # Get data about who done it out.err("Default caught API call (%s => %s:%s)\n" % (ip, method, uri)) # TODO: What is this? tictoc = None # Someone might be trying something bad, track their IP res = self.preprocess(request, (ip, None, ip, self.defaultFailures), tictoc) if(res): return res self.failprocess(ip, request, (ip, self.defaultFailures), None, (tictoc, None), pdapi.ERR_BADMETHOD) return ""
def loadFromDisk(self): """Attempts to load the data from disk. Returns True if success, False otherwise.""" if pdos.exists(self.filename): deleteFile = False out.info("Loading from disk\n") data = "" try: pyld = pickle.load(pdos.open(self.filename, "rb")) self.setAttr(self.importAttr(pyld)) return True except Exception as e: out.err("Error loading from disk: %s\n" % (str(e))) deleteFile = True # Delete the file if deleteFile: try: pdos.unlink(self.filename) except Exception as e: out.err("Error unlinking %s\n" % (self.filename)) return False
def readConfig(self): """Reads in the config file.""" def correctStr(line): return " ".join(line.split()) lines = [] try: fd = pdos.open(self.filepath, 'r') while(True): line = fd.readline() if(not line): break lines.append(line) fd.close() except Exception as e: out.err('Error reading file %s: %s\n' % (self.filepath, str(e))) raise e cfg = None opt = None data = [] # Now we have the data, deal with it for line in lines: line = line.rstrip() # If comment ignore if(line.startswith('#')): continue # First make all lines have correct whitespace # FIXME: if there is a space WITHIN quotes this kills it! # this could come up as a key in an encryption key line = correctStr(line) l = getLineParts(line) # # Config # #print("l: %s" % l) if(l[0] == 'config'): # Save last config we had if(cfg and opt): data.append((cfg, opt)) # start a new config cfg = {'type': l[1]} # Third element can be comment or name if(len(l) == 3): if (l[2].startswith('#')): cfg['comment'] = l[2][1:] else: cfg['name'] = l[2] elif (len(l) == 4): # Four elements, so third is name and 4th is comment cfg['name'] = l[2] cfg['comment'] = l[3][1:] opt = {} # # Options # elif(l[0] == 'option'): opt[l[1]] = l[2] # # List # elif(l[0] == 'list'): # Make sure there is a list key if('list' not in opt.keys()): opt['list'] = {} if(l[1] in opt['list'].keys()): opt['list'][l[1]].append(l[2]) else: opt['list'][l[1]] = [l[2]] else: # Also at the end of the loop, save the final config we were making # Make sure cfg,opt aren't None if(None not in (cfg, opt)): data.append((cfg, opt)) return data
def save(self, backupToken=None, internalid=None): """ Saves out the file in the proper format. Arguments: [backupPath] : Save a backup copy of the UCI file to the path provided. Should be a token name like 'backup', it gets appended with a hyphen. """ # Save original copy if(backupToken): self.backup(backupToken) output = "" # Now generate what the file would look like for c, o in self.config: #print("c: %s\n" % c.keys()) line = "config %s" % c['type'] # Check for optional name if('name' in c.keys()): line += " %s" % c['name'] if('comment' in c.keys()): line += " #%s" % c['comment'] output += "%s\n" % line # Get options # check for lists first, if they exist remove them first if('list' in o.keys()): theLists = o['list'] else: theLists = None # Now process everything else quick for k,v in o.iteritems(): # Make sure we skip the lists key if(k != 'list'): line = "\toption %s '%s'\n" % (k,v) output += line # Now process the list if(theLists): # theLists is a dict where the key is each list name # and the value is a list of the options we need to include for k,v in theLists.iteritems(): # so @v here is a list for vals in v: # Now append a list set to the config line = "\tlist %s '%s'\n" % (k, vals) output += line # Now add one extra newline before the next set output += "\n" # Now write to disk try: out.info('Saving %s to disk\n' % (self.filepath)) fd = pdos.open(self.filepath, 'w') fd.write(output) # Guarantee that its written to disk before we close fd.flush() os.fsync(fd.fileno()) fd.close() except Exception as e: out.err('Unable to save new config %s, %s\n' % (self.filepath, str(e))) out.err('Config may be corrupted, backup exists at /tmp/%s\n' % (self.myname))