Signed-off-by: Alexey Slaykovsky <aslaikov@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list