~ubuntu-branches/ubuntu/raring/virt-manager/raring-proposed

« back to all changes in this revision

Viewing changes to src/virtManager/create.py

  • Committer: Bazaar Package Importer
  • Author(s): Guido Günther, Laurent Léonard, Guido Günther
  • Date: 2009-10-07 14:04:03 UTC
  • mfrom: (2.3.1 experimental)
  • mto: (2.3.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20091007140403-kl9yum4ocrar1acq
Tags: 0.8.0-2
[ Laurent Léonard ]
* [61651ae] Drop ${shlibs:Depends} from dependencies since there is no more
  C code.
* [3319434] Drop redo-patches target from debian/rules. Since gbp-pq
  is used now.
* [b04541e] Clean debian/rules. Drop commented post-patches target
  since there is no more autogen.sh.
* [145ba60] Update french translation.
* [799f18e] Update 0001-use-usr-share-gconf-for-schema-data.patch.
* [052f7bb] Remove XS-Python-Version field from debian/control. Since
  it is deprecated with pysupport.
* [bfb1611][1a66b27][a8ce142][4116d07][31ff60a] Fix some misspellings in
  french translation.
* [6e23aff] Clean build dependencies.
* [b71c8c9] Bump Debhelper version to 7.
* [c614f09] Bump Standards-Version to 3.8.3.
* [99a52c2] Clean debian/rules.
* [52f3b63] Add clean target in debian/rules. To clean automatically
  generated files: - debian/pycompat (see #424898)
* [d5e2ef7] Remove tests/Makefile in the debian/rules clean target. To get a
  clean Debian diff at rebuild time, the file is automatically generated.
* [7da6d9b] Don't close connection on all libvirt errors. Pulled from
  upstream 1c886d1863f7.

[ Guido Günther ]
* upload to unstable
* [464fb65] make package arch all since there is no more C code.
* [25f7663] switch to python-support and use python-distutils
* [c4da06a] bump python-libvirt dependency so we get all of VMs new
  features.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
import virtinst
32
32
from virtinst import VirtualNetworkInterface
33
33
 
 
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
40
40
 
41
41
OS_GENERIC = "generic"
90
90
        self.detectedDistro = None
91
91
        self.detectThreadLock = threading.Lock()
92
92
 
93
 
        # Async install state
94
 
        self.install_error = None
95
 
        self.install_details = None
 
93
        # 'Guest' class from the previous failed install
 
94
        self.failed_guest = None
96
95
 
97
96
        self.window.signal_autoconnect({
98
97
            "on_vmm_newcreate_delete_event" : self.close,
106
105
 
107
106
            "on_create_conn_changed": self.conn_changed,
108
107
 
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,
115
113
 
116
114
            "on_install_detect_os_toggled": self.toggle_detect_os,
170
168
                                                          blue)
171
169
 
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)
175
 
        image = gtk.Image()
176
 
        image.set_from_pixbuf(icon_pixbuf)
 
171
        image = gtk.image_new_from_icon_name("vm_new_wizard",
 
172
                                             gtk.ICON_SIZE_DIALOG)
177
173
        image.show()
178
174
        box.pack_end(image, False)
179
175
 
185
181
        conn_list.pack_start(text, True)
186
182
        conn_list.add_attribute(text, 'text', 1)
187
183
 
 
184
        # ISO media list
 
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)
 
190
 
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)
193
197
 
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)
 
221
 
225
222
        # FIXME: We should disable all this if on a remote connection
226
223
        try:
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)
267
264
 
268
265
    def reset_state(self, urihint=None):
269
266
 
 
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)
272
270
 
287
285
        self.window.get_widget("install-os-type").set_active(0)
288
286
 
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())
291
291
 
292
292
        # Install URL
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())
300
300
 
301
301
        # Mem / CPUs
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
481
 
                label = domtype
482
 
 
483
 
                if domtype == "kvm":
484
 
                    if gtype == "xen":
485
 
                        label = "xenner"
486
 
                elif domtype == "xen":
487
 
                    if gtype == "xen":
488
 
                        label = "xen (paravirt)"
