host: Allow renaming virtual networks

This commit is contained in:
Cole Robinson 2013-09-29 12:14:00 -04:00
parent 74e8fff069
commit 369a17160a
6 changed files with 131 additions and 86 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.15.4 on Fri Sep 27 14:12:46 2013 -->
<!-- Generated with glade 3.16.0 on Sun Sep 29 11:40:23 2013 -->
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkAccelGroup" id="accelgroup1"/>
@ -715,7 +715,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">DNS Domain:</property>
<property name="label" translatable="yes">Domain:</property>
<property name="use_markup">True</property>
</object>
<packing>
@ -726,18 +726,29 @@
</packing>
</child>
<child>
<object class="GtkLabel" id="net-name">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">&lt;b&gt;Name&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="selectable">True</property>
<property name="label" translatable="yes">Name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="net-name">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="changed" handler="on_net_name_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>

View File

@ -716,46 +716,12 @@ class vmmConnection(vmmGObject):
# Libvirt object creation methods #
###################################
def create_network(self, xml, start=True, autostart=True):
# Define network
net = self._backend.networkDefineXML(xml)
def restore(self, frm):
self._backend.restore(frm)
try:
if start:
net.create()
net.setAutostart(autostart)
os.remove(frm)
except:
net.undefine()
raise
return net
def rename_vm(self, domainobj, origxml, newxml):
# Undefine old domain
domainobj.delete()
newobj = None
try:
try:
# Redefine new domain
newobj = self.define_domain(newxml)
except Exception, renameerr:
try:
logging.exception("Error defining new name XML")
newobj = self.define_domain(origxml)
except Exception, fixerr:
logging.exception("Failed to redefine original domain!")
raise RuntimeError(
_("Domain rename failed. Attempting to recover also "
"failed.\n\n"
"Original error: %s\n\n"
"Recover error: %s" %
(str(renameerr), str(fixerr))))
raise
finally:
if newobj:
# Reinsert handle into new domain
domainobj.change_name_backend(newobj)
logging.debug("Couldn't remove save file '%s' for restore", frm)
def define_domain(self, xml):
return self._backend.defineXML(xml)
@ -766,13 +732,53 @@ class vmmConnection(vmmGObject):
def define_interface(self, xml):
return self._backend.interfaceDefineXML(xml, 0)
def restore(self, frm):
self._backend.restore(frm)
def create_network(self, xml, start=True, autostart=True):
net = self.define_network(xml)
try:
os.remove(frm)
if start:
net.create()
net.setAutostart(autostart)
except:
logging.debug("Couldn't remove save file '%s' used for restore",
frm)
net.undefine()
raise
return net
def _rename_helper(self, objtype, define_cb, obj, origxml, newxml):
# Undefine the original object
obj.delete()
newobj = None
try:
try:
# Redefine new domain
newobj = define_cb(newxml)
except Exception, renameerr:
try:
logging.exception("Error defining new name %s XML",
objtype)
newobj = define_cb(origxml)
except Exception, fixerr:
logging.exception("Failed to redefine original %s!",
objtype)
raise RuntimeError(
_("%s rename failed. Attempting to recover also "
"failed.\n\n"
"Original error: %s\n\n"
"Recover error: %s" %
(objtype, str(renameerr), str(fixerr))))
raise
finally:
if newobj:
# Reinsert handle into new obj
obj.change_name_backend(newobj)
def rename_vm(self, obj, origxml, newxml):
return self._rename_helper("domain", self.define_domain,
obj, origxml, newxml)
def rename_network(self, obj, origxml, newxml):
return self._rename_helper("network", self.define_network,
obj, origxml, newxml)
####################

View File

@ -328,10 +328,6 @@ class vmmDomain(vmmLibvirtObject):
def status(self):
return self.lastStatus
def change_name_backend(self, newbackend):
# Used for changing the domain object after a rename
self._backend = newbackend
def get_cloning(self):
return self.cloning
def set_cloning(self, val):
@ -399,29 +395,10 @@ class vmmDomain(vmmLibvirtObject):
# Persistent XML change APIs #
##############################
# Rename
def define_name(self, newname):
# Do this, so that _xmlobj_to_define has original inactive XML
self._invalidate_xml()
guest = self._get_xmlobj_to_define()
if guest.name == newname:
return
if self.is_active():
raise RuntimeError(_("Cannot rename an active guest"))
logging.debug("Changing guest name to '%s'", newname)
origxml = guest.get_xml_config()
guest.name = newname
newxml = guest.get_xml_config()
try:
self.conn.rename_vm(self, origxml, newxml)
finally:
self._invalidate_xml()
self.emit("config-changed")
return self._define_name_helper("domain",
self.conn.rename_vm,
newname)
# Device Add/Remove
def add_device(self, devobj):

View File

