[libvirt] [PATCH go-xml] Added Storage Pool and Storage Volume XML schemes.
by Alexey Slaykovsky
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
7 years, 11 months
[libvirt] [PATCH 0/9] Qemu: s390: Cpu Model Support
by Jason J. Herne
This patch set enables cpu model support for s390. The user can now set exact
cpu models, query supported models via virsh domcapabilities, and use host-model
and host-passthrough modes. The end result is that migration is safer because
Qemu will perform runnability checking on the destination host and quit with an
error if the guest's cpu model is not supported.
Note: Some test data has been separated from corresponding test case updates for
ease of review.
Changelog
---------
[v3]
s390: Cpu driver support for update and compare
- Fixed indentation of error message in virCPUs390Update
test-data: Qemu caps replies and xml for s390x qemu 2.7 and 2.8
- Moved this patch before introduction of query-cpu-model-expansion
- Regenerated all test data
tests: domain capabilities: qemu 2.7 and 2.8 on s390x
- Added Qemu 2.7 test
- Removed fake host model name
- Moved this patch before introduction of query-cpu-model-expansion
tests: qemu capabilites: qemu 2.7 and 2.8 on s390x
- Moved this patch before introduction of query-cpu-model-expansion
- Stop using fake host cpu
qemu: qmp query-cpu-model-expansion command
- Moved query-cpu-model-expansion capability to this patch
- changed label "cleanup" to "error" in qemuMonitorCPUModelInfoCopy
- qemuMonitorJSONParseCPUModelProperty is now static, and also made
appropriate changes when passing a boolean to virJSONValueGetBoolean
- removed unnecessary error checking when assigning "data" variable in
qemuMonitorJSONGetCPUModelExpansion
- Fix up capabilities test data to reflect changes from this commit
- fixed query-cpu-model-expansion's enumeration formatting
qemu-caps: Get host model directly from Qemu when available
- Moved query-cpu-model-expansion capability from this patch
- virQEMUCapsCopyCPUModelFromQEMU is now static and type void
- check for native guest is done before attempting to set host CPU
- s390x no longer falls back to getting host CPU model from the host
if it cannot be retrieved from QEMU
- fixed unnecessary intialization of some variables that were introduced
in v2 of these patches
- virQEMUCapsLoadHostCPUModelInfo now first allocates data into a
qemuMonitorCPUModelInfoPtr before assigning it to appropriate qemuCaps field
- if we do not have QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION available, skip
trying to read the hostCPU portion of the qemu cache file
- all hostCPU element parsing is handled in its entirety within function
virQEMUCapsLoadHostCPUModelInfo
- Fix up capabilities test data to reflect changes from this commit
qemu: command: Support new cpu feature argument syntax
- Add error message for case where s390 guest attempts to use cpu features on
older qemu.
- Combined the tests into this commit
- Now tests s390 cpu features both with and without query-cpu-model-expansion
[v2]
* Added s390x cpu and capabilities tests
* Added cpu feature syntax tests
* Dropped patch: Warn when migrating host-passthrough
* Added patch: Document migrating host-passthrough is dangerous
s390: Cpu driver support for update and compare
- Compare: Added comment explaining why s390 bypasses the cpuCompare operation
- Update: Added error message explaining minimum match mode is not supported
- Update: Ensure user is not using unsupported optional feature policy
- Update: Use virCPUDefUpdateFeature to update/create user requested features
- Other minor fixes
s390-cpu: Remove nodeData and decode
- Completely remove nodeData and decode functions
qemu: qmp query-cpu-model-expansion command
- Cleaned up debug print
- Restructured qemuMonitorJSONGetCPUModelExpansion
- Added more JSON parsing error handling
- CPU model features now parsed via an iterator
- qemuMonitorJSONGetCPUModelExpansion: Fixed double free of model ptr
- Restructure qemuMonitorCPUModelInfoFree
- Other minor fixes
qemu-caps: Get host model directly from Qemu when available
- virQEMUCapsProbeQMPHostCPU: indentation fix
- Fixed rebase error involving a missing 'goto cleanup;'.
- Fix indentation in virQEMUCapsProbeQMPHostCPU
- virQEMUCapsInitHostCPUModel now routes to virQEMUCapsCopyModelFromQEMU or
virQEMUCapsCopyModelFromHost, depending on architecture.
- Restructure hostCpu data in qemu caps cache xml
- Other minor fixes
Collin L. Walling (5):
test-data: Qemu caps replies and xml for s390x qemu 2.7 and 2.8
tests: domain capabilities: qemu 2.7 and 2.8 on s390x
tests: qemu capabilites: qemu 2.7 and 2.8 on s390x
qemu: qmp query-cpu-model-expansion command
qemu: command: Support new cpu feature argument syntax
Jason J. Herne (4):
s390: Cpu driver support for update and compare
s390-cpu: Remove nodeData and decode
qemu-caps: Get host model directly from Qemu when available
tests: qemuxml2argv s390x cpu model
po/POTFILES.in | 1 +
src/cpu/cpu_s390.c | 103 +-
src/qemu/qemu_capabilities.c | 190 +-
src/qemu/qemu_capabilities.h | 3 +
src/qemu/qemu_command.c | 18 +-
src/qemu/qemu_monitor.c | 62 +
src/qemu/qemu_monitor.h | 22 +
src/qemu/qemu_monitor_json.c | 117 +
src/qemu/qemu_monitor_json.h | 6 +
tests/domaincapsschemadata/qemu_2.7.0.s390x.xml | 78 +
tests/domaincapsschemadata/qemu_2.8.0.s390x.xml | 159 +
tests/domaincapstest.c | 18 +
.../qemucapabilitiesdata/caps_2.7.0.s390x.replies | 11999 +++++++++++++++++
tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml | 140 +
.../qemucapabilitiesdata/caps_2.8.0.s390x.replies | 13380 +++++++++++++++++++
tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 286 +
tests/qemucapabilitiestest.c | 2 +
.../qemuxml2argv-cpu-s390-features.args | 19 +
.../qemuxml2argv-cpu-s390-features.xml | 23 +
.../qemuxml2argv-cpu-s390-zEC12.args | 19 +
.../qemuxml2argv-cpu-s390-zEC12.xml | 21 +
tests/qemuxml2argvtest.c | 14 +
22 files changed, 26638 insertions(+), 42 deletions(-)
create mode 100644 tests/domaincapsschemadata/qemu_2.7.0.s390x.xml
create mode 100644 tests/domaincapsschemadata/qemu_2.8.0.s390x.xml
create mode 100644 tests/qemucapabilitiesdata/caps_2.7.0.s390x.replies
create mode 100644 tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
create mode 100644 tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
create mode 100644 tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-s390-features.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-s390-features.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-s390-zEC12.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-s390-zEC12.xml
--
2.7.4
7 years, 11 months
Re: [libvirt] [RFC] phi support in libvirt
by He Chen
> On Mon, Dec 05, 2016 at 04:12:22PM +0000, Feng, Shaohe wrote:
> > Hi all:
> >
> > As we are know Intel® Xeon phi targets high-performance computing and
> > other parallel workloads.
> > Now qemu has supported phi virtualization,it is time for libvirt to
> > support phi.
>
> Can you provide pointer to the relevant QEMU changes.
>
Xeon Phi Knights Landing (KNL) contains 2 primary hardware features, one
is up to 288 CPUs which needs patches to support and we are pushing it,
the other is Multi-Channel DRAM (MCDRAM) which does not need any changes
currently.
Let me introduce more about MCDRAM, MCDRAM is on-package high-bandwidth
memory (~500GB/s).
On KNL platform, hardware expose MCDRAM as a seperate, CPUless and
remote NUMA node to OS so that MCDRAM will not be allocated by default
(since MCDRAM node has no CPU, every CPU regards MCDRAM node as remote
node). In this way, MCDRAM can be reserved for certain specific
applications.
> > Different from the traditional X86 server, There is a special numa
> > node with Multi-Channel DRAM (MCDRAM) on Phi, but without any CPU .
> >
> > Now libvirt requires nonempty cpus argument for NUMA node, such as.
> > <numa>
> > <cell id='0' cpus='0-239' memory='80' unit='GiB'/>
> > <cell id='1' cpus='240-243' memory='16' unit='GiB'/> </numa>
> >
> > In order to support phi virtualization, libvirt needs to allow a numa
> > cell definition without 'cpu' attribution.
> >
> > Such as:
> > <numa>
> > <cell id='0' cpus='0-239' memory='80' unit='GiB'/>
> > <cell id='1' memory='16' unit='GiB'/> </numa>
> >
> > When a cell without 'cpu', qemu will allocate memory by default MCDRAM instead of DDR.
>
> There's separate concepts at play which your description here is mixing up.
>
> First is the question of whether the guest NUMA node can be created with only RAM or CPUs, or a mix of both.
>
> Second is the question of what kind of host RAM (MCDRAM vs DDR) is used as the backing store for the guest
>
Guest NUMA node shoulde be created with memory only (keep the same as
host's) and the more important things is the memory should bind to (come
from) host MCDRAM node.
> These are separate configuration items which don't need to be conflated in libvirt. ie we should be able to create a guest with a node containing only memory, and back that by DDR on the host. Conversely we should be able to create a guest with a node containing memory + cpus and back that by MCDRAM on the host (even if that means the vCPUs will end up on a different host node from its RAM)
>
> On the first point, there still appears to be some brokness in either QEMU or Linux wrt configuration of virtual NUMA where either cpus or memory are absent from nodes.
>
> eg if I launch QEMU with
>
> -numa node,nodeid=0,cpus=0-3,mem=512
> -numa node,nodeid=1,mem=512
> -numa node,nodeid=2,cpus=4-7
> -numa node,nodeid=3,mem=512
> -numa node,nodeid=4,mem=512
> -numa node,nodeid=5,cpus=8-11
> -numa node,nodeid=6,mem=1024
> -numa node,nodeid=7,cpus=12-15,mem=1024
>
> then the guest reports
>
> # numactl --hardware
> available: 6 nodes (0,3-7)
> node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11
> node 0 size: 487 MB
> node 0 free: 230 MB
> node 3 cpus: 12 13 14 15
> node 3 size: 1006 MB
> node 3 free: 764 MB
> node 4 cpus:
> node 4 size: 503 MB
> node 4 free: 498 MB
> node 5 cpus:
> node 5 size: 503 MB
> node 5 free: 499 MB
> node 6 cpus:
> node 6 size: 503 MB
> node 6 free: 498 MB
> node 7 cpus:
> node 7 size: 943 MB
> node 7 free: 939 MB
>
> so its pushed all the CPUs from nodes without RAM into the first node, and moved CPUs from the 7th node into the 3rd node.
>
I am not sure why this happens, but basically, I lauch QEMU like:
-object memory-backend-ram,size=20G,prealloc=yes,host-nodes=0,policy=bind,id=node0 \
-numa node,nodeid=0,cpus=0-14,cpus=60-74,cpus=120-134,cpus=180-194,memdev=node0 \
-object memory-backend-ram,size=20G,prealloc=yes,host-nodes=1,policy=bind,id=node1 \
-numa node,nodeid=1,cpus=15-29,cpus=75-89,cpus=135-149,cpus=195-209,memdev=node1 \
-object memory-backend-ram,size=20G,prealloc=yes,host-nodes=2,policy=bind,id=node2 \
-numa node,nodeid=2,cpus=30-44,cpus=90-104,cpus=150-164,cpus=210-224,memdev=node2 \
-object memory-backend-ram,size=20G,prealloc=yes,host-nodes=3,policy=bind,id=node3 \
-numa node,nodeid=3,cpus=45-59,cpus=105-119,cpus=165-179,cpus=225-239,memdev=node3 \
-object memory-backend-ram,size=3G,prealloc=yes,host-nodes=4,policy=bind,id=node4 \
-numa node,nodeid=4,memdev=node4 \
-object memory-backend-ram,size=3G,prealloc=yes,host-nodes=5,policy=bind,id=node5 \
-numa node,nodeid=5,memdev=node5 \
-object memory-backend-ram,size=3G,prealloc=yes,host-nodes=6,policy=bind,id=node6 \
-numa node,nodeid=6,memdev=node6 \
-object memory-backend-ram,size=3G,prealloc=yes,host-nodes=7,policy=bind,id=node7 \
-numa node,nodeid=7,memdev=node7 \
(Please ignore the complex cpus parameters...)
As you can see, the pair of `-object memory-backend-ram` and `-numa` is
used to specify where the memory of the guest NUMA node is allocated
from. It works well for me :-)
> So before considering MCDRAM / Phi, we need to fix this more basic NUMA topology setup.
>
> > Now here I'd like to discuss these questions:
> > 1. This feature is only for Phi at present, but we
> > will check Phi platform for CPU-less NUMA node.
> > The NUMA node without CPU indicates MCDRAM node.
>
> We should not assume such semantics - it is a concept that is specific to particular Intel x86_64 CPUs. We need to consider that other architectures may have nodes without CPUs that are backed by normal DDR.
> IOW, we shoud be explicit about presence of MCDRAM in the host.
>
Agreed, but for KNL, that is how we detect MCDRAM on host:
1. detect CPU family is Xeon Phi X200 (means KNL)
2. enumerate all NUMA nodes and regard the nodes that contain memory
only as MCDRAM nodes.
...
Thanks,
-He
7 years, 11 months
[libvirt] [PATCH v2 0/3] Improve release notes process
by Andrea Bolognani
Details of changes from v1 can be found in the single
patches.
Andrea Bolognani (3):
NEWS: Improve building pipeline
NEWS: Reformat at generation time
docs: Document the release notes process for contributors
.gitignore | 1 +
HACKING | 6 ++
Makefile.am | 19 ++--
docs/Makefile.am | 25 +++++-
docs/hacking.html.in | 9 ++
docs/news-ascii.xsl | 66 ++++++++++++++
docs/news-html.xsl | 97 ++++++++++++++++++++
docs/news.html.in | 157 --------------------------------
docs/news.xml | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++
docs/news.xsl | 50 -----------
docs/reformat-news.py | 112 +++++++++++++++++++++++
11 files changed, 565 insertions(+), 218 deletions(-)
create mode 100644 docs/news-ascii.xsl
create mode 100644 docs/news-html.xsl
delete mode 100644 docs/news.html.in
create mode 100644 docs/news.xml
delete mode 100644 docs/news.xsl
create mode 100755 docs/reformat-news.py
--
2.7.4
7 years, 11 months
[libvirt] [PATCH] qemuDomainGetPreservedMounts: Fetch list of /dev/* mounts dynamically
by Michal Privoznik
With my namespace patches, we are spawning qemu in its own
namespace so that we can manage /dev entries ourselves. However,
some filesystems mounted under /dev needs to be preserved in
order to be shared with the parent namespace (e.g. /dev/pts).
Currently, the list of mount points to preserve is hardcoded
which ain't right - on some systems there might be less or more
items under real /dev that on our list. The solution is to parse
/proc/mounts and fetch the list from there.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_domain.c | 126 +++++++++++++++++++++++++++++++------------------
1 file changed, 81 insertions(+), 45 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 67e8836f3b..e0631bf55a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -99,14 +99,8 @@ VIR_ENUM_IMPL(qemuDomainNamespace, QEMU_DOMAIN_NS_LAST,
);
-static struct {
- const char *path;
- const char *suffix;
-} devPreserveMounts[] = {
- {"/dev/pts", "devpts"},
- {"/dev/shm", "devshm"},
- {"/dev/mqueue", "mqueue"},
-};
+#define PROC_MOUNTS "/proc/mounts"
+#define DEVPREFIX "/dev/"
struct _qemuDomainLogContext {
@@ -200,33 +194,73 @@ qemuDomainEnableNamespace(virDomainObjPtr vm,
}
+/**
+ * qemuDomainGetPreservedMounts:
+ *
+ * Process list of mounted filesystems and:
+ * a) save all FSs mounted under /dev to @devPath
+ * b) generate backup path for all the entries in a)
+ *
+ * Any of the return pointers can be NULL.
+ *
+ * Returns 0 on success, -1 otherwise (with error reported)
+ */
static int
qemuDomainGetPreservedMounts(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- char ***devMountsPath,
- size_t *ndevMountsPath)
+ char ***devPath,
+ char ***devSavePath,
+ size_t *ndevPath)
{
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
- char **paths;
- size_t i;
+ char **paths = NULL, **mounts = NULL;
+ size_t i, nmounts;
- if (VIR_ALLOC_N(paths, ARRAY_CARDINALITY(devPreserveMounts)) < 0)
+ if (virFileGetMountSubtree(PROC_MOUNTS, "/dev",
+ &mounts, &nmounts) < 0)
goto error;
- for (i = 0; i < ARRAY_CARDINALITY(devPreserveMounts); i++) {
+ if (!nmounts) {
+ if (ndevPath)
+ *ndevPath = 0;
+ return 0;
+ }
+
+ /* Okay, this is crazy. But virFileGetMountSubtree() fetched us all the
+ * mount points under /dev including /dev itself. Fortunately, the paths
+ * are sorted based in their length so we skip the first one (/dev) as it
+ * is handled differently anyway. */
+ VIR_DELETE_ELEMENT(mounts, 0, nmounts);
+
+ if (VIR_ALLOC_N(paths, nmounts) < 0)
+ goto error;
+
+ for (i = 0; i < nmounts; i++) {
if (virAsprintf(&paths[i], "%s/%s.%s",
cfg->stateDir, vm->def->name,
- devPreserveMounts[i].suffix) < 0)
+ mounts[i] + strlen(DEVPREFIX)) < 0)
goto error;
}
- *devMountsPath = paths;
- *ndevMountsPath = ARRAY_CARDINALITY(devPreserveMounts);
+ if (devPath)
+ *devPath = mounts;
+ else
+ virStringListFreeCount(mounts, nmounts);
+
+ if (devSavePath)
+ *devSavePath = paths;
+ else
+ virStringListFreeCount(paths, nmounts);
+
+ if (ndevPath)
+ *ndevPath = nmounts;
+
virObjectUnref(cfg);
return 0;
error:
- virStringListFreeCount(paths, ARRAY_CARDINALITY(devPreserveMounts));
+ virStringListFreeCount(mounts, nmounts);
+ virStringListFreeCount(paths, nmounts);
virObjectUnref(cfg);
return -1;
}
@@ -6917,8 +6951,6 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,
}
-#define DEVPREFIX "/dev/"
-
#if defined(__linux__)
static int
qemuDomainCreateDevice(const char *device,
@@ -7304,7 +7336,7 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
const unsigned long mount_flags = MS_MOVE;
char *devPath = NULL;
- char **devMountsPath = NULL;
+ char **devMountsPath = NULL, **devMountsSavePath = NULL;
size_t ndevMountsPath = 0, i;
int ret = -1;
@@ -7318,7 +7350,8 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
goto cleanup;
if (qemuDomainGetPreservedMounts(driver, vm,
- &devMountsPath, &ndevMountsPath) < 0)
+ &devMountsPath, &devMountsSavePath,
+ &ndevMountsPath) < 0)
goto cleanup;
if (qemuDomainSetupDev(driver, vm, devPath) < 0)
@@ -7326,11 +7359,11 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
/* Save some mount points because we want to share them with the host */
for (i = 0; i < ndevMountsPath; i++) {
- if (mount(devPreserveMounts[i].path, devMountsPath[i],
+ if (mount(devMountsPath[i], devMountsSavePath[i],
NULL, mount_flags, NULL) < 0) {
virReportSystemError(errno,
_("Unable to move %s mount"),
- devPreserveMounts[i].path);
+ devMountsPath[i]);
goto cleanup;
}
}
@@ -7361,18 +7394,18 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
}
for (i = 0; i < ndevMountsPath; i++) {
- if (virFileMakePath(devPreserveMounts[i].path) < 0) {
+ if (virFileMakePath(devMountsPath[i]) < 0) {
virReportSystemError(errno, _("Cannot create %s"),
- devPreserveMounts[i].path);
+ devMountsPath[i]);
goto cleanup;
}
- if (mount(devMountsPath[i], devPreserveMounts[i].path,
+ if (mount(devMountsSavePath[i], devMountsPath[i],
NULL, mount_flags, NULL) < 0) {
virReportSystemError(errno,
_("Failed to mount %s on %s"),
- devMountsPath[i],
- devPreserveMounts[i].path);
+ devMountsSavePath[i],
+ devMountsPath[i]);
goto cleanup;
}
}
@@ -7382,6 +7415,7 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
virObjectUnref(cfg);
VIR_FREE(devPath);
virStringListFreeCount(devMountsPath, ndevMountsPath);
+ virStringListFreeCount(devMountsSavePath, ndevMountsPath);
return ret;
}
@@ -7393,8 +7427,8 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
int ret = -1;
char *devPath = NULL;
- char **devMountsPath = NULL;
- size_t ndevMountsPath = 0, i;
+ char **devMountsSavePath = NULL;
+ size_t ndevMountsSavePath = 0, i;
if (!virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT) ||
!virQEMUDriverIsPrivileged(driver)) {
@@ -7407,7 +7441,8 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
goto cleanup;
if (qemuDomainGetPreservedMounts(driver, vm,
- &devMountsPath, &ndevMountsPath) < 0)
+ NULL, &devMountsSavePath,
+ &ndevMountsSavePath) < 0)
goto cleanup;
if (virFileMakePath(devPath) < 0) {
@@ -7417,11 +7452,11 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
goto cleanup;
}
- for (i = 0; i < ndevMountsPath; i++) {
- if (virFileMakePath(devMountsPath[i]) < 0) {
+ for (i = 0; i < ndevMountsSavePath; i++) {
+ if (virFileMakePath(devMountsSavePath[i]) < 0) {
virReportSystemError(errno,
_("Failed to create %s"),
- devMountsPath[i]);
+ devMountsSavePath[i]);
goto cleanup;
}
}
@@ -7434,10 +7469,10 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
if (ret < 0) {
if (devPath)
unlink(devPath);
- for (i = 0; i < ndevMountsPath; i++)
- unlink(devMountsPath[i]);
+ for (i = 0; i < ndevMountsSavePath; i++)
+ unlink(devMountsSavePath[i]);
}
- virStringListFreeCount(devMountsPath, ndevMountsPath);
+ virStringListFreeCount(devMountsSavePath, ndevMountsSavePath);
VIR_FREE(devPath);
virObjectUnref(cfg);
return ret;
@@ -7472,8 +7507,8 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
{
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
char *devPath = NULL;
- char **devMountsPath = NULL;
- size_t ndevMountsPath = 0, i;
+ char **devMountsSavePath = NULL;
+ size_t ndevMountsSavePath = 0, i;
if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
@@ -7484,7 +7519,8 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
goto cleanup;
if (qemuDomainGetPreservedMounts(driver, vm,
- &devMountsPath, &ndevMountsPath) < 0)
+ NULL, &devMountsSavePath,
+ &ndevMountsSavePath) < 0)
goto cleanup;
if (rmdir(devPath) < 0) {
@@ -7494,17 +7530,17 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
/* Bet effort. Fall through. */
}
- for (i = 0; i < ndevMountsPath; i++) {
- if (rmdir(devMountsPath[i]) < 0) {
+ for (i = 0; i < ndevMountsSavePath; i++) {
+ if (rmdir(devMountsSavePath[i]) < 0) {
virReportSystemError(errno,
_("Unable to remove %s"),
- devMountsPath[i]);
+ devMountsSavePath[i]);
/* Bet effort. Fall through. */
}
}
cleanup:
virObjectUnref(cfg);
- virStringListFreeCount(devMountsPath, ndevMountsPath);
+ virStringListFreeCount(devMountsSavePath, ndevMountsSavePath);
VIR_FREE(devPath);
}
--
2.11.0
7 years, 11 months
[libvirt] [PATCH] virsh: pool-list: introduce --uuid
by Chen Hanxiao
From: Chen Hanxiao <chenhanxiao(a)gmail.com>
This patch will introduce option [--uuid].
If specified, UUID of pools will be printed out.
virsh # pool-list --all
Name State Autostart
-------------------------------------------
default active yes
root active yes
virsh # pool-list --all --uuid
Name State Autostart UUID
---------------------------------------------------------------------------------
default active yes 45fdb1f3-402d-44c0-b2c0-a7be61fea6c7
root active yes eb397f25-9a44-459d-80df-330ca8f65ba8
Signed-off-by: Chen Hanxiao <chenhanxiao(a)gmail.com>
---
tools/virsh-pool.c | 31 ++++++++++++++++++++++++++++---
tools/virsh.pod | 5 +++--
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
index 8313be8..a502718 100644
--- a/tools/virsh-pool.c
+++ b/tools/virsh-pool.c
@@ -1060,6 +1060,10 @@ static const vshCmdOptDef opts_pool_list[] = {
.type = VSH_OT_BOOL,
.help = N_("display extended details for pools")
},
+ {.name = "uuid",
+ .type = VSH_OT_BOOL,
+ .help = N_("display UUID of pools")
+ },
{.name = NULL}
};
@@ -1087,6 +1091,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
const char *type = NULL;
bool details = vshCommandOptBool(cmd, "details");
bool inactive, all;
+ bool uuid = false;
char *outputStr = NULL;
inactive = vshCommandOptBool(cmd, "inactive");
@@ -1111,6 +1116,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
if (vshCommandOptBool(cmd, "transient"))
flags |= VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT;
+ if (vshCommandOptBool(cmd, "uuid"))
+ uuid = true;
+
if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0)
return false;
@@ -1298,17 +1306,34 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
/* Output basic info then return if --details option not selected */
if (!details) {
/* Output old style header */
- vshPrintExtra(ctl, " %-20s %-10s %-10s\n", _("Name"), _("State"),
+ vshPrintExtra(ctl, " %-20s %-10s %-10s", _("Name"), _("State"),
_("Autostart"));
- vshPrintExtra(ctl, "-------------------------------------------\n");
+ if (uuid)
+ vshPrintExtra(ctl, " %-10s\n", _("UUID"));
+ else
+ vshPrintExtra(ctl, "\n");
+
+ vshPrintExtra(ctl, "-------------------------------------------");
+
+ if (uuid)
+ vshPrintExtra(ctl, "--------------------------------------\n");
+ else
+ vshPrintExtra(ctl, "\n");
/* Output old style pool info */
for (i = 0; i < list->npools; i++) {
const char *name = virStoragePoolGetName(list->pools[i]);
- vshPrint(ctl, " %-20s %-10s %-10s\n",
+ char uuid_str[VIR_UUID_STRING_BUFLEN];
+ vshPrint(ctl, " %-20s %-10s %-10s",
name,
poolInfoTexts[i].state,
poolInfoTexts[i].autostart);
+ if (uuid) {
+ virStoragePoolGetUUIDString(list->pools[i], uuid_str);
+ vshPrintExtra(ctl, " %-36s\n", uuid_str);
+ } else {
+ vshPrintExtra(ctl, "\n");
+ }
}
/* Cleanup and return */
diff --git a/tools/virsh.pod b/tools/virsh.pod
index ef91223..0048c67 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -3612,7 +3612,7 @@ Returns basic information about the I<pool> object.
=item B<pool-list> [I<--inactive>] [I<--all>]
[I<--persistent>] [I<--transient>]
[I<--autostart>] [I<--no-autostart>]
- [[I<--details>] [<type>]
+ [[I<--details>] [I<--uuid>] [<type>]
List pool objects known to libvirt. By default, only active pools
are listed; I<--inactive> lists just the inactive pools, and I<--all>
@@ -3621,7 +3621,8 @@ lists all pools.
In addition, there are several sets of filtering flags. I<--persistent> is to
list the persistent pools, I<--transient> is to list the transient pools.
I<--autostart> lists the autostarting pools, I<--no-autostart> lists the pools
-with autostarting disabled.
+with autostarting disabled. If I<--uuid> is specified the UUID of the named
+pools will be printed out.
You may also want to list pools with specified types using I<type>, the
pool types must be separated by comma, e.g. --type dir,disk. The valid pool
--
2.7.4
7 years, 11 months
[libvirt] [PATCH 0/3] qemu: fix pit timer tick policy
by Maxim Nestratov
Maxim Nestratov (3):
qemu: fix pit timer tick policy=delay
qemu: allow to specify pit timer tick policy=discard
qemu: tests: add "no-kvm-pit-device" testcase
src/qemu/qemu_command.c | 10 ++++++--
.../qemuxml2argv-kvm-pit-delay.args | 2 +-
.../qemuxml2argv-kvm-pit-device.xml | 2 +-
.../qemuxml2argv-no-kvm-pit-device.args | 23 +++++++++++++++++
.../qemuxml2argv-no-kvm-pit-device.xml | 29 ++++++++++++++++++++++
tests/qemuxml2argvtest.c | 5 ++--
6 files changed, 64 insertions(+), 7 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-no-kvm-pit-device.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-no-kvm-pit-device.xml
--
2.4.11
7 years, 11 months
[libvirt] [PATCH go-xml] Added Storage Pool XML scheme.
by Alexey Slaykovsky
Signed-off-by: Alexey Slaykovsky <aslaikov(a)redhat.com>
---
storage.go | 114 +++++++++++++++++++++++++++
storage_test.go | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 354 insertions(+)
create mode 100644 storage.go
create mode 100644 storage_test.go
diff --git a/storage.go b/storage.go
new file mode 100644
index 0000000..b45f58e
--- /dev/null
+++ b/storage.go
@@ -0,0 +1,114 @@
+/*
+ * 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 StoragePoolTargetPermissions struct {
+ Owner string `xml:"owner"`
+ Group string `xml:"group"`
+ Mode string `xml:"mode"`
+ Label string `xml:"label"`
+}
+
+type StoragePoolTarget struct {
+ Path string `xml:"path"`
+ Permissions *StoragePoolTargetPermissions `xml:"permissions"`
+}
+
+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 StoragePoolSourceFormat struct {
+ Type string `xml:"type,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 *StoragePoolSourceFormat `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 uint64 `xml:"allocation,omitempty"`
+ Capacity uint64 `xml:"capacity,omitempty"`
+ Available uint64 `xml:"available,omitempty"`
+ Target *StoragePoolTarget `xml:"target"`
+ Source *StoragePoolSource `xml:"source"`
+}
diff --git a/storage_test.go b/storage_test.go
new file mode 100644
index 0000000..f08eefe
--- /dev/null
+++ b/storage_test.go
@@ -0,0 +1,240 @@
+/*
+ * 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 storageTestData = []struct {
+ Object *StoragePool
+ Expected []string
+}{
+ {
+ Object: &StoragePool{
+ Type: "dir",
+ Name: "pool",
+ UUID: "3e3fce45-4f53-4fa7-bb32-11f34168b82b",
+ Allocation: 1000000,
+ Capacity: 5000000,
+ Available: 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: &StoragePoolSourceFormat{
+ 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: &StoragePoolTarget{
+ Path: "/pool",
+ Permissions: &StoragePoolTargetPermissions{
+ 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 TestStorage(t *testing.T) {
+ for _, test := range storageTestData {
+ 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
7 years, 11 months
[libvirt] [PATCH] docs: Reference the right config option
by Martin Kletzander
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
Pushed as trivial
docs/auth.html.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/auth.html.in b/docs/auth.html.in
index 487c3aad798b..08feacc2e313 100644
--- a/docs/auth.html.in
+++ b/docs/auth.html.in
@@ -173,7 +173,7 @@ the libvirt daemon.
<h2><a name="ACL_server_polkit">UNIX socket PolicyKit auth</a></h2>
<p>
If libvirt contains support for PolicyKit, then access control options are
-more advanced. The <code>unix_sock_auth</code> parameter will default to
+more advanced. The <code>auth_unix_rw</code> parameter will default to
<code>polkit</code>, and the file permissions will default to <code>0777</code>
even on the RW socket. Upon connecting to the socket, the client application
will be required to identify itself with PolicyKit. The default policy for the
--
2.11.0
7 years, 11 months
[libvirt] [PATCH 0/2] Fix some nits
by Martin Kletzander
Martin Kletzander (2):
util: Don't lie in virFileGetMount*Subtree's docstrings
qemu: Remove /dev mount info properly
src/qemu/qemu_domain.c | 9 ++++-----
src/util/virfile.c | 5 ++---
2 files changed, 6 insertions(+), 8 deletions(-)
--
2.11.0
7 years, 11 months