489
 
                    elif gtype == "hvm":
490
 
                        label = "xen (fullvirt)"
491
 
                elif domtype == "test":
492
 
                    if gtype == "xen":
493
 
                        label = "test (xen)"
494
 
                    elif gtype == "hvm":
495
 
                        label = "test (hvm)"
 
481
                label = util.pretty_hv(gtype, domtype)
496
482
 
497
483
                # Don't add multiple rows for each arch
498
484
                for m in model:
559
545
                # Favor local connections over remote connections
560
546
                default = len(model)
561
547
 
562
 
            model.append([connobj.get_uri(), connobj.get_pretty_desc()])
 
548
            model.append([connobj.get_uri(), connobj.get_pretty_desc_active()])
563
549
 
564
550
        no_conns = (len(model) == 0)
565
551
 
604
590
            model.append([variant,
605
591
                          virtinst.FullVirtGuest.get_os_variant_label(_type,
606
592
                                                                      variant)])
607
 
    def populate_url_model(self, model, urls):
 
593
    def populate_media_model(self, model, urls):
608
594
        model.clear()
609
595
        for url in urls:
610
596
            model.append([url])
689
675
 
690
676
        net_list.set_active(default)
691
677
 
692
 
    def change_caps(self, gtype=None, dtype=None):
 
678
    def change_caps(self, gtype=None, dtype=None, arch=None):
 
679
 
 
680
        if gtype == 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":
 
686
                    gtype = "hvm"
 
687
                    break
 
688
 
693
689
        (newg,
694
690
         newdom) = virtinst.CapabilitiesParser.guest_lookup(conn=self.conn.vmm,
695
691
                                                            caps=self.caps,
696
692
                                                            os_type = gtype,
697
693
                                                            type = dtype,
698
 
                                                            accelerated=True)
 
694
                                                            accelerated=True,
 
695
                                                            arch=arch)
699
696
 
700
697
        if (self.capsguest and self.capsdomain and
701
698
            (newg.arch == self.capsguest.arch and
779
776
 
780
777
        return (distro, variant, dlabel, vlabel)
781
778
 
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()
785
782
        else:
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)
 
786
            return ret
787
787
 
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()
796
796
 
797
797
        return media
798
798
 
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()
803
803
 
804
 
        if media:
 
804
        if media and store_media:
805
805
            self.config.add_media_url(media)
806
 
        if ks:
 
806
        if ks and store_media:
807
807
            self.config.add_kickstart_url(ks)
808
808
 
809
809
        return (media.strip(), extra.strip(), ks.strip())
811
811
    def get_storage_info(self):
812
812
        path = None
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)
818
818
        else:
819
819
            path = self.window.get_widget("config-storage-entry").get_text()
820
820
 
821
 
        return (path, size, nosparse)
 
821
        return (path, size, sparse)
822
822
 
823
823
    def get_default_path(self, name):
824
824
        path = ""
825
825
 
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
830
830
 
831
831
        if not self.usepool:
832
832
 
916
916
        if idx < 0:
917
917
            return
918
918
 
 
919
        arch = src.get_model()[idx][0]
 
920
        self.change_caps(self.capsguest.os_type,
 
921
                         self.capsdomain.hypervisor_type,
 
922
                         arch)
 
923
 
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:
923
928
            return
924
929
        self.detect_media_os()
925
930
 
964
969
 
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)
969
974
 
970
975
    def detect_visibility_changed(self, src, ignore=None):
981
986
            nodetect_label.show()
982
987
 
983
988
    def browse_iso(self, ignore1=None, ignore2=None):
984
 
        f = self._browse_file(_("Locate ISO Image"), is_media=True)
985
 
        if f != None:
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,
 
991
                          is_media=True)
 
992
        self.window.get_widget("install-local-box").activate()
988
993
 
989
994
    def toggle_enable_storage(self, src):
990
995
        self.window.get_widget("config-storage-box").set_sensitive(src.get_active())
991
996
 
992
997
    def browse_storage(self, ignore1):
993
 
        f = self._browse_file(_("Locate existing storage"))
994
 
        if f != None:
