Merge heads

This commit is contained in:
Daniel P. Berrange 2007-07-04 00:50:50 -04:00
commit 1d710a9e50
16 changed files with 656 additions and 166 deletions

View File

@ -21,8 +21,9 @@ Further patches have been submitted by:
Mark Cave-Ayland <mark.cave-ayland-at-ilande-dot-co-dot-uk>
Richard W.M. Jones <rjones-at-redhat-dot-com>
Nobuhiro Itou <fj0873gn-at-aa-dot-jp-dot-fujitsu-dot-com>
Cole Robinson <crobinso-at-redhat-dot-com>
Ville Skytta <ville-dot-skytta-at-iki-dot-fi>
Mark Johnson <johnson-dot-nh-at-gmail-dot-com>
Cole Robinson <crobinso-at-redhat-dot-com>
<...send a patch & get your name here...>

View File

@ -1,6 +1,6 @@
[Desktop Entry]
_Name=Virtual Machine Manager
_Comment=The virtual machine management tool
_Comment=Manage virtual machines
Icon=::ICONDIR::/::PACKAGE::-icon.svg
Exec=::PACKAGE::
Type=Application

View File

@ -156,5 +156,18 @@
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/console/grab-notify</key>
<applyto>/apps/::PACKAGE::/console/grab-notify</applyto>
<owner>::PACKAGE::</owner>
<type>bool</type>
<default>1</default>
<locale name="C">
<short>Whether to show notification when grabbing mouse</short>
<long>Whether to show the notification hint when grabbing the mouse in the console</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -71,6 +71,7 @@ class vmmAddHardware(gobject.GObject):
"on_storage_file_address_changed": self.toggle_storage_size,
"on_storage_toggled" : self.change_storage_type,
"on_network_toggled" : self.change_network_type,
"on_mac_address_clicked" : self.change_macaddr_use,
"on_create_help_clicked": self.show_help,
})
@ -138,6 +139,7 @@ class vmmAddHardware(gobject.GObject):
self.change_storage_type()
self.change_network_type()
self.change_macaddr_use()
if os.getuid() == 0:
self.window.get_widget("storage-partition").set_active(True)
else:
@ -212,6 +214,12 @@ class vmmAddHardware(gobject.GObject):
model = dev.get_model()
return ["bridge", model.get_value(dev.get_active_iter(), 0)]
def get_config_macaddr(self):
macaddr = None
if self.window.get_widget("mac-address").get_active():
macaddr = self.window.get_widget("create-mac-address").get_text()
return macaddr
def page_changed(self, notebook, page, page_number):
if page_number == PAGE_DISK:
pass
@ -244,6 +252,11 @@ class vmmAddHardware(gobject.GObject):
self.window.get_widget("summary-net-target").set_text("-")
else:
raise ValueError, "Unknown networking type " + net[0]
macaddr = self.get_config_macaddr()
if macaddr != None:
self.window.get_widget("summary-mac-address").set_text(macaddr)
else:
self.window.get_widget("summary-mac-address").set_text("-")
def close(self, ignore1=None,ignore2=None):
self.topwin.hide()
@ -286,11 +299,12 @@ class vmmAddHardware(gobject.GObject):
def add_network(self):
net = self.get_config_network()
mac = self.get_config_macaddr()
vnic = None
if net[0] == "bridge":
vnic = virtinst.VirtualNetworkInterface(type=net[0], bridge=net[1])
vnic = virtinst.VirtualNetworkInterface(macaddr=mac, type=net[0], bridge=net[1])
elif net[0] == "network":
vnic = virtinst.VirtualNetworkInterface(type=net[0], network=net[1])
vnic = virtinst.VirtualNetworkInterface(macaddr=mac, type=net[0], network=net[1])
else:
raise ValueError, "Unsupported networking type " + net[0]
@ -446,6 +460,12 @@ class vmmAddHardware(gobject.GObject):
self.window.get_widget("net-network").set_sensitive(False)
self.window.get_widget("net-device").set_sensitive(True)
def change_macaddr_use(self, ignore=None):
if self.window.get_widget("mac-address").get_active():
self.window.get_widget("create-mac-address").set_sensitive(True)
else:
self.window.get_widget("create-mac-address").set_sensitive(False)
def validate(self, page_num):
if page_num == PAGE_INTRO:
if self.get_config_hardware_type() == None:
@ -484,6 +504,29 @@ class vmmAddHardware(gobject.GObject):
_("You must select one of the physical devices"))
return False
if self.window.get_widget("mac-address").get_active():
mac= self.window.get_widget("create-mac-address").get_text()
if len(mac) != 17:
self._validation_error_box(_("Invalid MAC address"), \
_("MAC adrress must be 17 characters"))
return False
if re.match("^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$",mac) == None:
self._validation_error_box(_("Invalid MAC address"), \
_("MAC address must be a form such as AA:BB:CC:DD:EE:FF, and MAC adrress may contain numeric and alphabet of A-F(a-f) and ':' characters only"))
return False
hostdevs = virtinst.util.get_host_network_devices()
for hostdev in hostdevs:
if mac.lower() == hostdev[4]:
return self._yes_no_box(_('MAC adress "%s" is already in use by host!' % mac), \
_("Do you really want to use the MAC address ?"))
vms = []
for domains in self.vm.get_connection().vms.values():
vms.append(domains.vm)
vnic = virtinst.VirtualNetworkInterface(macaddr=mac)
if vnic.countMACaddr(vms) > 0:
return self._yes_no_box(_('MAC adress "%s" is already in use by another guest!' % mac), \
_("Do you really want to use the MAC address ?"))
return True
def _validation_error_box(self, text1, text2=None):

