2016-06-16 17:28:51 -04:00
#
# Copyright 2006-2009, 2013, 2014 Red Hat, Inc.
#
2018-04-04 14:35:41 +01:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 15:00:02 -04:00
# See the COPYING file in the top-level directory.
2016-06-16 17:28:51 -04:00
import logging
import os
2019-06-07 17:32:51 -04:00
from . import progress
2018-03-20 12:27:37 -04:00
from . devices import DeviceDisk
2016-06-16 17:28:51 -04:00
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 :
logging . debug ( " Existing pool ' %s ' found for %s " , pool . name ( ) , path )
2019-04-14 19:16:10 -04:00
StoragePool . ensure_pool_is_running ( pool , refresh = True )
2016-06-16 17:28:51 -04:00
return pool
2017-07-18 19:09:58 -04:00
name = StoragePool . find_free_name ( conn , " boot-scratch " )
2016-06-16 17:28:51 -04:00
logging . 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
2019-06-08 09:41:52 -04:00
class _MockStream :
_data_size = None
def send ( self , data ) :
if self . _data_size is None :
self . _data_size = len ( data )
block_size = 1024
ret = min ( self . _data_size , block_size )
self . _data_size = max ( 0 , self . _data_size - block_size )
return ret
def finish ( self ) :
pass
2016-06-16 17:28:51 -04:00
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
2019-06-08 09:41:52 -04:00
if conn . in_testsuite ( ) :
stream = _MockStream ( )
else :
stream = conn . newStream ( 0 )
2016-06-16 17:28:51 -04:00
def safe_send ( data ) :
while True :
ret = stream . send ( data )
if ret == 0 or ret == len ( data ) :
break
data = data [ ret : ]
2019-06-07 17:32:51 -04:00
meter = progress . ensure_meter ( meter )
2016-06-16 17:28:51 -04:00
# Build placeholder volume
size = os . path . getsize ( src )
basename = os . path . basename ( src )
name = StorageVolume . find_free_name ( destpool , basename )
if name != basename :
logging . debug ( " Generated non-colliding volume name %s " , name )
2018-03-20 12:18:35 -04:00
vol_install = DeviceDisk . build_vol_install ( conn , name , destpool ,
2016-06-16 17:28:51 -04:00
( float ( size ) / 1024.0 / 1024.0 / 1024.0 ) , True )
2018-03-20 12:18:35 -04:00
disk = DeviceDisk ( conn )
2016-06-16 17:28:51 -04:00
disk . set_vol_install ( vol_install )
disk . validate ( )
2018-09-03 16:44:38 -04:00
disk . build_storage ( meter )
2016-06-16 17:28:51 -04:00
vol = disk . get_vol_object ( )
if not vol :
2019-03-15 13:42:27 -04:00
raise RuntimeError ( " Failed to lookup scratch media volume " )
2016-06-16 17:28:51 -04:00
try :
# Register upload
offset = 0
length = size
flags = 0
2019-06-08 09:41:52 -04:00
if not conn . in_testsuite ( ) :
vol . upload ( stream , offset , length , flags )
2016-06-16 17:28:51 -04:00
# Open source file
2018-03-18 11:50:22 -04:00
fileobj = open ( src , " rb " )
2016-06-16 17:28:51 -04:00
# Start transfer
total = 0
meter . start ( size = size ,
text = _ ( " Transferring %s " ) % os . path . basename ( src ) )
while True :
# blocksize = (1024 ** 2)
blocksize = 1024
data = fileobj . read ( blocksize )
if not data :
break
safe_send ( data )
total + = len ( data )
meter . update ( total )
# Cleanup
stream . finish ( )
meter . end ( size )
2017-07-24 09:26:48 +01:00
except Exception :
2018-03-18 11:50:22 -04:00
vol . delete ( 0 )
2016-06-16 17:28:51 -04:00
raise
return vol
def upload_kernel_initrd ( conn , scratchdir , system_scratchdir ,
meter , kernel , initrd ) :
"""
Upload kernel / initrd media to remote connection if necessary
"""
tmpvols = [ ]
if ( not conn . is_remote ( ) and
( conn . is_session_uri ( ) or scratchdir == system_scratchdir ) ) :
# We have access to system scratchdir, don't jump through hoops
logging . debug ( " Have access to preferred scratchdir so "
" nothing to upload " )
return kernel , initrd , tmpvols
2019-02-28 12:23:00 -05:00
if not conn . support_remote_url_install ( ) :
# Needed for the test_urls suite
logging . debug ( " Media upload not supported " )
return kernel , initrd , tmpvols
2016-06-16 17:28:51 -04:00
# Build pool
logging . debug ( " Uploading kernel/initrd media " )
pool = _build_pool ( conn , meter , system_scratchdir )
kvol = _upload_file ( conn , meter , pool , kernel )
newkernel = kvol . path ( )
tmpvols . append ( kvol )
ivol = _upload_file ( conn , meter , pool , initrd )
newinitrd = ivol . path ( )
tmpvols . append ( ivol )
return newkernel , newinitrd , tmpvols