mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-24 07:26:29 +00:00
VDI images working now
*Helpful error messages included
This commit is contained in:
parent
6fb60a33f0
commit
efecc15382
6 changed files with 81 additions and 15 deletions
|
@ -6,6 +6,7 @@ class NoPartitions(object):
|
|||
def __init__(self, data):
|
||||
root = data['root']
|
||||
self.root = SinglePartition(root['size'], root['filesystem'])
|
||||
self.partitions = [self.root]
|
||||
self.mount_points = [('/', self.root)]
|
||||
|
||||
def get_total_size(self):
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
|
||||
|
||||
def get_major_minor_dev_num(device_name):
|
||||
def get_partitions():
|
||||
import re
|
||||
regexp = re.compile('^ *(?P<major>\d+) *(?P<minor>\d+) *(?P<num_blks>\d+) {device_name}$'
|
||||
.format(device_name=device_name))
|
||||
with open('/proc/partitions') as partitions:
|
||||
regexp = re.compile('^ *(?P<major>\d+) *(?P<minor>\d+) *(?P<num_blks>\d+) (?P<dev_name>\S+)$')
|
||||
matches = {}
|
||||
path = '/proc/partitions'
|
||||
with open(path) as partitions:
|
||||
next(partitions)
|
||||
next(partitions)
|
||||
for line in partitions:
|
||||
match = regexp.match(line)
|
||||
if match is not None:
|
||||
return match.group('major'), match.group('minor')
|
||||
if match is None:
|
||||
raise RuntimeError('Unable to parse {line} in {path}'.format(line=line, path=path))
|
||||
matches[match.group('dev_name')] = match.groupdict()
|
||||
return matches
|
||||
|
|
|
@ -49,15 +49,17 @@ class LoopbackVolume(Volume):
|
|||
|
||||
def _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)
|
||||
from . import get_major_minor_dev_num
|
||||
major, minor = get_major_minor_dev_num(loop_device_name)
|
||||
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=major,
|
||||
minor=minor,
|
||||
major=loop_device_partition['major'],
|
||||
minor=loop_device_partition['minor'],
|
||||
start_sec=0))
|
||||
import string
|
||||
import os.path
|
||||
|
|
|
@ -64,15 +64,15 @@ class MountBoot(Task):
|
|||
|
||||
|
||||
class CreateBootMountDir(Task):
|
||||
description = 'Creating mountpoint boot partition'
|
||||
description = 'Creating mountpoint for the boot partition'
|
||||
phase = phases.volume_mounting
|
||||
after = [MountRoot]
|
||||
before = [MountBoot]
|
||||
|
||||
def run(self, info):
|
||||
import os
|
||||
info.boot = os.path.join(info.root, 'boot')
|
||||
os.makedirs()
|
||||
boot_dir = os.path.join(info.root, 'boot')
|
||||
os.makedirs(boot_dir)
|
||||
|
||||
|
||||
class MountSpecials(Task):
|
||||
|
|
|
@ -91,7 +91,9 @@ def tasks(tasklist, manifest):
|
|||
break
|
||||
|
||||
if 'boot' in manifest.volume['partitions']:
|
||||
tasklist.add(filesystem.MountBoot(), filesystem.UnmountBoot())
|
||||
tasklist.add(filesystem.CreateBootMountDir(),
|
||||
filesystem.MountBoot(),
|
||||
filesystem.UnmountBoot())
|
||||
|
||||
|
||||
def rollback_tasks(tasklist, tasks_completed, manifest):
|
||||
|
@ -105,7 +107,7 @@ def rollback_tasks(tasklist, tasks_completed, manifest):
|
|||
counter_task(filesystem.CreateMountDir, filesystem.DeleteMountDir)
|
||||
counter_task(partitioning.MapPartitions, partitioning.UnmapPartitions)
|
||||
counter_task(filesystem.MountRoot, filesystem.UnmountRoot)
|
||||
counter_task(filesystem.MountSpecials, filesystem.UnmountSpecials)
|
||||
counter_task(filesystem.MountBoot, filesystem.UnmountBoot)
|
||||
counter_task(filesystem.MountSpecials, filesystem.UnmountSpecials)
|
||||
counter_task(volume_tasks.Attach, volume_tasks.Detach)
|
||||
counter_task(workspace.CreateWorkspace, workspace.DeleteWorkspace)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from common.fs.loopbackvolume import LoopbackVolume
|
||||
from base.fs.exceptions import VolumeError
|
||||
from common.tools import log_check_call
|
||||
from common.fs import get_partitions
|
||||
|
||||
|
||||
class VirtualBoxVolume(LoopbackVolume):
|
||||
|
@ -9,3 +11,57 @@ class VirtualBoxVolume(LoopbackVolume):
|
|||
def _create(self, e):
|
||||
self.image_path = e.image_path
|
||||
log_check_call(['/usr/bin/qemu-img', 'create', '-f', 'vdi', self.image_path, str(self.size) + 'M'])
|
||||
|
||||
def _attach(self, e):
|
||||
num_partitions = len(self.partition_map.partitions)
|
||||
if not self._module_loaded('nbd'):
|
||||
msg = ('The kernel module `nbd\' must be loaded '
|
||||
'(`modprobe nbd max_part={num_partitions}\') to attach .vdi images'
|
||||
.format(num_partitions=num_partitions))
|
||||
raise VolumeError(msg)
|
||||
nbd_max_part = int(self._module_param('nbd', 'max_part'))
|
||||
if nbd_max_part < num_partitions:
|
||||
msg = ('The kernel module `nbd\' was loaded with the max_part '
|
||||
'parameter set to {max_part}, which is below '
|
||||
'the amount of partitions for this volume ({num_partitions}). '
|
||||
'Reload the nbd kernel module with max_part set to at least {num_partitions} '
|
||||
'(`rmmod nbd; modprobe nbd max_part={num_partitions}\').'
|
||||
.format(max_part=nbd_max_part, num_partitions=num_partitions))
|
||||
raise VolumeError(msg)
|
||||
self.loop_device_path = self._find_free_nbd_device()
|
||||
log_check_call(['/usr/bin/qemu-nbd', '--connect', self.loop_device_path, self.image_path])
|
||||
self.device_path = self.loop_device_path
|
||||
|
||||
def _detach(self, e):
|
||||
log_check_call(['/usr/bin/qemu-nbd', '--disconnect', self.loop_device_path])
|
||||
del self.loop_device_path
|
||||
del self.device_path
|
||||
|
||||
def _module_loaded(self, module):
|
||||
import re
|
||||
regexp = re.compile('^{module} +'.format(module=module))
|
||||
with open('/proc/modules') as loaded_modules:
|
||||
for line in loaded_modules:
|
||||
match = regexp.match(line)
|
||||
if match is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _module_param(self, module, param):
|
||||
import os.path
|
||||
param_path = os.path.join('/sys/module', module, 'parameters', param)
|
||||
with open(param_path) as param:
|
||||
return param.read().strip()
|
||||
|
||||
# From http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg02201.html
|
||||
# Apparently it's not in the current qemu-nbd shipped with wheezy
|
||||
def _is_nbd_used(self, device_name):
|
||||
return device_name in get_partitions()
|
||||
|
||||
def _find_free_nbd_device(self):
|
||||
import os.path
|
||||
for i in xrange(0, 15):
|
||||
device_name = 'nbd' + str(i)
|
||||
if not self._is_nbd_used(device_name):
|
||||
return os.path.join('/dev', device_name)
|
||||
raise VolumeError('Unable to find free nbd device.')
|
||||
|
|
Loading…
Add table
Reference in a new issue