View File

@ -209,6 +209,13 @@ class vmmConfig:
def set_console_keygrab(self, pref):
self.conf.set_int(self.conf_dir + "/console/keygrab", pref)
def show_console_grab_notify(self):
return self.conf.get_bool(self.conf_dir + "/console/grab-notify")
def set_console_grab_notify(self, state):
self.conf.set_bool(self.conf_dir + "/console/grab-notify", state)
def get_secret_name(self, vm):
return "vm-console-" + vm.get_uuid()

View File

@ -189,6 +189,8 @@ class vmmConnection(gobject.GObject):
return "QEMU session: " + self.get_hostname()
else:
return "QEMU system: " + self.get_hostname()
else:
return self.get_type() + ":" + self.get_hostname()
def get_uri(self):
@ -223,6 +225,13 @@ class vmmConnection(gobject.GObject):
def get_host_info(self):
return self.hostinfo
def get_max_vcpus(self):
try:
return self.vmm.getMaxVcpus(self.get_type())
except Exception, e:
logging.debug('Unable to get max vcpu')
return 32;
def connect(self, name, callback):
handle_id = gobject.GObject.connect(self, name, callback)

View File

@ -68,6 +68,17 @@ class vmmConsole(gobject.GObject):
self.vncViewerFailures = 0
self.vncViewerRetryDelay = 125
self.notifyID = None
try:
bus = dbus.SessionBus()
self.notifyObject = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
self.notifyInterface = dbus.Interface(self.notifyObject, "org.freedesktop.Notifications")
self.notifyInterface.connect_to_signal("ActionInvoked", self.notify_action)
self.notifyInterface.connect_to_signal("NotificationClosed", self.notify_closed)
except Exception, e:
logging.error("Cannot initialize notification system" + str(e))
pass
self.window.get_widget("console-pages").set_show_tabs(False)
self.config.on_console_keygrab_changed(self.keygrab_changed)
@ -121,30 +132,41 @@ class vmmConsole(gobject.GObject):
def notify_grabbed(self, src):
topwin = self.window.get_widget("vmm-console")
topwin.set_title(_("Press Ctrl+Alt to release pointer.") + " " + self.title)
if self.config.show_console_grab_notify():
try:
bus = dbus.SessionBus()
noteSvr = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
noteObj = dbus.Interface(noteSvr, "org.freedesktop.Notifications")
(x, y) = topwin.window.get_origin()
noteObj.Notify(topwin.get_title(),
self.notifyID = self.notifyInterface.Notify(topwin.get_title(),
0,
'',
_("Pointer grabbed"),
_("The mouse pointer has been restricted to the virtual " \
"console window. To release the pointer press the key pair " \
"Ctrl+Alt"),
[],
["dismiss", _("Do not show this notification in the future")],
{"desktop-entry": "virt-manager",
"x": x+200, "y": y},
5 * 1000);
8 * 1000);
except Exception, e:
logging.error("Cannot popup notification " + str(e))
pass
topwin.set_title(_("Press Ctrl+Alt to release pointer.") + " " + self.title)
def notify_ungrabbed(self, src):
topwin = self.window.get_widget("vmm-console")
topwin.set_title(self.title)
def notify_closed(self, id, reason=None):
if self.notifyID is not None and self.notifyID == id:
self.notifyID = None
def notify_action(self, id, action):
if self.notifyID is None or self.notifyID != id:
return
if action == "dismiss":
self.config.set_console_grab_notify(False)
def keygrab_changed(self, src, ignore1=None,ignore2=None,ignore3=None):
if self.config.get_console_keygrab() == 2:
self.vncViewer.set_autograb_keyboard(True)

