def readVersionData(self): g.feedback.log(LogLevels.INFO, "Reading version data") self.jinn = JinnVersion(self.data["Jinn"])
class Manifest(FileSystemHelper): def __init__(self, os, arch, osver, installed, location=None): self.jinn = None self.criticalMessage = None self.description = "" self.resources = [] self.actions = [] self.os = os self.arch = arch self.osver = osver if location is None: location = getManifestFile() g.feedback.log( LogLevels.DEBUG, "Manifest initialising from %s. OS: %s, Arch: %s" % (location, self.os, self.arch) ) self.load(location, installed) g.feedback.log( LogLevels.DEBUG, "Manifest initialised from %s. OS: %s, Arch: %s" % (location, self.os, self.arch) ) """ Loads data for this manifest from a specific location, then calls to parse it """ def load(self, location, installed): g.feedback.log(LogLevels.INFO, "Loading from %s" % location) if self.isPathUrl(location): l = UrlLoader(location) data = l.read(True, checkCache=(not installed)) else: l = FileLoader(location) data = l.read(True) if data is None: raise ManifestException("Unable to load data from the specified source") g.feedback.log(LogLevels.DEBUG, "Data: %s" % data) self.data = data self.parseData() """ Parses a generic data structure for this manifest """ def parseData(self): # check for any critical message self.criticalMessage = self.checkForCriticalMessage() self.readVersionData() self.readDescription() self.loadResources() self.loadActions() """ Check the manifest for critical user messages """ def checkForCriticalMessage(self): g.feedback.log(LogLevels.INFO, "checking for critical messages") osString = OperatingSystem().getOperatingSystem(self.os) archString = Architecture().getArchitecture(self.arch) try: self.critical = self.data["Critical"] except: return None if self.critical != None: # if there is a critical message for this operating system/architecture/version try: return self.critical[osString]["Message"] except: try: return self.critical[osString][archString]["Message"] except: return None else: return None """ Check the manifest version string is valid """ def readVersionData(self): g.feedback.log(LogLevels.INFO, "Reading version data") self.jinn = JinnVersion(self.data["Jinn"]) """ Load out the description """ def readDescription(self): g.feedback.log(LogLevels.INFO, "Reading description") try: self.description = self.data["Description"] except KeyError: raise ManifestException("The manifest file does not contain a description") if self.description == None or len(self.description) < 1: raise ManifestException("You must provide a description of this manifest") """ Returns whether or not this current platform is supported """ def platformSupported(self): g.feedback.log(LogLevels.DEBUG, "Checking manifest supported platform") if not "Platforms" in self.data: g.feedback.log(LogLevels.DEBUG, "No platforms specified, so we are supported") return True platforms = self.data["Platforms"] g.feedback.log(LogLevels.DEBUG, "Found platforms: %s" % platforms) # Check OS is specified os = OperatingSystem().getOperatingSystem(self.os) if not os in platforms: g.feedback.log(LogLevels.DEBUG, "OS %s not found in platforms" % os) return False # Check architecture is specified if "Architectures" in platforms[os]: arches = platforms[os]["Architectures"] arch = Architecture().getArchitecture(self.arch) if not arch in arches and not "All" in arches: g.feedback.log(LogLevels.DEBUG, "Arch %s not found in platforms for this OS (%s)" % (arch, os)) return False else: g.feedback.log( LogLevels.DEBUG, "Architectures not specified for platform %s, so we are supported architecture" % os ) # Check the version is specified if "Versions" in platforms[os]: v = platforms[os]["Versions"] if "Min" in v: vmin = v["Min"].split(".") g.feedback.log(LogLevels.DEBUG, "Min version of %s specified" % vmin) i = 0 while i < len(vmin): if int(self.osver[i]) < int(vmin[i]): g.feedback.log( LogLevels.DEBUG, "Version component %i, my version component %i is less than desired %i" % (i, int(self.osver[i]), int(vmin[i])), ) return False if int(self.osver[i]) > int(vmin[i]): g.feedback.log( LogLevels.DEBUG, "Version component %i, my version component %i is greater than desired %i so no need to continue" % (i, int(self.osver[i]), int(vmin[i])), ) break i += 1 if "Max" in v: vmax = v["Max"].split(".") g.feedback.log(LogLevels.DEBUG, "Max version of %s specified" % vmax) i = 0 while i < len(vmax): if int(self.osver[i]) > int(vmax[i]): g.feedback.log( LogLevels.DEBUG, "Version component %i, my version component %i is greater than desired %i" % (i, int(self.osver[i]), int(vmax[i])), ) return False if int(self.osver[i]) < int(vmax[i]): g.feedback.log( LogLevels.DEBUG, "Version component %i, my version component %i is less than desired %i so no need to continue" % (i, int(self.osver[i]), int(vmax[i])), ) break i += 1 else: g.feedback.log(LogLevels.DEBUG, "Versions not specified for platform %s, so we are supported version" % os) return True """ Load resources from the data """ def loadResources(self): g.feedback.log(LogLevels.INFO, "Loading resources") g.feedback.userMessage("MSG", "Loading resources") try: i = 0 dataResources = self.data["Resources"] for k in dataResources.keys(): g.feedback.log(LogLevels.DEBUG, "Found resource with ID %s" % k) g.feedback.userMessage("MSG", "Loading Resource: %s" % k) try: res = ResourceWrapper(k, self, dataResources[k], self.os, self.arch) if res.checkConditions(): g.feedback.log(LogLevels.DEBUG, "Conditions met for resource %s" % k) self.resources.append(res) else: g.feedback.log(LogLevels.DEBUG, "Conditions not met for resource %s" % k) i += 1 except ActivityNotFoundException: g.feedback.log(LogLevels.WARN, "No implementation for resource %s, ignoring" % k) if i < 1: raise ManifestException("The manifest must contain at least one valid resource") except KeyError: raise ManifestException("The manifest file does not contain any valid resources") """ Load actions from the data """ def loadActions(self): g.feedback.log(LogLevels.INFO, "Loading actions") try: dataActions = self.data["Actions"] for k in dataActions.keys(): g.feedback.log(LogLevels.DEBUG, "Found action with ID %s" % k) g.feedback.userMessage("MSG", "Loading Action: %s" % k) action = ActionWrapper(k, self, dataActions[k], self.os, self.arch) if action.checkConditions(): g.feedback.log(LogLevels.DEBUG, "Conditions met for action %s" % k) self.actions.append(action) else: g.feedback.log(LogLevels.DEBUG, "Conditions not met for action %s" % k) except KeyError: raise ManifestException("The manifest file does not contain any actions") """ Run the default action Returns false if no default action """ def runDefaultAction(self, args): g.feedback.log(LogLevels.INFO, "Running default action") for action in self.actions: if action.default: g.feedback.log(LogLevels.DEBUG, "The default action run is %s" % action.id) g.feedback.userMessage("MSG", "Performing action: %s" % action.id) return action.run(args) g.feedback.log(LogLevels.INFO, "No default action found") return False """ Returns an action with a specific name """ def getAction(self, name): for action in self.actions: if action.id == name: return action return None """ Run the specified action """ def runAction(self, actionName, args): g.feedback.log(LogLevels.DEBUG, "Running action %s with args %s" % (actionName, args)) g.feedback.userMessage("MSG", "Processing Action: %s : %s" % (actionName, args)) action = self.getAction(actionName) if action is not None: return action.run(args) return False """ Save the raw manifest data to the manifest fil """ def save(self): if not self.delete(getManifestFile()): return False return self.saveToFile(getManifestFile(), json.dumps(self.data)) """ Installs all of the resources """ def installResources(self): g.feedback.log(LogLevels.INFO, "Installing resources") for res in self.resources: g.feedback.userMessage("MSG", "Installing Resource: %s" % res.name) if not res.doInstall(): g.feedback.log(LogLevels.ERROR, "Failed to install resource with ID %s" % res.id) return False for res in self.resources: g.feedback.userMessage("MSG", "Running post-install script for: %s" % res.name) if not res.doInstallRun(): g.feedback.log(LogLevels.ERROR, "Failed to run install script for resource with ID %s" % res.id) return False return True """ Installs resources that are new in me from the old_resources """ def installNewResources(self, old_resources): for res in self.resources: old_resource = self.getResourceForId(res.id, old_resources) if old_resource is None: g.feedback.startUI("UPDATE", "Updates have been found, please wait while they are installed") g.feedback.log(LogLevels.DEBUG, "Resource with ID %s is new, so installing" % res.id) if not res.doInstall(): g.feedback.log(LogLevels.ERROR, "Installing new resource with ID %s failed" % res.id) return False g.feedback.userMessage("MSG", "Running post-install script for: %s" % res.name) if not res.doInstallRun(): g.feedback.log(LogLevels.ERROR, "Failed to run install script for resource with ID %s" % res.id) return False return True """ Uninstalls resources that were in old_resources but are not in me """ def uninstallRemovedResources(self, old_resources): for res in old_resources: new_resource = self.getResourceForId(res.id) if new_resource is None: g.feedback.startUI("UPDATE", "Updates have been found, please wait while they are installed") g.feedback.log(LogLevels.DEBUG, "Resource with ID %s is removed, so uninstalling" % res.id) g.feedback.userMessage("MSG", "Running pre-uninstall script for: %s" % res.name) if not res.doUninstall(): g.feedback.log(LogLevels.ERROR, "Uninstalling old resource with ID %s failed" % res.id) return False return True """ For the resources that are in both me and old_resources, if the version has changed, update that resource """ def updateResources(self, old_resources): for old_res in old_resources: new_res = self.getResourceForId(old_res.id) if new_res is not None: if new_res.isUpdatable(old_res): g.feedback.startUI("UPDATE", "Updates have been found, please wait while they are installed") g.feedback.log( LogLevels.DEBUG, "Resource with ID %s is changing version from %s to %s" % (new_res.id, old_res.version, new_res.version), ) g.feedback.userMessage( "MSG", "Updating Resource: %s from version %s to %s" % (new_res.id, old_res.version, new_res.version), ) if not old_res.doUninstall(): g.feedback.log(LogLevels.ERROR, "Failed to uninstall updating resource with ID %s" % new_res.id) return False # Install new one if not new_res.doInstall(): g.feedback.log(LogLevels.ERROR, "Failed to install updating resource with ID %s" % new_res.id) return False g.feedback.userMessage("MSG", "Running post-install script for: %s" % new_res.name) if not new_res.doInstallRun(): g.feedback.log( LogLevels.ERROR, "Failed to run install script for resource with ID %s" % new_res.id ) return False # Install the dependents that were removed during the uninstall if not new_res.installDependents(): g.feedback.log( LogLevels.ERROR, "Failed to install dependents of updating resource with ID %s" % new_res.id ) return False return True """ Uninstall all of the resources """ def uninstallResources(self): g.feedback.startUI("UPDATE", "Updates have been found, please wait while they are installed") g.feedback.log(LogLevels.DEBUG, "Uninstalling all resources") for res in self.resources: g.feedback.userMessage("MSG", "Running pre-uninstall script for: %s" % res.name) if not res.doUninstall(): g.feedback.log(LogLevels.ERROR, "Uninstalling resource with ID %s failed" % res.id) return False return True """ Helper which returns a resource which has a specific type Returns the inner type, not the wrapper! """ def getResourceForType(self, t): for res in self.resources: if res.type.getType() == t: return res return None """ Returns a resource given its ID Returns the wrapper """ def getResourceForId(self, i, resources=None): if resources is None: resources = self.resources for res in resources: if res.getId() == i: return res return None """ Returns whether or not a new binary exists """ def hasNewBinary(self, existing_binary): return self.jinn.getBinary(self.os, self.arch, self.osver) != existing_binary