示例#1
0
class RunSoftwareUpdate(Screen, HelpableScreen):
    skin = """
	<screen name="RunSoftwareUpdate" position="center,center" size="720,435" resolution="1280,720">
		<widget name="update" position="10,10" size="700,400" font="Regular;20" halign="center" transparent="1" valign="center" />
		<widget name="activity" position="10,420" size="700,5" />
	</screen>"""

    def __init__(self, session, *args):
        Screen.__init__(self, session)
        HelpableScreen.__init__(self)
        self.setTitle(_("Software Update"))
        self.onTimerTick = []
        self["update"] = ScrollLabel(
            _("Software update starting, please wait.\n\n"))
        self["activity"] = Slider(0, 100)
        self["actions"] = HelpableActionMap(
            self,
            ["OkCancelActions", "NavigationActions"],
            {
                "cancel":
                (self.keyCancel, _("Stop the update, if running, then exit")),
                "ok":
                (self.keyCancel, _("Stop the update, if running, then exit")),
                "top": (self.top, _("Move to first line / screen")),
                "pageUp": (self.pageUp, _("Move up a page / screen")),
                "up": (self.pageUp, _("Move up a page / screen")),
                # "first": (self.top, _("Move to first line / screen")),
                "left": (self.pageUp, _("Move up a page / screen")),
                "right": (self.pageDown, _("Move down a page / screen")),
                # "last": (self.bottom, _("Move to last line / screen")),
                "down": (self.pageDown, _("Move down a page / screen")),
                "pageDown": (self.pageDown, _("Move down a page / screen")),
                "bottom": (self.bottom, _("Move to last line / screen"))
            },
            prio=0,
            description=_("Software Update Actions"))
        self.activity = 0
        self.timer = eTimer()
        self.timer.callback.append(self.timeout)
        self.packageTotal = 0
        self.downloadCount = 0
        self.updateCount = 0
        self.installCount = 0
        self.removeCount = 0
        self.deselectCount = 0
        self.upgradeCount = 0
        self.configureCount = 0
        self.errorCount = 0
        self.updateFlag = True
        self.opkg = OpkgComponent()
        self.opkg.addCallback(self.opkgCallback)
        self.onLayoutFinish.append(self.layoutFinished)

    def layoutFinished(self):
        self.opkg.startCmd(OpkgComponent.CMD_UPDATE)
        self.timer.start(25, True)

    def timeout(self):
        if self.activity < 0:
            self.timer.stop()
            self["activity"].hide()
        else:
            self.activity += 1
            if self.activity == 100:
                self.activity = 0
            self["activity"].setValue(self.activity)
            self.timer.start(100, True)
        for callback in self.onTimerTick:
            callback()

    def opkgCallback(self, event, parameter):
        if event == OpkgComponent.EVENT_DOWNLOAD:
            self.downloadCount += 1
            if parameter.find(
                    "_"
            ) == -1:  # Only display the downloading of the feed packages.
                self["update"].appendText("%s: '%s'.\n" %
                                          (_("Downloading"), parameter))
        elif event == OpkgComponent.EVENT_UPDATED:
            self.updateCount += 1
            self["update"].appendText("%s: %s\n" % (_("Updated"), parameter))
        elif event == OpkgComponent.EVENT_UPVERSION:
            self.upgradeCount += 1
            self["update"].appendText("%s %s/%s: '%s'.\n" %
                                      (_("Updating"), self.upgradeCount,
                                       self.packageTotal, parameter))
        elif event == OpkgComponent.EVENT_INSTALL:
            self.installCount += 1
            self["update"].appendText("%s: '%s'.\n" %
                                      (_("Installing"), parameter))
        elif event == OpkgComponent.EVENT_REMOVE:
            self.removeCount += 1
            self["update"].appendText("%s: '%s'.\n" %
                                      (_("Removing"), parameter))
        elif event == OpkgComponent.EVENT_CONFIGURING:
            self.configureCount += 1
            self["update"].appendText("%s: '%s'.\n" %
                                      (_("Configuring"), parameter))
        elif event == OpkgComponent.EVENT_MODIFIED:
            if config.plugins.softwaremanager.overwriteConfigFiles.value in (
                    "N", "Y"):
                self.opkg.write(
                    True and
                    config.plugins.softwaremanager.overwriteConfigFiles.value)
            else:
                self.session.openWithCallback(
                    self.modificationCallback, MessageBox,
                    _("Configuration file '%s' has been modified since it was installed, would you like to keep the modified version?"
                      ) % parameter)
        elif event == OpkgComponent.EVENT_ERROR:
            self.errorCount += 1
        elif event == OpkgComponent.EVENT_DONE:
            if self.updateFlag:
                self.updateFlag = False
                self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST)
            elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST:
                self.packageTotal = len(self.opkg.getFetchedList())
                if self.packageTotal:
                    self.opkg.startCmd(OpkgComponent.CMD_UPGRADE,
                                       args={"testMode": False})
                else:
                    self.activity = -1
                    self["update"].appendText(
                        "%s\n\n%s" %
                        (_("No updates available."),
                         _("Press OK on your remote control to continue.")))
            else:
                if self.errorCount == 0:
                    self["update"].appendText("\n%s\n\n" %
                                              _("Update completed."))
                    self["update"].appendText(
                        "%s\n" %
                        ngettext("%d package was identified for upgrade.",
                                 "%d packages were identified for upgrade.",
                                 self.packageTotal) % self.packageTotal)
                    self["update"].appendText("%s\n" % ngettext(
                        "%d package was downloaded.",
                        "%d packages were downloaded.", self.downloadCount) %
                                              self.downloadCount)
                    self["update"].appendText(
                        "%s\n" %
                        ngettext("%d feed catalog package was updated.",
                                 "%d feed catalog packages were updated.",
                                 self.updateCount) % self.updateCount)
                    self["update"].appendText("%s\n" % ngettext(
                        "%d package was installed.",
                        "%d packages were installed.", self.installCount) %
                                              self.installCount)
                    self["update"].appendText("%s\n" % ngettext(
                        "%d package was removed.", "%d packages were removed.",
                        self.removeCount) % self.removeCount)
                    self["update"].appendText("%s\n" % ngettext(
                        "%d package was upgraded.",
                        "%d packages were upgraded.", self.upgradeCount) %
                                              self.upgradeCount)
                    self["update"].appendText("%s\n" % ngettext(
                        "%d package was configured.",
                        "%d packages were configured.", self.configureCount) %
                                              self.configureCount)
                    if self.deselectCount:
                        self["update"].appendText(
                            "%s\n" % ngettext("%d package was deselected.",
                                              "%d packages were deselected.",
                                              self.deselectCount) %
                            self.deselectCount)
                        self["update"].appendText("\n%s\n" % _(
                            "Deselected packages usually occur because those packaged are incompatible with existing packages.  While this is mostly harmless it is possible that your %s %s may experience issues."
                        ) % (displayBrand, displayModel))
                else:
                    error = _(
                        "Your receiver might be unusable now.  Please consult the manual for further assistance before rebooting your %s %s."
                    ) % (displayBrand, displayModel)
                    if self.upgradeCount == 0:
                        error = _(
                            "No updates were available.  Please try again later."
                        )
                    self["update"].appendText("%s: %s\n" % (_("Error"), error))
                self.activity = -1
                self["update"].appendText(
                    "\n%s" % _("Press OK on your remote control to continue."))

    def modificationCallback(self, answer):
        self.opkg.write("N" if answer else "Y")

    def keyCancel(self):
        if self.opkg.isRunning():
            self.opkg.stop()
        self.opkg.removeCallback(self.opkgCallback)
        if self.upgradeCount != 0 and self.errorCount == 0:
            self.restoreMetrixHD()
        else:
            self.close()

    def keyCancelCallback(self, answer):
        if answer:
            self.session.open(TryQuitMainloop, retvalue=QUIT_REBOOT)
        self.close()

    def top(self):
        self["update"].moveTop()

    def pageUp(self):
        self["update"].pageUp()

    def pageDown(self):
        self["update"].pageDown()

    def bottom(self):
        self["update"].moveBottom()

    def createSummary(self):
        return RunSoftwareUpdateSummary

    def restoreMetrixHD(
        self
    ):  # TODO: call this only after metrix update / move this to Metrix Plugin
        try:
            if config.skin.primary_skin.value == "MetrixHD/skin.MySkin.xml":
                if not exists("/usr/share/enigma2/MetrixHD/skin.MySkin.xml"):
                    from Plugins.SystemPlugins.SoftwareManager.BackupRestore import RestoreMyMetrixHD
                    self.session.openWithCallback(self.restoreMetrixHDCallback,
                                                  RestoreMyMetrixHD)
                    return
                elif config.plugins.MyMetrixLiteOther.EHDenabled.value != '0':
                    from Plugins.Extensions.MyMetrixLite.ActivateSkinSettings import ActivateSkinSettings
                    ActivateSkinSettings().RefreshIcons()
        except:
            pass
        self.restoreMetrixHDCallback()

    def restoreMetrixHDCallback(self, ret=None):
        self.session.openWithCallback(
            self.keyCancelCallback, MessageBox,
            _("Upgrade finished.") + " " +
            _("Do you want to reboot your %s %s?") %
            (displayBrand, displayModel))
