liveusb/creator.py | 258 ++++++++++++++++++++++++++++++++++------------------- liveusb/gui.py | 35 ++++--- 2 files changed, 189 insertions(+), 104 deletions(-)
New commits: commit a34a5591e3b8a83baefa746dd95a1b3b59b27e42 Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 21:00:17 2011 -0400
Fix an issue with our some of our freespace checking code
diff --git a/liveusb/creator.py b/liveusb/creator.py index 532b8c3..efd08ca 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -35,6 +35,7 @@ import re
from StringIO import StringIO from datetime import datetime +from pprint import pformat from stat import ST_SIZE
from liveusb.releases import releases diff --git a/liveusb/gui.py b/liveusb/gui.py index 3f0f15d..806baa9 100755 --- a/liveusb/gui.py +++ b/liveusb/gui.py @@ -383,12 +383,16 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): freespace = device['free'] current_overlay = self.overlaySlider.value()
- if not freespace: + if not device['mount']: self.live.log.warning(_('Device is not yet mounted, so we cannot ' 'determine the amount of free space. ' 'Setting a maximum limit of 8G for the ' 'persistent storage.')) freespace = 8192 + else: + if not freespace: + self.live.log.warning(_('No free space on %s') % drive) + freespace = 0
# FAT16 cannot handle files greater than 2G if device['fsversion'] == 'FAT16':
commit f8a14ccd8d838c64c221c20384d9863d8d811450 Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:56:45 2011 -0400
Remove our second logging handler when errors occur (ticket #637)
diff --git a/liveusb/gui.py b/liveusb/gui.py index 73ebceb..3f0f15d 100755 --- a/liveusb/gui.py +++ b/liveusb/gui.py @@ -184,6 +184,7 @@ class LiveUSBThread(QtCore.QThread): if not self.live.drive['uuid'] and not self.live.label: self.status(_("Error: Cannot set the label or obtain " "the UUID of your device. Unable to continue.")) + self.live.log.removeHandler(handler) return
self.live.check_free_space() @@ -191,12 +192,14 @@ class LiveUSBThread(QtCore.QThread): if not self.parent.opts.noverify: # Verify the MD5 checksum inside of the ISO image if not self.live.verify_iso_md5(): + self.live.log.removeHandler(handler) return
# If we know about this ISO, and it's SHA1 -- verify it release = self.live.get_release_from_iso() if release and ('sha1' in release or 'sha256' in release): if not self.live.verify_iso_sha1(progress=self): + self.live.log.removeHandler(handler) return
# Setup the progress bar
commit 747cabcee9dd5a6666fa376bd2092dbe12452915 Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:56:32 2011 -0400
Sleep less
diff --git a/liveusb/gui.py b/liveusb/gui.py index ab80b31..73ebceb 100755 --- a/liveusb/gui.py +++ b/liveusb/gui.py @@ -141,7 +141,7 @@ class ProgressThread(QtCore.QThread): self.emit(QtCore.SIGNAL("progress(int)"), value) if value >= self.totalsize: break - sleep(4) + sleep(3)
def terminate(self): self.emit(QtCore.SIGNAL("progress(int)"), self.totalsize)
commit 2040ac64fbddfc38a290511cba21f4b711a01a62 Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:56:09 2011 -0400
Spit out the exception, to make pyflakes happy
diff --git a/liveusb/creator.py b/liveusb/creator.py index 4031e4d..532b8c3 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -748,6 +748,7 @@ class LinuxLiveUSBCreator(LiveUSBCreator): try: self.popen('checkisomd5 "%s"' % self.iso) except LiveUSBError, e: + self.log.exception(e) self.log.info(_('ISO MD5 checksum verification failed')) return False self.log.info(_('ISO MD5 checksum passed'))
commit bfcd5533ca667e279c8a25d9b2fecdacd3094ffc Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:55:25 2011 -0400
Make the osmin.img optional, to work with things like the GNOME3 livecd
diff --git a/liveusb/creator.py b/liveusb/creator.py index 0c13c48..4031e4d 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -645,21 +645,29 @@ class LinuxLiveUSBCreator(LiveUSBCreator): liveos = os.path.join(self.dest, 'LiveOS') if not os.path.exists(liveos): os.mkdir(liveos) - for img in ('squashfs.img', 'osmin.img'): - start = datetime.now() - self.popen("cp %s '%s'" % (os.path.join(tmpliveos, img), - os.path.join(liveos, img))) - delta = datetime.now() - start - if delta.seconds: - self.mb_per_sec = (self.isosize / delta.seconds) / 1024**2 - if self.mb_per_sec: - self.log.info(_("Wrote to device at") + " %d MB/sec" % - self.mb_per_sec) + + start = datetime.now() + self.popen("cp %s '%s'" % (os.path.join(tmpliveos, 'squashfs.img'), + os.path.join(liveos, 'squashfs.img'))) + delta = datetime.now() - start + if delta.seconds: + self.mb_per_sec = (self.isosize / delta.seconds) / 1024**2 + if self.mb_per_sec: + self.log.info(_("Wrote to device at") + " %d MB/sec" % + self.mb_per_sec) + + osmin = os.path.join(tmpliveos, 'osmin.img') + if os.path.exists(osmin): + self.popen("cp %s '%s'" % (osmin, + os.path.join(liveos, 'osmin.img'))) + else: + self.log.debug('No osmin.img found') + isolinux = os.path.join(self.dest, 'isolinux') if not os.path.exists(isolinux): os.mkdir(isolinux) - self.popen("cp %s/* '%s'" % (os.path.join(tmpdir, 'isolinux'), - isolinux)) + self.popen("cp %s/* '%s'" % ( + os.path.join(tmpdir, 'isolinux'), isolinux))
if os.path.exists(os.path.join(tmpdir, 'EFI')): efi = os.path.join(self.dest, 'EFI')
commit a0359a0a1f4656c31c394adfc55978dd9f9ca4ea Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:53:43 2011 -0400
Port our mounting code to UDisks, and simplify it a bit
diff --git a/liveusb/creator.py b/liveusb/creator.py index bbb1200..0c13c48 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -548,14 +548,13 @@ class LinuxLiveUSBCreator(LiveUSBCreator): 'uuid' : str(dev.GetProperty('volume.uuid')), 'mount' : mount, 'udi' : dev, - 'unmount' : False, 'free' : mount and self.get_free_bytes(mount) / 1024**2 or None, 'device' : device, 'parent' : parent }
def mount_device(self): - """ Mount our device with HAL if it is not already mounted """ + """ Mount our device if it is not already mounted """ import dbus if not self.fstype: raise LiveUSBError(_("Unknown filesystem. Your device " @@ -568,59 +567,42 @@ class LinuxLiveUSBCreator(LiveUSBCreator): try: self.log.debug("Calling %s.Mount('', %s, [], ...)" % ( self.drive['udi'], self.fstype)) - self.drive['udi'].Mount('', self.fstype, [], - dbus_interface='org.freedesktop.Hal.Device.Volume') - self.drive['unmount'] = True + dev = self._get_device(self.drive['udi']) + dev.FilesystemMount('', [], + dbus_interface='org.freedesktop.UDisks.Device') except dbus.exceptions.DBusException, e: if e.get_dbus_name() == \ 'org.freedesktop.Hal.Device.Volume.AlreadyMounted': self.log.debug('Device already mounted') + else: + self.log.error('Unknown dbus exception:') + self.log.exception(e) except Exception, e: raise LiveUSBError(_("Unable to mount device: %s" % str(e))) - device = self.hal.FindDeviceStringMatch('block.device', - self.drive['device']) - device = self._get_device(device[0]) - self.dest = device.GetProperty('volume.mount_point') - self.log.debug("Mounted %s to %s " % (self.drive['device'], - self.dest)) - self.drive['mount'] = self.dest - self.drive['free'] = self.get_free_bytes(self.dest) / 1024**2 + + # Get the new mount point + udi = self.drive['udi'] + dev_obj = self.bus.get_object("org.freedesktop.UDisks", udi) + dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties") + mounts = map(str, list(dev.Get(udi, 'DeviceMountPaths'))) + if not mounts: + self.log.error(_('No mount points found after mounting attempt')) + else: + self.dest = self.drive['mount'] = mounts[0] + self.drive['free'] = self.get_free_bytes(self.dest) / 1024**2 + self.log.debug("Mounted %s to %s " % (self.drive['device'], + self.dest)) else: self.log.debug("Using existing mount: %s" % self.dest)
- def unmount_device(self, force=False): + def unmount_device(self): """ Unmount our device """ - import dbus - #try: - # unmount = self.drive.get('unmount', None) - #except KeyError, e: - # self.log.exception(e) - # return - if self.dest or force or (self.drive and - self.drive.get('unmount', False)): - self.log.debug("Unmounting %s from %s" % (self.drive['device'], - self.dest)) - try: - self.drive['udi'].Unmount([], - dbus_interface='org.freedesktop.Hal.Device.Volume') - except dbus.exceptions.DBusException, e: - if e.get_dbus_name() in ( - 'org.freedesktop.Hal.Device.Volume.NotMountedByHal', - 'org.freedesktop.Hal.Device.Volume.UnknownFailure'): - self.log.debug('Device not mounted by HAL; trying manually') - self.popen('umount %s' % self.drive['device'], passive=True) - else: - import traceback - self.log.warning("Unable to unmount device: %s" % str(e)) - self.log.debug(traceback.format_exc()) - return - self.drive['unmount'] = False - self.drive['mount'] = None - if os.path.exists(self.dest): - self.log.error("Mount %s exists after unmounting" % self.dest) - self.dest = None - else: - self.log.warning("self.dest and unmount not set, skipping unmount") + self.log.info("Unmounting %s" % self.dest) + self.popen('umount %s' % self.drive['device'], passive=True) + self.drive['mount'] = None + if os.path.exists(self.dest): + self.log.error("Mount %s exists after unmounting" % self.dest) + self.dest = None
def verify_filesystem(self): self.log.info(_("Verifying filesystem...")) @@ -747,7 +729,6 @@ class LinuxLiveUSBCreator(LiveUSBCreator): self.log.debug("Killed process %d" % pid) except OSError: pass - #self.unmount_device()
def verify_iso_md5(self): """ Verify the ISO md5sum. diff --git a/liveusb/gui.py b/liveusb/gui.py index 50daace..ab80b31 100755 --- a/liveusb/gui.py +++ b/liveusb/gui.py @@ -216,11 +216,9 @@ class LiveUSBThread(QtCore.QThread): if self.parent.opts.liveos_checksum: self.live.calculate_liveos_checksum()
- # This sometimes causes segfaults in dbus. - #self.live.unmount_device() - - # Flush all filesystem buffers + # Flush all filesystem buffers and unmount self.live.flush_buffers() + self.live.unmount_device()
duration = str(datetime.now() - now).split('.')[0] self.status(_("Complete! (%s)" % duration)) @@ -459,7 +457,7 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): return if self.live.drive['mount']: self.live.dest = self.live.drive['mount'] - self.live.unmount_device(force=True) + self.live.unmount_device() self.live.reset_mbr() elif not self.live.mbr_matches_syslinux_bin(): if self.opts.reset_mbr: @@ -492,7 +490,7 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): self.status(_("Press 'Create Live USB' again if you wish to " "continue.")) self.confirmed = True - self.live.unmount_device() + #self.live.unmount_device() self.enable_widgets(True) return else: @@ -504,7 +502,7 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): self.live.delete_liveos() except LiveUSBError, e: self.status(e.args[0]) - self.live.unmount_device() + #self.live.unmount_device() self.enable_widgets(True) return
commit f7f9b27e72c527fc5ea4ea07dce63f080c0c549b Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:50:26 2011 -0400
Support ext4, if the version of syslinux-extlinux does
diff --git a/liveusb/creator.py b/liveusb/creator.py index 8dabb3e..bbb1200 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -62,7 +62,8 @@ class LiveUSBCreator(object): _drive = None # mountpoint of the currently selected drive mb_per_sec = 0 # how many megabytes per second we can write log = None - valid_fstypes = ('vfat', 'msdos', 'ext2', 'ext3') + ext_fstypes = ['ext2', 'ext3', 'ext4'] + valid_fstypes = ['vfat', 'msdos'] + ext_fstypes
drive = property(fget=lambda self: self.drives[self._drive], fset=lambda self, d: self._set_drive(d)) @@ -412,12 +413,22 @@ class LiveUSBCreator(object): def is_admin(self): raise NotImplementedError
+ class LinuxLiveUSBCreator(LiveUSBCreator):
bus = None # the dbus.SystemBus hal = None # the org.freedesktop.Hal.Manager dbus.Interface udisks = None # the org.freedesktop.UDisks dbus.Interface
+ def __init__(self, *args, **kw): + super(LinuxLiveUSBCreator, self).__init__(*args, **kw) + extlinux = self.get_extlinux_version() + if extlinux < 4: + self.log.debug(_('You are using an old version of syslinux-extlinux ' + 'that does not support the ext4 filesystem')) + + self.valid_fstypes.remove('ext4') + def detect_removable_drives(self, callback=None): """ Detect all removable USB storage devices using UDisks via D-Bus """ import dbus @@ -706,7 +717,7 @@ class LinuxLiveUSBCreator(LiveUSBCreator): self.log.debug(_("Removing") + " %s" % ldlinux) os.unlink(ldlinux)
- if self.drive['fstype'] in ('ext2', 'ext3'): + if self.drive['fstype'] in self.ext_fstypes: shutil.move(os.path.join(syslinux_path, "syslinux.cfg"), os.path.join(syslinux_path, "extlinux.conf")) self.popen("extlinux -i '%s'" % syslinux_path) @@ -911,6 +922,24 @@ class LinuxLiveUSBCreator(LiveUSBCreator): def is_admin(self): return os.getuid() == 0
+ def get_extlinux_version(self): + """ Return the version of extlinux. None if it isn't installed """ + import subprocess + version = None + p = subprocess.Popen('extlinux -v', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + if p.returncode == 0: + version = int(err.split()[1].split('.')[0]) + elif p.returncode == 127: + self.log.warning('extlinux not found! Only FAT filesystems will be supported') + self.valid_fstypes.remove('ext4') + else: + self.log.debug('Unknown return code from extlinux: %s' % p.returncode) + self.log.debug('stdout: %s\nstderr: %s' % (out, err)) + return version + + class WindowsLiveUSBCreator(LiveUSBCreator):
def detect_removable_drives(self):
commit 867d428a4ab92200824d6a3bb7e15b8baae4a210 Author: Luke Macken lmacken@redhat.com Date: Mon Apr 25 20:44:49 2011 -0400
Port from HAL to UDisks
diff --git a/liveusb/creator.py b/liveusb/creator.py index 604d696..8dabb3e 100755 --- a/liveusb/creator.py +++ b/liveusb/creator.py @@ -416,40 +416,98 @@ class LinuxLiveUSBCreator(LiveUSBCreator):
bus = None # the dbus.SystemBus hal = None # the org.freedesktop.Hal.Manager dbus.Interface + udisks = None # the org.freedesktop.UDisks dbus.Interface
- def detect_removable_drives(self): - """ Detect all removable USB storage devices using HAL via D-Bus """ + def detect_removable_drives(self, callback=None): + """ Detect all removable USB storage devices using UDisks via D-Bus """ import dbus self.drives = {} self.bus = dbus.SystemBus() - hal_obj = self.bus.get_object("org.freedesktop.Hal", - "/org/freedesktop/Hal/Manager") - self.hal = dbus.Interface(hal_obj, "org.freedesktop.Hal.Manager") - - devices = [] - if self.opts.force: - devices = self.hal.FindDeviceStringMatch('block.device', - self.opts.force) - else: - devices = self.hal.FindDeviceByCapability("storage") + udisks_obj = self.bus.get_object("org.freedesktop.UDisks", + "/org/freedesktop/UDisks") + self.udisks = dbus.Interface(udisks_obj, "org.freedesktop.UDisks") + + def handle_reply(devices): + for device in devices: + dev_obj = self.bus.get_object("org.freedesktop.UDisks", device) + dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties") + + data = { + 'udi': str(device), + 'is_optical': bool(dev.Get(device, 'DeviceIsOpticalDisc')), + 'label': str(dev.Get(device, 'IdLabel')).replace(' ', '_'), + 'fstype': str(dev.Get(device, 'IdType')), + 'fsversion': str(dev.Get(device, 'IdVersion')), + 'uuid': str(dev.Get(device, 'IdUuid')), + 'device': str(dev.Get(device, 'DeviceFile')), + 'mount': map(str, list(dev.Get(device, 'DeviceMountPaths'))), + 'bootable': 'boot' in map(str, + list(dev.Get(device, 'PartitionFlags'))), + 'parent': None, + 'size': int(dev.Get(device, 'DeviceSize')), + } + + # Only pay attention to USB devices, unless --force'd + iface = str(dev.Get(device, 'DriveConnectionInterface')) + if iface != 'usb' and self.opts.force != data['device']: + self.log.warning('Skipping non-usb drive: %s' % device) + continue
- for device in devices: - dev = self._get_device(device) - if self.opts.force or self._storage_bus(dev) == "usb": - if self._block_is_volume(dev): - self._add_device(dev) + # Skip optical drives + if data['is_optical'] and self.opts.force != data['device']: + self.log.debug('Skipping optical device: %s' % data['device']) continue - else: # iterate over children looking for a volume - children = self.hal.FindDeviceStringMatch("info.parent", - device) - for child in children: - child = self._get_device(child) - if self._block_is_volume(child): - self._add_device(child, parent=dev) - #break # don't break, allow all partitions
- if not len(self.drives): - raise LiveUSBError(_("Unable to find any USB drives")) + # Skip things without a size + if not data['size'] and not self.opts.force: + self.log.debug('Skipping device without size: %s' % device) + continue + + # Skip devices with unknown filesystems + if data['fstype'] not in self.valid_fstypes and \ + self.opts.force != data['device']: + self.log.debug('Skipping %s with unknown filesystem: %s' % ( + data['device'], data['fstype'])) + continue + + parent = dev.Get(device, 'PartitionSlave') + if parent and parent != '/': + data['parent'] = str(dbus.Interface(self._get_device(parent), + 'org.freedesktop.DBus.Properties').Get(parent, + 'DeviceFile')) + + mount = data['mount'] + if mount: + if len(mount) > 1: + self.log.warning('Multiple mount points for %s' % + data['device']) + mount = data['mount'] = data['mount'][0] + else: + mount = data['mount'] = None + + data['free'] = mount and \ + self.get_free_bytes(mount) / 1024**2 or None + + self.log.debug(pformat(data)) + + self.drives[data['device']] = data + + # Remove parent drives if a valid partition exists + for parent in [d['parent'] for d in self.drives.values()]: + if parent in self.drives: + del(self.drives[parent]) + + if callback: + callback() + + if not len(self.drives): + raise LiveUSBError(_("Unable to find any USB drives")) + + def handle_error(error): + self.log.error(str(error)) + + self.udisks.EnumerateDevices(reply_handler=handle_reply, + error_handler=handle_error)
def _storage_bus(self, dev): storage_bus = None @@ -665,10 +723,10 @@ class LinuxLiveUSBCreator(LiveUSBCreator): return stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
def _get_device(self, udi): - """ Return a dbus Interface to a specific HAL device UDI """ + """ Return a dbus Interface to a specific UDisks device UDI """ import dbus - dev_obj = self.bus.get_object("org.freedesktop.Hal", udi) - return dbus.Interface(dev_obj, "org.freedesktop.Hal.Device") + dev_obj = self.bus.get_object("org.freedesktop.UDisks", udi) + return dbus.Interface(dev_obj, "org.freedesktop.UDisks.Device")
def terminate(self): import signal diff --git a/liveusb/gui.py b/liveusb/gui.py index 3cf2ad9..50daace 100755 --- a/liveusb/gui.py +++ b/liveusb/gui.py @@ -302,14 +302,16 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): return self.driveBox.clear() #self.textEdit.clear() - try: - self.live.detect_removable_drives() + def add_devices(): for device, info in self.live.drives.items(): if info['label']: self.driveBox.addItem("%s (%s)" % (device, info['label'])) else: self.driveBox.addItem(device) self.startButton.setEnabled(True) + + try: + self.live.detect_removable_drives(callback=add_devices) except LiveUSBError, e: self.textEdit.setPlainText(e.args[0]) self.startButton.setEnabled(False) @@ -346,10 +348,10 @@ class LiveUSBDialog(QtGui.QDialog, LiveUSBInterface): self.populate_devices)
# If we have access to HAL & DBus, intercept some useful signals - if hasattr(self.live, 'hal'): - self.live.hal.connect_to_signal('DeviceAdded', + if hasattr(self.live, 'udisks'): + self.live.udisks.connect_to_signal('DeviceAdded', self.populate_devices) - self.live.hal.connect_to_signal('DeviceRemoved', + self.live.udisks.connect_to_signal('DeviceRemoved', self.populate_devices)
@QtCore.pyqtSignature("QString")
liveusb-creator@lists.stg.fedorahosted.org