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

« back to all changes in this revision

Viewing changes to .pc/0006-Fix-error-launching-create-wizard-on-qemu-session.patch/src/virtManager/uihelpers.py

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2011-02-03 10:35:22 UTC
  • mfrom: (2.3.3 experimental)
  • Revision ID: james.westby@ubuntu.com-20110203103522-j8and6dsy3taczbj
Tags: 0.8.6-1ubuntu1
* Merge from debian experimental. Remaining changes:
  - Depend on python-appindicator for appindicator support.
  - Add a /usr/share/pixmaps/virt-manager-icon.svg symlink to link icon to
    where the Application Indicator can find it.
  - Add patch da_l10n.patch since it is not integrated. (refreshed)
  - Add patch show_session_or_system_in_console to make the overview
    screen show which local qemu session you're connected to. (refreshed)
  - Add patch more_helpful_error_message to explain to the user why he
    can't connect to qemu:///system and what he can do fix it.
  - Add patch qemu-system-by-default to automatically add qemu:///system
    to the list of hypervisors if the user has write access to the UNIX
    socket.
  - Drop patchsys-quilt include since dpkg-source does the quilt dance for
    us.
  - debian/control: lower libvirt-bin from Recommends to Suggests; seems
    some users (like netbooks) want to manage VMs, but not host them; see
    meta packages (ubuntu-virt, ubuntu-virt-server, ubuntu-virt-mgmt) for
    group installation of virt package sets.
* Removed patches:
  - debian/patches/custom-icon-installation.patch: Upstream.
  - debian/patches/remove-appindicator-workarounds.patch: Upstream.
  - debian/patches/fix-nc-with-zsh.patch: Upstream
* Removed python-ipy dependency as it is in universe:
  - debian/control: remove python-ipy from Depends
  - debian/series: disable 0002-Use-IPy-from-python-ipy.patch patch so
    we use the one that's included in the virt-manager source.
  - debian/rules: don't delete the IPy file.
* debian/patches/fix-cpu-wrong-types.patch: fix "value is of wrong type
  for this column" error by making sure we are using strings in
  src/virtManager/details.py.
* debian/patches/dont-always-launch-consoles.patch: Don't always launch
  consoles for running domains in src/virtManager/manager.py.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Copyright (C) 2009 Red Hat, Inc.
3
 
# Copyright (C) 2009 Cole Robinson <crobinso@redhat.com>
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 
# MA 02110-1301 USA.
19
 
#
20
 
 
21
 
import logging
22
 
import traceback
23
 
import os, statvfs
24
 
 
25
 
import gtk
26
 
 
27
 
import virtinst
28
 
from virtinst import VirtualNetworkInterface
29
 
from virtinst import VirtualDisk
30
 
 
31
 
from virtManager import util
32
 
from virtManager.error import vmmErrorDialog
33
 
 
34
 
OPTICAL_DEV_PATH = 0
35
 
OPTICAL_LABEL = 1
36
 
OPTICAL_IS_MEDIA_PRESENT = 2
37
 
OPTICAL_DEV_KEY = 3
38
 
OPTICAL_MEDIA_KEY = 4
39
 
OPTICAL_IS_VALID = 5
40
 
 
41
 
# What user we guess the qemu:///system starts the emulator as. Some distros
42
 
# may use a nonroot user, so simply changing this will cause several UI
43
 
# pieces to attempt to verify that permissions are correct. Eventually this
44
 
# should be exposed via capabilities so we can determine this programmatically.
45
 
QEMU_SYSTEM_EMULATOR_USER = "root"
46
 
 
47
 
##############################################################
48
 
# Initialize an error object to use for validation functions #
49
 
##############################################################
50
 
 
51
 
err_dial = vmmErrorDialog(None,
52
 
                          0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
53
 
                          _("Unexpected Error"),
54
 
                          _("An unexpected error occurred"))
55
 
 
56
 
def set_error_parent(parent):
57
 
    global err_dial
58
 
    err_dial.set_parent(parent)
59
 
    err_dial = err_dial
60
 
 
61
 
############################################################
62
 
# Helpers for shared storage UI between create/addhardware #
63
 
############################################################
64
 
 
65
 