View File

@ -92,6 +92,7 @@ class vmmCreate(gobject.GObject):
"on_storage_file_address_changed": self.toggle_storage_size,
"on_storage_toggled" : self.change_storage_type,
"on_network_toggled" : self.change_network_type,
"on_mac_address_clicked" : self.change_macaddr_use,
"on_media_toggled" : self.change_media_type,
"on_os_type_changed" : self.change_os_type,
"on_cpu_architecture_changed": self.change_cpu_arch,
@ -101,6 +102,11 @@ class vmmCreate(gobject.GObject):
self.set_initial_state()
# Guest to fill in with values along the way
self._guest = virtinst.Guest(type=self.get_domain_type())
self._disk = None
self._net = None
def show(self):
self.topwin.show()
self.reset_state()
@ -238,6 +244,7 @@ class vmmCreate(gobject.GObject):
self.change_media_type()
self.change_storage_type()
self.change_network_type()
self.change_macaddr_use()
self.window.get_widget("create-vm-name").set_text("")
self.window.get_widget("media-iso-image").set_active(True)
self.window.get_widget("fv-iso-location").set_text("")
@ -251,6 +258,7 @@ class vmmCreate(gobject.GObject):
self.window.get_widget("create-memory-max").set_value(500)
self.window.get_widget("create-memory-startup").set_value(500)
self.window.get_widget("create-vcpus").set_value(1)
self.window.get_widget("create-vcpus").get_adjustment().upper = self.connection.get_max_vcpus()
self.window.get_widget("non-sparse").set_active(True)
model = self.window.get_widget("pv-media-url").get_model()
self.populate_url_model(model, self.config.get_media_urls())
@ -362,6 +370,12 @@ class vmmCreate(gobject.GObject):
model = dev.get_model()
return ["bridge", model.get_value(dev.get_active_iter(), 0)]
def get_config_macaddr(self):
macaddr = None
if self.window.get_widget("mac-address").get_active():
macaddr = self.window.get_widget("create-mac-address").get_text()
return macaddr
def get_config_maximum_memory(self):
return self.window.get_widget("create-memory-max").get_value()
@ -449,6 +463,12 @@ class vmmCreate(gobject.GObject):
self.window.get_widget("summary-net-target").set_text("-")
else:
raise ValueError, "Unknown networking type " + net[0]
macaddr = self.get_config_macaddr()
if macaddr != None:
self.window.get_widget("summary-mac-address").set_text(macaddr)
else:
self.window.get_widget("summary-mac-address").set_text("-")
self.window.get_widget("create-forward").hide()
self.window.get_widget("create-finish").show()
@ -462,95 +482,27 @@ class vmmCreate(gobject.GObject):
return 0
def finish(self, ignore=None):
# first things first, are we trying to create a fully virt guest?
if self.get_config_method() == VM_FULLY_VIRT:
guest = virtinst.FullVirtGuest(type=self.get_domain_type(), \
hypervisorURI=self.connection.get_uri(), \
arch=self.get_domain_arch())
try:
guest.cdrom = self.get_config_install_source()
except ValueError, e:
self._validation_error_box(_("Invalid FV media address"),e.args[0])
try:
if self.get_config_os_type() is not None and self.get_config_os_type() != "generic":
logging.debug("OS Type: %s" % self.get_config_os_type())
guest.os_type = self.get_config_os_type()
except ValueError, e:
self._validation_error_box(_("Invalid FV OS Type"),e.args[0])
try:
if self.get_config_os_variant() is not None and self.get_config_os_type() != "generic":
logging.debug("OS Variant: %s" % self.get_config_os_variant())
guest.os_variant = self.get_config_os_variant()
except ValueError, e:
self._validation_error_box(_("Invalid FV OS Variant"),e.args[0])
# Validation should have mostly set up out guest. We just need
# to take care of a few pieces we didn't touch
else:
guest = virtinst.ParaVirtGuest(type=self.get_domain_type(), hypervisorURI=self.connection.get_uri())
guest = self._guest
guest.hypervisorURI = self.connection.get_uri()
# UUID, append disk and nic
try:
guest.location = self.get_config_install_source()
except ValueError, e:
self._validation_error_box(_("Invalid PV media address"), e.args[0])
return
ks = self.get_config_kickstart_source()
if ks != None and len(ks) != 0:
guest.extraargs = "ks=%s" % ks
# set the name
try:
guest.name = self.get_config_name()
except ValueError, e:
self._validation_error_box(_("Invalid system name"), e.args[0])
return
# set the memory
try:
guest.memory = int(self.get_config_initial_memory())
except ValueError:
self._validation_error_box(_("Invalid memory setting"), e.args[0])
return
try:
guest.maxmemory = int(self.get_config_maximum_memory())
except ValueError:
self._validation_error_box(_("Invalid memory setting"), e.args[0])
return
# set vcpus
guest.vcpus = int(self.get_config_virtual_cpus())
# disks
filesize = None
if self.get_config_disk_size() != None:
filesize = self.get_config_disk_size() / 1024.0
try:
d = virtinst.VirtualDisk(self.get_config_disk_image(), filesize, sparse = self.is_sparse_file())
if d.type == virtinst.VirtualDisk.TYPE_FILE and \
self.get_config_method() == VM_PARA_VIRT \
and virtinst.util.is_blktap_capable():
d.driver_name = virtinst.VirtualDisk.DRIVER_TAP
if d.type == virtinst.VirtualDisk.TYPE_FILE and not \
self.is_sparse_file():
self.non_sparse = True
else:
self.non_sparse = False
except ValueError, e:
self._validation_error_box(_("Invalid storage address"), e.args[0])
return
guest.disks.append(d)
# uuid
guest.uuid = virtinst.util.uuidToString(virtinst.util.randomUUID())
except ValueError, E:
self._validation_error_box(_("UUID Error"), str(e))
# network
net = self.get_config_network()
if net[0] == "bridge":
guest.nics.append(virtinst.VirtualNetworkInterface(type=net[0], bridge=net[1]))
elif net[0] == "network":
guest.nics.append(virtinst.VirtualNetworkInterface(type=net[0], network=net[1]))
elif net[0] == "user":
guest.nics.append(virtinst.VirtualNetworkInterface(type=net[0]))
else:
raise ValueError, "Unsupported networking type " + net[0]
try:
guest.disks.append(self._disk)
except ValueError, e:
self._validation_error_box(_("Error Setting up Disk"), str(e))
try:
guest.nics.append(self._net)
except ValueError, e:
self._validation_error_box(_("Error Setting up Network"), str(e))
# set up the graphics to use SDL
import keytable
@ -581,7 +533,7 @@ class vmmCreate(gobject.GObject):
"\n Memory: " + str(guest.memory) + \
"\n Max Memory: " + str(guest.maxmemory) + \
"\n # VCPUs: " + str(guest.vcpus) + \
"\n Filesize: " + str(filesize) + \
"\n Filesize: " + str(self._disk.size) + \
"\n Disk image: " + str(self.get_config_disk_image()) +\
"\n Non-sparse file: " + str(self.non_sparse))
@ -757,6 +709,12 @@ class vmmCreate(gobject.GObject):
self.window.get_widget("net-network").set_sensitive(False)
self.window.get_widget("net-device").set_sensitive(True)
def change_macaddr_use(self, ignore=None):
if self.window.get_widget("mac-address").get_active():
self.window.get_widget("create-mac-address").set_sensitive(True)
else:
self.window.get_widget("create-mac-address").set_sensitive(False)
def set_max_memory(self, src):
max_memory = src.get_adjustment().value
startup_mem_adjustment = self.window.get_widget("create-memory-startup").get_adjustment()
@ -765,68 +723,131 @@ class vmmCreate(gobject.GObject):
startup_mem_adjustment.upper = max_memory
def validate(self, page_num):
# Setting the values in the Guest/Disk/Network virtinst objects
# provides a lot of error checking for free, we just have to catch
# the messages
if page_num == PAGE_NAME:
name = self.window.get_widget("create-vm-name").get_text()
if len(name) > 50 or len(name) == 0:
self._validation_error_box(_("Invalid System Name"), \
_("System name must be non-blank and less than 50 characters"))
try:
self._guest.name = name
except ValueError, e:
self._validation_error_box(_("Invalid System Name"), str(e))
return False
if re.match("^[a-zA-Z0-9_]*$", name) == None:
self._validation_error_box(_("Invalid System Name"), \
_("System name may contain alphanumeric and '_' characters only"))
return False
elif page_num == PAGE_TYPE:
if self.get_config_method() == VM_FULLY_VIRT and self.connection.get_type().startswith("Xen") and not virtinst.util.is_hvm_capable():
self._validation_error_box(_("Hardware Support Required"), \
_("Your hardware does not appear to support full virtualization. Only paravirtualized guests will be available on this hardware."))
return False
# Set up appropriate guest object dependent on selected type
name = self._guest.name
if self.get_config_method() == VM_PARA_VIRT:
self._guest = virtinst.ParaVirtGuest(\
type=self.get_domain_type())
else:
self._guest = virtinst.FullVirtGuest(\
type=self.get_domain_type(), \
arch=self.get_domain_arch())
self._guest.name = name # Transfer name over
elif page_num == PAGE_FVINST:
if self.window.get_widget("media-iso-image").get_active():
src = self.get_config_install_source()
if src == None or len(src) == 0:
self._validation_error_box(_("ISO Path Required"), \
_("You must specify an ISO location for the guest installation"))
return False
elif not(os.path.exists(src)):
self._validation_error_box(_("ISO Path Not Found"), \
_("You must specify a valid path to the ISO image for guest installation"))
try:
self._guest.cdrom = src
except ValueError, e:
self._validation_error_box(_("ISO Path Not Found"), str(e))
return False
else:
cdlist = self.window.get_widget("cd-path")
if cdlist.get_active() == -1:
self._validation_error_box(_("Install media required"), \
_("You must select the CDROM install media for guest installation"))
return False
elif page_num == PAGE_PVINST:
src = self.get_config_install_source()
if src == None or len(src) == 0:
self._validation_error_box(_("URL Required"), \
_("You must specify a URL for the install image for the guest install"))
try:
self._guest.cdrom = src
except ValueError, e:
self._validation_error_box(_("CD-ROM Path Error"), str(e))
return False
try:
if self.get_config_os_type() is not None \
and self.get_config_os_type() != "generic":
logging.debug("OS Type: %s" % self.get_config_os_type())
self._guest.os_type = self.get_config_os_type()
except ValueError, e:
self._validation_error_box(_("Invalid FV OS Type"), str(e))
return False
try:
if self.get_config_os_variant() is not None \
and self.get_config_os_type() != "generic":
logging.debug("OS Variant: %s" % self.get_config_os_variant())
self._guest.os_variant = self.get_config_os_variant()
except ValueError, e:
self._validation_error_box(_("Invalid FV OS Variant"), str(e))
return False
elif page_num == PAGE_PVINST:
src = self.get_config_install_source()
try:
self._guest.location = src
except ValueError, e:
self._validation_error_box(_("Invalid Install URL"), str(e))
return False
ks = self.get_config_kickstart_source()
if ks is not None and len(ks) != 0:
if not (ks.startswith("http://") or ks.startswith("ftp://") \
or ks.startswith("nfs:")):
self._validation_error_box(_("Kickstart URL Error"), \
_("Kickstart location must be an NFS, HTTP or FTP source"))
return False
else:
self._guest.extraargs = "ks=%s" % (ks,)
elif page_num == PAGE_DISK:
disk = self.get_config_disk_image()
if disk == None or len(disk) == 0:
self._validation_error_box(_("Storage Address Required"), \
_("You must specify a partition or a file for storage for the guest install"))
return False
if not self.window.get_widget("storage-partition").get_active():
if os.path.isdir(disk):
self._validation_error_box(_("Storage Address Is Directory"), \
_("You chose 'Simple File' storage for your storage method, but chose a directory instead of a file. Please enter a new filename or choose an existing file."))
# Attempt to set disk
filesize = None
if self.get_config_disk_size() != None:
filesize = self.get_config_disk_size() / 1024.0
try:
if self.window.get_widget("storage-partition").get_active():
type = virtinst.VirtualDisk.TYPE_BLOCK
else:
type = virtinst.VirtualDisk.TYPE_FILE
self._disk = virtinst.VirtualDisk(\
self.get_config_disk_image(), \
filesize, \
sparse = self.is_sparse_file(), \
type=type)
if self._disk.type == virtinst.VirtualDisk.TYPE_FILE and \
self.get_config_method() == VM_PARA_VIRT and \
virtinst.util.is_blktap_capable():
self._disk.driver_name = virtinst.VirtualDisk.DRIVER_TAP
if self._disk.type == virtinst.VirtualDisk.TYPE_FILE and not \
self.is_sparse_file():
self.non_sparse = True
else:
self.non_sparse = False
except ValueError, e:
self._validation_error_box(_("Invalid Storage Address"), \
str(e))
return False
d = virtinst.VirtualDisk(self.get_config_disk_image(), self.get_config_disk_size(), sparse = self.is_sparse_file())
if d.is_conflict_disk(self.connection.vmm) is True:
res = self._yes_no_box(_('Disk "%s" is already in use by another guest!' % disk), \
_("Do you really want to use the disk ?"))
if self._disk.is_conflict_disk(self.connection.vmm) is True:
res = self._yes_no_box(_('Disk "%s" is already in use by another guest!' % disk), _("Do you really want to use the disk ?"))
return res
elif page_num == PAGE_NETWORK:
if self.window.get_widget("net-type-network").get_active():
if self.window.get_widget("net-network").get_active() == -1:
self._validation_error_box(_("Virtual Network Required"),
@ -838,7 +859,73 @@ class vmmCreate(gobject.GObject):
_("You must select one of the physical devices"))
return False
net = self.get_config_network()
if self.window.get_widget("mac-address").get_active():
mac = self.window.get_widget("create-mac-address").get_text()
if mac is None or len(mac) == 0:
self._validation_error_box(_("Invalid MAC address"), \
_("No MAC address was entered. Please enter a valid MAC address."))
return False
try:
self._guest.mac = mac
except ValueError, e:
self._validation_error_box(_("Invalid Mac address"), \
str(e))
return False
hostdevs = virtinst.util.get_host_network_devices()
for hostdev in hostdevs:
if mac.lower() == hostdev[4]:
return self._yes_no_box(_('MAC address "%s" is already in use by host!' % mac), _("Do you really want to use the MAC address ?"))
else:
mac = None
try:
if net[0] == "bridge":
self._net = virtinst.VirtualNetworkInterface(macaddr=mac, \
type=net[0], \
bridge=net[1])
elif net[0] == "network":
self._net = virtinst.VirtualNetworkInterface(macaddr=mac, \
type=net[0], \
network=net[1])
elif net[0] == "user":
self._net = virtinst.VirtualNetworkInterface(macaddr=mac, \
type=net[0])
except ValueError, e:
self._validation_error_box(_("Network Parameter Error"), \
str(e))
return False
vms = []
for domains in self.connection.vms.values():
vms.append(domains.vm)
if self._net.countMACaddr(vms) > 0:
return self._yes_no_box(_('MAC address "%s" is already in use by another guest!' % mac), _("Do you really want to use the MAC address ?"))
elif page_num == PAGE_CPUMEM:
# Set vcpus
try:
self._guest.vcpus = int(self.get_config_virtual_cpus())
except ValueError, e:
self._validation_error_box(_("VCPU Count Error"), \
str(e))
return False
# Set Memory
try:
self._guest.memory = int(self.get_config_initial_memory())
except ValueError, e:
self._validation_error_box(_("Memory Amount Error"), \
str(e))
return False
# Set Max Memory
try:
self._guest.maxmemory = int(self.get_config_maximum_memory())
except ValueError, e:
self._validation_error_box(_("Max Memory Amount Error"), \
str(e))
return False
# do this always, since there's no "leaving a notebook page" event.
self.window.get_widget("create-back").set_sensitive(True)
return True

