Signed-off-by: Alexey Slaykovsky <aslaikov(a)redhat.com>
---
domain.go | 9 +-
domain_test.go | 8 +-
memory.go | 31 +++++
storage.go | 159 ++++++++++++++++++++++
storage_test.go | 413 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 609 insertions(+), 11 deletions(-)
create mode 100644 memory.go
create mode 100644 storage.go
create mode 100644 storage_test.go
diff --git a/domain.go b/domain.go
index ec2bd02..f8833a1 100644
--- a/domain.go
+++ b/domain.go
@@ -121,11 +121,6 @@ type DomainDeviceList struct {
Videos []DomainVideo `xml:"video"`
}
-type DomainMemory struct {
- Value string `xml:",chardata"`
- Unit string `xml:"unit,attr"`
-}
-
type DomainOSType struct {
Arch string `xml:"arch,attr"`
Machine string `xml:"machine,attr"`
@@ -194,8 +189,8 @@ type Domain struct {
Type string `xml:"type,attr"`
Name string `xml:"name"`
UUID *string `xml:"uuid"`
- Memory *DomainMemory `xml:"memory"`
- CurrentMemory *DomainMemory `xml:"currentMemory"`
+ Memory *Memory `xml:"memory"`
+ CurrentMemory *Memory `xml:"currentMemory"`
Devices *DomainDeviceList `xml:"devices"`
OS *DomainOS `xml:"os"`
SysInfo *DomainSysInfo `xml:"sysinfo"`
diff --git a/domain_test.go b/domain_test.go
index ae262e5..c22c384 100644
--- a/domain_test.go
+++ b/domain_test.go
@@ -125,13 +125,13 @@ var domainTestData = []struct {
Object: &Domain{
Type: "kvm",
Name: "test",
- Memory: &DomainMemory{
+ Memory: &Memory{
Unit: "KiB",
- Value: "8192",
+ Value: 8192,
},
- CurrentMemory: &DomainMemory{
+ CurrentMemory: &Memory{
Unit: "KiB",
- Value: "4096",
+ Value: 4096,
},
OS: &DomainOS{
Type: &DomainOSType{
diff --git a/memory.go b/memory.go
new file mode 100644
index 0000000..78844ac
--- /dev/null
+++ b/memory.go
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the libvirt-go-xml project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ */
+
+package libvirtxml
+
+type Memory struct {
+ Unit string `xml:"unit,attr,omitempty"`
+ Value uint64 `xml:",chardata"`
+}
diff --git a/storage.go b/storage.go
new file mode 100644
index 0000000..eccbee5
--- /dev/null
+++ b/storage.go
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the libvirt-go-xml project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ */
+
+package libvirtxml
+
+import "encoding/xml"
+
+type StorageFormat struct {
+ Type string `xml:"type,attr"`
+}
+
+type StoragePermissions struct {
+ Owner string `xml:"owner,omitempty"`
+ Group string `xml:"group,omitempty"`
+ Mode string `xml:"mode,omitempty"`
+ Label string `xml:"label,omitempty"`
+}
+
+type StorageTargetEncryptionSecret struct {
+ Type string `xml:"type,attr,omitempty"`
+ UUID string `xml:"uuid,attr,omitempty"`
+}
+
+type StorageTargetEncryption struct {
+ Type string `xml:"type,attr,omitempty"`
+ Format string `xml:"format,attr,omitempty"`
+ Secret *StorageTargetEncryptionSecret `xml:"secret"`
+}
+
+type StorageTargetTimestamps struct {
+ Atime string `xml:"atime"`
+ Mtime string `xml:"mtime"`
+ Ctime string `xml:"ctime"`
+}
+
+type StorageTargetFeature struct {
+ LazyRefcounts *struct{} `xml:"lazy_refcounts"`
+}
+
+type StorageTarget struct {
+ Path string `xml:"path,omitempty"`
+ Format *StorageFormat `xml:"format"`
+ Permissions *StoragePermissions `xml:"permissions"`
+ Timestamps *StorageTargetTimestamps `xml:"timestamps"`
+ Compat string `xml:"compat,omitempty"`
+ NoCOW *struct{} `xml:"nocow"`
+ Features []StorageTargetFeature `xml:"features"`
+ Encryption *StorageTargetEncryption `xml:"encryption"`
+}
+
+type StoragePoolSourceHost struct {
+ Name string `xml:"name,attr"`
+}
+
+type StoragePoolSourceDevice struct {
+ Path string `xml:"path,attr"`
+ PartSeparator string `xml:"part_separator,attr,omitempty"`
+}
+
+type StoragePoolSourceAuthSecret struct {
+ Usage string `xml:"usage,attr"`
+}
+
+type StoragePoolSourceAuth struct {
+ Type string `xml:"type,attr"`
+ Username string `xml:"username,attr"`
+ Secret *StoragePoolSourceAuthSecret `xml:"secret"`
+}
+
+type StoragePoolSourceVendor struct {
+ Name string `xml:"name,attr"`
+}
+
+type StoragePoolSourceProduct struct {
+ Name string `xml:"name,attr"`
+}
+
+type StoragePoolSourceAdapterParentAddrAddress struct {
+ Domain string `xml:"domain,attr"`
+ Bus string `xml:"bus,attr"`
+ Slot string `xml:"slot,attr"`
+ Addr string `xml:"addr,attr"`
+}
+
+type StoragePoolSourceAdapterParentAddr struct {
+ UniqueID uint64 `xml:"unique_id,attr"`
+ Address *StoragePoolSourceAdapterParentAddrAddress `xml:"address"`
+}
+
+type StoragePoolSourceAdapter struct {
+ Type string `xml:"type,attr"`
+ Name string `xml:"name,attr,omitempty"`
+ Parent string `xml:"parent,attr,omitempty"`
+ WWNN string `xml:"wwnn,attr,omitempty"`
+ WWPN string `xml:"wwpn,attr,omitempty"`
+ ParentAddr *StoragePoolSourceAdapterParentAddr `xml:"parentaddr"`
+}
+
+type StoragePoolSource struct {
+ Host *StoragePoolSourceHost `xml:"host"`
+ Device *StoragePoolSourceDevice `xml:"device"`
+ Auth *StoragePoolSourceAuth `xml:"auth"`
+ Vendor *StoragePoolSourceVendor `xml:"vendor"`
+ Product *StoragePoolSourceProduct `xml:"product"`
+ Format *StorageFormat `xml:"format"`
+ Adapter *StoragePoolSourceAdapter `xml:"adapter"`
+}
+
+type StoragePool struct {
+ XMLName xml.Name `xml:"pool"`
+ Type string `xml:"type,attr"`
+ Name string `xml:"name"`
+ UUID string `xml:"uuid,omitempty"`
+ Allocation *Memory `xml:"allocation"`
+ Capacity *Memory `xml:"capacity"`
+ Available *Memory `xml:"available"`
+ Target *StorageTarget `xml:"target"`
+ Source *StoragePoolSource `xml:"source"`
+}
+
+type StorageVolumeBackingStore struct {
+ Path string `xml:"path"`
+ Format *StorageFormat `xml:"format"`
+ Permissions *StoragePermissions `xml:"permissions"`
+}
+
+type StorageVolume struct {
+ XMLName xml.Name `xml:"volume"`
+ Type string `xml:"type,attr,omitempty"`
+ Name string `xml:"name"`
+ Key string `xml:"key,omitempty"`
+ Allocation *Memory `xml:"allocation"`
+ Capacity *Memory `xml:"capacity"`
+ Physical *Memory `xml:"physical"`
+ Target *StorageTarget `xml:"target"`
+ BackingStore *StorageVolumeBackingStore `xml:"backingStore"`
+}
diff --git a/storage_test.go b/storage_test.go
new file mode 100644
index 0000000..f47634a
--- /dev/null
+++ b/storage_test.go
@@ -0,0 +1,413 @@
+/*
+ * This file is part of the libvirt-go-xml project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ */
+
+package libvirtxml
+
+import (
+ "encoding/xml"
+ "strings"
+ "testing"
+)
+
+var storagePoolTestData = []struct {
+ Object *StoragePool
+ Expected []string
+}{
+ {
+ Object: &StoragePool{
+ Type: "dir",
+ Name: "pool",
+ UUID: "3e3fce45-4f53-4fa7-bb32-11f34168b82b",
+ Allocation: &Memory{
+ Value: 1000000,
+ },
+ Capacity: &Memory{
+ Value: 5000000,
+ },
+ Available: &Memory{
+ Value: 3000000,
+ },
+ },
+ Expected: []string{
+ `<pool type="dir">`,
+ ` <name>pool</name>`,
+ ` <uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid>`,
+ ` <allocation>1000000</allocation>`,
+ ` <capacity>5000000</capacity>`,
+ ` <available>3000000</available>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "iscsi",
+ Name: "pool",
+ Source: &StoragePoolSource{
+ Host: &StoragePoolSourceHost{
+ Name: "host.example.com",
+ },
+ Device: &StoragePoolSourceDevice{
+ Path: "pool.example.com:iscsi-pool",
+ },
+ Auth: &StoragePoolSourceAuth{
+ Type: "chap",
+ Username: "username",
+ Secret: &StoragePoolSourceAuthSecret{
+ Usage: "cluster",
+ },
+ },
+ Vendor: &StoragePoolSourceVendor{
+ Name: "vendor",
+ },
+ Product: &StoragePoolSourceProduct{
+ Name: "product",
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="iscsi">`,
+ ` <name>pool</name>`,
+ ` <source>`,
+ ` <host name="host.example.com"></host>`,
+ ` <device path="pool.example.com:iscsi-pool"></device>`,
+ ` <auth type="chap" username="username">`,
+ ` <secret usage="cluster"></secret>`,
+ ` </auth>`,
+ ` <vendor name="vendor"></vendor>`,
+ ` <product name="product"></product>`,
+ ` </source>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "disk",
+ Name: "pool",
+ Source: &StoragePoolSource{
+ Device: &StoragePoolSourceDevice{
+ Path: "/dev/mapper/pool",
+ PartSeparator: "no",
+ },
+ Format: &StorageFormat{
+ Type: "gpt",
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="disk">`,
+ ` <name>pool</name>`,
+ ` <source>`,
+ ` <device path="/dev/mapper/pool"
part_separator="no"></device>`,
+ ` <format type="gpt"></format>`,
+ ` </source>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "scsi",
+ Name: "pool",
+ Source: &StoragePoolSource{
+ Adapter: &StoragePoolSourceAdapter{
+ Type: "scsi_host",
+ Name: "scsi_host",
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="scsi">`,
+ ` <name>pool</name>`,
+ ` <source>`,
+ ` <adapter type="scsi_host"
name="scsi_host"></adapter>`,
+ ` </source>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "scsi",
+ Name: "pool",
+ Source: &StoragePoolSource{
+ Adapter: &StoragePoolSourceAdapter{
+ Type: "scsi_host",
+ ParentAddr: &StoragePoolSourceAdapterParentAddr{
+ UniqueID: 1,
+ Address: &StoragePoolSourceAdapterParentAddrAddress{
+ Domain: "0x0000",
+ Bus: "0x00",
+ Slot: "0x1f",
+ Addr: "0x2",
+ },
+ },
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="scsi">`,
+ ` <name>pool</name>`,
+ ` <source>`,
+ ` <adapter type="scsi_host">`,
+ ` <parentaddr unique_id="1">`,
+ ` <address domain="0x0000" bus="0x00"
slot="0x1f" addr="0x2"></address>`,
+ ` </parentaddr>`,
+ ` </adapter>`,
+ ` </source>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "fs",
+ Name: "pool",
+ Source: &StoragePoolSource{
+ Adapter: &StoragePoolSourceAdapter{
+ Type: "fc_host",
+ Parent: "scsi_parent",
+ WWNN: "20000000c9831b4b",
+ WWPN: "10000000c9831b4b",
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="fs">`,
+ ` <name>pool</name>`,
+ ` <source>`,
+ ` <adapter type="fc_host" parent="scsi_parent"
wwnn="20000000c9831b4b" wwpn="10000000c9831b4b"></adapter>`,
+ ` </source>`,
+ `</pool>`,
+ },
+ },
+ {
+ Object: &StoragePool{
+ Type: "dir",
+ Name: "pool",
+ Target: &StorageTarget{
+ Path: "/pool",
+ Permissions: &StoragePermissions{
+ Owner: "1",
+ Group: "1",
+ Mode: "0744",
+ Label: "pool",
+ },
+ },
+ },
+ Expected: []string{
+ `<pool type="dir">`,
+ ` <name>pool</name>`,
+ ` <target>`,
+ ` <path>/pool</path>`,
+ ` <permissions>`,
+ ` <owner>1</owner>`,
+ ` <group>1</group>`,
+ ` <mode>0744</mode>`,
+ ` <label>pool</label>`,
+ ` </permissions>`,
+ ` </target>`,
+ `</pool>`,
+ },
+ },
+}
+
+func TestStoragePool(t *testing.T) {
+ for _, test := range storagePoolTestData {
+ doc, err := xml.MarshalIndent(test.Object, "", " ")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expect := strings.Join(test.Expected, "\n")
+
+ if string(doc) != expect {
+ t.Fatal("Bad xml:\n", string(doc), "\n does not match\n", expect,
"\n")
+ }
+ }
+}
+
+var storageVolumeTestData = []struct {
+ Object *StorageVolume
+ Expected []string
+}{
+ {
+ Object: &StorageVolume{
+ Type: "file",
+ Name: "file.img",
+ Key: "/file.img",
+ Allocation: &Memory{
+ Value: 0,
+ },
+
+ Capacity: &Memory{
+ Unit: "T",
+ Value: 1,
+ },
+ },
+ Expected: []string{
+ `<volume type="file">`,
+ ` <name>file.img</name>`,
+ ` <key>/file.img</key>`,
+ ` <allocation>0</allocation>`,
+ ` <capacity unit="T">1</capacity>`,
+ `</volume>`,
+ },
+ },
+ {
+ Object: &StorageVolume{
+ Type: "file",
+ Name: "file.img",
+ Target: &StorageTarget{
+ Path: "/file.img",
+ Format: &StorageFormat{
+ Type: "qcow2",
+ },
+ Permissions: &StoragePermissions{
+ Owner: "107",
+ Group: "107",
+ Mode: "0744",
+ Label: "image",
+ },
+ Timestamps: &StorageTargetTimestamps{
+ Atime: "1341933637.273190990",
+ Mtime: "1341930622.047245868",
+ Ctime: "1341930622.047245868",
+ },
+ Compat: "1.1",
+ NoCOW: &struct{}{},
+ Features: []StorageTargetFeature{
+ StorageTargetFeature{
+ LazyRefcounts: &struct{}{},
+ },
+ },
+ },
+ },
+ Expected: []string{
+ `<volume type="file">`,
+ ` <name>file.img</name>`,
+ ` <target>`,
+ ` <path>/file.img</path>`,
+ ` <format type="qcow2"></format>`,
+ ` <permissions>`,
+ ` <owner>107</owner>`,
+ ` <group>107</group>`,
+ ` <mode>0744</mode>`,
+ ` <label>image</label>`,
+ ` </permissions>`,
+ ` <timestamps>`,
+ ` <atime>1341933637.273190990</atime>`,
+ ` <mtime>1341930622.047245868</mtime>`,
+ ` <ctime>1341930622.047245868</ctime>`,
+ ` </timestamps>`,
+ ` <compat>1.1</compat>`,
+ ` <nocow></nocow>`,
+ ` <features>`,
+ ` <lazy_refcounts></lazy_refcounts>`,
+ ` </features>`,
+ ` </target>`,
+ `</volume>`,
+ },
+ },
+ {
+ Object: &StorageVolume{
+ Type: "file",
+ Name: "file.img",
+ BackingStore: &StorageVolumeBackingStore{
+ Path: "/master.img",
+ Format: &StorageFormat{
+ Type: "raw",
+ },
+ Permissions: &StoragePermissions{
+ Owner: "107",
+ Group: "107",
+ Mode: "0744",
+ Label: "label",
+ },
+ },
+ },
+ Expected: []string{
+ `<volume type="file">`,
+ ` <name>file.img</name>`,
+ ` <backingStore>`,
+ ` <path>/master.img</path>`,
+ ` <format type="raw"></format>`,
+ ` <permissions>`,
+ ` <owner>107</owner>`,
+ ` <group>107</group>`,
+ ` <mode>0744</mode>`,
+ ` <label>label</label>`,
+ ` </permissions>`,
+ ` </backingStore>`,
+ `</volume>`,
+ },
+ },
+ {
+ Object: &StorageVolume{
+ Name: "luks.img",
+ Capacity: &Memory{
+ Unit: "G",
+ Value: 5,
+ },
+ Target: &StorageTarget{
+ Path: "/luks.img",
+ Format: &StorageFormat{
+ Type: "raw",
+ },
+ Encryption: &StorageTargetEncryption{
+ Format: "luks",
+ Secret: &StorageTargetEncryptionSecret{
+ Type: "passphrase",
+ UUID: "f52a81b2-424e-490c-823d-6bd4235bc572",
+ },
+ },
+ },
+ },
+ Expected: []string{
+ `<volume>`,
+ ` <name>luks.img</name>`,
+ ` <capacity unit="G">5</capacity>`,
+ ` <target>`,
+ ` <path>/luks.img</path>`,
+ ` <format type="raw"></format>`,
+ ` <encryption format="luks">`,
+ ` <secret type="passphrase"
uuid="f52a81b2-424e-490c-823d-6bd4235bc572"></secret>`,
+ ` </encryption>`,
+ ` </target>`,
+ `</volume>`,
+ },
+ },
+}
+
+func TestStorageVolume(t *testing.T) {
+ for _, test := range storageVolumeTestData {
+ doc, err := xml.MarshalIndent(test.Object, "", " ")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expect := strings.Join(test.Expected, "\n")
+
+ if string(doc) != expect {
+ t.Fatal("Bad xml:\n", string(doc), "\n does not match\n", expect,
"\n")
+ }
+ }
+}
--
2.11.0