2008-09-07 18:56:30 -04:00
#
# Copyright (C) 2008 Red Hat, Inc.
# Copyright (C) 2008 Cole Robinson <crobinso@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
import libvirt
2010-02-11 12:32:00 -05:00
import logging
import os . path
2008-09-07 18:56:30 -04:00
2009-03-09 01:04:29 -04:00
import virtManager
2008-09-07 18:56:30 -04:00
import virtinst
2011-04-18 13:19:39 -04:00
running_config = None
2011-08-29 12:11:43 -04:00
xml_escape = virtinst . util . xml_escape
2013-04-13 14:34:52 -04:00
2010-12-10 18:03:51 -05:00
def get_default_pool_path ( conn ) :
if conn . is_session_uri ( ) :
return os . path . expanduser ( " ~/VirtualMachines " )
return " /var/lib/libvirt/images "
2008-09-07 18:56:30 -04:00
2013-04-13 14:34:52 -04:00
2010-12-10 18:03:51 -05:00
def get_default_pool_name ( conn ) :
ignore = conn
return " default "
2013-04-13 14:34:52 -04:00
2010-12-10 18:03:51 -05:00
def build_default_pool ( vmmconn ) :
2010-03-04 15:31:33 -05:00
"""
Helper to build the ' default ' storage pool
"""
2010-12-10 18:03:51 -05:00
conn = vmmconn . vmm
2010-03-04 15:31:33 -05:00
2010-12-10 18:03:51 -05:00
path = get_default_pool_path ( vmmconn )
name = get_default_pool_name ( vmmconn )
2008-09-07 18:56:30 -04:00
pool = None
try :
2010-12-10 18:03:51 -05:00
pool = conn . storagePoolLookupByName ( name )
2008-09-07 18:56:30 -04:00
except libvirt . libvirtError :
pass
if pool :
return
try :
2012-01-16 22:04:40 -05:00
logging . debug ( " Attempting to build default pool with target ' %s ' " ,
2010-12-10 18:03:51 -05:00
path )
2008-09-07 18:56:30 -04:00
defpool = virtinst . Storage . DirectoryPool ( conn = conn ,
2010-12-10 18:03:51 -05:00
name = name ,
target_path = path )
2008-09-07 18:56:30 -04:00
newpool = defpool . install ( build = True , create = True )
newpool . setAutostart ( True )
except Exception , e :
raise RuntimeError ( _ ( " Couldn ' t create default storage pool ' %s ' : %s " ) %
2010-12-10 18:03:51 -05:00
( path , str ( e ) ) )
2009-01-26 11:12:43 -05:00
2013-04-13 14:34:52 -04:00
2010-12-09 14:06:00 -05:00
def get_ideal_path_info ( conn , name ) :
path = get_default_dir ( conn )
2010-03-04 15:31:33 -05:00
suffix = " .img "
return ( path , name , suffix )
2013-04-13 14:34:52 -04:00
2010-12-09 14:06:00 -05:00
def get_ideal_path ( conn , name ) :
target , name , suffix = get_ideal_path_info ( conn , name )
2010-03-04 15:31:33 -05:00
return os . path . join ( target , name ) + suffix
2013-04-13 14:34:52 -04:00
2010-03-04 15:31:33 -05:00
def get_default_pool ( conn ) :
pool = None
2010-12-10 18:03:51 -05:00
default_name = get_default_pool_name ( conn )
2010-03-04 15:31:33 -05:00
for uuid in conn . list_pool_uuids ( ) :
p = conn . get_pool ( uuid )
2010-12-10 18:03:51 -05:00
if p . get_name ( ) == default_name :
2010-03-04 15:31:33 -05:00
pool = p
return pool
2013-04-13 14:34:52 -04:00
2010-12-09 14:06:00 -05:00
def get_default_dir ( conn ) :
2010-03-04 15:31:33 -05:00
pool = get_default_pool ( conn )
if pool :
return pool . get_target_path ( )
else :
2010-12-09 14:06:00 -05:00
return running_config . get_default_image_dir ( conn )
2010-03-04 15:31:33 -05:00
2013-04-13 14:34:52 -04:00
2011-07-22 19:50:30 -04:00
def get_default_path ( conn , name , collidelist = None ) :
collidelist = collidelist or [ ]
2010-03-04 15:31:33 -05:00
pool = get_default_pool ( conn )
2010-12-09 14:06:00 -05:00
default_dir = get_default_dir ( conn )
2010-03-04 15:31:33 -05:00
2011-07-22 19:50:30 -04:00
def path_exists ( p ) :
return os . path . exists ( p ) or p in collidelist
2010-03-04 15:31:33 -05:00
if not pool :
# Use old generating method
origf = os . path . join ( default_dir , name + " .img " )
f = origf
n = 1
2011-07-22 19:50:30 -04:00
while path_exists ( f ) and n < 100 :
2010-03-04 15:31:33 -05:00
f = os . path . join ( default_dir , name +
" - " + str ( n ) + " .img " )
n + = 1
2011-07-22 19:50:30 -04:00
if path_exists ( f ) :
2010-03-04 15:31:33 -05:00
f = origf
path = f
else :
2010-12-09 14:06:00 -05:00
target , ignore , suffix = get_ideal_path_info ( conn , name )
2010-03-04 15:31:33 -05:00
2011-07-22 19:50:30 -04:00
# Sanitize collidelist to work with the collision checker
2011-08-30 14:29:08 -04:00
newcollidelist = [ ]
for c in collidelist :
if c and os . path . dirname ( c ) == pool . get_target_path ( ) :
newcollidelist . append ( os . path . basename ( c ) )
2011-07-22 19:50:30 -04:00
2010-03-04 15:31:33 -05:00
path = virtinst . Storage . StorageVolume . find_free_name ( name ,
2011-07-22 19:50:30 -04:00
pool_object = pool . pool , suffix = suffix ,
2011-08-30 14:29:08 -04:00
collidelist = newcollidelist )
2010-03-04 15:31:33 -05:00
path = os . path . join ( target , path )
return path
2009-06-18 10:38:15 -04:00
def xml_parse_wrapper ( xml , parse_func , * args , * * kwargs ) :
"""
Parse the passed xml string into an xpath context , which is passed
to parse_func , along with any extra arguments .
"""
2012-02-02 11:58:49 -05:00
import libxml2
2009-06-18 10:38:15 -04:00
doc = None
ctx = None
ret = None
try :
doc = libxml2 . parseDoc ( xml )
ctx = doc . xpathNewContext ( )
ret = parse_func ( doc , ctx , * args , * * kwargs )
finally :
2012-11-08 14:15:02 +01:00
if ctx is not None :
2009-06-18 10:38:15 -04:00
ctx . xpathFreeContext ( )
2012-11-08 14:15:02 +01:00
if doc is not None :
2009-06-18 10:38:15 -04:00
doc . freeDoc ( )
return ret
2009-03-08 15:14:00 -04:00
2010-12-09 14:06:00 -05:00
def browse_local ( parent , dialog_name , conn , start_folder = None ,
2011-04-18 11:32:12 -04:00
_type = None , dialog_type = None ,
2011-09-26 20:44:40 -04:00
confirm_func = None , browse_reason = None ,
choose_button = None ) :
2009-06-22 14:24:09 -04:00
"""
Helper function for launching a filechooser
@param parent : Parent window for the filechooser
@param dialog_name : String to use in the title bar of the filechooser .
2009-06-23 19:30:12 -04:00
@param conn : vmmConnection used by calling class
2009-06-22 14:24:09 -04:00
@param start_folder : Folder the filechooser is viewing at startup
@param _type : File extension to filter by ( e . g . " iso " , " png " )
@param dialog_type : Maps to FileChooserDialog ' action '
@param confirm_func : Optional callback function if file is chosen .
2009-06-23 19:30:12 -04:00
@param browse_reason : The vmmConfig . CONFIG_DIR * reason we are browsing .
If set , this will override the ' folder ' parameter with the gconf
value , and store the user chosen path .
2009-06-22 14:24:09 -04:00
"""
2013-04-13 14:34:52 -04:00
from gi . repository import Gtk # pylint: disable=E0611
2009-03-08 15:14:00 -04:00
2009-11-10 14:30:51 -05:00
# Initial setup
2009-03-08 15:14:00 -04:00
overwrite_confirm = False
2011-04-18 11:32:12 -04:00
if dialog_type is None :
2012-05-14 14:24:56 +01:00
dialog_type = Gtk . FileChooserAction . OPEN
if dialog_type == Gtk . FileChooserAction . SAVE :
2011-09-26 20:44:40 -04:00
if choose_button is None :
2012-05-14 14:24:56 +01:00
choose_button = Gtk . STOCK_SAVE
2011-09-26 20:44:40 -04:00
overwrite_confirm = True
if choose_button is None :
2012-05-14 14:24:56 +01:00
choose_button = Gtk . STOCK_OPEN
2009-03-08 15:14:00 -04:00
2012-05-14 14:24:56 +01:00
fcdialog = Gtk . FileChooserDialog ( title = dialog_name ,
2012-10-14 00:15:04 -04:00
parent = parent ,
action = dialog_type ,
2012-05-14 14:24:56 +01:00
buttons = ( Gtk . STOCK_CANCEL ,
Gtk . ResponseType . CANCEL ,
choose_button ,
Gtk . ResponseType . ACCEPT ) )
fcdialog . set_default_response ( Gtk . ResponseType . ACCEPT )
2009-03-08 15:14:00 -04:00
2009-11-10 14:30:51 -05:00
# If confirm is set, warn about a file overwrite
2009-03-08 15:14:00 -04:00
if confirm_func :
overwrite_confirm = True
fcdialog . connect ( " confirm-overwrite " , confirm_func )
fcdialog . set_do_overwrite_confirmation ( overwrite_confirm )
2009-11-10 14:30:51 -05:00
# Set file match pattern (ex. *.png)
2012-11-08 14:15:02 +01:00
if _type is not None :
2009-03-08 15:14:00 -04:00
pattern = _type
name = None
if type ( _type ) is tuple :
pattern = _type [ 0 ]
name = _type [ 1 ]
2012-05-14 14:24:56 +01:00
f = Gtk . FileFilter ( )
2009-03-08 15:14:00 -04:00
f . add_pattern ( " *. " + pattern )
if name :
f . set_name ( name )
fcdialog . set_filter ( f )
2009-11-10 14:30:51 -05:00
# Set initial dialog folder
if browse_reason :
2010-12-09 14:06:00 -05:00
start_folder = running_config . get_default_directory ( conn ,
browse_reason )
2009-11-10 14:30:51 -05:00
2012-11-08 14:15:02 +01:00
if start_folder is not None :
2010-05-20 15:40:48 -04:00
if os . access ( start_folder , os . R_OK ) :
2009-11-10 14:30:51 -05:00
fcdialog . set_current_folder ( start_folder )
2009-03-08 15:14:00 -04:00
2009-11-10 14:30:51 -05:00
# Run the dialog and parse the response
2012-10-14 00:15:04 -04:00
ret = None
2012-05-14 14:24:56 +01:00
if fcdialog . run ( ) == Gtk . ResponseType . ACCEPT :
2012-10-14 00:15:04 -04:00
ret = fcdialog . get_filename ( )
fcdialog . destroy ( )
2009-06-23 19:30:12 -04:00
2009-11-10 14:30:51 -05:00
# Store the chosen directory in gconf if necessary
2009-06-25 22:12:09 -04:00
if ret and browse_reason and not ret . startswith ( " /dev " ) :
2010-12-09 14:06:00 -05:00
running_config . set_default_directory ( os . path . dirname ( ret ) ,
browse_reason )
2009-06-23 19:30:12 -04:00
return ret
2009-03-08 15:14:00 -04:00
2013-04-13 14:34:52 -04:00
2010-12-09 14:06:00 -05:00
def dup_lib_conn ( libconn ) :
2010-12-10 09:57:42 -05:00
conn = _dup_all_conn ( None , libconn )
if isinstance ( conn , virtManager . connection . vmmConnection ) :
return conn . vmm
return conn
2009-07-14 15:32:39 -04:00
2013-04-13 14:34:52 -04:00
2010-12-09 15:45:05 -05:00
def dup_conn ( conn ) :
return _dup_all_conn ( conn , None )
2009-07-14 15:32:39 -04:00
2013-04-13 14:34:52 -04:00
2010-12-09 15:45:05 -05:00
def _dup_all_conn ( conn , libconn ) :
2009-03-09 01:04:29 -04:00
is_readonly = False
if libconn :
uri = libconn . getURI ( )
is_test = uri . startswith ( " test " )
vmm = libconn
else :
is_test = conn . is_test_conn ( )
is_readonly = conn . is_read_only ( )
uri = conn . get_uri ( )
vmm = conn . vmm
if is_test :
# Skip duplicating a test conn, since it doesn't maintain state
# between instances
2010-12-09 15:45:05 -05:00
return conn or vmm
2009-07-01 14:59:29 -04:00
2011-04-14 15:43:31 -04:00
if running_config . support_threading :
2009-07-01 14:59:29 -04:00
# Libvirt 0.6.0 implemented client side request threading: this
2009-07-01 14:59:29 -04:00
# removes the need to actually duplicate the connection.
2010-12-09 15:45:05 -05:00
return conn or vmm
2009-07-01 14:59:29 -04:00
2009-03-09 01:04:29 -04:00
logging . debug ( " Duplicating connection for async operation. " )
2010-12-09 14:06:00 -05:00
newconn = virtManager . connection . vmmConnection ( uri , readOnly = is_readonly )
2010-11-29 18:00:35 -05:00
newconn . open ( sync = True )
2009-03-09 01:04:29 -04:00
2010-12-09 15:45:05 -05:00
return newconn
2009-05-12 13:09:08 -04:00
2013-04-13 14:34:52 -04:00
2009-05-12 13:09:08 -04:00
def pretty_hv ( gtype , domtype ) :
"""
Convert XML < domain type = ' foo ' > and < os > < type > bar < / type >
into a more human relevant string .
"""
gtype = gtype . lower ( )
domtype = domtype . lower ( )
label = domtype
if domtype == " kvm " :
if gtype == " xen " :
label = " xenner "
elif domtype == " xen " :
if gtype == " xen " :
label = " xen (paravirt) "
elif gtype == " hvm " :
label = " xen (fullvirt) "
elif domtype == " test " :
if gtype == " xen " :
label = " test (xen) "
elif gtype == " hvm " :
label = " test (hvm) "
return label
2009-07-11 21:23:16 -04:00
2013-04-13 14:34:52 -04:00
2009-11-25 16:13:46 -05:00
def uuidstr ( rawuuid ) :
2010-11-29 14:06:43 -05:00
hx = [ ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' ,
' 8 ' , ' 9 ' , ' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' ]
2009-11-25 16:13:46 -05:00
uuid = [ ]
for i in range ( 16 ) :
uuid . append ( hx [ ( ( ord ( rawuuid [ i ] ) >> 4 ) & 0xf ) ] )
uuid . append ( hx [ ( ord ( rawuuid [ i ] ) & 0xf ) ] )
if i == 3 or i == 5 or i == 7 or i == 9 :
uuid . append ( ' - ' )
return " " . join ( uuid )
2009-12-14 16:45:55 -05:00
2013-04-13 14:34:52 -04:00
2010-02-08 17:13:36 -05:00
def iface_in_use_by ( conn , name ) :
use_str = " "
for i in conn . list_interface_names ( ) :
iface = conn . get_interface ( i )
if name in iface . get_slave_names ( ) :
if use_str :
use_str + = " , "
use_str + = iface . get_name ( )
return use_str
2011-04-10 17:08:23 -04:00
2013-04-13 14:34:52 -04:00
2011-04-10 17:08:23 -04:00
def pretty_mem ( val ) :
val = int ( val )
if val > ( 10 * 1024 * 1024 ) :
return " %2.2f GB " % ( val / ( 1024.0 * 1024.0 ) )
else :
return " %2.0f MB " % ( val / 1024.0 )
2013-04-13 14:34:52 -04:00
2011-04-10 17:08:23 -04:00
def pretty_bytes ( val ) :
val = int ( val )
if val > ( 1024 * 1024 * 1024 ) :
return " %2.2f GB " % ( val / ( 1024.0 * 1024.0 * 1024.0 ) )
else :
return " %2.2f MB " % ( val / ( 1024.0 * 1024.0 ) )
xpath = virtinst . util . get_xml_path
2011-04-14 16:43:17 -04:00
2013-04-13 14:34:52 -04:00
2011-07-22 13:11:04 -04:00
def chkbox_helper ( src , getcb , setcb , text1 , text2 = None ,
alwaysrecord = False ,
default = True ,
2011-07-19 20:29:07 -04:00
chktext = _ ( " Don ' t ask me again " ) ) :
2011-04-14 16:43:17 -04:00
"""
Helper to prompt user about proceeding with an operation
2011-07-22 13:11:04 -04:00
Returns True if the ' yes ' or ' ok ' button was selected , False otherwise
@alwaysrecord : Don ' t require user to select ' yes ' to record chkbox value
@default : What value to return if getcb tells us not to prompt
2011-04-14 16:43:17 -04:00
"""
2013-04-13 14:34:52 -04:00
from gi . repository import Gtk # pylint: disable=E0611
2011-04-18 11:32:12 -04:00
2011-04-14 16:43:17 -04:00
do_prompt = getcb ( )
if not do_prompt :
2011-07-22 13:11:04 -04:00
return default
2011-04-14 16:43:17 -04:00
res = src . err . warn_chkbox ( text1 = text1 , text2 = text2 ,
2011-07-19 20:29:07 -04:00
chktext = chktext ,
2012-05-14 14:24:56 +01:00
buttons = Gtk . ButtonsType . YES_NO )
2011-04-14 16:43:17 -04:00
response , skip_prompt = res
2011-07-19 20:29:07 -04:00
if alwaysrecord or response :
setcb ( not skip_prompt )
2011-04-14 16:43:17 -04:00
2011-07-22 13:11:04 -04:00
return response
2011-06-08 18:16:12 -04:00
2013-04-13 14:34:52 -04:00
2011-06-08 18:16:12 -04:00
def get_list_selection ( widget ) :
selection = widget . get_selection ( )
active = selection . get_selected ( )
treestore , treeiter = active
2012-11-08 14:15:02 +01:00
if treeiter is not None :
2011-06-08 18:16:12 -04:00
return treestore [ treeiter ]
return None
2013-04-13 14:34:52 -04:00
2011-06-08 18:16:12 -04:00
def set_list_selection ( widget , rownum ) :
path = str ( rownum )
selection = widget . get_selection ( )
selection . unselect_all ( )
widget . set_cursor ( path )
selection . select_path ( path )