995
 
            self.window.get_widget("config-storage-entry").set_text(f)
 
998
        self._browse_file(_("Locate existing storage"),
 
999
                          self.set_disk_storage_path,
 
1000
                          is_media=False)
996
1001
 
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())
1003
1008
 
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)
 
1011
 
 
1012
    def set_disk_storage_path(self, ignore, path):
 
1013
        self.window.get_widget("config-storage-entry").set_text(path)
1011
1014
 
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."),
1217
1220
                                    str(e))
 
1221
 
 
1222
        # Validation passed, store the install path (if there is one) in
 
1223
        # gconf
 
1224
        self.get_config_local_media(store_media=True)
 
1225
        self.get_config_url_info(store_media=True)
1218
1226
        return True
1219
1227
 
1220
1228
    def validate_mem_page(self):
1257
1265
                                        size = disksize,
1258
1266
                                        sparse = sparse)
1259
1267
 
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
1264
 
 
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()))
1413
1416
            return False
1414
1417
 
1415
 
 
1416
1418
        logging.debug("Creating a VM %s" % guest.name +
1417
1419
                      "\n  Type: %s,%s" % (guest.type,
1418
1420
                                           guest.installer.os_type) +
1428
1430
                      "\n  Audio?: %s" % str(self.get_config_sound()))
1429
1431
 
1430
1432
        # Start the install
1431
 
        self.install_error = None
 
1433
        self.failed_guest = None
1432
1434
        self.topwin.set_sensitive(False)
1433
1435
        self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
1434
1436
 
1440
1442
                                     "images may take a few minutes to "
1441
1443
                                     "complete."))
1442
1444
        progWin.run()
 
1445
        error, details = progWin.get_error()
1443
1446
 
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
1449
 
            # their mistakes
1450
 
            return
 
1447
        if error != None:
 
1448
            self.err.show_err(error, details)
1451
1449
 
1452
1450
        self.topwin.set_sensitive(True)
1453
1451
        self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW))
 
1452
 
 
1453
        if error:
 
1454
            self.failed_guest = self.guest
 
1455
            return
 
1456
 
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)
1470
1473
 
1471
1474
    def do_install(self, guest, asyncjob):
1472
1475
        meter = vmmCreateMeter(asyncjob)
1473
 
 
 
1476
        error = None
 
1477
        details = None
1474
1478
        try:
1475
1479
            logging.debug("Starting background install process")
1476
1480
 
1484
1488
 
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")
 
1492
                details = error
1489
1493
                logging.error("Guest install did not return a domain")
1490
1494
            else:
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)))
1499
 
 
1500
 
            self.install_error = (_("Unable to complete install: '%s'") %
1501
 
                                  str(value))
1502
 
            self.install_details = details
1503
 
            logging.error(details)
1504
 
 
 
1503
            error = (_("Unable to complete install: '%s'") % str(value))
 
1504
 
 
1505
        if error:
 
1506
            asyncjob.set_error(error, details)
1505
1507
 
1506
1508
    def pretty_storage(self, size):
1507
1509
        return "%.1f Gb" % float(size)
1622
1624
 
1623
1625
            self._safe_wrapper(self.set_distro_selection, results)
1624
1626
        finally:
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)
1641
1642
 
1642
 
    def _browse_file(self, dialog_name, folder=None, is_media=False):
1643
 
 
1644
 
        if self.conn.is_remote() or not is_media:
1645
 
            if self.storage_browser == None:
1646
 
                self.storage_browser = vmmStorageBrowser(self.config,
1647
 
                                                         self.conn)
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)
1653
 
            return None
1654
 
 
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,
 
1646
                                                     is_media)
 
1647
            self.storage_browser.connect("storage-browse-finish",
 
1648
                                         callback)
 
1649
        if is_media:
 
1650
            reason = self.config.CONFIG_DIR_MEDIA
 
1651
        else:
 
1652
            reason = self.config.CONFIG_DIR_IMAGE
 
1653
 
 
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)
1656
1658
 
1657
1659
    def show_help(self, ignore):
1658
1660
        # No help available yet.