示例#2
0
class Opkg(Screen):
    def __init__(self, session, cmdList=[]):
        Screen.__init__(self, session)

        self.cmdList = cmdList

        self.sliderPackages = {}

        self.slider = Slider(0, len(cmdList))
        self["slider"] = self.slider
        self.activityslider = Slider(0, 100)
        self["activityslider"] = self.activityslider
        self.status = Label(_("Preparing... Please wait"))
        self["status"] = self.status
        self.package = Label()
        self["package"] = self.package

        self.packages = 0
        self.error = 0
        self.processed_packages = []

        self.activity = 0
        self.activityTimer = eTimer()
        self.activityTimer.callback.append(self.doActivityTimer)
        #self.activityTimer.start(100, False)

        self.opkg = OpkgComponent()
        self.opkg.addCallback(self.opkgCallback)

        self.runningCmd = None
        self.runNextCmd()

        self["actions"] = ActionMap(["WizardActions"], {
            "ok": self.exit,
            "back": self.exit
        }, -1)

    def runNextCmd(self):
        if self.runningCmd is None:
            self.runningCmd = 0
        else:
            self.runningCmd += 1
        print(len(self.cmdList), self.runningCmd)
        if len(self.cmdList) - 1 < self.runningCmd:
            self.activityslider.setValue(0)
            self.slider.setValue(len(self.cmdList))

            self.package.setText("")
            self.status.setText(
                ngettext(
                    "Done - Installed, updated or removed %d package (%s)",
                    "Done - Installed, updated or removed %d packages (%s)",
                    self.packages) %
                (self.packages,
                 ngettext("with %d error", "with %d errors", self.error) %
                 self.error))
            return False
        else:
            cmd = self.cmdList[self.runningCmd]
            self.slider.setValue(self.runningCmd)
            self.opkg.startCmd(cmd[0], args=cmd[1])
            self.startActivityTimer()

    def doActivityTimer(self):
        if not self.opkg.isRunning():
            self.stopActivityTimer()
        else:
            self.activity += 1
            if self.activity == 100:
                self.activity = 0
            self.activityslider.setValue(self.activity)

    def startActivityTimer(self):
        self.activityTimer.start(100, False)

    def stopActivityTimer(self):
        self.activityTimer.stop()

    def opkgCallback(self, event, param):
        if event == OpkgComponent.EVENT_DOWNLOAD:
            self.status.setText(_("Downloading"))
        elif event == OpkgComponent.EVENT_UPGRADE:
            if param in self.sliderPackages:
                self.slider.setValue(self.sliderPackages[param])
            self.package.setText(param)
            self.status.setText(_("Updating"))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_INSTALL:
            self.package.setText(param)
            self.status.setText(_("Installing"))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_REMOVE:
            self.package.setText(param)
            self.status.setText(_("Removing"))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_CONFIGURING:
            self.package.setText(param)
            self.status.setText(_("Configuring"))
        elif event == OpkgComponent.EVENT_ERROR:
            self.error += 1
        elif event == OpkgComponent.EVENT_DONE:
            self.runNextCmd()
        elif event == OpkgComponent.EVENT_MODIFIED:
            self.session.openWithCallback(
                self.modificationCallback, MessageBox,
                _("A configuration file (%s) has been modified since it was installed. Would you like to keep the modified version?"
                  ) % (param))

    def modificationCallback(self, res):
        self.opkg.write(res and "N" or "Y")

    def exit(self):
        if not self.opkg.isRunning():
            self.close()
