From 8165297a0285fa440db37d6fd85fb80f4546fe12 Mon Sep 17 00:00:00 2001 From: Anders Ingemann Date: Sat, 18 Jan 2014 16:33:41 +0100 Subject: [PATCH] Generalize link_dm_node() it works for all devices Also accept some new parameters to adjust offsets and startsecotrs when creating the disk mapping --- base/fs/volume.py | 49 +++++++++++++++++++++++++++++++++++++ common/fs/loopbackvolume.py | 45 ---------------------------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/base/fs/volume.py b/base/fs/volume.py index aba03f9..cf3353b 100644 --- a/base/fs/volume.py +++ b/base/fs/volume.py @@ -11,12 +11,15 @@ class Volume(FSMProxy): 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'}, ] def __init__(self, partition_map): self.device_path = None + self.real_device_path = None self.partition_map = partition_map self.size = self.partition_map.get_total_size() @@ -25,6 +28,8 @@ class Volume(FSMProxy): def set_dev_path(e): self.partition_map.root.device_path = self.device_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} super(Volume, self).__init__(cfg) @@ -36,3 +41,47 @@ class Volume(FSMProxy): def _check_blocking(self, e): if self.partition_map.is_blocking(): 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 diff --git a/common/fs/loopbackvolume.py b/common/fs/loopbackvolume.py index 3a6ef0d..4355c41 100644 --- a/common/fs/loopbackvolume.py +++ b/common/fs/loopbackvolume.py @@ -1,18 +1,9 @@ from base.fs.volume import Volume from common.tools import log_check_call -from base.fs.exceptions import VolumeError 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 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.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