2006-08-09 19:40:34 +04:00
#
2015-01-27 19:04:18 +03:00
# Copyright (C) 2008, 2013, 2014, 2015 Red Hat, Inc.
2009-03-09 23:16:45 +03:00
# Copyright (C) 2008 Cole Robinson <crobinso@redhat.com>
2006-08-09 19:40:34 +04:00
#
# 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
2007-11-20 19:12:20 +03:00
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2006-08-09 19:40:34 +04:00
#
2009-03-09 23:16:45 +03:00
import logging
2013-07-07 04:03:42 +04:00
import threading
import time
2006-08-09 19:40:34 +04:00
2012-05-14 17:24:56 +04:00
from gi . repository import GObject
from gi . repository import Gtk
from gi . repository import Gdk
2015-04-11 19:57:32 +03:00
from gi . repository import Pango
2011-04-29 00:17:44 +04:00
2009-03-09 23:16:45 +03:00
import virtinst
2013-08-09 17:23:01 +04:00
from virtinst import util
2009-03-09 23:16:45 +03:00
2014-09-13 00:10:45 +04:00
from . import uiutil
from . baseclass import vmmGObjectUI
from . asyncjob import vmmAsyncJob
from . storagebrowse import vmmStorageBrowser
from . details import vmmDetails
from . domain import vmmDomainVirtinst
from . netlist import vmmNetworkList
from . mediacombo import vmmMediaCombo
from . addstorage import vmmAddStorage
2006-08-17 00:00:28 +04:00
2009-03-09 23:16:45 +03:00
# Number of seconds to wait for media detection
DETECT_TIMEOUT = 20
2006-08-10 02:53:30 +04:00
2011-04-28 18:39:12 +04:00
DEFAULT_MEM = 1024
2015-09-12 20:03:51 +03:00
( PAGE_NAME ,
PAGE_INSTALL ,
PAGE_MEM ,
PAGE_STORAGE ,
PAGE_FINISH ) = range ( 5 )
2008-02-23 23:26:26 +03:00
2015-09-12 20:03:51 +03:00
( INSTALL_PAGE_ISO ,
INSTALL_PAGE_URL ,
INSTALL_PAGE_PXE ,
INSTALL_PAGE_IMPORT ,
INSTALL_PAGE_CONTAINER_APP ,
INSTALL_PAGE_CONTAINER_OS ) = range ( 6 )
2009-11-20 19:39:22 +03:00
2015-09-12 22:14:40 +03:00
# Column numbers for os type/version list models
( OS_COL_ID ,
OS_COL_LABEL ,
OS_COL_IS_SEP ,
OS_COL_IS_SHOW_ALL ) = range ( 4 )
2012-02-02 20:32:29 +04:00
2015-09-12 20:03:51 +03:00
#####################
# Pretty UI helpers #
#####################
def _pretty_arch ( _a ) :
2013-10-02 21:19:40 +04:00
if _a == " armv7l " :
return " arm "
return _a
2015-09-12 20:03:51 +03:00
def _pretty_storage ( size ) :
return " %.1f GiB " % float ( size )
def _pretty_memory ( mem ) :
return " %d MiB " % ( mem / 1024.0 )
2015-09-14 23:05:58 +03:00
###########################################################
# Helpers for tracking devices we create from this wizard #
###########################################################
def _mark_vmm_device ( dev ) :
setattr ( dev , " vmm_create_wizard_device " , True )
def _get_vmm_device ( guest , devkey ) :
for dev in guest . get_devices ( devkey ) :
if hasattr ( dev , " vmm_create_wizard_device " ) :
return dev
def _remove_vmm_device ( guest , devkey ) :
dev = _get_vmm_device ( guest , devkey )
if dev :
guest . remove_device ( dev )
2015-09-12 20:03:51 +03:00
##############
# Main class #
##############
2010-12-09 01:26:19 +03:00
class vmmCreate ( vmmGObjectUI ) :
2012-05-14 17:24:56 +04:00
__gsignals__ = {
2013-09-22 23:13:41 +04:00
" action-show-domain " : ( 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 , engine ) :
2013-09-23 00:10:16 +04:00
vmmGObjectUI . __init__ ( self , " create.ui " , " vmm-create " )
2010-11-30 22:33:21 +03:00
self . engine = engine
2009-03-09 23:16:45 +03:00
self . conn = None
2015-09-13 19:45:35 +03:00
self . _capsinfo = None
2010-12-08 00:48:13 +03:00
2015-09-13 19:45:35 +03:00
self . _guest = None
self . _failed_guest = None
2010-12-08 00:48:13 +03:00
2009-03-09 23:16:45 +03:00
# Distro detection state variables
2015-09-12 22:14:40 +03:00
self . _detect_os_in_progress = False
self . _os_already_detected_for_media = False
self . _show_all_os_was_selected = False
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
self . _customize_window = None
2010-02-07 20:18:28 +03:00
2015-09-13 19:45:35 +03:00
self . _storage_browser = None
self . _netlist = None
self . _mediacombo = None
2014-01-28 01:58:45 +04:00
2015-09-13 19:45:35 +03:00
self . _addstorage = vmmAddStorage ( self . conn , self . builder , self . topwin )
2015-09-14 01:01:39 +03:00
self . widget ( " storage-align " ) . add ( self . _addstorage . top_box )
2015-09-12 20:03:51 +03:00
def _browse_file_cb ( ignore , widget ) :
self . _browse_file ( widget )
2015-09-13 19:45:35 +03:00
self . _addstorage . connect ( " browse-clicked " , _browse_file_cb )
2014-01-29 01:53:11 +04:00
2013-02-16 22:31:46 +04:00
self . builder . connect_signals ( {
2015-09-06 21:42:55 +03:00
" on_vmm_newcreate_delete_event " : self . _close_requested ,
2009-03-09 23:16:45 +03:00
2015-09-06 21:42:55 +03:00
" on_create_cancel_clicked " : self . _close_requested ,
2015-09-12 20:03:51 +03:00
" on_create_back_clicked " : self . _back_clicked ,
" on_create_forward_clicked " : self . _forward_clicked ,
" on_create_finish_clicked " : self . _finish_clicked ,
" on_create_pages_switch_page " : self . _page_changed ,
" on_create_conn_changed " : self . _conn_changed ,
" on_method_changed " : self . _method_changed ,
2015-09-15 01:31:56 +03:00
" on_xen_type_changed " : self . _xen_type_changed ,
2015-09-14 01:01:39 +03:00
" on_arch_changed " : self . _arch_changed ,
2015-09-15 01:31:56 +03:00
" on_virt_type_changed " : self . _virt_type_changed ,
" on_machine_changed " : self . _machine_changed ,
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
" on_install_cdrom_radio_toggled " : self . _local_media_toggled ,
" on_install_iso_entry_changed " : self . _iso_changed ,
" on_install_iso_entry_activate " : self . _iso_activated ,
" on_install_iso_browse_clicked " : self . _browse_iso ,
" on_install_url_entry_changed " : self . _url_changed ,
" on_install_url_entry_activate " : self . _url_activated ,
2015-09-12 20:03:51 +03:00
" on_install_import_browse_clicked " : self . _browse_import ,
" on_install_app_browse_clicked " : self . _browse_app ,
" on_install_oscontainer_browse_clicked " : self . _browse_oscontainer ,
" on_install_detect_os_toggled " : self . _toggle_detect_os ,
" on_install_os_type_changed " : self . _change_os_type ,
" on_install_os_version_changed " : self . _change_os_version ,
" on_install_detect_os_box_show " : self . _os_detect_visibility_changed ,
" on_install_detect_os_box_hide " : self . _os_detect_visibility_changed ,
2015-09-14 01:01:39 +03:00
" on_kernel_browse_clicked " : self . _browse_kernel ,
" on_initrd_browse_clicked " : self . _browse_initrd ,
" on_dtb_browse_clicked " : self . _browse_dtb ,
2015-09-12 20:03:51 +03:00
" on_enable_storage_toggled " : self . _toggle_enable_storage ,
2015-09-14 23:22:17 +03:00
" on_create_vm_name_changed " : self . _name_changed ,
2009-03-09 23:16:45 +03:00
} )
2011-04-18 19:25:28 +04:00
self . bind_escape_key_close ( )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
self . _init_state ( )
###########################
# Standard window methods #
###########################
2009-03-09 23:16:45 +03:00
2010-02-07 20:18:28 +03:00
def is_visible ( self ) :
2012-05-14 17:24:56 +04:00
return self . topwin . get_visible ( )
2010-02-07 20:18:28 +03:00
2011-04-14 16:47:42 +04:00
def show ( self , parent , uri = None ) :
2012-02-01 03:16:54 +04:00
logging . debug ( " Showing new vm wizard " )
2011-04-14 16:47:42 +04:00
2012-02-14 01:19:34 +04:00
if not self . is_visible ( ) :
2015-09-12 20:03:51 +03:00
self . _reset_state ( uri )
2012-02-14 01:19:34 +04:00
self . topwin . set_transient_for ( parent )
2006-09-13 01:49:29 +04:00
self . topwin . present ( )
2006-08-09 19:40:34 +04:00
2015-09-06 21:42:55 +03:00
def _close ( self , ignore1 = None , ignore2 = None ) :
2014-02-05 23:25:01 +04:00
if self . is_visible ( ) :
logging . debug ( " Closing new vm wizard " )
2009-03-09 23:16:45 +03:00
self . topwin . hide ( )
2009-09-22 00:09:51 +04:00
2015-11-22 03:25:02 +03:00
self . _cleanup_customize_window ( )
2015-09-13 19:45:35 +03:00
if self . _storage_browser :
self . _storage_browser . close ( )
2010-02-07 20:18:28 +03:00
2011-07-24 05:16:54 +04:00
def _cleanup ( self ) :
2011-04-13 17:27:02 +04:00
self . conn = None
2015-09-13 19:45:35 +03:00
self . _capsinfo = None
self . _guest = None
if self . _storage_browser :
self . _storage_browser . cleanup ( )
self . _storage_browser = None
if self . _netlist :
self . _netlist . cleanup ( )
self . _netlist = None
if self . _netlist :
self . _netlist . cleanup ( )
self . _netlist = None
if self . _mediacombo :
self . _mediacombo . cleanup ( )
self . _mediacombo = None
if self . _addstorage :
self . _addstorage . cleanup ( )
self . _addstorage = None
2014-01-28 22:51:59 +04:00
2015-09-12 20:03:51 +03:00
##########################
# Initial state handling #
##########################
def _show_startup_error ( self , error , hideinstall = True ) :
2011-07-14 21:13:13 +04:00
self . widget ( " startup-error-box " ) . show ( )
self . widget ( " create-forward " ) . set_sensitive ( False )
2012-02-09 18:04:09 +04:00
if hideinstall :
self . widget ( " install-box " ) . hide ( )
2013-10-05 18:31:02 +04:00
self . widget ( " arch-expander " ) . hide ( )
2009-09-29 22:00:50 +04:00
2015-09-23 23:28:46 +03:00
self . widget ( " startup-error " ) . set_text ( " %s : %s " % ( _ ( " Error " ) , error ) )
2009-03-09 23:16:45 +03:00
return False
2015-09-12 20:03:51 +03:00
def _show_startup_warning ( self , error ) :
2011-07-14 21:13:13 +04:00
self . widget ( " startup-error-box " ) . show ( )
2015-09-23 23:46:33 +03:00
self . widget ( " startup-error " ) . set_markup (
" <span size= ' small ' > %s : %s </span> " % ( _ ( " Warning " ) , error ) )
def _show_arch_warning ( self , error ) :
self . widget ( " arch-warning-box " ) . show ( )
self . widget ( " arch-warning " ) . set_markup (
" <span size= ' small ' > %s : %s </span> " % ( _ ( " Warning " ) , error ) )
2010-02-11 04:26:40 +03:00
2015-09-12 20:03:51 +03:00
def _init_state ( self ) :
2011-07-14 21:13:13 +04:00
self . widget ( " create-pages " ) . set_show_tabs ( False )
self . widget ( " install-method-pages " ) . set_show_tabs ( False )
2006-08-09 19:40:34 +04:00
2012-05-14 17:24:56 +04:00
blue = Gdk . Color . parse ( " #0072A8 " ) [ 1 ]
2013-09-27 18:26:43 +04:00
self . widget ( " header " ) . modify_bg ( Gtk . StateType . NORMAL , blue )
2009-03-09 23:58:55 +03:00
2009-03-09 23:16:45 +03:00
# Connection list
2011-07-14 21:13:13 +04:00
self . widget ( " create-conn-label " ) . set_text ( " " )
self . widget ( " startup-error " ) . set_text ( " " )
conn_list = self . widget ( " create-conn " )
2012-05-14 17:24:56 +04:00
conn_model = Gtk . ListStore ( str , str )
2009-03-09 23:16:45 +03:00
conn_list . set_model ( conn_model )
2015-04-11 19:57:32 +03:00
text = uiutil . init_combo_text_column ( conn_list , 1 )
text . set_property ( " ellipsize " , Pango . EllipsizeMode . MIDDLE )
2009-03-09 23:16:45 +03:00
2009-05-11 19:00:03 +04:00
# ISO media list
2015-09-12 22:14:40 +03:00
iso_list = self . widget ( " install-iso-combo " )
2012-05-14 17:24:56 +04:00
iso_model = Gtk . ListStore ( str )
2009-05-11 19:00:03 +04:00
iso_list . set_model ( iso_model )
2012-05-14 17:24:56 +04:00
iso_list . set_entry_text_column ( 0 )
2009-05-11 19:00:03 +04:00
2009-03-09 23:16:45 +03:00
# Lists for the install urls
2015-09-12 22:14:40 +03:00
media_url_list = self . widget ( " install-url-combo " )
2012-05-14 17:24:56 +04:00
media_url_model = Gtk . ListStore ( str )
2006-10-11 17:07:45 +04:00
media_url_list . set_model ( media_url_model )
2012-05-14 17:24:56 +04:00
media_url_list . set_entry_text_column ( 0 )
2006-10-11 17:07:45 +04:00
2011-07-26 02:53:09 +04:00
def sep_func ( model , it , combo ) :
ignore = combo
2015-09-12 22:14:40 +03:00
return model [ it ] [ OS_COL_IS_SEP ]
def make_os_model ( ) :
# [os value, os label, is seperator, is 'show all']
cols = [ ]
cols . insert ( OS_COL_ID , str )
cols . insert ( OS_COL_LABEL , str )
cols . insert ( OS_COL_IS_SEP , bool )
cols . insert ( OS_COL_IS_SHOW_ALL , bool )
return Gtk . ListStore ( * cols )
2011-07-26 02:53:09 +04:00
2009-03-09 23:16:45 +03:00
# Lists for distro type + variant
2011-07-14 21:13:13 +04:00
os_type_list = self . widget ( " install-os-type " )
2015-09-12 22:14:40 +03:00
os_type_model = make_os_model ( )
2007-02-19 19:52:37 +03:00
os_type_list . set_model ( os_type_model )
2015-04-10 20:04:02 +03:00
uiutil . init_combo_text_column ( os_type_list , 1 )
2011-07-26 02:53:09 +04:00
os_type_list . set_row_separator_func ( sep_func , os_type_list )
2007-02-19 19:52:37 +03:00
2011-07-14 21:13:13 +04:00
os_variant_list = self . widget ( " install-os-version " )
2015-09-12 22:14:40 +03:00
os_variant_model = make_os_model ( )
2007-02-19 19:52:37 +03:00
os_variant_list . set_model ( os_variant_model )
2015-04-10 20:04:02 +03:00
uiutil . init_combo_text_column ( os_variant_list , 1 )
2011-07-26 02:53:09 +04:00
os_variant_list . set_row_separator_func ( sep_func , os_variant_list )
2014-04-24 18:58:11 +04:00
entry = self . widget ( " install-os-version-entry " )
completion = Gtk . EntryCompletion ( )
entry . set_completion ( completion )
completion . set_text_column ( 1 )
completion . set_inline_completion ( True )
2014-07-04 15:43:46 +04:00
completion . set_model ( os_variant_model )
2014-04-24 18:58:11 +04:00
2009-03-09 23:16:45 +03:00
# Archtecture
2015-09-14 01:01:39 +03:00
archList = self . widget ( " arch " )
2015-09-15 01:31:56 +03:00
# [label, guest.os.arch value]
2014-01-27 04:18:22 +04:00
archModel = Gtk . ListStore ( str , str )
2008-03-10 01:18:33 +03:00
archList . set_model ( archModel )
2015-09-15 01:31:56 +03:00
uiutil . init_combo_text_column ( archList , 0 )
2013-10-02 21:10:11 +04:00
archList . set_row_separator_func (
lambda m , i , ignore : m [ i ] [ 0 ] is None , None )
2007-02-20 07:11:21 +03:00
2015-09-15 01:31:56 +03:00
# guest.os.type value for xen (hvm vs. xen)
hyperList = self . widget ( " xen-type " )
# [label, guest.os_type value]
2014-01-27 04:18:22 +04:00
hyperModel = Gtk . ListStore ( str , str )
2008-03-10 01:18:33 +03:00
hyperList . set_model ( hyperModel )
2015-04-10 20:04:02 +03:00
uiutil . init_combo_text_column ( hyperList , 0 )
2007-02-20 07:11:21 +03:00
2015-09-15 01:31:56 +03:00
# guest.os.machine value
2015-09-14 01:01:39 +03:00
lst = self . widget ( " machine " )
2015-09-15 01:31:56 +03:00
# [machine ID]
2014-01-27 04:18:22 +04:00
model = Gtk . ListStore ( str )
2013-10-02 01:40:44 +04:00
lst . set_model ( model )
2015-04-10 20:04:02 +03:00
uiutil . init_combo_text_column ( lst , 0 )
2013-10-02 21:10:11 +04:00
lst . set_row_separator_func ( lambda m , i , ignore : m [ i ] [ 0 ] is None , None )
2013-10-02 01:40:44 +04:00
2015-09-15 01:31:56 +03:00
# guest.type value for xen (qemu vs kvm)
lst = self . widget ( " virt-type " )
# [label, guest.type value]
model = Gtk . ListStore ( str , str )
lst . set_model ( model )
uiutil . init_combo_text_column ( lst , 0 )
2015-09-12 20:03:51 +03:00
def _reset_state ( self , urihint = None ) :
"""
Reset all UI state to default values . Conn specific state is
2015-11-02 22:08:09 +03:00
populated in _populate_conn_state
2015-09-12 20:03:51 +03:00
"""
2015-09-13 19:45:35 +03:00
self . _failed_guest = None
self . _guest = None
2015-09-12 22:14:40 +03:00
self . _show_all_os_was_selected = False
2015-11-22 03:25:02 +03:00
self . _undo_finish_cursor ( self . topwin )
2010-12-08 00:48:13 +03:00
2011-07-14 21:13:13 +04:00
self . widget ( " create-pages " ) . set_current_page ( PAGE_NAME )
2015-09-12 20:03:51 +03:00
self . _page_changed ( None , None , PAGE_NAME )
2006-11-06 19:36:55 +03:00
2009-03-09 23:16:45 +03:00
# Name page state
2011-07-14 21:13:13 +04:00
self . widget ( " create-vm-name " ) . set_text ( " " )
self . widget ( " method-local " ) . set_active ( True )
self . widget ( " create-conn " ) . set_active ( - 1 )
2015-09-12 20:03:51 +03:00
activeconn = self . _populate_conn_list ( urihint )
2013-10-01 23:18:34 +04:00
self . widget ( " arch-expander " ) . set_expanded ( False )
2010-02-11 04:26:40 +03:00
2015-11-02 22:08:09 +03:00
if self . _set_conn ( activeconn ) is False :
return False
2010-02-11 04:26:40 +03:00
2009-03-09 23:16:45 +03:00
# Everything from this point forward should be connection independent
# Distro/Variant
2015-09-12 20:03:51 +03:00
self . _toggle_detect_os ( self . widget ( " install-detect-os " ) )
self . _populate_os_type_model ( )
2011-07-14 21:13:13 +04:00
self . widget ( " install-os-type " ) . set_active ( 0 )
2007-04-23 23:08:56 +04:00
2015-09-12 20:03:51 +03:00
def _populate_media_model ( media_model , urls ) :
media_model . clear ( )
if urls is None :
return
for url in urls :
media_model . append ( [ url ] )
2015-09-12 22:14:40 +03:00
self . widget ( " install-iso-entry " ) . set_text ( " " )
iso_model = self . widget ( " install-iso-combo " ) . get_model ( )
2015-09-12 20:03:51 +03:00
_populate_media_model ( iso_model , self . config . get_iso_paths ( ) )
2007-07-10 05:13:56 +04:00
2009-03-09 23:16:45 +03:00
# Install URL
2011-07-14 21:13:13 +04:00
self . widget ( " install-urlopts-entry " ) . set_text ( " " )
2015-09-12 22:14:40 +03:00
self . widget ( " install-url-entry " ) . set_text ( " " )
2011-07-14 21:13:13 +04:00
self . widget ( " install-url-options " ) . set_expanded ( False )
2015-09-12 22:14:40 +03:00
urlmodel = self . widget ( " install-url-combo " ) . get_model ( )
2015-09-12 20:03:51 +03:00
_populate_media_model ( urlmodel , self . config . get_media_urls ( ) )
2015-09-12 22:14:40 +03:00
self . _set_distro_labels ( " - " , " - " )
2007-07-14 22:43:52 +04:00
2010-03-23 01:15:18 +03:00
# Install import
2011-07-14 21:13:13 +04:00
self . widget ( " install-import-entry " ) . set_text ( " " )
2015-09-14 01:01:39 +03:00
self . widget ( " kernel " ) . set_text ( " " )
self . widget ( " initrd " ) . set_text ( " " )
self . widget ( " dtb " ) . set_text ( " " )
2010-03-23 01:15:18 +03:00
2011-06-08 01:42:50 +04:00
# Install container app
2011-07-14 21:13:13 +04:00
self . widget ( " install-app-entry " ) . set_text ( " /bin/sh " )
2011-06-08 01:42:50 +04:00
2011-06-21 19:04:22 +04:00
# Install container OS
2011-07-14 21:13:13 +04:00
self . widget ( " install-oscontainer-fs " ) . set_text ( " " )
2011-06-21 19:04:22 +04:00
2009-03-09 23:16:45 +03:00
# Storage
2011-07-14 21:13:13 +04:00
self . widget ( " enable-storage " ) . set_active ( True )
2015-09-13 19:45:35 +03:00
self . _addstorage . reset_state ( )
2015-09-14 01:01:39 +03:00
self . _addstorage . widget ( " storage-create " ) . set_active ( True )
self . _addstorage . widget ( " storage-entry " ) . set_text ( " " )
2014-01-15 01:03:58 +04:00
2009-03-09 23:16:45 +03:00
# Final page
2011-07-14 21:13:13 +04:00
self . widget ( " summary-customize " ) . set_active ( False )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _set_caps_state ( self ) :
"""
Set state that is dependent on when capsinfo changes
"""
self . _populate_machine ( )
2015-09-23 23:46:33 +03:00
self . widget ( " arch-warning-box " ) . hide ( )
2013-10-02 19:56:51 +04:00
2012-02-09 18:50:54 +04:00
# Helper state
2009-03-09 23:16:45 +03:00
is_local = not self . conn . is_remote ( )
is_storage_capable = self . conn . is_storage_capable ( )
2012-02-09 18:50:54 +04:00
can_storage = ( is_local or is_storage_capable )
2015-09-13 19:45:35 +03:00
is_pv = ( self . _capsinfo . os_type == " xen " )
2011-06-08 01:42:50 +04:00
is_container = self . conn . is_container ( )
2013-10-06 18:08:04 +04:00
can_remote_url = self . conn . get_backend ( ) . support_remote_url_install ( )
2009-03-09 23:16:45 +03:00
2015-09-13 19:45:35 +03:00
installable_arch = ( self . _capsinfo . arch in
2015-07-13 14:35:24 +03:00
[ " i686 " , " x86_64 " , " ppc64 " , " ppc64le " , " ia64 " , " s390x " ] )
2013-10-02 19:56:51 +04:00
2015-09-13 19:45:35 +03:00
if self . _capsinfo . arch == " aarch64 " :
2015-02-22 18:01:02 +03:00
try :
2015-09-13 19:45:35 +03:00
guest = self . conn . caps . build_virtinst_guest ( self . _capsinfo )
2015-02-22 18:01:02 +03:00
guest . set_uefi_default ( )
installable_arch = True
logging . debug ( " UEFI found for aarch64, setting it as default. " )
except Exception , e :
installable_arch = False
logging . debug ( " Error checking for aarch64 UEFI default " ,
exc_info = True )
msg = _ ( " Failed to setup UEFI for AArch64: %s \n "
" Install options are limited. " ) % e
2015-09-23 23:46:33 +03:00
self . _show_arch_warning ( msg )
2015-02-22 18:01:02 +03:00
2009-03-09 23:16:45 +03:00
# Install Options
2011-07-14 21:13:13 +04:00
method_tree = self . widget ( " method-tree " )
method_pxe = self . widget ( " method-pxe " )
method_local = self . widget ( " method-local " )
2012-02-09 18:50:54 +04:00
method_import = self . widget ( " method-import " )
2011-07-14 21:13:13 +04:00
method_container_app = self . widget ( " method-container-app " )
2009-03-09 23:16:45 +03:00
2013-10-02 19:56:51 +04:00
method_tree . set_sensitive ( ( is_local or can_remote_url ) and
installable_arch )
method_local . set_sensitive ( not is_pv and can_storage and
installable_arch )
method_pxe . set_sensitive ( not is_pv and installable_arch )
2012-02-09 18:50:54 +04:00
method_import . set_sensitive ( can_storage )
virt_methods = [ method_local , method_tree , method_pxe , method_import ]
2009-03-09 23:16:45 +03:00
pxe_tt = None
local_tt = None
tree_tt = None
2012-02-09 18:50:54 +04:00
import_tt = None
if not is_local :
if not can_remote_url :
tree_tt = _ ( " Libvirt version does not "
" support remote URL installs. " )
if not is_storage_capable :
local_tt = _ ( " Connection does not support storage management. " )
import_tt = local_tt
2009-03-09 23:16:45 +03:00
if is_pv :
base = _ ( " %s installs not available for paravirt guests. " )
pxe_tt = base % " PXE "
local_tt = base % " CDROM/ISO "
2013-10-02 19:56:51 +04:00
if not installable_arch :
msg = ( _ ( " Architecture ' %s ' is not installable " ) %
2015-09-13 19:45:35 +03:00
self . _capsinfo . arch )
2013-10-02 19:56:51 +04:00
tree_tt = msg
local_tt = msg
pxe_tt = msg
2014-01-12 23:41:25 +04:00
if not any ( [ w . get_active ( ) and w . get_sensitive ( )
for w in virt_methods ] ) :
for w in virt_methods :
if w . get_sensitive ( ) :
w . set_active ( True )
break
2009-03-09 23:16:45 +03:00
2012-02-09 18:50:54 +04:00
if not ( is_container or
2013-04-12 00:32:00 +04:00
[ w for w in virt_methods if w . get_sensitive ( ) ] ) :
2015-09-12 20:03:51 +03:00
return self . _show_startup_error (
2012-02-09 18:50:54 +04:00
_ ( " No install methods available for this connection. " ) ,
hideinstall = False )
2009-03-09 23:16:45 +03:00
2012-05-14 17:24:56 +04:00
method_tree . set_tooltip_text ( tree_tt or " " )
method_local . set_tooltip_text ( local_tt or " " )
method_pxe . set_tooltip_text ( pxe_tt or " " )
method_import . set_tooltip_text ( import_tt or " " )
2009-03-09 23:16:45 +03:00
2011-06-08 01:42:50 +04:00
# Container install options
method_container_app . set_active ( True )
2013-09-02 04:18:14 +04:00
self . widget ( " virt-install-box " ) . set_visible ( not is_container )
self . widget ( " container-install-box " ) . set_visible ( is_container )
2011-06-08 01:42:50 +04:00
2015-09-13 19:45:35 +03:00
show_dtb = ( " arm " in self . _capsinfo . arch or
" microblaze " in self . _capsinfo . arch or
" ppc " in self . _capsinfo . arch )
2015-09-14 01:01:39 +03:00
self . widget ( " kernel-box " ) . set_visible ( not installable_arch )
uiutil . set_grid_row_visible ( self . widget ( " dtb " ) , show_dtb )
2013-10-02 19:56:51 +04:00
2015-11-02 22:08:09 +03:00
def _populate_conn_state ( self ) :
2015-09-12 20:03:51 +03:00
"""
Update all state that has some dependency on the current connection
"""
2013-10-02 15:35:02 +04:00
self . conn . schedule_priority_tick ( pollnet = True ,
pollpool = True , polliface = True ,
2015-04-07 20:56:48 +03:00
pollnodedev = True )
2013-10-02 15:35:02 +04:00
self . widget ( " install-box " ) . show ( )
self . widget ( " create-forward " ) . set_sensitive ( True )
2015-11-02 22:08:09 +03:00
self . _capsinfo = None
2015-07-20 10:19:57 +03:00
self . conn . invalidate_caps ( )
2015-09-12 20:03:51 +03:00
self . _change_caps ( )
2015-07-20 10:19:57 +03:00
2015-09-13 19:45:35 +03:00
if not self . _capsinfo . guest . has_install_options ( ) :
2013-10-02 15:35:02 +04:00
error = _ ( " No hypervisor options were found for this "
" connection. " )
if self . conn . is_qemu ( ) :
error + = " \n \n "
error + = _ ( " This usually means that QEMU or KVM is not "
" installed on your machine, or the KVM kernel "
" modules are not loaded. " )
2015-09-12 20:03:51 +03:00
return self . _show_startup_error ( error )
2013-10-02 15:35:02 +04:00
2015-09-15 01:31:56 +03:00
# A bit out of order, but populate the xen/virt/arch/machine lists
# so we can work with a default.
self . _populate_xen_type ( )
2015-09-12 20:03:51 +03:00
self . _populate_arch ( )
2015-09-15 01:31:56 +03:00
self . _populate_virt_type ( )
2013-10-02 15:35:02 +04:00
2015-09-15 01:31:56 +03:00
show_arch = ( self . widget ( " xen-type " ) . get_visible ( ) or
self . widget ( " virt-type " ) . get_visible ( ) or
2015-09-14 01:01:39 +03:00
self . widget ( " arch " ) . get_visible ( ) or
self . widget ( " machine " ) . get_visible ( ) )
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible ( self . widget ( " arch-expander " ) , show_arch )
2013-10-02 15:35:02 +04:00
if self . conn . is_xen ( ) :
2015-04-03 23:39:47 +03:00
has_hvm_guests = False
for g in self . conn . caps . guests :
if g . os_type == " hvm " :
has_hvm_guests = True
if not has_hvm_guests :
error = _ ( " Host is not advertising support for full "
2013-10-02 15:35:02 +04:00
" virtualization. Install options may be limited. " )
2015-09-12 20:03:51 +03:00
self . _show_startup_warning ( error )
2013-10-02 15:35:02 +04:00
elif self . conn . is_qemu ( ) :
2015-09-13 19:45:35 +03:00
if not self . _capsinfo . guest . is_kvm_available ( ) :
2013-10-02 15:35:02 +04:00
error = _ ( " KVM is not available. This may mean the KVM "
" package is not installed, or the KVM kernel modules "
" are not loaded. Your virtual machines may perform poorly. " )
2015-09-12 20:03:51 +03:00
self . _show_startup_warning ( error )
2013-10-02 15:35:02 +04:00
2009-03-09 23:16:45 +03:00
# Install local
2015-09-12 22:14:40 +03:00
iso_option = self . widget ( " install-iso-radio " )
cdrom_option = self . widget ( " install-cdrom-radio " )
2009-11-30 20:51:25 +03:00
2015-09-13 19:45:35 +03:00
if self . _mediacombo :
2015-09-12 22:14:40 +03:00
self . widget ( " install-cdrom-align " ) . remove (
2015-09-13 19:45:35 +03:00
self . _mediacombo . top_box )
self . _mediacombo . cleanup ( )
self . _mediacombo = None
2009-11-30 20:51:25 +03:00
2015-09-13 19:45:35 +03:00
self . _mediacombo = vmmMediaCombo ( self . conn , self . builder , self . topwin ,
2015-04-07 20:56:48 +03:00
vmmMediaCombo . MEDIA_CDROM )
2015-09-12 22:14:40 +03:00
2015-09-13 19:45:35 +03:00
self . _mediacombo . combo . connect ( " changed " , self . _cdrom_changed )
self . _mediacombo . reset_state ( )
2015-09-12 22:14:40 +03:00
self . widget ( " install-cdrom-align " ) . add (
2015-09-13 19:45:35 +03:00
self . _mediacombo . top_box )
2009-11-30 20:51:25 +03:00
2009-03-09 23:16:45 +03:00
# Don't select physical CDROM if no valid media is present
2015-09-13 19:45:35 +03:00
cdrom_option . set_active ( self . _mediacombo . has_media ( ) )
iso_option . set_active ( not self . _mediacombo . has_media ( ) )
2009-11-16 00:36:37 +03:00
2014-03-19 19:05:54 +04:00
enable_phys = not self . _stable_defaults ( )
cdrom_option . set_sensitive ( enable_phys )
cdrom_option . set_tooltip_text ( " " if enable_phys else
_ ( " Physical CDROM passthrough not supported with this hypervisor " ) )
2009-11-16 00:36:37 +03:00
# Only allow ISO option for remote VM
2013-10-02 15:35:02 +04:00
is_local = not self . conn . is_remote ( )
2014-03-19 19:05:54 +04:00
if not is_local or not enable_phys :
2009-11-16 00:36:37 +03:00
iso_option . set_active ( True )
2009-03-09 23:16:45 +03:00
2015-09-12 22:14:40 +03:00
self . _local_media_toggled ( cdrom_option )
2009-03-09 23:16:45 +03:00
# Memory
memory = int ( self . conn . host_memory_size ( ) )
2010-12-10 19:47:07 +03:00
mem_label = ( _ ( " Up to %(maxmem)s available on the host " ) %
2015-09-12 20:03:51 +03:00
{ ' maxmem ' : _pretty_memory ( memory ) } )
2009-03-09 23:16:45 +03:00
mem_label = ( " <span size= ' small ' color= ' #484848 ' > %s </span> " %
mem_label )
2015-09-14 01:01:39 +03:00
self . widget ( " mem " ) . set_range ( 50 , memory / 1024 )
2011-07-14 21:13:13 +04:00
self . widget ( " phys-mem-label " ) . set_markup ( mem_label )
2009-03-09 23:16:45 +03:00
# CPU
2013-07-06 20:36:07 +04:00
phys_cpus = int ( self . conn . host_active_processor_count ( ) )
2009-03-09 23:16:45 +03:00
cmax = phys_cpus
2009-03-10 05:42:17 +03:00
if cmax < = 0 :
cmax = 1
2010-12-10 19:47:07 +03:00
cpu_label = ( _ ( " Up to %(numcpus)d available " ) %
{ ' numcpus ' : int ( phys_cpus ) } )
2009-03-09 23:16:45 +03:00
cpu_label = ( " <span size= ' small ' color= ' #484848 ' > %s </span> " %
cpu_label )
2015-09-14 01:01:39 +03:00
self . widget ( " cpus " ) . set_range ( 1 , cmax )
2011-07-14 21:13:13 +04:00
self . widget ( " phys-cpu-label " ) . set_markup ( cpu_label )
2009-03-09 23:16:45 +03:00
# Storage
2015-09-13 19:45:35 +03:00
self . _addstorage . conn = self . conn
self . _addstorage . reset_state ( )
2009-03-09 23:16:45 +03:00
# Networking
2015-09-14 01:01:39 +03:00
self . widget ( " advanced-expander " ) . set_expanded ( False )
2014-01-28 22:59:31 +04:00
2015-09-13 19:45:35 +03:00
if self . _netlist :
2015-09-14 01:01:39 +03:00
self . widget ( " netdev-ui-align " ) . remove ( self . _netlist . top_box )
2015-09-13 19:45:35 +03:00
self . _netlist . cleanup ( )
self . _netlist = None
2014-01-28 22:59:31 +04:00
2015-09-13 19:45:35 +03:00
self . _netlist = vmmNetworkList ( self . conn , self . builder , self . topwin )
2015-09-14 01:01:39 +03:00
self . widget ( " netdev-ui-align " ) . add ( self . _netlist . top_box )
2015-09-13 19:45:35 +03:00
self . _netlist . connect ( " changed " , self . _netdev_changed )
self . _netlist . reset_state ( )
2010-12-04 20:28:44 +03:00
2015-11-02 22:08:09 +03:00
def _set_conn ( self , newconn ) :
self . widget ( " startup-error-box " ) . hide ( )
self . widget ( " arch-warning-box " ) . hide ( )
self . conn = newconn
if not self . conn :
return self . _show_startup_error (
_ ( " No active connection to install on. " ) )
try :
self . _populate_conn_state ( )
except Exception , e :
logging . exception ( " Error setting create wizard conn state. " )
return self . _show_startup_error ( str ( e ) )
2015-09-12 20:03:51 +03:00
2015-09-15 01:31:56 +03:00
def _change_caps ( self , gtype = None , arch = None , domtype = None ) :
2015-09-12 20:03:51 +03:00
"""
Change the cached capsinfo for the passed values , and trigger
all needed UI refreshing
"""
if gtype is None :
# If none specified, prefer HVM so install options aren't limited
# with a default PV choice.
for g in self . conn . caps . guests :
if g . os_type == " hvm " :
gtype = " hvm "
break
2015-09-15 01:31:56 +03:00
capsinfo = self . conn . caps . guest_lookup ( os_type = gtype ,
arch = arch ,
typ = domtype )
2015-09-12 20:03:51 +03:00
2015-09-13 19:45:35 +03:00
if self . _capsinfo :
if ( self . _capsinfo . guest == capsinfo . guest and
self . _capsinfo . domain == capsinfo . domain ) :
2015-09-12 20:03:51 +03:00
return
2015-09-13 19:45:35 +03:00
self . _capsinfo = capsinfo
2015-09-12 20:03:51 +03:00
logging . debug ( " Guest type set to os_type= %s , arch= %s , dom_type= %s " ,
2015-09-13 19:45:35 +03:00
self . _capsinfo . os_type ,
self . _capsinfo . arch ,
self . _capsinfo . hypervisor_type )
2015-09-12 20:03:51 +03:00
self . _set_caps_state ( )
##################################################
# Helpers for populating hv/arch/machine/conn UI #
##################################################
2015-09-15 01:31:56 +03:00
def _populate_xen_type ( self ) :
model = self . widget ( " xen-type " ) . get_model ( )
2009-03-09 23:16:45 +03:00
model . clear ( )
default = 0
2015-09-15 01:31:56 +03:00
guests = [ ]
if self . conn . is_xen ( ) or self . conn . is_test_conn ( ) :
guests = self . conn . caps . guests [ : ]
2013-10-02 01:27:58 +04:00
2015-09-15 01:31:56 +03:00
for guest in guests :
2013-10-02 01:27:58 +04:00
if not guest . domains :
continue
2015-09-15 01:31:56 +03:00
gtype = guest . os_type
2013-10-02 01:27:58 +04:00
dom = guest . domains [ 0 ]
domtype = dom . hypervisor_type
2014-01-27 02:42:24 +04:00
label = self . conn . pretty_hv ( gtype , domtype )
2013-10-02 01:27:58 +04:00
# Don't add multiple rows for each arch
for m in model :
if m [ 0 ] == label :
label = None
break
if label is None :
continue
# Determine if this is the default given by guest_lookup
2015-09-13 19:45:35 +03:00
if ( gtype == self . _capsinfo . os_type and
2015-09-15 01:31:56 +03:00
domtype == self . _capsinfo . hypervisor_type ) :
2013-10-02 01:27:58 +04:00
default = len ( model )
2006-08-09 19:40:34 +04:00
2013-10-02 01:27:58 +04:00
model . append ( [ label , gtype ] )
2015-09-15 01:31:56 +03:00
show = bool ( len ( model ) )
uiutil . set_grid_row_visible ( self . widget ( " xen-type " ) , show )
2013-10-02 01:27:58 +04:00
if show :
2015-09-15 01:31:56 +03:00
self . widget ( " xen-type " ) . set_active ( default )
2006-09-13 01:49:29 +04:00
2015-09-12 20:03:51 +03:00
def _populate_arch ( self ) :
2015-09-15 01:31:56 +03:00
model = self . widget ( " arch " ) . get_model ( )
2009-03-09 23:16:45 +03:00
model . clear ( )
default = 0
2013-10-02 01:27:58 +04:00
archs = [ ]
2014-03-12 19:42:50 +04:00
for guest in self . conn . caps . guests :
2015-09-13 19:45:35 +03:00
if guest . os_type == self . _capsinfo . os_type :
2013-10-02 01:27:58 +04:00
archs . append ( guest . arch )
# Combine x86/i686 to avoid confusion
2014-01-18 22:23:30 +04:00
if ( self . conn . caps . host . cpu . arch == " x86_64 " and
2013-10-02 21:10:11 +04:00
" x86_64 " in archs and " i686 " in archs ) :
2013-10-02 01:27:58 +04:00
archs . remove ( " i686 " )
2013-10-02 21:10:11 +04:00
archs . sort ( )
2015-07-13 14:35:24 +03:00
prios = [ " x86_64 " , " i686 " , " aarch64 " , " armv7l " , " ppc64 " , " ppc64le " ,
" s390x " ]
2014-01-18 22:23:30 +04:00
if self . conn . caps . host . cpu . arch not in prios :
2013-10-02 21:10:11 +04:00
prios = [ ]
else :
for p in prios [ : ] :
if p not in archs :
prios . remove ( p )
else :
archs . remove ( p )
if prios :
if archs :
prios + = [ None ]
archs = prios + archs
2009-03-09 23:16:45 +03:00
2013-10-02 01:27:58 +04:00
default = 0
2015-09-13 19:45:35 +03:00
if self . _capsinfo . arch in archs :
default = archs . index ( self . _capsinfo . arch )
2013-10-02 21:10:11 +04:00
2013-10-02 01:27:58 +04:00
for arch in archs :
2015-09-15 01:31:56 +03:00
model . append ( [ _pretty_arch ( arch ) , arch ] )
2009-03-09 23:16:45 +03:00
2013-10-02 01:27:58 +04:00
show = not ( len ( archs ) < 2 )
2015-09-15 01:31:56 +03:00
uiutil . set_grid_row_visible ( self . widget ( " arch " ) , show )
self . widget ( " arch " ) . set_active ( default )
def _populate_virt_type ( self ) :
model = self . widget ( " virt-type " ) . get_model ( )
model . clear ( )
# Allow choosing between qemu and kvm for archs that traditionally
2015-09-29 03:00:01 +03:00
# have a decent amount of TCG usage, like armv7l. Also include
# aarch64 which can be used for arm32 VMs as well
2015-09-15 01:31:56 +03:00
domains = [ d . hypervisor_type for d in self . _capsinfo . guest . domains [ : ] ]
if not self . conn . is_qemu ( ) :
domains = [ ]
2015-09-29 03:00:01 +03:00
elif self . _capsinfo . arch in [ " i686 " , " x86_64 " , " ppc64 " , " ppc64le " ] :
2015-09-15 01:31:56 +03:00
domains = [ ]
default = 0
if self . _capsinfo . hypervisor_type in domains :
default = domains . index ( self . _capsinfo . hypervisor_type )
prios = [ " kvm " ]
for domain in prios :
if domain not in domains :
continue
domains . remove ( domain )
domains . insert ( 0 , domain )
for domain in domains :
label = self . conn . pretty_hv ( self . _capsinfo . os_type , domain )
model . append ( [ label , domain ] )
show = bool ( len ( model ) > 1 )
uiutil . set_grid_row_visible ( self . widget ( " virt-type " ) , show )
self . widget ( " virt-type " ) . set_active ( default )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _populate_machine ( self ) :
2015-09-15 01:31:56 +03:00
model = self . widget ( " machine " ) . get_model ( )
2013-10-02 01:40:44 +04:00
model . clear ( )
2015-09-13 19:45:35 +03:00
machines = self . _capsinfo . machines [ : ]
if self . _capsinfo . arch in [ " i686 " , " x86_64 " ] :
2013-10-02 01:40:44 +04:00
machines = [ ]
2013-10-02 21:10:11 +04:00
machines . sort ( )
2013-10-02 01:40:44 +04:00
defmachine = None
2013-10-02 21:10:11 +04:00
prios = [ ]
2015-09-13 19:45:35 +03:00
recommended_machine = self . _capsinfo . get_recommended_machine ( )
2014-09-24 00:05:48 +04:00
if recommended_machine :
defmachine = recommended_machine
prios = [ defmachine ]
2013-10-02 21:10:11 +04:00
for p in prios [ : ] :
if p not in machines :
prios . remove ( p )
else :
machines . remove ( p )
if prios :
machines = prios + [ None ] + machines
2013-10-02 01:40:44 +04:00
default = 0
2013-10-02 21:10:11 +04:00
if defmachine and defmachine in machines :
2013-10-02 01:40:44 +04:00
default = machines . index ( defmachine )
for m in machines :
model . append ( [ m ] )
show = ( len ( machines ) > 1 )
2015-09-15 01:31:56 +03:00
uiutil . set_grid_row_visible ( self . widget ( " machine " ) , show )
2013-10-02 01:40:44 +04:00
if show :
2015-09-15 01:31:56 +03:00
self . widget ( " machine " ) . set_active ( default )
2013-10-02 19:56:51 +04:00
else :
2015-09-15 01:31:56 +03:00
self . widget ( " machine " ) . emit ( " changed " )
2013-10-02 01:40:44 +04:00
2015-09-12 20:03:51 +03:00
def _populate_conn_list ( self , urihint = None ) :
2011-07-14 21:13:13 +04:00
conn_list = self . widget ( " create-conn " )
2009-03-09 23:16:45 +03:00
model = conn_list . get_model ( )
model . clear ( )
default = - 1
2011-07-23 00:43:26 +04:00
for c in self . engine . conns . values ( ) :
connobj = c [ " conn " ]
2009-03-09 23:16:45 +03:00
if not connobj . is_active ( ) :
continue
if connobj . get_uri ( ) == urihint :
default = len ( model )
elif default < 0 and not connobj . is_remote ( ) :
# Favor local connections over remote connections
default = len ( model )
2015-04-11 19:57:32 +03:00
model . append ( [ connobj . get_uri ( ) , connobj . get_pretty_desc ( ) ] )
2009-03-09 23:16:45 +03:00
no_conns = ( len ( model ) == 0 )
if default < 0 and not no_conns :
default = 0
activeuri = " "
activedesc = " "
activeconn = None
if not no_conns :
conn_list . set_active ( default )
activeuri , activedesc = model [ default ]
2011-07-23 00:43:26 +04:00
activeconn = self . engine . conns [ activeuri ] [ " conn " ]
2009-03-09 23:16:45 +03:00
2011-07-14 21:13:13 +04:00
self . widget ( " create-conn-label " ) . set_text ( activedesc )
2009-03-09 23:16:45 +03:00
if len ( model ) < = 1 :
2011-07-14 21:13:13 +04:00
self . widget ( " create-conn " ) . hide ( )
self . widget ( " create-conn-label " ) . show ( )
2006-09-13 01:49:29 +04:00
else :
2011-07-14 21:13:13 +04:00
self . widget ( " create-conn " ) . show ( )
self . widget ( " create-conn-label " ) . hide ( )
2009-03-09 23:16:45 +03:00
return activeconn
2015-09-12 20:03:51 +03:00
#############################################
# Helpers for populating OS type/variant UI #
#############################################
2011-07-26 02:53:09 +04:00
def _add_os_row ( self , model , name = " " , label = " " , supported = False ,
sep = False , action = False ) :
2015-09-12 22:14:40 +03:00
"""
Helper for building an os type / version row and adding it to
the list model if necessary
"""
visible = self . _show_all_os_was_selected or supported
2011-07-26 02:53:09 +04:00
if sep or action :
2015-09-12 22:14:40 +03:00
visible = not self . _show_all_os_was_selected
2011-07-26 02:53:09 +04:00
if not visible :
return
2015-09-12 22:14:40 +03:00
row = [ ]
row . insert ( OS_COL_ID , name )
row . insert ( OS_COL_LABEL , label )
row . insert ( OS_COL_IS_SEP , sep )
row . insert ( OS_COL_IS_SHOW_ALL , action )
2011-07-26 02:53:09 +04:00
2015-09-12 22:14:40 +03:00
model . append ( row )
def _populate_os_type_model ( self ) :
widget = self . widget ( " install-os-type " )
model = widget . get_model ( )
2009-03-09 23:16:45 +03:00
model . clear ( )
2012-10-24 23:12:19 +04:00
2015-04-04 20:48:15 +03:00
# Kind of a hack, just show linux + windows by default since
# that's all 98% of people care about
supportl = [ " generic " , " linux " , " windows " ]
2011-07-26 02:53:09 +04:00
2015-04-04 20:48:15 +03:00
# Move 'generic' to the front of the list
types = virtinst . OSDB . list_types ( )
types . remove ( " generic " )
types . insert ( 0 , " generic " )
2011-07-26 02:53:09 +04:00
2015-04-04 19:37:46 +03:00
for typename in types :
supported = ( typename in supportl )
typelabel = typename . capitalize ( )
if typename in [ " unix " ] :
typelabel = typename . upper ( )
self . _add_os_row ( model , typename , typelabel , supported )
2011-07-26 02:53:09 +04:00
self . _add_os_row ( model , sep = True )
self . _add_os_row ( model , label = _ ( " Show all OS options " ) , action = True )
2015-04-04 20:48:15 +03:00
# Select 'generic' by default
2011-07-26 02:53:09 +04:00
widget . set_active ( 0 )
2015-09-12 22:14:40 +03:00
def _populate_os_variant_model ( self , _type ) :
widget = self . widget ( " install-os-version " )
model = widget . get_model ( )
2009-03-09 23:16:45 +03:00
model . clear ( )
2010-12-14 00:02:59 +03:00
preferred = self . config . preferred_distros
2015-04-04 20:48:15 +03:00
variants = virtinst . OSDB . list_os ( typename = _type , sortpref = preferred )
supportl = virtinst . OSDB . list_os ( typename = _type , sortpref = preferred ,
only_supported = True )
2011-07-26 02:53:09 +04:00
for v in variants :
2015-04-04 20:48:15 +03:00
supported = v in supportl or v . name == " generic "
2013-08-11 22:52:30 +04:00
self . _add_os_row ( model , v . name , v . label , supported )
2011-07-26 02:53:09 +04:00
self . _add_os_row ( model , sep = True )
self . _add_os_row ( model , label = _ ( " Show all OS options " ) , action = True )
2015-04-04 20:48:15 +03:00
widget . set_active ( 0 )
2015-09-12 22:14:40 +03:00
def _set_distro_labels ( self , distro , ver ) :
self . widget ( " install-os-type-label " ) . set_text ( distro )
self . widget ( " install-os-version-label " ) . set_text ( ver )
def _set_os_id_in_ui ( self , os_widget , os_id ) :
"""
Helper method to set the os type / version widgets to the passed
OS ID value
"""
model = os_widget . get_model ( )
def find_row ( ) :
for idx in range ( len ( model ) ) :
row = model [ idx ]
if os_id and row [ OS_COL_ID ] == os_id :
os_widget . set_active ( idx )
return row [ OS_COL_LABEL ]
os_widget . set_active ( 0 )
label = None
if os_id :
label = find_row ( )
if not label and not self . _show_all_os_was_selected :
# We didn't find the OS in the variant UI, but we are only
# showing the reduced OS list. Trigger the _show_all_os option,
# and try again.
os_widget . set_active ( len ( model ) - 1 )
label = find_row ( )
return label or _ ( " Unknown " )
def _set_distro_selection ( self , variant ) :
"""
Update the UI with the distro that was detected from the detection
thread .
"""
if not self . _is_os_detect_active ( ) :
# If the user changed the OS detect checkbox inbetween, don't
# update the UI
return
distro_type = None
distro_var = None
if variant :
osclass = virtinst . OSDB . lookup_os ( variant )
distro_type = osclass . get_typename ( )
distro_var = osclass . name
dl = self . _set_os_id_in_ui (
self . widget ( " install-os-type " ) , distro_type )
vl = self . _set_os_id_in_ui (
self . widget ( " install-os-version " ) , distro_var )
self . _set_distro_labels ( dl , vl )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
###############################
# Misc UI populating routines #
###############################
2009-03-09 23:16:45 +03:00
2015-09-14 23:22:17 +03:00
def _populate_summary_storage ( self , path = None ) :
2015-09-14 23:05:58 +03:00
storagetmpl = " <span size= ' small ' color= ' #484848 ' > %s </span> "
storagesize = " "
storagepath = " "
disk = _get_vmm_device ( self . _guest , " disk " )
if disk :
if disk . wants_storage_creation ( ) :
storagesize = " %s " % _pretty_storage ( disk . get_size ( ) )
2015-09-14 23:22:17 +03:00
if not path :
path = disk . path
storagepath = ( storagetmpl % path )
2015-09-14 23:05:58 +03:00
elif len ( self . _guest . get_devices ( " filesystem " ) ) :
fs = self . _guest . get_devices ( " filesystem " ) [ 0 ]
storagepath = storagetmpl % fs . source
elif self . _guest . os . is_container ( ) :
storagepath = _ ( " Host filesystem " )
else :
storagepath = _ ( " None " )
self . widget ( " summary-storage " ) . set_markup ( storagesize )
self . widget ( " summary-storage " ) . set_visible ( bool ( storagesize ) )
self . widget ( " summary-storage-path " ) . set_markup ( storagepath )
2015-09-12 20:03:51 +03:00
def _populate_summary ( self ) :
distro , version , ignore1 , dlabel , vlabel = self . _get_config_os_info ( )
2015-09-13 19:45:35 +03:00
mem = _pretty_memory ( int ( self . _guest . memory ) )
cpu = str ( int ( self . _guest . vcpus ) )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
instmethod = self . _get_config_install_page ( )
2009-03-09 23:16:45 +03:00
install = " "
if instmethod == INSTALL_PAGE_ISO :
install = _ ( " Local CDROM/ISO " )
elif instmethod == INSTALL_PAGE_URL :
install = _ ( " URL Install Tree " )
elif instmethod == INSTALL_PAGE_PXE :
install = _ ( " PXE Install " )
2010-03-23 01:15:18 +03:00
elif instmethod == INSTALL_PAGE_IMPORT :
install = _ ( " Import existing OS image " )
2011-06-08 01:42:50 +04:00
elif instmethod == INSTALL_PAGE_CONTAINER_APP :
install = _ ( " Application container " )
2011-06-21 19:04:22 +04:00
elif instmethod == INSTALL_PAGE_CONTAINER_OS :
2011-06-08 01:42:50 +04:00
install = _ ( " Operating system container " )
2009-03-09 23:16:45 +03:00
osstr = " "
2012-02-14 03:35:56 +04:00
have_os = True
2015-09-13 19:45:35 +03:00
if self . _guest . os . is_container ( ) :
2011-06-21 19:04:22 +04:00
osstr = _ ( " Linux " )
2012-02-14 03:35:56 +04:00
elif not distro :
2009-03-09 23:16:45 +03:00
osstr = _ ( " Generic " )
2012-02-14 03:35:56 +04:00
have_os = False
elif not version :
2009-03-09 23:16:45 +03:00
osstr = _ ( " Generic " ) + " " + dlabel
2012-02-14 03:35:56 +04:00
have_os = False
2007-03-21 19:28:36 +03:00
else :
2009-03-09 23:16:45 +03:00
osstr = vlabel
2007-03-21 19:28:36 +03:00
2013-09-02 04:18:14 +04:00
self . widget ( " finish-warn-os " ) . set_visible ( not have_os )
2011-07-14 21:13:13 +04:00
self . widget ( " summary-os " ) . set_text ( osstr )
self . widget ( " summary-install " ) . set_text ( install )
self . widget ( " summary-mem " ) . set_text ( mem )
self . widget ( " summary-cpu " ) . set_text ( cpu )
2015-09-14 23:05:58 +03:00
self . _populate_summary_storage ( )
2006-09-13 01:49:29 +04:00
2015-09-12 20:03:51 +03:00
self . _netdev_changed ( None )
2014-01-28 01:58:45 +04:00
2015-09-12 20:03:51 +03:00
################################
# UI state getters and helpers #
################################
def _get_config_name ( self ) :
2011-07-14 21:13:13 +04:00
return self . widget ( " create-vm-name " ) . get_text ( )
2006-09-13 01:49:29 +04:00
2015-09-12 20:03:51 +03:00
def _get_config_machine ( self ) :
2015-09-14 01:01:39 +03:00
return uiutil . get_list_selection ( self . widget ( " machine " ) ,
2014-04-03 18:53:54 +04:00
check_visible = True )
2013-10-02 19:56:51 +04:00
2015-09-12 20:03:51 +03:00
def _get_config_install_page ( self ) :
2013-09-09 19:02:34 +04:00
if self . widget ( " virt-install-box " ) . get_visible ( ) :
2011-07-14 21:13:13 +04:00
if self . widget ( " method-local " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_ISO
2011-07-14 21:13:13 +04:00
elif self . widget ( " method-tree " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_URL
2011-07-14 21:13:13 +04:00
elif self . widget ( " method-pxe " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_PXE
2011-07-14 21:13:13 +04:00
elif self . widget ( " method-import " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_IMPORT
else :
2011-07-14 21:13:13 +04:00
if self . widget ( " method-container-app " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_CONTAINER_APP
2011-07-14 21:13:13 +04:00
if self . widget ( " method-container-os " ) . get_active ( ) :
2011-06-08 01:42:50 +04:00
return INSTALL_PAGE_CONTAINER_OS
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _is_container_install ( self ) :
return self . _get_config_install_page ( ) in [ INSTALL_PAGE_CONTAINER_APP ,
INSTALL_PAGE_CONTAINER_OS ]
def _should_skip_disk_page ( self ) :
return self . _get_config_install_page ( ) in [ INSTALL_PAGE_IMPORT ,
INSTALL_PAGE_CONTAINER_APP ,
INSTALL_PAGE_CONTAINER_OS ]
def _get_config_os_info ( self ) :
2015-05-20 00:17:53 +03:00
drow = uiutil . get_list_selected_row ( self . widget ( " install-os-type " ) )
vrow = uiutil . get_list_selected_row ( self . widget ( " install-os-version " ) )
2009-03-09 23:16:45 +03:00
distro = None
dlabel = None
variant = None
2014-06-04 17:57:43 +04:00
variant_found = False
2014-04-24 18:58:11 +04:00
vlabel = self . widget ( " install-os-version-entry " ) . get_text ( )
2015-09-12 22:14:40 +03:00
for row in self . widget ( " install-os-version " ) . get_model ( ) :
if ( not row [ OS_COL_IS_SEP ] and
not row [ OS_COL_IS_SHOW_ALL ] and
row [ OS_COL_LABEL ] == vlabel ) :
variant = row [ OS_COL_ID ]
2014-06-04 17:57:43 +04:00
variant_found = True
2014-04-24 18:58:11 +04:00
break
2014-06-04 17:57:43 +04:00
if vlabel and not variant_found :
2014-04-24 18:58:11 +04:00
return ( None , None , False , None , None )
2009-03-09 23:16:45 +03:00
2014-01-27 05:21:12 +04:00
if drow :
2015-09-12 22:14:40 +03:00
distro = drow [ OS_COL_ID ]
dlabel = drow [ OS_COL_LABEL ]
2014-01-27 05:21:12 +04:00
if vrow :
2015-09-12 22:14:40 +03:00
variant = vrow [ OS_COL_ID ]
vlabel = vrow [ OS_COL_LABEL ]
2009-03-09 23:16:45 +03:00
2013-01-13 01:13:53 +04:00
return ( distro and str ( distro ) ,
variant and str ( variant ) ,
2014-04-24 18:58:11 +04:00
True ,
2013-01-13 01:13:53 +04:00
str ( dlabel ) , str ( vlabel ) )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _get_config_local_media ( self , store_media = False ) :
2015-09-12 22:14:40 +03:00
if self . widget ( " install-cdrom-radio " ) . get_active ( ) :
2015-09-13 19:45:35 +03:00
return self . _mediacombo . get_path ( )
2009-03-09 23:16:45 +03:00
else :
2015-09-12 22:14:40 +03:00
ret = self . widget ( " install-iso-entry " ) . get_text ( )
2009-05-11 19:00:03 +04:00
if ret and store_media :
2013-04-18 01:39:25 +04:00
self . config . add_iso_path ( ret )
2009-05-11 19:00:03 +04:00
return ret
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _get_config_detectable_media ( self ) :
instpage = self . _get_config_install_page ( )
2009-03-09 23:16:45 +03:00
media = " "
if instpage == INSTALL_PAGE_ISO :
2015-09-12 20:03:51 +03:00
media = self . _get_config_local_media ( )
2009-03-09 23:16:45 +03:00
elif instpage == INSTALL_PAGE_URL :
2015-09-12 22:14:40 +03:00
media = self . widget ( " install-url-entry " ) . get_text ( )
2010-03-23 01:15:18 +03:00
elif instpage == INSTALL_PAGE_IMPORT :
2011-07-14 21:13:13 +04:00
media = self . widget ( " install-import-entry " ) . get_text ( )
2009-03-09 23:16:45 +03:00
return media
2015-09-12 20:03:51 +03:00
def _get_config_url_info ( self , store_media = False ) :
2015-09-12 22:14:40 +03:00
media = self . widget ( " install-url-entry " ) . get_text ( ) . strip ( )
2011-07-14 21:13:13 +04:00
extra = self . widget ( " install-urlopts-entry " ) . get_text ( ) . strip ( )
2009-03-09 23:16:45 +03:00
2009-05-11 19:00:03 +04:00
if media and store_media :
2009-03-09 23:16:45 +03:00
self . config . add_media_url ( media )
2015-11-22 04:21:09 +03:00
return ( media . strip ( ) , extra . strip ( ) )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _get_config_import_path ( self ) :
2011-07-14 21:13:13 +04:00
return self . widget ( " install-import-entry " ) . get_text ( )
2010-03-23 01:15:18 +03:00
2015-09-12 20:03:51 +03:00
def _is_default_storage ( self ) :
2015-09-13 19:45:35 +03:00
return ( self . _addstorage . is_default_storage ( ) and
2015-09-12 20:03:51 +03:00
not self . _should_skip_disk_page ( ) )
2010-03-04 02:16:08 +03:00
2015-09-12 20:03:51 +03:00
def _is_os_detect_active ( self ) :
2011-07-14 21:13:13 +04:00
return self . widget ( " install-detect-os " ) . get_active ( )
2009-03-09 23:16:45 +03:00
2015-09-06 21:42:55 +03:00
################
# UI Listeners #
################
def _close_requested ( self , * ignore1 , * * ignore2 ) :
2015-09-12 20:03:51 +03:00
"""
When user tries to close the dialog , check for any disks that
we should auto cleanup
"""
2015-09-13 19:45:35 +03:00
if ( self . _failed_guest and
self . _failed_guest . get_created_disks ( ) ) :
2015-09-06 21:42:55 +03:00
def _cleanup_disks ( asyncjob ) :
meter = asyncjob . get_meter ( )
2015-09-13 19:45:35 +03:00
self . _failed_guest . cleanup_created_disks ( meter )
2015-09-06 21:42:55 +03:00
def _cleanup_disks_finished ( error , details ) :
if error :
logging . debug ( " Error cleaning up disk images: "
" \n error= %s \n details= %s " , error , details )
self . idle_add ( self . _close )
progWin = vmmAsyncJob (
_cleanup_disks , [ ] ,
_cleanup_disks_finished , [ ] ,
_ ( " Removing disk images " ) ,
_ ( " Removing disk images we created for this virtual machine. " ) ,
self . topwin )
progWin . run ( )
else :
self . _close ( )
return 1
2015-09-12 20:03:51 +03:00
# Intro page listeners
def _conn_changed ( self , src ) :
2015-05-20 00:17:53 +03:00
uri = uiutil . get_list_selection ( src )
2015-11-02 22:08:09 +03:00
newconn = None
2014-01-27 05:21:12 +04:00
if uri :
2015-11-02 22:08:09 +03:00
newconn = self . engine . conns [ uri ] [ " conn " ]
2010-02-11 04:26:40 +03:00
# If we aren't visible, let reset_state handle this for us, which
# has a better chance of reporting error
if not self . is_visible ( ) :
2009-03-09 23:16:45 +03:00
return
2015-11-02 22:08:09 +03:00
if self . conn is not newconn :
self . _set_conn ( newconn )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _method_changed ( self , src ) :
2011-06-21 21:04:46 +04:00
ignore = src
2015-09-12 20:03:51 +03:00
# Reset the page number, since the total page numbers depend
# on the chosen install method
self . _set_page_num_text ( 0 )
2011-06-21 21:04:46 +04:00
2015-09-12 20:03:51 +03:00
def _machine_changed ( self , ignore ) :
machine = self . _get_config_machine ( )
2015-09-13 19:45:35 +03:00
show_dtb_virtio = ( self . _capsinfo . arch == " armv7l " and
2013-10-02 19:56:51 +04:00
machine in [ " vexpress-a9 " , " vexpress-15 " ] )
2014-01-27 03:15:50 +04:00
uiutil . set_grid_row_visible (
2015-09-14 01:01:39 +03:00
self . widget ( " dtb-warn-virtio " ) , show_dtb_virtio )
2013-10-02 19:56:51 +04:00
2015-09-15 01:31:56 +03:00
def _xen_type_changed ( self , ignore ) :
os_type = uiutil . get_list_selection ( self . widget ( " xen-type " ) , column = 1 )
if not os_type :
2009-03-09 23:16:45 +03:00
return
2015-09-15 01:31:56 +03:00
self . _change_caps ( os_type )
2015-09-12 20:03:51 +03:00
self . _populate_arch ( )
2009-03-09 23:16:45 +03:00
2015-09-15 01:31:56 +03:00
def _arch_changed ( self , ignore ) :
arch = uiutil . get_list_selection ( self . widget ( " arch " ) , column = 1 )
2014-01-27 05:21:12 +04:00
if not arch :
2009-03-09 23:16:45 +03:00
return
2015-09-13 19:45:35 +03:00
self . _change_caps ( self . _capsinfo . os_type , arch )
2015-09-15 01:31:56 +03:00
self . _populate_virt_type ( )
def _virt_type_changed ( self , ignore ) :
domtype = uiutil . get_list_selection ( self . widget ( " virt-type " ) , column = 1 )
if not domtype :
return
self . _change_caps ( self . _capsinfo . os_type , self . _capsinfo . arch , domtype )
2015-09-12 20:03:51 +03:00
2009-05-11 21:18:14 +04:00
2015-09-12 20:03:51 +03:00
# Install page listeners
2015-09-12 22:14:40 +03:00
def _detectable_media_widget_changed ( self , widget , checkfocus = True ) :
self . _os_already_detected_for_media = False
# If the text entry widget has focus, don't fire detect_media_os,
# it means the user is probably typing. It will be detected
# when the user activates the widget, or we try to switch pages
if ( checkfocus and
hasattr ( widget , " get_text " ) and widget . has_focus ( ) ) :
2009-03-09 23:16:45 +03:00
return
2014-03-20 04:09:58 +04:00
2015-09-12 22:14:40 +03:00
self . _start_detect_os_if_needed ( )
2009-03-09 23:16:45 +03:00
2015-09-12 22:14:40 +03:00
def _url_changed ( self , src ) :
self . _detectable_media_widget_changed ( src )
def _url_activated ( self , src ) :
self . _detectable_media_widget_changed ( src , checkfocus = False )
def _iso_changed ( self , src ) :
self . _detectable_media_widget_changed ( src )
def _iso_activated ( self , src ) :
self . _detectable_media_widget_changed ( src , checkfocus = False )
def _cdrom_changed ( self , src ) :
self . _detectable_media_widget_changed ( src )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _toggle_detect_os ( self , src ) :
2014-08-05 12:37:37 +04:00
dodetect = src . get_active ( )
2009-03-09 23:16:45 +03:00
2013-10-05 18:29:16 +04:00
self . widget ( " install-os-type-label " ) . set_visible ( dodetect )
self . widget ( " install-os-version-label " ) . set_visible ( dodetect )
self . widget ( " install-os-type " ) . set_visible ( not dodetect )
self . widget ( " install-os-version " ) . set_visible ( not dodetect )
2009-03-09 23:16:45 +03:00
if dodetect :
2014-04-24 18:58:11 +04:00
self . widget ( " install-os-version-entry " ) . set_text ( " " )
2015-09-12 22:14:40 +03:00
self . _os_already_detected_for_media = False
self . _start_detect_os_if_needed ( )
2009-03-09 23:16:45 +03:00
2011-07-26 02:53:09 +04:00
def _selected_os_row ( self ) :
2015-05-20 00:17:53 +03:00
return uiutil . get_list_selected_row ( self . widget ( " install-os-type " ) )
2011-07-26 02:53:09 +04:00
2015-09-12 20:03:51 +03:00
def _change_os_type ( self , box ) :
2011-07-26 02:53:09 +04:00
ignore = box
row = self . _selected_os_row ( )
2015-09-12 22:14:40 +03:00
if not row :
return
_type = row [ OS_COL_ID ]
self . _populate_os_variant_model ( _type )
if not row [ OS_COL_IS_SHOW_ALL ] :
return
self . _show_all_os_was_selected = True
self . _populate_os_type_model ( )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _change_os_version ( self , box ) :
2015-09-12 22:14:40 +03:00
show_all = uiutil . get_list_selection ( box ,
column = OS_COL_IS_SHOW_ALL , check_entry = False )
2014-01-27 05:21:12 +04:00
if not show_all :
2011-07-26 02:53:09 +04:00
return
2015-04-04 23:32:41 +03:00
# 'show all OS' was clicked
# Get previous type to reselect it later
2011-07-26 02:53:09 +04:00
type_row = self . _selected_os_row ( )
if not type_row :
return
2015-09-12 22:14:40 +03:00
old_type = type_row [ OS_COL_ID ]
2011-07-26 02:53:09 +04:00
2015-09-12 22:14:40 +03:00
self . _show_all_os_was_selected = True
2015-09-12 20:03:51 +03:00
self . _populate_os_type_model ( )
2011-07-26 02:53:09 +04:00
2015-04-04 23:32:41 +03:00
# Reselect previous type row
2014-01-27 05:21:12 +04:00
os_type_list = self . widget ( " install-os-type " )
os_type_model = os_type_list . get_model ( )
2011-07-26 02:53:09 +04:00
for idx in range ( len ( os_type_model ) ) :
2015-09-12 22:14:40 +03:00
if os_type_model [ idx ] [ OS_COL_ID ] == old_type :
2011-07-26 02:53:09 +04:00
os_type_list . set_active ( idx )
break
2015-09-12 22:14:40 +03:00
def _local_media_toggled ( self , src ) :
usecdrom = src . get_active ( )
self . widget ( " install-cdrom-align " ) . set_sensitive ( usecdrom )
self . widget ( " install-iso-combo " ) . set_sensitive ( not usecdrom )
self . widget ( " install-iso-browse " ) . set_sensitive ( not usecdrom )
2009-03-09 23:16:45 +03:00
2015-09-12 22:14:40 +03:00
if usecdrom :
2015-09-13 19:45:35 +03:00
self . _cdrom_changed ( self . _mediacombo . combo )
2015-09-12 22:14:40 +03:00
else :
self . _iso_changed ( self . widget ( " install-iso-entry " ) )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _os_detect_visibility_changed ( self , src , ignore = None ) :
2013-09-09 19:02:34 +04:00
is_visible = src . get_visible ( )
2011-07-14 21:13:13 +04:00
detect_chkbox = self . widget ( " install-detect-os " )
nodetect_label = self . widget ( " install-nodetect-label " )
2009-03-09 23:16:45 +03:00
detect_chkbox . set_active ( is_visible )
detect_chkbox . toggled ( )
if is_visible :
nodetect_label . hide ( )
else :
nodetect_label . show ( )
2015-09-12 20:03:51 +03:00
def _browse_oscontainer ( self , ignore ) :
2013-10-02 19:56:51 +04:00
self . _browse_file ( " install-oscontainer-fs " , is_dir = True )
2015-09-12 20:03:51 +03:00
def _browse_app ( self , ignore ) :
2013-10-02 19:56:51 +04:00
self . _browse_file ( " install-app-entry " )
2015-09-12 20:03:51 +03:00
def _browse_import ( self , ignore ) :
2013-10-02 19:56:51 +04:00
self . _browse_file ( " install-import-entry " )
2015-09-12 20:03:51 +03:00
def _browse_iso ( self , ignore ) :
2011-06-21 19:04:22 +04:00
def set_path ( ignore , path ) :
2015-09-12 22:14:40 +03:00
self . widget ( " install-iso-entry " ) . set_text ( path )
2013-10-02 19:56:51 +04:00
self . _browse_file ( None , cb = set_path , is_media = True )
2015-09-12 20:03:51 +03:00
def _browse_kernel ( self , ignore ) :
2015-09-14 01:01:39 +03:00
self . _browse_file ( " kernel " )
2015-09-12 20:03:51 +03:00
def _browse_initrd ( self , ignore ) :
2015-09-14 01:01:39 +03:00
self . _browse_file ( " initrd " )
2015-09-12 20:03:51 +03:00
def _browse_dtb ( self , ignore ) :
2015-09-14 01:01:39 +03:00
self . _browse_file ( " dtb " )
2011-06-21 19:04:22 +04:00
2015-09-12 20:03:51 +03:00
# Storage page listeners
def _toggle_enable_storage ( self , src ) :
2015-09-14 01:01:39 +03:00
self . widget ( " storage-align " ) . set_sensitive ( src . get_active ( ) )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
# Summary page listeners
2015-09-14 23:22:17 +03:00
def _name_changed ( self , src ) :
newname = src . get_text ( )
if not src . is_visible ( ) :
return
if not newname :
return
try :
path , ignore = self . _get_storage_path ( newname , do_log = False )
self . _populate_summary_storage ( path = path )
except :
logging . debug ( " Error generating storage path on name change "
" for name= %s " , newname , exc_info = True )
2015-09-12 20:03:51 +03:00
def _netdev_changed ( self , ignore ) :
2015-09-13 19:45:35 +03:00
row = self . _netlist . get_network_row ( )
2015-09-12 20:03:51 +03:00
pxe_install = ( self . _get_config_install_page ( ) == INSTALL_PAGE_PXE )
2015-11-02 22:41:47 +03:00
ntype = row [ 0 ]
connkey = row [ 6 ]
expand = ( ntype != " network " and ntype != " bridge " )
no_network = ntype is None
if ( no_network or ntype == virtinst . VirtualNetworkInterface . TYPE_USER ) :
can_pxe = False
elif ntype != virtinst . VirtualNetworkInterface . TYPE_VIRTUAL :
can_pxe = True
else :
can_pxe = self . conn . get_net ( connkey ) . can_pxe ( )
if expand :
self . widget ( " advanced-expander " ) . set_expanded ( True )
2015-09-12 20:03:51 +03:00
2015-11-22 04:39:55 +03:00
self . widget ( " netdev-warn-box " ) . set_visible ( False )
2015-11-02 22:41:47 +03:00
def _show_netdev_warn ( msg ) :
2015-09-14 01:01:39 +03:00
self . widget ( " advanced-expander " ) . set_expanded ( True )
2015-11-02 22:41:47 +03:00
self . widget ( " netdev-warn-box " ) . set_visible ( True )
self . widget ( " netdev-warn-label " ) . set_markup (
" <small> %s </small> " % msg )
2015-11-02 22:42:42 +03:00
if no_network :
_show_netdev_warn ( _ ( " No network selected " ) )
elif not can_pxe and pxe_install :
2015-11-02 22:41:47 +03:00
_show_netdev_warn ( _ ( " Network selection does not support PXE " ) )
2015-09-12 20:03:51 +03:00
########################
# Misc helper routines #
########################
def _stable_defaults ( self ) :
emu = None
2015-09-13 19:45:35 +03:00
if self . _guest :
emu = self . _guest . emulator
elif self . _capsinfo :
emu = self . _capsinfo . emulator
2015-09-12 20:03:51 +03:00
ret = self . conn . stable_defaults ( emu )
return ret
def _browse_file ( self , cbwidget , cb = None , is_media = False , is_dir = False ) :
if is_media :
reason = self . config . CONFIG_DIR_ISO_MEDIA
elif is_dir :
reason = self . config . CONFIG_DIR_FS
else :
reason = self . config . CONFIG_DIR_IMAGE
if cb :
callback = cb
else :
def callback ( ignore , text ) :
widget = cbwidget
if type ( cbwidget ) is str :
widget = self . widget ( cbwidget )
widget . set_text ( text )
2015-09-13 19:45:35 +03:00
if self . _storage_browser and self . _storage_browser . conn != self . conn :
self . _storage_browser . cleanup ( )
self . _storage_browser = None
if self . _storage_browser is None :
self . _storage_browser = vmmStorageBrowser ( self . conn )
2015-09-12 20:03:51 +03:00
2015-09-13 19:45:35 +03:00
self . _storage_browser . set_stable_defaults ( self . _stable_defaults ( ) )
self . _storage_browser . set_vm_name ( self . _get_config_name ( ) )
self . _storage_browser . set_finish_cb ( callback )
self . _storage_browser . set_browse_reason ( reason )
self . _storage_browser . show ( self . topwin )
2015-09-12 20:03:51 +03:00
######################
# Navigation methods #
######################
def _set_page_num_text ( self , cur ) :
"""
Set the ' page 1 of 4 ' style text in the wizard header
"""
cur + = 1
final = PAGE_FINISH + 1
if self . _should_skip_disk_page ( ) :
final - = 1
cur = min ( cur , final )
page_lbl = ( " <span color= ' #59B0E2 ' > %s </span> " %
_ ( " Step %(current_page)d of %(max_page)d " ) %
{ ' current_page ' : cur , ' max_page ' : final } )
self . widget ( " header-pagenum " ) . set_markup ( page_lbl )
def _set_install_page ( self ) :
2011-07-14 21:13:13 +04:00
instnotebook = self . widget ( " install-method-pages " )
detectbox = self . widget ( " install-detect-os-box " )
osbox = self . widget ( " install-os-distro-box " )
2015-09-12 20:03:51 +03:00
instpage = self . _get_config_install_page ( )
2009-03-09 23:16:45 +03:00
2011-06-08 01:42:50 +04:00
# Setting OS value for a container guest doesn't really matter
# at the moment
iscontainer = instpage in [ INSTALL_PAGE_CONTAINER_APP ,
INSTALL_PAGE_CONTAINER_OS ]
2013-09-02 04:18:14 +04:00
osbox . set_visible ( iscontainer )
2011-06-08 01:42:50 +04:00
2014-08-05 12:37:37 +04:00
enabledetect = ( instpage == INSTALL_PAGE_ISO and
self . conn and
not self . conn . is_remote ( ) or
2015-09-12 20:03:51 +03:00
self . _get_config_install_page ( ) == INSTALL_PAGE_URL )
2014-08-05 12:37:37 +04:00
detectbox . set_visible ( enabledetect )
2009-03-09 23:16:45 +03:00
if instpage == INSTALL_PAGE_PXE :
# Hide the install notebook for pxe, since there isn't anything
# to ask for
instnotebook . hide ( )
else :
instnotebook . show ( )
2011-06-08 01:42:50 +04:00
2009-03-09 23:16:45 +03:00
instnotebook . set_current_page ( instpage )
2015-09-12 20:03:51 +03:00
def _back_clicked ( self , src_ignore ) :
2011-07-14 21:13:13 +04:00
notebook = self . widget ( " create-pages " )
2009-03-09 23:16:45 +03:00
curpage = notebook . get_current_page ( )
2010-06-02 18:07:34 +04:00
next_page = curpage - 1
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
if curpage == PAGE_FINISH and self . _should_skip_disk_page ( ) :
2010-06-02 18:07:34 +04:00
# Skip over storage page
next_page - = 1
2009-03-09 23:16:45 +03:00
2010-06-02 18:07:34 +04:00
notebook . set_current_page ( next_page )
2009-03-09 23:16:45 +03:00
2011-07-19 05:31:06 +04:00
def _get_next_pagenum ( self , curpage ) :
next_page = curpage + 1
2015-09-12 20:03:51 +03:00
if next_page == PAGE_STORAGE and self . _should_skip_disk_page ( ) :
2011-07-19 05:31:06 +04:00
# Skip storage page for import installs
next_page + = 1
return next_page
2015-09-12 20:03:51 +03:00
def _forward_clicked ( self , src_ignore = None ) :
2011-07-14 21:13:13 +04:00
notebook = self . widget ( " create-pages " )
2009-03-09 23:16:45 +03:00
curpage = notebook . get_current_page ( )
2015-09-12 22:14:40 +03:00
if curpage == PAGE_INSTALL :
2010-12-03 20:55:56 +03:00
# Make sure we have detected the OS before validating the page
2015-09-12 22:14:40 +03:00
did_start = self . _start_detect_os_if_needed (
forward_after_finish = True )
if did_start :
return
2010-12-03 20:55:56 +03:00
2015-09-12 20:03:51 +03:00
if self . _validate ( curpage ) is not True :
2009-03-09 23:16:45 +03:00
return
if curpage == PAGE_NAME :
2015-09-12 20:03:51 +03:00
self . _set_install_page ( )
2009-03-09 23:16:45 +03:00
2011-07-19 05:31:06 +04:00
next_page = self . _get_next_pagenum ( curpage )
2010-03-23 01:15:18 +03:00
2011-07-14 21:13:13 +04:00
self . widget ( " create-forward " ) . grab_focus ( )
2010-03-23 01:15:18 +03:00
notebook . set_current_page ( next_page )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _page_changed ( self , ignore1 , ignore2 , pagenum ) :
2009-03-09 23:16:45 +03:00
if pagenum == PAGE_INSTALL :
2013-10-02 20:12:26 +04:00
self . widget ( " install-os-distro-box " ) . set_visible (
2015-09-12 20:03:51 +03:00
not self . _is_container_install ( ) )
2015-09-12 22:14:40 +03:00
# Kick off distro detection when we switch to the install
# page, to detect the default selected media
self . _start_detect_os_if_needed ( check_install_page = False )
2013-10-02 20:12:26 +04:00
elif pagenum == PAGE_FINISH :
2014-05-31 21:31:08 +04:00
try :
2015-09-12 20:03:51 +03:00
self . _populate_summary ( )
2014-05-31 21:31:08 +04:00
except Exception , e :
self . err . show_err ( _ ( " Error populating summary page: %s " ) %
str ( e ) )
return
2013-10-02 20:12:26 +04:00
self . widget ( " create-finish " ) . grab_focus ( )
2014-05-31 21:31:08 +04:00
2015-09-12 20:03:51 +03:00
self . _set_page_num_text ( pagenum )
2014-05-31 21:31:08 +04:00
self . widget ( " create-back " ) . set_sensitive ( pagenum != PAGE_NAME )
self . widget ( " create-forward " ) . set_visible ( pagenum != PAGE_FINISH )
self . widget ( " create-finish " ) . set_visible ( pagenum == PAGE_FINISH )
2013-10-02 20:12:26 +04:00
2015-09-12 22:14:40 +03:00
# Hide all other pages, so the dialog isn't all stretched out
# because of one large page.
2013-10-02 20:12:26 +04:00
for nr in range ( self . widget ( " create-pages " ) . get_n_pages ( ) ) :
page = self . widget ( " create-pages " ) . get_nth_page ( nr )
page . set_visible ( nr == pagenum )
2010-12-04 20:28:44 +03:00
2015-09-12 20:03:51 +03:00
############################
# Page validation routines #
############################
def _build_guest ( self , variant ) :
2015-09-13 19:45:35 +03:00
guest = self . conn . caps . build_virtinst_guest ( self . _capsinfo )
2015-09-12 20:03:51 +03:00
guest . os . machine = self . _get_config_machine ( )
2010-02-06 01:58:26 +03:00
2011-07-07 22:39:28 +04:00
# Generate UUID (makes customize dialog happy)
try :
2013-08-09 17:23:01 +04:00
guest . uuid = util . randomUUID ( guest . conn )
2011-07-07 22:39:28 +04:00
except Exception , e :
self . err . show_err ( _ ( " Error setting UUID: %s " ) % str ( e ) )
return None
2013-11-10 03:33:49 +04:00
# OS distro/variant validation
try :
if variant :
guest . os_variant = variant
except ValueError , e :
2015-08-10 20:02:27 +03:00
self . err . val_err ( _ ( " Error setting OS information. " ) , str ( e ) )
2013-11-10 03:33:49 +04:00
return None
2015-02-22 18:01:02 +03:00
if guest . os . is_arm64 ( ) :
try :
guest . set_uefi_default ( )
except :
# If this errors we will have already informed the user
# on page 1.
pass
2011-06-09 01:20:26 +04:00
# Set up default devices
2010-02-06 01:58:26 +03:00
try :
2014-02-08 01:07:32 +04:00
guest . default_graphics_type = self . config . get_graphics_type ( )
guest . skip_default_sound = not self . config . get_new_vm_sound ( )
2014-02-05 21:58:53 +04:00
guest . skip_default_usbredir = (
self . config . get_add_spice_usbredir ( ) == " no " )
2014-02-05 22:51:53 +04:00
guest . x86_cpu_default = self . config . get_default_cpu_setting (
for_cpu = True )
2014-02-05 21:58:53 +04:00
2014-02-08 01:07:32 +04:00
guest . add_default_devices ( )
2010-02-06 01:58:26 +03:00
except Exception , e :
2011-06-09 01:20:26 +04:00
self . err . show_err ( _ ( " Error setting up default devices: " ) + str ( e ) )
2010-02-06 01:58:26 +03:00
return None
return guest
2015-09-12 20:03:51 +03:00
def _validate ( self , pagenum ) :
2009-03-09 23:16:45 +03:00
try :
if pagenum == PAGE_NAME :
2015-09-12 20:03:51 +03:00
return self . _validate_intro_page ( )
2009-03-09 23:16:45 +03:00
elif pagenum == PAGE_INSTALL :
2015-09-12 20:03:51 +03:00
return self . _validate_install_page ( )
2009-03-09 23:16:45 +03:00
elif pagenum == PAGE_MEM :
2015-09-12 20:03:51 +03:00
return self . _validate_mem_page ( )
2009-03-09 23:16:45 +03:00
elif pagenum == PAGE_STORAGE :
2015-09-12 20:03:51 +03:00
return self . _validate_storage_page ( )
2009-03-09 23:16:45 +03:00
elif pagenum == PAGE_FINISH :
2015-09-12 20:03:51 +03:00
return self . _validate_final_page ( )
2009-03-09 23:16:45 +03:00
except Exception , e :
self . err . show_err ( _ ( " Uncaught error validating install "
2011-04-06 19:22:03 +04:00
" parameters: %s " ) % str ( e ) )
2009-03-09 23:16:45 +03:00
return
2015-09-12 20:03:51 +03:00
def _validate_intro_page ( self ) :
2013-10-02 19:56:51 +04:00
# We just set this here because it's needed soon after for distro
2015-09-13 19:45:35 +03:00
# detection. But the 'real' self._guest is created in validate_install,
2015-09-12 20:03:51 +03:00
# and it just uses _build_guest, so don't ever add any other guest
2013-10-02 19:56:51 +04:00
# altering here.
2015-09-13 19:45:35 +03:00
self . _guest = self . _build_guest ( None )
if not self . _guest :
2013-10-02 19:56:51 +04:00
return False
2013-10-01 23:18:34 +04:00
return True
2009-03-09 23:16:45 +03:00
2013-10-01 23:18:34 +04:00
def _generate_default_name ( self , distro , variant ) :
force_num = False
2015-09-13 19:45:35 +03:00
if self . _guest . os . is_container ( ) :
2013-10-01 23:18:34 +04:00
basename = " container "
force_num = True
elif not distro :
basename = " vm "
force_num = True
elif not variant :
basename = distro
else :
basename = variant
2009-03-09 23:16:45 +03:00
2015-09-13 19:45:35 +03:00
if self . _guest . os . arch != self . conn . caps . host . cpu . arch :
basename + = " - %s " % _pretty_arch ( self . _guest . os . arch )
2013-10-02 21:19:40 +04:00
force_num = False
2013-10-01 23:18:34 +04:00
return util . generate_name ( basename ,
self . conn . get_backend ( ) . lookupByName ,
start_num = force_num and 1 or 2 , force_num = force_num ,
sep = not force_num and " - " or " " ,
2014-06-03 01:17:47 +04:00
collidelist = [ vm . get_name ( ) for vm in self . conn . list_vms ( ) ] )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _validate_install_page ( self ) :
instmethod = self . _get_config_install_page ( )
2009-03-09 23:16:45 +03:00
installer = None
location = None
extra = None
cdrom = False
2010-03-23 01:15:18 +03:00
is_import = False
2011-06-08 01:42:50 +04:00
init = None
2011-06-21 19:04:22 +04:00
fs = None
2015-09-12 20:03:51 +03:00
distro , variant , valid , ignore1 , ignore2 = self . _get_config_os_info ( )
2014-04-24 18:58:11 +04:00
if not valid :
return self . err . val_err ( _ ( " Please specify a valid OS variant. " ) )
2009-03-09 23:16:45 +03:00
if instmethod == INSTALL_PAGE_ISO :
2010-12-08 00:17:19 +03:00
instclass = virtinst . DistroInstaller
2015-09-12 20:03:51 +03:00
media = self . _get_config_local_media ( )
2009-03-09 23:16:45 +03:00
if not media :
2011-08-30 22:50:50 +04:00
return self . err . val_err (
_ ( " An install media selection is required. " ) )
2009-03-09 23:16:45 +03:00
location = media
cdrom = True
elif instmethod == INSTALL_PAGE_URL :
instclass = virtinst . DistroInstaller
2015-11-22 04:21:09 +03:00
media , extra = self . _get_config_url_info ( )
2009-03-09 23:16:45 +03:00
if not media :
2011-08-30 22:50:50 +04:00
return self . err . val_err ( _ ( " An install tree is required. " ) )
2009-03-09 23:16:45 +03:00
location = media
elif instmethod == INSTALL_PAGE_PXE :
instclass = virtinst . PXEInstaller
2010-03-23 01:15:18 +03:00
elif instmethod == INSTALL_PAGE_IMPORT :
instclass = virtinst . ImportInstaller
is_import = True
2015-09-12 20:03:51 +03:00
import_path = self . _get_config_import_path ( )
2010-03-23 01:15:18 +03:00
if not import_path :
2011-08-30 22:50:50 +04:00
return self . err . val_err (
_ ( " A storage path to import is required. " ) )
2009-03-09 23:16:45 +03:00
2011-06-08 01:42:50 +04:00
elif instmethod == INSTALL_PAGE_CONTAINER_APP :
instclass = virtinst . ContainerInstaller
2015-09-12 20:03:51 +03:00
init = self . widget ( " install-app-entry " ) . get_text ( )
2011-06-08 01:42:50 +04:00
if not init :
2011-08-30 22:50:50 +04:00
return self . err . val_err ( _ ( " An application path is required. " ) )
2011-06-08 01:42:50 +04:00
2011-06-21 19:04:22 +04:00
elif instmethod == INSTALL_PAGE_CONTAINER_OS :
instclass = virtinst . ContainerInstaller
2015-09-12 20:03:51 +03:00
fs = self . widget ( " install-oscontainer-fs " ) . get_text ( )
2011-06-21 19:04:22 +04:00
if not fs :
2011-08-30 22:50:50 +04:00
return self . err . val_err ( _ ( " An OS directory path is required. " ) )
2011-06-21 19:04:22 +04:00
2009-03-09 23:16:45 +03:00
# Build the installer and Guest instance
try :
2013-10-02 19:56:51 +04:00
# Overwrite the guest
2013-07-17 15:53:47 +04:00
installer = instclass ( self . conn . get_backend ( ) )
2015-09-13 19:45:35 +03:00
self . _guest = self . _build_guest ( variant or distro )
if not self . _guest :
2010-02-06 01:58:26 +03:00
return False
2015-09-13 19:45:35 +03:00
self . _guest . installer = installer
2009-03-09 23:16:45 +03:00
except Exception , e :
2011-08-30 22:50:50 +04:00
return self . err . val_err (
_ ( " Error setting installer parameters. " ) , e )
2009-03-09 23:16:45 +03:00
# Validate media location
try :
if location is not None :
2015-09-13 19:45:35 +03:00
self . _guest . installer . location = location
2009-03-09 23:16:45 +03:00
if cdrom :
2015-09-13 19:45:35 +03:00
self . _guest . installer . cdrom = True
2009-03-09 23:16:45 +03:00
if extra :
2016-03-18 05:28:17 +03:00
self . _guest . installer . extraargs = [ extra ]
2011-06-08 01:42:50 +04:00
if init :
2015-09-13 19:45:35 +03:00
self . _guest . os . init = init
2011-06-08 01:42:50 +04:00
2011-06-21 19:04:22 +04:00
if fs :
2015-09-13 19:45:35 +03:00
fsdev = virtinst . VirtualFilesystem ( self . _guest . conn )
2011-06-21 19:04:22 +04:00
fsdev . target = " / "
fsdev . source = fs
2015-09-13 19:45:35 +03:00
self . _guest . add_device ( fsdev )
2009-03-09 23:16:45 +03:00
except Exception , e :
2011-08-30 22:50:50 +04:00
return self . err . val_err (
_ ( " Error setting install media location. " ) , e )
2009-03-09 23:16:45 +03:00
2013-10-02 19:56:51 +04:00
# Setting kernel
if instmethod == INSTALL_PAGE_IMPORT :
2015-09-14 01:01:39 +03:00
kernel = self . widget ( " kernel " ) . get_text ( ) or None
kargs = self . widget ( " kernel-args " ) . get_text ( ) or None
initrd = self . widget ( " initrd " ) . get_text ( ) or None
dtb = self . widget ( " dtb " ) . get_text ( ) or None
2013-10-02 19:56:51 +04:00
2015-09-14 01:01:39 +03:00
if not self . widget ( " dtb " ) . get_visible ( ) :
2013-10-02 19:56:51 +04:00
dtb = None
2015-09-14 01:01:39 +03:00
if not self . widget ( " kernel " ) . get_visible ( ) :
2013-10-02 19:56:51 +04:00
kernel = None
initrd = None
kargs = None
2015-09-13 19:45:35 +03:00
self . _guest . os . kernel = kernel
self . _guest . os . initrd = initrd
self . _guest . os . dtb = dtb
self . _guest . os . kernel_args = kargs
2013-10-02 19:56:51 +04:00
2015-09-13 19:45:35 +03:00
require_kernel = ( " arm " in self . _capsinfo . arch )
2013-10-02 19:56:51 +04:00
if require_kernel and not kernel :
return self . err . val_err (
_ ( " A kernel is required for %s guests. " ) %
2015-09-13 19:45:35 +03:00
self . _capsinfo . arch )
2013-10-02 19:56:51 +04:00
2013-10-01 23:18:34 +04:00
try :
name = self . _generate_default_name ( distro , variant )
self . widget ( " create-vm-name " ) . set_text ( name )
2015-09-13 19:45:35 +03:00
self . _guest . name = name
2013-10-01 23:18:34 +04:00
except Exception , e :
return self . err . val_err ( _ ( " Error setting default name. " ) , e )
2010-03-23 01:15:18 +03:00
# Kind of wonky, run storage validation now, which will assign
# the import path. Import installer skips the storage page.
if is_import :
2015-09-12 20:03:51 +03:00
if not self . _validate_storage_page ( ) :
2010-03-23 01:15:18 +03:00
return False
2015-09-13 19:45:35 +03:00
if self . _guest . installer . scratchdir_required ( ) :
path = util . make_scratchdir ( self . _guest . conn , self . _guest . type )
2013-10-01 23:18:34 +04:00
elif instmethod == INSTALL_PAGE_ISO :
2015-09-13 19:45:35 +03:00
path = self . _guest . installer . location
2013-10-01 23:18:34 +04:00
else :
path = None
2009-12-01 20:41:45 +03:00
2013-10-01 23:18:34 +04:00
if path :
2015-09-13 19:45:35 +03:00
self . _addstorage . check_path_search (
2014-01-29 01:53:11 +04:00
self , self . conn , path )
2009-12-01 20:41:45 +03:00
2015-04-04 19:04:11 +03:00
res = None
osobj = virtinst . OSDB . lookup_os ( variant )
if osobj :
2015-09-13 19:45:35 +03:00
res = osobj . get_recommended_resources ( self . _guest )
2015-04-04 19:10:20 +03:00
logging . debug ( " Recommended resources for variant= %s : %s " ,
variant , res )
2014-02-17 19:40:05 +04:00
# Change the default values suggested to the user.
ram_size = DEFAULT_MEM
if res and res . get ( " ram " ) > 0 :
ram_size = res [ " ram " ] / ( 1024 * * 2 )
2015-09-14 01:01:39 +03:00
self . widget ( " mem " ) . set_value ( ram_size )
2014-02-17 19:40:05 +04:00
n_cpus = 1
if res and res . get ( " n-cpus " ) > 0 :
n_cpus = res [ " n-cpus " ]
2015-09-14 01:01:39 +03:00
self . widget ( " cpus " ) . set_value ( n_cpus )
2014-02-17 19:40:05 +04:00
if res and res . get ( " storage " ) :
storage_size = int ( res [ " storage " ] ) / ( 1024 * * 3 )
2015-09-14 02:30:10 +03:00
self . _addstorage . widget ( " storage-size " ) . set_value ( storage_size )
2014-02-17 19:40:05 +04:00
2009-05-11 19:00:03 +04:00
# Validation passed, store the install path (if there is one) in
2014-09-28 15:37:16 +04:00
# gsettings
2015-09-12 20:03:51 +03:00
self . _get_config_local_media ( store_media = True )
self . _get_config_url_info ( store_media = True )
2009-03-09 23:16:45 +03:00
return True
2007-02-01 22:16:44 +03:00
2015-09-12 20:03:51 +03:00
def _validate_mem_page ( self ) :
2015-09-14 01:01:39 +03:00
cpus = self . widget ( " cpus " ) . get_value ( )
mem = self . widget ( " mem " ) . get_value ( )
2009-03-09 23:16:45 +03:00
# VCPUS
try :
2015-09-13 19:45:35 +03:00
self . _guest . vcpus = int ( cpus )
2009-03-09 23:16:45 +03:00
except Exception , e :
2011-08-30 22:50:50 +04:00
return self . err . val_err ( _ ( " Error setting CPUs. " ) , e )
2009-03-09 23:16:45 +03:00
# Memory
try :
2015-09-13 19:45:35 +03:00
self . _guest . memory = int ( mem ) * 1024
self . _guest . maxmemory = int ( mem ) * 1024
2009-03-09 23:16:45 +03:00
except Exception , e :
2011-08-30 22:50:50 +04:00
return self . err . val_err ( _ ( " Error setting guest memory. " ) , e )
2009-03-09 23:16:45 +03:00
return True
2015-09-14 23:22:17 +03:00
def _get_storage_path ( self , vmname , do_log ) :
2015-09-06 21:42:55 +03:00
failed_disk = None
2015-09-14 23:05:58 +03:00
if self . _failed_guest :
failed_disk = _get_vmm_device ( self . _failed_guest , " disk " )
2010-12-08 00:48:13 +03:00
2014-01-29 01:53:11 +04:00
path = None
2015-09-06 21:42:55 +03:00
path_already_created = False
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
if self . _get_config_install_page ( ) == INSTALL_PAGE_IMPORT :
path = self . _get_config_import_path ( )
2015-09-06 21:42:55 +03:00
2015-09-12 20:03:51 +03:00
elif self . _is_default_storage ( ) :
2015-09-14 23:05:58 +03:00
if failed_disk :
# Don't generate a new path if the install failed
2015-09-06 21:42:55 +03:00
path = failed_disk . path
path_already_created = failed_disk . storage_was_created
2015-09-14 23:22:17 +03:00
if do_log :
logging . debug ( " Reusing failed disk path= %s "
" already_created= %s " , path , path_already_created )
2015-09-06 21:42:55 +03:00
else :
2015-09-14 23:22:17 +03:00
path = self . _addstorage . get_default_path ( vmname )
if do_log :
logging . debug ( " Default storage path is: %s " , path )
return path , path_already_created
def _validate_storage_page ( self ) :
path , path_already_created = self . _get_storage_path (
self . _guest . name , do_log = True )
2012-02-13 23:49:00 +04:00
2015-09-14 23:05:58 +03:00
disk = None
2015-09-14 01:42:10 +03:00
storage_enabled = self . widget ( " enable-storage " ) . get_active ( )
2015-09-13 23:02:35 +03:00
try :
2015-09-14 01:42:10 +03:00
if storage_enabled :
2015-09-14 23:05:58 +03:00
disk = self . _addstorage . validate_storage ( self . _guest . name ,
2015-09-14 01:42:10 +03:00
path = path )
2015-09-13 23:02:35 +03:00
except Exception , e :
return self . err . val_err ( _ ( " Storage parameter error. " ) , e )
2015-09-14 23:05:58 +03:00
if disk is False :
2015-09-14 01:42:10 +03:00
return False
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
if self . _get_config_install_page ( ) == INSTALL_PAGE_ISO :
2014-01-29 01:53:11 +04:00
# CD/ISO install and no disks implies LiveCD
2015-09-14 01:42:10 +03:00
self . _guest . installer . livecd = not storage_enabled
2009-03-09 23:16:45 +03:00
2015-09-14 23:05:58 +03:00
if disk and self . _addstorage . validate_disk_object ( disk ) is False :
return False
_remove_vmm_device ( self . _guest , " disk " )
2015-09-14 01:42:10 +03:00
if not storage_enabled :
return True
2009-09-24 19:41:49 +04:00
2015-09-14 23:05:58 +03:00
disk . storage_was_created = path_already_created
_mark_vmm_device ( disk )
self . _guest . add_device ( disk )
2010-12-08 00:48:13 +03:00
2009-09-24 19:41:49 +04:00
return True
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _validate_final_page ( self ) :
2010-12-07 22:20:11 +03:00
# HV + Arch selection
2015-09-12 20:03:51 +03:00
name = self . _get_config_name ( )
2015-09-13 19:45:35 +03:00
if name != self . _guest . name :
2015-04-03 00:54:47 +03:00
try :
2015-09-13 19:45:35 +03:00
self . _guest . name = name
2015-04-03 00:54:47 +03:00
except Exception , e :
return self . err . val_err ( _ ( " Invalid guest name " ) , str ( e ) )
2015-09-12 20:03:51 +03:00
if self . _is_default_storage ( ) :
2015-05-03 23:37:42 +03:00
logging . debug ( " User changed VM name and using default "
" storage, re-validating with new default storage path. " )
2013-10-01 23:18:34 +04:00
# User changed the name and we are using default storage
# which depends on the VM name. Revalidate things
2015-09-12 20:03:51 +03:00
if not self . _validate_storage_page ( ) :
2013-10-01 23:18:34 +04:00
return False
2010-12-07 22:20:11 +03:00
2015-09-13 19:45:35 +03:00
nettype = self . _netlist . get_network_selection ( ) [ 0 ]
2009-03-09 23:16:45 +03:00
if nettype is None :
# No network device available
2015-09-12 20:03:51 +03:00
instmethod = self . _get_config_install_page ( )
2009-03-09 23:16:45 +03:00
methname = None
if instmethod == INSTALL_PAGE_PXE :
methname = " PXE "
elif instmethod == INSTALL_PAGE_URL :
methname = " URL "
if methname :
2011-08-30 22:50:50 +04:00
return self . err . val_err (
_ ( " Network device required for %s install. " ) %
methname )
2009-03-09 23:16:45 +03:00
2015-04-08 01:52:35 +03:00
macaddr = virtinst . VirtualNetworkInterface . generate_mac (
self . conn . get_backend ( ) )
2015-09-13 19:45:35 +03:00
nic = self . _netlist . validate_network ( macaddr )
2012-11-08 17:15:02 +04:00
if nic is False :
2009-11-20 21:12:24 +03:00
return False
2015-09-14 23:05:58 +03:00
_remove_vmm_device ( self . _guest , " interface " )
2011-04-08 01:11:10 +04:00
if nic :
2015-09-14 23:05:58 +03:00
_mark_vmm_device ( nic )
self . _guest . add_device ( nic )
2010-01-25 18:04:31 +03:00
2009-03-09 23:16:45 +03:00
return True
2015-09-12 20:03:51 +03:00
#############################
# Distro detection handling #
#############################
2015-09-12 22:14:40 +03:00
def _start_detect_os_if_needed ( self ,
forward_after_finish = False , check_install_page = True ) :
"""
Will kick off the OS detection thread if all conditions are met ,
like we actually have media to detect , detection isn ' t already
in progress , etc .
Returns True if we actually start the detection process
"""
is_install_page = ( self . widget ( " create-pages " ) . get_current_page ( ) ==
PAGE_INSTALL )
media = self . _get_config_detectable_media ( )
if self . _detect_os_in_progress :
return
if check_install_page and not is_install_page :
return
if not media :
return
if not self . _is_os_detect_active ( ) :
return
if self . _os_already_detected_for_media :
2015-09-12 20:03:51 +03:00
return
2015-09-12 22:14:40 +03:00
self . _do_start_detect_os ( media , forward_after_finish )
return True
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
def _do_start_detect_os ( self , media , forward_after_finish ) :
self . _detect_os_in_progress = False
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
logging . debug ( " Starting OS detection thread for media= %s " , media )
self . widget ( " create-forward " ) . set_sensitive ( False )
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
class ThreadResults ( object ) :
"""
Helper object to track results from the detection thread
"""
_DETECT_FAILED = 1
_DETECT_INPROGRESS = 2
def __init__ ( self ) :
self . _results = self . _DETECT_INPROGRESS
def in_progress ( self ) :
return self . _results == self . _DETECT_INPROGRESS
def set_failed ( self ) :
self . _results = self . _DETECT_FAILED
def set_distro ( self , distro ) :
self . _results = distro
def get_distro ( self ) :
if self . _results == self . _DETECT_FAILED :
return None
return self . _results
thread_results = ThreadResults ( )
detectThread = threading . Thread ( target = self . _detect_thread_cb ,
name = " Actual media detection " ,
args = ( media , thread_results ) )
detectThread . setDaemon ( True )
detectThread . start ( )
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
self . _report_detect_os_progress ( 0 , thread_results ,
forward_after_finish )
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
def _detect_thread_cb ( self , media , thread_results ) :
"""
Thread callback that does the actual detection
"""
try :
installer = virtinst . DistroInstaller ( self . conn . get_backend ( ) )
installer . location = media
2015-09-12 20:03:51 +03:00
2015-09-13 19:45:35 +03:00
distro = installer . detect_distro ( self . _guest )
2015-09-12 22:14:40 +03:00
thread_results . set_distro ( distro )
except :
logging . exception ( " Error detecting distro. " )
thread_results . set_failed ( )
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
def _report_detect_os_progress ( self , idx , thread_results ,
forward_after_finish ) :
"""
Checks detection progress via the _detect_os_results variable
and updates the UI labels , counts the number of iterations ,
etc .
We set a hard time limit on the distro detection to avoid the
chance of the detection hanging ( like slow URL lookup )
"""
2015-09-12 20:03:51 +03:00
try :
base = _ ( " Detecting " )
2015-09-12 22:14:40 +03:00
if ( thread_results . in_progress ( ) and
2015-09-12 20:03:51 +03:00
( idx < ( DETECT_TIMEOUT * 2 ) ) ) :
2015-09-12 22:14:40 +03:00
# Thread is still going and we haven't hit the timeout yet,
# so update the UI labels and reschedule this function
2015-09-12 20:03:51 +03:00
detect_str = base + ( " . " * ( ( idx % 3 ) + 1 ) )
self . _set_distro_labels ( detect_str , detect_str )
2015-09-12 22:14:40 +03:00
self . timeout_add ( 500 , self . _report_detect_os_progress ,
idx + 1 , thread_results , forward_after_finish )
2015-09-12 20:03:51 +03:00
return
2015-09-12 22:14:40 +03:00
distro = thread_results . get_distro ( )
2015-09-12 20:03:51 +03:00
except :
2015-09-12 22:14:40 +03:00
distro = None
2015-09-12 20:03:51 +03:00
logging . exception ( " Error in distro detect timeout " )
2015-09-12 22:14:40 +03:00
logging . debug ( " Finished UI OS detection. " )
2015-09-12 20:03:51 +03:00
self . widget ( " create-forward " ) . set_sensitive ( True )
2015-09-12 22:14:40 +03:00
self . _os_already_detected_for_media = True
self . _detect_os_in_progress = False
self . _set_distro_selection ( distro )
2015-09-12 20:03:51 +03:00
2015-09-12 22:14:40 +03:00
if forward_after_finish :
self . idle_add ( self . _forward_clicked , ( ) )
2015-09-12 20:03:51 +03:00
##########################
# Guest install routines #
##########################
2015-11-22 03:25:02 +03:00
def _set_finish_cursor ( self , topwin ) :
topwin . set_sensitive ( False )
topwin . get_window ( ) . set_cursor (
Gdk . Cursor . new ( Gdk . CursorType . WATCH ) )
def _undo_finish_cursor ( self , topwin ) :
topwin . set_sensitive ( True )
if not topwin . get_window ( ) :
return
topwin . get_window ( ) . set_cursor (
Gdk . Cursor . new ( Gdk . CursorType . TOP_LEFT_ARROW ) )
2013-09-07 04:59:01 +04:00
2015-09-12 20:03:51 +03:00
def _finish_clicked ( self , src_ignore ) :
2010-02-06 01:58:26 +03:00
# Validate the final page
2011-07-14 21:13:13 +04:00
page = self . widget ( " create-pages " ) . get_current_page ( )
2015-09-12 20:03:51 +03:00
if self . _validate ( page ) is not True :
2008-09-02 20:09:39 +04:00
return False
2014-03-20 22:02:25 +04:00
logging . debug ( " Starting create finish() sequence " )
2015-09-13 19:45:35 +03:00
guest = self . _guest
2009-03-09 23:16:45 +03:00
# Start the install
2015-09-13 19:45:35 +03:00
self . _failed_guest = None
2015-11-22 03:25:02 +03:00
self . _set_finish_cursor ( self . topwin )
2007-01-11 00:11:57 +03:00
2015-11-22 03:25:02 +03:00
if not self . widget ( " summary-customize " ) . get_active ( ) :
2015-09-12 20:03:51 +03:00
self . _start_install ( guest )
2015-11-22 03:25:02 +03:00
return
logging . debug ( " User requested ' customize ' , launching dialog " )
try :
self . _show_customize_dialog ( guest )
except Exception , e :
self . _undo_finish_cursor ( self . topwin )
self . err . show_err ( _ ( " Error starting installation: " ) + str ( e ) )
return
def _cleanup_customize_window ( self ) :
if not self . _customize_window :
return
# We can re-enter this: cleanup() -> close() -> "details-closed"
window = self . _customize_window
self . _customize_window = None
window . cleanup ( )
2010-02-07 20:18:28 +03:00
2015-09-12 20:03:51 +03:00
def _show_customize_dialog ( self , guest ) :
2015-09-13 19:45:35 +03:00
virtinst_guest = vmmDomainVirtinst ( self . conn , guest , self . _guest . uuid )
2010-02-07 20:18:28 +03:00
def start_install_wrapper ( ignore , guest ) :
2010-12-07 22:20:11 +03:00
if not self . is_visible ( ) :
return
2014-03-20 22:02:25 +04:00
logging . debug ( " User finished customize dialog, starting install " )
2015-11-22 03:25:02 +03:00
guest . update_defaults ( )
2015-09-12 20:03:51 +03:00
self . _start_install ( guest )
2010-12-07 22:20:11 +03:00
2015-05-03 23:53:43 +03:00
def config_canceled ( ignore ) :
logging . debug ( " User closed customize window, closing wizard " )
2015-09-06 21:42:55 +03:00
self . _close_requested ( )
2010-02-07 20:18:28 +03:00
2015-11-22 03:25:02 +03:00
self . _cleanup_customize_window ( )
2015-09-12 20:03:51 +03:00
self . _customize_window = vmmDetails ( virtinst_guest , self . topwin )
2015-11-22 03:25:02 +03:00
self . _customize_window . connect (
" customize-finished " , start_install_wrapper , guest )
self . _customize_window . connect ( " details-closed " , config_canceled )
2015-09-12 20:03:51 +03:00
self . _customize_window . show ( )
2010-02-07 20:18:28 +03:00
2015-11-22 03:25:02 +03:00
def _install_finished_cb ( self , error , details , parentobj ) :
self . _undo_finish_cursor ( parentobj . topwin )
2009-04-03 22:15:15 +04:00
if error :
2010-12-10 17:57:42 +03:00
error = ( _ ( " Unable to complete install: ' %s ' " ) % error )
2015-11-22 03:25:02 +03:00
parentobj . err . show_err ( error , details = details )
2015-09-13 19:45:35 +03:00
self . _failed_guest = self . _guest
2009-04-03 22:15:15 +04:00
return
2015-09-06 21:42:55 +03:00
self . _close ( )
2011-04-15 22:43:52 +04:00
# Launch details dialog for new VM
2015-09-13 19:45:35 +03:00
self . emit ( " action-show-domain " , self . conn . get_uri ( ) , self . _guest . name )
2013-09-07 04:59:01 +04:00
2015-09-12 20:03:51 +03:00
def _start_install ( self , guest ) :
"""
Launch the async job to start the install
"""
2015-11-22 03:25:02 +03:00
parentobj = self . _customize_window or self
2015-09-12 20:03:51 +03:00
progWin = vmmAsyncJob ( self . _do_async_install , [ guest ] ,
2015-11-22 03:25:02 +03:00
self . _install_finished_cb , [ parentobj ] ,
2013-09-07 04:59:01 +04:00
_ ( " Creating Virtual Machine " ) ,
_ ( " The virtual machine is now being "
" created. Allocation of disk storage "
" and retrieval of the installation "
" images may take a few minutes to "
" complete. " ) ,
2015-11-22 03:25:02 +03:00
parentobj . topwin )
2013-09-07 04:59:01 +04:00
progWin . run ( )
2009-03-09 23:16:45 +03:00
2015-09-12 20:03:51 +03:00
def _do_async_install ( self , asyncjob , guest ) :
"""
Kick off the actual install
"""
2012-02-10 19:24:43 +04:00
meter = asyncjob . get_meter ( )
2008-08-18 20:02:49 +04:00
2015-03-27 02:08:04 +03:00
# Build a list of pools we should refresh, if we are creating storage
refresh_pools = [ ]
for disk in guest . get_devices ( " disk " ) :
if not disk . wants_storage_creation ( ) :
continue
pool = disk . get_parent_pool ( )
if not pool :
continue
poolname = pool . name ( )
if poolname not in refresh_pools :
refresh_pools . append ( poolname )
2010-12-10 17:57:42 +03:00
logging . debug ( " Starting background install process " )
2013-08-09 19:25:05 +04:00
guest . start_install ( meter = meter )
2010-12-10 17:57:42 +03:00
logging . debug ( " Install completed " )
2010-03-01 03:40:06 +03:00
2013-07-07 04:03:42 +04:00
# Wait for VM to show up
2013-07-07 19:06:15 +04:00
self . conn . schedule_priority_tick ( pollvm = True )
2013-07-07 04:03:42 +04:00
count = 0
2014-06-03 01:17:47 +04:00
foundvm = None
while count < 100 :
for vm in self . conn . list_vms ( ) :
if vm . get_uuid ( ) == guest . uuid :
foundvm = vm
if foundvm :
break
2013-07-07 04:03:42 +04:00
count + = 1
time . sleep ( .1 )
2014-06-03 01:17:47 +04:00
if not foundvm :
raise RuntimeError (
_ ( " VM ' %s ' didn ' t show up after expected time. " ) % guest . name )
vm = foundvm
2007-04-11 02:50:04 +04:00
2010-12-10 17:57:42 +03:00
if vm . is_shutoff ( ) :
# Domain is already shutdown, but no error was raised.
# Probably means guest had no 'install' phase, as in
# for live cds. Try to restart the domain.
vm . startup ( )
2012-02-14 00:47:06 +04:00
elif guest . installer . has_install_phase ( ) :
2010-12-10 17:57:42 +03:00
# Register a status listener, which will restart the
# guest after the install has finished
2012-02-13 23:55:59 +04:00
def cb ( ) :
2015-04-10 01:02:42 +03:00
vm . connect_opt_out ( " state-changed " ,
2015-09-12 20:03:51 +03:00
self . _check_install_status , guest )
2012-02-13 23:55:59 +04:00
return False
self . idle_add ( cb )
2007-04-11 02:50:04 +04:00
2015-03-27 02:08:04 +03:00
# Kick off pool updates
for poolname in refresh_pools :
try :
pool = self . conn . get_pool ( poolname )
self . idle_add ( pool . refresh )
except :
logging . debug ( " Error looking up pool= %s for refresh after "
" VM creation. " , poolname , exc_info = True )
2007-06-22 21:32:13 +04:00
2015-09-12 20:03:51 +03:00
def _check_install_status ( self , vm , virtinst_guest ) :
"""
Watch the domain that we are installing , waiting for the state
to change , so we can restart it as needed
"""
2010-03-01 03:40:06 +03:00
if vm . is_crashed ( ) :
logging . debug ( " VM crashed, cancelling install plans. " )
return True
if not vm . is_shutoff ( ) :
return
try :
if virtinst_guest :
continue_inst = virtinst_guest . get_continue_inst ( )
if continue_inst :
logging . debug ( " VM needs a 2 stage install, continuing. " )
# Continue the install, then reconnect this opt
# out handler, removing the virtinst_guest which
# will force one final restart.
virtinst_guest . continue_install ( )
2010-05-13 19:21:01 +04:00
2015-04-10 01:02:42 +03:00
vm . connect_opt_out ( " state-changed " ,
2015-09-12 20:03:51 +03:00
self . _check_install_status , None )
2010-03-01 03:40:06 +03:00
return True
2010-05-13 19:21:01 +04:00
if vm . get_install_abort ( ) :
logging . debug ( " User manually shutdown VM, not restarting "
" guest after install. " )
return True
2010-03-01 03:40:06 +03:00
logging . debug ( " Install should be completed, starting VM. " )
vm . startup ( )
except Exception , e :
2011-04-06 19:22:03 +04:00
self . err . show_err ( _ ( " Error continue install: %s " ) % str ( e ) )
2010-03-01 03:40:06 +03:00
return True