View File

@ -364,8 +364,9 @@ class vmmDetails(gobject.GObject):
self.window.get_widget("state-host-cpus").set_text("%d" % self.vm.get_connection().host_active_processor_count())
status = self.vm.status()
if status in [ libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_CRASHED ]:
self.window.get_widget("config-vcpus").get_adjustment().upper = 32
self.window.get_widget("state-vm-maxvcpus").set_text("32")
cpu_max = self.vm.get_connection().get_max_vcpus()
self.window.get_widget("config-vcpus").get_adjustment().upper = cpu_max
self.window.get_widget("state-vm-maxvcpus").set_text(str(cpu_max))
else:
self.window.get_widget("config-vcpus").get_adjustment().upper = self.vm.vcpu_max_count()
self.window.get_widget("state-vm-maxvcpus").set_text("%d" % (self.vm.vcpu_max_count()))
@ -472,7 +473,7 @@ class vmmDetails(gobject.GObject):
vnic = None
if netinfo[0] == "bridge":
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], bridge=netinfo[1], macaddr=netinfo[3])
elif net[0] == "network":
elif netinfo[0] == "network":
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], network=netinfo[1], macaddr=netinfo[3])
else:
vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], macaddr=netinfo[3])

View File

@ -430,6 +430,7 @@ class vmmDomain(gobject.GObject):
return os.access(tty, os.R_OK | os.W_OK)
def get_graphics_console(self):
self.xml = None
type = self.get_xml_string("/domain/devices/graphics/@type")
port = None
if type == "vnc":
@ -456,23 +457,28 @@ class vmmDomain(gobject.GObject):
type = node.prop("type")
srcpath = None
devdst = None
devtype = node.prop("device")
if devtype == None:
devtype = "disk"
for child in node.children:
if child.name == "source":
if type == "file":
srcpath = child.prop("file")
elif type == "block":
srcpath = child.prop("dev")
elif type == None:
type = "-"
elif child.name == "target":
devdst = child.prop("dev")
if srcpath == None:
if devtype == "cdrom":
srcpath = "-"
type = "block"
else:
raise RuntimeError("missing source path")
if devdst == None:
raise RuntimeError("missing destination device")
devtype = node.prop("device")
if devtype == None:
devtype = "disk"
disks.append([type, srcpath, devtype, devdst])
finally:
@ -533,10 +539,13 @@ class vmmDomain(gobject.GObject):
def add_device(self, xml):
logging.debug("Adding device " + xml)
# get the XML for the live domain before we attach the device
# otherwise the device gets added to the XML twice.
vmxml = self.vm.XMLDesc(0)
if self.is_active():
self.vm.attachDevice(xml)
vmxml = self.vm.XMLDesc(0)
index = vmxml.find("</devices>")
newxml = vmxml[0:index] + xml + vmxml[index:]

