node_device.go 21 KB

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