示例#1
0
 def readVersionData(self):
     g.feedback.log(LogLevels.INFO, "Reading version data")
     self.jinn = JinnVersion(self.data["Jinn"])
示例#2
0
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
示例#3
0
文件: Manifest.py 项目: yoda-vid/jinn
 def readVersionData(self):
     g.feedback.log(LogLevels.INFO, "Reading version data")
     self.jinn = JinnVersion(self.data["Jinn"])