bootstrap-vz/common/fs/loopbackvolume.py
2013-10-27 18:11:53 +01:00

80 lines
2.7 KiB
Python

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):
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'},
]
extension = 'raw'
def __init__(self, partition_map):
super(LoopbackVolume, self).__init__(partition_map)
def create(self, image_path):
self.fsm.create(image_path=image_path)
def _before_create(self, e):
self.image_path = e.image_path
log_check_call(['/usr/bin/qemu-img', 'create', '-f', 'raw', self.image_path, str(self.size) + 'M'])
def _before_attach(self, e):
[self.loop_device_path] = log_check_call(['/sbin/losetup', '--show', '--find', self.image_path])
self.device_path = self.loop_device_path
def _before_link_dm_node(self, e):
import os.path
from . import get_partitions
proc_partitions = get_partitions()
loop_device_name = os.path.basename(self.loop_device_path)
loop_device_partition = proc_partitions[loop_device_name]
sectors = self.size*1024*1024/512
table = ('{log_start_sec} {sectors} linear {major}:{minor} {start_sec}'
.format(log_start_sec=0,
sectors=sectors,
major=loop_device_partition['major'],
minor=loop_device_partition['minor'],
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
def _before_unlink_dm_node(self, e):
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
def _before_detach(self, e):
log_check_call(['/sbin/losetup', '--detach', self.loop_device_path])
del self.loop_device_path
del self.device_path
def _before_delete(self, e):
from os import remove
remove(self.image_path)
del self.image_path