View File

@ -171,6 +171,7 @@ class vmmManager(gobject.GObject):
"on_vm_open_clicked": self.open_vm_console,
"on_vm_new_clicked": self.show_vm_create,
"on_vm_delete_clicked": self.delete_vm,
"on_menu_edit_delete_activate" : self.delete_vm,
"on_menu_edit_details_activate": self.show_vm_details,
"on_menu_host_details_activate": self.show_host,

View File

@ -992,7 +992,7 @@
<child>
<widget class="GtkTable" id="table31">
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_rows">8</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
@ -1319,6 +1319,79 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="mac-address">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Set _fixed MAC address for this NIC?</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<signal name="clicked" handler="on_mac_address_clicked" last_modification_time="Wed, 16 May 2007 02:31:50 GMT"/>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label386">
<property name="visible">True</property>
<property name="label" translatable="yes">_MAC address:</property>
<property name="use_underline">True</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">create-mac-address</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="create-mac-address">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">17</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">•</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
@ -1597,7 +1670,7 @@
<widget class="GtkTable" id="summary-network">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_rows">4</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
@ -1742,6 +1815,62 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label387">
<property name="visible">True</property>
<property name="label" translatable="yes">MAC address:</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="summary-mac-address">
<property name="visible">True</property>
<property name="label" translatable="yes">-</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>

