Harddisk: Code cleanup, add ext3-to-ext4 conversion option
authorMike Looijmans <milo-software@users.sourceforge.net>
Sat, 16 Jul 2011 14:01:55 +0000 (16:01 +0200)
committerMike Looijmans <milo-software@users.sourceforge.net>
Sat, 16 Jul 2011 14:01:55 +0000 (16:01 +0200)
Remove obsolete code from Harddisk.py
Re-organize the harddisk setup to offer more than just two options
Add a recipe for ext3 to ext4 conversion.

Haven't found a nice way to detect already-ext4 disks, but running it
twice appears to have no ill effects, and has the side effect of rebuilding
your directory indices.

data/menu.xml
lib/python/Components/Harddisk.py
lib/python/Screens/HarddiskSetup.py

index 21144db..9ccb536 100755 (executable)
@@ -59,6 +59,7 @@
                                        <item level="1" entryID="harddisk_setup"><setup id="harddisk"/></item>
                                        <item level="0" text="Initialization" entryID="harddisk_init"><screen module="HarddiskSetup" screen="HarddiskSelection"/></item>
                                        <item level="0" text="Filesystem Check" entryID="harddisk_check"><screen module="HarddiskSetup" screen="HarddiskFsckSelection"/></item>
+                                       <item level="0" text="Convert filesystem ext3 to ext4" entryID="harddisk_convert"><screen module="HarddiskSetup" screen="HarddiskConvertExt4Selection"/></item>
                                </menu>
                                <!--<item text="Remote Control"><setup id="rc" /></item>-->
                                <!--<item text="OSD"><setup id="osd" /></item>-->
index c3ed952..b9ab5ad 100644 (file)
@@ -203,19 +203,8 @@ class Harddisk:
                return (res >> 8)
 
        def mkfs(self):
-               if isFileSystemSupported("ext4"):
-                       cmd = "mkfs.ext4 "
-               else:
-                       cmd = "mkfs.ext3 "
-               size = self.diskSize()
-               if size > 16 * 1024:
-                       cmd += "-T largefile -O sparse_super "
-               elif size > 2 * 1024:
-                       cmd += "-T largefile -N %d " % (size * 32)
-               cmd += "-m0 -O dir_index " + self.partitionPath("1")
-               print "[Harddisk]", cmd
-               res = system(cmd)
-               return (res >> 8)
+               # No longer supported, use createInitializeJob instead
+               return 1 
 
        def mount(self):
                # try mounting through fstab first
@@ -257,15 +246,8 @@ class Harddisk:
                return 0
 
        def fsck(self):
-               # We autocorrect any failures
-               # TODO: we could check if the fs is actually ext3
-               if self.mount_device is None:
-                       dev = self.partitionPath("1")
-               else:
-                       dev = self.mount_device
-               cmd = "fsck.ext3 -f -p " + dev
-               res = system(cmd)
-               return (res >> 8)
+               # No longer supported, use createCheckJob instead
+               return 1 
 
        def killPartitionTable(self):
                zero = 512 * '\0'
@@ -350,47 +332,12 @@ class Harddisk:
                return job
 
        def initialize(self):
-               self.unmount()
-
-               # Udev tries to mount the partition immediately if there is an
-               # old filesystem on it when fdisk reloads the partition table.
-               # To prevent that, we overwrite the first 3 sectors of the
-               # partition, if the partition existed before. That's enough for
-               # ext3 at least.
-               self.killPartition("1")
-
-               if self.createPartition() != 0:
-                       return -1
-
-               if self.mkfs() != 0:
-                       return -2
-
-               if self.mount() != 0:
-                       return -3
-
-               if self.createMovieFolder() != 0:
-                       return -4
-
-               return 0
+               # no longer supported
+               return -5
 
        def check(self):
-               self.unmount()
-
-               res = self.fsck()
-               if res & 2 == 2:
-                       return -6
-
-               if res & 4 == 4:
-                       return -7
-
-               if res != 0 and res != 1:
-                       # A sum containing 1 will also include a failure
-                       return -5
-
-               if self.mount() != 0:
-                       return -3
-
-               return 0
+               # no longer supported
+               return -5
                
        def createCheckJob(self):
                job = Task.Job(_("Checking Filesystem..."))
@@ -411,6 +358,47 @@ class Harddisk:
                task.check = self.mountDevice
                return job
 
+       def createExt4ConversionJob(self):
+               if not isFileSystemSupported('ext4'):
+                       raise Exception, _("You system does not support ext4")
+               job = Task.Job(_("Convert ext3 to ext4..."))
+               if not path.exists('/sbin/tune2fs'):
+                       task = Task.LoggingTask(job, "update packages")
+                       task.setTool('opkg')
+                       task.args.append('update')
+                       task = Task.LoggingTask(job, "Install e2fsprogs-tune2fs")
+                       task.setTool('opkg')
+                       task.args.append('install')
+                       task.args.append('e2fsprogs-tune2fs')
+               if self.findMount():
+                       # Create unmount task if it was not mounted
+                       UnmountTask(job, self)
+                       dev = self.mount_device
+               else:
+                       # otherwise, assume there is one partition
+                       dev = self.partitionPath("1")
+               task = Task.LoggingTask(job, "fsck")
+               task.setTool('fsck.ext3')
+               task.args.append('-f')
+               task.args.append('-p')
+               task.args.append(dev)
+               task = Task.LoggingTask(job, "tune2fs")
+               task.setTool('tune2fs')
+               task.args.append('-O')
+               task.args.append('extents,uninit_bg,dir_index')
+               task.args.append(dev)
+               task = Task.LoggingTask(job, "fsck")
+               task.setTool('fsck.ext4')
+               task.postconditions = [] # ignore result, it will always "fail"
+               task.args.append('-f')
+               task.args.append('-p')
+               task.args.append('-D')
+               task.args.append(dev)
+               MountTask(job, self)
+               task = Task.ConditionTask(job, _("Wait for mount"))
+               task.check = self.mountDevice
+               return job
+
        def getDeviceDir(self):
                return self.dev_path
 
