[libvirt] [PATCH 0/2] Two vhostuser improvements
by Michal Privoznik
*** BLURB HERE ***
Michal Privoznik (2):
virsh: Accept iface alias for domifstats too
qemu: Query for vhostuser iface names at runtime
src/qemu/qemu_command.c | 4 +++
src/qemu/qemu_domain.c | 20 ++++---------
src/qemu/qemu_driver.c | 6 ++--
src/util/virnetdevopenvswitch.c | 1 +
tests/Makefile.am | 7 -----
tests/qemuxml2xmlmock.c | 33 ----------------------
.../qemuxml2xmlout-net-vhostuser.xml | 2 --
tests/qemuxml2xmltest.c | 2 +-
tools/virsh-domain-monitor.c | 3 +-
9 files changed, 18 insertions(+), 60 deletions(-)
delete mode 100644 tests/qemuxml2xmlmock.c
--
2.13.0
7 years, 5 months
[libvirt] [PATCH go-xml] Add support for Node Device with basic testing.
by Vladik Romanovsky
---
node_device.go | 310 +++++++++++++++++++++++++++++++++++++++++++++++
node_device_test.go | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 647 insertions(+)
create mode 100644 node_device.go
create mode 100644 node_device_test.go
diff --git a/node_device.go b/node_device.go
new file mode 100644
index 0000000..cc40451
--- /dev/null
+++ b/node_device.go
@@ -0,0 +1,310 @@
+/*
+ * This file is part of the libvirt-go-xml project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ */
+
+package libvirtxml
+
+import (
+ "encoding/xml"
+)
+
+type NodeDevice struct {
+ Name string `xml:"name"`
+ Path string `xml:"path,omitempty"`
+ Parent string `xml:"parent,omitempty"`
+ Driver string `xml:"driver>name,omitempty"`
+ Capability interface{} `xml:"capability"`
+}
+
+type NodeDeviceVendor struct {
+ ID string `xml:"id,attr,omitempty"`
+ Name string `xml:",chardata"`
+}
+type NodeDeviceProduct struct {
+ ID string `xml:"id,attr,omitempty"`
+ Name string `xml:",chardata"`
+}
+
+type NodeDevicePciExpress struct {
+ Links []NodeDevicePciExpressLink `xml:"link"`
+}
+
+type NodeDevicePciExpressLink struct {
+ Validity string `xml:"validity,attr,omitempty"`
+ Speed float64 `xml:"speed,attr,omitempty"`
+ Port int `xml:"port,attr,omitempty"`
+ Width int `xml:"width,attr,omitempty"`
+}
+
+type NodeDeviceIOMMUGroup struct {
+ Number int `xml:"number,attr"`
+}
+
+type NodeDeviceNUMA struct {
+ Node int `xml:"node,attr"`
+}
+
+type NodeDevicePCIAddress struct {
+ Domain string `xml:"domain,attr"`
+ Bus string `xml:"bus,attr"`
+ Slot string `xml:"slot,attr"`
+ Function string `xml:"function,attr"`
+}
+
+type NodeDeviceSystemHardware struct {
+ Vendor string `xml:"vendor"`
+ Version string `xml:"version"`
+ Serial string `xml:"serial"`
+ UUID string `xml:"uuid"`
+}
+
+type NodeDeviceSystemFirmware struct {
+ Vendor string `xml:"vendor"`
+ Version string `xml:"version"`
+ ReleaseDate string `xml:"release_date"`
+}
+
+type NodeDeviceNetOffloadFeatures struct {
+ Name string `xml:"name,attr"`
+}
+
+type NodeDeviceNetLink struct {
+ State string `xml:"state,attr"`
+ Speed string `xml:"speed,attr,omitempty"`
+}
+
+type NodeDevicePciCapability struct {
+ Domain int `xml:"domain,omitempty"`
+ Bus int `xml:"bus,omitempty"`
+ Slot int `xml:"slot,omitempty"`
+ Function int `xml:"function,omitempty"`
+ Product *NodeDeviceProduct `xml:"product,omitempty"`
+ Vendor *NodeDeviceVendor `xml:"vendor,omitempty"`
+ IommuGroup *NodeDeviceIOMMUGroup `xml:"iommuGroup,omitempty"`
+ Numa *NodeDeviceNUMA `xml:"numa,omitempty"`
+ PciExpress *NodeDevicePciExpress `xml:"pci-express,omitempty"`
+ Capability []NodeDeviceNestedPciCapability `xml:"capability,omitempty"`
+}
+
+type NodeDeviceNestedPciCapability struct {
+ Type string `xml:"type,attr"`
+ Address []NodeDevicePCIAddress `xml:"address,omitempty"`
+ MaxCount int `xml:"maxCount,attr,omitempty"`
+}
+
+type NodeDeviceSystemCapability struct {
+ Product string `xml:"product"`
+ Hardware *NodeDeviceSystemHardware `xml:"hardware"`
+ Firmware *NodeDeviceSystemFirmware `xml:"firmware"`
+}
+
+type NodeDeviceUSBDeviceCapability struct {
+ Bus int `xml:"bus"`
+ Device int `xml:"device"`
+ Product *NodeDeviceProduct `xml:"product,omitempty"`
+ Vendor *NodeDeviceVendor `xml:"vendor,omitempty"`
+}
+
+type NodeDeviceUSBCapability struct {
+ Number int `xml:"number"`
+ Class int `xml:"class"`
+ Subclass int `xml:"subclass"`
+ Protocol int `xml:"protocol"`
+ Description string `xml:"description,omitempty"`
+}
+
+type NodeDeviceNetCapability struct {
+ Interface string `xml:"interface"`
+ Address string `xml:"address"`
+ Link *NodeDeviceNetLink `xml:"link"`
+ Features []NodeDeviceNetOffloadFeatures `xml:"feature,omitempty"`
+ Capability *NodeDeviceNestedNetCapability `xml:"capability"`
+}
+
+type NodeDeviceNestedNetCapability struct {
+ Type string `xml:"type,attr"`
+}
+
+type NodeDeviceSCSIHostCapability struct {
+ Host int `xml:"host"`
+ UniqueID int `xml:"unique_id"`
+ Capability []NodeDeviceNestedSCSIHostCapability `xml:"capability"`
+}
+
+type NodeDeviceNestedSCSIHostCapability struct {
+ Type string `xml:"type,attr"`
+ Vports int `xml:"vports,omitempty"`
+ MaxVports int `xml:"maxvports,,omitempty"`
+ WWNN string `xml:"wwnn,omitempty"`
+ WWPN string `xml:"wwpn,omitempty"`
+ FabricWWN string `xml:"fabric_wwn,omitempty"`
+}
+
+type NodeDeviceSCSICapability struct {
+ Host int `xml:"host"`
+ Bus int `xml:"bus"`
+ Target int `xml:"target"`
+ Lun int `xml:"lun"`
+ Type string `xml:"type"`
+}
+
+type NodeDeviceNestedStorageCapability struct {
+ Type string `xml:"type,attr"`
+ MediaAvailable int `xml:"media_available,omitempty"`
+ MediaSize int `xml:"media_size,omitempty"`
+ MediaLable int `xml:"media_label,omitempty"`
+}
+
+type NodeDeviceStorageCapability struct {
+ Block string `xml:"block"`
+ Bus string `xml:"bus"`
+ DriverType string `xml:"drive_type"`
+ Model string `xml:"model"`
+ Vendor string `xml:"vendor"`
+ Serial string `xml:"serial,omitempty"`
+ Size int `xml:"size,omitempty"`
+ Capability *NodeDeviceNestedStorageCapability `xml:"capability,omitempty"`
+}
+
+type NodeDeviceDRMCapability struct {
+ Type string `xml:"type"`
+}
+
+func (c *NodeDevice) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+
+ for {
+ t, err := d.Token()
+ if err != nil {
+ return err
+ }
+ switch token := t.(type) {
+ case xml.StartElement:
+ switch token.Name.Local {
+ case "name":
+ var content string
+ if err := d.DecodeElement(&content, &start); err != nil {
+ return err
+ }
+ c.Name = content
+ case "path":
+ var content string
+ if err := d.DecodeElement(&content, &start); err != nil {
+ return err
+ }
+ c.Path = content
+ case "parent":
+ var content string
+ if err := d.DecodeElement(&content, &start); err != nil {
+ return err
+ }
+ c.Parent = content
+ case "driver":
+ tmp := struct {
+ Name string `xml:"name"`
+ }{}
+ if err := d.DecodeElement(&tmp, &token); err != nil {
+ return err
+ }
+ c.Driver = tmp.Name
+ case "capability":
+ for _, attr := range token.Attr {
+ if attr.Name.Local == "type" {
+ switch attr.Value {
+ case "pci":
+ var pciCaps NodeDevicePciCapability
+ if err := d.DecodeElement(&pciCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = pciCaps
+ case "system":
+ var systemCaps NodeDeviceSystemCapability
+ if err := d.DecodeElement(&systemCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = systemCaps
+ case "usb_device":
+ var usbdevCaps NodeDeviceUSBDeviceCapability
+ if err := d.DecodeElement(&usbdevCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = usbdevCaps
+ case "usb":
+ var usbCaps NodeDeviceUSBCapability
+ if err := d.DecodeElement(&usbCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = usbCaps
+ case "net":
+ var netCaps NodeDeviceNetCapability
+ if err := d.DecodeElement(&netCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = netCaps
+ case "scsi_host":
+ var scsiHostCaps NodeDeviceSCSIHostCapability
+ if err := d.DecodeElement(&scsiHostCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = scsiHostCaps
+ case "scsi":
+ var scsiCaps NodeDeviceSCSICapability
+ if err := d.DecodeElement(&scsiCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = scsiCaps
+ case "storage":
+ var storageCaps NodeDeviceStorageCapability
+ if err := d.DecodeElement(&storageCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = storageCaps
+ case "drm":
+ var drmCaps NodeDeviceDRMCapability
+ if err := d.DecodeElement(&drmCaps, &token); err != nil {
+ return err
+ }
+ c.Capability = drmCaps
+ }
+ }
+ }
+ }
+ case xml.EndElement:
+ return nil
+ }
+ }
+
+ return nil
+}
+
+func (c *NodeDevice) Unmarshal(doc string) error {
+ return xml.Unmarshal([]byte(doc), c)
+}
+
+func (c *NodeDevice) Marshal() (string, error) {
+ doc, err := xml.MarshalIndent(c, "", " ")
+ if err != nil {
+ return "", err
+ }
+ return string(doc), nil
+}
diff --git a/node_device_test.go b/node_device_test.go
new file mode 100644
index 0000000..a9f939e
--- /dev/null
+++ b/node_device_test.go
@@ -0,0 +1,337 @@
+/*
+ * This file is part of the libvirt-go-xml project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ */
+
+package libvirtxml
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+)
+
+var NodeDeviceTestData = []struct {
+ Object *NodeDevice
+ XML []string
+}{
+ {
+ Object: &NodeDevice{
+ Name: "pci_0000_81_00_0",
+ Parent: "pci_0000_80_01_0",
+ Driver: "ixgbe",
+ Capability: NodeDevicePciCapability{
+ Domain: 1,
+ Bus: 21,
+ Slot: 10,
+ Function: 50,
+ Product: &NodeDeviceProduct{
+ ID: "0x1528",
+ Name: "Ethernet Controller 10-Gigabit X540-AT2",
+ },
+ Vendor: &NodeDeviceVendor{
+ ID: "0x8086",
+ Name: "Intel Corporation",
+ },
+ IommuGroup: &NodeDeviceIOMMUGroup{
+ Number: 3,
+ },
+ Numa: &NodeDeviceNUMA{
+ Node: 1,
+ },
+ Capability: []NodeDeviceNestedPciCapability{
+ NodeDeviceNestedPciCapability{
+ Type: "virt_functions",
+ Address: []NodeDevicePCIAddress{
+ NodeDevicePCIAddress{
+ Domain: "0x0000",
+ Bus: "0x81",
+ Slot: "0x10",
+ Function: "0x1",
+ },
+ NodeDevicePCIAddress{
+ Domain: "0x0000",
+ Bus: "0x81",
+ Slot: "0x10",
+ Function: "0x3",
+ },
+ },
+ MaxCount: 63,
+ },
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>pci_0000_81_00_0</name>`,
+ ` <parent>pci_0000_80_01_0</parent>`,
+ ` <driver>`,
+ ` <name>ixgbe</name>`,
+ ` </driver>`,
+ ` <capability type='pci'>`,
+ ` <domain>1</domain>`,
+ ` <bus>21</bus>`,
+ ` <slot>10</slot>`,
+ ` <function>50</function>`,
+ ` <product id='0x1528'>Ethernet Controller 10-Gigabit X540-AT2</product>`,
+ ` <vendor id='0x8086'>Intel Corporation</vendor>`,
+ ` <capability type='virt_functions' maxCount='63'>`,
+ ` <address domain='0x0000' bus='0x81' slot='0x10' function='0x1'/>`,
+ ` <address domain='0x0000' bus='0x81' slot='0x10' function='0x3'/>`,
+ ` </capability>`,
+ ` <iommuGroup number='3'>`,
+ ` <address domain='0x0000' bus='0x15' slot='0x00' function='0x4'/>`,
+ ` </iommuGroup>`,
+ ` <numa node='1'/>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "pci_10df_fe00_0_scsi_host",
+ Parent: "pci_10df_fe00_0",
+ Capability: NodeDeviceSCSIHostCapability{
+ Host: 4,
+ Capability: []NodeDeviceNestedSCSIHostCapability{
+ NodeDeviceNestedSCSIHostCapability{
+ Type: "fc_host",
+ WWNN: "20000000c9848141",
+ WWPN: "10000000c9848141",
+ },
+ NodeDeviceNestedSCSIHostCapability{
+ Type: "vport_ops",
+ },
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>pci_10df_fe00_0_scsi_host</name>`,
+ ` <parent>pci_10df_fe00_0</parent>`,
+ ` <capability type='scsi_host'>`,
+ ` <host>4</host>`,
+ ` <capability type='fc_host'>`,
+ ` <wwnn>20000000c9848141</wwnn>`,
+ ` <wwpn>10000000c9848141</wwpn>`,
+ ` </capability>`,
+ ` <capability type='vport_ops' />`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "computer",
+ Capability: NodeDeviceSystemCapability{
+ Hardware: &NodeDeviceSystemHardware{
+ Vendor: "LENOVO",
+ Version: "ThinkPad T61",
+ Serial: "L3B2616",
+ UUID: "97e80381-494f-11cb-8e0e-cbc168f7d753",
+ },
+ Firmware: &NodeDeviceSystemFirmware{
+ Vendor: "LENOVO",
+ Version: "7LET51WW (1.21 )",
+ ReleaseDate: "08/22/2007",
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>computer</name>`,
+ ` <capability type='system'>`,
+ ` <hardware>`,
+ ` <vendor>LENOVO</vendor>`,
+ ` <version>ThinkPad T61</version>`,
+ ` <serial>L3B2616</serial>`,
+ ` <uuid>97e80381-494f-11cb-8e0e-cbc168f7d753</uuid>`,
+ ` </hardware>`,
+ ` <firmware>`,
+ ` <vendor>LENOVO</vendor>`,
+ ` <version>7LET51WW (1.21 )</version>`,
+ ` <release_date>08/22/2007</release_date>`,
+ ` </firmware>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "usb_device_1d6b_1_0000_00_1a_0",
+ Parent: "pci_8086_2834",
+ Driver: "usb",
+ Capability: NodeDeviceUSBDeviceCapability{
+ Bus: 3,
+ Device: 1,
+ Product: &NodeDeviceProduct{
+ ID: "0x0001",
+ Name: "1.1 root hub",
+ },
+ Vendor: &NodeDeviceVendor{
+ ID: "0x1d6b",
+ Name: "Linux Foundation",
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>usb_device_1d6b_1_0000_00_1a_0</name>`,
+ ` <parent>pci_8086_2834</parent>`,
+ ` <driver>`,
+ ` <name>usb</name>`,
+ ` </driver>`,
+ ` <capability type='usb_device'>`,
+ ` <bus>3</bus>`,
+ ` <device>1</device>`,
+ ` <product id='0x0001'>1.1 root hub</product>`,
+ ` <vendor id='0x1d6b'>Linux Foundation</vendor>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "usb_device_1d6b_1_0000_00_1a_0_if0",
+ Parent: "usb_device_1d6b_1_0000_00_1a_0",
+ Driver: "hub",
+ Capability: NodeDeviceUSBCapability{
+ Number: 0,
+ Class: 9,
+ Subclass:0,
+ Protocol: 0,
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>usb_device_1d6b_1_0000_00_1a_0_if0</name>`,
+ ` <parent>usb_device_1d6b_1_0000_00_1a_0</parent>`,
+ ` <driver>`,
+ ` <name>hub</name>`,
+ ` </driver>`,
+ ` <capability type='usb'>`,
+ ` <number>0</number>`,
+ ` <class>9</class>`,
+ ` <subclass>0</subclass>`,
+ ` <protocol>0</protocol>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "net_wlp3s0_4c_eb_42_aa_aa_82",
+ Path: "/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0",
+ Parent: "pci_0000_03_00_0",
+ Capability: NodeDeviceNetCapability{
+ Interface: "wlp3s0",
+ Address: "4c:eb:42:aa:aa:82",
+ Link: &NodeDeviceNetLink{
+ State: "up",
+ },
+ Features: []NodeDeviceNetOffloadFeatures{
+ NodeDeviceNetOffloadFeatures{
+ Name: "sg",
+ },
+ NodeDeviceNetOffloadFeatures{
+ Name: "gso",
+ },
+ NodeDeviceNetOffloadFeatures{
+ Name: "gro",
+ },
+ },
+ Capability: &NodeDeviceNestedNetCapability{
+ Type: "80211",
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>net_wlp3s0_4c_eb_42_aa_aa_82</name>`,
+ ` <path>/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0</path>`,
+ ` <parent>pci_0000_03_00_0</parent>`,
+ ` <capability type='net'>`,
+ ` <interface>wlp3s0</interface>`,
+ ` <address>4c:eb:42:aa:aa:82</address>`,
+ ` <link state='up'/>`,
+ ` <feature name='sg'/>`,
+ ` <feature name='gso'/>`,
+ ` <feature name='gro'/>`,
+ ` <capability type='80211'/>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+ {
+ Object: &NodeDevice{
+ Name: "storage_model_DVDRAM_GSA_U10N",
+ Parent: "pci_8086_2850_scsi_host_scsi_device_lun0",
+ Capability: NodeDeviceStorageCapability{
+ Block: "/dev/sr1",
+ Bus: "pci",
+ DriverType: "cdrom",
+ Model:"DVDRAM GSA-U10N",
+ Vendor: "HL-DT-ST",
+ Capability: &NodeDeviceNestedStorageCapability{
+ Type: "removable",
+ MediaAvailable: 0,
+ MediaSize: 0,
+ },
+ },
+ },
+ XML: []string{
+ `<device>`,
+ ` <name>storage_model_DVDRAM_GSA_U10N</name>`,
+ ` <parent>pci_8086_2850_scsi_host_scsi_device_lun0</parent>`,
+ ` <capability type='storage'>`,
+ ` <block>/dev/sr1</block>`,
+ ` <bus>pci</bus>`,
+ ` <drive_type>cdrom</drive_type>`,
+ ` <model>DVDRAM GSA-U10N</model>`,
+ ` <vendor>HL-DT-ST</vendor>`,
+ ` <capability type='removable'>`,
+ ` <media_available>0</media_available>`,
+ ` <media_size>0</media_size>`,
+ ` </capability>`,
+ ` </capability>`,
+ `</device>`,
+ },
+ },
+
+}
+
+func TestNodeDevice(t *testing.T) {
+ for _, test := range NodeDeviceTestData {
+ xmlDoc := strings.Join(test.XML, "\n")
+ nodeDevice := NodeDevice{}
+ err := nodeDevice.Unmarshal(xmlDoc)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ res := reflect.DeepEqual(&nodeDevice, test.Object)
+ if !res {
+ t.Fatal("Bad NodeDevice object creation.", "\nExpected: ", test.Object, "\nActual: ", nodeDevice)
+ }
+ }
+}
--
2.9.4
7 years, 5 months
[libvirt] [PATCH] virFDStreamThread: Make sure we won't exceed @length
by Michal Privoznik
There's a problem with current streams after I switched them from
iohelper to thread implementation. Previously, iohelper made sure
not to exceed specified @length resulting in the pipe EOF
appearing at the exact right moment (the pipe was used to tunnel
the data from the iohelper to the daemon). Anyway, when switching
to thread I had to write the I/O code from scratch. Whilst doing
that I took an inspiration from the iohelper code, but since the
usage of pipe switched to slightly different meaning, there was
no 1:1 relationship between the codes.
Moreover, after introducing VIR_FDSTREAM_MSG_TYPE_HOLE, the
condition that should made sure we won't exceed @length was
completely wrong.
The fix is to:
a) account for holes for @length
b) cap not just data sections but holes too (if @length would be
exceeded)
For this purpose, the condition needs to be brought closer to the
code that handles holes and data sections.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/util/virfdstream.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/util/virfdstream.c b/src/util/virfdstream.c
index 7ee58be13..ae6f78e01 100644
--- a/src/util/virfdstream.c
+++ b/src/util/virfdstream.c
@@ -420,6 +420,8 @@ virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
const int fdout,
const char *fdinname,
const char *fdoutname,
+ size_t length,
+ size_t total,
size_t *dataLen,
size_t buflen)
{
@@ -433,10 +435,18 @@ virFDStreamThreadDoRead(virFDStreamDataPtr fdst,
if (virFileInData(fdin, &inData, §ionLen) < 0)
goto error;
+ if (length &&
+ sectionLen > length - total)
+ sectionLen = length - total;
+
if (inData)
*dataLen = sectionLen;
}
+ if (length &&
+ buflen > length - total)
+ buflen = length - total;
+
if (VIR_ALLOC(msg) < 0)
goto error;
@@ -578,13 +588,6 @@ virFDStreamThread(void *opaque)
while (1) {
ssize_t got;
- if (length &&
- (length - total) < buflen)
- buflen = length - total;
-
- if (buflen == 0)
- break; /* End of requested data from client */
-
while (doRead == (fdst->msg != NULL) &&
!fdst->threadQuit) {
if (virCondWait(&fdst->threadCond, &fdst->parent.lock)) {
@@ -608,6 +611,7 @@ virFDStreamThread(void *opaque)
got = virFDStreamThreadDoRead(fdst, sparse,
fdin, fdout,
fdinname, fdoutname,
+ length, total,
&dataLen, buflen);
else
got = virFDStreamThreadDoWrite(fdst, sparse,
--
2.13.0
7 years, 5 months
[libvirt] [PATCH] virNetClientStreamQueuePacket: Set st->incomingEOF on the end of stream
by Michal Privoznik
While reworking client side of streams, I had to postpone payload
decoding so that stream holes and stream data can be
distinguished in virNetClientStreamRecvPacket. That's merely what
18944b7aea46d does. However, I accidentally removed one important
bit: when server sends us an empty STREAM packet (with no
payload) - meaning end of stream - st->incomingEOF flag needs to
be set. It used to be before I touched the code. After I removed
it, virNetClientStreamRecvPacket will try to fetch more data from
the stream, but it will never come.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Thanks to Martin who helped me debug this.
src/rpc/virnetclientstream.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index a9bf271dc..54729c84f 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -278,6 +278,15 @@ int virNetClientStreamQueuePacket(virNetClientStreamPtr st,
VIR_DEBUG("Incoming stream message: stream=%p message=%p", st, msg);
+ if (msg->bufferLength == msg->bufferOffset) {
+ /* No payload means end of the stream. */
+ virObjectLock(st);
+ st->incomingEOF = true;
+ virNetClientStreamEventTimerUpdate(st);
+ virObjectUnlock(st);
+ return 0;
+ }
+
/* Unfortunately, we must allocate new message as the one we
* get in @msg is going to be cleared later in the process. */
--
2.13.0
7 years, 5 months
[libvirt] [PATCH] virDomainNetDefParseXML: Fix typo
by Michal Privoznik
In 9cb891141c we've introduced some logic to clearing suggested
macvtap/macvlan ifnames. The logic consists of comparing ifname
string with strings that libvirt would generate. However, due to
a typo only VIR_NET_GENERATED_MACVTAP_PREFIX was compared. Twice.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Pushed as trivial.
src/conf/domain_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2e2e7334a..3e884225b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10074,7 +10074,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (ifname &&
flags & VIR_DOMAIN_DEF_PARSE_INACTIVE &&
(STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
- STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX))) {
+ STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX))) {
VIR_FREE(ifname);
}
--
2.13.0
7 years, 5 months
[libvirt] [PATCHv2 00/15] Allow virtio devices to use vIOMMU
by Ján Tomko
https://bugzilla.redhat.com/show_bug.cgi?id=1283251
Ján Tomko (15):
conf: eliminate monster condition in virDomainControllerDefFormat
virDomainControllerDefFormat: do not mix attributes and subelements
conf: add device_iotlb attribute to iommu
qemu: format device-iotlb on intel-iommu command line
qemuxml2xmltest: add virtio-options test
Add virtio-related options to interfaces
add virtio-related options to memballoon
Add virtio-related options to disks
Add virtio-related options to controllers
Add virtio-related options to filesystems
Add virtio-related options to rng devices
Add virtio-related options to video
Add virtio-related options to input devices
qemuxml2argvtest: add virtio-options test case
qemu: format virtio-related options on the command line
docs/formatdomain.html.in | 87 ++++++++
docs/schemas/domaincommon.rng | 40 ++++
src/conf/domain_conf.c | 224 ++++++++++++++++++---
src/conf/domain_conf.h | 27 +++
src/qemu/qemu_capabilities.c | 15 +-
src/qemu/qemu_capabilities.h | 5 +
src/qemu/qemu_command.c | 69 +++++++
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 3 +
.../qemuxml2argv-intel-iommu-device-iotlb.args | 19 ++
.../qemuxml2argv-intel-iommu-device-iotlb.xml | 31 +++
.../qemuxml2argv-virtio-options.args | 57 ++++++
.../qemuxml2argv-virtio-options.xml | 104 ++++++++++
tests/qemuxml2argvtest.c | 18 ++
.../qemuxml2xmlout-intel-iommu-device-iotlb.xml | 1 +
.../qemuxml2xmlout-virtio-options.xml | 104 ++++++++++
tests/qemuxml2xmltest.c | 2 +
16 files changed, 772 insertions(+), 34 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-intel-iommu-device-iotlb.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-intel-iommu-device-iotlb.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-virtio-options.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu-device-iotlb.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-virtio-options.xml
--
2.10.2
7 years, 5 months
[libvirt] Remotable Libvirt
by Peter
Hi Everyone,
We are working towards building on the virtualization management
functionality in cockpit (http://cockpit-project.org/) and wanted to get
some feedback on the best way to integrate with libvirt.
As a quick overview, cockpit aims to talk to existing remotable system
APIs. Usually these API’s take the form of dbus, REST or executable
commands. The majority of cockpit is implemented in javascript. There is
no cockpit backend that knows how to change a hostname for example. The
cockpit backend knows how to handle a dbus payload. The javascript
running in the users browser knows how to use the systemd dbus API at
org.freedesktop.hostname1 to manage the system hostname.
Right now some of the basics have been implemented by spawning commands
on the system. This isn't ideal because it involves parsing / screen
scraping output and doesn't support receiving events so we have to poll
(ei run the command again) to keep the UI up to date.
As far as I know libvirt doesn't currently have a remoteable API. It
does have a daemon that communicates with clients via a XDR RPC.
(https://libvirt.org/internals/rpc.html) However from what I'm hearing
the RPC is considered an internal implementation and shouldn't be used
by external applications. Is that still the case? Is there any chance of
getting talking the daemon directly using the XDR standard for a subset
of methods blessed as part of the externally supported API?
An alternative is to implement a standards based remotable API, using
something like dbus or REST, that can be used by external applications.
I imagine that this would be at a bit of a higher level than the current
RPC and contain at least some of the logic around the actions it
performs rather than being a direct passthrough to the daemon.
Of course that is a pretty big undertaking and would, in my opinion,
only be worth it if there is broader interest in the community and use
cases beyond what cockpit would like to.
7 years, 5 months
[libvirt] [PATCH v2] qemu: Fix serial stub console allocation
by Erik Skultety
When adding the aliased serial stub console, the structure wasn't
properly allocated (VIR_ALLOC instead of virDomainChrDefNew) which then
resulted in SIGSEGV in virDomainChrSourceIsEqual during a serial device
coldplug.
https://bugzilla.redhat.com/show_bug.cgi?id=1434278
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4a7d99725..6701bd9bc 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1802,15 +1802,17 @@ qemuDomainChrPreInsert(virDomainDefPtr vmdef,
if (virDomainChrPreAlloc(vmdef, chr) < 0)
return -1;
- /* Due to some crazy backcompat stuff, the first serial device is an alias
- * to the first console too. If this is the case, the definition must be
- * duplicated as first console device. */
+ /* Due to historical reasons, the first console is an alias to the
+ * first serial device (if such exists). If this is the case, we need to
+ * create an object for the first console as well.
+ */
if (vmdef->nserials == 0 && vmdef->nconsoles == 0 &&
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
if (!vmdef->consoles && VIR_ALLOC(vmdef->consoles) < 0)
return -1;
- if (VIR_ALLOC(vmdef->consoles[0]) < 0) {
+ /* We'll be dealing with serials[0] directly, so NULL is fine here. */
+ if (!(vmdef->consoles[0] = virDomainChrDefNew(NULL))) {
VIR_FREE(vmdef->consoles);
return -1;
}
@@ -1841,7 +1843,7 @@ qemuDomainChrInsertPreAllocCleanup(virDomainDefPtr vmdef,
/* Remove the stub console added by qemuDomainChrPreInsert */
if (vmdef->nserials == 0 && vmdef->nconsoles == 1 &&
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
- VIR_FREE(vmdef->consoles[0]);
+ virDomainChrDefFree(vmdef->consoles[0]);
VIR_FREE(vmdef->consoles);
vmdef->nconsoles = 0;
}
--
2.13.0
7 years, 5 months
[libvirt] [PATCH v2 00/20] Fix regression caused by recent CPU driver changes
by Jiri Denemark
https://bugzilla.redhat.com/show_bug.cgi?id=1441662
when I was enhancing libvirt's guest CPU configuration code to be able
to really ensure stable guest CPU ABI, I added a new attribute
//cpu/@check which is nicely backward compatible... an old libvirt will
just ignore it. However, even if check='full' will be ignored, an old
libvirt will still see the updated CPU definition (features added or
removed by the hypervisor will be shown there). And because we need QEMU
2.9.0 to check what features are going to be added or removed before we
actually start the domain, migrating such domain to an older libvirt or
QEMU may fail if QEMU enables a feature which is not supported by the
host CPU. Known features causing problems are, e.g., x2apic, hypervisor,
and arat. To make things even worse, updating a CPU definition with the
automatically added/removed features can be done since QEMU 1.5.0.
Even save/restore or snapshot revert on a single host running new
libvirt and QEMU < 2.9.0 is now affected by this regression.
This series fixes the regression by storing the original guest CPU
definition in migratable XML and sending the updated CPU in a side
channel (a migration or save cookie).
Version 2:
- see individual patches for changes
Jiri Denemark (20):
conf: Make error reporting in virCPUDefIsEqual optional
conf: Refactor virCPUDefParseXML
conf: Make virDomainSnapshotDefFormat easier to read
conf: Pass xmlopt to virDomainSnapshotDefFormat
qemu: Rename xml_len in virQEMUSaveHeader as data_len
qemu: Fix memory leaks in qemuDomainSaveImageOpen
qemu: Introduce virQEMUSaveData{New,Free}
qemu: Introduce virQEMUSaveDataFinish
qemu: Refactor qemuDomainSaveHeader
qemu: Introduce virQEMUSaveData structure
conf: Introduce virSaveCookie
conf: Add save cookie callbacks to xmlopt
qemu: Implement virSaveCookie object and callbacks
qemu: Store save cookie in save images and snapshots
qemu: Remember CPU def from domain start
qemu: Report the original CPU in migratable xml
qemu: Always send persistent XML during migration
qemu: Send updated CPU in migration cookie
qemu: Store updated CPU in save cookie
qemu: Use updated CPU when starting QEMU if possible
docs/formatsnapshot.html.in | 6 +
docs/schemas/domainsnapshot.rng | 7 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/bhyve/bhyve_domain.c | 2 +-
src/conf/cpu_conf.c | 192 ++++++++--------
src/conf/cpu_conf.h | 12 +-
src/conf/domain_conf.c | 30 ++-
src/conf/domain_conf.h | 7 +-
src/conf/snapshot_conf.c | 40 +++-
src/conf/snapshot_conf.h | 3 +
src/conf/virsavecookie.c | 144 ++++++++++++
src/conf/virsavecookie.h | 62 +++++
src/cpu/cpu.c | 5 +-
src/esx/esx_driver.c | 2 +-
src/libvirt_private.syms | 10 +
src/libxl/libxl_conf.c | 2 +-
src/lxc/lxc_conf.c | 2 +-
src/openvz/openvz_driver.c | 2 +-
src/phyp/phyp_driver.c | 2 +-
src/qemu/qemu_capabilities.c | 2 +-
src/qemu/qemu_conf.c | 3 +-
src/qemu/qemu_domain.c | 207 +++++++++++++++--
src/qemu/qemu_domain.h | 22 ++
src/qemu/qemu_driver.c | 468 ++++++++++++++++++++++++++------------
src/qemu/qemu_migration.c | 18 +-
src/qemu/qemu_migration_cookie.c | 31 ++-
src/qemu/qemu_migration_cookie.h | 5 +
src/qemu/qemu_process.c | 37 ++-
src/qemu/qemu_process.h | 2 +
src/security/virt-aa-helper.c | 2 +-
src/test/test_driver.c | 3 +-
src/uml/uml_driver.c | 2 +-
src/vbox/vbox_common.c | 6 +-
src/vmware/vmware_driver.c | 3 +-
src/vmx/vmx.c | 2 +-
src/vz/vz_driver.c | 3 +-
src/xen/xen_driver.c | 2 +-
src/xenapi/xenapi_driver.c | 2 +-
tests/bhyveargv2xmltest.c | 2 +-
tests/cputest.c | 5 +-
tests/domainsnapshotxml2xmltest.c | 1 +
tests/testutils.c | 2 +-
43 files changed, 1047 insertions(+), 315 deletions(-)
create mode 100644 src/conf/virsavecookie.c
create mode 100644 src/conf/virsavecookie.h
--
2.13.0
7 years, 5 months
[libvirt] [PATCH go-xml] 1,rename DomainInterfaceBoot to DomainDeviceBoot; 2,support disk boot order
by zhenwei.pi
---
domain.go | 5 +++--
domain_test.go | 6 +++++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/domain.go b/domain.go
index 1d91dc3..7d8f6d6 100644
--- a/domain.go
+++ b/domain.go
@@ -98,6 +98,7 @@ type DomainDisk struct {
ReadOnly *DomainDiskReadOnly `xml:"readonly"`
Shareable *DomainDiskShareable `xml:"shareable"`
Address *DomainAddress `xml:"address"`
+ Boot *DomainDeviceBoot `xml:"boot"`
}
type DomainFilesystemDriver struct {
@@ -171,7 +172,7 @@ type DomainInterfaceLink struct {
State string `xml:"state,attr"`
}
-type DomainInterfaceBoot struct {
+type DomainDeviceBoot struct {
Order uint `xml:"order,attr"`
}
@@ -193,7 +194,7 @@ type DomainInterface struct {
Target *DomainInterfaceTarget `xml:"target"`
Alias *DomainInterfaceAlias `xml:"alias"`
Link *DomainInterfaceLink `xml:"link"`
- Boot *DomainInterfaceBoot `xml:"boot"`
+ Boot *DomainDeviceBoot `xml:"boot"`
Script *DomainInterfaceScript `xml:"script"`
Driver *DomainInterfaceDriver `xml:"driver"`
Address *DomainAddress `xml:"address"`
diff --git a/domain_test.go b/domain_test.go
index b83d4ae..3d015c7 100644
--- a/domain_test.go
+++ b/domain_test.go
@@ -87,6 +87,9 @@ var domainTestData = []struct {
Bus: "virtio",
},
Serial: "fishfood",
+ Boot: &DomainDeviceBoot{
+ Order: 1,
+ },
},
DomainDisk{
Type: "block",
@@ -189,6 +192,7 @@ var domainTestData = []struct {
` <source file="/var/lib/libvirt/images/demo.qcow2"></source>`,
` <target dev="vda" bus="virtio"></target>`,
` <serial>fishfood</serial>`,
+ ` <boot order="1"></boot>`,
` </disk>`,
` <disk type="block" device="disk">`,
` <driver name="qemu" type="raw"></driver>`,
@@ -710,7 +714,7 @@ var domainTestData = []struct {
Link: &DomainInterfaceLink{
State: "up",
},
- Boot: &DomainInterfaceBoot{
+ Boot: &DomainDeviceBoot{
Order: 1,
},
Driver: &DomainInterfaceDriver{
--
2.7.4
7 years, 5 months