示例#3
0
class UpdatePlugin(Screen, ProtectedScreen):
	skin = """
		<screen name="UpdatePlugin" position="center,center" size="550,300">
			<widget name="activityslider" position="0,0" size="550,5"  />
			<widget name="slider" position="0,150" size="550,30"  />
			<widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
			<widget source="status" render="Label" position="10,180" size="540,100" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
		</screen>"""

	def __init__(self, session, *args):
		Screen.__init__(self, session)
		ProtectedScreen.__init__(self)

		self.sliderPackages = { "enigma2": 1, "openvision": 2 }

		self.setTitle(_("Software update"))
		self.slider = Slider(0, 4)
		self["slider"] = self.slider
		self.activityslider = Slider(0, 100)
		self["activityslider"] = self.activityslider
		self.status = StaticText(_("Please wait..."))
		self["status"] = self.status
		self.package = StaticText(_("Package list update"))
		self["package"] = self.package
		self.oktext = _("Press OK on your remote control to continue.")

		self.packages = 0
		self.error = 0
		self.processed_packages = []
		self.total_packages = None

		self.channellist_only = 0
		self.channellist_name = ''
		self.updating = False
		self.opkg = OpkgComponent()
		self.opkg.addCallback(self.opkgCallback)
		self.onClose.append(self.__close)

		self["actions"] = ActionMap(["WizardActions"],
		{
			"ok": self.exit,
			"back": self.exit
		}, -1)

		self.activity = 0
		self.activityTimer = eTimer()
		self.activityTimer.callback.append(self.checkTraficLight)
		self.activityTimer.callback.append(self.doActivityTimer)
		self.activityTimer.start(100, True)

	def isProtected(self):
		return config.ParentalControl.setuppinactive.value and\
			(not config.ParentalControl.config_sections.main_menu.value and not config.ParentalControl.config_sections.configuration.value  or hasattr(self.session, 'infobar') and self.session.infobar is None) and\
			config.ParentalControl.config_sections.software_update.value

	def checkTraficLight(self):
		self.activityTimer.callback.remove(self.checkTraficLight)
		self.activityTimer.start(100, False)
		status = None
		message = None
		abort = False
		picon = MessageBox.TYPE_ERROR
		url = "https://openvision.tech/trafficlight"

		# try to fetch the trafficlight json from the website
		try:
			status = dict(json.load(urlopen(url, timeout=5)))
			print("[SoftwareUpdate] status is: ", status)
		except:
			pass

		# process the status fetched
		if status is not None:

			try:
				# get image version and machine name
				machine = getBoxType()
				version = open("/etc/issue").readlines()[-2].split()[1]

				# do we have an entry for this version
				if version in status and machine in status[version]['machines']:
					if 'abort' in status[version]:
						abort = status[version]['abort']
					if 'from' in status[version]:
						starttime = datetime.datetime.strptime(status[version]['from'], '%Y%m%d%H%M%S')
					else:
						starttime = datetime.datetime.now()
					if 'to' in status[version]:
						endtime = datetime.datetime.strptime(status[version]['to'], '%Y%m%d%H%M%S')
					else:
						endtime = datetime.datetime.now()
					if (starttime <= datetime.datetime.now() and endtime >= datetime.datetime.now()):
						message = str(status[version]['message'])

				# check if we have per-language messages
				if type(message) is dict:
					lang = language.getLanguage()
					if lang in message:
						message = message[lang]
					elif 'en_EN' in message:
						message = message['en_EN']
					else:
						message =  _("The current image might not be stable.\nFor more information see %s.") % ("openvision.tech")

			except Exception as e:
				print("[SoftwareUpdate] status error: ", str(e))
				message =  _("The current image might not be stable.\nFor more information see %s.") % ("openvision.tech")

		# or display a generic warning if fetching failed
		else:
			message = _("The status of the current image could not be checked because %s can not be reached.") % ("openvision.tech")

		# show the user the message first
		if message is not None:
			if abort:
				self.session.openWithCallback(self.close, MessageBox, message, type=MessageBox.TYPE_ERROR, picon = picon)
			else:
				message += "\n\n" + _("Do you want to update your receiver?")
				self.session.openWithCallback(self.startActualUpdate, MessageBox, message, picon = picon)

		# no message, continue with the update
		else:
			self.startActualUpdate(True)

	def getLatestImageTimestamp(self):
		def gettime(url):
			try:
				return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(calendar.timegm(urlopen("%s/Packages.gz" % url).info().getdate('Last-Modified'))-time.altzone))
			except:
				return ""
		return sorted([gettime(open("/etc/opkg/%s" % file, "r").readlines()[0].split()[2]) for file in os.listdir("/etc/opkg") if not file.startswith("3rd-party") and file not in ("arch.conf", "opkg.conf", "picons-feed.conf")], reverse=True)[0]

	def startActualUpdate(self,answer):
		if answer:
			self.updating = True
			self.opkg.startCmd(OpkgComponent.CMD_UPDATE)
		else:
			self.close()

	def doActivityTimer(self):
		self.activity += 1
		if self.activity == 100:
			self.activity = 0
		self.activityslider.setValue(self.activity)

	def showUpdateCompletedMessage(self):
		self.setEndMessage(ngettext("Update completed, %d package was installed.", "Update completed, %d packages were installed.", self.packages) % self.packages)

	def opkgCallback(self, event, param):
		if event == OpkgComponent.EVENT_DOWNLOAD:
			self.status.setText(_("Downloading"))
		elif event == OpkgComponent.EVENT_UPGRADE:
			if param in self.sliderPackages:
				self.slider.setValue(self.sliderPackages[param])
			self.package.setText(param)
			self.status.setText(_("Updating") + ": %s/%s" % (self.packages, self.total_packages))
			if not param in self.processed_packages:
				self.processed_packages.append(param)
				self.packages += 1
		elif event == OpkgComponent.EVENT_INSTALL:
			self.package.setText(param)
			self.status.setText(_("Installing"))
			if not param in self.processed_packages:
				self.processed_packages.append(param)
				self.packages += 1
		elif event == OpkgComponent.EVENT_REMOVE:
			self.package.setText(param)
			self.status.setText(_("Removing"))
			if not param in self.processed_packages:
				self.processed_packages.append(param)
				self.packages += 1
		elif event == OpkgComponent.EVENT_CONFIGURING:
			self.package.setText(param)
			self.status.setText(_("Configuring"))
		elif event == OpkgComponent.EVENT_MODIFIED:
			if config.plugins.softwaremanager.overwriteConfigFiles.value in ("N", "Y"):
				self.opkg.write(True and config.plugins.softwaremanager.overwriteConfigFiles.value)
			else:
				self.session.openWithCallback(
					self.modificationCallback,
					MessageBox,
					_("A configuration file (%s) has been modified since it was installed.\nDo you want to keep your modifications?") % (param)
				)
		elif event == OpkgComponent.EVENT_ERROR:
			self.error += 1
		elif event == OpkgComponent.EVENT_DONE:
			if self.updating:
				self.updating = False
				self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST)
			elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST:
				self.total_packages = len(self.opkg.getFetchedList())
				if self.total_packages:
					latestImageTimestamp = self.getLatestImageTimestamp()
					if latestImageTimestamp:
						message = _("Do you want to update your receiver to %s?") % latestImageTimestamp + "\n"
					else:
						message = _("Do you want to update your receiver?") + "\n"
					message += "(" + (ngettext("%s updated package available", "%s updated packages available", self.total_packages) % self.total_packages) + ")"
					if self.total_packages > 150:
						choices = [(_("Update and reboot"), "cold")]
						message += " " + _("Reflash recommended!")
					else:
						choices = [(_("Update and reboot (recommended)"), "cold"),
						(_("Update and ask to reboot"), "hot")]
					choices.append((_("Update channel list only"), "channels"))
					choices.append((_("Show packages to be updated"), "showlist"))
				else:
					message = _("No updates available")
					choices = []
				if fileExists("/home/root/opkgupgrade.log"):
					choices.append((_("Show latest update log"), "log"))
				choices.append((_("Show latest commits"), "commits"))
				choices.append((_("Cancel"), ""))
				self.session.openWithCallback(self.startActualUpgrade, ChoiceBox, title=message, list=choices, windowTitle=self.title)
			elif self.channellist_only > 0:
				if self.channellist_only == 1:
					self.setEndMessage(_("Could not find installed channel list."))
				elif self.channellist_only == 2:
					self.slider.setValue(2)
					self.opkg.startCmd(OpkgComponent.CMD_REMOVE, {'package': self.channellist_name})
					self.channellist_only += 1
				elif self.channellist_only == 3:
					self.slider.setValue(3)
					self.opkg.startCmd(OpkgComponent.CMD_INSTALL, {'package': self.channellist_name})
					self.channellist_only += 1
				elif self.channellist_only == 4:
					self.showUpdateCompletedMessage()
					eDVBDB.getInstance().reloadBouquets()
					eDVBDB.getInstance().reloadServicelist()
			elif self.error == 0:
				self.showUpdateCompletedMessage()
			else:
				self.activityTimer.stop()
				self.activityslider.setValue(0)
				error = _("Your receiver might be unusable now. Please consult the manual for further assistance before rebooting your receiver.")
				if self.packages == 0:
					error = _("No updates available. Please try again later.")
				if self.updating:
					error = _("Update failed. Your receiver does not have a working internet connection.")
				self.status.setText(_("Error") +  " - " + error)
		elif event == OpkgComponent.EVENT_LISTITEM:
			if 'enigma2-plugin-settings-' in param[0] and self.channellist_only > 0:
				self.channellist_name = param[0]
				self.channellist_only = 2
		#print(event, "-", param)
		pass

	def setEndMessage(self, txt):
		self.slider.setValue(4)
		self.activityTimer.stop()
		self.activityslider.setValue(0)
		self.package.setText(txt)
		self.status.setText(self.oktext)

	def startActualUpgrade(self, answer):
		if not answer or not answer[1]:
			self.close()
			return
		if answer[1] == "cold":
			self.session.open(TryQuitMainloop,retvalue=42)
			self.close()
		elif answer[1] == "channels":
			self.channellist_only = 1
			self.slider.setValue(1)
			self.opkg.startCmd(OpkgComponent.CMD_LIST, args = {'installed_only': True})
		elif answer[1] == "commits":
			self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), CommitInfo)
		elif answer[1] == "showlist":
			text = "\n".join([x[0] for x in sorted(self.opkg.getFetchedList(), key=lambda d: d[0])])
			self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Packages to update"), True)
		elif answer[1] == "log":
			text = open("/home/root/opkgupgrade.log", "r").read()
			self.session.openWithCallback(boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE, None), TextBox, text, _("Latest update log"), True)
		else:
			self.opkg.startCmd(OpkgComponent.CMD_UPGRADE, args = {'test_only': False})

	def modificationCallback(self, res):
		self.opkg.write(res and "N" or "Y")

	def exit(self):
		if not self.opkg.isRunning():
			if self.packages != 0 and self.error == 0 and self.channellist_only == 0:
				self.session.openWithCallback(self.exitAnswer, MessageBox, _("Update completed. Do you want to reboot your receiver?"))
			else:
				self.close()
		else:
			if not self.updating:
				self.close()

	def exitAnswer(self, result):
		if result is not None and result:
			self.session.open(TryQuitMainloop, retvalue=2)
		self.close()

	def __close(self):
		self.opkg.removeCallback(self.opkgCallback)
