# # Copyright (C) 2009 Red Hat, Inc. # Copyright (C) 2009 Cole Robinson # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA. # from virtinst import Interface from virtinst import util from virtManager.libvirtobject import vmmLibvirtObject class vmmInterface(vmmLibvirtObject): def __init__(self, conn, backend, key): vmmLibvirtObject.__init__(self, conn, backend, key) self._name = key self._active = True self._xml = None self._xml_flags = None (self._inactive_xml_flags, self._active_xml_flags) = self.conn.get_interface_flags( self._backend) self._support_isactive = None self.tick() self.refresh_xml() # Routines from vmmLibvirtObject def _XMLDesc(self, flags): return self._backend.XMLDesc(flags) def _define(self, xml): return self.conn.define_interface(xml) def xpath(self, *args, **kwargs): # Must use this function for ALL XML parsing ret = util.xpath(self.get_xml(), *args, **kwargs) if ret: return ret if not self.is_active(): return ret # The running config did not have the info requested return util.xpath(self.get_xml(inactive=True), *args, **kwargs) def set_active(self, state): if state == self._active: return self.idle_emit(state and "started" or "stopped") self._active = state self.refresh_xml() def _backend_get_active(self): ret = True if self._support_isactive is None: self._support_isactive = self.conn.check_interface_support( self._backend, self.conn.SUPPORT_INTERFACE_ISACTIVE) if not self._support_isactive: return True return bool(self._backend.isActive()) def tick(self): self.set_active(self._backend_get_active()) def is_active(self): return self._active def get_name(self): return self._name def get_mac(self): return self.xpath("/interface/mac/@address") def _kick_conn(self): self.conn.schedule_priority_tick(polliface=True) def start(self): self._backend.create(0) self.idle_add(self.refresh_xml) self._kick_conn() def stop(self): self._backend.destroy(0) self.idle_add(self.refresh_xml) self._kick_conn() def delete(self): self._backend.undefine() self._kick_conn() def is_bridge(self): typ = self.get_type() return typ == "bridge" def get_type(self): return self.xpath("/interface/@type") def get_pretty_type(self): itype = self.get_type() if itype == Interface.Interface.INTERFACE_TYPE_VLAN: return "VLAN" elif itype: return str(itype).capitalize() else: return "Interface" def get_startmode(self): return self.xpath("/interface/start/@mode") or "none" def set_startmode(self, newmode): def set_start_xml(doc, ctx): node = ctx.xpathEval("/interface/start[1]") node = (node and node[0] or None) iface_node = ctx.xpathEval("/interface")[0] if not node: node = iface_node.newChild(None, "start", None) node.setProp("mode", newmode) return doc.serialize() self._redefine(util.xml_parse_wrapper, set_start_xml) def get_slaves(self): typ = self.get_type() xpath = "/interface/%s/interface/@name" % typ def node_func(ctx): nodes = ctx.xpathEval(xpath) names = [x.content for x in nodes] ret = [] for name in names: type_path = ("/interface/%s/interface[@name='%s']/@type" % (typ, name)) nodes = ctx.xpathEval(type_path) ret.append((name, nodes and nodes[0].content or "Unknown")) return ret ret = self.xpath(func=node_func) if not ret: return [] return ret def get_slave_names(self): # Returns a list of names of all enslaved interfaces return [x[0] for x in self.get_slaves()] def get_ipv4(self): base_xpath = "/interface/protocol[@family='ipv4']" if not self.xpath(base_xpath): return [] dhcp = bool(self.xpath("count(%s/dhcp)" % base_xpath)) addr = self.xpath(base_xpath + "/ip/@address") if addr: prefix = self.xpath(base_xpath + "/ip[@address='%s']/@prefix" % addr) if prefix: addr += "/%s" % prefix return [dhcp, addr] def get_ipv6(self): base_xpath = "/interface/protocol[@family='ipv6']" if not self.xpath(base_xpath): return [] dhcp = bool(self.xpath("count(%s/dhcp)" % base_xpath)) autoconf = bool(self.xpath("count(%s/autoconf)" % base_xpath)) def addr_func(ctx): nodes = ctx.xpathEval(base_xpath + "/ip") nodes = nodes or [] ret = [] for node in nodes: addr = node.prop("address") pref = node.prop("prefix") if not addr: continue if pref: addr += "/%s" % pref ret.append(addr) return ret ret = self.xpath(func=addr_func) return [dhcp, autoconf, ret] def get_protocol_xml(self): def protocol(ctx): node = ctx.xpathEval("/interface/protocol") node = node and node[0] or None ret = None if node: ret = node.serialize() return ret ret = self.xpath(func=protocol) if ret: ret = " %s\n" % ret return ret def _redefine(self, xml_func, *args): """ Helper function for altering a redefining VM xml @param xml_func: Function to alter the running XML. Takes the original XML as its first argument. @param args: Extra arguments to pass to xml_func """ origxml = self._xml_to_redefine() # Sanitize origxml to be similar to what we will get back origxml = util.xml_parse_wrapper(origxml, lambda d, c: d.serialize()) newxml = xml_func(origxml, *args) self._redefine_xml(newxml)