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(ðCaps, &start); err != nil { 579 return err 580 } 581 c.Ethernet80203 = ðCaps 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 }