def set_sparse_tooltip(widget):
66
 
    sparse_str = _("Fully allocating storage will take longer now, "
67
 
                   "but the OS install phase will be quicker. \n\n"
68
 
                   "Skipping allocation can also cause space issues on "
69
 
                   "the host machine, if the maximum image size exceeds "
70
 
                   "available storage space.")
71
 
    util.tooltip_wrapper(widget, sparse_str)
72
 
 
73
 
def host_disk_space(conn, config):
74
 
    pool = util.get_default_pool(conn)
75
 
    path = util.get_default_dir(conn, config)
76
 
 
77
 
    avail = 0
78
 
    if pool:
79
 
        # FIXME: make sure not inactive?
80
 
        # FIXME: use a conn specific function after we send pool-added
81
 
        pool = virtinst.util.lookup_pool_by_path(conn.vmm, path)
82
 
        if pool:
83
 
            pool.refresh(0)
84
 
            avail = int(virtinst.util.get_xml_path(pool.XMLDesc(0),
85
 
                                                   "/pool/available"))
86
 
 
87
 
    elif not conn.is_remote():
88
 
        vfs = os.statvfs(os.path.dirname(path))
89
 
        avail = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL]
90
 
 
91
 
    return float(avail / 1024.0 / 1024.0 / 1024.0)
92
 
 
93
 
def host_space_tick(conn, config, widget):
94
 
    max_storage = host_disk_space(conn, config)
95
 
 
96
 
    def pretty_storage(size):
97
 
        return "%.1f Gb" % float(size)
98
 
 
99
 
    hd_label = ("%s available in the default location" %
100
 
                pretty_storage(max_storage))
101
 
    hd_label = ("<span color='#484848'>%s</span>" % hd_label)
102
 
    widget.set_markup(hd_label)
103
 
 
104
 
    return 1
105
 
 
106
 
#####################################################
107
 
# Hardware model list building (for details, addhw) #
108
 
#####################################################
109
 
def build_video_combo(vm, video_dev, no_default=False):
110
 
    video_dev_model = gtk.ListStore(str)
111
 
    video_dev.set_model(video_dev_model)
112
 
    text = gtk.CellRendererText()
113
 
    video_dev.pack_start(text, True)
114
 
    video_dev.add_attribute(text, 'text', 0)
115
 
    video_dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
116
 
 
117
 
    tmpdev = virtinst.VirtualVideoDevice(vm.get_connection().vmm)
118
 
    for m in tmpdev.model_types:
119
 
        if m == tmpdev.MODEL_DEFAULT and no_default:
120
 
            continue
121
 
        video_dev_model.append([m])
122
 
    if len(video_dev_model) > 0:
123
 
        video_dev.set_active(0)
124
 
 
125
 
def build_sound_combo(vm, combo, no_default=False):
126
 
    dev_model = gtk.ListStore(str)
127
 
    combo.set_model(dev_model)
128
 
    text = gtk.CellRendererText()
129
 
    combo.pack_start(text, True)
130
 
    combo.add_attribute(text, 'text', 0)
131
 
    dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
132
 
 
133
 
    for m in virtinst.VirtualAudio.MODELS:
134
 
        if m == virtinst.VirtualAudio.MODEL_DEFAULT and no_default:
135
 
            continue
136
 
        dev_model.append([m])
137
 
    if len(dev_model) > 0:
138
 
        combo.set_active(0)
139
 
 
140
 
def build_watchdogmodel_combo(vm, combo, no_default=False):
141
 
    dev_model = gtk.ListStore(str)
142
 
    combo.set_model(dev_model)
143
 
    text = gtk.CellRendererText()
144
 
    combo.pack_start(text, True)
145
 
    combo.add_attribute(text, 'text', 0)
146
 
    dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
147
 
 
148
 
    for m in virtinst.VirtualWatchdog.MODELS:
149
 
        if m == virtinst.VirtualAudio.MODEL_DEFAULT and no_default:
150
 
            continue
151
 
        dev_model.append([m])
152
 
    if len(dev_model) > 0:
153
 
        combo.set_active(0)
154
 
 
155
 
def build_watchdogaction_combo(vm, combo, no_default=False):
156
 
    dev_model = gtk.ListStore(str, str)
157
 
    combo.set_model(dev_model)
158
 
    text = gtk.CellRendererText()
159
 
    combo.pack_start(text, True)
160
 
    combo.add_attribute(text, 'text', 1)