View File

@ -192,9 +192,22 @@
<child>
<widget class="GtkImageMenuItem" id="console_help">
<property name="visible">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_console_help_activate" last_modification_time="Mon, 19 Mar 2007 21:13:07 GMT"/>
<accelerator key="F1" modifiers="0" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image30">
<property name="visible">True</property>
<property name="stock">gtk-help</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>

View File

@ -3118,7 +3118,7 @@ mipsel</property>
<child>
<widget class="GtkTable" id="table31">
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_rows">8</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
@ -3445,6 +3445,79 @@ mipsel</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label385">
<property name="visible">True</property>
<property name="label" translatable="yes">_MAC address:</property>
<property name="use_underline">True</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">create-mac-address</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="mac-address">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Set _fixed MAC address for your virtual system?</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<signal name="clicked" handler="on_mac_address_clicked" last_modification_time="Tue, 15 May 2007 02:05:47 GMT"/>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="create-mac-address">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">17</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">•</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
@ -4225,7 +4298,7 @@ mipsel</property>
<widget class="GtkTable" id="table29">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="n_rows">16</property>
<property name="n_rows">17</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
@ -5038,6 +5111,62 @@ mipsel</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label386">
<property name="visible">True</property>
<property name="label" translatable="yes">MAC address:</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">16</property>
<property name="bottom_attach">17</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="summary-mac-address">
<property name="visible">True</property>
<property name="label" translatable="yes">-</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">16</property>
<property name="bottom_attach">17</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>

