diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index 1551d7a1..5f0d64bd 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -463,6 +463,15 @@ class Storage(object): for target in parsed_xml.xpath( "//domain/devices/disk/target")]) + def export(self, volume): + ''' Helper function to export volume (pool.export(volume))''' + assert isinstance(volume, (Volume, basestring)), \ + "You need to pass a Volume or pool name as str" + if isinstance(volume, Volume): + return self.pools[volume.name].export(volume) + else: + return self.pools[volume].export(self.vm.volumes[volume]) + class Pool(object): ''' A Pool is used to manage different kind of volumes (File diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 3ccd2688..ea7d1165 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -100,7 +100,12 @@ class ThinPool(qubes.storage.Pool): def export(self, volume): ''' Returns an object that can be `open()`. ''' - return '/dev/' + volume.vid + devpath = '/dev/' + volume.vid + if not os.access(devpath, os.R_OK): + # FIXME: convert to udev rules, and drop after introducing qubesd + subprocess.check_call(['sudo', 'chgrp', 'qubes', devpath]) + subprocess.check_call(['sudo', 'chmod', 'g+rw', devpath]) + return devpath def init_volume(self, vm, volume_config): ''' Initialize a :py:class:`qubes.storage.Volume` from `volume_config`.