Generalize link_dm_node() it works for all devices

Also accept some new parameters to adjust offsets and startsecotrs when creating the disk mapping
This commit is contained in:
Anders Ingemann 2014-01-18 16:33:41 +01:00
parent 150073e354
commit 8165297a02
2 changed files with 49 additions and 45 deletions

View file

@ -11,12 +11,15 @@ class Volume(FSMProxy):
events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'detached'}, events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'detached'},
{'name': 'attach', 'src': 'detached', 'dst': 'attached'}, {'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': 'detach', 'src': 'attached', 'dst': 'detached'},
{'name': 'delete', 'src': 'detached', 'dst': 'deleted'}, {'name': 'delete', 'src': 'detached', 'dst': 'deleted'},
] ]
def __init__(self, partition_map): def __init__(self, partition_map):
self.device_path = None self.device_path = None
self.real_device_path = None
self.partition_map = partition_map self.partition_map = partition_map
self.size = self.partition_map.get_total_size() self.size = self.partition_map.get_total_size()
@ -25,6 +28,8 @@ class Volume(FSMProxy):
def set_dev_path(e): def set_dev_path(e):
self.partition_map.root.device_path = self.device_path self.partition_map.root.device_path = self.device_path
callbacks['onafterattach'] = set_dev_path callbacks['onafterattach'] = set_dev_path
callbacks['onlink_dm_node'] = set_dev_path
callbacks['onunlink_dm_node'] = set_dev_path
cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': callbacks} cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': callbacks}
super(Volume, self).__init__(cfg) super(Volume, self).__init__(cfg)
@ -36,3 +41,47 @@ class Volume(FSMProxy):
def _check_blocking(self, e): def _check_blocking(self, e):
if self.partition_map.is_blocking(): if self.partition_map.is_blocking():
raise VolumeError('The partitionmap prevents the detach procedure') raise VolumeError('The partitionmap prevents the detach procedure')
def _before_link_dm_node(self, e):
import os.path
from common.fs import get_partitions
proc_partitions = get_partitions()
device_name = os.path.basename(self.device_path)
device_partition = proc_partitions[device_name]
# The sector the volume should start at in the new volume
logical_start_sector = getattr(e, 'logical_start_sector', 0)
# The offset at which the volume should begin to be mapped in the new volume
start_sector = getattr(e, 'start_sector', 0)
sectors = getattr(e, 'sectors', self.size * 1024 * 1024 / 512 - start_sector)
table = ('{log_start_sec} {sectors} linear {major}:{minor} {start_sec}'
.format(log_start_sec=logical_start_sector,
sectors=sectors,
major=device_partition['major'],
minor=device_partition['minor'],
start_sec=start_sector))
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.unlinked_device_path = self.device_path
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.unlinked_device_path

View file

@ -1,18 +1,9 @@
from base.fs.volume import Volume from base.fs.volume import Volume
from common.tools import log_check_call from common.tools import log_check_call
from base.fs.exceptions import VolumeError
class LoopbackVolume(Volume): 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' extension = 'raw'
def create(self, image_path): def create(self, image_path):
@ -26,42 +17,6 @@ class LoopbackVolume(Volume):
[self.loop_device_path] = log_check_call(['/sbin/losetup', '--show', '--find', self.image_path]) [self.loop_device_path] = log_check_call(['/sbin/losetup', '--show', '--find', self.image_path])
self.device_path = self.loop_device_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): def _before_detach(self, e):
log_check_call(['/sbin/losetup', '--detach', self.loop_device_path]) log_check_call(['/sbin/losetup', '--detach', self.loop_device_path])
del self.loop_device_path del self.loop_device_path