161
 
    dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
162
 
 
163
 
    for m in virtinst.VirtualWatchdog.ACTIONS:
164
 
        if m == virtinst.VirtualWatchdog.ACTION_DEFAULT and no_default:
165
 
            continue
166
 
        dev_model.append([m, virtinst.VirtualWatchdog.get_action_desc(m)])
167
 
    if len(dev_model) > 0:
168
 
        combo.set_active(0)
169
 
 
170
 
def build_netmodel_combo(vm, combo):
171
 
    dev_model = gtk.ListStore(str, str)
172
 
    combo.set_model(dev_model)
173
 
    text = gtk.CellRendererText()
174
 
    combo.pack_start(text, True)
175
 
    combo.add_attribute(text, 'text', 1)
176
 
    dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
177
 
 
178
 
    populate_netmodel_combo(vm, combo)
179
 
    combo.set_active(0)
180
 
 
181
 
def populate_netmodel_combo(vm, combo):
182
 
    model = combo.get_model()
183
 
    model.clear()
184
 
 
185
 
    # [xml value, label]
186
 
    model.append([None, _("Hypervisor default")])
187
 
    if vm.is_hvm():
188
 
        mod_list = [ "rtl8139", "ne2k_pci", "pcnet" ]
189
 
        if vm.get_hv_type() == "kvm":
190
 
            mod_list.append("e1000")
191
 
            mod_list.append("virtio")
192
 
        mod_list.sort()
193
 
 
194
 
        for m in mod_list:
195
 
            model.append([m, m])
196
 
 
197
 
 
198
 
#######################################################################
199
 
# Widgets for listing network device options (in create, addhardware) #
200
 
#######################################################################
201
 
 
202
 
def pretty_network_desc(nettype, source=None, netobj=None):
203
 
    if nettype == VirtualNetworkInterface.TYPE_USER:
204
 
        return _("Usermode networking")
205
 
 
206
 
    extra = None
207
 
    if nettype == VirtualNetworkInterface.TYPE_BRIDGE:
208
 
        ret = _("Bridge")
209
 
    elif nettype == VirtualNetworkInterface.TYPE_VIRTUAL:
210
 
        ret = _("Virtual network")
211
 
        if netobj:
212
 
            extra = ": %s" % netobj.pretty_forward_mode()
213
 
    else:
214
 
        ret = nettype.capitalize()
215
 
 
216
 
    if source:
217
 
        ret += " '%s'" % source
218
 
    if extra:
219
 
        ret += " %s" % extra
220
 
 
221
 
    return ret
222
 
 
223
 
def init_network_list(net_list, bridge_box):
224
 
    # [ network type, source name, label, sensitive?, net is active,
225
 
    #   manual bridge]
226
 
    net_model = gtk.ListStore(str, str, str, bool, bool, bool)
227
 
    net_list.set_model(net_model)
228
 
 
229
 
    net_list.connect("changed", net_list_changed, bridge_box)
230
 
 
231
 
    text = gtk.CellRendererText()
232
 
    net_list.pack_start(text, True)
233
 
    net_list.add_attribute(text, 'text', 2)
234
 
    net_list.add_attribute(text, 'sensitive', 3)
235
 
 
236
 
def net_list_changed(net_list, bridge_box):
237
 
    active = net_list.get_active()
238
 
    if active < 0:
239
 
        return
240
 
 
241
 
    row = net_list.get_model()[active]
242
 
    show_bridge = row[5]
243
 
 
244
 
    bridge_box.set_property("visible", show_bridge)
245
 
 
246
 
def get_network_selection(net_list, bridge_entry):
247
 
    row = net_list.get_model()[net_list.get_active()]
248
 
    net_type = row[0]
249
 
    net_src = row[1]
250
 
    net_check_bridge = row[5]
251
 
 
252
 
    if net_check_bridge:
253
 
        net_type = VirtualNetworkInterface.TYPE_BRIDGE
254
 
        net_src = bridge_entry.get_text()
255
 
 
256
 
    return net_type, net_src
257
 
 
258
 
def populate_network_list(net_list, conn):
259
 
    model = net_list.get_model()
260
 
    model.clear()
261
 
 
262
 
    vnet_bridges = []
263
 
    vnet_dict = {}
264
 
    bridge_dict = {}
265
 
    iface_dict = {}
