plugin interface changed: now we use classes (inherited by CryptoBoxPlugin) instead of plain scripts
added some log entries use threading module instead of "fork" for background formatting redirection for "network" plugin fixed empty return value of plugins defaults to plugin overview page
This commit is contained in:
parent
52ccaeb530
commit
56e954d1c4
11 changed files with 545 additions and 436 deletions
|
@ -1,49 +1,64 @@
|
||||||
import subprocess
|
import CryptoBoxPlugin
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def doAction(hdf, cbox, store=None, year=0, month=0, day=0, hour=0, minute=0):
|
class date(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||||
import datetime
|
|
||||||
__prepareFormData(hdf, cbox)
|
def doAction(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
|
||||||
if store:
|
import datetime
|
||||||
try:
|
if store:
|
||||||
year, month, day = int(year), int(month), int(day)
|
try:
|
||||||
hour, minute = int(hour), int(minute)
|
year, month, day = int(year), int(month), int(day)
|
||||||
new_date = datetime.datetime(year, month, day, hour, minute)
|
hour, minute = int(hour), int(minute)
|
||||||
except ValueError:
|
new_date = datetime.datetime(year, month, day, hour, minute)
|
||||||
hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
except ValueError:
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
||||||
|
self.__prepareFormData()
|
||||||
|
return "form_date"
|
||||||
|
date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
|
||||||
|
if self.__setDate(date):
|
||||||
|
self.cbox.log.info("changed date to: %s" % date)
|
||||||
|
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
## a failure should usually be an invalid date (we do not check it really)
|
||||||
|
self.cbox.log.info("failed to set date: %s" % date)
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
||||||
|
self.__prepareFormData()
|
||||||
|
return "form_date"
|
||||||
|
else:
|
||||||
|
self.__prepareFormData()
|
||||||
|
return "form_date"
|
||||||
|
|
||||||
|
|
||||||
|
def getStatus(self):
|
||||||
|
return str(self.__getCurrentDate())
|
||||||
|
|
||||||
|
|
||||||
|
def __prepareFormData(self):
|
||||||
|
date = self.__getCurrentDate()
|
||||||
|
self.hdf[self.hdf_prefix + "year"] = date.year
|
||||||
|
self.hdf[self.hdf_prefix + "month"] = date.month
|
||||||
|
self.hdf[self.hdf_prefix + "day"] = date.day
|
||||||
|
self.hdf[self.hdf_prefix + "hour"] = date.hour
|
||||||
|
self.hdf[self.hdf_prefix + "minute"] = date.minute
|
||||||
|
|
||||||
|
|
||||||
|
def __getCurrentDate(self):
|
||||||
|
import datetime
|
||||||
|
return datetime.datetime(2000,1,1).now()
|
||||||
|
|
||||||
|
|
||||||
|
def __setDate(self, date):
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
args = [
|
args = [
|
||||||
cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
os.path.join(self.pluginDir, "root_action.py"),
|
||||||
"%02d%02d%02d%02d%d" % (month, day, hour, minute, year)])
|
date])
|
||||||
proc.communicate()
|
proc.communicate()
|
||||||
if proc.returncode == 0:
|
return proc.returncode == 0
|
||||||
return "form_system"
|
|
||||||
else:
|
|
||||||
hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
|
||||||
return "form_date"
|
|
||||||
else:
|
|
||||||
return "form_date"
|
|
||||||
|
|
||||||
|
|
||||||
def getStatus(cbox):
|
|
||||||
return str(__getCurrentDate())
|
|
||||||
|
|
||||||
|
|
||||||
def __prepareFormData(hdf, cbox):
|
|
||||||
date = __getCurrentDate()
|
|
||||||
hdf["Data.Plugins.date.year"] = date.year
|
|
||||||
hdf["Data.Plugins.date.month"] = date.month
|
|
||||||
hdf["Data.Plugins.date.day"] = date.day
|
|
||||||
hdf["Data.Plugins.date.hour"] = date.hour
|
|
||||||
hdf["Data.Plugins.date.minute"] = date.minute
|
|
||||||
|
|
||||||
|
|
||||||
def __getCurrentDate():
|
|
||||||
import datetime
|
|
||||||
return datetime.datetime(2000,1,1).now()
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,14 @@ Text.Months {
|
||||||
12 = December
|
12 = December
|
||||||
}
|
}
|
||||||
|
|
||||||
WarningMessage.InvalidDate {
|
SuccessMessage.DateChanged {
|
||||||
Title = Invalid value
|
Title = Date changed
|
||||||
Text = An invalid value for date or time was supplied. Please try again.
|
Text = The date was changed successfully.
|
||||||
|
}
|
||||||
|
|
||||||
|
WarningMessage {
|
||||||
|
InvalidDate {
|
||||||
|
Title = Invalid value
|
||||||
|
Text = An invalid value for date or time was supplied. Please try again.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
|
import CryptoBoxPlugin
|
||||||
|
|
||||||
def doAction(hdf, cbox):
|
class logs(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||||
__prepareFormData(hdf,cbox)
|
|
||||||
return "show_log"
|
def doAction(self):
|
||||||
|
self.__prepareFormData()
|
||||||
|
return "show_log"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(cbox):
|
def getStatus(self):
|
||||||
return "%s:%s:%s" % (
|
return "%s:%s:%s" % (
|
||||||
cbox.prefs["Log"]["Level"],
|
self.cbox.prefs["Log"]["Level"],
|
||||||
cbox.prefs["Log"]["Destination"],
|
self.cbox.prefs["Log"]["Destination"],
|
||||||
cbox.prefs["Log"]["Details"])
|
self.cbox.prefs["Log"]["Details"])
|
||||||
|
|
||||||
|
|
||||||
def __prepareFormData(hdf, cbox):
|
def __prepareFormData(self):
|
||||||
hdf["Data.Plugins.logs.Content"] = __getLogContent(cbox)
|
self.hdf[self.hdf_prefix + "Content"] = self.__getLogContent()
|
||||||
|
|
||||||
|
|
||||||
def __getLogContent(cbox, lines=30, maxSize=2000):
|
def __getLogContent(self, lines=30, maxSize=2000):
|
||||||
return "<br/>".join(cbox.getLogData(lines, maxSize))
|
return "<br/>".join(self.cbox.getLogData(lines, maxSize))
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ Rank = 30
|
||||||
|
|
||||||
Title.Network = Network settings
|
Title.Network = Network settings
|
||||||
|
|
||||||
Button.Network = Update settings
|
Button.Network = Update network settings
|
||||||
|
|
||||||
Text.IP = Network address
|
Text.IP = Network address
|
||||||
|
|
||||||
|
|
|
@ -1,71 +1,110 @@
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import imp
|
|
||||||
import os
|
import os
|
||||||
|
import CryptoBoxPlugin
|
||||||
|
|
||||||
|
## specify (in seconds), how long we should wait before redirecting and ip change
|
||||||
|
REDIRECT_DELAY=20
|
||||||
|
CHANGE_IP_DELAY=5
|
||||||
|
|
||||||
def doAction(hdf, cbox, store=None, ip1="", ip2="", ip3="", ip4=""):
|
class network(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||||
__prepareFormData(hdf, cbox)
|
|
||||||
if store:
|
def doAction(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4=""):
|
||||||
try:
|
## if we were redirected, then we should display the default page
|
||||||
for ip_in in (ip1, ip2, ip3, ip4):
|
if redirected == "1":
|
||||||
if (int(ip_in) < 0) or (int(ip_in) > 255):
|
return None
|
||||||
cbox.log.debug("invalid IP supplied: %s" % str((ip1,ip2,ip3,ip4)))
|
## request for IP change?
|
||||||
raise ValueError
|
if store:
|
||||||
ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
|
try:
|
||||||
except ValueError:
|
for ip_in in (ip1, ip2, ip3, ip4):
|
||||||
hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
if (int(ip_in) < 0) or (int(ip_in) > 255):
|
||||||
return "form_system"
|
self.cbox.log.info("invalid IP supplied: %s" % str((ip1,ip2,ip3,ip4)))
|
||||||
if __setIP(cbox, ip):
|
raise ValueError
|
||||||
hdf["Data.Success"] = "Plugins.network.IPChanged"
|
ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
|
||||||
hdf["Data.Redirect.URL"] = ""
|
except ValueError:
|
||||||
hdf["Data.Redirect.Delay"] = 30
|
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
||||||
return "form_system"
|
return None
|
||||||
|
if self.__setIP(ip):
|
||||||
|
self.cbox.log.info("the IP was successfully changed: %s" % ip)
|
||||||
|
self.hdf["Data.Success"] = "Plugins.network.IPChanged"
|
||||||
|
self.hdf["Data.Redirect.URL"] = self.__getRedirectDestination(ip)
|
||||||
|
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
self.cbox.log.warn("failed to change IP address to: %s" % ip)
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
||||||
|
self.__prepareFormData()
|
||||||
|
return "form_network"
|
||||||
else:
|
else:
|
||||||
hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
## just show the form
|
||||||
|
self.__prepareFormData()
|
||||||
return "form_network"
|
return "form_network"
|
||||||
else:
|
|
||||||
return "form_network"
|
|
||||||
|
|
||||||
|
|
||||||
def getStatus(cbox):
|
def getStatus(self):
|
||||||
return "%d.%d.%d.%d" % __getCurrentIP(cbox)
|
return "%d.%d.%d.%d" % self.__getCurrentIP()
|
||||||
|
|
||||||
|
|
||||||
def __prepareFormData(hdf, cbox):
|
def __getRedirectDestionation(self, ip):
|
||||||
(oc1, oc2, oc3, oc4) = __getCurrentIP(cbox)
|
import cherrypy
|
||||||
hdf["Data.Plugins.network.ip.oc1"] = oc1
|
req = cherrypy.request
|
||||||
hdf["Data.Plugins.network.ip.oc2"] = oc2
|
dest = ip
|
||||||
hdf["Data.Plugins.network.ip.oc3"] = oc3
|
base_parts = req.base.split(":")
|
||||||
hdf["Data.Plugins.network.ip.oc4"] = oc4
|
if len(base_parts) == 3:
|
||||||
|
dest += ":%s" % base_parts[2]
|
||||||
|
return dest
|
||||||
|
|
||||||
|
|
||||||
def __getCurrentIP(cbox):
|
def __prepareFormData(self):
|
||||||
root_action_plug = imp.load_source("root_action", os.path.join(os.path.dirname(__file__), "root_action.py"))
|
(oc1, oc2, oc3, oc4) = self.__getCurrentIP()
|
||||||
proc = subprocess.Popen(
|
self.hdf[self.hdf_prefix + "ip.oc1"] = oc1
|
||||||
shell = False,
|
self.hdf[self.hdf_prefix + "ip.oc2"] = oc2
|
||||||
stdout = subprocess.PIPE,
|
self.hdf[self.hdf_prefix + "ip.oc3"] = oc3
|
||||||
args = [
|
self.hdf[self.hdf_prefix + "ip.oc4"] = oc4
|
||||||
root_action_plug.IFCONFIG_BIN,
|
|
||||||
root_action_plug.IFACE])
|
|
||||||
(output, error) = proc.communicate()
|
|
||||||
if proc.returncode != 0: return (0,0,0,0)
|
|
||||||
match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',output)
|
|
||||||
if match:
|
|
||||||
return tuple([int(e) for e in match.groups()])
|
|
||||||
else:
|
|
||||||
return (0,0,0,0)
|
|
||||||
|
|
||||||
|
|
||||||
def __setIP(cbox, ip):
|
def __getCurrentIP(self):
|
||||||
proc = subprocess.Popen(
|
import re
|
||||||
shell = False,
|
import imp
|
||||||
args = [
|
## load some values from the root_action.py script
|
||||||
cbox.prefs["Programs"]["super"],
|
root_action_plug = imp.load_source("root_action", os.path.join(self.pluginDir, "root_action.py"))
|
||||||
cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
## get the current IP of the network interface
|
||||||
"plugin",
|
proc = subprocess.Popen(
|
||||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
shell = False,
|
||||||
ip])
|
stdout = subprocess.PIPE,
|
||||||
proc.communicate()
|
args = [
|
||||||
return proc.returncode == 0
|
root_action_plug.IFCONFIG_BIN,
|
||||||
|
root_action_plug.IFACE])
|
||||||
|
(output, error) = proc.communicate()
|
||||||
|
if proc.returncode != 0: return (0,0,0,0)
|
||||||
|
## this regex matches the four numbers of the IP
|
||||||
|
match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',output)
|
||||||
|
if match:
|
||||||
|
## use the previously matched numbers
|
||||||
|
return tuple([int(e) for e in match.groups()])
|
||||||
|
else:
|
||||||
|
return (0,0,0,0)
|
||||||
|
|
||||||
|
|
||||||
|
def __setIP(self, ip):
|
||||||
|
import threading
|
||||||
|
## call the root_action script after some seconds - so we can deliver the page before
|
||||||
|
def delayedIPchange():
|
||||||
|
import time
|
||||||
|
time.sleep(CHANGE_IP_DELAY)
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
shell = False,
|
||||||
|
args = [
|
||||||
|
self.cbox.prefs["Programs"]["super"],
|
||||||
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
|
"plugin",
|
||||||
|
os.path.join(self.pluginDir, "root_action.py"),
|
||||||
|
ip])
|
||||||
|
proc.communicate()
|
||||||
|
return
|
||||||
|
thread = threading.Thread()
|
||||||
|
thread.run = delayedIPchange
|
||||||
|
thread.setDaemon(True)
|
||||||
|
thread.start()
|
||||||
|
# TODO: how could we guess, if it failed?
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ Text {
|
||||||
Size = Size (MB)
|
Size = Size (MB)
|
||||||
SelectDevice = Choose a disk for partitioning
|
SelectDevice = Choose a disk for partitioning
|
||||||
WarningMessage = If you continue, you will destroy all data on the choosen disk. Please be careful!
|
WarningMessage = If you continue, you will destroy all data on the choosen disk. Please be careful!
|
||||||
|
ProgressInfo = Progress of formatting:
|
||||||
}
|
}
|
||||||
|
|
||||||
SuccessMessage {
|
SuccessMessage {
|
||||||
|
|
|
@ -2,308 +2,328 @@ import subprocess
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import CryptoBoxTools
|
import CryptoBoxTools
|
||||||
|
import CryptoBoxPlugin
|
||||||
|
|
||||||
PartTypes = {
|
class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||||
"windows" : ["0xC", "vfat"],
|
|
||||||
"linux" : ["L", "ext3"]}
|
|
||||||
|
|
||||||
ConfigPartition = {
|
PartTypes = {
|
||||||
"size" : 5, # size of configuration partition (if necessary) in MB
|
"windows" : ["0xC", "vfat"],
|
||||||
"type" : "L",
|
"linux" : ["L", "ext3"]}
|
||||||
"fs" : "ext2"}
|
|
||||||
|
|
||||||
logger = logging.getLogger("CryptoBox")
|
ConfigPartition = {
|
||||||
|
"size" : 5, # size of configuration partition (if necessary) in MB
|
||||||
|
"type" : "L",
|
||||||
|
"fs" : "ext2"}
|
||||||
|
|
||||||
|
|
||||||
def doAction(hdf, cbox, **args):
|
def doAction(self, **args):
|
||||||
try:
|
## retrieve some values from 'args' - defaults are empty
|
||||||
step = args["step"]
|
self.withConfigPartition = self.__isWithConfigPartition(args)
|
||||||
del args["step"]
|
self.device = self.__getSelectedDevice(args)
|
||||||
except KeyError:
|
self.deviceSize = self.__getAvailableDeviceSize(self.device)
|
||||||
step = "select_device"
|
|
||||||
if step == "add_partition":
|
|
||||||
return __actionAddPartition(hdf, cbox, args)
|
|
||||||
if step == "del_partition":
|
|
||||||
return __actionDelPartition(hdf, cbox, args)
|
|
||||||
elif step == "finish":
|
|
||||||
return __actionFinish(hdf, cbox, args)
|
|
||||||
else: # for "select_device" and for invalid targets
|
|
||||||
return __actionSelectDevice(hdf, cbox, args)
|
|
||||||
|
|
||||||
|
|
||||||
def getStatus(cbox):
|
|
||||||
return "TODO"
|
|
||||||
|
|
||||||
|
|
||||||
def __isDeviceValid(device, cbox):
|
|
||||||
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"""
|
|
||||||
# TODO: the config partition is ignored, as it is not part of the container list - that is not good
|
|
||||||
import re
|
|
||||||
for c in cbox.getContainerList():
|
|
||||||
if re.match(device + "\d*$", c.getDevice()):
|
|
||||||
if c.isMounted(): return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def __actionSelectDevice(hdf, cbox, args):
|
|
||||||
block_devices = [e
|
|
||||||
for e in CryptoBoxTools.getParentBlockDevices()
|
|
||||||
if cbox.isDeviceAllowed(e)]
|
|
||||||
counter = 0
|
|
||||||
for a in block_devices:
|
|
||||||
hdf["Data.Plugins.partition.BlockDevices.%d" % counter] = a
|
|
||||||
cbox.log.debug("found a suitable block device: %s" % a)
|
|
||||||
counter += 1
|
|
||||||
if __withConfigPartition(args):
|
|
||||||
hdf["Data.Plugins.partition.CreateConfigPartition"] = "1"
|
|
||||||
## there is no disk available
|
|
||||||
if not block_devices:
|
|
||||||
hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable"
|
|
||||||
return "select_device"
|
|
||||||
|
|
||||||
|
|
||||||
def __actionAddPartition(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 = __getAvailableDeviceSize(device, __withConfigPartition(args))
|
|
||||||
hdf["Data.Plugins.partition.Device"] = device
|
|
||||||
hdf["Data.Plugins.partition.Device.Size"] = size
|
|
||||||
parts = __getPartitionsFromArgs(hdf, args, size)
|
|
||||||
__setPartitionData(hdf, parts, size, __withConfigPartition(args))
|
|
||||||
return "set_partitions"
|
|
||||||
|
|
||||||
|
|
||||||
def __actionDelPartition(hdf, cbox, args):
|
|
||||||
try:
|
|
||||||
device = args["block_device"]
|
|
||||||
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)
|
|
||||||
size = __getAvailableDeviceSize(device, __withConfigPartition(args))
|
|
||||||
hdf["Data.Plugins.partition.Device"] = device
|
|
||||||
hdf["Data.Plugins.partition.Device.Size"] = size
|
|
||||||
parts = __getPartitionsFromArgs(hdf, args, 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, __withConfigPartition(args))
|
|
||||||
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 = __getAvailableDeviceSize(device, __withConfigPartition(args))
|
|
||||||
parts = __getPartitionsFromArgs(hdf, args, size)
|
|
||||||
if parts:
|
|
||||||
if not __runFDisk(cbox, device, parts, __withConfigPartition(args)):
|
|
||||||
hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
|
||||||
return __actionAddPartition(hdf, cbox, args)
|
|
||||||
else:
|
|
||||||
if __formatPartitions(cbox, device, parts, __withConfigPartition(args)):
|
|
||||||
hdf["Data.Success"] = "Plugins.partition.Partitioned"
|
|
||||||
else:
|
|
||||||
hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
|
|
||||||
cbox.reReadContainerList()
|
|
||||||
return "form_system"
|
|
||||||
else:
|
|
||||||
return __actionSelectDevice(hdf, cbox, args)
|
|
||||||
|
|
||||||
|
|
||||||
def __setPartitionData(hdf, parts, size, withConfigPartition):
|
|
||||||
availSize = size
|
|
||||||
i = 0
|
|
||||||
for part in parts:
|
|
||||||
logger.debug(part)
|
|
||||||
hdf["Data.Plugins.partition.Parts.%d.Size" % i] = part["size"]
|
|
||||||
hdf["Data.Plugins.partition.Parts.%d.Type" % i] = part["type"]
|
|
||||||
availSize -= part["size"]
|
|
||||||
i += 1
|
|
||||||
hdf["Data.Plugins.partition.availSize"] = availSize
|
|
||||||
if withConfigPartition:
|
|
||||||
hdf["Data.Plugins.partition.CreateConfigPartition"] = "1"
|
|
||||||
for t in PartTypes.keys():
|
|
||||||
hdf["Data.Plugins.partition.Types.%s" % t] = t
|
|
||||||
|
|
||||||
|
|
||||||
def __getPartitionsFromArgs(hdf, args, maxSize):
|
|
||||||
parts = []
|
|
||||||
done = False
|
|
||||||
availSize = maxSize
|
|
||||||
i = -1
|
|
||||||
while not done:
|
|
||||||
i += 1
|
|
||||||
try:
|
try:
|
||||||
size = int(args["part%d_size" % i])
|
step = args["step"]
|
||||||
partType = args["part%d_type" % i]
|
del args["step"]
|
||||||
if int(size) > availSize:
|
|
||||||
hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
|
|
||||||
continue
|
|
||||||
if int(size) < 10:
|
|
||||||
hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
|
|
||||||
continue
|
|
||||||
if not partType in PartTypes.keys(): continue
|
|
||||||
parts.append({"size":size, "type":partType})
|
|
||||||
availSize -= size
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
done = True
|
step = "select_device"
|
||||||
return parts
|
## no (or invalid) device was supplied
|
||||||
|
if not self.device:
|
||||||
|
step == "select_device"
|
||||||
|
if step == "add_partition":
|
||||||
|
return self.__actionAddPartition(args)
|
||||||
|
if step == "del_partition":
|
||||||
|
return self.__actionDelPartition(args)
|
||||||
|
elif step == "finish":
|
||||||
|
return self.__actionFinish(args)
|
||||||
|
else: # for "select_device" and for invalid targets
|
||||||
|
return self.__actionSelectDevice(args)
|
||||||
|
|
||||||
|
|
||||||
def __getAvailableDeviceSize(device, withConfigPartition):
|
def getStatus(self):
|
||||||
"""calculate the available size (MB) of the device
|
return "%s / %s / %s" % (self.device, self.deviceSize, self.withConfigPartition)
|
||||||
also consider a (possible) configuration partition"""
|
|
||||||
rdev = os.stat(device).st_rdev
|
|
||||||
minor = os.minor(rdev)
|
def __getSelectedDevice(self, args):
|
||||||
major = os.major(rdev)
|
|
||||||
for f in file("/proc/partitions"):
|
|
||||||
try:
|
try:
|
||||||
elements = f.split()
|
device = args["block_device"]
|
||||||
if len(elements) != 4: continue
|
except KeyError:
|
||||||
if (int(elements[0]) == major) and (int(elements[1]) == minor):
|
return None
|
||||||
deviceSize = int(elements[2])/1024
|
if not self.__isDeviceValid(device):
|
||||||
if withConfigPartition: deviceSize -= ConfigPartition["size"]
|
return None
|
||||||
return deviceSize
|
if self.__isDeviceBusy(device):
|
||||||
except ValueError:
|
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
|
||||||
pass
|
return None
|
||||||
return 0
|
return device
|
||||||
|
|
||||||
|
|
||||||
def __withConfigPartition(args):
|
def __isDeviceValid(self, device):
|
||||||
try:
|
if not device:
|
||||||
if args["create_config_partition"]:
|
return False
|
||||||
createConfig = True
|
if not self.cbox.isDeviceAllowed(device):
|
||||||
|
return False
|
||||||
|
if not device in CryptoBoxTools.getParentBlockDevices():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def __isDeviceBusy(self, device):
|
||||||
|
"""check if the device (or one of its partitions) is mounted"""
|
||||||
|
# TODO: the config partition is ignored, as it is not part of the container list - that is not good
|
||||||
|
import re
|
||||||
|
for c in self.cbox.getContainerList():
|
||||||
|
if re.match(device + "\d*$", c.getDevice()):
|
||||||
|
if c.isMounted(): return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def __actionSelectDevice(self, args):
|
||||||
|
block_devices = [e
|
||||||
|
for e in CryptoBoxTools.getParentBlockDevices()
|
||||||
|
if self.cbox.isDeviceAllowed(e)]
|
||||||
|
counter = 0
|
||||||
|
for a in block_devices:
|
||||||
|
self.hdf[self.hdf_prefix + "BlockDevices.%d" % counter] = a
|
||||||
|
self.cbox.log.debug("found a suitable block device: %s" % a)
|
||||||
|
counter += 1
|
||||||
|
if self.withConfigPartition:
|
||||||
|
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
||||||
|
## there is no disk available
|
||||||
|
if not block_devices:
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable"
|
||||||
|
return "select_device"
|
||||||
|
|
||||||
|
|
||||||
|
def __actionAddPartition(self, args):
|
||||||
|
self.hdf[self.hdf_prefix + "Device"] = self.device
|
||||||
|
self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
|
||||||
|
parts = self.__getPartitionsFromArgs(args)
|
||||||
|
self.__setPartitionData(parts)
|
||||||
|
return "set_partitions"
|
||||||
|
|
||||||
|
|
||||||
|
def __actionDelPartition(self, args):
|
||||||
|
try:
|
||||||
|
part_num = int(args["del_num"])
|
||||||
|
except (TypeError,KeyError):
|
||||||
|
return self.__actionAddPartition(args)
|
||||||
|
self.hdf[self.hdf_prefix + "Device"] = self.device
|
||||||
|
self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
|
||||||
|
parts = self.__getPartitionsFromArgs(args)
|
||||||
|
## valid partition number to be deleted?
|
||||||
|
if part_num < len(parts):
|
||||||
|
del parts[part_num]
|
||||||
else:
|
else:
|
||||||
|
return self.__actionAddPartition(args)
|
||||||
|
self.__setPartitionData(parts)
|
||||||
|
return "set_partitions"
|
||||||
|
|
||||||
|
|
||||||
|
def __actionFinish(self, args):
|
||||||
|
parts = self.__getPartitionsFromArgs(args)
|
||||||
|
if parts:
|
||||||
|
self.__setPartitionData(parts)
|
||||||
|
if not self.__runFDisk(parts):
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
||||||
|
return self.__actionAddPartition(args)
|
||||||
|
else:
|
||||||
|
# TODO: will we use the "yield"-style? If yes, then remove these messages (success and warning)
|
||||||
|
#if self.__formatPartitions(parts):
|
||||||
|
# self.hdf["Data.Success"] = "Plugins.partition.Partitioned"
|
||||||
|
#else:
|
||||||
|
# self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
|
||||||
|
"""
|
||||||
|
tricky problem: if the device was partitioned, then a created config partition is still part of the containerlist, as the label is not checked again - very ugly!!! So we will call reReadContainerList after formatting the last partition - see below
|
||||||
|
"""
|
||||||
|
self.cbox.reReadContainerList()
|
||||||
|
def result_generator():
|
||||||
|
counter = 0
|
||||||
|
## initialize the generator
|
||||||
|
formatPart_gen = self.__formatPartitions(parts)
|
||||||
|
while counter < len(parts):
|
||||||
|
## first part: get the device name
|
||||||
|
yield formatPart_gen.next()
|
||||||
|
counter += 1
|
||||||
|
## second part: do the real formatting of a partition
|
||||||
|
result = formatPart_gen.next()
|
||||||
|
## after the first partiton, we can reRead the containerList (as the possible config partition was already created)
|
||||||
|
if self.withConfigPartition and (counter == 1):
|
||||||
|
## important: reRead the containerList
|
||||||
|
self.cbox.reReadContainerList()
|
||||||
|
## return the result
|
||||||
|
yield result
|
||||||
|
return {
|
||||||
|
"template": "show_format_progress",
|
||||||
|
"generator": result_generator}
|
||||||
|
else:
|
||||||
|
return self.__actionAddPartition(args)
|
||||||
|
|
||||||
|
|
||||||
|
def __setPartitionData(self, parts):
|
||||||
|
availSize = self.deviceSize
|
||||||
|
i = 0
|
||||||
|
for part in parts:
|
||||||
|
self.cbox.log.debug(part)
|
||||||
|
self.hdf[self.hdf_prefix + "Parts.%d.Size" % i] = part["size"]
|
||||||
|
self.hdf[self.hdf_prefix + "Parts.%d.Type" % i] = part["type"]
|
||||||
|
availSize -= part["size"]
|
||||||
|
i += 1
|
||||||
|
self.hdf[self.hdf_prefix + "availSize"] = availSize
|
||||||
|
if self.withConfigPartition:
|
||||||
|
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
||||||
|
for t in self.PartTypes.keys():
|
||||||
|
self.hdf[self.hdf_prefix + "Types.%s" % t] = t
|
||||||
|
|
||||||
|
|
||||||
|
def __getPartitionsFromArgs(self, args):
|
||||||
|
parts = []
|
||||||
|
done = False
|
||||||
|
availSize = self.deviceSize
|
||||||
|
i = -1
|
||||||
|
while not done:
|
||||||
|
i += 1
|
||||||
|
try:
|
||||||
|
size = int(args["part%d_size" % i])
|
||||||
|
partType = args["part%d_type" % i]
|
||||||
|
if int(size) > availSize:
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
|
||||||
|
continue
|
||||||
|
if int(size) < 10:
|
||||||
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
|
||||||
|
continue
|
||||||
|
if not partType in self.PartTypes.keys(): continue
|
||||||
|
parts.append({"size":size, "type":partType})
|
||||||
|
availSize -= size
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
except KeyError:
|
||||||
|
done = True
|
||||||
|
return parts
|
||||||
|
|
||||||
|
|
||||||
|
def __getAvailableDeviceSize(self, device):
|
||||||
|
"""calculate the available size (MB) of the device
|
||||||
|
also consider a (possible) configuration partition"""
|
||||||
|
if not device: return 0
|
||||||
|
rdev = os.stat(device).st_rdev
|
||||||
|
minor = os.minor(rdev)
|
||||||
|
major = os.major(rdev)
|
||||||
|
for f in file("/proc/partitions"):
|
||||||
|
try:
|
||||||
|
elements = f.split()
|
||||||
|
if len(elements) != 4: continue
|
||||||
|
if (int(elements[0]) == major) and (int(elements[1]) == minor):
|
||||||
|
deviceSize = int(elements[2])/1024
|
||||||
|
if self.withConfigPartition:
|
||||||
|
deviceSize -= self.ConfigPartition["size"]
|
||||||
|
return deviceSize
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def __isWithConfigPartition(self, args):
|
||||||
|
try:
|
||||||
|
if args["create_config_partition"]:
|
||||||
|
createConfig = True
|
||||||
|
else:
|
||||||
|
createConfig = False
|
||||||
|
except KeyError:
|
||||||
createConfig = False
|
createConfig = False
|
||||||
except KeyError:
|
return createConfig
|
||||||
createConfig = False
|
|
||||||
return createConfig
|
|
||||||
|
|
||||||
|
|
||||||
def __runFDisk(cbox, device, parts, withConfigPartition):
|
def __runFDisk(self, parts):
|
||||||
## check if the device is completely filled (to avoid some empty last blocks)
|
## check if the device is completely filled (to avoid some empty last blocks)
|
||||||
avail_size = __getAvailableDeviceSize(device, withConfigPartition)
|
avail_size = self.deviceSize
|
||||||
for d in parts: avail_size -= d["size"]
|
for d in parts: avail_size -= d["size"]
|
||||||
isFilled = avail_size == 0
|
isFilled = avail_size == 0
|
||||||
proc = subprocess.Popen(
|
|
||||||
shell = False,
|
|
||||||
stdin = subprocess.PIPE,
|
|
||||||
stdout = 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])
|
|
||||||
for line in __getSFDiskLayout(parts, withConfigPartition, isFilled):
|
|
||||||
proc.stdin.write(line + "\n")
|
|
||||||
(output, error) = proc.communicate()
|
|
||||||
if proc.returncode != 0: logger.debug("partitioning failed: %s" % error)
|
|
||||||
return proc.returncode == 0
|
|
||||||
|
|
||||||
|
|
||||||
def __getSFDiskLayout(paramParts, withConfigPartition, isFilled):
|
|
||||||
parts = paramParts[:]
|
|
||||||
## first a (possible) configuration partition - so it will be reusable
|
|
||||||
if withConfigPartition:
|
|
||||||
## fill the main table (including a config partition)
|
|
||||||
yield ",%d,%s" % (ConfigPartition["size"], ConfigPartition["type"])
|
|
||||||
## one primary partition
|
|
||||||
yield ",%d,%s,*" % (parts[0]["size"], PartTypes[parts[0]["type"]][0])
|
|
||||||
del parts[0]
|
|
||||||
## no extended partition, if there is only one disk
|
|
||||||
if not parts: return
|
|
||||||
## an extended container for the rest
|
|
||||||
yield ",,E"
|
|
||||||
## an empty partition in main table
|
|
||||||
yield ";"
|
|
||||||
## maybe another empty partition if there is no config partition
|
|
||||||
if not withConfigPartition: yield ";"
|
|
||||||
while parts:
|
|
||||||
if isFilled and (len(parts) == 1):
|
|
||||||
yield ",,%s" % (PartTypes[parts[0]["type"]][0],)
|
|
||||||
else:
|
|
||||||
yield ",%d,%s" % (parts[0]["size"], PartTypes[parts[0]["type"]][0])
|
|
||||||
del parts[0]
|
|
||||||
|
|
||||||
|
|
||||||
def __formatPartitions(cbox, device, paramParts, withConfigPartition):
|
|
||||||
success = True
|
|
||||||
parts = paramParts[:]
|
|
||||||
part_num = 1
|
|
||||||
## maybe a config partition?
|
|
||||||
if withConfigPartition:
|
|
||||||
dev_name = device + str(part_num)
|
|
||||||
logger.info("formatting config partition (%s)" % dev_name)
|
|
||||||
if __formatOnePartition(cbox, dev_name, ConfigPartition["fs"]):
|
|
||||||
__setLabelOfPartition(cbox, dev_name, cbox.prefs["Main"]["ConfigVolumeLabel"])
|
|
||||||
else:
|
|
||||||
success = False
|
|
||||||
part_num += 1
|
|
||||||
## the first data partition
|
|
||||||
dev_name = device + str(part_num)
|
|
||||||
partType = PartTypes[parts[0]["type"]][1]
|
|
||||||
logger.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
|
||||||
if not __formatOnePartition(cbox, dev_name, partType):
|
|
||||||
success = False
|
|
||||||
del parts[0]
|
|
||||||
## other data partitions
|
|
||||||
part_num = 5
|
|
||||||
while parts:
|
|
||||||
dev_name = device + str(part_num)
|
|
||||||
partType = PartTypes[parts[0]["type"]][1]
|
|
||||||
logger.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
|
||||||
if not __formatOnePartition(cbox, dev_name, partType):
|
|
||||||
success = False
|
|
||||||
part_num += 1
|
|
||||||
del parts[0]
|
|
||||||
return success
|
|
||||||
|
|
||||||
|
|
||||||
def __formatOnePartition(cbox, dev_name, type):
|
|
||||||
import time, sys
|
|
||||||
child_pid = os.fork()
|
|
||||||
## we run formatting as a parallel thread
|
|
||||||
## TODO: the parent thread still waits for the last child - that is not good for big harddisks
|
|
||||||
if child_pid == 0:
|
|
||||||
## we are the child process
|
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
stdin = subprocess.PIPE,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
stderr = subprocess.PIPE,
|
stderr = subprocess.PIPE,
|
||||||
args = [
|
args = [
|
||||||
cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
|
"plugin",
|
||||||
|
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||||
|
"partition",
|
||||||
|
self.device])
|
||||||
|
for line in self.__getSFDiskLayout(parts, isFilled):
|
||||||
|
proc.stdin.write(line + "\n")
|
||||||
|
(output, error) = proc.communicate()
|
||||||
|
if proc.returncode != 0: self.cbox.log.debug("partitioning failed: %s" % error)
|
||||||
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def __getSFDiskLayout(self, paramParts, isFilled):
|
||||||
|
parts = paramParts[:]
|
||||||
|
## first a (possible) configuration partition - so it will be reusable
|
||||||
|
if self.withConfigPartition:
|
||||||
|
## fill the main table (including a config partition)
|
||||||
|
yield ",%d,%s" % (self.ConfigPartition["size"], self.ConfigPartition["type"])
|
||||||
|
## one primary partition
|
||||||
|
yield ",%d,%s,*" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0])
|
||||||
|
del parts[0]
|
||||||
|
## no extended partition, if there is only one disk
|
||||||
|
if not parts: return
|
||||||
|
## an extended container for the rest
|
||||||
|
yield ",,E"
|
||||||
|
## an empty partition in main table
|
||||||
|
yield ";"
|
||||||
|
## maybe another empty partition if there is no config partition
|
||||||
|
if not self.withConfigPartition: yield ";"
|
||||||
|
while parts:
|
||||||
|
if isFilled and (len(parts) == 1):
|
||||||
|
yield ",,%s" % (self.PartTypes[parts[0]["type"]][0],)
|
||||||
|
else:
|
||||||
|
yield ",%d,%s" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0])
|
||||||
|
del parts[0]
|
||||||
|
|
||||||
|
|
||||||
|
def __formatPartitions(self, paramParts):
|
||||||
|
import threading
|
||||||
|
parts = paramParts[:]
|
||||||
|
part_num = 1
|
||||||
|
## maybe a config partition?
|
||||||
|
if self.withConfigPartition:
|
||||||
|
dev_name = self.device + str(part_num)
|
||||||
|
self.cbox.log.info("formatting config partition (%s)" % dev_name)
|
||||||
|
if self.__formatOnePartition(dev_name, self.ConfigPartition["fs"]):
|
||||||
|
self.__setLabelOfPartition(dev_name, self.cbox.prefs["Main"]["ConfigVolumeLabel"])
|
||||||
|
part_num += 1
|
||||||
|
## the first data partition
|
||||||
|
dev_name = self.device + str(part_num)
|
||||||
|
partType = self.PartTypes[parts[0]["type"]][1]
|
||||||
|
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
||||||
|
yield dev_name
|
||||||
|
if self.__formatOnePartition(dev_name, partType):
|
||||||
|
yield "OK"
|
||||||
|
else:
|
||||||
|
yield "<b>Failed!</b>"
|
||||||
|
del parts[0]
|
||||||
|
## other data partitions
|
||||||
|
part_num = 5
|
||||||
|
while parts:
|
||||||
|
dev_name = self.device + str(part_num)
|
||||||
|
partType = self.PartTypes[parts[0]["type"]][1]
|
||||||
|
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
||||||
|
yield dev_name
|
||||||
|
if self.__formatOnePartition(dev_name, partType):
|
||||||
|
yield "OK"
|
||||||
|
else:
|
||||||
|
yield "<b>Failed!</b>"
|
||||||
|
part_num += 1
|
||||||
|
del parts[0]
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def __formatOnePartition(self, dev_name, type):
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
shell = False,
|
||||||
|
args = [
|
||||||
|
self.cbox.prefs["Programs"]["super"],
|
||||||
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||||
"format",
|
"format",
|
||||||
|
@ -311,37 +331,29 @@ def __formatOnePartition(cbox, dev_name, type):
|
||||||
type])
|
type])
|
||||||
(output, error) = proc.communicate()
|
(output, error) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
logger.warn("failed to create filesystem on %s: %s" % (dev_name, error))
|
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
|
||||||
sys.exit(1)
|
return False
|
||||||
else:
|
else:
|
||||||
sys.exit(0)
|
return True
|
||||||
else:
|
|
||||||
time.sleep(1)
|
|
||||||
(pid, exit_state) = os.waitpid(child_pid, os.WNOHANG)
|
def __setLabelOfPartition(self, dev_name, label):
|
||||||
if ((pid == 0) and (exit_state == 0)) \
|
proc = subprocess.Popen(
|
||||||
or ((pid == child_pid) and (exit_state == 0)):
|
shell = False,
|
||||||
|
stdout = subprocess.PIPE,
|
||||||
|
stderr = subprocess.PIPE,
|
||||||
|
args = [
|
||||||
|
self.cbox.prefs["Programs"]["super"],
|
||||||
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
|
"plugin",
|
||||||
|
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||||
|
"label",
|
||||||
|
dev_name,
|
||||||
|
label])
|
||||||
|
(output, error) = proc.communicate()
|
||||||
|
if proc.returncode == 0:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __setLabelOfPartition(cbox, dev_name, label):
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
shell = False,
|
|
||||||
stdout = 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"),
|
|
||||||
"label",
|
|
||||||
dev_name,
|
|
||||||
label])
|
|
||||||
(output, error) = proc.communicate()
|
|
||||||
if proc.returncode == 0:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.warn("failed to create filesystem on %s: %s" % (device + str(part_num), error))
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,28 @@ def __partitionDevice(device):
|
||||||
|
|
||||||
|
|
||||||
def __formatPartition(device, type):
|
def __formatPartition(device, type):
|
||||||
proc = subprocess.Popen(
|
import time, threading
|
||||||
shell = False,
|
result = True
|
||||||
args = [
|
def formatting():
|
||||||
MKFS_BIN,
|
proc = subprocess.Popen(
|
||||||
"-t", type,
|
shell = False,
|
||||||
device])
|
stdin = subprocess.PIPE,
|
||||||
proc.communicate()
|
stdout = subprocess.PIPE,
|
||||||
return proc.returncode == 0
|
stderr = subprocess.PIPE,
|
||||||
|
args = [
|
||||||
|
MKFS_BIN,
|
||||||
|
"-t", type,
|
||||||
|
device])
|
||||||
|
proc.communicate()
|
||||||
|
## TODO: very ugly way of communication: it assumes, that failures are fast - success is slow
|
||||||
|
if proc.returncode == 0:
|
||||||
|
time.sleep(1)
|
||||||
|
thread = threading.Thread()
|
||||||
|
thread.setDaemon(True)
|
||||||
|
thread.run = formatting
|
||||||
|
thread.start()
|
||||||
|
time.sleep(0.5)
|
||||||
|
return thread.isAlive()
|
||||||
|
|
||||||
|
|
||||||
def __labelPartition(device, label):
|
def __labelPartition(device, label):
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<input type="hidden" name="step" value="add_partition" />
|
<input type="hidden" name="step" value="add_partition" />
|
||||||
<?cs set: x = subcount(Data.Plugins.partition.Parts) ?>
|
<?cs set: x = subcount(Data.Plugins.partition.Parts) ?>
|
||||||
<td><?cs var:x ?></td>
|
<td><?cs var:x ?></td>
|
||||||
<td><input type="text" name="part<?cs var:x ?>_size" size="8" value="<?cs var:Data.Plugins.partition.availSize ?>" /></td>
|
<td><input type="text" name="part<?cs var:x ?>_size" size="8" value="<?cs var:Data.Plugins.partition.availSize ?>" tabindex="0" /></td>
|
||||||
<td><select name="part<?cs var:x ?>_type" size="0"><?cs each: t = Data.Plugins.partition.Types ?><option <?cs if:t == "windows" ?>selected="selected"<?cs /if ?>><?cs var:t ?></option>
|
<td><select name="part<?cs var:x ?>_type" size="0"><?cs each: t = Data.Plugins.partition.Types ?><option <?cs if:t == "windows" ?>selected="selected"<?cs /if ?>><?cs var:t ?></option>
|
||||||
<?cs /each ?></select></td>
|
<?cs /each ?></select></td>
|
||||||
<td>
|
<td>
|
||||||
|
|
13
pythonrewrite/plugins/partition/show_format_progress.cs
Normal file
13
pythonrewrite/plugins/partition/show_format_progress.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?cs # $Id$ ?>
|
||||||
|
|
||||||
|
<h1><?cs var:html_escape(Lang.Plugins.partition.Title.Partition) ?></h1>
|
||||||
|
|
||||||
|
<p><?cs var:html_escape(Lang.Plugins.partition.Text.ProgressInfo) ?>
|
||||||
|
<ul>
|
||||||
|
<?cs loop: x = #0, subcount(Data.Plugins.partition.Parts)-1, #1 ?>
|
||||||
|
<li><!-- CONTENT_DUMMY -->:
|
||||||
|
<!-- CONTENT_DUMMY --></li>
|
||||||
|
<?cs /loop ?>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
|
@ -5,15 +5,20 @@ The following directory structure is required:
|
||||||
|
|
||||||
|
|
||||||
Python code interface:
|
Python code interface:
|
||||||
def doAction(hdf, cbox, store=None, ???):
|
- create a class with the same name as the plugin - it has to inherit CryptoBoxPlugin
|
||||||
|
- function "doAction":
|
||||||
- this function will get called whenever this plugins is involved in a request
|
- this function will get called whenever this plugins is involved in a request
|
||||||
- all arguments should be optional (e.g. for displaying a form without previous input values)
|
- all arguments should be optional (e.g. for displaying a form without previous input values)
|
||||||
- the argument "store" should be used to process a form submission (just a recommendation)
|
- the argument "store" should be used to process a form submission (just a recommendation)
|
||||||
- if the processing failed for some reason (invalid input, ...), it should manually set the "Data.Warning" (resp. "Data.Error" or "Data.Success") to a value of your choice (preferably you may want to use messages of your namespace (e.g. "Plugins.PLUGINNAME.InvalidInput"))
|
- if the processing failed for some reason (invalid input, ...), it should manually set the "Data.Warning" (resp. "Data.Error" or "Data.Success") to a value of your choice (preferably you may want to use messages of your namespace (e.g. "Plugins.PLUGINNAME.InvalidInput"))
|
||||||
- the return value should be the name of the template that should be displayed after processing (a template file in the plugin directory takes precedence over global template files)
|
- the return value should be the name of the template that should be displayed after processing (a template file in the plugin directory takes precedence over global template files)
|
||||||
|
- the return value may also be a dictionary with the following elements:
|
||||||
|
* template: the name of the template file (mandatory)
|
||||||
|
* generator: a generator object ("yield") - its content will replace every occourence of "<!-- CONTENT_DUMMY -->" in the template (useful for pages that are displayed step by step (as for formatting of filesystems))
|
||||||
|
- an empty (e.g. None) return value can be used to go return to the plugin page
|
||||||
|
|
||||||
def def getStatus(cbox):
|
- function "getStatus":
|
||||||
- returns a string, that described a state connected to this plugin (e.g. the current date and time (for the "date" plugin)
|
- returns a string, that describes a state connected to this plugin (e.g. the current date and time (for the "date" plugin))
|
||||||
|
|
||||||
|
|
||||||
Language file structure:
|
Language file structure:
|
||||||
|
|
Loading…
Reference in a new issue