diff --git a/pythonrewrite/bin/CryptoBox.py b/pythonrewrite/bin/CryptoBox.py index ac74e63..4a3e9b2 100755 --- a/pythonrewrite/bin/CryptoBox.py +++ b/pythonrewrite/bin/CryptoBox.py @@ -113,10 +113,10 @@ class CryptoBoxProps(CryptoBox): def __init__(self, config_file=None): '''read config and fill class variables''' CryptoBox.__init__(self, config_file) - self.__reReadContainerList() + self.reReadContainerList() - def __reReadContainerList(self): + def reReadContainerList(self): self.containers = [] for device in CryptoBoxTools.getAvailablePartitions(): if self.isDeviceAllowed(device): diff --git a/pythonrewrite/bin/CryptoBoxTools.py b/pythonrewrite/bin/CryptoBoxTools.py index a73a659..5a10ecd 100644 --- a/pythonrewrite/bin/CryptoBoxTools.py +++ b/pythonrewrite/bin/CryptoBoxTools.py @@ -18,7 +18,8 @@ def getAvailablePartitions(): if (len(p_details) == 4): "the following code prevents double entries like /dev/hda and /dev/hda1" (p_major, p_minor, p_size, p_device) = p_details - if re.search('^[0-9]*$', p_major) and re.search('^[0-9]*$', p_minor): + ## ignore lines with: invalid minor/major or extend partitions (size=1) + if re.search('^[0-9]*$', p_major) and re.search('^[0-9]*$', p_minor) and (p_size != "1"): p_parent = re.sub('[1-9]?[0-9]$', '', p_device) if p_parent == p_device: if [e for e in ret_list if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]: diff --git a/pythonrewrite/bin/WebInterfaceDataset.py b/pythonrewrite/bin/WebInterfaceDataset.py index fb770a1..65e8f09 100644 --- a/pythonrewrite/bin/WebInterfaceDataset.py +++ b/pythonrewrite/bin/WebInterfaceDataset.py @@ -14,6 +14,7 @@ class WebInterfaceDataset(dict): self.cbox = cbox self.__setConfigValues() self.__setCryptoBoxState() + def setPluginState(self, plugins): @@ -41,18 +42,7 @@ class WebInterfaceDataset(dict): self["Data.CurrentDisk.capacity.percent"] = percent - def __setConfigValues(self): - self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"]) - self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"]) - self["Settings.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"]) - self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"] - self["Settings.Language"] = self.prefs["WebSettings"]["Language"] - self["Settings.DocLang"] = self.prefs["WebSettings"]["DocLanguage"] - self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"] - - - def __setCryptoBoxState(self): - self["Data.Version"] = self.cbox.VERSION + def setContainersState(self): avail_counter = 0 active_counter = 0 for container in self.cbox.getContainerList(): @@ -67,6 +57,20 @@ class WebInterfaceDataset(dict): if isMounted: active_counter += 1 avail_counter += 1 self["Data.activeDisksCount"] = active_counter + + + def __setConfigValues(self): + self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"]) + self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"]) + self["Settings.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"]) + self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"] + self["Settings.Language"] = self.prefs["WebSettings"]["Language"] + self["Settings.DocLang"] = self.prefs["WebSettings"]["DocLanguage"] + self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"] + + + def __setCryptoBoxState(self): + self["Data.Version"] = self.cbox.VERSION for lang in self.cbox.getAvailableLanguages(): self["Data.Languages." + lang] = self.__getLanguageName(lang) ## TODO: open issues: Data.Config.AdminPasswordIsSet diff --git a/pythonrewrite/bin/WebInterfaceSites.py b/pythonrewrite/bin/WebInterfaceSites.py index 04a6e17..988833f 100755 --- a/pythonrewrite/bin/WebInterfaceSites.py +++ b/pythonrewrite/bin/WebInterfaceSites.py @@ -34,6 +34,10 @@ class WebInterfaceSites: def __resetDataset(self): + """this method has to be called at the beginning of every "site" action + important: only at the beginning of an action (to not loose information) + important: for _every_ "site" action (cherrypy is stateful) + """ self.dataset = WebInterfaceDataset.WebInterfaceDataset(self.cbox, self.prefs) @@ -144,8 +148,6 @@ class WebInterfaceSites: self.dataset["Data.Warning"] = "SetVolumeNameFailed" else: self.log.info("successfully renamed volume '%s' to '%s'" % (device, volume_name)) - # reread the dataset - self.__resetDataset() self.dataset.setCurrentDiskState(device) else: self.dataset["Data.Warning"] = "InvalidVolumeName" @@ -188,8 +190,6 @@ class WebInterfaceSites: self.log.warn("failed to mount the device (%s)" % device) else: self.log.info("successfully mounted the container (%s)" % device) - # reread the dataset - self.__resetDataset() self.dataset.setCurrentDiskState(device) else: if self.cbox.getContainerList(): @@ -264,7 +264,6 @@ class WebInterfaceSites: else: self.log.info("successfully initialized device '%s'" % device) # reread the dataset - self.__resetDataset() self.dataset.setCurrentDiskState(device) return self.__render("show_volume") else: @@ -274,8 +273,9 @@ class WebInterfaceSites: return self.__render("show_status") - def test(self): + def test(self, weblang=""): self.__resetDataset() + self.__setWebLang(weblang) return "test passed" @@ -306,7 +306,6 @@ class WebInterfaceSites: else: self.log.info("successfully unmounted the container (%s)" % device) # reread the dataset - self.__resetDataset() self.dataset.setCurrentDiskState(device) else: if self.cbox.getContainerList(): @@ -455,6 +454,9 @@ class WebInterfaceSites: ## add the current state of the plugins to the hdf dataset self.dataset.setPluginState(self.pluginList) + ## update the container information + self.dataset.setContainersState() + hdf = neo_util.HDF() hdf.readFile(hdf_path) self.log.debug(self.dataset) diff --git a/pythonrewrite/lang/de.hdf b/pythonrewrite/lang/de.hdf index 336f873..be13668 100644 --- a/pythonrewrite/lang/de.hdf +++ b/pythonrewrite/lang/de.hdf @@ -8,10 +8,9 @@ Lang { Top = Die CryptoBox Slogan = ... und 1984 war gestern! Init = Initialisierung der CryptoBox - Mount = Aktivierung der Crypto-Daten - Umount = Deaktivierung der Crypto-Daten + Mount = Aktivierung des Containers + Umount = Deaktivierung des Containers Config = Konfiguration der CryptoBox - Log = Protokoll der CryptoBox System = System Status = Status der CryptoBox Volume = Eigenschaften von @@ -31,7 +30,6 @@ Lang { PartitionInfo = Derzeitige Partitionierung der Festplatte: IPAddress = Netzwerk-Adresse (IP) der CryptoBox: TimeOut = Zeitabschaltung des Crypto-Dateisystems (in Minuten): - EmptyLog = Das Logbuch der CryptoBox ist leer. SelectLanguage = Spracheinstellung: RedirectNote = Klicke hier, falls dein Browser die automatische Weiterleitung nicht unterstützt. ProjectHomePage = Projekt-Seite @@ -54,12 +52,11 @@ Lang { DoInit = Initialisierung SaveConfig = Speichere Konfiguration Update = Aktualisieren - Mount = Crypto-Daten aktivieren - Umount = Crypto-Daten deaktivieren + Mount = Container aktivieren + Umount = Container deaktivieren Config = Einstellungen PowerOff = ausschalten ReBoot = neu starten - Protocol = Protokoll anzeigen Documentation = Hilfe Status = Status System = System diff --git a/pythonrewrite/plugins/partition/lang/en.hdf b/pythonrewrite/plugins/partition/lang/en.hdf index f790621..fdd0a27 100644 --- a/pythonrewrite/plugins/partition/lang/en.hdf +++ b/pythonrewrite/plugins/partition/lang/en.hdf @@ -6,9 +6,9 @@ Title.Partition = Disk partitions Button { SelectDevice = Repartition disk - AddPartition = Add another partition - Back = Back - SavePartitions = Save changes + AddPartition = Add + DelPartition = Remove + SavePartitions = Write new partition table AbortPartitions = Cancel } @@ -20,14 +20,33 @@ Text { Ext3 = Ext3 Reiser = Reiser } + PartNum = Id + PartType = Type Size = Size (MB) SelectDevice = Choose a disk for partitioning - NoDevicesAvailable = No suitable disks found - please check your configuration and hardware setup. + WarningMessage = If you continue, you will destroy all data on the choosen disk. Please be careful! +} - -WarningMessage { - InvalidInput { - Title = Invalid input - Text = You entered an invalid value. +SuccessMessage { + Partitioned { + Title = Partitioning complete + Text = The disk was partitioned successfully. + } +} + +WarningMessage { + NoDisksAvailable { + Title = No disks found + Text = No suitable disks found - please check your configuration and hardware setup. + } + + PartitioningFailed { + Title = Partitioning failed + Text = The partitioning of the device failed for some reason - sorry! + } + + DiskIsBusy { + Title = This disk is busy + Text = Please deactivate all containers of this disk before partitioning. } } diff --git a/pythonrewrite/plugins/partition/partition.py b/pythonrewrite/plugins/partition/partition.py index e9305af..dbdf517 100644 --- a/pythonrewrite/plugins/partition/partition.py +++ b/pythonrewrite/plugins/partition/partition.py @@ -28,15 +28,24 @@ def doAction(hdf, cbox, **args): def getStatus(cbox): - #return "%d.%d.%d.%d" % __getCurrentIP(cbox) return "TODO" def __isDeviceValid(device, cbox): + ## TODO: also check for "is device busy" add output a warning if not cbox.isDeviceAllowed(device): return False if not device in CryptoBoxTools.getParentBlockDevices(): return False + return True + + +def __isDeviceBusy(device, cbox): + """check if the device (or one of its partitions) is mounted""" + for c in cbox.getContainerList(): + if re.match(device + "\d*$", c.getDevice()): + if c.isMounted(): return True + return False def __actionSelectDevice(hdf, cbox, args): @@ -48,6 +57,9 @@ def __actionSelectDevice(hdf, cbox, args): hdf["Data.Plugins.partition.BlockDevices.%d" % counter] = a cbox.log.debug("found a suitable block device: %s" % a) counter += 1 + ## there is no disk available + if not block_devices: + hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable" return "select_device" @@ -56,8 +68,10 @@ def __actionAddPartition(hdf, cbox, args): device = args["block_device"] except KeyError: return __actionSelectDevice(hdf, cbox, args) - #FIXME: the following check should obviuosly get reversed - if __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + if not __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + if __isDeviceBusy(device, cbox): + hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy" + return __actionSelectDevice(hdf, cbox, args) size = __getDeviceSize(device) hdf["Data.Plugins.partition.Device"] = device hdf["Data.Plugins.partition.Device.Size"] = size @@ -69,18 +83,49 @@ def __actionAddPartition(hdf, cbox, args): def __actionDelPartition(hdf, cbox, args): try: device = args["block_device"] - except KeyError: + part_num = int(args["del_num"]) + except (TypeError,KeyError): + return __actionSelectDevice(hdf, cbox, args) + if not __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + if __isDeviceBusy(device, cbox): + hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy" return __actionSelectDevice(hdf, cbox, args) - #FIXME: the following check should obviuosly get reversed - if __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) size = __getDeviceSize(device) hdf["Data.Plugins.partition.Device"] = device hdf["Data.Plugins.partition.Device.Size"] = size parts = __getPartitionsFromArgs(args, size) - __setPartitionData(hdf, parts[:-1], size) + ## valid partition number to be deleted? + if part_num < len(parts): + del parts[part_num] + else: + return __actionSelectDevice(hdf, cbox, args) + __setPartitionData(hdf, parts, size) return "set_partitions" +def __actionFinish(hdf, cbox, args): + try: + device = args["block_device"] + except KeyError: + return __actionSelectDevice(hdf, cbox, args) + if not __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + if __isDeviceBusy(device, cbox): + hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy" + return __actionSelectDevice(hdf, cbox, args) + size = __getDeviceSize(device) + parts = __getPartitionsFromArgs(args, size) + if parts: + if not __runFDisk(cbox, device, parts): + hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed" + return __actionAddPartition(hdf, cbox, args) + else: + hdf["Data.Success"] = "Plugins.partition.Partitioned" + cbox.reReadContainerList() + return "form_system" + else: + return __actionSelectDevice(hdf, cbox, args) + + def __setPartitionData(hdf, parts, size): availSize = size i = 0 @@ -126,8 +171,41 @@ def __getDeviceSize(device): elements = f.split() if len(elements) != 4: continue if (int(elements[0]) == major) and (int(elements[1]) == minor): - return int(elements[2]) + return int(elements[2])/1024 except ValueError: pass return 0 + +def __runFDisk(cbox, device, parts): + proc = subprocess.Popen( + shell = False, + stdin = subprocess.PIPE, + stderr = subprocess.PIPE, + args = [ + cbox.prefs["Programs"]["super"], + cbox.prefs["Programs"]["CryptoBoxRootActions"], + "plugin", + os.path.join(os.path.dirname(__file__), "root_action.py"), + "partition", + device]) + import logging + logger = logging.getLogger("CryptoBox") + for line in __getSFDiskLayout(parts): proc.stdin.write(line + "\n") + (output, error) = proc.communicate() + if error: logger.debug("partitioning failed: %s" % error) + return proc.returncode == 0 + + +def __getSFDiskLayout(paramParts): + parts = paramParts[:] + ## first a primary partition + yield ",%d,%s,*" % (parts[0]["size"], PartTypes[parts[0]["type"]]) + del parts[0] + if not parts: return + yield ",,E" # extended container for the rest + yield ";" # empty partition in main table + yield ";" # another empty partition in main table + while parts: + yield ",%d,%s" % (parts[0]["size"], PartTypes[parts[0]["type"]]) + del parts[0] diff --git a/pythonrewrite/plugins/partition/root_action.py b/pythonrewrite/plugins/partition/root_action.py index 1b23a91..96082cf 100755 --- a/pythonrewrite/plugins/partition/root_action.py +++ b/pythonrewrite/plugins/partition/root_action.py @@ -1,10 +1,9 @@ #!/usr/bin/env python2.4 -#TODO: add netmask and gateway - ## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script PLUGIN_TYPE = "cryptobox" +SFDISK_BIN = "/sbin/sfdisk" import subprocess import re @@ -12,22 +11,39 @@ import sys import os +def __partitionDevice(device): + ## do not use the "-q" flag, as this spoils the exit code of sfdisk (seems to be a bug) + proc = subprocess.Popen( + shell = False, + args = [ + SFDISK_BIN, + "-uM", + device]) + proc.communicate() + return proc.returncode == 0 + + if __name__ == "__main__": args = sys.argv[1:] self_bin =sys.argv[0] - if len(args) > 1: + if len(args) > 2: sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args)) sys.exit(1) if len(args) == 0: sys.stderr.write("%s: no argument supplied\n" % self_bin) sys.exit(1) - - proc = subprocess.Popen( - shell = False, - args = [IFCONFIG_BIN, IFACE, args[0]]) - proc.communicate() - sys.exit(proc.returncode) + + if args[0] == "partition": + if len(args) < 2: + sys.stderr.write("%s: not enough arguments (%s)\n" % (self_bin, args)) + sys.exit(1) + if __partitionDevice(args[1]): + sys.exit(0) + else: + sys.exit(1) + else: + sys.exit(1) diff --git a/pythonrewrite/plugins/partition/select_device.cs b/pythonrewrite/plugins/partition/select_device.cs index 9b982a9..8da649a 100644 --- a/pythonrewrite/plugins/partition/select_device.cs +++ b/pythonrewrite/plugins/partition/select_device.cs @@ -13,15 +13,17 @@
++ +
+ - - - - + + diff --git a/pythonrewrite/plugins/partition/set_partitions.cs b/pythonrewrite/plugins/partition/set_partitions.cs index ad2dc96..2774d76 100644 --- a/pythonrewrite/plugins/partition/set_partitions.cs +++ b/pythonrewrite/plugins/partition/set_partitions.cs @@ -2,32 +2,56 @@ --
- -
++ | + | + | + |
---|---|---|---|
+ | + | + | + - + + + + | +
+ | + | + | + + | +
+ +
+ diff --git a/pythonrewrite/templates/nav.cs b/pythonrewrite/templates/nav.cs index 882c7ed..c430361 100644 --- a/pythonrewrite/templates/nav.cs +++ b/pythonrewrite/templates/nav.cs @@ -1,25 +1,11 @@ - - + + - - - - + + - - diff --git a/pythonrewrite/templates/show_volumes.cs b/pythonrewrite/templates/show_volumes.cs index 7dc400e..088f72b 100644 --- a/pythonrewrite/templates/show_volumes.cs +++ b/pythonrewrite/templates/show_volumes.cs @@ -6,7 +6,9 @@ -