View File

@ -170,9 +170,22 @@
<child>
<widget class="GtkImageMenuItem" id="details_help">
<property name="visible">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_details_help_activate" last_modification_time="Fri, 16 Mar 2007 19:22:15 GMT"/>
<accelerator key="F1" modifiers="0" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image76">
<property name="visible">True</property>
<property name="stock">gtk-help</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>

View File

@ -52,7 +52,7 @@
<accelerator key="n" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image106">
<widget class="GtkImage" id="image118">
<property name="visible">True</property>
<property name="stock">gtk-new</property>
<property name="icon_size">1</property>
@ -75,7 +75,7 @@
<accelerator key="r" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image107">
<widget class="GtkImage" id="image119">
<property name="visible">True</property>
<property name="stock">gtk-open</property>
<property name="icon_size">1</property>
@ -102,7 +102,7 @@
<signal name="activate" handler="on_menu_file_open_connection_activate" last_modification_time="Mon, 12 Jun 2006 20:34:47 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image108">
<widget class="GtkImage" id="image120">
<property name="visible">True</property>
<property name="stock">gtk-connect</property>
<property name="icon_size">1</property>
@ -169,7 +169,7 @@
<signal name="activate" handler="on_menu_edit_details_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image109">
<widget class="GtkImage" id="image121">
<property name="visible">True</property>
<property name="stock">gtk-properties</property>
<property name="icon_size">1</property>
@ -190,7 +190,7 @@
<signal name="activate" handler="on_menu_edit_delete_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image110">
<widget class="GtkImage" id="image122">
<property name="visible">True</property>
<property name="stock">gtk-delete</property>
<property name="icon_size">1</property>
@ -317,9 +317,22 @@
<child>
<widget class="GtkImageMenuItem" id="menu_help">
<property name="visible">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_help_activate" last_modification_time="Thu, 08 Mar 2007 17:55:25 GMT"/>
<accelerator key="F1" modifiers="0" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image123">
<property name="visible">True</property>
<property name="stock">gtk-help</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>