X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fpython%2FComponents%2FHarddisk.py;h=9b3a684c4f60f0c8c2ed2444add581ff04954f13;hp=0f1a8fcafb304c5007558a01b693850af1e55c63;hb=HEAD;hpb=30da484f79db1d8210a3dcb31b359484873dc240 diff --git a/lib/python/Components/Harddisk.py b/lib/python/Components/Harddisk.py old mode 100644 new mode 100755 index 0f1a8fc..9b3a684 --- a/lib/python/Components/Harddisk.py +++ b/lib/python/Components/Harddisk.py @@ -1,9 +1,13 @@ from os import system, listdir, statvfs, popen, makedirs, stat, major, minor, path, access -from Tools.Directories import SCOPE_HDD, resolveFilename + +from Tools.Directories import SCOPE_HDD, resolveFilename, fileExists + from Tools.CList import CList from SystemInfo import SystemInfo import time from Components.Console import Console +import os +import glob def MajorMinor(path): rdev = stat(path).st_rdev @@ -15,6 +19,95 @@ def readFile(filename): file.close() return data +def getProcMounts(): + try: + mounts = open("/proc/mounts", 'r') + except IOError, ex: + print "[Harddisk] Failed to open /proc/mounts", ex + return [] + result = [line.strip().split(' ') for line in mounts] + for item in result: + # Spaces are encoded as \040 in mounts + item[1] = item[1].replace('\\040', ' ') + return result + +def CheckSfdiskVer(): + cmd = 'sfdisk --version' + lines = popen(cmd).readlines() + for l in lines: + if l.find("sfdisk from util-linux") != -1: + ver = l.split()[-1].strip() + break + try: + vs = ver.split('.') + if len(vs) > 2: + ver = '.'.join(vs[:2]) + + ver = float(ver) + except: + print "[CheckSfdiskVer] check parted version Failed!" + return 0 + return ver + +def enableUdevEvent(enable = True): + if enable: + option = '--start-exec-queue' + else: + option = '--stop-exec-queue' + cmd = "udevadm control %s" % option + print "CMD : ", cmd + system(cmd) + +def findMountPoint(path): + 'Example: findMountPoint("/media/hdd/some/file") returns "/media/hdd"' + path = os.path.abspath(path) + while not os.path.ismount(path): + path = os.path.dirname(path) + return path + +def getDeviceFile(dev_path): + for parts in getProcMounts(): + if os.path.realpath(parts[1]).startswith(dev_path): + return parts[0] + +def getMountPath(mountPath): + mountPath = os.path.realpath(mountPath) + while not os.path.ismount(mountPath): + mountPath = os.path.dirname(mountPath) + + return mountPath + +def getDeviceInterface(mountPath): + mountPath = getMountPath(mountPath) + + if mountPath == '/': + return None + + from Components.Harddisk import getDeviceFile + dev = getDeviceFile(mountPath) + + if dev and dev.startswith("/dev/sd"): + dev = os.path.basename(dev) + phyPath = os.path.realpath('/sys/block/' + dev[:3]) + + # check usb + for x in glob.glob("/sys/bus/usb/devices/usb*"): + if phyPath.find(os.path.realpath(x)) != -1: + from Tools.HardwareInfo import HardwareInfo + if (HardwareInfo().get_vu_device_name() == "zero4k") and (phyPath.find("f0b00500.ehci_v2/usb2/2-1") != -1): + return "ata" + else: + return "usb" + + # check ata + if phyPath.find("/ata") != -1: + return "ata" + + return None + +def isUsbStorage(dirname): + return getDeviceInterface(dirname) in (None, "usb") + DEVTYPE_UDEV = 0 DEVTYPE_DEVFS = 1 @@ -35,6 +128,8 @@ class Harddisk: self.dev_path = '' self.disk_path = '' + self.mount_path = None + self.mount_device = None self.phys_path = path.realpath(self.sysfsPath('device')) if self.type == DEVTYPE_UDEV: @@ -95,7 +190,12 @@ class Harddisk: return ret def diskSize(self): - line = readFile(self.sysfsPath('size')) + try: + line = readFile(self.sysfsPath('size')) + except: + harddiskmanager.removeHotplugPartition(self.device) + print "error remove",self.device + return -1 try: cap = int(line) except: @@ -109,14 +209,19 @@ class Harddisk: return "%d.%03d GB" % (cap/1000, cap%1000) def model(self): - if self.device[:2] == "hd": - return readFile('/proc/ide/' + self.device + '/model') - elif self.device[:2] == "sd": - vendor = readFile(self.sysfsPath('device/vendor')) - model = readFile(self.sysfsPath('device/model')) - return vendor + '(' + model + ')' - else: - assert False, "no hdX or sdX" + try: + if self.device[:2] == "hd": + return readFile('/proc/ide/' + self.device + '/model') + elif self.device[:2] == "sd": + vendor = readFile(self.sysfsPath('device/vendor')) + model = readFile(self.sysfsPath('device/model')) + return vendor + '(' + model + ')' + else: + assert False, "no hdX or sdX" + except: + harddiskmanager.removeHotplugPartition(self.device) + print "error remove",self.device + return -1 def free(self): try: @@ -163,6 +268,18 @@ class Harddisk: numPart += 1 return numPart + def mountDevice(self): + for parts in getProcMounts(): + if path.realpath(parts[0]).startswith(self.dev_path): + self.mount_device = parts[0] + self.mount_path = parts[1] + return parts[1] + + def findMount(self): + if self.mount_path is None: + return self.mountDevice() + return self.mount_path + def unmount(self): try: mounts = open("/proc/mounts") @@ -187,11 +304,70 @@ class Harddisk: pass res = system(cmd) + print "CMD : ", cmd + return (res >> 8) + + def checkPartionPath(self, path): + import time, os + for i in range(1,10): + if os.path.exists(path): + return True + time.sleep(1) + return False + + def updatePartition(self): + sfdiskVer = CheckSfdiskVer() + if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26 + cmd = 'sfdisk -R %s; sleep 5' % (self.disk_path) + elif path.exists('/usr/sbin/partprobe'): + cmd = 'partprobe %s; sleep 5' % (self.disk_path) + elif path.exists('/usr/sbin/partx'): + cmd = 'partx -u %s' % (self.disk_path) + else: + return -1 + + print "CMD : ", cmd + res = system(cmd) + return (res >> 8) def createPartition(self): - cmd = 'printf "0,\n;\n;\n;\ny\n" | sfdisk -f ' + self.disk_path + def CheckPartedVer(): + cmd = 'parted --version' + lines = popen(cmd).readlines() + for l in lines: + if l.find("parted (GNU parted)") != -1: + ver = l.split()[3].strip() + break + try: + ver = float(ver) + except: + print "[CheckPartedVer] check parted version Failed!" + return 0 + return ver + + disk_size = self.diskSize() + + if disk_size > 2.2 * 1000 * 1000: # if 2.2 TB + setAlign = "" + partedVer = CheckPartedVer() + if partedVer >= 2.1: # align option is supported in version 2.1 or later + setAlign = "--align optimal" + cmd = 'parted %s %s --script mklabel gpt mkpart disk ext2 0%% 100%%' % ( setAlign, self.disk_path ) + + else: + sfdiskVer = CheckSfdiskVer() + if sfdiskVer <= 2.21: + cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS ' + self.disk_path + else: + cmd = 'printf "8,\nquit\nY\n" | sfdisk -f -uS ' + self.disk_path + + print "CMD : ", cmd res = system(cmd) + + if not self.checkPartionPath(self.partitionPath("1")): + print "no exist : ", self.partitionPath("1") + return 1 return (res >> 8) def mkfs(self): @@ -199,6 +375,7 @@ class Harddisk: if self.diskSize() > 4 * 1024: cmd += "-T largefile " cmd += "-m0 -O dir_index " + self.partitionPath("1") + print "CMD : ", cmd res = system(cmd) return (res >> 8) @@ -212,23 +389,40 @@ class Harddisk: fstab.close() res = -1 + mount_point = None for line in lines: parts = line.strip().split(" ") - real_path = path.realpath(parts[0]) - if not real_path[-1].isdigit(): - continue - try: - if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])): - cmd = "mount -t ext3 " + parts[0] - res = system(cmd) + real_path = path.realpath(parts[0]) + if not real_path[-1].isdigit(): + continue + try: + if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])): + mount_point = parts[0] break except OSError: pass - return (res >> 8) + if mount_point is None: + return 0 + + cmd = "mount -t ext3 " + mount_point + print "CMD : ", cmd + res = system(cmd) + + if (res >> 8) != 0: + return -3 + + if self.createMovieFolder() != 0: + return -4 + + return 0 def createMovieFolder(self): try: + if not fileExists("/hdd", 0): + print "not found /hdd" + system("ln -s /media/hdd /hdd") + makedirs(resolveFilename(SCOPE_HDD)) except OSError: return -1 @@ -246,15 +440,17 @@ class Harddisk: if access(part, 0): cmd = 'dd bs=512 count=3 if=/dev/zero of=' + part + print "CMD : ", cmd res = system(cmd) else: res = 0 return (res >> 8) - errorList = [ _("Everything is fine"), _("Creating partition failed"), _("Mkfs failed"), _("Mount failed"), _("Create movie folder failed"), _("Fsck failed"), _("Please Reboot"), _("Filesystem contains uncorrectable errors"), _("Unmount failed")] + errorList = [ _("Everything is fine"), _("Creating partition failed"), _("Mkfs failed"), _("Mount failed"), _("Create movie folder failed"), _("Fsck failed"), _("Please Reboot"), _("Filesystem contains uncorrectable errors"), _("Unmount failed"), _("partx failed")] def initialize(self): + enableUdevEvent(False) self.unmount() # Udev tries to mount the partition immediately if there is an @@ -264,19 +460,23 @@ class Harddisk: # ext3 at least. self.killPartition("1") - if self.createPartition() != 0: - return -1 + if self.updatePartition() != 0: + res = -9 - if self.mkfs() != 0: - return -2 + elif self.createPartition() != 0: + res = -1 - if self.mount() != 0: - return -3 + elif self.updatePartition() != 0: + res = -9 - if self.createMovieFolder() != 0: - return -4 + elif self.mkfs() != 0: + res = -2 - return 0 + else: + res = self.mount() + + enableUdevEvent(True) + return res def check(self): self.unmount() @@ -337,6 +537,10 @@ class Harddisk: idle_time = t - self.last_access stats = self.readStats() + + if stats == -1: + self.setIdleTime(0) + return print "nr_read", stats[0], "nr_write", stats[1] l = sum(stats) print "sum", l, "prev_sum", self.last_stat @@ -489,7 +693,7 @@ class HarddiskManager: try: removable = bool(int(readFile(devpath + "/removable"))) dev = int(readFile(devpath + "/dev").split(':')[0]) - if dev in (7, 31): # loop, mtdblock + if dev in (7, 31, 179): # loop, mtdblock, mmcblock blacklisted = True if blockdev[0:2] == 'sr': is_cdrom = True @@ -533,6 +737,7 @@ class HarddiskManager: def getAutofsMountpoint(self, device): return "/autofs/%s/" % (device) + def is_hard_mounted(self, device): mounts = file('/proc/mounts').read().split('\n') for x in mounts: @@ -540,6 +745,13 @@ class HarddiskManager: return True return False + def getMountpoint(self, device): + dev = "/dev/%s" % device + for item in getProcMounts(): + if item[0] == dev and item[1].find('/autofs') == -1: + return item[1] + return None + def addHotplugPartition(self, device, physdev = None): if not physdev: dev, part = self.splitDeviceName(device) @@ -570,7 +782,7 @@ class HarddiskManager: self.hdd.sort() SystemInfo["Harddisk"] = len(self.hdd) > 0 - if (not removable or medium_found) and not self.is_hard_mounted(device): + if not removable or medium_found: # device is the device name, without /dev # physdev is the physical device path, which we (might) use to determine the userfriendly name description = self.getUserfriendlyDeviceName(device, physdev) @@ -581,11 +793,11 @@ class HarddiskManager: return error, blacklisted, removable, is_cdrom, partitions, medium_found def removeHotplugPartition(self, device): - mountpoint = self.getAutofsMountpoint(device) for x in self.partitions[:]: - if x.mountpoint == mountpoint: + if x.device == device: self.partitions.remove(x) - self.on_partition_list_change("remove", x) + if x.mountpoint: + self.on_partition_list_change("remove", x) l = len(device) if l and not device[l-1].isdigit(): for hdd in self.hdd: @@ -601,6 +813,8 @@ class HarddiskManager: def HDDList(self): list = [ ] for hd in self.hdd: + if hd.model() == -1: + continue hdd = hd.model() + " - " + hd.bus() cap = hd.capacity() if cap != "": @@ -612,7 +826,7 @@ class HarddiskManager: return self.cd def getMountedPartitions(self, onlyhotplug = False): - parts = [x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted()] + parts = [x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted() and x.mountpoint] devs = set([x.device for x in parts]) for devname in devs.copy(): if not devname: @@ -621,9 +835,28 @@ class HarddiskManager: if part and dev in devs: # if this is a partition and we still have the wholedisk, remove wholedisk devs.remove(dev) + # remove duplicate device + no_force_mounted_list = [x.mountpoint for x in self.partitions if not x.force_mounted] + for x in parts: + if x.force_mounted: + mp = self.getMountpoint(x.device) + if mp and mp in no_force_mounted_list: + devs.remove(x.device) + # return all devices which are not removed due to being a wholedisk when a partition exists return [x for x in parts if not x.device or x.device in devs] + def getLabelFromDevName(self, dev): + data = None + try: + data = os.popen("e2label %s" % dev).read().strip() + if not data: + data = None + except: + data = None + + return data + def splitDeviceName(self, devname): # this works for: sdaX, hdaX, sr0 (which is in fact dev="sr0", part=""). It doesn't work for other names like mtdblock3, but they are blacklisted anyway. dev = devname[:3] @@ -634,14 +867,20 @@ class HarddiskManager: return dev, part and int(part) or 0 def getUserfriendlyDeviceName(self, dev, phys): + label = self.getLabelFromDevName("/dev/" + dev) dev, part = self.splitDeviceName(dev) description = "External Storage %s" % dev have_model_descr = False - try: - description = readFile("/sys" + phys + "/model") + + if label: + description = label have_model_descr = True - except IOError, s: - print "couldn't read model: ", s + else: + try: + description = readFile("/sys" + phys + "/model") + have_model_descr = True + except IOError, s: + print "couldn't read model: ", s from Tools.HardwareInfo import HardwareInfo if dev.find('sr') == 0 and dev[2].isdigit(): devicedb = DEVICEDB_SR