266
 
 
267
 
    def add_row(*args):
268
 
        model.append(build_row(*args))
269
 
 
270
 
    def build_row(nettype, name, label, is_sensitive, is_running,
271
 
                  manual_bridge=False):
272
 
        return [nettype, name, label, is_sensitive, is_running, manual_bridge]
273
 
 
274
 
    def set_active(idx):
275
 
        net_list.set_active(idx)
276
 
 
277
 
    def add_dict(indict, model):
278
 
        keylist = indict.keys()
279
 
        keylist.sort()
280
 
        rowlist = map(lambda key: indict[key], keylist)
281
 
        for row in rowlist:
282
 
            model.append(row)
283
 
 
284
 
    # For qemu:///session
285
 
    if conn.is_qemu_session():
286
 
        nettype = VirtualNetworkInterface.TYPE_USER
287
 
        add_row(nettype, None, pretty_network_desc(nettype), True)
288
 
        set_active(0)
289
 
        return
290
 
 
291
 
    hasNet = False
292
 
    netIdxLabel = None
293
 
    # Virtual Networks
294
 
    for uuid in conn.list_net_uuids():
295
 
        net = conn.get_net(uuid)
296
 
        nettype = VirtualNetworkInterface.TYPE_VIRTUAL
297
 
 
298
 
        label = pretty_network_desc(nettype, net.get_name(), net)
299
 
        if not net.is_active():
300
 
            label +=  " (%s)" % _("Inactive")
301
 
 
302
 
        hasNet = True
303
 
        # FIXME: Should we use 'default' even if it's inactive?
304
 
        # FIXME: This preference should be configurable
305
 
        if net.get_name() == "default":
306
 
            netIdxLabel = label
307
 
 
308
 
        vnet_dict[label] = build_row(nettype, net.get_name(), label, True,
309
 
                                     net.is_active())
310
 
 
311
 
        # Build a list of vnet bridges, so we know not to list them
312
 
        # in the physical interface list
313
 
        vnet_bridge = net.get_bridge_device()
314
 
        if vnet_bridge:
315
 
            vnet_bridges.append(vnet_bridge)
316
 
 
317
 
    if not hasNet:
318
 
        label = _("No virtual networks available")
319
 
        vnet_dict[label] = build_row(None, None, label, False, False)
320
 
 
321
 
    # Physical devices
322
 
    hasShared = False
323
 
    brIdxLabel = None
324
 
    for name in conn.list_net_device_paths():
325
 
        br = conn.get_net_device(name)
326
 
        bridge_name = br.get_bridge()
327
 
        nettype = VirtualNetworkInterface.TYPE_BRIDGE
328
 
 
329
 
        if (bridge_name in vnet_bridges) or (br.get_name() in vnet_bridges):
330
 
            # Don't list this, as it is basically duplicating virtual net info
331
 
            continue
332
 
 
333
 
        if br.is_shared():
334
 
            sensitive = True
335
 
            if br.get_bridge():
336
 
                hasShared = True
337
 
                brlabel = "(%s)" % pretty_network_desc(nettype, bridge_name)
338
 
            else:
339
 
                bridge_name = name
340
 
                brlabel = _("(Empty bridge)")
341
 
        else:
342
 
            sensitive = False
343
 
            brlabel = "(%s)" %  _("Not bridged")
344
 
 
345
 
        label = _("Host device %s %s") % (br.get_name(), brlabel)
346
 
        if hasShared and not brIdxLabel:
347
 
            brIdxLabel = label
348
 
 
349
 
        row = build_row(nettype, bridge_name, label, sensitive, True)
350
 
 
351
 
        if sensitive:
352
 
            bridge_dict[label] = row
353
 
        else:
354
 
            iface_dict[label] = row
355
 
 
356
 
    add_dict(bridge_dict, model)
357
 
    add_dict(vnet_dict, model)
358
 
    add_dict(iface_dict, model)
359
 
 
360
 
    # If there is a bridge device, default to that
361
 
    # If not, use 'default' network
362
 
    # If not present, use first list entry
363
 
    # If list empty, use no network devices
364
 
    return_warn = False
365
 
    label = brIdxLabel or netIdxLabel
366
 
 
367
 
    for idx in range(len(model)):
368
 
        row = model[idx]
369
 
        is_inactive = not row[4]
