github.com/v21neolink/libvirt-go-xml@v1.0.5/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  	CSS        *NodeDeviceCSSCapability
    69  	APQueue    *NodeDeviceAPQueueCapability
    70  	APCard     *NodeDeviceAPCardCapability
    71  	APMatrix   *NodeDeviceAPMatrixCapability
    72  }
    73  
    74  type NodeDeviceIDName struct {
    75  	ID   string `xml:"id,attr"`
    76  	Name string `xml:",chardata"`
    77  }
    78  
    79  type NodeDevicePCIExpress struct {
    80  	Links []NodeDevicePCIExpressLink `xml:"link"`
    81  }
    82  
    83  type NodeDevicePCIExpressLink struct {
    84  	Validity string  `xml:"validity,attr,omitempty"`
    85  	Speed    float64 `xml:"speed,attr,omitempty"`
    86  	Port     *uint   `xml:"port,attr"`
    87  	Width    *uint   `xml:"width,attr"`
    88  }
    89  
    90  type NodeDeviceIOMMUGroup struct {
    91  	Number  int                    `xml:"number,attr"`
    92  	Address []NodeDevicePCIAddress `xml:"address"`
    93  }
    94  
    95  type NodeDeviceNUMA struct {
    96  	Node int `xml:"node,attr"`
    97  }
    98  
    99  type NodeDevicePCICapability struct {
   100  	Class        string                       `xml:"class,omitempty"`
   101  	Domain       *uint                        `xml:"domain"`
   102  	Bus          *uint                        `xml:"bus"`
   103  	Slot         *uint                        `xml:"slot"`
   104  	Function     *uint                        `xml:"function"`
   105  	Product      NodeDeviceIDName             `xml:"product,omitempty"`
   106  	Vendor       NodeDeviceIDName             `xml:"vendor,omitempty"`
   107  	IOMMUGroup   *NodeDeviceIOMMUGroup        `xml:"iommuGroup"`
   108  	NUMA         *NodeDeviceNUMA              `xml:"numa"`
   109  	PCIExpress   *NodeDevicePCIExpress        `xml:"pci-express"`
   110  	Capabilities []NodeDevicePCISubCapability `xml:"capability"`
   111  }
   112  
   113  type NodeDevicePCIAddress struct {
   114  	Domain   *uint `xml:"domain,attr"`
   115  	Bus      *uint `xml:"bus,attr"`
   116  	Slot     *uint `xml:"slot,attr"`
   117  	Function *uint `xml:"function,attr"`
   118  }
   119  
   120  type NodeDevicePCISubCapability struct {
   121  	VirtFunctions *NodeDevicePCIVirtFunctionsCapability
   122  	PhysFunction  *NodeDevicePCIPhysFunctionCapability
   123  	MDevTypes     *NodeDevicePCIMDevTypesCapability
   124  	Bridge        *NodeDevicePCIBridgeCapability
   125  }
   126  
   127  type NodeDevicePCIVirtFunctionsCapability struct {
   128  	Address  []NodeDevicePCIAddress `xml:"address,omitempty"`
   129  	MaxCount int                    `xml:"maxCount,attr,omitempty"`
   130  }
   131  
   132  type NodeDevicePCIPhysFunctionCapability struct {
   133  	Address NodeDevicePCIAddress `xml:"address,omitempty"`
   134  }
   135  
   136  type NodeDevicePCIMDevTypesCapability struct {
   137  	Types []NodeDeviceMDevType `xml:"type"`
   138  }
   139  
   140  type NodeDeviceMDevType struct {
   141  	ID                 string `xml:"id,attr"`
   142  	Name               string `xml:"name"`
   143  	DeviceAPI          string `xml:"deviceAPI"`
   144  	AvailableInstances uint   `xml:"availableInstances"`
   145  }
   146  
   147  type NodeDevicePCIBridgeCapability struct {
   148  }
   149  
   150  type NodeDeviceSystemHardware struct {
   151  	Vendor  string `xml:"vendor"`
   152  	Version string `xml:"version"`
   153  	Serial  string `xml:"serial"`
   154  	UUID    string `xml:"uuid"`
   155  }
   156  
   157  type NodeDeviceSystemFirmware struct {
   158  	Vendor      string `xml:"vendor"`
   159  	Version     string `xml:"version"`
   160  	ReleaseData string `xml:"release_date"`
   161  }
   162  
   163  type NodeDeviceSystemCapability struct {
   164  	Product  string                    `xml:"product,omitempty"`
   165  	Hardware *NodeDeviceSystemHardware `xml:"hardware"`
   166  	Firmware *NodeDeviceSystemFirmware `xml:"firmware"`
   167  }
   168  
   169  type NodeDeviceUSBDeviceCapability struct {
   170  	Bus     int              `xml:"bus"`
   171  	Device  int              `xml:"device"`
   172  	Product NodeDeviceIDName `xml:"product,omitempty"`
   173  	Vendor  NodeDeviceIDName `xml:"vendor,omitempty"`
   174  }
   175  
   176  type NodeDeviceUSBCapability struct {
   177  	Number      int    `xml:"number"`
   178  	Class       int    `xml:"class"`
   179  	Subclass    int    `xml:"subclass"`
   180  	Protocol    int    `xml:"protocol"`
   181  	Description string `xml:"description,omitempty"`
   182  }
   183  
   184  type NodeDeviceNetOffloadFeatures struct {
   185  	Name string `xml:"name,attr"`
   186  }
   187  
   188  type NodeDeviceNetLink struct {
   189  	State string `xml:"state,attr"`
   190  	Speed string `xml:"speed,attr,omitempty"`
   191  }
   192  
   193  type NodeDeviceNetSubCapability struct {
   194  	Wireless80211 *NodeDeviceNet80211Capability
   195  	Ethernet80203 *NodeDeviceNet80203Capability
   196  }
   197  
   198  type NodeDeviceNet80211Capability struct {
   199  }
   200  
   201  type NodeDeviceNet80203Capability struct {
   202  }
   203  
   204  type NodeDeviceNetCapability struct {
   205  	Interface  string                         `xml:"interface"`
   206  	Address    string                         `xml:"address"`
   207  	Link       *NodeDeviceNetLink             `xml:"link"`
   208  	Features   []NodeDeviceNetOffloadFeatures `xml:"feature,omitempty"`
   209  	Capability []NodeDeviceNetSubCapability   `xml:"capability"`
   210  }
   211  
   212  type NodeDeviceSCSIVPortOpsCapability struct {
   213  	VPorts    int `xml:"vports,omitempty"`
   214  	MaxVPorts int `xml:"maxvports,omitempty"`
   215  }
   216  
   217  type NodeDeviceSCSIFCHostCapability struct {
   218  	WWNN      string `xml:"wwnn,omitempty"`
   219  	WWPN      string `xml:"wwpn,omitempty"`
   220  	FabricWWN string `xml:"fabric_wwn,omitempty"`
   221  }
   222  
   223  type NodeDeviceSCSIHostSubCapability struct {
   224  	VPortOps *NodeDeviceSCSIVPortOpsCapability
   225  	FCHost   *NodeDeviceSCSIFCHostCapability
   226  }
   227  
   228  type NodeDeviceSCSIHostCapability struct {
   229  	Host       uint                              `xml:"host"`
   230  	UniqueID   *uint                             `xml:"unique_id"`
   231  	Capability []NodeDeviceSCSIHostSubCapability `xml:"capability"`
   232  }
   233  
   234  type NodeDeviceSCSITargetCapability struct {
   235  	Target     string                              `xml:"target"`
   236  	Capability []NodeDeviceSCSITargetSubCapability `xml:"capability"`
   237  }
   238  
   239  type NodeDeviceSCSITargetSubCapability struct {
   240  	FCRemotePort *NodeDeviceSCSIFCRemotePortCapability
   241  }
   242  
   243  type NodeDeviceSCSIFCRemotePortCapability struct {
   244  	RPort string `xml:"rport"`
   245  	WWPN  string `xml:"wwpn"`
   246  }
   247  
   248  type NodeDeviceSCSICapability struct {
   249  	Host   int    `xml:"host"`
   250  	Bus    int    `xml:"bus"`
   251  	Target int    `xml:"target"`
   252  	Lun    int    `xml:"lun"`
   253  	Type   string `xml:"type"`
   254  }
   255  
   256  type NodeDeviceStorageSubCapability struct {
   257  	Removable *NodeDeviceStorageRemovableCapability
   258  }
   259  
   260  type NodeDeviceStorageRemovableCapability struct {
   261  	MediaAvailable   *uint  `xml:"media_available"`
   262  	MediaSize        *uint  `xml:"media_size"`
   263  	MediaLabel       string `xml:"media_label,omitempty"`
   264  	LogicalBlockSize *uint  `xml:"logical_block_size"`
   265  	NumBlocks        *uint  `xml:"num_blocks"`
   266  }
   267  
   268  type NodeDeviceStorageCapability struct {
   269  	Block            string                           `xml:"block,omitempty"`
   270  	Bus              string                           `xml:"bus,omitempty"`
   271  	DriverType       string                           `xml:"drive_type,omitempty"`
   272  	Model            string                           `xml:"model,omitempty"`
   273  	Vendor           string                           `xml:"vendor,omitempty"`
   274  	Serial           string                           `xml:"serial,omitempty"`
   275  	Size             *uint                            `xml:"size"`
   276  	LogicalBlockSize *uint                            `xml:"logical_block_size"`
   277  	NumBlocks        *uint                            `xml:"num_blocks"`
   278  	Capability       []NodeDeviceStorageSubCapability `xml:"capability"`
   279  }
   280  
   281  type NodeDeviceDRMCapability struct {
   282  	Type string `xml:"type"`
   283  }
   284  
   285  type NodeDeviceCCWCapability struct {
   286  	CSSID *uint `xml:"cssid"`
   287  	SSID  *uint `xml:"ssid"`
   288  	DevNo *uint `xml:"devno"`
   289  }
   290  
   291  type NodeDeviceMDevCapability struct {
   292  	Type       *NodeDeviceMDevCapabilityType   `xml:"type"`
   293  	IOMMUGroup *NodeDeviceIOMMUGroup           `xml:"iommuGroup"`
   294  	UUID       string                          `xml:"uuid,omitempty"`
   295  	Attrs      []NodeDeviceMDevCapabilityAttrs `xml:"attr,omitempty"`
   296  }
   297  
   298  type NodeDeviceMDevCapabilityType struct {
   299  	ID string `xml:"id,attr"`
   300  }
   301  
   302  type NodeDeviceMDevCapabilityAttrs struct {
   303  	Name  string `xml:"name,attr"`
   304  	Value string `xml:"value,attr"`
   305  }
   306  
   307  type NodeDeviceCSSCapability struct {
   308  	CSSID        *uint                        `xml:"cssid"`
   309  	SSID         *uint                        `xml:"ssid"`
   310  	DevNo        *uint                        `xml:"devno"`
   311  	Capabilities []NodeDeviceCSSSubCapability `xml:"capability"`
   312  }
   313  
   314  type NodeDeviceCSSSubCapability struct {
   315  	MDevTypes *NodeDeviceCSSMDevTypesCapability
   316  }
   317  
   318  type NodeDeviceCSSMDevTypesCapability struct {
   319  	Types []NodeDeviceMDevType `xml:"type"`
   320  }
   321  
   322  type NodeDeviceAPQueueCapability struct {
   323  	APAdapter string `xml:"ap-adapter"`
   324  	APDomain  string `xml:"ap-domain"`
   325  }
   326  
   327  type NodeDeviceAPCardCapability struct {
   328  	APAdapter string `xml:"ap-adapter"`
   329  }
   330  
   331  type NodeDeviceAPMatrixCapability struct {
   332  	Capabilities []NodeDeviceAPMatrixSubCapability `xml:"capability"`
   333  }
   334  
   335  type NodeDeviceAPMatrixSubCapability struct {
   336  	MDevTypes *NodeDeviceAPMatrixMDevTypesCapability
   337  }
   338  
   339  type NodeDeviceAPMatrixMDevTypesCapability struct {
   340  	Types []NodeDeviceMDevType `xml:"type"`
   341  }
   342  
   343  func (a *NodeDevicePCIAddress) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   344  	marshalUintAttr(&start, "domain", a.Domain, "0x%04x")
   345  	marshalUintAttr(&start, "bus", a.Bus, "0x%02x")
   346  	marshalUintAttr(&start, "slot", a.Slot, "0x%02x")
   347  	marshalUintAttr(&start, "function", a.Function, "0x%x")
   348  	e.EncodeToken(start)
   349  	e.EncodeToken(start.End())
   350  	return nil
   351  }
   352  
   353  func (a *NodeDevicePCIAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   354  	for _, attr := range start.Attr {
   355  		if attr.Name.Local == "domain" {
   356  			if err := unmarshalUintAttr(attr.Value, &a.Domain, 0); err != nil {
   357  				return err
   358  			}
   359  		} else if attr.Name.Local == "bus" {
   360  			if err := unmarshalUintAttr(attr.Value, &a.Bus, 0); err != nil {
   361  				return err
   362  			}
   363  		} else if attr.Name.Local == "slot" {
   364  			if err := unmarshalUintAttr(attr.Value, &a.Slot, 0); err != nil {
   365  				return err
   366  			}
   367  		} else if attr.Name.Local == "function" {
   368  			if err := unmarshalUintAttr(attr.Value, &a.Function, 0); err != nil {
   369  				return err
   370  			}
   371  		}
   372  	}
   373  	d.Skip()
   374  	return nil
   375  }
   376  
   377  func (c *NodeDeviceCSSSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   378  	typ, ok := getAttr(start.Attr, "type")
   379  	if !ok {
   380  		return fmt.Errorf("Missing node device capability type")
   381  	}
   382  
   383  	switch typ {
   384  	case "mdev_types":
   385  		var mdevTypesCaps NodeDeviceCSSMDevTypesCapability
   386  		if err := d.DecodeElement(&mdevTypesCaps, &start); err != nil {
   387  			return err
   388  		}
   389  		c.MDevTypes = &mdevTypesCaps
   390  	}
   391  	d.Skip()
   392  	return nil
   393  }
   394  
   395  func (c *NodeDeviceCSSSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   396  	if c.MDevTypes != nil {
   397  		start.Attr = append(start.Attr, xml.Attr{
   398  			xml.Name{Local: "type"}, "mdev_types",
   399  		})
   400  		return e.EncodeElement(c.MDevTypes, start)
   401  	}
   402  	return nil
   403  }
   404  
   405  func (c *NodeDeviceCCWCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   406  	e.EncodeToken(start)
   407  	if c.CSSID != nil {
   408  		cssid := xml.StartElement{
   409  			Name: xml.Name{Local: "cssid"},
   410  		}
   411  		e.EncodeToken(cssid)
   412  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.CSSID)))
   413  		e.EncodeToken(cssid.End())
   414  	}
   415  	if c.SSID != nil {
   416  		ssid := xml.StartElement{
   417  			Name: xml.Name{Local: "ssid"},
   418  		}
   419  		e.EncodeToken(ssid)
   420  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.SSID)))
   421  		e.EncodeToken(ssid.End())
   422  	}
   423  	if c.DevNo != nil {
   424  		devno := xml.StartElement{
   425  			Name: xml.Name{Local: "devno"},
   426  		}
   427  		e.EncodeToken(devno)
   428  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%04x", *c.DevNo)))
   429  		e.EncodeToken(devno.End())
   430  	}
   431  	e.EncodeToken(start.End())
   432  	return nil
   433  }
   434  
   435  func (c *NodeDeviceCCWCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   436  	for {
   437  		tok, err := d.Token()
   438  		if err == io.EOF {
   439  			break
   440  		}
   441  		if err != nil {
   442  			return err
   443  		}
   444  
   445  		switch tok := tok.(type) {
   446  		case xml.StartElement:
   447  			cdata, err := d.Token()
   448  			if err != nil {
   449  				return err
   450  			}
   451  
   452  			if tok.Name.Local != "cssid" &&
   453  				tok.Name.Local != "ssid" &&
   454  				tok.Name.Local != "devno" {
   455  				continue
   456  			}
   457  
   458  			chardata, ok := cdata.(xml.CharData)
   459  			if !ok {
   460  				return fmt.Errorf("Expected text for CCW '%s'", tok.Name.Local)
   461  			}
   462  
   463  			valstr := strings.TrimPrefix(string(chardata), "0x")
   464  			val, err := strconv.ParseUint(valstr, 16, 64)
   465  			if err != nil {
   466  				return err
   467  			}
   468  
   469  			vali := uint(val)
   470  			if tok.Name.Local == "cssid" {
   471  				c.CSSID = &vali
   472  			} else if tok.Name.Local == "ssid" {
   473  				c.SSID = &vali
   474  			} else if tok.Name.Local == "devno" {
   475  				c.DevNo = &vali
   476  			}
   477  		}
   478  	}
   479  	return nil
   480  }
   481  
   482  func (c *NodeDeviceCSSCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   483  	e.EncodeToken(start)
   484  	if c.CSSID != nil {
   485  		cssid := xml.StartElement{
   486  			Name: xml.Name{Local: "cssid"},
   487  		}
   488  		e.EncodeToken(cssid)
   489  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.CSSID)))
   490  		e.EncodeToken(cssid.End())
   491  	}
   492  	if c.SSID != nil {
   493  		ssid := xml.StartElement{
   494  			Name: xml.Name{Local: "ssid"},
   495  		}
   496  		e.EncodeToken(ssid)
   497  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.SSID)))
   498  		e.EncodeToken(ssid.End())
   499  	}
   500  	if c.DevNo != nil {
   501  		devno := xml.StartElement{
   502  			Name: xml.Name{Local: "devno"},
   503  		}
   504  		e.EncodeToken(devno)
   505  		e.EncodeToken(xml.CharData(fmt.Sprintf("0x%04x", *c.DevNo)))
   506  		e.EncodeToken(devno.End())
   507  	}
   508  	if c.Capabilities != nil {
   509  		for _, subcap := range c.Capabilities {
   510  			start := xml.StartElement{
   511  				Name: xml.Name{Local: "capability"},
   512  			}
   513  			e.EncodeElement(&subcap, start)
   514  		}
   515  	}
   516  	e.EncodeToken(start.End())
   517  	return nil
   518  }
   519  
   520  func (c *NodeDeviceCSSCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   521  	for {
   522  		tok, err := d.Token()
   523  		if err == io.EOF {
   524  			break
   525  		}
   526  		if err != nil {
   527  			return err
   528  		}
   529  
   530  		switch tok := tok.(type) {
   531  		case xml.StartElement:
   532  			cdata, err := d.Token()
   533  			if err != nil {
   534  				return err
   535  			}
   536  
   537  			if tok.Name.Local == "capability" {
   538  				subcap := &NodeDeviceCSSSubCapability{}
   539  				err := d.DecodeElement(subcap, &tok)
   540  				if err != nil {
   541  					return err
   542  				}
   543  				c.Capabilities = append(c.Capabilities, *subcap)
   544  				continue
   545  			}
   546  
   547  			if tok.Name.Local != "cssid" &&
   548  				tok.Name.Local != "ssid" &&
   549  				tok.Name.Local != "devno" {
   550  				continue
   551  			}
   552  
   553  			chardata, ok := cdata.(xml.CharData)
   554  			if !ok {
   555  				return fmt.Errorf("Expected text for CSS '%s'", tok.Name.Local)
   556  			}
   557  
   558  			valstr := strings.TrimPrefix(string(chardata), "0x")
   559  			val, err := strconv.ParseUint(valstr, 16, 64)
   560  			if err != nil {
   561  				return err
   562  			}
   563  
   564  			vali := uint(val)
   565  			if tok.Name.Local == "cssid" {
   566  				c.CSSID = &vali
   567  			} else if tok.Name.Local == "ssid" {
   568  				c.SSID = &vali
   569  			} else if tok.Name.Local == "devno" {
   570  				c.DevNo = &vali
   571  			}
   572  		}
   573  	}
   574  	return nil
   575  }
   576  
   577  func (c *NodeDevicePCISubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   578  	typ, ok := getAttr(start.Attr, "type")
   579  	if !ok {
   580  		return fmt.Errorf("Missing node device capability type")
   581  	}
   582  
   583  	switch typ {
   584  	case "virt_functions":
   585  		var virtFuncCaps NodeDevicePCIVirtFunctionsCapability
   586  		if err := d.DecodeElement(&virtFuncCaps, &start); err != nil {
   587  			return err
   588  		}
   589  		c.VirtFunctions = &virtFuncCaps
   590  	case "phys_function":
   591  		var physFuncCaps NodeDevicePCIPhysFunctionCapability
   592  		if err := d.DecodeElement(&physFuncCaps, &start); err != nil {
   593  			return err
   594  		}
   595  		c.PhysFunction = &physFuncCaps
   596  	case "mdev_types":
   597  		var mdevTypeCaps NodeDevicePCIMDevTypesCapability
   598  		if err := d.DecodeElement(&mdevTypeCaps, &start); err != nil {
   599  			return err
   600  		}
   601  		c.MDevTypes = &mdevTypeCaps
   602  	case "pci-bridge":
   603  		var bridgeCaps NodeDevicePCIBridgeCapability
   604  		if err := d.DecodeElement(&bridgeCaps, &start); err != nil {
   605  			return err
   606  		}
   607  		c.Bridge = &bridgeCaps
   608  	}
   609  	d.Skip()
   610  	return nil
   611  }
   612  
   613  func (c *NodeDevicePCISubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   614  	if c.VirtFunctions != nil {
   615  		start.Attr = append(start.Attr, xml.Attr{
   616  			xml.Name{Local: "type"}, "virt_functions",
   617  		})
   618  		return e.EncodeElement(c.VirtFunctions, start)
   619  	} else if c.PhysFunction != nil {
   620  		start.Attr = append(start.Attr, xml.Attr{
   621  			xml.Name{Local: "type"}, "phys_function",
   622  		})
   623  		return e.EncodeElement(c.PhysFunction, start)
   624  	} else if c.MDevTypes != nil {
   625  		start.Attr = append(start.Attr, xml.Attr{
   626  			xml.Name{Local: "type"}, "mdev_types",
   627  		})
   628  		return e.EncodeElement(c.MDevTypes, start)
   629  	} else if c.Bridge != nil {
   630  		start.Attr = append(start.Attr, xml.Attr{
   631  			xml.Name{Local: "type"}, "pci-bridge",
   632  		})
   633  		return e.EncodeElement(c.Bridge, start)
   634  	}
   635  	return nil
   636  }
   637  
   638  func (c *NodeDeviceSCSITargetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   639  	typ, ok := getAttr(start.Attr, "type")
   640  	if !ok {
   641  		return fmt.Errorf("Missing node device capability type")
   642  	}
   643  
   644  	switch typ {
   645  	case "fc_remote_port":
   646  		var fcCaps NodeDeviceSCSIFCRemotePortCapability
   647  		if err := d.DecodeElement(&fcCaps, &start); err != nil {
   648  			return err
   649  		}
   650  		c.FCRemotePort = &fcCaps
   651  	}
   652  	d.Skip()
   653  	return nil
   654  }
   655  
   656  func (c *NodeDeviceSCSITargetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   657  	if c.FCRemotePort != nil {
   658  		start.Attr = append(start.Attr, xml.Attr{
   659  			xml.Name{Local: "type"}, "fc_remote_port",
   660  		})
   661  		return e.EncodeElement(c.FCRemotePort, start)
   662  	}
   663  	return nil
   664  }
   665  
   666  func (c *NodeDeviceSCSIHostSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   667  	typ, ok := getAttr(start.Attr, "type")
   668  	if !ok {
   669  		return fmt.Errorf("Missing node device capability type")
   670  	}
   671  
   672  	switch typ {
   673  	case "fc_host":
   674  		var fcCaps NodeDeviceSCSIFCHostCapability
   675  		if err := d.DecodeElement(&fcCaps, &start); err != nil {
   676  			return err
   677  		}
   678  		c.FCHost = &fcCaps
   679  	case "vport_ops":
   680  		var vportCaps NodeDeviceSCSIVPortOpsCapability
   681  		if err := d.DecodeElement(&vportCaps, &start); err != nil {
   682  			return err
   683  		}
   684  		c.VPortOps = &vportCaps
   685  	}
   686  	d.Skip()
   687  	return nil
   688  }
   689  
   690  func (c *NodeDeviceSCSIHostSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   691  	if c.FCHost != nil {
   692  		start.Attr = append(start.Attr, xml.Attr{
   693  			xml.Name{Local: "type"}, "fc_host",
   694  		})
   695  		return e.EncodeElement(c.FCHost, start)
   696  	} else if c.VPortOps != nil {
   697  		start.Attr = append(start.Attr, xml.Attr{
   698  			xml.Name{Local: "type"}, "vport_ops",
   699  		})
   700  		return e.EncodeElement(c.VPortOps, start)
   701  	}
   702  	return nil
   703  }
   704  
   705  func (c *NodeDeviceStorageSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   706  	typ, ok := getAttr(start.Attr, "type")
   707  	if !ok {
   708  		return fmt.Errorf("Missing node device capability type")
   709  	}
   710  
   711  	switch typ {
   712  	case "removable":
   713  		var removeCaps NodeDeviceStorageRemovableCapability
   714  		if err := d.DecodeElement(&removeCaps, &start); err != nil {
   715  			return err
   716  		}
   717  		c.Removable = &removeCaps
   718  	}
   719  	d.Skip()
   720  	return nil
   721  }
   722  
   723  func (c *NodeDeviceStorageSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   724  	if c.Removable != nil {
   725  		start.Attr = append(start.Attr, xml.Attr{
   726  			xml.Name{Local: "type"}, "removable",
   727  		})
   728  		return e.EncodeElement(c.Removable, start)
   729  	}
   730  	return nil
   731  }
   732  
   733  func (c *NodeDeviceNetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   734  	typ, ok := getAttr(start.Attr, "type")
   735  	if !ok {
   736  		return fmt.Errorf("Missing node device capability type")
   737  	}
   738  
   739  	switch typ {
   740  	case "80211":
   741  		var wlanCaps NodeDeviceNet80211Capability
   742  		if err := d.DecodeElement(&wlanCaps, &start); err != nil {
   743  			return err
   744  		}
   745  		c.Wireless80211 = &wlanCaps
   746  	case "80203":
   747  		var ethCaps NodeDeviceNet80203Capability
   748  		if err := d.DecodeElement(&ethCaps, &start); err != nil {
   749  			return err
   750  		}
   751  		c.Ethernet80203 = &ethCaps
   752  	}
   753  	d.Skip()
   754  	return nil
   755  }
   756  
   757  func (c *NodeDeviceNetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   758  	if c.Wireless80211 != nil {
   759  		start.Attr = append(start.Attr, xml.Attr{
   760  			xml.Name{Local: "type"}, "80211",
   761  		})
   762  		return e.EncodeElement(c.Wireless80211, start)
   763  	} else if c.Ethernet80203 != nil {
   764  		start.Attr = append(start.Attr, xml.Attr{
   765  			xml.Name{Local: "type"}, "80203",
   766  		})
   767  		return e.EncodeElement(c.Ethernet80203, start)
   768  	}
   769  	return nil
   770  }
   771  
   772  func (c *NodeDeviceAPMatrixSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   773  	typ, ok := getAttr(start.Attr, "type")
   774  	if !ok {
   775  		return fmt.Errorf("Missing node device capability type")
   776  	}
   777  
   778  	switch typ {
   779  	case "mdev_types":
   780  		var mdevTypeCaps NodeDeviceAPMatrixMDevTypesCapability
   781  		if err := d.DecodeElement(&mdevTypeCaps, &start); err != nil {
   782  			return err
   783  		}
   784  		c.MDevTypes = &mdevTypeCaps
   785  	}
   786  	d.Skip()
   787  	return nil
   788  }
   789  
   790  func (c *NodeDeviceAPMatrixSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   791  	if c.MDevTypes != nil {
   792  		start.Attr = append(start.Attr, xml.Attr{
   793  			xml.Name{Local: "type"}, "mdev_types",
   794  		})
   795  		return e.EncodeElement(c.MDevTypes, start)
   796  	}
   797  	return nil
   798  }
   799  
   800  func (c *NodeDeviceCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
   801  	typ, ok := getAttr(start.Attr, "type")
   802  	if !ok {
   803  		return fmt.Errorf("Missing node device capability type")
   804  	}
   805  
   806  	switch typ {
   807  	case "pci":
   808  		var pciCaps NodeDevicePCICapability
   809  		if err := d.DecodeElement(&pciCaps, &start); err != nil {
   810  			return err
   811  		}
   812  		c.PCI = &pciCaps
   813  	case "system":
   814  		var systemCaps NodeDeviceSystemCapability
   815  		if err := d.DecodeElement(&systemCaps, &start); err != nil {
   816  			return err
   817  		}
   818  		c.System = &systemCaps
   819  	case "usb_device":
   820  		var usbdevCaps NodeDeviceUSBDeviceCapability
   821  		if err := d.DecodeElement(&usbdevCaps, &start); err != nil {
   822  			return err
   823  		}
   824  		c.USBDevice = &usbdevCaps
   825  	case "usb":
   826  		var usbCaps NodeDeviceUSBCapability
   827  		if err := d.DecodeElement(&usbCaps, &start); err != nil {
   828  			return err
   829  		}
   830  		c.USB = &usbCaps
   831  	case "net":
   832  		var netCaps NodeDeviceNetCapability
   833  		if err := d.DecodeElement(&netCaps, &start); err != nil {
   834  			return err
   835  		}
   836  		c.Net = &netCaps
   837  	case "scsi_host":
   838  		var scsiHostCaps NodeDeviceSCSIHostCapability
   839  		if err := d.DecodeElement(&scsiHostCaps, &start); err != nil {
   840  			return err
   841  		}
   842  		c.SCSIHost = &scsiHostCaps
   843  	case "scsi_target":
   844  		var scsiTargetCaps NodeDeviceSCSITargetCapability
   845  		if err := d.DecodeElement(&scsiTargetCaps, &start); err != nil {
   846  			return err
   847  		}
   848  		c.SCSITarget = &scsiTargetCaps
   849  	case "scsi":
   850  		var scsiCaps NodeDeviceSCSICapability
   851  		if err := d.DecodeElement(&scsiCaps, &start); err != nil {
   852  			return err
   853  		}
   854  		c.SCSI = &scsiCaps
   855  	case "storage":
   856  		var storageCaps NodeDeviceStorageCapability
   857  		if err := d.DecodeElement(&storageCaps, &start); err != nil {
   858  			return err
   859  		}
   860  		c.Storage = &storageCaps
   861  	case "drm":
   862  		var drmCaps NodeDeviceDRMCapability
   863  		if err := d.DecodeElement(&drmCaps, &start); err != nil {
   864  			return err
   865  		}
   866  		c.DRM = &drmCaps
   867  	case "ccw":
   868  		var ccwCaps NodeDeviceCCWCapability
   869  		if err := d.DecodeElement(&ccwCaps, &start); err != nil {
   870  			return err
   871  		}
   872  		c.CCW = &ccwCaps
   873  	case "mdev":
   874  		var mdevCaps NodeDeviceMDevCapability
   875  		if err := d.DecodeElement(&mdevCaps, &start); err != nil {
   876  			return err
   877  		}
   878  		c.MDev = &mdevCaps
   879  	case "css":
   880  		var cssCaps NodeDeviceCSSCapability
   881  		if err := d.DecodeElement(&cssCaps, &start); err != nil {
   882  			return err
   883  		}
   884  		c.CSS = &cssCaps
   885  	case "ap_queue":
   886  		var apCaps NodeDeviceAPQueueCapability
   887  		if err := d.DecodeElement(&apCaps, &start); err != nil {
   888  			return err
   889  		}
   890  		c.APQueue = &apCaps
   891  	case "ap_matrix":
   892  		var apCaps NodeDeviceAPMatrixCapability
   893  		if err := d.DecodeElement(&apCaps, &start); err != nil {
   894  			return err
   895  		}
   896  		c.APMatrix = &apCaps
   897  	case "ap_card":
   898  		var apCaps NodeDeviceAPCardCapability
   899  		if err := d.DecodeElement(&apCaps, &start); err != nil {
   900  			return err
   901  		}
   902  		c.APCard = &apCaps
   903  	}
   904  	d.Skip()
   905  	return nil
   906  }
   907  
   908  func (c *NodeDeviceCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   909  	if c.PCI != nil {
   910  		start.Attr = append(start.Attr, xml.Attr{
   911  			xml.Name{Local: "type"}, "pci",
   912  		})
   913  		return e.EncodeElement(c.PCI, start)
   914  	} else if c.System != nil {
   915  		start.Attr = append(start.Attr, xml.Attr{
   916  			xml.Name{Local: "type"}, "system",
   917  		})
   918  		return e.EncodeElement(c.System, start)
   919  	} else if c.USB != nil {
   920  		start.Attr = append(start.Attr, xml.Attr{
   921  			xml.Name{Local: "type"}, "usb",
   922  		})
   923  		return e.EncodeElement(c.USB, start)
   924  	} else if c.USBDevice != nil {
   925  		start.Attr = append(start.Attr, xml.Attr{
   926  			xml.Name{Local: "type"}, "usb_device",
   927  		})
   928  		return e.EncodeElement(c.USBDevice, start)
   929  	} else if c.Net != nil {
   930  		start.Attr = append(start.Attr, xml.Attr{
   931  			xml.Name{Local: "type"}, "net",
   932  		})
   933  		return e.EncodeElement(c.Net, start)
   934  	} else if c.SCSI != nil {
   935  		start.Attr = append(start.Attr, xml.Attr{
   936  			xml.Name{Local: "type"}, "scsi",
   937  		})
   938  		return e.EncodeElement(c.SCSI, start)
   939  	} else if c.SCSIHost != nil {
   940  		start.Attr = append(start.Attr, xml.Attr{
   941  			xml.Name{Local: "type"}, "scsi_host",
   942  		})
   943  		return e.EncodeElement(c.SCSIHost, start)
   944  	} else if c.SCSITarget != nil {
   945  		start.Attr = append(start.Attr, xml.Attr{
   946  			xml.Name{Local: "type"}, "scsi_target",
   947  		})
   948  		return e.EncodeElement(c.SCSITarget, start)
   949  	} else if c.Storage != nil {
   950  		start.Attr = append(start.Attr, xml.Attr{
   951  			xml.Name{Local: "type"}, "storage",
   952  		})
   953  		return e.EncodeElement(c.Storage, start)
   954  	} else if c.DRM != nil {
   955  		start.Attr = append(start.Attr, xml.Attr{
   956  			xml.Name{Local: "type"}, "drm",
   957  		})
   958  		return e.EncodeElement(c.DRM, start)
   959  	} else if c.CCW != nil {
   960  		start.Attr = append(start.Attr, xml.Attr{
   961  			xml.Name{Local: "type"}, "ccw",
   962  		})
   963  		return e.EncodeElement(c.CCW, start)
   964  	} else if c.MDev != nil {
   965  		start.Attr = append(start.Attr, xml.Attr{
   966  			xml.Name{Local: "type"}, "mdev",
   967  		})
   968  		return e.EncodeElement(c.MDev, start)
   969  	} else if c.CSS != nil {
   970  		start.Attr = append(start.Attr, xml.Attr{
   971  			xml.Name{Local: "type"}, "css",
   972  		})
   973  		return e.EncodeElement(c.CSS, start)
   974  	} else if c.APQueue != nil {
   975  		start.Attr = append(start.Attr, xml.Attr{
   976  			xml.Name{Local: "type"}, "ap_queue",
   977  		})
   978  		return e.EncodeElement(c.APQueue, start)
   979  	} else if c.APCard != nil {
   980  		start.Attr = append(start.Attr, xml.Attr{
   981  			xml.Name{Local: "type"}, "ap_card",
   982  		})
   983  		return e.EncodeElement(c.APCard, start)
   984  	} else if c.APMatrix != nil {
   985  		start.Attr = append(start.Attr, xml.Attr{
   986  			xml.Name{Local: "type"}, "ap_matrix",
   987  		})
   988  		return e.EncodeElement(c.APMatrix, start)
   989  	}
   990  	return nil
   991  }
   992  
   993  func (c *NodeDevice) Unmarshal(doc string) error {
   994  	return xml.Unmarshal([]byte(doc), c)
   995  }
   996  
   997  func (c *NodeDevice) Marshal() (string, error) {
   998  	doc, err := xml.MarshalIndent(c, "", "  ")
   999  	if err != nil {
  1000  		return "", err
  1001  	}
  1002  	return string(doc), nil
  1003  }