2013-09-15 13:19:45 +02:00
|
|
|
from base.fs.volume import Volume
|
|
|
|
from common.tools import log_check_call
|
|
|
|
from base.fs.exceptions import VolumeError
|
|
|
|
|
|
|
|
|
|
|
|
# QEMU formats:
|
|
|
|
# raw, host_device, qcow2, qcow, cow, vdi, vmdk, vpc, cloop
|
|
|
|
|
|
|
|
|
|
|
|
class LoopbackVolume(Volume):
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'detached'},
|
|
|
|
{'name': 'attach', 'src': 'detached', 'dst': 'attached'},
|
|
|
|
{'name': 'link_dm_node', 'src': 'attached', 'dst': 'linked'},
|
|
|
|
{'name': 'unlink_dm_node', 'src': 'linked', 'dst': 'attached'},
|
|
|
|
{'name': 'detach', 'src': 'attached', 'dst': 'detached'},
|
|
|
|
{'name': 'delete', 'src': 'detached', 'dst': 'deleted'},
|
|
|
|
]
|
2013-09-15 13:19:45 +02:00
|
|
|
|
|
|
|
def create(self, image_path):
|
|
|
|
self.fsm.create(image_path=image_path)
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_create(self, e):
|
2013-09-15 13:19:45 +02:00
|
|
|
self.image_path = e.image_path
|
|
|
|
log_check_call(['/usr/bin/qemu-img', 'create', '-f', 'raw', self.image_path, str(self.size) + 'M'])
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_attach(self, e):
|
2013-09-15 13:19:45 +02:00
|
|
|
[self.loop_device_path] = log_check_call(['/sbin/losetup', '--show', '--find', self.image_path])
|
|
|
|
self.device_path = self.loop_device_path
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_link_dm_node(self, e):
|
2013-09-15 17:07:57 +02:00
|
|
|
import os.path
|
2013-09-15 18:26:22 +02:00
|
|
|
from . import get_partitions
|
|
|
|
proc_partitions = get_partitions()
|
2013-09-15 17:07:57 +02:00
|
|
|
loop_device_name = os.path.basename(self.loop_device_path)
|
2013-09-15 18:26:22 +02:00
|
|
|
loop_device_partition = proc_partitions[loop_device_name]
|
|
|
|
|
2013-12-14 19:37:23 +01:00
|
|
|
sectors = self.size * 1024 * 1024 / 512
|
2013-09-15 13:19:45 +02:00
|
|
|
table = ('{log_start_sec} {sectors} linear {major}:{minor} {start_sec}'
|
|
|
|
.format(log_start_sec=0,
|
|
|
|
sectors=sectors,
|
2013-09-15 18:26:22 +02:00
|
|
|
major=loop_device_partition['major'],
|
|
|
|
minor=loop_device_partition['minor'],
|
2013-09-15 13:19:45 +02:00
|
|
|
start_sec=0))
|
|
|
|
import string
|
|
|
|
import os.path
|
|
|
|
for letter in string.ascii_lowercase:
|
|
|
|
dev_name = 'vd' + letter
|
|
|
|
dev_path = os.path.join('/dev/mapper', dev_name)
|
|
|
|
if not os.path.exists(dev_path):
|
|
|
|
self.dm_node_name = dev_name
|
|
|
|
self.dm_node_path = dev_path
|
|
|
|
break
|
|
|
|
|
|
|
|
if not hasattr(self, 'dm_node_name'):
|
|
|
|
raise VolumeError('Unable to find a free block device path for mounting the bootstrap volume')
|
|
|
|
|
|
|
|
log_check_call(['/sbin/dmsetup', 'create', self.dm_node_name], table)
|
|
|
|
self.device_path = self.dm_node_path
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_unlink_dm_node(self, e):
|
2013-09-15 13:19:45 +02:00
|
|
|
log_check_call(['/sbin/dmsetup', 'remove', self.dm_node_name])
|
|
|
|
del self.dm_node_name
|
|
|
|
del self.dm_node_path
|
|
|
|
self.device_path = self.loop_device_path
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_detach(self, e):
|
2013-09-15 13:19:45 +02:00
|
|
|
log_check_call(['/sbin/losetup', '--detach', self.loop_device_path])
|
|
|
|
del self.loop_device_path
|
|
|
|
del self.device_path
|
|
|
|
|
2013-09-22 21:20:09 +02:00
|
|
|
def _before_delete(self, e):
|
2013-09-15 13:19:45 +02:00
|
|
|
from os import remove
|
|
|
|
remove(self.image_path)
|
|
|
|
del self.image_path
|