github.com/zhaoxuat/libvirt-go-xml@v6.3.1-0.20200612053919-a025f1d30c41+incompatible/node_device.go (about)

     1  /*
     2   * This file is part of the libvirt-go-xml project
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    20   * THE SOFTWARE.
    21   *
    22   * Copyright (C) 2017 Red Hat, Inc.
    23   *
    24   */
    25  
    26  package libvirtxml
    27  
    28  import (
    29  	"encoding/xml"
    30  	"fmt"
    31  	"io"
    32  	"strconv"
    33  	"strings"
    34  )
    35  
    36  type NodeDevice struct {
    37  	XMLName    xml.Name             `xml:"device"`
    38  	Name       string               `xml:"name"`
    39  	Path       string               `xml:"path,omitempty"`
    40  	DevNodes   []NodeDeviceDevNode  `xml:"devnode"`
    41  	Parent     string               `xml:"parent,omitempty"`
    42  	Driver     *NodeDeviceDriver    `xml:"driver"`
    43  	Capability NodeDeviceCapability `xml:"capability"`
    44  }
    45  
    46  type NodeDeviceDevNode struct {
    47  	Type string `xml:"type,attr,omitempty"`
    48  	Path string `xml:",chardata"`
    49  }
    50  
    51  type NodeDeviceDriver struct {
    52  	Name string `xml:"name"`
    53  }
    54  
    55  type NodeDeviceCapability struct {
    56  	System     *NodeDeviceSystemCapability
    57  	PCI        *NodeDevicePCICapability
    58  	USB        *NodeDeviceUSBCapability
    59  	USBDevice  *NodeDeviceUSBDeviceCapability
    60  	Net        *NodeDeviceNetCapability
    61  	SCSIHost   *NodeDeviceSCSIHostCapability
    62  	SCSITarget *NodeDeviceSCSITargetCapability
    63  	SCSI       *NodeDeviceSCSICapability
    64  	Storage    *NodeDeviceStorageCapability
    65  	DRM        *NodeDeviceDRMCapability
    66  	CCW        *NodeDeviceCCWCapability
    67  	MDev       *NodeDeviceMDevCapability
    68  }
    69  
    70  type NodeDeviceIDName struct {
    71  	ID   string `xml:"id,attr"`
    72  	Name string `xml:",chardata"`
    73  }
    74  
    75  type NodeDevicePCIExpress struct {
    76  	Links []NodeDevicePCIExpressLink `xml:"link"`
    77  }
    78  
    79  type NodeDevicePCIExpressLink struct {
    80  	Validity string  `xml:"validity,attr,omitempty"`
    81  	Speed    float64 `xml:"speed,attr,omitempty"`
    82  	Port     *uint   `xml:"port,attr"`
    83  	Width    *uint   `xml:"width,attr"`
    84  }
    85  
    86  type NodeDeviceIOMMUGroup struct {
    87  	Number  int                    `xml:"number,attr"`
    88  	Address []NodeDevicePCIAddress `xml:"address"`
    89  }
    90  
    91  type NodeDeviceNUMA struct {
    92  	Node int `xml:"node,attr"`
    93  }
    94  
    95  type NodeDevicePCICapability struct {
    96  	Class        string                       `xml:"class,omitempty"`
    97  	Domain       *uint                        `xml:"domain"`
    98  	Bus          *uint                        `xml:"bus"`
    99  	Slot         *uint                        `xml:"slot"`
   100  	Function     *uint                        `xml:"function"`
   101  	Product      NodeDeviceIDName             `xml:"product,omitempty"`
   102  	Vendor       NodeDeviceIDName             `xml:"vendor,omitempty"`
   103  	IOMMUGroup   *NodeDeviceIOMMUGroup        `xml:"iommuGroup"`
   104  	NUMA         *NodeDeviceNUMA              `xml:"numa"`
   105  	PCIExpress   *NodeDevicePCIExpress        `xml:"pci-express"`
   106  	Capabilities []NodeDevicePCISubCapability `xml:"capability"`
   107  }
   108  
   109  type NodeDevicePCIAddress struct {
   110  	Domain   *uint `xml:"domain,attr"`
   111  	Bus      *uint `xml:"bus,attr"`
   112  	Slot     *uint `xml:"slot,attr"`
   113  	Function *uint `xml:"function,attr"`
   114  }
   115  
   116  type NodeDevicePCISubCapability struct {
   117  	VirtFunctions *NodeDevicePCIVirtFunctionsCapability
   118  	PhysFunction  *NodeDevicePCIPhysFunctionCapability
   119  	MDevTypes     *NodeDevicePCIMDevTypesCapability
   120  	Bridge        *NodeDevicePCIBridgeCapability
   121  }
   122  
   123  type NodeDevicePCIVirtFunctionsCapability struct {
   124  	Address  []NodeDevicePCIAddress `xml:"address,omitempty"`
   125  	MaxCount int                    `xml:"maxCount,attr,omitempty"`
   126  }
   127  
   128  type NodeDevicePCIPhysFunctionCapability struct {
   129  	Address NodeDevicePCIAddress `xml:"address,omitempty"`
   130  }
   131  
   132  type NodeDevicePCIMDevTypesCapability struct {
   133  	Types []NodeDevicePCIMDevType `xml:"type"`
   134  }
   135  
   136  type NodeDevicePCIMDevType struct {
   137  	ID                 string `xml:"id,attr"`
   138  	Name               string `xml:"name"`
   139  	DeviceAPI          string `xml:"deviceAPI"`
   140  	AvailableInstances uint   `xml:"availableInstances"`
   141  }
   142  
   143  type NodeDevicePCIBridgeCapability struct {
   144  }
   145  
   146  type NodeDeviceSystemHardware struct {
   147  	Vendor  string `xml:"vendor"`
   148  	Version string `xml:"version"`
   149  	Serial  string `xml:"serial"`
   150  	UUID    string `xml:"uuid"`
   151  }
   152  
   153  type NodeDeviceSystemFirmware struct {
   154  	Vendor      string `xml:"vendor"`
   155  	Version     string `xml:"version"`
   156  	ReleaseData string `xml:"release_date"`
   157  }
   158  
   159  type NodeDeviceSystemCapability struct {
   160  	Product  string                    `xml:"product,omitempty"`
   161  	Hardware *NodeDeviceSystemHardware `xml:"hardware"`
   162  	Firmware *NodeDeviceSystemFirmware `xml:"firmware"`
   163  }
   164  
   165  type NodeDeviceUSBDeviceCapability struct {
   166  	Bus     int              `xml:"bus"`
   167  	Device  int              `xml:"device"`
   168  	Product NodeDeviceIDName `xml:"product,omitempty"`
   169  	Vendor  NodeDeviceIDName `xml:"vendor,omitempty"`
   170  }
   171  
   172  type NodeDeviceUSBCapability struct {
   173  	Number      int    `xml:"number"`
   174  	Class       int    `xml:"class"`
   175  	Subclass    int    `xml:"subclass"`
   176  	Protocol    int    `xml:"protocol"`
   177  	Description string `xml:"description,omitempty"`
   178  }
   179  
   180  type NodeDeviceNetOffloadFeatures struct {
   181  	Name string `xml:"name,attr"`
   182  }
   183  
   184  type NodeDeviceNetLink struct {
   185  	State string `xml:"state,attr"`
   186  	Speed string `xml:"speed,attr,omitempty"`
   187  }
   188  
   189  type NodeDeviceNetSubCapability struct {
   190  	Wireless80211 *NodeDeviceNet80211Capability
   191  	Ethernet80203 *NodeDeviceNet80203Capability
   192  }
   193  
   194  type NodeDeviceNet80211Capability struct {
   195  }
   196  
   197  type NodeDeviceNet80203Capability struct {
   198  }
   199  
   200  type NodeDeviceNetCapability struct {
   201  	Interface  string                         `xml:"interface"`
   202  	Address    string                         `xml:"address"`
   203  	Link       *NodeDeviceNetLink             `xml:"link"`
   204  	Features   []NodeDeviceNetOffloadFeatures `xml:"feature,omitempty"`
   205  	Capability []NodeDeviceNetSubCapability   `xml:"capability"`
   206  }
   207  
   208  type NodeDeviceSCSIVPortOpsCapability struct {
   209  	VPorts    int `xml:"vports,omitempty"`
   210  	MaxVPorts int `xml:"maxvports,omitempty"`
   211  }
   212  
   213  type NodeDeviceSCSIFCHostCapability struct {
   214  	WWNN      string `xml:"wwnn,omitempty"`
   215  	WWPN      string `xml:"wwpn,omitempty"`
   216  	FabricWWN string `xml:"fabric_wwn,omitempty"`
   217  }
   218  
   219  type NodeDeviceSCSIHostSubCapability struct {
   220  	VPortOps *NodeDeviceSCSIVPortOpsCapability
   221  	FCHost   *NodeDeviceSCSIFCHostCapability
   222  }
   223  
   224  type NodeDeviceSCSIHostCapability struct {
   225  	Host       uint                              `xml:"host"`
   226  	UniqueID   *uint                             `xml:"unique_id"`
   227  	Capability []NodeDeviceSCSIHostSubCapability `xml:"capability"`
   228  }
   229  
   230  type NodeDeviceSCSITargetCapability struct {
   231  	Target     string                              `xml:"target"`
   232  	Capability []NodeDeviceSCSITargetSubCapability `xml:"capability"`
   233  }
   234  
   235  type NodeDeviceSCSITargetSubCapability struct {
   236  	FCRemotePort *NodeDeviceSCSIFCRemotePortCapability
   237  }
   238  
   239  type NodeDeviceSCSIFCRemotePortCapability struct {
   240  	RPort string `xml:"rport"`
   241  	WWPN  string `xml:"wwpn"`
   242  }
   243  
   244  type NodeDeviceSCSICapability struct {
   245  	Host   int    `xml:"host"`
   246  	Bus    int    `xml:"bus"`
   247  	Target int    `xml:"target"`
   248  	Lun    int    `xml:"lun"`
   249  	Type   string `xml:"type"`
   250  }
   251  
   252  type NodeDeviceStorageSubCapability struct {
   253  	Removable *NodeDeviceStorageRemovableCapability
   254  }
   255  
   256  type NodeDeviceStorageRemovableCapability struct {
   257  	MediaAvailable   *uint  `xml:"media_available"`
   258  	MediaSize        *uint  `xml:"media_size"`
   259  	MediaLabel       string `xml:"media_label,omitempty"`
   260  	LogicalBlockSize *uint  `xml:"logical_block_size"`
   261  	NumBlocks        *uint  `xml:"num_blocks"`
   262  }
   263  
   264  type NodeDeviceStorageCapability struct {
   265  	Block            string                           `xml:"block,omitempty"`
   266  	Bus              string                           `xml:"bus,omitempty"`
   267  	DriverType       string                           `xml:"drive_type,omitempty"`
   268  	Model            string                           `xml:"model,omitempty"`
   269  	Vendor           string                           `xml:"vendor,omitempty"`
   270  	Serial           string                           `xml:"serial,omitempty"`
   271  	Size             *uint                            `xml:"size"`
   272  	LogicalBlockSize *uint                            `xml:"logical_block_size"`
   273  	NumBlocks        *uint                            `xml:"num_blocks"`
   274  	Capability       []NodeDeviceStorageSubCapability `xml:"capability"`
   275  }
   276  
   277  type NodeDeviceDRMCapability struct {
   278  	Type string `xml:"type"`
   279  }
   280  
   281  type NodeDeviceCCWCapability struct {
   282  	CSSID *uint `xml:"cssid"`
   283  	SSID  *uint `xml:"ssid"`
   284  	DevNo *uint `xml:"devno"`
   285  }
   286  
   287  type NodeDeviceMDevCapability struct {
   288  	Type       *NodeDeviceMDevCapabilityType `xml:"type"`
   289  	IOMMUGroup *NodeDeviceIOMMUGroup         `xml:"iommuGroup"`
   290  }
   291  
   292  type NodeDeviceMDevCapabilityType struct {
   293  	ID string `xml:"id,attr"`
   294  }
   295  
   296  func (a *NodeDevicePCIAddress) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   297  	marshalUintAttr(&start, "domain", a.Domain, "0x%04x")
   298  	marshalUintAttr(&start, "bus", a.Bus, "0x%02x")
   299  	marshalUintAttr(&start, "slot", a.Slot, "0x%02x")
   300  	marshalUintAttr(&start, "function", a.Function, "0x%x")
   301  	e.EncodeToken(start)
   302  	e.EncodeToken(start.End())
   303  	return nil
   304  }
   305  
   306  func (a *NodeDevicePCIAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   307  	for _, attr := range start.Attr {
   308  		if attr.Name.Local == "domain" {
   309  			if err := unmarshalUintAttr(attr.Value, &a.Domain, 0); err != nil {
   310  				return err
   311  			}
   312  		} else if attr.Name.Local == "bus" {
   313  			if err := unmarshalUintAttr(attr.Value, &a.Bus, 0); err != nil {
   314  				return err
   315  			}
   316  		} else if attr.Name.Local == "slot" {
   317  			if err := unmarshalUintAttr(attr.Value, &a.Slot, 0); err != nil {
   318  				return err
   319  			}
   320  		} else if attr.Name.Local == "function" {
   321  			if err := unmarshalUintAttr(attr.Value, &a.Function, 0); err != nil {
   322  				return err
   323  			}
   324  		}
   325  	}
   326  	d.Skip()
   327  	return nil
   328  }
   329  
   330  func (c *NodeDeviceCCWCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   331  	e.EncodeToken(start)
   332  	if c.CSSID != nil {
   333  		cssid := xml.StartElement{
   334  			Name: xml.Name{Local: "cssid"},
   335  		}
   336  		e.EncodeToken(cssid)
   337  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.CSSID)))
   338  		e.EncodeToken(cssid.End())
   339  	}
   340  	if c.SSID != nil {
   341  		ssid := xml.StartElement{
   342  			Name: xml.Name{Local: "ssid"},
   343  		}
   344  		e.EncodeToken(ssid)
   345  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.SSID)))
   346  		e.EncodeToken(ssid.End())
   347  	}
   348  	if c.DevNo != nil {
   349  		devno := xml.StartElement{
   350  			Name: xml.Name{Local: "devno"},
   351  		}
   352  		e.EncodeToken(devno)
   353  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%04x", *c.DevNo)))
   354  		e.EncodeToken(devno.End())
   355  	}
   356  	e.EncodeToken(start.End())
   357  	return nil
   358  }
   359  
   360  func (c *NodeDeviceCCWCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   361  	for {
   362  		tok, err := d.Token()
   363  		if err == io.EOF {
   364  			break
   365  		}
   366  		if err != nil {
   367  			return err
   368  		}
   369  
   370  		switch tok := tok.(type) {
   371  		case xml.StartElement:
   372  			cdata, err := d.Token()
   373  			if err != nil {
   374  				return err
   375  			}
   376  
   377  			if tok.Name.Local != "cssid" &&
   378  				tok.Name.Local != "ssid" &&
   379  				tok.Name.Local != "devno" {
   380  				continue
   381  			}
   382  
   383  			chardata, ok := cdata.(xml.CharData)
   384  			if !ok {
   385  				return fmt.Errorf("Expected text for CCW '%s'", tok.Name.Local)
   386  			}
   387  
   388  			valstr := strings.TrimPrefix(string(chardata), "0x")
   389  			val, err := strconv.ParseUint(valstr, 16, 64)
   390  			if err != nil {
   391  				return err
   392  			}
   393  
   394  			vali := uint(val)
   395  			if tok.Name.Local == "cssid" {
   396  				c.CSSID = &vali
   397  			} else if tok.Name.Local == "ssid" {
   398  				c.SSID = &vali
   399  			} else if tok.Name.Local == "devno" {
   400  				c.DevNo = &vali
   401  			}
   402  		}
   403  	}
   404  	return nil
   405  }
   406  
   407  func (c *NodeDevicePCISubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   408  	typ, ok := getAttr(start.Attr, "type")
   409  	if !ok {
   410  		return fmt.Errorf("Missing node device capability type")
   411  	}
   412  
   413  	switch typ {
   414  	case "virt_functions":
   415  		var virtFuncCaps NodeDevicePCIVirtFunctionsCapability
   416  		if err := d.DecodeElement(&virtFuncCaps, &start); err != nil {
   417  			return err
   418  		}
   419  		c.VirtFunctions = &virtFuncCaps
   420  	case "phys_function":
   421  		var physFuncCaps NodeDevicePCIPhysFunctionCapability
   422  		if err := d.DecodeElement(&physFuncCaps, &start); err != nil {
   423  			return err
   424  		}
   425  		c.PhysFunction = &physFuncCaps
   426  	case "mdev_types":
   427  		var mdevTypeCaps NodeDevicePCIMDevTypesCapability
   428  		if err := d.DecodeElement(&mdevTypeCaps, &start); err != nil {
   429  			return err
   430  		}
   431  		c.MDevTypes = &mdevTypeCaps
   432  	case "pci-bridge":
   433  		var bridgeCaps NodeDevicePCIBridgeCapability
   434  		if err := d.DecodeElement(&bridgeCaps, &start); err != nil {
   435  			return err
   436  		}
   437  		c.Bridge = &bridgeCaps
   438  	}
   439  	d.Skip()
   440  	return nil
   441  }
   442  
   443  func (c *NodeDevicePCISubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   444  	if c.VirtFunctions != nil {
   445  		start.Attr = append(start.Attr, xml.Attr{
   446  			xml.Name{Local: "type"}, "virt_functions",
   447  		})
   448  		return e.EncodeElement(c.VirtFunctions, start)
   449  	} else if c.PhysFunction != nil {
   450  		start.Attr = append(start.Attr, xml.Attr{
   451  			xml.Name{Local: "type"}, "phys_function",
   452  		})
   453  		return e.EncodeElement(c.PhysFunction, start)
   454  	} else if c.MDevTypes != nil {
   455  		start.Attr = append(start.Attr, xml.Attr{
   456  			xml.Name{Local: "type"}, "mdev_types",
   457  		})
   458  		return e.EncodeElement(c.MDevTypes, start)
   459  	} else if c.Bridge != nil {
   460  		start.Attr = append(start.Attr, xml.Attr{
   461  			xml.Name{Local: "type"}, "pci-bridge",
   462  		})
   463  		return e.EncodeElement(c.Bridge, start)
   464  	}
   465  	return nil
   466  }
   467  
   468  func (c *NodeDeviceSCSITargetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   469  	typ, ok := getAttr(start.Attr, "type")
   470  	if !ok {
   471  		return fmt.Errorf("Missing node device capability type")
   472  	}
   473  
   474  	switch typ {
   475  	case "fc_remote_port":
   476  		var fcCaps NodeDeviceSCSIFCRemotePortCapability
   477  		if err := d.DecodeElement(&fcCaps, &start); err != nil {
   478  			return err
   479  		}
   480  		c.FCRemotePort = &fcCaps
   481  	}
   482  	d.Skip()
   483  	return nil
   484  }
   485  
   486  func (c *NodeDeviceSCSITargetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   487  	if c.FCRemotePort != nil {
   488  		start.Attr = append(start.Attr, xml.Attr{
   489  			xml.Name{Local: "type"}, "fc_remote_port",
   490  		})
   491  		return e.EncodeElement(c.FCRemotePort, start)
   492  	}
   493  	return nil
   494  }
   495  
   496  func (c *NodeDeviceSCSIHostSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   497  	typ, ok := getAttr(start.Attr, "type")
   498  	if !ok {
   499  		return fmt.Errorf("Missing node device capability type")
   500  	}
   501  
   502  	switch typ {
   503  	case "fc_host":
   504  		var fcCaps NodeDeviceSCSIFCHostCapability
   505  		if err := d.DecodeElement(&fcCaps, &start); err != nil {
   506  			return err
   507  		}
   508  		c.FCHost = &fcCaps
   509  	case "vport_ops":
   510  		var vportCaps NodeDeviceSCSIVPortOpsCapability
   511  		if err := d.DecodeElement(&vportCaps, &start); err != nil {
   512  			return err
   513  		}
   514  		c.VPortOps = &vportCaps
   515  	}
   516  	d.Skip()
   517  	return nil
   518  }
   519  
   520  func (c *NodeDeviceSCSIHostSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   521  	if c.FCHost != nil {
   522  		start.Attr = append(start.Attr, xml.Attr{
   523  			xml.Name{Local: "type"}, "fc_host",
   524  		})
   525  		return e.EncodeElement(c.FCHost, start)
   526  	} else if c.VPortOps != nil {
   527  		start.Attr = append(start.Attr, xml.Attr{
   528  			xml.Name{Local: "type"}, "vport_ops",
   529  		})
   530  		return e.EncodeElement(c.VPortOps, start)
   531  	}
   532  	return nil
   533  }
   534  
   535  func (c *NodeDeviceStorageSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   536  	typ, ok := getAttr(start.Attr, "type")
   537  	if !ok {
   538  		return fmt.Errorf("Missing node device capability type")
   539  	}
   540  
   541  	switch typ {
   542  	case "removable":
   543  		var removeCaps NodeDeviceStorageRemovableCapability
   544  		if err := d.DecodeElement(&removeCaps, &start); err != nil {
   545  			return err
   546  		}
   547  		c.Removable = &removeCaps
   548  	}
   549  	d.Skip()
   550  	return nil
   551  }
   552  
   553  func (c *NodeDeviceStorageSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   554  	if c.Removable != nil {
   555  		start.Attr = append(start.Attr, xml.Attr{
   556  			xml.Name{Local: "type"}, "removable",
   557  		})
   558  		return e.EncodeElement(c.Removable, start)
   559  	}
   560  	return nil
   561  }
   562  
   563  func (c *NodeDeviceNetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   564  	typ, ok := getAttr(start.Attr, "type")
   565  	if !ok {
   566  		return fmt.Errorf("Missing node device capability type")
   567  	}
   568  
   569  	switch typ {
   570  	case "80211":
   571  		var wlanCaps NodeDeviceNet80211Capability
   572  		if err := d.DecodeElement(&wlanCaps, &start); err != nil {
   573  			return err
   574  		}
   575  		c.Wireless80211 = &wlanCaps
   576  	case "80203":
   577  		var ethCaps NodeDeviceNet80203Capability
   578  		if err := d.DecodeElement(&ethCaps, &start); err != nil {
   579  			return err
   580  		}
   581  		c.Ethernet80203 = &ethCaps
   582  	}
   583  	d.Skip()
   584  	return nil
   585  }
   586  
   587  func (c *NodeDeviceNetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   588  	if c.Wireless80211 != nil {
   589  		start.Attr = append(start.Attr, xml.Attr{
   590  			xml.Name{Local: "type"}, "80211",
   591  		})
   592  		return e.EncodeElement(c.Wireless80211, start)
   593  	} else if c.Ethernet80203 != nil {
   594  		start.Attr = append(start.Attr, xml.Attr{
   595  			xml.Name{Local: "type"}, "80203",
   596  		})
   597  		return e.EncodeElement(c.Ethernet80203, start)
   598  	}
   599  	return nil
   600  }
   601  
   602  func (c *NodeDeviceCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   603  	typ, ok := getAttr(start.Attr, "type")
   604  	if !ok {
   605  		return fmt.Errorf("Missing node device capability type")
   606  	}
   607  
   608  	switch typ {
   609  	case "pci":
   610  		var pciCaps NodeDevicePCICapability
   611  		if err := d.DecodeElement(&pciCaps, &start); err != nil {
   612  			return err
   613  		}
   614  		c.PCI = &pciCaps
   615  	case "system":
   616  		var systemCaps NodeDeviceSystemCapability
   617  		if err := d.DecodeElement(&systemCaps, &start); err != nil {
   618  			return err
   619  		}
   620  		c.System = &systemCaps
   621  	case "usb_device":
   622  		var usbdevCaps NodeDeviceUSBDeviceCapability
   623  		if err := d.DecodeElement(&usbdevCaps, &start); err != nil {
   624  			return err
   625  		}
   626  		c.USBDevice = &usbdevCaps
   627  	case "usb":
   628  		var usbCaps NodeDeviceUSBCapability
   629  		if err := d.DecodeElement(&usbCaps, &start); err != nil {
   630  			return err
   631  		}
   632  		c.USB = &usbCaps
   633  	case "net":
   634  		var netCaps NodeDeviceNetCapability
   635  		if err := d.DecodeElement(&netCaps, &start); err != nil {
   636  			return err
   637  		}
   638  		c.Net = &netCaps
   639  	case "scsi_host":
   640  		var scsiHostCaps NodeDeviceSCSIHostCapability
   641  		if err := d.DecodeElement(&scsiHostCaps, &start); err != nil {
   642  			return err
   643  		}
   644  		c.SCSIHost = &scsiHostCaps
   645  	case "scsi_target":
   646  		var scsiTargetCaps NodeDeviceSCSITargetCapability
   647  		if err := d.DecodeElement(&scsiTargetCaps, &start); err != nil {
   648  			return err
   649  		}
   650  		c.SCSITarget = &scsiTargetCaps
   651  	case "scsi":
   652  		var scsiCaps NodeDeviceSCSICapability
   653  		if err := d.DecodeElement(&scsiCaps, &start); err != nil {
   654  			return err
   655  		}
   656  		c.SCSI = &scsiCaps
   657  	case "storage":
   658  		var storageCaps NodeDeviceStorageCapability
   659  		if err := d.DecodeElement(&storageCaps, &start); err != nil {
   660  			return err
   661  		}
   662  		c.Storage = &storageCaps
   663  	case "drm":
   664  		var drmCaps NodeDeviceDRMCapability
   665  		if err := d.DecodeElement(&drmCaps, &start); err != nil {
   666  			return err
   667  		}
   668  		c.DRM = &drmCaps
   669  	case "ccw":
   670  		var ccwCaps NodeDeviceCCWCapability
   671  		if err := d.DecodeElement(&ccwCaps, &start); err != nil {
   672  			return err
   673  		}
   674  		c.CCW = &ccwCaps
   675  	case "mdev":
   676  		var mdevCaps NodeDeviceMDevCapability
   677  		if err := d.DecodeElement(&mdevCaps, &start); err != nil {
   678  			return err
   679  		}
   680  		c.MDev = &mdevCaps
   681  	}
   682  	d.Skip()
   683  	return nil
   684  }
   685  
   686  func (c *NodeDeviceCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   687  	if c.PCI != nil {
   688  		start.Attr = append(start.Attr, xml.Attr{
   689  			xml.Name{Local: "type"}, "pci",
   690  		})
   691  		return e.EncodeElement(c.PCI, start)
   692  	} else if c.System != nil {
   693  		start.Attr = append(start.Attr, xml.Attr{
   694  			xml.Name{Local: "type"}, "system",
   695  		})
   696  		return e.EncodeElement(c.System, start)
   697  	} else if c.USB != nil {
   698  		start.Attr = append(start.Attr, xml.Attr{
   699  			xml.Name{Local: "type"}, "usb",
   700  		})
   701  		return e.EncodeElement(c.USB, start)
   702  	} else if c.USBDevice != nil {
   703  		start.Attr = append(start.Attr, xml.Attr{
   704  			xml.Name{Local: "type"}, "usb_device",
   705  		})
   706  		return e.EncodeElement(c.USBDevice, start)
   707  	} else if c.Net != nil {
   708  		start.Attr = append(start.Attr, xml.Attr{
   709  			xml.Name{Local: "type"}, "net",
   710  		})
   711  		return e.EncodeElement(c.Net, start)
   712  	} else if c.SCSI != nil {
   713  		start.Attr = append(start.Attr, xml.Attr{
   714  			xml.Name{Local: "type"}, "scsi",
   715  		})
   716  		return e.EncodeElement(c.SCSI, start)
   717  	} else if c.SCSIHost != nil {
   718  		start.Attr = append(start.Attr, xml.Attr{
   719  			xml.Name{Local: "type"}, "scsi_host",
   720  		})
   721  		return e.EncodeElement(c.SCSIHost, start)
   722  	} else if c.SCSITarget != nil {
   723  		start.Attr = append(start.Attr, xml.Attr{
   724  			xml.Name{Local: "type"}, "scsi_target",
   725  		})
   726  		return e.EncodeElement(c.SCSITarget, start)
   727  	} else if c.Storage != nil {
   728  		start.Attr = append(start.Attr, xml.Attr{
   729  			xml.Name{Local: "type"}, "storage",
   730  		})
   731  		return e.EncodeElement(c.Storage, start)
   732  	} else if c.DRM != nil {
   733  		start.Attr = append(start.Attr, xml.Attr{
   734  			xml.Name{Local: "type"}, "drm",
   735  		})
   736  		return e.EncodeElement(c.DRM, start)
   737  	} else if c.CCW != nil {
   738  		start.Attr = append(start.Attr, xml.Attr{
   739  			xml.Name{Local: "type"}, "ccw",
   740  		})
   741  		return e.EncodeElement(c.CCW, start)
   742  	} else if c.MDev != nil {
   743  		start.Attr = append(start.Attr, xml.Attr{
   744  			xml.Name{Local: "type"}, "mdev",
   745  		})
   746  		return e.EncodeElement(c.MDev, start)
   747  	}
   748  	return nil
   749  }
   750  
   751  func (c *NodeDevice) Unmarshal(doc string) error {
   752  	return xml.Unmarshal([]byte(doc), c)
   753  }
   754  
   755  func (c *NodeDevice) Marshal() (string, error) {
   756  	doc, err := xml.MarshalIndent(c, "", "  ")
   757  	if err != nil {
   758  		return "", err
   759  	}
   760  	return string(doc), nil
   761  }