2008-08-15 19:24:24 +04:00
#
2014-01-20 20:09:13 +04:00
# Copyright (C) 2008, 2013, 2014 Red Hat, Inc.
2008-08-15 19:24:24 +04:00
# 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 logging
2012-05-14 17:24:56 +04:00
from gi . repository import GObject
from gi . repository import Gtk
from gi . repository import Gdk
2011-04-18 20:39:53 +04:00
2014-09-13 00:10:45 +04:00
from . import uiutil
from . baseclass import vmmGObjectUI
from . asyncjob import vmmAsyncJob
2008-08-15 19:24:24 +04:00
2013-09-20 04:18:12 +04:00
from virtinst import StorageVolume
2008-08-15 19:24:24 +04:00
2013-04-13 22:34:52 +04:00
2010-12-09 01:26:19 +03:00
class vmmCreateVolume ( vmmGObjectUI ) :
2012-05-14 17:24:56 +04:00
__gsignals__ = {
2015-04-09 21:42:25 +03:00
" vol-created " : ( GObject . SignalFlags . RUN_FIRST , None , [ str , str ] ) ,
2012-05-14 17:24:56 +04:00
}
2010-12-09 01:26:19 +03:00
def __init__ ( self , conn , parent_pool ) :
2013-09-23 00:10:16 +04:00
vmmGObjectUI . __init__ ( self , " createvol.ui " , " vmm-create-vol " )
2008-08-15 19:24:24 +04:00
self . conn = conn
self . parent_pool = parent_pool
2009-11-15 23:57:38 +03:00
self . name_hint = None
2008-08-15 19:24:24 +04:00
self . vol = None
2013-09-29 18:53:37 +04:00
self . storage_browser = None
2008-08-15 19:24:24 +04:00
2013-02-16 22:31:46 +04:00
self . builder . connect_signals ( {
2008-09-06 21:20:35 +04:00
" on_vmm_create_vol_delete_event " : self . close ,
2008-08-15 19:24:24 +04:00
" on_vol_cancel_clicked " : self . close ,
" on_vol_create_clicked " : self . finish ,
2013-09-29 18:53:37 +04:00
2009-10-05 19:34:39 +04:00
" on_vol_name_changed " : self . vol_name_changed ,
2013-10-01 22:49:19 +04:00
" on_vol_format_changed " : self . vol_format_changed ,
" on_backing_store_changed " : self . _show_alloc ,
2009-10-05 19:50:10 +04:00
" on_vol_allocation_value_changed " : self . vol_allocation_changed ,
" on_vol_capacity_value_changed " : self . vol_capacity_changed ,
2013-09-29 18:53:37 +04:00
" on_backing_browse_clicked " : self . browse_backing ,
2008-08-15 19:24:24 +04:00
} )
2011-04-18 19:25:28 +04:00
self . bind_escape_key_close ( )
2008-08-15 19:24:24 +04:00
2013-09-22 20:18:49 +04:00
self . _init_state ( )
2008-08-15 19:24:24 +04:00
self . reset_state ( )
2011-04-14 16:47:42 +04:00
def show ( self , parent ) :
2015-08-10 23:45:44 +03:00
try :
parent_xml = self . parent_pool . xmlobj . get_xml_config ( )
except :
logging . debug ( " Error getting parent_pool xml " , exc_info = True )
parent_xml = None
logging . debug ( " Showing new volume wizard for parent_pool= \n %s " ,
parent_xml )
2009-03-08 22:16:47 +03:00
self . reset_state ( )
2011-04-14 16:47:42 +04:00
self . topwin . set_transient_for ( parent )
2008-08-15 19:24:24 +04:00
self . topwin . present ( )
def close ( self , ignore1 = None , ignore2 = None ) :
2012-02-01 03:16:54 +04:00
logging . debug ( " Closing new volume wizard " )
2008-08-15 19:24:24 +04:00
self . topwin . hide ( )
2013-09-29 18:53:37 +04:00
if self . storage_browser :
self . storage_browser . close ( )
2009-03-08 22:16:47 +03:00
self . set_modal ( False )
2008-08-15 19:24:24 +04:00
return 1
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
self . conn = None
self . parent_pool = None
2011-04-12 02:35:21 +04:00
2013-09-29 18:53:37 +04:00
if self . storage_browser :
self . storage_browser . cleanup ( )
self . storage_browser = None
2009-11-15 23:57:38 +03:00
def set_name_hint ( self , hint ) :
self . name_hint = hint
2009-03-08 22:16:47 +03:00
def set_modal ( self , modal ) :
self . topwin . set_modal ( bool ( modal ) )
2013-08-13 16:26:26 +04:00
def set_parent_pool ( self , conn , pool ) :
self . conn = conn
2008-08-15 19:24:24 +04:00
self . parent_pool = pool
2009-11-15 23:57:38 +03:00
def default_vol_name ( self ) :
if not self . name_hint :
return " "
suffix = self . default_suffix ( )
2010-02-22 16:49:21 +03:00
ret = " "
2009-11-15 23:57:38 +03:00
try :
2013-10-01 00:21:23 +04:00
ret = StorageVolume . find_free_name (
self . parent_pool . get_backend ( ) , self . name_hint , suffix = suffix )
2009-11-15 23:57:38 +03:00
except :
2013-09-27 21:15:57 +04:00
logging . exception ( " Error finding a default vol name " )
2010-02-22 16:49:21 +03:00
return ret
2009-11-15 23:57:38 +03:00
def default_suffix ( self ) :
2014-02-05 02:30:24 +04:00
if self . vol . file_type != self . vol . TYPE_FILE :
return " "
return StorageVolume . get_file_extension_for_format (
self . get_config_format ( ) )
2009-11-15 23:57:38 +03:00
2013-09-22 20:18:49 +04:00
def _init_state ( self ) :
2013-09-27 21:05:52 +04:00
blue = Gdk . color_parse ( " #0072A8 " )
self . widget ( " header " ) . modify_bg ( Gtk . StateType . NORMAL , blue )
2013-09-22 20:18:49 +04:00
format_list = self . widget ( " vol-format " )
format_model = Gtk . ListStore ( str , str )
format_list . set_model ( format_model )
2015-04-10 20:04:02 +03:00
uiutil . init_combo_text_column ( format_list , 1 )
2013-09-22 20:18:49 +04:00
2013-09-20 04:18:12 +04:00
def _make_stub_vol ( self ) :
self . vol = StorageVolume ( self . conn . get_backend ( ) )
self . vol . pool = self . parent_pool . get_backend ( )
2015-04-11 21:56:23 +03:00
def _can_only_sparse ( self ) :
2013-10-01 22:49:19 +04:00
if self . get_config_format ( ) == " qcow2 " :
2015-04-11 21:56:23 +03:00
return True
2013-10-01 22:49:19 +04:00
if ( self . widget ( " backing-store " ) . is_visible ( ) and
self . widget ( " backing-store " ) . get_text ( ) ) :
2015-04-11 21:56:23 +03:00
return True
return False
def _can_alloc ( self ) :
if self . _can_only_sparse ( ) :
return False
if self . parent_pool . get_type ( ) == " logical " :
# Sparse LVM volumes don't auto grow, so alloc=0 is useless
2013-10-01 22:49:19 +04:00
return False
return True
def _show_alloc ( self , * args , * * kwargs ) :
ignore = args
ignore = kwargs
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible (
2013-10-01 22:49:19 +04:00
self . widget ( " vol-allocation " ) , self . _can_alloc ( ) )
def _can_backing ( self ) :
if self . parent_pool . get_type ( ) == " logical " :
return True
if self . get_config_format ( ) == " qcow2 " :
return True
return False
def _show_backing ( self ) :
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible (
2013-10-01 22:49:19 +04:00
self . widget ( " backing-expander " ) , self . _can_backing ( ) )
2013-09-29 18:53:37 +04:00
2008-08-15 19:24:24 +04:00
def reset_state ( self ) :
2013-09-20 04:18:12 +04:00
self . _make_stub_vol ( )
2015-09-14 23:29:16 +03:00
self . widget ( " vol-name " ) . set_text ( self . default_vol_name ( ) or " " )
2011-07-14 21:13:13 +04:00
self . widget ( " vol-name " ) . grab_focus ( )
2013-09-27 21:15:57 +04:00
self . vol_name_changed ( self . widget ( " vol-name " ) )
2008-08-15 19:24:24 +04:00
2013-09-27 21:15:57 +04:00
self . populate_vol_format ( )
2013-09-27 21:20:45 +04:00
hasformat = bool ( len ( self . vol . list_formats ( ) ) )
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible ( self . widget ( " vol-format " ) , hasformat )
2013-09-27 21:20:45 +04:00
if hasformat :
2013-10-01 22:49:19 +04:00
# Select the default storage format
2011-07-14 21:13:13 +04:00
self . widget ( " vol-format " ) . set_active ( 0 )
2013-10-02 23:17:15 +04:00
default = self . conn . get_default_storage_format ( )
2013-10-01 22:49:19 +04:00
for row in self . widget ( " vol-format " ) . get_model ( ) :
if row [ 0 ] == default :
self . widget ( " vol-format " ) . set_active_iter ( row . iter )
break
2008-08-15 19:24:24 +04:00
2013-09-27 21:05:52 +04:00
default_alloc = 0
2015-09-14 02:30:10 +03:00
default_cap = 20
2013-09-27 21:05:52 +04:00
2013-10-01 22:49:19 +04:00
self . widget ( " backing-store " ) . set_text ( " " )
2013-09-27 21:05:52 +04:00
alloc = default_alloc
2013-09-29 18:53:37 +04:00
if not self . _can_alloc ( ) :
alloc = default_cap
2013-10-01 22:49:19 +04:00
self . _show_alloc ( )
self . _show_backing ( )
2013-09-29 18:53:37 +04:00
self . widget ( " backing-expander " ) . set_expanded ( False )
2013-03-13 18:29:22 +04:00
2011-07-14 21:13:13 +04:00
self . widget ( " vol-allocation " ) . set_range ( 0 ,
2013-09-27 21:05:52 +04:00
int ( self . parent_pool . get_available ( ) / 1024 / 1024 / 1024 ) )
2013-03-13 18:29:22 +04:00
self . widget ( " vol-allocation " ) . set_value ( alloc )
2015-04-11 21:56:23 +03:00
self . widget ( " vol-capacity " ) . set_range ( 0.1 , 1000000 )
2013-09-27 21:05:52 +04:00
self . widget ( " vol-capacity " ) . set_value ( default_cap )
2008-08-15 19:24:24 +04:00
2011-07-14 21:13:13 +04:00
self . widget ( " vol-parent-name " ) . set_markup (
" <b> " + self . parent_pool . get_name ( ) + " ' s</b> " )
self . widget ( " vol-parent-space " ) . set_text (
self . parent_pool . get_pretty_available ( ) )
2008-08-15 19:24:24 +04:00
def get_config_format ( self ) :
2015-05-20 00:17:53 +03:00
return uiutil . get_list_selection ( self . widget ( " vol-format " ) )
2008-08-15 19:24:24 +04:00
def populate_vol_format ( self ) :
2014-01-20 20:09:13 +04:00
stable_whitelist = [ " raw " , " qcow2 " , " qed " ]
2011-07-14 21:13:13 +04:00
model = self . widget ( " vol-format " ) . get_model ( )
2008-08-15 19:24:24 +04:00
model . clear ( )
2011-03-08 21:57:56 +03:00
2013-09-20 04:18:12 +04:00
formats = self . vol . list_formats ( )
if self . vol . list_create_formats ( ) is not None :
formats = self . vol . list_create_formats ( )
2011-03-08 21:57:56 +03:00
2013-09-20 04:18:12 +04:00
if ( self . vol . file_type == self . vol . TYPE_FILE and
2014-01-20 20:09:13 +04:00
self . conn . stable_defaults ( ) ) :
2011-09-27 02:53:00 +04:00
newfmts = [ ]
2014-01-20 20:09:13 +04:00
for f in stable_whitelist :
2011-09-27 02:53:00 +04:00
if f in formats :
newfmts . append ( f )
formats = newfmts
2008-08-15 19:24:24 +04:00
for f in formats :
model . append ( [ f , f ] )
2009-10-05 19:34:39 +04:00
def vol_name_changed ( self , src ) :
text = src . get_text ( )
2013-09-27 21:15:57 +04:00
suffix = self . default_suffix ( )
if " . " in text :
suffix = " "
self . widget ( " vol-name-suffix " ) . set_text ( suffix )
2011-07-14 21:13:13 +04:00
self . widget ( " vol-create " ) . set_sensitive ( bool ( text ) )
2009-10-05 19:34:39 +04:00
2009-10-05 19:50:10 +04:00
def vol_allocation_changed ( self , src ) :
2011-07-14 21:13:13 +04:00
cap_widget = self . widget ( " vol-capacity " )
2009-10-05 19:50:10 +04:00
alloc = src . get_value ( )
cap = cap_widget . get_value ( )
if alloc > cap :
cap_widget . set_value ( alloc )
def vol_capacity_changed ( self , src ) :
2011-07-14 21:13:13 +04:00
alloc_widget = self . widget ( " vol-allocation " )
2009-10-05 19:50:10 +04:00
cap = src . get_value ( )
2011-07-14 21:13:13 +04:00
alloc = self . widget ( " vol-allocation " ) . get_value ( )
2009-10-05 19:50:10 +04:00
if cap < alloc :
alloc_widget . set_value ( cap )
2013-10-01 22:49:19 +04:00
def vol_format_changed ( self , src ) :
ignore = src
self . _show_alloc ( )
self . _show_backing ( )
2014-02-05 02:30:24 +04:00
self . widget ( " vol-name " ) . emit ( " changed " )
2013-09-29 18:53:37 +04:00
def browse_backing ( self , src ) :
ignore = src
self . _browse_file ( )
2015-04-09 21:42:25 +03:00
def _signal_vol_created ( self , pool , volname ) :
self . emit ( " vol-created " , pool . get_connkey ( ) , volname )
2013-09-07 04:59:01 +04:00
def _finish_cb ( self , error , details ) :
self . topwin . set_sensitive ( True )
self . topwin . get_window ( ) . set_cursor (
Gdk . Cursor . new ( Gdk . CursorType . TOP_LEFT_ARROW ) )
if error :
error = _ ( " Error creating vol: %s " ) % error
self . show_err ( error ,
details = details )
else :
2015-04-09 21:42:25 +03:00
self . parent_pool . connect ( " refreshed " , self . _signal_vol_created ,
self . vol . name )
self . idle_add ( self . parent_pool . refresh )
2013-09-07 04:59:01 +04:00
self . close ( )
2010-12-09 19:22:35 +03:00
def finish ( self , src_ignore ) :
2008-08-15 19:24:24 +04:00
try :
if not self . validate ( ) :
return
except Exception , e :
2011-04-06 19:22:03 +04:00
self . show_err ( _ ( " Uncaught error validating input: %s " ) % str ( e ) )
2008-08-15 19:24:24 +04:00
return
self . topwin . set_sensitive ( False )
2013-09-07 04:59:01 +04:00
self . topwin . get_window ( ) . set_cursor (
Gdk . Cursor . new ( Gdk . CursorType . WATCH ) )
2008-08-15 19:24:24 +04:00
2010-12-09 20:37:48 +03:00
progWin = vmmAsyncJob ( self . _async_vol_create , [ ] ,
2013-09-07 04:59:01 +04:00
self . _finish_cb , [ ] ,
2010-12-10 17:57:42 +03:00
_ ( " Creating storage volume... " ) ,
_ ( " Creating the storage volume may take a "
2011-04-14 16:47:42 +04:00
" while... " ) ,
self . topwin )
2013-09-07 04:59:01 +04:00
progWin . run ( )
2008-08-15 19:24:24 +04:00
def _async_vol_create ( self , asyncjob ) :
2013-07-05 16:59:58 +04:00
conn = self . conn . get_backend ( )
2008-08-15 19:24:24 +04:00
2010-12-10 17:57:42 +03:00
# Lookup different pool obj
2013-07-05 16:59:58 +04:00
newpool = conn . storagePoolLookupByName ( self . parent_pool . get_name ( ) )
2010-12-10 17:57:42 +03:00
self . vol . pool = newpool
2008-08-15 19:24:24 +04:00
2012-02-10 19:24:43 +04:00
meter = asyncjob . get_meter ( )
2010-12-10 17:57:42 +03:00
logging . debug ( " Starting backround vol creation. " )
self . vol . install ( meter = meter )
2012-02-10 23:07:51 +04:00
logging . debug ( " vol creation complete. " )
2008-08-15 19:24:24 +04:00
def validate ( self ) :
2011-07-14 21:13:13 +04:00
name = self . widget ( " vol-name " ) . get_text ( )
suffix = self . widget ( " vol-name-suffix " ) . get_text ( )
2008-09-06 21:39:21 +04:00
volname = name + suffix
2009-05-11 18:13:32 +04:00
fmt = self . get_config_format ( )
2011-07-14 21:13:13 +04:00
alloc = self . widget ( " vol-allocation " ) . get_value ( )
cap = self . widget ( " vol-capacity " ) . get_value ( )
2013-09-29 18:53:37 +04:00
backing = self . widget ( " backing-store " ) . get_text ( )
2013-09-27 21:05:52 +04:00
if not self . widget ( " vol-allocation " ) . get_visible ( ) :
alloc = cap
2015-04-11 21:56:23 +03:00
if self . _can_only_sparse ( ) :
alloc = 0
2008-08-15 19:24:24 +04:00
try :
2013-09-20 04:18:12 +04:00
self . _make_stub_vol ( )
self . vol . name = volname
2013-09-27 21:05:52 +04:00
self . vol . capacity = ( cap * 1024 * 1024 * 1024 )
2013-09-29 18:53:37 +04:00
self . vol . allocation = ( alloc * 1024 * 1024 * 1024 )
if backing :
self . vol . backing_store = backing
2009-05-11 18:13:32 +04:00
if fmt :
self . vol . format = fmt
2013-09-20 04:18:12 +04:00
self . vol . validate ( )
2008-08-15 19:24:24 +04:00
except ValueError , e :
2011-08-30 22:50:50 +04:00
return self . val_err ( _ ( " Volume Parameter Error " ) , e )
2008-08-15 19:24:24 +04:00
return True
2011-04-06 19:22:03 +04:00
def show_err ( self , info , details = None ) :
2013-09-07 04:16:37 +04:00
self . err . show_err ( info , details , modal = self . topwin . get_modal ( ) )
2009-03-08 22:16:47 +03:00
2010-02-22 17:04:48 +03:00
def val_err ( self , info , details ) :
2013-09-29 18:53:37 +04:00
return self . err . val_err ( info , details , modal = self . topwin . get_modal ( ) )
def _browse_file ( self ) :
2015-04-09 01:29:48 +03:00
if self . storage_browser and self . storage_browser . conn != self . conn :
self . storage_browser . cleanup ( )
self . storage_browser = None
2013-09-29 18:53:37 +04:00
if self . storage_browser is None :
def cb ( src , text ) :
ignore = src
self . widget ( " backing-store " ) . set_text ( text )
2014-09-13 00:10:45 +04:00
from . storagebrowse import vmmStorageBrowser
2013-09-29 18:53:37 +04:00
self . storage_browser = vmmStorageBrowser ( self . conn )
2014-12-10 02:37:00 +03:00
self . storage_browser . set_finish_cb ( cb )
2013-09-29 18:53:37 +04:00
self . storage_browser . topwin . set_modal ( self . topwin . get_modal ( ) )
self . storage_browser . set_browse_reason (
self . config . CONFIG_DIR_IMAGE )
2015-04-09 01:29:48 +03:00
self . storage_browser . show ( self . topwin )