370
 
        if label:
371
 
            if row[2] == label:
372
 
                default = idx
373
 
                return_warn = is_inactive
374
 
                break
375
 
        else:
376
 
            if row[3] == True:
377
 
                default = idx
378
 
                return_warn = is_inactive
379
 
                break
380
 
    else:
381
 
        return_warn = True
382
 
        row = build_row(None, None, _("No networking."), True, False)
383
 
        model.insert(0, row)
384
 
        default = 0
385
 
 
386
 
    # After all is said and done, add a manual bridge option
387
 
    manual_row = build_row(None, None, _("Specify shared device name"),
388
 
                           True, False, manual_bridge=True)
389
 
    model.append(manual_row)
390
 
 
391
 
    set_active(default)
392
 
    return return_warn
393
 
 
394
 
def validate_network(parent, conn, nettype, devname, macaddr, model=None):
395
 
    set_error_parent(parent)
396
 
 
397
 
    net = None
398
 
 
399
 
    if nettype is None:
400
 
        return None
401
 
 
402
 
    # Make sure VirtualNetwork is running
403
 
    if (nettype == VirtualNetworkInterface.TYPE_VIRTUAL and
404
 
        devname not in conn.vmm.listNetworks()):
405
 
 
406
 
        res = err_dial.yes_no(_("Virtual Network is not active."),
407
 
                              _("Virtual Network '%s' is not active. "
408
 
                                "Would you like to start the network "
409
 
                                "now?") % devname)
410
 
        if not res:
411
 
            return False
412
 
 
413
 
        # Try to start the network
414
 
        try:
415
 
            virnet = conn.vmm.networkLookupByName(devname)
416
 
            virnet.create()
417
 
            logging.info("Started network '%s'." % devname)
418
 
        except Exception, e:
419
 
            return err_dial.show_err(_("Could not start virtual network "
420
 
                                       "'%s': %s") % (devname, str(e)),
421
 
                                       "".join(traceback.format_exc()))
422
 
 
423
 
    # Create network device
424
 
    try:
425
 
        bridge = None
426
 
        netname = None
427
 
        if nettype == VirtualNetworkInterface.TYPE_VIRTUAL:
428
 
            netname = devname
429
 
        elif nettype == VirtualNetworkInterface.TYPE_BRIDGE:
430
 
            bridge = devname
431
 
        elif nettype == VirtualNetworkInterface.TYPE_USER:
432
 
            pass
433
 
 
434
 
        net = VirtualNetworkInterface(type = nettype,
435
 
                                      bridge = bridge,
436
 
                                      network = netname,
437
 
                                      macaddr = macaddr,
438
 
                                      model = model)
439
 
    except Exception, e:
440
 
        return err_dial.val_err(_("Error with network parameters."), str(e))
441
 
 
442
 
    # Make sure there is no mac address collision
443
 
    isfatal, errmsg = net.is_conflict_net(conn.vmm)
444
 
    if isfatal:
445
 
        return err_dial.val_err(_("Mac address collision."), errmsg)
446
 
    elif errmsg is not None:
447
 
        retv = err_dial.yes_no(_("Mac address collision."),
448
 
                               _("%s Are you sure you want to use this "
449
 
                                 "address?") % errmsg)
450
 
        if not retv:
451
 
            return False
452
 
 
453
 
    return net
454
 
 
455
 
def generate_macaddr(conn):
456
 
    newmac = ""
457
 
    try:
458
 
        net = VirtualNetworkInterface(conn=conn.vmm)
459
 
        net.setup(conn.vmm)
460
 
        newmac = net.macaddr
461
 
    except:
462
 
        pass
463
 
 
464
 
    return newmac
465
 
 
466
 
 
467
 
############################################
468
 
# Populate media widget (choosecd, create) #
469
 
############################################
470
 
 
471
 
def init_mediadev_combo(widget):
472
 
    # [Device path, pretty label, has_media?, device key, media key,
473
 
    #  vmmMediaDevice, is valid device]
474
 
    model = gtk.ListStore(str, str, bool, str, str, bool)
475
 
    widget.set_model(model)
476
 
    model.clear()
477
 
 
478
 
    text = gtk.CellRendererText()
479
 
    widget.pack_start(text, True)
480
 
    widget.add_attribute(text, 'text', OPTICAL_LABEL)