示例#4
0
class UpdatePlugin(Screen, ProtectedScreen):
    skin = """
		<screen name="UpdatePlugin" position="center,center" size="550,300">
			<widget name="activityslider" position="0,0" size="550,5"  />
			<widget name="slider" position="0,150" size="550,30"  />
			<widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
			<widget source="status" render="Label" position="10,180" size="540,100" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
		</screen>"""

    def __init__(self, session, *args):
        Screen.__init__(self, session)
        ProtectedScreen.__init__(self)

        self.sliderPackages = {"gigablue-": 1, "enigma2": 2, "teamblue-": 3}

        self.setTitle(_("Software update"))
        self.slider = Slider(0, 4)
        self["slider"] = self.slider
        self.activityslider = Slider(0, 100)
        self["activityslider"] = self.activityslider
        self.status = StaticText(_("Please wait..."))
        self["status"] = self.status
        self.package = StaticText(_("Package list update"))
        self["package"] = self.package
        self.oktext = _("Press OK on your remote control to continue.")

        self.packages = 0
        self.error = 0
        self.processed_packages = []
        self.total_packages = None

        self.channellist_only = 0
        self.channellist_name = ''
        self.updating = False
        self.opkg = OpkgComponent()
        self.opkg.addCallback(self.opkgCallback)
        self.onClose.append(self.__close)

        self["actions"] = ActionMap(["WizardActions"], {
            "ok": self.exit,
            "back": self.exit
        }, -1)

        self.activity = 0
        self.activityTimer = eTimer()
        self.activityTimer.callback.append(self.checkTraficLight)
        self.activityTimer.callback.append(self.doActivityTimer)
        self.activityTimer.start(100, True)

    def isProtected(self):
        return config.ParentalControl.setuppinactive.value and\
         (not config.ParentalControl.config_sections.main_menu.value and not config.ParentalControl.config_sections.configuration.value  or hasattr(self.session, 'infobar') and self.session.infobar is None) and\
         config.ParentalControl.config_sections.software_update.value

    def checkTraficLight(self):
        self.activityTimer.callback.remove(self.checkTraficLight)
        self.activityTimer.start(100, False)
        message = ""
        picon = None
        default = True
        url = "http://images.teamblue.tech/status/%s-%s/" % (getImageVersion(),
                                                             getImageType())
        # print "[SoftwareUpdate] url status: ", url
        try:
            # TODO: Use Twisted's URL fetcher, urlopen is evil. And it can
            # run in parallel to the package update.
            try:
                status = urlopen(url, timeout=5).read().split('!', 1)
                print status
            except:
                # bypass the certificate check
                from ssl import _create_unverified_context
                status = urlopen(
                    url, timeout=5,
                    context=_create_unverified_context()).read().split('!', 1)
                print status
            # prefer getMachineBuild
            if getMachineBuild() in status[0].split(','):
                message = len(status) > 1 and status[1] or _(
                    "The current software might not be stable.\nFor more information see %s."
                ) % ("http://images.teamblue.tech")
                picon = MessageBox.TYPE_ERROR
                default = False
            # only use getBoxType if no getMachineBuild
            elif getBoxType() in status[0].split(','):
                message = len(status) > 1 and status[1] or _(
                    "The current software might not be stable.\nFor more information see %s."
                ) % ("http://images.teamblue.tech")
                picon = MessageBox.TYPE_ERROR
                default = False
        except:
            message = _(
                "The status of the current software could not be checked because %s can not be reached."
            ) % ("http://images.teamblue.tech")
            picon = MessageBox.TYPE_ERROR
            default = False
        if default:
            self.showDisclaimer()
        else:
            message += "\n" + _("Do you want to update your receiver?")
            self.session.openWithCallback(self.startActualUpdate,
                                          MessageBox,
                                          message,
                                          default=default,
                                          picon=picon)

    def showDisclaimer(self, justShow=False):
        if config.usage.show_update_disclaimer.value or justShow:
            message = _(
                "With this disclaimer the teamBlue team is informing you that we are working with nightly builds and it might be that after the upgrades your set top box \
is not anymore working as expected. Therefore it is recommended to create backups. If something went wrong you can easily and quickly restore. \
If you discover 'bugs' please keep them reported on www.teamblue.tech.\n\nDo you understand this?"
            )
            list = not justShow and [
                (_("no"), False), (_("yes"), True),
                (_("yes") + " " + _("and never show this message again"),
                 "never")
            ] or []
            self.session.openWithCallback(boundFunction(
                self.disclaimerCallback, justShow),
                                          MessageBox,
                                          message,
                                          list=list,
                                          title=_("Disclaimer"))
        else:
            self.startActualUpdate(True)

    def disclaimerCallback(self, justShow, answer):
        if answer == "never":
            config.usage.show_update_disclaimer.value = False
            config.usage.show_update_disclaimer.save()
        if justShow and answer:
            self.ipkgCallback(IpkgComponent.EVENT_DONE, None)
        else:
            self.startActualUpdate(answer)

    def getLatestImageTimestamp(self):
        url = "http://images.teamblue.tech/status/%s-%s/buildtimestamp-%s" % (
            getImageVersion(), getImageType(), getBoxType())
        # print "[SoftwareUpdate] url buildtimestamp: ", url
        try:
            # TODO: Use Twisted's URL fetcher, urlopen is evil. And it can
            # run in parallel to the package update.
            from time import strftime
            from datetime import datetime
            try:
                latestImageTimestamp = datetime.fromtimestamp(
                    int(urlopen(url, timeout=5).read())).strftime(
                        _("%Y-%m-%d %H:%M"))
            except:
                # bypass the certificate check
                from ssl import _create_unverified_context
                latestImageTimestamp = datetime.fromtimestamp(
                    int(
                        urlopen(url,
                                timeout=5,
                                context=_create_unverified_context()).read())
                ).strftime(_("%Y-%m-%d %H:%M"))
        except:
            latestImageTimestamp = ""
        print "[SoftwareUpdate] latestImageTimestamp:", latestImageTimestamp
        return latestImageTimestamp

    def startActualUpdate(self, answer):
        if answer:
            self.updating = True
            self.opkg.startCmd(OpkgComponent.CMD_UPDATE)
        else:
            self.close()

    def doActivityTimer(self):
        self.activity += 1
        if self.activity == 100:
            self.activity = 0
        self.activityslider.setValue(self.activity)

    def showUpdateCompletedMessage(self):
        self.setEndMessage(
            ngettext("Update completed, %d package was installed.",
                     "Update completed, %d packages were installed.",
                     self.packages) % self.packages)

    def opkgCallback(self, event, param):
        if event == OpkgComponent.EVENT_DOWNLOAD:
            self.status.setText(_("Downloading"))
        elif event == OpkgComponent.EVENT_UPGRADE:
            if param in self.sliderPackages:
                self.slider.setValue(self.sliderPackages[param])
            self.package.setText(param)
            self.status.setText(
                _("Updating") + ": %s/%s" %
                (self.packages, self.total_packages))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_INSTALL:
            self.package.setText(param)
            self.status.setText(_("Installing"))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_REMOVE:
            self.package.setText(param)
            self.status.setText(_("Removing"))
            if not param in self.processed_packages:
                self.processed_packages.append(param)
                self.packages += 1
        elif event == OpkgComponent.EVENT_CONFIGURING:
            self.package.setText(param)
            self.status.setText(_("Configuring"))
        elif event == OpkgComponent.EVENT_MODIFIED:
            if config.plugins.softwaremanager.overwriteConfigFiles.value in (
                    "N", "Y"):
                self.opkg.write(
                    True and
                    config.plugins.softwaremanager.overwriteConfigFiles.value)
            else:
                self.session.openWithCallback(
                    self.modificationCallback, MessageBox,
                    _("A configuration file (%s) has been modified since it was installed.\nDo you want to keep your modifications?"
                      ) % (param))
        elif event == OpkgComponent.EVENT_ERROR:
            self.error += 1
        elif event == OpkgComponent.EVENT_DONE:
            if self.updating:
                self.updating = False
                self.opkg.startCmd(OpkgComponent.CMD_UPGRADE_LIST)
            elif self.opkg.currentCommand == OpkgComponent.CMD_UPGRADE_LIST:
                self.total_packages = len(self.opkg.getFetchedList())
                if self.total_packages:
                    latestImageTimestamp = self.getLatestImageTimestamp()
                    if latestImageTimestamp:
                        message = _(
                            "Latest available teamBlue %s build is from: %s"
                        ) % (getImageVersion(),
                             self.getLatestImageTimestamp()) + "\n"
                        message += _(
                            "Do you want to update your receiver?") + "\n"
                    else:
                        message = _(
                            "Do you want to update your receiver?") + "\n"
                    message += "(" + (ngettext(
                        "%s updated package available",
                        "%s updated packages available", self.total_packages) %
                                      self.total_packages) + ")"
                    if self.total_packages > 150:
                        message += " " + _("Reflash recommended!")
                    choices = [
                        (_("Update and reboot (recommended)"), "cold"),
                        (_("Update and ask to reboot"), "hot"),
                        #(_("Update channel list only"), "channels"),
                        (_("Show packages to be updated"), "showlist")
                    ]
                else:
                    message = _("No updates available")
                    choices = []
                if fileExists("/home/root/opkgupgrade.log"):
                    choices.append((_("Show latest update log"), "log"))
                choices.append((_("Show latest commits"), "commits"))
                if not config.usage.show_update_disclaimer.value:
                    choices.append((_("Show disclaimer"), "disclaimer"))
                choices.append((_("Cancel"), ""))
                self.session.openWithCallback(self.startActualUpgrade,
                                              ChoiceBox,
                                              title=message,
                                              list=choices,
                                              windowTitle=self.title)
            elif self.channellist_only > 0:
                if self.channellist_only == 1:
                    self.setEndMessage(
                        _("Could not find installed channel list."))
                elif self.channellist_only == 2:
                    self.slider.setValue(2)
                    self.opkg.startCmd(OpkgComponent.CMD_REMOVE,
                                       {'package': self.channellist_name})
                    self.channellist_only += 1
                elif self.channellist_only == 3:
                    self.slider.setValue(3)
                    self.opkg.startCmd(OpkgComponent.CMD_INSTALL,
                                       {'package': self.channellist_name})
                    self.channellist_only += 1
                elif self.channellist_only == 4:
                    self.showUpdateCompletedMessage()
                    eDVBDB.getInstance().reloadBouquets()
                    eDVBDB.getInstance().reloadServicelist()
            elif self.error == 0:
                self.showUpdateCompletedMessage()
            else:
                self.activityTimer.stop()
                self.activityslider.setValue(0)
                error = _(
                    "Your receiver might be unusable now. Please consult the manual for further assistance before rebooting your receiver."
                )
                if self.packages == 0:
                    error = _("No updates available. Please try again later.")
                if self.updating:
                    error = _(
                        "Update failed. Your receiver does not have a working internet connection."
                    )
                self.status.setText(_("Error") + " - " + error)
        elif event == OpkgComponent.EVENT_LISTITEM:
            if 'enigma2-plugin-settings-' in param[
                    0] and self.channellist_only > 0:
                self.channellist_name = param[0]
                self.channellist_only = 2
        #print event, "-", param
        pass

    def setEndMessage(self, txt):
        self.slider.setValue(4)
        self.activityTimer.stop()
        self.activityslider.setValue(0)
        self.package.setText(txt)
        self.status.setText(self.oktext)

    def startActualUpgrade(self, answer):
        if not answer or not answer[1]:
            self.close()
            return
        if answer[1] == "cold":
            self.session.open(TryQuitMainloop, retvalue=42)
            self.close()
        elif answer[1] == "channels":
            self.channellist_only = 1
            self.slider.setValue(1)
            self.opkg.startCmd(OpkgComponent.CMD_LIST,
                               args={'installed_only': True})
        elif answer[1] == "commits":
            self.session.openWithCallback(
                boundFunction(self.opkgCallback, OpkgComponent.EVENT_DONE,
                              None), CommitInfo)
        elif answer[1] == "disclaimer":
            self.showDisclaimer(justShow=True)
        elif answer[1] == "showlist":
            text = "\n".join([
                x[0]
                for x in sorted(self.opkg.getFetchedList(), key=lambda d: d[0])
            ])
            self.session.openWithCallback(
                boundFunction(self.opkgCallback,
                              OpkgComponent.EVENT_DONE, None), TextBox, text,
                _("Packages to update"), True)
        elif answer[1] == "log":
            text = open("/home/root/opkgupgrade.log", "r").read()
            self.session.openWithCallback(
                boundFunction(self.opkgCallback,
                              OpkgComponent.EVENT_DONE, None), TextBox, text,
                _("Latest update log"), True)
        else:
            self.opkg.startCmd(OpkgComponent.CMD_UPGRADE,
                               args={'test_only': False})

    def modificationCallback(self, res):
        self.opkg.write(res and "N" or "Y")

    def exit(self):
        if not self.opkg.isRunning():
            if self.packages != 0 and self.error == 0 and self.channellist_only == 0:
                self.session.openWithCallback(
                    self.exitAnswer, MessageBox,
                    _("Update completed. Do you want to reboot your receiver?")
                )
            else:
                self.close()
        else:
            if not self.updating:
                self.close()

    def exitAnswer(self, result):
        if result is not None and result:
            self.session.open(TryQuitMainloop, retvalue=2)
        self.close()

    def __close(self):
        self.opkg.removeCallback(self.opkgCallback)