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 ,
2017-03-13 15:01:51 +03:00
INSTALL_PAGE_CONTAINER_OS ,
INSTALL_PAGE_VZ_TEMPLATE ) = range ( 7 )
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 ) :
2016-07-26 10:32:14 +03:00
return _ ( " %.1f GiB " ) % float ( size )
2015-09-12 20:03:51 +03:00
def _pretty_memory ( mem ) :
2016-07-26 10:32:14 +03:00
return _ ( " %d MiB " ) % ( mem / 1024.0 )
2015-09-12 20:03:51 +03:00
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 ] ) ,
2016-05-20 16:27:17 +03:00
" create-opened " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" create-closed " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
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 ,
2017-03-13 15:01:51 +03:00
" on_vz_virt_type_changed " : self . _vz_virt_type_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 )
2016-05-20 16:27:17 +03:00
self . emit ( " create-opened " )
2012-02-14 01:19:34 +04:00
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 " )
2016-05-20 16:27:17 +03:00
self . emit ( " create-closed " )
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 )
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
return Gtk . TreeStore ( * cols )
def make_completion_model ( ) :
# [os value, os label]
cols = [ ]
cols . insert ( OS_COL_ID , str )
cols . insert ( OS_COL_LABEL , str )
2015-09-12 22:14:40 +03:00
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 )
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
completion . set_model ( make_completion_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
2017-04-27 22:00:17 +03:00
self . reset_finish_cursor ( )
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 )
2017-03-13 15:01:51 +03:00
self . widget ( " vz-virt-type-hvm " ) . set_active ( True )
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
2017-03-13 15:01:51 +03:00
# Install VZ container from template
self . widget ( " install-container-template " ) . set_text ( " centos-7-x86_64 " )
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 ( )
2017-03-13 15:01:51 +03:00
is_vz = self . conn . is_vz ( )
2017-03-22 18:31:53 +03:00
is_vz_container = ( is_vz and self . _capsinfo . os_type == " exe " )
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
2017-06-28 22:17:20 +03:00
[ " i686 " , " x86_64 " , " ppc64 " , " ppc64le " , " 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. " )
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-02-22 18:01:02 +03:00
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 ( " container-install-box " ) . set_visible ( is_container )
2017-03-13 15:01:51 +03:00
self . widget ( " vz-install-box " ) . set_visible ( is_vz )
2017-03-22 18:31:53 +03:00
self . widget ( " virt-install-box " ) . set_visible (
not is_container and not is_vz_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
2017-03-13 15:01:51 +03:00
elif self . conn . is_vz ( ) :
has_hvm_guests = False
has_exe_guests = False
for g in self . conn . caps . guests :
if g . os_type == " hvm " :
has_hvm_guests = True
if g . os_type == " exe " :
has_exe_guests = True
self . widget ( " vz-virt-type-hvm " ) . set_sensitive ( has_hvm_guests )
self . widget ( " vz-virt-type-exe " ) . set_sensitive ( has_exe_guests )
2017-03-22 18:31:53 +03:00
self . widget ( " vz-virt-type-hvm " ) . set_active ( has_hvm_guests )
self . widget ( " vz-virt-type-exe " ) . set_active (
not has_hvm_guests and has_exe_guests )
2017-03-13 15:01:51 +03: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 ( )
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-11-02 22:08:09 +03:00
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 = [ ]
2017-06-27 21:13:36 +03:00
if self . conn . is_xen ( ) or self . conn . is_test ( ) :
2015-09-15 01:31:56 +03:00
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 #
#############################################
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
def _add_os_row ( self , model , name = " " , label = " " ,
sep = False , action = False , parent = None ) :
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
"""
2011-07-26 02:53:09 +04:00
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
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
return model . append ( parent , row )
def _add_completion_row ( self , model , name , label ) :
row = [ ]
row . insert ( OS_COL_ID , name )
row . insert ( OS_COL_LABEL , label )
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
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
supported = { " 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
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
# Pretty names for OSes. If a new OS is not found here,
# its capitalized name is used.
oses = {
2017-04-24 17:20:42 +03:00
" bsd " : _ ( " BSD " ) ,
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
" generic " : _ ( " Generic " ) ,
" linux " : _ ( " Linux " ) ,
2017-04-24 17:20:43 +03:00
" macos " : _ ( " macOS " ) ,
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
" other " : _ ( " Others " ) ,
" solaris " : _ ( " Solaris " ) ,
" windows " : _ ( " Windows " ) ,
}
# When only the "supported" types are requested,
# filter them.
if not self . _show_all_os_was_selected :
types = [ t for t in types if t in supported ]
2015-04-04 19:37:46 +03:00
for typename in types :
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
try :
typelabel = oses [ typename ]
except KeyError :
typelabel = typename . capitalize ( )
2015-04-04 19:37:46 +03:00
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
self . _add_os_row ( model , typename , typelabel )
2011-07-26 02:53:09 +04:00
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
if not self . _show_all_os_was_selected :
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 ( )
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
completion_model = self . widget ( " install-os-version-entry " ) . get_completion ( ) . get_model ( )
completion_model . clear ( )
2011-07-26 02:53:09 +04:00
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
preferred = self . config . preferred_distros
2011-07-26 02:53:09 +04:00
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
# All the subgroups for top-level types. Distributions not
# belonging to these groups will be shown either in a "Others"
# group, or top-level if there are no other groups.
groups = {
" altlinux " : _ ( " ALT Linux " ) ,
" centos " : _ ( " CentOS " ) ,
" debian " : _ ( " Debian " ) ,
" fedora " : _ ( " Fedora " ) ,
" freebsd " : _ ( " FreeBSD " ) ,
" mageia " : _ ( " Mageia " ) ,
" netbsd " : _ ( " NetBSD " ) ,
" openbsd " : _ ( " OpenBSD " ) ,
" opensuse " : _ ( " openSUSE " ) ,
" rhel " : _ ( " Red Hat Enterprise Linux " ) ,
" sled " : _ ( " SUSE Linux Enterprise Desktop " ) ,
" sles " : _ ( " SUSE Linux Enterprise Server " ) ,
" ubuntu " : _ ( " Ubuntu " ) ,
}
if self . _show_all_os_was_selected :
# List all the OSes, and determine which OSes have groups,
# and which do not.
variants = virtinst . OSDB . list_os ( typename = _type ,
sortpref = preferred )
all_distros = set ( [ os . distro for os in variants ] )
distros = [ os for os in all_distros if os in groups ]
distros . sort ( )
other_distros = [ os for os in all_distros if os not in groups ]
parents = dict ( )
if len ( distros ) > 0 :
# We have groups for the OSes, so create them.
for d in distros :
parents [ d ] = self . _add_os_row ( model , " " , groups [ d ] )
# Create the "Others" group at the end, for the OSes
# without a group.
if len ( other_distros ) :
others_parent = self . _add_os_row ( model , " " , _ ( ' Others ' ) )
for d in other_distros :
parents [ d ] = others_parent
else :
# No groups, so assume the top-level will be the parent
# all the OSes.
for d in other_distros :
parents [ d ] = None
for v in variants :
self . _add_os_row ( model , v . name , v . label ,
parent = parents [ v . distro ] )
self . _add_completion_row ( completion_model , v . name , v . label )
else :
# We are showing only the supported systems, so query them,
# and add them directly to their type.
variants = virtinst . OSDB . list_os ( typename = _type ,
sortpref = preferred , only_supported = True )
for v in variants :
self . _add_os_row ( model , v . name , v . label )
self . _add_completion_row ( completion_model , v . name , v . label )
# Add the menu entries to show all the OSes
self . _add_os_row ( model , sep = True )
self . _add_os_row ( model , label = _ ( " Show all OS options " ) , action = True )
2011-07-26 02:53:09 +04:00
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 ( ) :
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
def cmp_func ( model , path , it , user_data ) :
ignore = path
if model . get_value ( it , OS_COL_ID ) == os_id :
os_widget . set_active_iter ( it )
user_data [ 0 ] = model . get_value ( it , OS_COL_LABEL )
return True
return False
data = [ None ]
model . foreach ( cmp_func , data )
label = data [ 0 ]
if not label :
os_widget . set_active ( 0 )
return label
2015-09-12 22:14:40 +03:00
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 " )
2017-03-13 15:01:51 +03:00
elif instmethod == INSTALL_PAGE_VZ_TEMPLATE :
install = _ ( " Virtuozzo 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 ) :
2017-03-13 15:01:51 +03:00
if self . widget ( " vz-install-box " ) . get_visible ( ) :
if self . widget ( " vz-virt-type-exe " ) . get_active ( ) :
return INSTALL_PAGE_VZ_TEMPLATE
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 ,
2017-03-13 15:01:51 +03:00
INSTALL_PAGE_CONTAINER_OS ,
INSTALL_PAGE_VZ_TEMPLATE ]
2015-09-12 20:03:51 +03:00
def _should_skip_disk_page ( self ) :
return self . _get_config_install_page ( ) in [ INSTALL_PAGE_IMPORT ,
INSTALL_PAGE_CONTAINER_APP ,
2017-03-13 15:01:51 +03:00
INSTALL_PAGE_CONTAINER_OS ,
INSTALL_PAGE_VZ_TEMPLATE ]
2015-09-12 20:03:51 +03:00
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 " ) )
2009-03-09 23:16:45 +03:00
distro = None
dlabel = None
variant = None
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
entry = self . widget ( " install-os-version-entry " )
vlabel = entry . get_text ( )
2014-04-24 18:58:11 +04:00
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
for row in entry . get_completion ( ) . get_model ( ) :
if row [ OS_COL_LABEL ] == vlabel :
2015-09-12 22:14:40 +03:00
variant = row [ OS_COL_ID ]
2014-04-24 18:58:11 +04:00
break
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
if not variant :
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 ]
2009-03-09 23:16:45 +03:00
2013-01-13 01:13:53 +04:00
return ( distro and str ( distro ) ,
create: refactor combobox with distros
When showing all the OSes, the list of distributions for some types of
OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll.
As solution, introduce groups for some of the OS families, leaving the
ones without a defined group into a "Others" group.
To keep the completion working in the editable combobox, add a separate
completion model for the completion entry, providing all the OSes
directly there as simple list.
There are a number of changes related to this:
- the model for the OS comboboxes is now a TreeStore, and the iterations
on the OS variant keep that into account
- there are better UI labels for OS types and groups
- when there are no groups for a type, add all the OSes directly, just
like now
- optimize the way types are added to the combobox: when not adding all
of them, filter out those not "supported"
- optimize the way OSes are added to the combobox: query only for the
list we need (supported or all, not both), and group them according
to the hash defined
- add separator + "show all" options only when not showing all of them
- _add_os_row now is called only when needed, so remove its "supported"
parameter
2017-04-24 17:20:41 +03:00
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 )
2017-05-17 14:53:38 +03:00
return ( media , extra )
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
2017-03-13 15:01:51 +03:00
def _vz_virt_type_changed ( self , ignore ) :
is_hvm = self . widget ( " vz-virt-type-hvm " ) . get_active ( )
if is_hvm :
self . _change_caps ( " hvm " )
else :
self . _change_caps ( " exe " )
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 ( )
2016-04-18 23:42:12 +03:00
for idx , row in enumerate ( os_type_model ) :
if row [ 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 ( )
2017-05-05 19:47:21 +03:00
except Exception as e :
2014-05-31 21:31:08 +04:00
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 )
2016-06-16 12:04:36 +03:00
# If no machine was selected don't clear recommended machine
machine = self . _get_config_machine ( )
if machine :
guest . os . machine = 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 )
2017-05-05 19:47:21 +03:00
except Exception as e :
2011-07-07 22:39:28 +04:00
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
2017-05-05 19:47:21 +03:00
except ValueError as 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 ( )
2017-05-05 19:47:21 +03:00
except Exception as 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 ( )
2017-05-05 19:47:21 +03:00
except Exception as e :
2009-03-09 23:16:45 +03:00
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
2017-03-13 15:01:51 +03:00
template = 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
2016-06-07 14:55:58 +03:00
if not virtinst . VirtualDisk . path_definitely_exists (
self . conn . get_backend ( ) ,
import_path ) :
return self . err . val_err ( _ ( " The import path must point to "
" an existing storage. " ) )
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
2017-03-13 15:01:51 +03:00
elif instmethod == INSTALL_PAGE_VZ_TEMPLATE :
instclass = virtinst . ContainerInstaller
template = self . widget ( " install-container-template " ) . get_text ( )
if not template :
return self . err . val_err ( _ ( " A template name is required. " ) )
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
2017-05-05 19:47:21 +03:00
except Exception as 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 )
2017-03-13 15:01:51 +03:00
if template :
fsdev = virtinst . VirtualFilesystem ( self . _guest . conn )
fsdev . target = " / "
fsdev . type = " template "
fsdev . source = template
self . _guest . add_device ( fsdev )
2017-05-05 19:47:21 +03:00
except Exception as 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
2017-05-05 19:47:21 +03:00
except Exception as e :
2013-10-01 23:18:34 +04:00
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 )
2017-05-05 19:47:21 +03:00
except Exception as 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
2017-05-05 19:47:21 +03:00
except Exception as 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 )
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-09-13 23:02:35 +03:00
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
2017-05-05 19:47:21 +03:00
except Exception as e :
2015-04-03 00:54:47 +03:00
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 #
##########################
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
2017-04-27 22:00:17 +03:00
self . set_finish_cursor ( )
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 )
2017-05-05 19:47:21 +03:00
except Exception as e :
2017-04-27 22:00:17 +03:00
self . reset_finish_cursor ( )
2015-11-22 03:25:02 +03:00
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 " )
2016-06-17 02:47:49 +03:00
self . _failed_guest = None
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 ) :
2017-04-27 22:00:17 +03:00
self . reset_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 " ,
virtinst: guest: drop 'continue_install' concept
continue_install is intended to facilitate windows XP style 3 stage
installs:
stage 1: initial dos style disk setup, reboot
stage 2: actual full installer, reboot
stage 3: OS is functional, virt-install is done
The code assumed that we needed to keep the cdrom as the primary
boot device for the second stage, so virt-install/virt-manager needed
to hang around through the second stage run, wait until the VM shutdown,
then encode the final XML to boot of the disk.
Windows is and always has been smart enough to handle that case though...
after the initial boot, if we set the hd as the primary boot device
for stage 2, the disk bits that windows already installed will make
use of the cdrom as necessary. So the entire premise of continue_install
is irrelevant. Maybe back when it was added, when xen didn't even have
working ACPI support, this served a purpose, but I'm pretty sure we
can safely drop it nowadays.
2016-06-16 23:13:54 +03:00
self . _check_install_status )
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
virtinst: guest: drop 'continue_install' concept
continue_install is intended to facilitate windows XP style 3 stage
installs:
stage 1: initial dos style disk setup, reboot
stage 2: actual full installer, reboot
stage 3: OS is functional, virt-install is done
The code assumed that we needed to keep the cdrom as the primary
boot device for the second stage, so virt-install/virt-manager needed
to hang around through the second stage run, wait until the VM shutdown,
then encode the final XML to boot of the disk.
Windows is and always has been smart enough to handle that case though...
after the initial boot, if we set the hd as the primary boot device
for stage 2, the disk bits that windows already installed will make
use of the cdrom as necessary. So the entire premise of continue_install
is irrelevant. Maybe back when it was added, when xen didn't even have
working ACPI support, this served a purpose, but I'm pretty sure we
can safely drop it nowadays.
2016-06-16 23:13:54 +03:00
def _check_install_status ( self , vm ) :
2015-09-12 20:03:51 +03:00
"""
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
2016-05-13 18:28:03 +03: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
try :
logging . debug ( " Install should be completed, starting VM. " )
vm . startup ( )
2017-05-05 19:47:21 +03:00
except Exception as 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