481
 
    widget.add_attribute(text, 'sensitive', OPTICAL_IS_VALID)
482
 
 
483
 
def populate_mediadev_combo(conn, widget, devtype):
484
 
    sigs = []
485
 
 
486
 
    model = widget.get_model()
487
 
    model.clear()
488
 
    set_mediadev_default(model)
489
 
 
490
 
    sigs.append(conn.connect("mediadev-added", mediadev_added, widget, devtype))
491
 
    sigs.append(conn.connect("mediadev-removed", mediadev_removed, widget))
492
 
 
493
 
    widget.set_active(-1)
494
 
    mediadev_set_default_selection(widget)
495
 
 
496
 
    return sigs
497
 
 
498
 
def set_mediadev_default(model):
499
 
    if len(model) == 0:
500
 
        model.append([None, _("No device present"), False, None, None, False])
501
 
 
502
 
def set_row_from_object(row, obj):
503
 
    row[OPTICAL_DEV_PATH] = obj.get_path()
504
 
    row[OPTICAL_LABEL] = obj.pretty_label()
505
 
    row[OPTICAL_IS_MEDIA_PRESENT] = obj.has_media()
506
 
    row[OPTICAL_DEV_KEY] = obj.get_key()
507
 
    row[OPTICAL_MEDIA_KEY] = obj.get_media_key()
508
 
    row[OPTICAL_IS_VALID] = True
509
 
 
510
 
def mediadev_removed(ignore_helper, key, widget):
511
 
    model = widget.get_model()
512
 
    active = widget.get_active()
513
 
    idx = 0
514
 
 
515
 
    for row in model:
516
 
        if row[OPTICAL_DEV_KEY] == key:
517
 
            # Whole device removed
518
 
            del(model[idx])
519
 
 
520
 
            if idx > active and active != -1:
521
 
                widget.set_active(active-1)
522
 
            elif idx == active:
523
 
                widget.set_active(-1)
524
 
 
525
 
        idx += 1
526
 
 
527
 
    set_mediadev_default(model)
528
 
    mediadev_set_default_selection(widget)
529
 
 
530
 
def mediadev_added(ignore_helper, newobj, widget, devtype):
531
 
    model = widget.get_model()
532
 
 
533
 
    if newobj.get_media_type() != devtype:
534
 
        return
535
 
 
536
 
    if len(model) == 1 and model[0][OPTICAL_IS_VALID] == False:
537
 
        # Only entry is the 'No device' entry
538
 
        model.clear()
539
 
 
540
 
    newobj.connect("media-added", mediadev_media_changed, widget)
541
 
    newobj.connect("media-removed", mediadev_media_changed, widget)
542
 
 
543
 
    # Brand new device
544
 
    row = [None, None, None, None, None, None]
545
 
    set_row_from_object(row, newobj)
546
 
    model.append(row)
547
 
 
548
 
    mediadev_set_default_selection(widget)
549
 
 
550
 
def mediadev_media_changed(newobj, widget):
551
 
    model = widget.get_model()
552
 
    active = widget.get_active()
553
 
    idx = 0
554
 
 
555
 
    # Search for the row with matching device node and
556
 
    # fill in info about inserted media. If model has no current
557
 
    # selection, select the new media.
558
 
    for row in model:
559
 
        if row[OPTICAL_DEV_PATH] == newobj.get_path():
560
 
            set_row_from_object(row, newobj)
561
 
            has_media = row[OPTICAL_IS_MEDIA_PRESENT]
562
 
 
563
 
            if has_media and active == -1:
564
 
                widget.set_active(idx)
565
 
            elif not has_media and active == idx:
566
 
                widget.set_active(-1)
567
 
 
568
 
        idx = idx + 1
569
 
 
570
 
    mediadev_set_default_selection(widget)
571
 
 
572
 
def mediadev_set_default_selection(widget):
573
 
    # Set the first active cdrom device as selected, otherwise none
574
 
    model = widget.get_model()
575
 
    idx = 0
576
 
    active = widget.get_active()
577
 
 
578
 
    if active != -1:
579
 
        # already a selection, don't change it
580
 
        return
581
 
 
582
 
    for row in model:
583
 
        if row[OPTICAL_IS_MEDIA_PRESENT] == True:
584
 
            widget.set_active(idx)
585
 
            return
