def testNetworkValidation(self): network = virtinst.VirtualNetworkInterface(conn=testconn) self._testArgs(network, virtinst.VirtualNetworkInterface, 'network') # Test dynamic MAC/Bridge success try: network = virtinst.VirtualNetworkInterface() network.setup(testconn) except Exception, e: raise AssertionError( "Network setup with no params failed, expected success." + " Exception was: %s: %s" % (str(e), "".join(traceback.format_exc())))
def testAddRemoveDevices(self): guest, outfile = self._get_test_content("add-devices") # Basic removal of existing device rmdev = guest.get_devices("disk")[2] guest.remove_device(rmdev) # Basic device add guest.add_device(virtinst.VirtualWatchdog(conn)) # Test adding device with child properties (address value) adddev = virtinst.VirtualNetworkInterface(conn=conn) adddev.type = "network" adddev.source = "default" adddev.macaddr = "1A:2A:3A:4A:5A:6A" adddev.address.set_addrstr("spapr-vio") # Test adding and removing the same device guest.add_device(adddev) guest.remove_device(adddev) guest.add_device(adddev) # Test adding device built from parsed XML guest.add_device( virtinst.VirtualAudio(conn, parsexml="""<sound model='pcspk'/>""")) self._alter_compare(guest.get_xml_config(), outfile)
def parse_netdev_entry(conn, ifaces, fullkey, value): """ Parse a particular key/value for a network. Throws ValueError. """ ignore, ignore, inst, key = re.split("^(ethernet)([0-9]+).", fullkey) lvalue = value.lower() if key == "present" and lvalue == "false": return net = None for checkiface in ifaces: if getattr(checkiface, "vmx_inst") == inst: net = checkiface break if not net: net = virtinst.VirtualNetworkInterface(conn) setattr(net, "vmx_inst", inst) net.set_default_source() ifaces.append(net) if key == "virtualdev": # "vlance", "vmxnet", "e1000" if lvalue in ["e1000"]: net.model = lvalue if key == "addresstype" and lvalue == "generated": # Autogenerate a MAC address, the default pass if key == "address": # we ignore .generatedAddress for auto mode net.macaddr = lvalue return net, inst
def testDefaultBridge(self): # Test our handling of the default bridge routines origfunc = None try: from virtinst import deviceinterface origfunc = getattr(deviceinterface, "_default_bridge") def newbridge(ignore_conn): return "bzz0" setattr(deviceinterface, "_default_bridge", newbridge) dev1 = virtinst.VirtualNetworkInterface(_default_conn) dev1.macaddr = "22:22:33:44:55:66" dev2 = virtinst.VirtualNetworkInterface( _default_conn, parsexml=dev1.get_xml_config()) dev2.source = None dev2.source = "foobr0" dev2.macaddr = "22:22:33:44:55:67" dev3 = virtinst.VirtualNetworkInterface( _default_conn, parsexml=dev1.get_xml_config()) dev3.source = None dev3.macaddr = "22:22:33:44:55:68" utils.diff_compare( dev1.get_xml_config(), None, "<interface type=\"bridge\">\n" " <source bridge=\"bzz0\"/>\n" " <mac address=\"22:22:33:44:55:66\"/>\n" "</interface>\n") utils.diff_compare( dev2.get_xml_config(), None, "<interface type=\"bridge\">\n" " <source bridge=\"foobr0\"/>\n" " <mac address=\"22:22:33:44:55:67\"/>\n" "</interface>\n") utils.diff_compare( dev3.get_xml_config(), None, "<interface type=\"bridge\">\n" " <mac address=\"22:22:33:44:55:68\"/>\n" "</interface>\n") finally: if origfunc: from virtinst import deviceinterface setattr(deviceinterface, "_default_bridge", origfunc)
def testDefaultBridge(self): origfunc = None util = None try: util = getattr(virtinst, "util") origfunc = util.default_bridge def newbridge(ignore_conn): return "bzz0" util.default_bridge = newbridge dev1 = virtinst.VirtualNetworkInterface(utils.get_conn()) dev1.macaddr = "22:22:33:44:55:66" dev2 = virtinst.VirtualNetworkInterface( utils.get_conn(), parsexml=dev1.get_xml_config()) dev2.source = None dev2.source = "foobr0" dev2.macaddr = "22:22:33:44:55:67" dev3 = virtinst.VirtualNetworkInterface( utils.get_conn(), parsexml=dev1.get_xml_config()) dev3.source = None dev3.macaddr = "22:22:33:44:55:68" utils.diff_compare( dev1.get_xml_config(), None, "<interface type=\"bridge\">\n" " <source bridge=\"bzz0\"/>\n" " <mac address=\"22:22:33:44:55:66\"/>\n" "</interface>\n") utils.diff_compare( dev2.get_xml_config(), None, "<interface type=\"bridge\">\n" " <source bridge=\"foobr0\"/>\n" " <mac address=\"22:22:33:44:55:67\"/>\n" "</interface>\n") utils.diff_compare( dev3.get_xml_config(), None, "<interface type=\"bridge\">\n" " <mac address=\"22:22:33:44:55:68\"/>\n" "</interface>\n") finally: if util and origfunc: util.default_bridge = origfunc
def __init__(self, url = None): if url is None: url = get_default_url() logging.info("Connecting to libvirt: %s" % url) self.__url = None self.__conn = None self.open_connection(url) self.__capabilities = virtinst.CapabilitiesParser.parse(self.__conn.getCapabilities()) self.__net = virtinst.VirtualNetworkInterface(conn = self.__conn) self.__net.setup(self.__conn) (self.__new_guest, self.__new_domain) = virtinst.CapabilitiesParser.guest_lookup(conn = self.__conn)
def _setup_nics(self, config): self.__guest.nics = [] nic = virtinst.VirtualNetworkInterface(type = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL, bridge = config.get_network_bridge(), network = config.get_network_bridge(), macaddr = config.get_mac_address()) self.__guest.nics.append(nic) # ensure the network is running if config.get_network_bridge() not in self.__conn.listNetworks(): network = self.__conn.networkLookupByName(config.get_network_bridge()) network.create()
def testNetworkValidation(self): network = virtinst.VirtualNetworkInterface(conn=testconn) self._testArgs(network, virtinst.VirtualNetworkInterface, 'network') # Test MAC Address collision hostmac = virtinst.util.get_host_network_devices() if len(hostmac) is not 0: hostmac = hostmac[0][4] for params in ({'macaddr': hostmac}, ): network = virtinst.VirtualNetworkInterface(*(), **params) self.assertRaises(RuntimeError, network.setup, \ testconn) # Test dynamic MAC/Bridge success try: network = virtinst.VirtualNetworkInterface() network.setup(testconn) except Exception, e: raise AssertionError, \ "Network setup with no params failed, expected success." + \ " Exception was: %s: %s" % (str(e), "".join(traceback.format_exc()))
def testDefaultBridge(self): origfunc = None util = None try: i = utils.make_pxe_installer() g = utils.get_basic_fullyvirt_guest(installer=i) util = getattr(virtinst, "_util") origfunc = util.default_bridge2 def newbridge(ignore_conn): return ["bridge", "br0"] util.default_bridge2 = newbridge dev1 = virtinst.VirtualNetworkInterface(conn=g.conn) dev1.macaddr = "11:22:33:44:55:66" g.add_device(dev1) dev2 = virtinst.VirtualNetworkInterface(conn=g.conn, parsexml=dev1.get_xml_config()) dev2.source = None dev2.source = "foobr0" dev2.macaddr = "11:22:33:44:55:67" g.add_device(dev2) dev3 = virtinst.VirtualNetworkInterface(conn=g.conn, parsexml=dev1.get_xml_config()) dev3.source = None dev3.macaddr = "11:22:33:44:55:68" g.add_device(dev3) self._compare(g, "boot-default-bridge", False, do_create=False) dev3.type = dev3.TYPE_USER self._compare(g, None, False) finally: if util and origfunc: util.default_bridge2 = origfunc
def testAddRemoveDevices(self): infile = "tests/xmlparse-xml/add-devices-in.xml" outfile = "tests/xmlparse-xml/add-devices-out.xml" guest = virtinst.Guest(conn=conn, parsexml=file(infile).read()) rmdev = guest.get_devices("disk")[2] guest.remove_device(rmdev) adddev = virtinst.VirtualNetworkInterface(conn=conn, type="network", network="default", macaddr="1A:2A:3A:4A:5A:6A") guest.add_device(virtinst.VirtualWatchdog(conn)) guest.add_device(adddev) guest.remove_device(adddev) guest.add_device(adddev) self._alter_compare(guest.get_config_xml(), outfile)
def testAddRemoveDevices(self): guest, outfile = self._get_test_content("add-devices") rmdev = guest.get_devices("disk")[2] guest.remove_device(rmdev) adddev = virtinst.VirtualNetworkInterface(conn=conn) adddev.type = "network" adddev.source = "default" adddev.macaddr = "1A:2A:3A:4A:5A:6A" adddev.address.set_addrstr("spapr-vio") guest.add_device(virtinst.VirtualWatchdog(conn)) guest.add_device(adddev) guest.remove_device(adddev) guest.add_device(adddev) guest.add_device( virtinst.VirtualAudio(conn, parsexml="""<sound model='pcspk'/>""")) self._alter_compare(guest.get_xml_config(), outfile)
def _make_guest(installer=None, conn=None, os_variant=None): if conn is None: conn = _default_conn g = conn.caps.lookup_virtinst_guest() g.type = "kvm" g.name = "TestGuest" g.memory = int(200 * 1024) g.maxmemory = int(400 * 1024) g.uuid = "12345678-1234-1234-1234-123456789012" gdev = virtinst.VirtualGraphics(conn) gdev.type = "vnc" gdev.keymap = "ja" g.add_device(gdev) g.features.pae = False g.vcpus = 5 if not installer: installer = _make_installer(conn=conn) g.installer = installer g.emulator = "/usr/lib/xen/bin/qemu-dm" g.os.arch = "i686" g.os.os_type = "hvm" if os_variant: g.os_variant = os_variant g.add_default_input_device() g.add_default_console_device() g.add_device(virtinst.VirtualAudio(g.conn)) # Floppy disk path = "/dev/default-pool/testvol1.img" d = VirtualDisk(conn) d.path = path d.device = d.DEVICE_FLOPPY d.validate() g.add_device(d) # File disk path = "/dev/default-pool/new-test-suite.img" d = virtinst.VirtualDisk(conn) d.path = path if d.wants_storage_creation(): parent_pool = d.get_parent_pool() vol_install = virtinst.VirtualDisk.build_vol_install(conn, os.path.basename(path), parent_pool, .0000001, True) d.set_vol_install(vol_install) d.validate() g.add_device(d) # Block disk path = "/dev/disk-pool/diskvol1" d = virtinst.VirtualDisk(conn) d.path = path d.validate() g.add_device(d) # Network device dev = virtinst.VirtualNetworkInterface(conn) dev.macaddr = "22:22:33:44:55:66" dev.type = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL dev.source = "default" g.add_device(dev) return g
def get_virtual_network(): dev = virtinst.VirtualNetworkInterface(conn=_conn) dev.macaddr = "11:22:33:44:55:66" dev.type = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL dev.network = "default" return dev
class vmmNetworkList(object): def __init__(self, conn): self.conn = conn # self._warn_list = None self._network_model = None self._selected_network = None self._netbridge_name = None self._net_source_mode_model = None self._selected_net_source_mode = None self._net_portgroup_model = None self._selected_net_portgroup = None # self._vport_type = None self._vport_managerid = None self._vport_typeid = None self._vport_idver = None self._vport_instid = None self._init() def _cleanup(self): try: self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) except: pass self.conn = None ########################## # Initialization methods # ########################## def _init(self): self._warn_list = [] self._init_network_model() self._init_net_portgroup_model() def _init_network_model(self): self._network_model = [] def _init_net_portgroup_model(self): self._net_portgroup_model = [] def _get_network_model(self): return self._network_model def _get_net_portgroup_model(self): return self._net_portgroup_model def _add_warn(self, warn): self._warn_list.append(warn) def _pretty_network_desc(self, nettype, source=None, netobj=None): if nettype == virtinst.VirtualNetworkInterface.TYPE_USER: return _("Usermode networking") extra = None if nettype == virtinst.VirtualNetworkInterface.TYPE_BRIDGE: ret = _("Bridge") elif nettype == virtinst.VirtualNetworkInterface.TYPE_VIRTUAL: ret = _("Virtual network") if netobj: extra = ": %s" % netobj.pretty_forward_mode() else: ret = nettype.capitalize() if source: ret += " '%s'" % source if extra: ret += " %s" % extra return ret def _build_source_row(self, nettype, source_name, label, is_sensitive, is_running, manual_bridge=False, key=None): return [nettype, source_name, label, is_sensitive, is_running, manual_bridge, key] def _find_virtual_networks(self): rows = [] vnet_bridges = [] default_label = None for net in self.conn.list_nets(): nettype = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL label = self._pretty_network_desc(nettype, net.get_name(), net) if not net.is_active(): label += " (%s)" % _("Inactive") if net.get_name() == "default": default_label = label rows.append(self._build_source_row( nettype, net.get_name(), label, True, net.is_active(), key=net.get_connkey())) # Build a list of vnet bridges, so we know not to list them # in the physical interface list vnet_bridge = net.get_bridge_device() if vnet_bridge: vnet_bridges.append(vnet_bridge) if not rows: label = _("No virtual networks available") rows.append(self._build_source_row( None, None, label, False, False)) return rows, vnet_bridges, default_label def _find_physical_devices(self, vnet_bridges): rows = [] can_default = False default_label = None skip_ifaces = ["lo"] vnet_taps = [] for vm in self.conn.list_vms(): for nic in vm.get_network_devices(refresh_if_nec=False): if nic.target_dev and nic.target_dev not in vnet_taps: vnet_taps.append(nic.target_dev) netdevs = {} for iface in self.conn.list_interfaces(): netdevs[iface.get_name()] = [ iface.get_name(), iface.is_bridge(), iface.get_slave_names()] for nodedev in self.conn.filter_nodedevs("net"): if nodedev.xmlobj.interface not in netdevs: netdevs[nodedev.xmlobj.interface] = [nodedev.xmlobj.interface, False, []] # For every bridge used by a virtual network, and any slaves of # those devices, don't list them. for vnet_bridge in vnet_bridges: slave_names = netdevs.pop(vnet_bridge, [None, None, []])[2] for slave in slave_names: netdevs.pop(slave, None) for name, is_bridge, slave_names in netdevs.values(): if ((name in vnet_taps) or (name in [v + "-nic" for v in vnet_bridges]) or (name in skip_ifaces)): # Don't list this, as it is basically duplicating # virtual net info continue sensitive = True source_name = name label = _("Host device %s") % (name) if is_bridge: nettype = virtinst.VirtualNetworkInterface.TYPE_BRIDGE if slave_names: extra = (_("Host device %s") % slave_names[0]) can_default = True else: extra = _("Empty bridge") label = _("Bridge %s: %s") % (name, extra) elif self.conn.check_support( self.conn.SUPPORT_CONN_DIRECT_INTERFACE): nettype = virtinst.VirtualNetworkInterface.TYPE_DIRECT label += (": %s" % _("macvtap")) else: nettype = None sensitive = False source_name = None label += (": %s" % _("Not bridged")) if can_default and not default_label: default_label = label rows.append(self._build_source_row( nettype, source_name, label, sensitive, True, key=name)) return rows, default_label def _populate_network_model(self): model = self._network_model def _add_manual_bridge_row(): manual_row = self._build_source_row( None, None, _("Specify shared device name"), True, False, manual_bridge=True) model.append(manual_row) if self.conn.is_qemu_session(): nettype = virtinst.VirtualNetworkInterface.TYPE_USER r = self._build_source_row( nettype, None, self._pretty_network_desc(nettype), True, True) model.append(r) _add_manual_bridge_row() return (vnets, vnet_bridges, default_net) = self._find_virtual_networks() (iface_rows, default_bridge) = self._find_physical_devices( vnet_bridges) # Sorting is: # 1) Bridges # 2) Virtual networks # 3) direct/macvtap # 4) Disabled list entries # Each category sorted alphabetically bridges = [row for row in iface_rows if row[0] == "bridge"] direct = [row for row in iface_rows if row[0] == "direct"] disabled = [row for row in iface_rows if row[0] is None] for rows in [bridges, vnets, direct, disabled]: rows.sort(key=lambda r: r[2]) for row in rows: model.append(row) # If there is a bridge device, default to that # If not, use 'default' network # If not present, use first list entry # If list empty, use no network devices label = default_bridge or default_net default = 0 if not len(model): row = self._build_source_row( None, None, _("No networking"), True, False) model.insert(0, row) default = 0 elif label: default = [idx for idx in range(len(model)) if model[idx][2] == label][0] _add_manual_bridge_row() return default ############### # Public APIs # ############### def get_network_row(self): if self._selected_network is not None: return self._network_model[self._selected_network] def get_network_selection(self): bridge_entry = self._netbridge_name row = self.get_network_row() if not row: return None, None, None, None net_type = row[0] net_src = row[1] net_check_bridge = row[5] if net_check_bridge and bridge_entry is not None: net_type = virtinst.VirtualNetworkInterface.TYPE_BRIDGE net_src = bridge_entry mode = None if self._selected_net_source_mode is not None: mode = self._selected_net_source_mode portgroup = None if self._selected_net_portgroup is not None: portgroup = self._selected_net_portgroup return net_type, net_src, mode, portgroup or None def get_vport(self): return (self._vport_type, self._vport_managerid, self._vport_typeid, self._vport_idver, self._vport_instid) def validate_network(self, macaddr, model=None): nettype, devname, mode, portgroup = self.get_network_selection() if nettype is None: return None net = None # Make sure VirtualNetwork is running netobj = None if nettype == virtinst.VirtualNetworkInterface.TYPE_VIRTUAL: for net in self.conn.list_nets(): if net.get_name() == devname: netobj = net break if netobj and not netobj.is_active(): # Try to start the network try: netobj.start() logging.info("Started network '%s'", devname) except Exception, e: return _("Could not start virtual network '%s': %s" % (devname, str(e))) # Create network device try: net = virtinst.VirtualNetworkInterface(self.conn.get_backend()) net.type = nettype net.source = devname net.macaddr = macaddr net.model = model net.source_mode = mode net.portgroup = portgroup if net.model == "spapr-vlan": net.address.set_addrstr("spapr-vio") if net.type == "direct": (vport_type, vport_managerid, vport_typeid, vport_idver, vport_instid) = self.get_vport() net.virtualport.type = vport_type or None net.virtualport.managerid = vport_managerid or None net.virtualport.typeid = vport_typeid or None net.virtualport.typeidversion = vport_idver or None net.virtualport.instanceid = vport_instid or None except Exception, e: return _("Error with network parameters.") + str(e)
def _import_file(doc, ctx, conn, input_file): ignore = doc def xpath_str(path): ret = ctx.xpathEval(path) result = None if ret is not None: if type(ret) == list: if len(ret) >= 1: result = ret[0].content else: result = ret return result def bool_val(val): if str(val).lower() == "false": return False elif str(val).lower() == "true": return True return False def xpath_nodechildren(path): # Return the children of the first node found by the xpath nodes = ctx.xpathEval(path) if not nodes: return [] return node_list(nodes[0]) def _lookup_disk_path(path): fmt = "vmdk" ref = None def _path_has_prefix(prefix): if path.startswith(prefix): return path[len(prefix):] if path.startswith("ovf:" + prefix): return path[len("ovf:" + prefix):] return False if _path_has_prefix("/disk/"): disk_ref = _path_has_prefix("/disk/") xpath = (_make_section_xpath(envbase, "DiskSection") + "/ovf:Disk[@ovf:diskId='%s']" % disk_ref) if not ctx.xpathEval(xpath): raise ValueError( _("Unknown disk reference id '%s' " "for path %s.") % (path, disk_ref)) ref = xpath_str(xpath + "/@ovf:fileRef") elif _path_has_prefix("/file/"): ref = _path_has_prefix("/file/") else: raise ValueError(_("Unknown storage path type %s." % path)) xpath = (envbase + "/ovf:References/ovf:File[@ovf:id='%s']" % ref) if not ctx.xpathEval(xpath): raise ValueError( _("Unknown reference id '%s' " "for path %s.") % (ref, path)) return xpath_str(xpath + "/@ovf:href"), fmt is_ovirt_format = False envbase = "/ovf:Envelope[1]" vsbase = envbase + "/ovf:VirtualSystem" if not ctx.xpathEval(vsbase): vsbase = envbase + "/ovf:Content[@xsi:type='ovf:VirtualSystem_Type']" is_ovirt_format = True def _make_section_xpath(base, section_name): if is_ovirt_format: return (base + "/ovf:Section[@xsi:type='ovf:%s_Type']" % section_name) return base + "/ovf:%s" % section_name osbase = _make_section_xpath(vsbase, "OperatingSystemSection") vhstub = _make_section_xpath(vsbase, "VirtualHardwareSection") if not ctx.xpathEval(vsbase): raise RuntimeError("Did not find any VirtualSystem section") if not ctx.xpathEval(vhstub): raise RuntimeError("Did not find any VirtualHardwareSection") vhbase = vhstub + "/ovf:Item[rasd:ResourceType='%s']" # General info name = xpath_str(vsbase + "/ovf:Name") desc = xpath_str(vsbase + "/ovf:AnnotationSection/ovf:Annotation") if not desc: desc = xpath_str(vsbase + "/ovf:Description") vcpus = xpath_str((vhbase % DEVICE_CPU) + "/rasd:VirtualQuantity") sockets = xpath_str((vhbase % DEVICE_CPU) + "/rasd:num_of_sockets") cores = xpath_str((vhbase % DEVICE_CPU) + "/rasd:num_of_cores") mem = xpath_str((vhbase % DEVICE_MEMORY) + "/rasd:VirtualQuantity") alloc_mem = xpath_str((vhbase % DEVICE_MEMORY) + "/rasd:AllocationUnits") os_id = xpath_str(osbase + "/@id") os_version = xpath_str(osbase + "/@version") # This is the VMWare OS name os_vmware = xpath_str(osbase + "/@osType") logging.debug("OS parsed as: id=%s version=%s vmware=%s", os_id, os_version, os_vmware) # Sections that we handle # NetworkSection is ignored, since I don't have an example of # a valid section in the wild. parsed_sections = [ "References", "DiskSection", "NetworkSection", "VirtualSystem" ] # Check for unhandled 'required' sections for env_node in xpath_nodechildren(envbase): if env_node.name in parsed_sections: continue elif env_node.isText(): continue logging.debug("Unhandled XML section '%s'", env_node.name) if not bool_val(env_node.prop("required")): continue raise StandardError( _("OVF section '%s' is listed as " "required, but parser doesn't know " "how to handle it.") % env_node.name) disk_buses = {} for node in ctx.xpathEval(vhbase % DEVICE_IDE_BUS): instance_id = _get_child_content(node, "InstanceID") disk_buses[instance_id] = "ide" for node in ctx.xpathEval(vhbase % DEVICE_SCSI_BUS): instance_id = _get_child_content(node, "InstanceID") disk_buses[instance_id] = "scsi" ifaces = [] for node in ctx.xpathEval(vhbase % DEVICE_ETHERNET): iface = virtinst.VirtualNetworkInterface(conn) # XXX: Just ignore 'source' info and choose the default net_model = _get_child_content(node, "ResourceSubType") if net_model and not net_model.isdigit(): iface.model = net_model.lower() iface.set_default_source() ifaces.append(iface) disks = [] for node in ctx.xpathEval(vhbase % DEVICE_DISK): bus_id = _get_child_content(node, "Parent") path = _get_child_content(node, "HostResource") bus = disk_buses.get(bus_id, "ide") fmt = "raw" if path: path, fmt = _lookup_disk_path(path) disk = virtinst.VirtualDisk(conn) disk.path = path disk.driver_type = fmt disk.bus = bus disk.device = "disk" disks.append(disk) # XXX: Convert these OS values to something useful ignore = os_version ignore = os_id ignore = os_vmware (capsguest, capsdomain) = conn.caps.guest_lookup() guest = conn.caps.build_virtinst_guest(conn, capsguest, capsdomain) guest.installer = virtinst.ImportInstaller(conn) if not name: name = os.path.basename(input_file) guest.name = name.replace(" ", "_") guest.description = desc or None if vcpus: guest.vcpus = int(vcpus) elif sockets or cores: if sockets: guest.cpu.sockets = int(sockets) if cores: guest.cpu.cores = int(cores) guest.cpu.vcpus_from_topology() if mem: guest.memory = _convert_alloc_val(alloc_mem, mem) * 1024 for dev in ifaces + disks: guest.add_device(dev) return guest
def start_install(name=None, ram=None, disks=None, mac=None, uuid=None, extra=None, vcpus=None, profile_data=None, arch=None, no_gfx=False, fullvirt=True, bridge=None, virt_type=None, virt_auto_boot=False, qemu_driver_type=None, qemu_net_type=None): vtype = "qemu" if virtinst.util.is_kvm_capable(): vtype = "kvm" arch = None # let virtinst.FullVirtGuest() default to the host arch elif virtinst.util.is_kqemu_capable(): vtype = "kqemu" print "- using qemu hypervisor, type=%s" % vtype if arch is not None and arch.lower() in ["x86", "i386"]: arch = "i686" guest = virtinst.FullVirtGuest(hypervisorURI="qemu:///system", type=vtype, arch=arch) if not profile_data.has_key("file"): # images don't need to source this if not profile_data.has_key("install_tree"): raise koan.InfoException( "Cannot find install source in kickstart file, aborting.") if not profile_data["install_tree"].endswith("/"): profile_data["install_tree"] = profile_data["install_tree"] + "/" # virt manager doesn't like nfs:// and just wants nfs: # (which cobbler should fix anyway) profile_data["install_tree"] = profile_data["install_tree"].replace( "nfs://", "nfs:") if profile_data.has_key("file"): # this is an image based installation input_path = profile_data["file"] print "- using image location %s" % input_path if input_path.find(":") == -1: # this is not an NFS path guest.cdrom = input_path else: (tempdir, filename) = utils.nfsmount(input_path) guest.cdrom = os.path.join(tempdir, filename) kickstart = profile_data.get("kickstart", "") if kickstart != "": # we have a (windows?) answer file we have to provide # to the ISO. print "I want to make a floppy for %s" % kickstart floppy_path = utils.make_floppy(kickstart) guest.disks.append( virtinst.VirtualDisk(device=virtinst.VirtualDisk.DEVICE_FLOPPY, path=floppy_path)) else: guest.location = profile_data["install_tree"] extra = extra.replace("&", "&") guest.extraargs = extra if profile_data.has_key("breed"): breed = profile_data["breed"] if breed != "other" and breed != "": if breed in ["ubuntu", "debian", "redhat"]: guest.set_os_type("linux") elif breed == "suse": guest.set_os_type("linux") # SUSE requires the correct arch to find # kernel+initrd on the inst-source /boot/<arch>/loader/... guest.arch = profile_data["arch"] if guest.arch in ["i386", "i486", "i586"]: guest.arch = "i686" elif breed in ["windows"]: guest.set_os_type("windows") else: guest.set_os_type("unix") if profile_data.has_key("os_version"): # FIXME: when os_version is not defined and it's linux, do we use generic24/generic26 ? if breed == "ubuntu": # If breed is Ubuntu, need to set the version to the type of "ubuntu<version>" # as defined by virtinst. (i.e. ubuntunatty) version = "ubuntu%s" % profile_data["os_version"] else: version = profile_data["os_version"] if version != "other" and version != "": try: guest.set_os_variant(version) except: print "- virtinst library does not understand variant %s, treating as generic" % version pass guest.set_name(name) guest.set_memory(ram) guest.set_vcpus(vcpus) guest.set_autostart(virt_auto_boot) # for KVM, we actually can't disable this, since it's the only # console it has other than SDL guest.set_graphics("vnc") if uuid is not None: guest.set_uuid(uuid) for d in disks: print "- adding disk: %s of size %s (driver type=%s)" % (d[0], d[1], d[2]) if d[1] != 0 or d[0].startswith("/dev"): vdisk = virtinst.VirtualDisk(d[0], size=d[1], bus=qemu_driver_type) try: vdisk.set_driver_type(d[2]) except: print "- virtinst failed to create the VirtualDisk with the specified driver type (%s), using whatever it defaults to instead" % d[ 2] guest.disks.append(vdisk) else: raise koan.InfoException( "this virtualization type does not work without a disk image, set virt-size in Cobbler to non-zero" ) if profile_data.has_key("interfaces"): counter = 0 interfaces = profile_data["interfaces"].keys() interfaces.sort() vlanpattern = re.compile("[a-zA-Z0-9]+\.[0-9]+") for iname in interfaces: intf = profile_data["interfaces"][iname] if intf["interface_type"] in ("master", "bond", "bridge") or vlanpattern.match( iname) or iname.find(":") != -1: continue mac = intf["mac_address"] if mac == "": mac = random_mac() if bridge is None: profile_bridge = profile_data["virt_bridge"] intf_bridge = intf["virt_bridge"] if intf_bridge == "": if profile_bridge == "": raise koan.InfoException( "virt-bridge setting is not defined in cobbler") intf_bridge = profile_bridge else: if bridge.find(",") == -1: intf_bridge = bridge else: bridges = bridge.split(",") intf_bridge = bridges[counter] nic_obj = virtinst.VirtualNetworkInterface(macaddr=mac, bridge=intf_bridge, model=qemu_net_type) guest.nics.append(nic_obj) counter = counter + 1 else: if bridge is not None: profile_bridge = bridge else: profile_bridge = profile_data["virt_bridge"] if profile_bridge == "": raise koan.InfoException( "virt-bridge setting is not defined in cobbler") nic_obj = virtinst.VirtualNetworkInterface(macaddr=random_mac(), bridge=profile_bridge, model=qemu_net_type) guest.nics.append(nic_obj) guest.start_install() return "use virt-manager and connect to qemu to manage guest: %s" % name
def _import_file(conn, input_file): """ Parse the OVF file and generate a virtinst.Guest object from it """ root = xml.etree.ElementTree.parse(input_file).getroot() vsnode = _find(root, "./ovf:VirtualSystem") vhnode = _find(vsnode, "./ovf:VirtualHardwareSection") # General info name = _text(vsnode.find("./ovf:Name", OVF_NAMESPACES)) desc = _text( vsnode.find("./ovf:AnnotationSection/ovf:Annotation", OVF_NAMESPACES)) if not desc: desc = _text(vsnode.find("./ovf:Description", OVF_NAMESPACES)) vhxpath = "./ovf:Item[rasd:ResourceType='%s']" vcpus = _text( _find(vhnode, (vhxpath % DEVICE_CPU) + "/rasd:VirtualQuantity")) mem = _text( _find(vhnode, (vhxpath % DEVICE_MEMORY) + "/rasd:VirtualQuantity")) alloc_mem = _text( _find(vhnode, (vhxpath % DEVICE_MEMORY) + "/rasd:AllocationUnits")) # Sections that we handle # NetworkSection is ignored, since I don't have an example of # a valid section in the wild. parsed_sections = [ "References", "DiskSection", "NetworkSection", "VirtualSystem" ] # Check for unhandled 'required' sections for env_node in root.findall("./"): if any([p for p in parsed_sections if p in env_node.tag]): continue logging.debug("Unhandled XML section '%s'", env_node.tag) if not _convert_bool_val(env_node.attrib.get("required")): continue raise Exception( _("OVF section '%s' is listed as " "required, but parser doesn't know " "how to handle it.") % env_node.name) disk_buses = {} for node in _findall(vhnode, vhxpath % DEVICE_IDE_BUS): instance_id = _text(_find(node, "rasd:InstanceID")) disk_buses[instance_id] = "ide" for node in _findall(vhnode, vhxpath % DEVICE_SCSI_BUS): instance_id = _text(_find(node, "rasd:InstanceID")) disk_buses[instance_id] = "scsi" ifaces = [] for node in _findall(vhnode, vhxpath % DEVICE_ETHERNET): iface = virtinst.VirtualNetworkInterface(conn) # Just ignore 'source' info for now and choose the default net_model = _text(_find(node, "rasd:ResourceSubType")) if net_model and not net_model.isdigit(): iface.model = net_model.lower() iface.set_default_source() ifaces.append(iface) disks = [] for node in _findall(vhnode, vhxpath % DEVICE_DISK): bus_id = _text(_find(node, "rasd:Parent")) path = _text(_find(node, "rasd:HostResource")) bus = disk_buses.get(bus_id, "ide") fmt = "raw" if path: path = _lookup_disk_path(root, path) fmt = "vmdk" disk = virtinst.VirtualDisk(conn) disk.path = path disk.driver_type = fmt disk.bus = bus disk.device = "disk" disks.append(disk) # Generate the Guest guest = conn.caps.lookup_virtinst_guest() guest.installer = virtinst.ImportInstaller(conn) if not name: name = os.path.basename(input_file) guest.name = name.replace(" ", "_") guest.description = desc or None if vcpus: guest.vcpus = int(vcpus) if mem: guest.memory = _convert_alloc_val(alloc_mem, mem) * 1024 for dev in ifaces + disks: guest.add_device(dev) return guest
class vmmNetworkList(vmmGObjectUI): __gsignals__ = { "changed": (GObject.SignalFlags.RUN_FIRST, None, []), "changed-vport": (GObject.SignalFlags.RUN_FIRST, None, []) } def __init__(self, conn, builder, topwin): vmmGObjectUI.__init__(self, "netlist.ui", None, builder=builder, topwin=topwin) self.conn = conn self.builder.connect_signals({ "on_net_source_changed": self._on_net_source_changed, "on_net_source_mode_changed": self._emit_changed, "on_net_portgroup_changed": self._emit_changed, "on_net_bridge_name_changed": self._emit_changed, "on_vport_type_changed": self._emit_vport_changed, "on_vport_managerid_changed": self._emit_vport_changed, "on_vport_typeid_changed": self._emit_vport_changed, "on_vport_typeidversion_changed": self._emit_vport_changed, "on_vport_instanceid_changed": self._emit_vport_changed, }) self._init_ui() self.top_label = self.widget("net-source-label") self.top_box = self.widget("net-source-box") self.top_vport = self.widget("vport-expander") def _cleanup(self): try: self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) self.conn.disconnect_by_func(self._repopulate_network_list) except: pass self.conn = None ########################## # Initialization methods # ########################## def _init_ui(self): # [ network type, source name, label, sensitive?, net is active, # manual bridge, net instance] model = Gtk.ListStore(str, str, str, bool, bool, bool, object) combo = self.widget("net-source") combo.set_model(model) text = Gtk.CellRendererText() combo.pack_start(text, True) combo.add_attribute(text, 'text', 2) combo.add_attribute(text, 'sensitive', 3) combo = self.widget("net-source-mode") # [xml value, label] model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) model.append(["bridge", "Bridge"]) model.append(["vepa", "VEPA"]) model.append(["private", "Private"]) model.append(["passthrough", "Passthrough"]) combo.set_active(0) combo = self.widget("net-portgroup") # [xml value, label] model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.set_combo_text_column(combo, 1) self.conn.connect("net-added", self._repopulate_network_list) self.conn.connect("net-removed", self._repopulate_network_list) self.conn.connect("interface-added", self._repopulate_network_list) self.conn.connect("interface-removed", self._repopulate_network_list) def _pretty_network_desc(self, nettype, source=None, netobj=None): if nettype == virtinst.VirtualNetworkInterface.TYPE_USER: return _("Usermode networking") extra = None if nettype == virtinst.VirtualNetworkInterface.TYPE_BRIDGE: ret = _("Bridge") elif nettype == virtinst.VirtualNetworkInterface.TYPE_VIRTUAL: ret = _("Virtual network") if netobj: extra = ": %s" % netobj.pretty_forward_mode() else: ret = nettype.capitalize() if source: ret += " '%s'" % source if extra: ret += " %s" % extra return ret def _build_source_row(self, nettype, source_name, label, is_sensitive, is_running, manual_bridge=False, key=None): return [ nettype, source_name, label, is_sensitive, is_running, manual_bridge, key ] def _find_virtual_networks(self): rows = [] vnet_bridges = [] default_label = None for net in self.conn.list_nets(): nettype = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL label = self._pretty_network_desc(nettype, net.get_name(), net) if not net.is_active(): label += " (%s)" % _("Inactive") if net.get_name() == "default": default_label = label rows.append( self._build_source_row(nettype, net.get_name(), label, True, net.is_active(), key=net.get_connkey())) # Build a list of vnet bridges, so we know not to list them # in the physical interface list vnet_bridge = net.get_bridge_device() if vnet_bridge: vnet_bridges.append(vnet_bridge) if not rows: label = _("No virtual networks available") rows.append(self._build_source_row(None, None, label, False, False)) return rows, vnet_bridges, default_label def _find_physical_devices(self, vnet_bridges): rows = [] can_default = False default_label = None skip_ifaces = ["lo"] vnet_taps = [] for vm in self.conn.list_vms(): for nic in vm.get_network_devices(refresh_if_nec=False): if nic.target_dev and nic.target_dev not in vnet_taps: vnet_taps.append(nic.target_dev) netdevs = {} for iface in self.conn.list_interfaces(): netdevs[iface.get_name()] = [ iface.get_name(), iface.is_bridge(), iface.get_slave_names() ] for nodedev in self.conn.get_nodedevs("net"): if nodedev.interface not in netdevs: netdevs[nodedev.interface] = [nodedev.interface, False, []] # For every bridge used by a virtual network, and any slaves of # those devices, don't list them. for vnet_bridge in vnet_bridges: slave_names = netdevs.pop(vnet_bridge, [None, None, []])[2] for slave in slave_names: netdevs.pop(slave, None) for name, is_bridge, slave_names in netdevs.values(): if ((name in vnet_taps) or (name in [v + "-nic" for v in vnet_bridges]) or (name in skip_ifaces)): # Don't list this, as it is basically duplicating # virtual net info continue sensitive = True source_name = name label = _("Host device %s") % (name) if is_bridge: nettype = virtinst.VirtualNetworkInterface.TYPE_BRIDGE if slave_names: extra = ("(%s)" % _("Host device %s") % slave_names[0]) can_default = True else: extra = _("(Empty bridge)") label = _("Bridge %s %s") % (name, extra) elif self.conn.check_support( self.conn.SUPPORT_CONN_DIRECT_INTERFACE): nettype = virtinst.VirtualNetworkInterface.TYPE_DIRECT label += (": %s" % _("macvtap")) else: nettype = None sensitive = False source_name = None label += (" (%s)" % _("Not bridged")) if can_default and not default_label: default_label = label rows.append( self._build_source_row(nettype, source_name, label, sensitive, True, key=name)) return rows, default_label def _populate_network_list(self): net_list = self.widget("net-source") model = net_list.get_model() model.clear() # For qemu:///session if self.conn.is_qemu_session(): nettype = virtinst.VirtualNetworkInterface.TYPE_USER r = self._build_source_row(nettype, None, self._pretty_network_desc(nettype), True, True) model.append(r) net_list.set_active(0) return (vnets, vnet_bridges, default_net) = self._find_virtual_networks() (iface_rows, default_bridge) = self._find_physical_devices(vnet_bridges) # Sorting is: # 1) Bridges # 2) Virtual networks # 3) direct/macvtap # 4) Disabled list entries # Each category sorted alphabetically bridges = [row for row in iface_rows if row[0] == "bridge"] direct = [row for row in iface_rows if row[0] == "direct"] disabled = [row for row in iface_rows if row[0] is None] for rows in [bridges, vnets, direct, disabled]: rows.sort(key=lambda r: r[2]) for row in rows: model.append(row) # If there is a bridge device, default to that # If not, use 'default' network # If not present, use first list entry # If list empty, use no network devices label = default_bridge or default_net default = 0 if not len(model): row = self._build_source_row(None, None, _("No networking"), True, False) model.insert(0, row) default = 0 elif label: default = [ idx for idx in range(len(model)) if model[idx][2] == label ][0] # After all is said and done, add a manual bridge option manual_row = self._build_source_row(None, None, _("Specify shared device name"), True, False, manual_bridge=True) model.append(manual_row) net_list.set_active(default) ############### # Public APIs # ############### def get_network_row(self): return uiutil.get_list_selection(self.widget("net-source"), None) def get_network_selection(self): bridge_entry = self.widget("net-bridge-name") row = self.get_network_row() if not row: return None, None, None, None net_type = row[0] net_src = row[1] net_check_bridge = row[5] if net_check_bridge and bridge_entry: net_type = virtinst.VirtualNetworkInterface.TYPE_BRIDGE net_src = bridge_entry.get_text() mode = None if self.widget("net-source-mode").is_visible(): mode = uiutil.get_combo_entry(self.widget("net-source-mode"), 0) portgroup = None if self.widget("net-portgroup").is_visible(): portgroup = uiutil.get_combo_entry(self.widget("net-portgroup"), 0) return net_type, net_src, mode, portgroup def get_vport(self): vport_type = self.widget("vport-type").get_text() vport_managerid = self.widget("vport-managerid").get_text() vport_typeid = self.widget("vport-typeid").get_text() vport_idver = self.widget("vport-typeidversion").get_text() vport_instid = self.widget("vport-instanceid").get_text() return (vport_type, vport_managerid, vport_typeid, vport_idver, vport_instid) def validate_network(self, macaddr, model=None): nettype, devname, mode, portgroup = self.get_network_selection() if nettype is None: return None net = None # Make sure VirtualNetwork is running netobj = None if nettype == virtinst.VirtualNetworkInterface.TYPE_VIRTUAL: for net in self.conn.list_nets(): if net.get_name() == devname: netobj = net break if netobj and not netobj.is_active(): res = self.err.yes_no( _("Virtual Network is not active."), _("Virtual Network '%s' is not active. " "Would you like to start the network " "now?") % devname) if not res: return False # Try to start the network try: netobj.start() netobj.tick() logging.info("Started network '%s'", devname) except Exception, e: return self.err.show_err( _("Could not start virtual network " "'%s': %s") % (devname, str(e))) # Create network device try: net = virtinst.VirtualNetworkInterface(self.conn.get_backend()) net.type = nettype net.source = devname net.macaddr = macaddr net.model = model net.source_mode = mode net.portgroup = portgroup if net.model == "spapr-vlan": net.address.set_addrstr("spapr-vio") if net.type == "direct": (vport_type, vport_managerid, vport_typeid, vport_idver, vport_instid) = self.get_vport() net.virtualport.type = vport_type or None net.virtualport.managerid = vport_managerid or None net.virtualport.typeid = vport_typeid or None net.virtualport.typeidversion = vport_idver or None net.virtualport.instanceid = vport_instid or None except Exception, e: return self.err.val_err(_("Error with network parameters."), e)
def validate_network(self, macaddr, model=None): nettype, devname, mode, portgroup = self.get_network_selection() if nettype is None: return None net = None # Make sure VirtualNetwork is running netobj = None if nettype == virtinst.VirtualNetworkInterface.TYPE_VIRTUAL: for net in self.conn.list_nets(): if net.get_name() == devname: netobj = net break if netobj and not netobj.is_active(): res = self.err.yes_no( _("Virtual Network is not active."), _("Virtual Network '%s' is not active. " "Would you like to start the network " "now?") % devname) if not res: return False # Try to start the network try: netobj.start() logging.info("Started network '%s'", devname) except Exception as e: return self.err.show_err( _("Could not start virtual network " "'%s': %s") % (devname, str(e))) # Create network device try: net = virtinst.VirtualNetworkInterface(self.conn.get_backend()) net.type = nettype net.source = devname net.macaddr = macaddr net.model = model net.source_mode = mode net.portgroup = portgroup if net.model == "spapr-vlan": net.address.set_addrstr("spapr-vio") if net.type == "direct": (vport_type, vport_managerid, vport_typeid, vport_idver, vport_instid) = self.get_vport() net.virtualport.type = vport_type or None net.virtualport.managerid = vport_managerid or None net.virtualport.typeid = vport_typeid or None net.virtualport.typeidversion = vport_idver or None net.virtualport.instanceid = vport_instid or None except Exception as e: return self.err.val_err(_("Error with network parameters."), e) # Make sure there is no mac address collision isfatal, errmsg = net.is_conflict_net(net.conn, net.macaddr) if isfatal: return self.err.val_err(_("Mac address collision."), errmsg) elif errmsg is not None: retv = self.err.yes_no( _("Mac address collision."), _("%s Are you sure you want to use this address?") % errmsg) if not retv: return False return net