Create a network with a device pool containing all the VFs of an SR-IOV device. Signed-off-by: Lin Ma <lma@xxxxxxxx> --- tests/xmlparse-xml/network-vf-pool-in.xml | 5 + tests/xmlparse-xml/network-vf-pool-out.xml | 6 ++ tests/xmlparse.py | 21 ++++ ui/createnet.ui | 92 ++++++++++++++++- virtManager/createnet.py | 153 ++++++++++++++++++++--------- virtinst/network.py | 12 +++ 6 files changed, 240 insertions(+), 49 deletions(-) create mode 100644 tests/xmlparse-xml/network-vf-pool-in.xml create mode 100644 tests/xmlparse-xml/network-vf-pool-out.xml diff --git a/tests/xmlparse-xml/network-vf-pool-in.xml b/tests/xmlparse-xml/network-vf-pool-in.xml new file mode 100644 index 0000000..821aa07 --- /dev/null +++ b/tests/xmlparse-xml/network-vf-pool-in.xml @@ -0,0 +1,5 @@ +<network> + <name>passthrough</name> + <forward mode="hostdev" managed="yes"> + </forward> +</network> diff --git a/tests/xmlparse-xml/network-vf-pool-out.xml b/tests/xmlparse-xml/network-vf-pool-out.xml new file mode 100644 index 0000000..62a7305 --- /dev/null +++ b/tests/xmlparse-xml/network-vf-pool-out.xml @@ -0,0 +1,6 @@ +<network> + <name>new-foo</name> + <forward mode="hostdev" managed="yes"> + <pf dev="eth3"/> + </forward> +</network> diff --git a/tests/xmlparse.py b/tests/xmlparse.py index a7fe5dd..b8beebf 100644 --- a/tests/xmlparse.py +++ b/tests/xmlparse.py @@ -1293,6 +1293,27 @@ class XMLParseTest(unittest.TestCase): utils.diff_compare(net.get_xml_config(), outfile) utils.test_create(conn, net.get_xml_config(), "networkDefineXML") + def testNetVfPool(self): + basename = "network-vf-pool" + infile = "tests/xmlparse-xml/%s-in.xml" % basename + outfile = "tests/xmlparse-xml/%s-out.xml" % basename + net = virtinst.Network(conn, parsexml=file(infile).read()) + + check = self._make_checker(net) + check("name", "passthrough", "new-foo") + + check = self._make_checker(net.forward) + check("mode", "hostdev") + check("managed", "yes") + + r = net.forward.add_pf() + r.dev = "eth3" + check = self._make_checker(r) + check("dev", "eth3") + + utils.diff_compare(net.get_xml_config(), outfile) + utils.test_create(conn, net.get_xml_config(), "networkDefineXML") + ############## # Misc tests # diff --git a/ui/createnet.ui b/ui/createnet.ui index 161056b..7bbd326 100644 --- a/ui/createnet.ui +++ b/ui/createnet.ui @@ -1091,6 +1091,94 @@ <property name="can_focus">False</property> <property name="spacing">6</property> <child> + <object class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="left_padding">15</property> + <child> + <object class="GtkBox" id="box14"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkRadioButton" id="net-sriov-vfs-pool"> + <property name="label" translatable="yes">_Pool containing all of VFs of a SR-IOV device</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="valign">start</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">net-forward-dev</property> + <signal name="toggled" handler="on_net_forward_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment8"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="left_padding">25</property> + <child> + <object class="GtkGrid" id="table36"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">4</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkLabel" id="label393"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Device _List:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">net-forward</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="pf-list"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> <object class="GtkLabel" id="label205"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -1103,7 +1191,7 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> @@ -1354,7 +1442,7 @@ <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> diff --git a/virtManager/createnet.py b/virtManager/createnet.py index 9fdbc45..2154df1 100644 --- a/virtManager/createnet.py +++ b/virtManager/createnet.py @@ -120,6 +120,12 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("header").modify_bg(Gtk.StateType.NORMAL, blue) # [ label, dev name ] + pf_list = self.widget("pf-list") + pf_model = Gtk.ListStore(str, str) + pf_list.set_model(pf_model) + uiutil.init_combo_text_column(pf_list, 0) + + # [ label, dev name ] fw_list = self.widget("net-forward") fw_model = Gtk.ListStore(str, str) fw_list.set_model(fw_model) @@ -167,6 +173,9 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-enable-ipv6-networking").set_active(False) + pf_model = self.widget("pf-list").get_model() + pf_model.clear() + fw_model = self.widget("net-forward").get_model() fw_model.clear() fw_model.append([_("Any physical device"), None]) @@ -181,6 +190,26 @@ class vmmCreateNetwork(vmmGObjectUI): for name in devnames: fw_model.append([_("Physical device %s") % name, name]) + devprettynames = [] + ifnames = [] + for pcidev in self.conn.filter_nodedevs("pci"): + if pcidev.xmlobj.capability_type == "virt_functions": + devdesc = pcidev.xmlobj.pretty_name() + for netdev in self.conn.filter_nodedevs("net"): + if pcidev.xmlobj.name == netdev.xmlobj.parent: + ifname = netdev.xmlobj.interface + devprettyname = "%s (%s)" % (ifname, devdesc) + devprettynames.append(devprettyname) + ifnames.append(ifname) + break + if not devprettynames: + pf_model.append([_("No available device"), None]) + else: + for devprettyname, ifname in zip(devprettynames, ifnames): + pf_model.append([_("%s") % devprettyname, ifname]) + + self.widget("pf-list").set_active(0) + self.widget("net-forward").set_active(0) self.widget("net-forward-mode").set_active(0) self.widget("net-forward-none").set_active(True) @@ -223,6 +252,11 @@ class vmmCreateNetwork(vmmGObjectUI): return self._get_network_helper("net-dhcpv6-end") def get_config_forwarding(self): + if self.widget("net-sriov-vfs-pool").get_active(): + name = uiutil.get_list_selection(self.widget("pf-list"), column=1) + mode = "hostdev" + return [name, mode] + if self.widget("net-forward-none").get_active(): return [None, None] @@ -481,10 +515,27 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("create-finish").grab_focus() def change_forward_type(self, ignore): - skip_fwd = self.widget("net-forward-none").get_active() + index = self.widget("pf-list").get_active() + model = self.widget("pf-list").get_model() + item = model[index] + if item[0] == "No available device": + sriov_capable = False + else: + sriov_capable = True + self.widget("net-sriov-vfs-pool").set_sensitive(sriov_capable) + vf_pool = self.widget("net-sriov-vfs-pool").get_active() + if not vf_pool: + skip_fwd = self.widget("net-forward-none").get_active() + + self.widget("net-forward-mode").set_sensitive(not skip_fwd) + self.widget("net-forward").set_sensitive(not skip_fwd) + else: + self.widget("net-forward-mode").set_sensitive(False) + self.widget("net-forward").set_sensitive(False) - self.widget("net-forward-mode").set_sensitive(not skip_fwd) - self.widget("net-forward").set_sensitive(not skip_fwd) + self.widget("table36").set_sensitive(vf_pool) + self.widget("box13").set_sensitive(not vf_pool) + self.widget("hbox6").set_sensitive(not vf_pool) def change_ipv4_enable(self, ignore): enabled = self.get_config_ipv4_enable() @@ -676,56 +727,64 @@ class vmmCreateNetwork(vmmGObjectUI): net = self._build_xmlstub() net.name = self.widget("net-name").get_text() - net.domain_name = self.widget("net-domain-name").get_text() or None - - if self.widget("net-enable-ipv6-networking").get_active(): - net.ipv6 = True dev, mode = self.get_config_forwarding() if mode: net.forward.mode = mode net.forward.dev = dev or None - if self.get_config_ipv4_enable(): - ip = self.get_config_ip4() - ipobj = net.add_ip() - ipobj.address = str(ip.network + 1) - ipobj.netmask = str(ip.netmask) - - if self.get_config_dhcpv4_enable(): - dhcpobj = ipobj.add_range() - dhcpobj.start = str(self.get_config_dhcpv4_start().network) - dhcpobj.end = str(self.get_config_dhcpv4_end().network) - - if self.get_config_ipv6_enable(): - ip = self.get_config_ip6() - ipobj = net.add_ip() - ipobj.family = "ipv6" - ipobj.address = str(ip.network + 1) - ipobj.prefix = str(ip.prefixlen) - - if self.get_config_dhcpv6_enable(): - dhcpobj = ipobj.add_range() - dhcpobj.start = str(self.get_config_dhcpv6_start().network) - dhcpobj.end = str(self.get_config_dhcpv6_end().network) - - netaddr = _make_ipaddr(self.get_config_routev4_network()) - gwaddr = _make_ipaddr(self.get_config_routev4_gateway()) - if netaddr and gwaddr: - route = net.add_route() - route.family = "ipv4" - route.address = netaddr.network - route.prefix = netaddr.prefixlen - route.gateway = gwaddr.network - - netaddr = _make_ipaddr(self.get_config_routev6_network()) - gwaddr = _make_ipaddr(self.get_config_routev6_gateway()) - if netaddr and gwaddr: - route = net.add_route() - route.family = "ipv6" - route.address = netaddr.network - route.prefix = netaddr.prefixlen - route.gateway = gwaddr.network + if net.forward.mode == "hostdev": + net.forward.managed = "yes" + pfobj = net.forward.add_pf() + pfobj.dev = net.forward.dev + net.forward.dev = None + net.domain_name = None + else: + net.domain_name = self.widget("net-domain-name").get_text() or None + + if self.widget("net-enable-ipv6-networking").get_active(): + net.ipv6 = True + + if self.get_config_ipv4_enable(): + ip = self.get_config_ip4() + ipobj = net.add_ip() + ipobj.address = str(ip.network + 1) + ipobj.netmask = str(ip.netmask) + + if self.get_config_dhcpv4_enable(): + dhcpobj = ipobj.add_range() + dhcpobj.start = str(self.get_config_dhcpv4_start().network) + dhcpobj.end = str(self.get_config_dhcpv4_end().network) + + if self.get_config_ipv6_enable(): + ip = self.get_config_ip6() + ipobj = net.add_ip() + ipobj.family = "ipv6" + ipobj.address = str(ip.network + 1) + ipobj.prefix = str(ip.prefixlen) + + if self.get_config_dhcpv6_enable(): + dhcpobj = ipobj.add_range() + dhcpobj.start = str(self.get_config_dhcpv6_start().network) + dhcpobj.end = str(self.get_config_dhcpv6_end().network) + + netaddr = _make_ipaddr(self.get_config_routev4_network()) + gwaddr = _make_ipaddr(self.get_config_routev4_gateway()) + if netaddr and gwaddr: + route = net.add_route() + route.family = "ipv4" + route.address = netaddr.network + route.prefix = netaddr.prefixlen + route.gateway = gwaddr.network + + netaddr = _make_ipaddr(self.get_config_routev6_network()) + gwaddr = _make_ipaddr(self.get_config_routev6_gateway()) + if netaddr and gwaddr: + route = net.add_route() + route.family = "ipv6" + route.address = netaddr.network + route.prefix = netaddr.prefixlen + route.gateway = gwaddr.network return net diff --git a/virtinst/network.py b/virtinst/network.py index 457afa0..dfc1436 100644 --- a/virtinst/network.py +++ b/virtinst/network.py @@ -72,11 +72,23 @@ class _NetworkRoute(XMLBuilder): netmask = XMLProperty("./@netmask") +class _NetworkForwardPf(XMLBuilder): + _XML_ROOT_NAME = "pf" + dev = XMLProperty("./@dev") + + class _NetworkForward(XMLBuilder): _XML_ROOT_NAME = "forward" mode = XMLProperty("./@mode") dev = XMLProperty("./@dev") + managed = XMLProperty("./@managed") + pf = XMLChildProperty(_NetworkForwardPf) + + def add_pf(self): + r = _NetworkForwardPf(self.conn) + self.add_child(r) + return r def pretty_desc(self): return Network.pretty_forward_desc(self.mode, self.dev) -- 2.9.2 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list