From nobody Tue May 7 17:08:01 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1496864917159338.9491222450913; Wed, 7 Jun 2017 12:48:37 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 990F480508; Wed, 7 Jun 2017 19:48:31 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E1EE317AD7; Wed, 7 Jun 2017 19:48:30 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 899814A48C; Wed, 7 Jun 2017 19:48:29 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v57Jkqc5031037 for ; Wed, 7 Jun 2017 15:46:52 -0400 Received: by smtp.corp.redhat.com (Postfix) id E468E77D7E; Wed, 7 Jun 2017 19:46:52 +0000 (UTC) Received: from romwork.redhat.com (ovpn-120-109.rdu2.redhat.com [10.10.120.109]) by smtp.corp.redhat.com (Postfix) with ESMTP id CCD4E60F92; Wed, 7 Jun 2017 19:46:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 990F480508 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 990F480508 From: Vladik Romanovsky To: libvir-list@redhat.com Date: Wed, 7 Jun 2017 15:46:40 -0400 Message-Id: <20170607194640.11903-1-vromanso@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Vladik Romanovsky Subject: [libvirt] [PATCH go-xml] Add support for Node Device with basic testing. X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 07 Jun 2017 19:48:32 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" --- 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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 :=3D d.Token() + if err !=3D nil { + return err + } + switch token :=3D t.(type) { + case xml.StartElement: + switch token.Name.Local { + case "name": + var content string + if err :=3D d.DecodeElement(&content, &start); err !=3D nil { + return err + } + c.Name =3D content + case "path": + var content string + if err :=3D d.DecodeElement(&content, &start); err !=3D nil { + return err + } + c.Path =3D content + case "parent": + var content string + if err :=3D d.DecodeElement(&content, &start); err !=3D nil { + return err + } + c.Parent =3D content + case "driver": + tmp :=3D struct { + Name string `xml:"name"` + }{} + if err :=3D d.DecodeElement(&tmp, &token); err !=3D nil { + return err + } + c.Driver =3D tmp.Name + case "capability": + for _, attr :=3D range token.Attr { + if attr.Name.Local =3D=3D "type" { + switch attr.Value { + case "pci": + var pciCaps NodeDevicePciCapability + if err :=3D d.DecodeElement(&pciCaps, &token); err !=3D nil { + return err + } + c.Capability =3D pciCaps + case "system": + var systemCaps NodeDeviceSystemCapability + if err :=3D d.DecodeElement(&systemCaps, &token); err !=3D nil { + return err + } + c.Capability =3D systemCaps + case "usb_device": + var usbdevCaps NodeDeviceUSBDeviceCapability + if err :=3D d.DecodeElement(&usbdevCaps, &token); err !=3D nil { + return err + } + c.Capability =3D usbdevCaps + case "usb": + var usbCaps NodeDeviceUSBCapability + if err :=3D d.DecodeElement(&usbCaps, &token); err !=3D nil { + return err + } + c.Capability =3D usbCaps + case "net": + var netCaps NodeDeviceNetCapability + if err :=3D d.DecodeElement(&netCaps, &token); err !=3D nil { + return err + } + c.Capability =3D netCaps + case "scsi_host": + var scsiHostCaps NodeDeviceSCSIHostCapability + if err :=3D d.DecodeElement(&scsiHostCaps, &token); err !=3D nil { + return err + } + c.Capability =3D scsiHostCaps + case "scsi": + var scsiCaps NodeDeviceSCSICapability + if err :=3D d.DecodeElement(&scsiCaps, &token); err !=3D nil { + return err + } + c.Capability =3D scsiCaps + case "storage": + var storageCaps NodeDeviceStorageCapability + if err :=3D d.DecodeElement(&storageCaps, &token); err !=3D nil { + return err + } + c.Capability =3D storageCaps + case "drm": + var drmCaps NodeDeviceDRMCapability + if err :=3D d.DecodeElement(&drmCaps, &token); err !=3D nil { + return err + } + c.Capability =3D 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 :=3D xml.MarshalIndent(c, "", " ") + if err !=3D 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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 =3D []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{ + ``, + ` pci_0000_81_00_0`, + ` pci_0000_80_01_0`, + ` `, + ` ixgbe`, + ` `, + ` `, + ` 1`, + ` 21`, + ` 10`, + ` 50`, + ` Ethernet Controller 10-Gigabit X540-AT2`, + ` Intel Corporation`, + ` `, + `
`, + `
`, + ` `, + ` `, + `
`, + ` `, + ` `, + ` `, + ``, + }, + }, + { + 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{ + ``, + ` pci_10df_fe00_0_scsi_host`, + ` pci_10df_fe00_0`, + ` `, + ` 4`, + ` `, + ` 20000000c9848141`, + ` 10000000c9848141`, + ` `, + ` `, + ` `, + ``, + }, + }, + { + 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{ + ``, + ` computer`, + ` `, + ` `, + ` LENOVO`, + ` ThinkPad T61`, + ` L3B2616`, + ` 97e80381-494f-11cb-8e0e-cbc168f7d753`, + ` `, + ` `, + ` LENOVO`, + ` 7LET51WW (1.21 )`, + ` 08/22/2007`, + ` `, + ` `, + ``, + }, + }, + { + 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{ + ``, + ` usb_device_1d6b_1_0000_00_1a_0`, + ` pci_8086_2834`, + ` `, + ` usb`, + ` `, + ` `, + ` 3`, + ` 1`, + ` 1.1 root hub`, + ` Linux Foundation`, + ` `, + ``, + }, + }, + { + 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{ + ``, + ` usb_device_1d6b_1_0000_00_1a_0_if0`, + ` usb_device_1d6b_1_0000_00_1a_0`, + ` `, + ` hub`, + ` `, + ` `, + ` 0`, + ` 9`, + ` 0`, + ` 0`, + ` `, + ``, + }, + }, + { + 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{ + ``, + ` net_wlp3s0_4c_eb_42_aa_aa_82`, + ` /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0`, + ` pci_0000_03_00_0`, + ` `, + ` wlp3s0`, + `
4c:eb:42:aa:aa:82
`, + ` `, + ` `, + ` `, + ` `, + ` `, + ` `, + `
`, + }, + }, + { + 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{ + ``, + ` storage_model_DVDRAM_GSA_U10N`, + ` pci_8086_2850_scsi_host_scsi_device_lun0`, + ` `, + ` /dev/sr1`, + ` pci`, + ` cdrom`, + ` DVDRAM GSA-U10N`, + ` HL-DT-ST`, + ` `, + ` 0`, + ` 0`, + ` `, + ` `, + ``, + }, + }, + +} + +func TestNodeDevice(t *testing.T) { + for _, test :=3D range NodeDeviceTestData { + xmlDoc :=3D strings.Join(test.XML, "\n") + nodeDevice :=3D NodeDevice{} + err :=3D nodeDevice.Unmarshal(xmlDoc) + if err !=3D nil { + t.Fatal(err) + } + + res :=3D reflect.DeepEqual(&nodeDevice, test.Object) + if !res { + t.Fatal("Bad NodeDevice object creation.", "\nExpected: ", test.Object,= "\nActual: ", nodeDevice) + } + } +} --=20 2.9.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list