index 2d2d549..5d10e24 100644 (file)
@@ -12,74 +12,39 @@ class HarddiskSetup(Screen):
        HARDDISK_INITIALIZE = 1
        HARDDISK_CHECK = 2
 
-       def __init__(self, session, hdd, type = None):
+       def __init__(self, session, hdd, action, text, question):
                Screen.__init__(self, session)
-               self.hdd = hdd
-
-               if type not in (self.HARDDISK_INITIALIZE, self.HARDDISK_CHECK):
-                       self.type = self.HARDDISK_INITIALIZE
-               else:
-                       self.type = type
-
+               self.action = action
+               self.question = question
                self["model"] = Label(_("Model: ") + hdd.model())
                self["capacity"] = Label(_("Capacity: ") + hdd.capacity())
                self["bus"] = Label(_("Bus: ") + hdd.bus())
                self["initialize"] = Pixmap()
-
-               if self.type == self.HARDDISK_INITIALIZE:
-                       text = _("Initialize")
-               else:
-                       text = _("Check")
                self["initializetext"] = Label(text)
-
                self["actions"] = ActionMap(["OkCancelActions"],
                {
                        "ok": self.close,
                        "cancel": self.close
                })
-               
                self["shortcuts"] = ActionMap(["ShortcutActions"],
                {
                        "red": self.hddQuestion
                })
 
-       def hddReady(self, result):
-               print "Result: " + str(result)
-               if result is None:
-                       # todo: Notify about background task?
-                       self.close()
-               elif (result != 0):
-                       if self.type == self.HARDDISK_INITIALIZE:
-                               message = _("Unable to initialize device.\nError: ")
-                       else:
-                               message = _("Unable to complete filesystem check.\nError: ")
-                       self.session.open(MessageBox, message + str(self.hdd.errorList[0 - result]), MessageBox.TYPE_ERROR)
-               else:
-                       self.close()
-
        def hddQuestion(self):
-               if self.type == self.HARDDISK_INITIALIZE:
-                       message = _("Do you really want to initialize the device?\nAll data on the disk will be lost!")
-               else:
-                       message = _("Do you really want to check the filesystem?\nThis could take lots of time!")
-               message += "\n" + _("You can continue watching TV etc. while this is running.")
+               message = self.question + "\n" + _("You can continue watching TV etc. while this is running.")
                self.session.openWithCallback(self.hddConfirmed, MessageBox, message)
 
        def hddConfirmed(self, confirmed):
                if not confirmed:
                        return
-               print "this will start either the initialize or the fsck now!"
-               if self.type == self.HARDDISK_INITIALIZE:
-                       Components.Task.job_manager.AddJob(self.hdd.createInitializeJob())
-               else:
-                       Components.Task.job_manager.AddJob(self.hdd.createCheckJob())
+               Components.Task.job_manager.AddJob(self.action())
                self.close()
 
 
 class HarddiskSelection(Screen):
        def __init__(self, session):
                Screen.__init__(self, session)
-               
                if harddiskmanager.HDDCount() == 0:
                        tlist = []
                        tlist.append((_("no storage devices found"), 0))
@@ -93,10 +58,16 @@ class HarddiskSelection(Screen):
                        "cancel": self.close
                })
 
+       def doIt(self, selection):
+               self.session.openWithCallback(self.close, HarddiskSetup, selection,
+                        action=selection.createInitializeJob,
+                        text=_("Initialize"),
+                        question=_("Do you really want to initialize the device?\nAll data on the disk will be lost!"))
+       
        def okbuttonClick(self):
                selection = self["hddlist"].getCurrent()
                if selection[1] != 0:
-                       self.session.openWithCallback(self.close, HarddiskSetup, selection[1], HarddiskSetup.HARDDISK_INITIALIZE)
+                       self.doIt(selection[1])
 
 # This is actually just HarddiskSelection but with correct type
 class HarddiskFsckSelection(HarddiskSelection):
@@ -104,7 +75,19 @@ class HarddiskFsckSelection(HarddiskSelection):
                HarddiskSelection.__init__(self, session)
                self.skinName = "HarddiskSelection"
 
-       def okbuttonClick(self):
-               selection = self["hddlist"].getCurrent()
-               if selection[1] != 0:
-                       self.session.open(HarddiskSetup, selection[1], HarddiskSetup.HARDDISK_CHECK)
+       def doIt(self, selection):
+               self.session.openWithCallback(self.close, HarddiskSetup, selection,
+                        action=selection.createCheckJob,
+                        text=_("Check"),
+                        question=_("Do you really want to check the filesystem?\nThis could take lots of time!"))
+
+class HarddiskConvertExt4Selection(HarddiskSelection):
+       def __init__(self, session):
+               HarddiskSelection.__init__(self, session)
+               self.skinName = "HarddiskSelection"
+
+       def doIt(self, selection):
+               self.session.openWithCallback(self.close, HarddiskSetup, selection,
+                        action=selection.createExt4ConversionJob,
+                        text=_("Convert ext3 to ext4"),
+                        question=_("Do you really want to convert the filesystem?\nYou cannot go back!"))