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 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 plan 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. """ if not self.execute_called: # Save a timestamp from when we started execution. self.startTime = time.time() # Generate the plans we need to setup the chute if (executionplan.generatePlans(self)): out.warn('Failed to generate plans\n') self.complete(success=False, message=self.failure) return # Aggregate those plans executionplan.aggregatePlans(self) self.execute_called = True # Execute on those plans exec_result = executionplan.executePlans(self) if isinstance(exec_result, defer.Deferred): return exec_result elif exec_result is True: # Getting here means we need to abort what we did res = 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 # Respond to the API server to let them know the result self.complete(success=True, message='Chute {} {} success'.format( self.name, self.updateType))
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 isinstance(line, list): data = "\n".join(line) + "\n" elif isinstance(line, six.string_types): 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 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: with open(self.filename, 'wb') as output: pickle.dump(pyld, output) os.fsync(output.fileno()) except Exception as e: out.err('Error writing to disk %s\n' % (str(e)))
def loadFromDisk(self): """Attempts to load the data from disk. Returns True if success, False otherwise.""" if (pdos.exists(self.filename)): deleteFile = False 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 loadFromDisk(self): """Attempts to load the data from disk. Returns True if success, False otherwise.""" if(pdos.exists(self.filename)): deleteFile = False 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 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: with open(self.filename, 'wb') as output: pickle.dump(pyld, output) os.fsync(output.fileno()) except Exception as e: out.err('Error writing to disk %s\n' % (str(e))) try: with open(self.filename + ".yaml", "w") as output: yaml.dump(pyld, output) except Exception as error: out.err("Error writing yaml file: {}".format(error))
def readConfig(self): """Reads in the config file.""" 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.strip() # If comment ignore if line.startswith('#'): continue l = getLineParts(line) # # Config # 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 the key exists and is a list. if l[1] not in opt: opt[l[1]] = [] elif not isinstance(opt[l[1]], list): # One line started with "option", another with "list". If # this is supposed to be a list, they should all start with # "list". raise Exception("Malformed UCI: mixed list/option lines") opt[l[1]].append(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="paradrop", 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 = "" output += "#" * 80 + "\n" output += "# Configuration file generated by paradrop-daemon\n".format(self.myname) output += "# Path: {}\n".format(self.filepath) output += "# Package: {}\n".format(self.myname) output += "#" * 80 + "\n" output += "\n" # Now generate what the file would look like for c, o in self.config: line = "config %s" % c['type'] # Check for optional name if 'name' in c: line += " %s" % c['name'] if 'comment' in c: line += " #%s" % c['comment'] output += "%s\n" % line for k, v in six.iteritems(o): if isinstance(v, list): # For list-valued options, emit one line for each item # in the list. for vals in v: # Now append a list set to the config line = "\tlist %s '%s'\n" % (k, vals) output += line # Skip options that are None rather than writing "None". elif v is not None: sv = stringifyOptionValue(v) line = "\toption %s '%s'\n" % (k, sv) 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))