@ -43,6 +43,9 @@ from virtManager.graphwidgets import Sparkline
INTERFACE_PAGE_INFO = 0
INTERFACE_PAGE_ERROR = 1
(EDIT_NET_NAME,
EDIT_NET_AUTOSTART) = range(2)
class vmmHost(vmmGObjectUI):
__gsignals__ = {
@ -70,6 +73,8 @@ class vmmHost(vmmGObjectUI):
self.volmenu = None
self._in_refresh = False
self.net_active_edits = []
self.cpu_usage_graph = None
self.memory_usage_graph = None
self.init_conn_state()
@ -91,9 +96,11 @@ class vmmHost(vmmGObjectUI):
"on_net_delete_clicked": self.delete_network,
"on_net_stop_clicked": self.stop_network,
"on_net_start_clicked": self.start_network,
"on_net_autostart_toggled": self.net_autostart_changed,
"on_net_apply_clicked": self.net_apply,
"on_net_list_changed": self.net_selected,
"on_net_autostart_toggled": self.net_autostart_changed,
"on_net_name_changed": (lambda *x:
self.enable_net_apply(x, EDIT_NET_NAME)),
"on_pool_add_clicked" : self.add_pool,
"on_vol_add_clicked" : self.add_vol,
@ -462,19 +469,34 @@ class vmmHost(vmmGObjectUI):
logging.debug("Applying changes for network '%s'", net.get_name())
try:
auto = self.widget("net-autostart").get_active()
net.set_autostart(auto)
if EDIT_NET_AUTOSTART in self.net_active_edits:
auto = self.widget("net-autostart").get_active()
net.set_autostart(auto)
if EDIT_NET_NAME in self.net_active_edits:
net.define_name(self.widget("net-name").get_text())
self.repopulate_networks()
except Exception, e:
self.err.show_err(_("Error setting net autostart: %s") % str(e))
return
finally:
self.disable_net_apply()
def disable_net_apply(self):
self.net_active_edits = []
self.widget("net-apply").set_sensitive(False)
def enable_net_apply(self, *arglist):
edittype = arglist[-1]
self.widget("net-apply").set_sensitive(True)
if edittype not in self.net_active_edits:
self.net_active_edits.append(edittype)
def net_autostart_changed(self, src_ignore):
auto = self.widget("net-autostart").get_active()
self.widget("net-autostart").set_label(auto and
_("On Boot") or
_("Never"))
self.widget("net-apply").set_sensitive(True)
self.enable_net_apply(EDIT_NET_AUTOSTART)
def current_network(self):
sel = self.widget("net-list").get_selection()
@ -516,7 +538,7 @@ class vmmHost(vmmGObjectUI):
try:
net = self.conn.get_net(selected[0].get_value(selected[1], 0))
except KeyError:
self.widget("net-apply").set_sensitive(False)
self.disable_net_apply()
return
except Exception, e:
logging.exception(e)
@ -527,8 +549,8 @@ class vmmHost(vmmGObjectUI):
except Exception, e:
logging.exception(e)
self.set_net_error_page(_("Error selecting network: %s") % e)
self.widget("net-apply").set_sensitive(False)
finally:
self.disable_net_apply()
def _populate_net_ipv4_state(self, net):
(netstr,
@ -592,8 +614,8 @@ class vmmHost(vmmGObjectUI):
active = net.is_active()
self.widget("net-details").set_sensitive(True)
self.widget("net-name").set_markup(
"<b>Network %s:</b>" % net.get_name())
self.widget("net-name").set_text(net.get_name())
self.widget("net-name").set_editable(not active)
self.widget("net-device").set_text(net.get_bridge_device() or "")
self.widget("net-name-domain").set_text(net.get_name_domain() or "")
uihelpers.set_grid_row_visible(self.widget("net-name-domain"),
@ -643,7 +665,7 @@ class vmmHost(vmmGObjectUI):
self.widget("net-ipv6-route").set_text("")
self.widget("net-ipv6-forwarding").set_text(
_("Isolated network"))
self.widget("net-apply").set_sensitive(False)
self.disable_net_apply()
def repopulate_networks(self, src_ignore=None, uuid_ignore=None):
self.populate_networks(self.widget("net-list").get_model())

View File

@ -78,6 +78,30 @@ class vmmLibvirtObject(vmmGObject):
def get_key(self):
return self._key
def change_name_backend(self, newbackend):
# Used for changing the backing object after a rename
self._backend = newbackend
def _define_name_helper(self, objtype, rename_cb, newname):
oldname = self.get_xmlobj().name
self._invalidate_xml()
xmlobj = self._get_xmlobj_to_define()
if xmlobj.name == newname:
return
logging.debug("Changing %s name from %s to %s",
objtype, oldname, newname)
origxml = xmlobj.get_xml_config()
xmlobj.name = newname
newxml = xmlobj.get_xml_config()
try:
rename_cb(self, origxml, newxml)
finally:
self._invalidate_xml()
self.emit("config-changed")
#############################################################
# Functions that should probably be overridden in sub class #

View File

@ -107,6 +107,11 @@ class vmmNetwork(vmmLibvirtObject):
def tick(self):
self._set_active(self._backend_get_active())
def define_name(self, newname):
return self._define_name_helper("network",
self.conn.rename_network,
newname)
###############
# XML parsing #