586
 
        idx += 1
587
 
 
588
 
    widget.set_active(-1)
589
 
 
590
 
 
591
 
####################################################################
592
 
# Build toolbar shutdown button menu (manager and details toolbar) #
593
 
####################################################################
594
 
 
595
 
def build_shutdown_button_menu(config, widget, shutdown_cb, reboot_cb,
596
 
                               destroy_cb):
597
 
    icon_name = config.get_shutdown_icon_name()
598
 
    widget.set_icon_name(icon_name)
599
 
    menu = gtk.Menu()
600
 
    widget.set_menu(menu)
601
 
 
602
 
    rebootimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
603
 
    shutdownimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
604
 
    destroyimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
605
 
 
606
 
    reboot = gtk.ImageMenuItem(_("_Reboot"))
607
 
    reboot.set_image(rebootimg)
608
 
    reboot.show()
609
 
    reboot.connect("activate", reboot_cb)
610
 
    menu.add(reboot)
611
 
 
612
 
    shutdown = gtk.ImageMenuItem(_("_Shut Down"))
613
 
    shutdown.set_image(shutdownimg)
614
 
    shutdown.show()
615
 
    shutdown.connect("activate", shutdown_cb)
616
 
    menu.add(shutdown)
617
 
 
618
 
    destroy = gtk.ImageMenuItem(_("_Force Off"))
619
 
    destroy.set_image(destroyimg)
620
 
    destroy.show()
621
 
    destroy.connect("activate", destroy_cb)
622
 
    menu.add(destroy)
623
 
 
624
 
#####################################
625
 
# Path permissions checker for qemu #
626
 
#####################################
627
 
def check_path_search_for_qemu(parent, config, conn, path):
628
 
    set_error_parent(parent)
629
 
 
630
 
    if conn.is_remote() or not conn.is_qemu_system():
631
 
        return
632
 
 
633
 
    user = QEMU_SYSTEM_EMULATOR_USER
634
 
 
635
 
    skip_paths = config.get_perms_fix_ignore()
636
 
    broken_paths = VirtualDisk.check_path_search_for_user(conn.vmm, path, user)
637
 
    for p in broken_paths:
638
 
        if p in skip_paths:
639
 
            broken_paths.remove(p)
640
 
 
641
 
    if not broken_paths:
642
 
        return
643
 
 
644
 
    logging.debug("No search access for dirs: %s" % broken_paths)
645
 
    resp, chkres = err_dial.warn_chkbox(
646
 
                    _("The emulator may not have search permissions "
647
 
                      "for the path '%s'.") % path,
648
 
                    _("Do you want to correct this now?"),
649
 
                    _("Don't ask about these directories again."),
650
 
                    buttons=gtk.BUTTONS_YES_NO)
651
 
 
652
 
    if chkres:
653
 
        config.add_perms_fix_ignore(broken_paths)
654
 
    if not resp:
655
 
        return
656
 
 
657
 
    logging.debug("Attempting to correct permission issues.")
658
 
    errors = VirtualDisk.fix_path_search_for_user(conn.vmm, path, user)
659
 
    if not errors:
660
 
        return
661
 
 
662
 
    errmsg = _("Errors were encountered changing permissions for the "
663
 
               "following directories:")
664
 
    details = ""
665
 
    for path, error in errors.items():
666
 
        if path not in broken_paths:
667
 
            continue
668
 
        details += "%s : %s\n" % (path, error)
669
 
 
670
 
    logging.debug("Permission errors:\n%s" % details)
671
 
 
672
 
    ignore, chkres = err_dial.err_chkbox(errmsg, details,
673
 
                         _("Don't ask about these directories again."))
674
 
 
675
 
    if chkres:
676
 
        config.add_perms_fix_ignore(errors.keys())
677
 
 
678
 
######################################
679
 
# Interface startmode widget builder #
680
 
######################################
681
 
 
682
 
def build_startmode_combo(start_list):
683
 
    start_model = gtk.ListStore(str)
684
 
    start_list.set_model(start_model)
685
 
    text = gtk.CellRendererText()
686
 
    start_list.pack_start(text, True)
687
 
    start_list.add_attribute(text, 'text', 0)
688
 
    start_model.append(["none"])
689
 
    start_model.append(["onboot"])
690
 
    start_model.append(["hotplug"])
691