1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
#
# Copyright 2006-2009, 2013, 2014 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import os
from .. import progress
from ..devices import DeviceDisk
from ..logger import log
from ..storage import StoragePool, StorageVolume
def _build_pool(conn, meter, path):
"""
Helper function for building a pool on demand. Used for building
a scratchdir pool for volume upload
"""
pool = StoragePool.lookup_pool_by_path(conn, path)
if pool: # pragma: no cover
log.debug("Existing pool '%s' found for %s", pool.name(), path)
StoragePool.ensure_pool_is_running(pool, refresh=True)
return pool
name = StoragePool.find_free_name(conn, "boot-scratch")
log.debug("Building storage pool: path=%s name=%s", path, name)
poolbuild = StoragePool(conn)
poolbuild.type = poolbuild.TYPE_DIR
poolbuild.name = name
poolbuild.target_path = path
# Explicitly don't build? since if we are creating this directory
# we probably don't have correct perms
ret = poolbuild.install(meter=meter, create=True, build=False,
autostart=True)
return ret
class _MockStream:
_data_size = None
def send(self, data):
if self._data_size is None:
self._data_size = len(data)
block_size = 128
ret = min(self._data_size, block_size)
self._data_size = max(0, self._data_size - block_size)
return ret
def finish(self):
pass
def _upload_file(conn, meter, destpool, src):
"""
Helper for uploading a file to a pool, via libvirt. Used for
kernel/initrd upload when we can't access the system scratchdir
"""
# Build stream object
if conn.in_testsuite():
stream = _MockStream()
else:
stream = conn.newStream(0) # pragma: no cover
def safe_send(data):
while True:
ret = stream.send(data)
if ret == 0 or ret == len(data):
break
data = data[ret:]
meter = progress.ensure_meter(meter)
# Build placeholder volume
size = os.path.getsize(src)
basename = os.path.basename(src)
name = StorageVolume.find_free_name(conn, destpool, basename)
log.debug("Generated volume name %s", name)
vol_install = DeviceDisk.build_vol_install(conn, name, destpool,
(float(size) / 1024.0 / 1024.0 / 1024.0), True)
disk = DeviceDisk(conn)
disk.set_vol_install(vol_install)
disk.validate()
disk.build_storage(meter)
vol = disk.get_vol_object()
if not vol:
raise RuntimeError( # pragma: no cover
"Failed to lookup scratch media volume")
try:
# Register upload
offset = 0
length = size
flags = 0
if not conn.in_testsuite():
vol.upload(stream, offset, length, flags) # pragma: no cover
# Open source file
fileobj = open(src, "rb")
# Start transfer
total = 0
msg = _("Transferring '%(filename)s'") % {
"filename": os.path.basename(src)}
meter.start(msg, size)
while True:
blocksize = 1024 * 1024 # 1 MiB
data = fileobj.read(blocksize)
if not data:
break
safe_send(data)
total += len(data)
meter.update(total)
# Cleanup
stream.finish()
meter.end()
except Exception: # pragma: no cover
vol.delete(0)
raise
return vol
def upload_paths(conn, system_scratchdir, meter, pathlist):
"""
Upload passed paths to the connection scratchdir
"""
# Build pool
log.debug("Uploading kernel/initrd media")
pool = _build_pool(conn, meter, system_scratchdir)
tmpvols = []
newpaths = []
try:
for path in pathlist:
vol = _upload_file(conn, meter, pool, path)
newpaths.append(vol.path())
tmpvols.append(vol)
except Exception: # pragma: no cover
for vol in tmpvols:
vol.delete(0)
raise
return newpaths, tmpvols
|