32
32
from virtinst import VirtualNetworkInterface
34
import virtManager.opticalhelper
34
35
from virtManager import util
35
36
from virtManager.error import vmmErrorDialog
36
37
from virtManager.asyncjob import vmmAsyncJob
37
38
from virtManager.createmeter import vmmCreateMeter
38
from virtManager.opticalhelper import vmmOpticalDriveHelper
39
39
from virtManager.storagebrowse import vmmStorageBrowser
41
41
OS_GENERIC = "generic"
90
90
self.detectedDistro = None
91
91
self.detectThreadLock = threading.Lock()
94
self.install_error = None
95
self.install_details = None
93
# 'Guest' class from the previous failed install
94
self.failed_guest = None
97
96
self.window.signal_autoconnect({
98
97
"on_vmm_newcreate_delete_event" : self.close,
107
106
"on_create_conn_changed": self.conn_changed,
109
"on_install_url_entry_activate": self.detect_media_os,
110
108
"on_install_url_box_changed": self.url_box_changed,
111
109
"on_install_local_cdrom_toggled": self.local_cdrom_toggled,
112
110
"on_install_local_cdrom_combo_changed": self.detect_media_os,
113
"on_install_local_entry_activate": self.detect_media_os,
111
"on_install_local_box_changed": self.detect_media_os,
114
112
"on_install_local_browse_clicked": self.browse_iso,
116
114
"on_install_detect_os_toggled": self.toggle_detect_os,
172
170
box = self.window.get_widget("create-vm-icon-box")
173
iconfile = self.config.get_icon_dir() + "/virt-manager-icon.svg"
174
icon_pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(iconfile, 48, 48)
176
image.set_from_pixbuf(icon_pixbuf)
171
image = gtk.image_new_from_icon_name("vm_new_wizard",
172
gtk.ICON_SIZE_DIALOG)
178
174
box.pack_end(image, False)
185
181
conn_list.pack_start(text, True)
186
182
conn_list.add_attribute(text, 'text', 1)
185
iso_list = self.window.get_widget("install-local-box")
186
iso_model = gtk.ListStore(str)
187
iso_list.set_model(iso_model)
188
iso_list.set_text_column(0)
189
self.window.get_widget("install-local-box").child.connect("activate", self.detect_media_os)
188
191
# Lists for the install urls
189
192
media_url_list = self.window.get_widget("install-url-box")
190
193
media_url_model = gtk.ListStore(str)
191
194
media_url_list.set_model(media_url_model)
192
195
media_url_list.set_text_column(0)
196
self.window.get_widget("install-url-box").child.connect("activate", self.detect_media_os)
194
198
ks_url_list = self.window.get_widget("install-ks-box")
195
199
ks_url_model = gtk.ListStore(str)
214
218
# Physical CD-ROM model
215
219
cd_list = self.window.get_widget("install-local-cdrom-combo")
216
220
cd_radio = self.window.get_widget("install-local-cdrom")
217
# Fields are raw device path, volume label, flag indicating
218
# whether volume is present or not, and HAL path
219
cd_model = gtk.ListStore(str, str, bool, str)
220
cd_list.set_model(cd_model)
221
text = gtk.CellRendererText()
222
cd_list.pack_start(text, True)
223
cd_list.add_attribute(text, 'text', 1)
224
cd_list.add_attribute(text, 'sensitive', 2)
225
222
# FIXME: We should disable all this if on a remote connection
227
vmmOpticalDriveHelper(cd_list)
224
virtManager.opticalhelper.init_optical_combo(cd_list)
228
225
except Exception, e:
229
226
logging.error("Unable to create optical-helper widget: '%s'", e)
230
227
cd_radio.set_sensitive(False)
268
265
def reset_state(self, urihint=None):
267
self.failed_guest = None
270
268
self.window.get_widget("create-pages").set_current_page(PAGE_NAME)
271
269
self.page_changed(None, None, PAGE_NAME)
287
285
self.window.get_widget("install-os-type").set_active(0)
289
287
# Install local/iso
290
self.window.get_widget("install-local-entry").set_text("")
288
self.window.get_widget("install-local-box").child.set_text("")
289
iso_model = self.window.get_widget("install-local-box").get_model()
290
self.populate_media_model(iso_model, self.conn.config_get_iso_paths())
293
293
self.window.get_widget("install-urlopts-entry").set_text("")
294
self.window.get_widget("install-ks-entry").set_text("")
295
self.window.get_widget("install-url-entry").set_text("")
294
self.window.get_widget("install-ks-box").child.set_text("")
295
self.window.get_widget("install-url-box").child.set_text("")
296
296
urlmodel = self.window.get_widget("install-url-box").get_model()
297
297
ksmodel = self.window.get_widget("install-ks-box").get_model()
298
self.populate_url_model(urlmodel, self.config.get_media_urls())
299
self.populate_url_model(ksmodel, self.config.get_kickstart_urls())
298
self.populate_media_model(urlmodel, self.config.get_media_urls())
299
self.populate_media_model(ksmodel, self.config.get_kickstart_urls())
302
302
self.window.get_widget("config-mem").set_value(512)
478
478
gtype = guest.os_type
479
479
for dom in guest.domains:
480
480
domtype = dom.hypervisor_type
486
elif domtype == "xen":
488
label = "xen (paravirt)"
490
label = "xen (fullvirt)"
491
elif domtype == "test":
481
label = util.pretty_hv(gtype, domtype)
497
483
# Don't add multiple rows for each arch
559
545
# Favor local connections over remote connections
560
546
default = len(model)
562
model.append([connobj.get_uri(), connobj.get_pretty_desc()])
548
model.append([connobj.get_uri(), connobj.get_pretty_desc_active()])
564
550
no_conns = (len(model) == 0)
604
590
model.append([variant,
605
591
virtinst.FullVirtGuest.get_os_variant_label(_type,
607
def populate_url_model(self, model, urls):
593
def populate_media_model(self, model, urls):
610
596
model.append([url])
690
676
net_list.set_active(default)
692
def change_caps(self, gtype=None, dtype=None):
678
def change_caps(self, gtype=None, dtype=None, arch=None):
681
# If none specified, prefer HVM. This way, the default install
682
# options won't be limited because we default to PV. If hvm not
683
# supported, differ to guest_lookup
684
for g in self.caps.guests:
685
if g.os_type == "hvm":
694
690
newdom) = virtinst.CapabilitiesParser.guest_lookup(conn=self.conn.vmm,
700
697
if (self.capsguest and self.capsdomain and
701
698
(newg.arch == self.capsguest.arch and
780
777
return (distro, variant, dlabel, vlabel)
782
def get_config_local_media(self):
779
def get_config_local_media(self, store_media=False):
783
780
if self.window.get_widget("install-local-cdrom").get_active():
784
781
return self.window.get_widget("install-local-cdrom-combo").get_active_text()
786
return self.window.get_widget("install-local-entry").get_text()
783
ret = self.window.get_widget("install-local-box").child.get_text()
784
if ret and store_media:
785
self.conn.config_add_iso_path(ret)
788
788
def get_config_detectable_media(self):
789
789
instpage = self.get_config_install_page()
792
792
if instpage == INSTALL_PAGE_ISO:
793
793
media = self.get_config_local_media()
794
794
elif instpage == INSTALL_PAGE_URL:
795
media = self.window.get_widget("install-url-entry").get_text()
795
media = self.window.get_widget("install-url-box").get_active_text()
799
def get_config_url_info(self):
800
media = self.window.get_widget("install-url-entry").get_text().strip()
799
def get_config_url_info(self, store_media=False):
800
media = self.window.get_widget("install-url-box").get_active_text().strip()
801
801
extra = self.window.get_widget("install-urlopts-entry").get_text().strip()
802
ks = self.window.get_widget("install-ks-entry").get_text().strip()
802
ks = self.window.get_widget("install-ks-box").get_active_text().strip()
804
if media and store_media:
805
805
self.config.add_media_url(media)
806
if ks and store_media:
807
807
self.config.add_kickstart_url(ks)
809
809
return (media.strip(), extra.strip(), ks.strip())
811
811
def get_storage_info(self):
813
813
size = self.window.get_widget("config-storage-size").get_value()
814
nosparse = self.window.get_widget("config-storage-nosparse").get_active()
814
sparse = not self.window.get_widget("config-storage-nosparse").get_active()
815
815
if self.window.get_widget("config-storage-create").get_active():
816
816
path = self.get_default_path(self.guest.name)
817
817
logging.debug("Default storage path is: %s" % path)
819
819
path = self.window.get_widget("config-storage-entry").get_text()
821
return (path, size, nosparse)
821
return (path, size, sparse)
823
823
def get_default_path(self, name):
826
826
# Don't generate a new path if the install failed
827
if self.install_error:
828
if self.guest and len(self.guest.disks) > 0:
829
return self.guest.disks[0].path
827
if self.failed_guest:
828
if len(self.failed_guest.disks) > 0:
829
return self.failed_guest.disks[0].path
831
831
if not self.usepool:
919
arch = src.get_model()[idx][0]
920
self.change_caps(self.capsguest.os_type,
921
self.capsdomain.hypervisor_type,
919
924
def url_box_changed(self, ignore):
920
925
# If the url_entry has focus, don't fire detect_media_os, it means
921
926
# the user is probably typing
922
if self.window.get_widget("install-url-entry").flags() & gtk.HAS_FOCUS:
927
if self.window.get_widget("install-url-box").child.flags() & gtk.HAS_FOCUS:
924
929
self.detect_media_os()
965
970
def toggle_local_iso(self, src):
966
971
uselocal = src.get_active()
967
self.window.get_widget("install-local-entry").set_sensitive(uselocal)
972
self.window.get_widget("install-local-box").set_sensitive(uselocal)
968
973
self.window.get_widget("install-local-browse").set_sensitive(uselocal)
970
975
def detect_visibility_changed(self, src, ignore=None):
981
986
nodetect_label.show()
983
988
def browse_iso(self, ignore1=None, ignore2=None):
984
f = self._browse_file(_("Locate ISO Image"), is_media=True)
986
self.window.get_widget("install-local-entry").set_text(f)
987
self.window.get_widget("install-local-entry").activate()
989
self._browse_file(_("Locate ISO Image"),
990
self.set_iso_storage_path,
992
self.window.get_widget("install-local-box").activate()
989
994
def toggle_enable_storage(self, src):
990
995
self.window.get_widget("config-storage-box").set_sensitive(src.get_active())
992
997
def browse_storage(self, ignore1):
993
f = self._browse_file(_("Locate existing storage"))
995
self.window.get_widget("config-storage-entry").set_text(f)
998
self._browse_file(_("Locate existing storage"),
999
self.set_disk_storage_path,
997
1002
def toggle_storage_select(self, src):
998
1003
act = src.get_active()
1001
1006
def toggle_macaddr(self, src):
1002
1007
self.window.get_widget("config-macaddr").set_sensitive(src.get_active())
1004
def set_storage_path(self, src, path):
1005
notebook = self.window.get_widget("create-pages")
1006
curpage = notebook.get_current_page()
1007
if curpage == PAGE_INSTALL:
1008
self.window.get_widget("install-local-entry").set_text(path)
1009
elif curpage == PAGE_STORAGE:
1010
self.window.get_widget("config-storage-entry").set_text(path)
1009
def set_iso_storage_path(self, ignore, path):
1010
self.window.get_widget("install-local-box").child.set_text(path)
1012
def set_disk_storage_path(self, ignore, path):
1013
self.window.get_widget("config-storage-entry").set_text(path)
1012
1015
# Navigation methods
1013
1016
def set_install_page(self):
1215
1218
except ValueError, e:
1216
1219
return self.err.val_err(_("Error setting OS information."),
1222
# Validation passed, store the install path (if there is one) in
1224
self.get_config_local_media(store_media=True)
1225
self.get_config_url_info(store_media=True)
1220
1228
def validate_mem_page(self):
1257
1265
size = disksize,
1258
1266
sparse = sparse)
1260
if (disk.type == virtinst.VirtualDisk.TYPE_FILE and
1261
self.guest.type == "xen" and
1262
virtinst.util.is_blktap_capable()):
1263
disk.driver_name = virtinst.VirtualDisk.DRIVER_TAP
1265
1268
self.guest.disks.append(disk)
1266
1269
except Exception, e:
1267
1270
return self.verr(_("Storage parameter error."), str(e))
1412
1415
"".join(traceback.format_exc()))
1416
1418
logging.debug("Creating a VM %s" % guest.name +
1417
1419
"\n Type: %s,%s" % (guest.type,
1418
1420
guest.installer.os_type) +
1440
1442
"images may take a few minutes to "
1445
error, details = progWin.get_error()
1444
if self.install_error != None:
1445
self.err.show_err(self.install_error, self.install_details)
1446
self.topwin.set_sensitive(True)
1447
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW))
1448
# Don't close becase we allow user to go back in wizard & correct
1448
self.err.show_err(error, details)
1452
1450
self.topwin.set_sensitive(True)
1453
1451
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW))
1454
self.failed_guest = self.guest
1454
1457
# Ensure new VM is loaded
1455
1458
# FIXME: Hmm, shouldn't we emit a signal here rather than do this?
1456
1459
self.conn.tick(noStatsUpdate=True)
1485
1489
dom = guest.start_install(False, meter = meter)
1486
1490
if dom == None:
1487
self.install_error = _("Guest installation failed to complete")
1488
self.install_details = self.install_error
1491
error = _("Guest installation failed to complete")
1489
1493
logging.error("Guest install did not return a domain")
1491
1495
logging.debug("Install completed")
1496
1500
details = ("Unable to complete install '%s'" %
1497
1501
(str(_type) + " " + str(value) + "\n" +
1498
1502
traceback.format_exc (stacktrace)))
1500
self.install_error = (_("Unable to complete install: '%s'") %
1502
self.install_details = details
1503
logging.error(details)
1503
error = (_("Unable to complete install: '%s'") % str(value))
1506
asyncjob.set_error(error, details)
1506
1508
def pretty_storage(self, size):
1507
1509
return "%.1f Gb" % float(size)
1623
1625
self._safe_wrapper(self.set_distro_selection, results)
1625
self.detectDistro = None
1626
1627
self._clear_detect_thread()
1627
1628
self._safe_wrapper(self._set_forward_sensitive, (True,))
1628
1629
logging.debug("Leaving OS detection thread.")
1639
1640
logging.exception("Error detecting distro.")
1640
1641
self.detectedDistro = (None, None)
1642
def _browse_file(self, dialog_name, folder=None, is_media=False):
1644
if self.conn.is_remote() or not is_media:
1645
if self.storage_browser == None:
1646
self.storage_browser = vmmStorageBrowser(self.config,
1648
self.storage_browser.connect("storage-browse-finish",
1649
self.set_storage_path)
1650
self.storage_browser.local_args = { "dialog_name": dialog_name,
1651
"start_folder": folder}
1652
self.storage_browser.show(self.conn)
1655
return util.browse_local(self.topwin, dialog_name, folder)
1643
def _browse_file(self, dialog_name, callback, folder=None, is_media=False):
1644
if self.storage_browser == None:
1645
self.storage_browser = vmmStorageBrowser(self.config, self.conn,
1647
self.storage_browser.connect("storage-browse-finish",
1650
reason = self.config.CONFIG_DIR_MEDIA
1652
reason = self.config.CONFIG_DIR_IMAGE
1654
self.storage_browser.local_args = { "dialog_name": dialog_name,
1655
"start_folder": folder,
1656
"browse_reason": reason}
1657
self.storage_browser.show(self.conn)
1657
1659
def show_help(self, ignore):
1658
1660
# No help available yet.