[libvirt] [PATCH v2 1/3] conf: Format numatune XML correctly while placement is none
by Osier Yang
setNumaParameters tunes the numa setting using cgroup, it's another
entry except libnuma/numad for numa tuning. And it doesn't set the
placement, and further more, the formating codes doesn't take this
into consideration.
How to reproduce:
conn = libvirt.open(None)
dom = conn.lookupByName('linux')
param = {'numa_nodeset': '0', 'numa_mode': 1}
dom.setNumaParameters(param, 2)
% virsh start linux
error: Failed to start domain rhel6.3rc
error: (domain_definition):8: error parsing attribute name
<memory mode='preferred' </numatune>
-------------------------------^
---
src/conf/domain_conf.c | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 81c6308..c44d89d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -12795,23 +12795,26 @@ virDomainDefFormatInternal(virDomainDefPtr def,
const char *placement;
mode = virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode);
- virBufferAsprintf(buf, " <memory mode='%s' ", mode);
+ virBufferAsprintf(buf, " <memory mode='%s'", mode);
- if (def->numatune.memory.placement_mode ==
- VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_STATIC) {
+ if (def->numatune.memory.nodemask) {
nodemask = virDomainCpuSetFormat(def->numatune.memory.nodemask,
- VIR_DOMAIN_CPUMASK_LEN);
+ VIR_DOMAIN_CPUMASK_LEN);
if (nodemask == NULL) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to format nodeset for "
"NUMA memory tuning"));
goto cleanup;
}
- virBufferAsprintf(buf, "nodeset='%s'/>\n", nodemask);
+ virBufferAsprintf(buf, " nodeset='%s'/>\n", nodemask);
VIR_FREE(nodemask);
- } else if (def->numatune.memory.placement_mode) {
+ } else if (def->numatune.memory.placement_mode ==
+ VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_AUTO) {
placement = virDomainNumatuneMemPlacementModeTypeToString(def->numatune.memory.placement_mode);
- virBufferAsprintf(buf, "placement='%s'/>\n", placement);
+ virBufferAsprintf(buf, " placement='%s'/>\n", placement);
+ } else {
+ /* Should not hit here. */
+ virBufferAddLit(buf, "/>\n");
}
virBufferAddLit(buf, " </numatune>\n");
}
--
1.7.7.3
12 years, 3 months
[libvirt] [PATCH 0/6 v3] Support forward mode='hostdev' and interface pools
by Shradha Shah
This patch series supports the forward mode='hostdev'. The functionality
of this mode is the same as interface type='hostdev' but with the added
benefit of using interface pools.
The patch series also contains a patch to support use of interface names
and PCI device addresses interchangeably in a network xml, and return
the appropriate one in actualDevice when networkAllocateActualDevice is
called.
At the top level managed attribute can be specified with identical results
as when it's specified for a hostdev.
Currently forward mode='hostdev' does not support USB devices.
Shradha Shah (6):
Prerequisite Patch. virDomainDevicePCIAddress and respective
functions moved to a new file called conf/device_conf.ch
Moved the code to create implicit interface pool from PF to a new
function
RNG updates, new xml parser/formatter code to support forward
mode=hostdev
Code to return interface name or pci_addr of the VF in actualDevice
Forward Mode Hostdev network driver Implementation
Forward Mode 'Hostdev' qemu driver implementation
docs/formatnetwork.html.in | 62 ++++++
docs/schemas/network.rng | 82 ++++++++-
include/libvirt/virterror.h | 1 +
src/Makefile.am | 7 +-
src/conf/device_conf.c | 135 +++++++++++++
src/conf/device_conf.h | 65 +++++++
src/conf/domain_conf.c | 114 ++----------
src/conf/domain_conf.h | 25 +---
src/conf/network_conf.c | 126 +++++++++++--
src/conf/network_conf.h | 29 +++-
src/libvirt_private.syms | 10 +-
src/network/bridge_driver.c | 322 +++++++++++++++++++++++++-------
src/qemu/qemu_command.c | 27 ++-
src/qemu/qemu_hotplug.c | 7 +-
src/qemu/qemu_monitor.c | 14 +-
src/qemu/qemu_monitor.h | 17 +-
src/qemu/qemu_monitor_json.c | 14 +-
src/qemu/qemu_monitor_json.h | 14 +-
src/qemu/qemu_monitor_text.c | 16 +-
src/qemu/qemu_monitor_text.h | 14 +-
src/util/virnetdev.c | 29 ++--
src/util/virnetdev.h | 4 +-
src/xen/xend_internal.c | 3 +-
tests/networkxml2xmlin/hostdev-pf.xml | 11 +
tests/networkxml2xmlin/hostdev.xml | 10 +
tests/networkxml2xmlout/hostdev-pf.xml | 7 +
tests/networkxml2xmlout/hostdev.xml | 10 +
tests/networkxml2xmltest.c | 2 +
28 files changed, 890 insertions(+), 287 deletions(-)
create mode 100644 src/conf/device_conf.c
create mode 100644 src/conf/device_conf.h
create mode 100644 tests/networkxml2xmlin/hostdev-pf.xml
create mode 100644 tests/networkxml2xmlin/hostdev.xml
create mode 100644 tests/networkxml2xmlout/hostdev-pf.xml
create mode 100644 tests/networkxml2xmlout/hostdev.xml
--
1.7.4.4
12 years, 4 months
[libvirt] [PATCH] virsh: Check for existence of storage before undefining the domain
by Peter Krempa
When undefining a domain and removing associated storage using "virsh
undefine --storage" the domain was at first undefined and after that the
storage removal proces was started. If the user specified an invalid
disk to remove, the error could not be corrected.
This patch moves enumeration and filtering of volumes that should be
removed before the domain is undefined, but the removal process is still
kept after the domain has been undefined.
---
tools/virsh.c | 280 +++++++++++++++++++++++++++++----------------------------
1 files changed, 144 insertions(+), 136 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 0354822..e6b8e5f 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3007,6 +3007,12 @@ static const vshCmdOptDef opts_undefine[] = {
{NULL, 0, 0, NULL}
};
+typedef struct {
+ virStorageVolPtr vol;
+ char *source;
+ char *target;
+} vshUndefineVolume;
+
static bool
cmdUndefine(vshControl *ctl, const vshCmd *cmd)
{
@@ -3019,7 +3025,6 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
bool managed_save = vshCommandOptBool(cmd, "managed-save");
bool snapshots_metadata = vshCommandOptBool(cmd, "snapshots-metadata");
bool wipe_storage = vshCommandOptBool(cmd, "wipe-storage");
- bool remove_storage = false;
bool remove_all_storage = vshCommandOptBool(cmd, "remove-all-storage");
/* Positive if these items exist. */
int has_managed_save = 0;
@@ -3031,6 +3036,8 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
int rc = -1;
int running;
/* list of volumes to remove along with this domain */
+ vshUndefineVolume *vlist = NULL;
+ int nvols = 0;
const char *volumes_arg = NULL;
char *volumes = NULL;
char **volume_tokens = NULL;
@@ -3045,8 +3052,10 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr *vol_nodes = NULL;
int nvolumes = 0;
- virStorageVolPtr vol = NULL;
- bool vol_del_failed = false;
+ bool vol_not_found = false;
+
+ ignore_value(vshCommandOptString(cmd, "storage", &volumes_arg));
+ volumes = vshStrdup(ctl, volumes_arg);
if (managed_save) {
flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE;
@@ -3063,36 +3072,21 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return false;
- /* check if a string that should contain list of volumes to remove is present */
- if (vshCommandOptString(cmd, "storage", &volumes_arg) > 0) {
- volumes = vshStrdup(ctl, volumes_arg);
-
- if (remove_all_storage) {
- vshError(ctl, _("Specified both --storage and --remove-all-storage"));
- goto cleanup;
- }
- remove_storage = true;
- }
-
/* Do some flag manipulation. The goal here is to disable bits
* from flags to reduce the likelihood of a server rejecting
* unknown flag bits, as well as to track conditions which are
* safe by default for the given hypervisor and server version. */
- running = virDomainIsActive(dom);
- if (running < 0) {
- virshReportError(ctl);
- goto cleanup;
- }
+ if ((running = virDomainIsActive(dom)) < 0)
+ goto error;
+
if (!running) {
/* Undefine with snapshots only fails for inactive domains,
* and managed save only exists on inactive domains; if
* running, then we don't want to remove anything. */
has_managed_save = virDomainHasManagedSaveImage(dom, 0);
if (has_managed_save < 0) {
- if (last_error->code != VIR_ERR_NO_SUPPORT) {
- virshReportError(ctl);
- goto cleanup;
- }
+ if (last_error->code != VIR_ERR_NO_SUPPORT)
+ goto error;
virFreeError(last_error);
last_error = NULL;
has_managed_save = 0;
@@ -3100,10 +3094,8 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
has_snapshots = virDomainSnapshotNum(dom, 0);
if (has_snapshots < 0) {
- if (last_error->code != VIR_ERR_NO_SUPPORT) {
- virshReportError(ctl);
- goto cleanup;
- }
+ if (last_error->code != VIR_ERR_NO_SUPPORT)
+ goto error;
virFreeError(last_error);
last_error = NULL;
has_snapshots = 0;
@@ -3137,16 +3129,116 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
}
/* Stash domain description for later use */
- if (remove_storage || remove_all_storage) {
+ if (volumes || remove_all_storage) {
if (running) {
vshError(ctl, _("Storage volume deletion is supported only on stopped domains"));
goto cleanup;
}
+ if (volumes && remove_all_storage) {
+ vshError(ctl, _("Specified both --storage and --remove-all-storage"));
+ goto cleanup;
+ }
+
if (!(def = virDomainGetXMLDesc(dom, 0))) {
vshError(ctl, _("Could not retrieve domain XML description"));
goto cleanup;
}
+
+ if (!(doc = virXMLParseStringCtxt(def, _("(domain_definition)"),
+ &ctxt)))
+ goto error;
+
+ /* tokenize the string from user and save it's parts into an array */
+ if (volumes) {
+ /* count the delimiters */
+ volume_tok = volumes;
+ nvolume_tokens = 1; /* we need at least one member */
+ while (*volume_tok) {
+ if (*(volume_tok++) == ',')
+ nvolume_tokens++;
+ }
+
+ volume_tokens = vshCalloc(ctl, nvolume_tokens, sizeof(char *));
+
+ /* tokenize the input string */
+ nvolume_tokens = 0;
+ volume_tok = volumes;
+ do {
+ volume_tokens[nvolume_tokens] = strsep(&volume_tok, ",");
+ nvolume_tokens++;
+ } while (volume_tok);
+ }
+
+ if ((nvolumes = virXPathNodeSet("./devices/disk", ctxt,
+ &vol_nodes)) < 0)
+ goto error;
+
+ if (nvolumes > 0)
+ vlist = vshCalloc(ctl, nvolumes, sizeof(*vlist));
+
+ for (vol_i = 0; vol_i < nvolumes; vol_i++) {
+ ctxt->node = vol_nodes[vol_i];
+
+ /* get volume source and target paths */
+ if (!(target = virXPathString("string(./target/@dev)", ctxt)))
+ goto error;
+
+ if (!(source = virXPathString("string("
+ "./source/@file|"
+ "./source/@dir|"
+ "./source/@name|"
+ "./source/@dev)", ctxt))) {
+ if (last_error && last_error->code != VIR_ERR_OK)
+ goto error;
+ else
+ continue;
+ }
+
+ /* lookup if volume was selected by user */
+ if (volumes) {
+ volume_tok = NULL;
+ for (tok_i = 0; tok_i < nvolume_tokens; tok_i++) {
+ if (volume_tokens[tok_i] &&
+ (STREQ(volume_tokens[tok_i], target) ||
+ STREQ(volume_tokens[tok_i], source))) {
+ volume_tok = volume_tokens[tok_i];
+ volume_tokens[tok_i] = NULL;
+ break;
+ }
+ }
+ if (!volume_tok)
+ continue;
+ }
+
+ if (!(vlist[nvols].vol = virStorageVolLookupByPath(ctl->conn,
+ source))) {
+ vshPrint(ctl,
+ _("Storage volume '%s'(%s) is not managed by libvirt. "
+ "Remove it manually.\n"), target, source);
+ virFreeError(last_error);
+ last_error = NULL;
+ continue;
+ }
+ vlist[nvols].source = source;
+ vlist[nvols].target = target;
+ nvols++;
+ }
+
+ /* print volumes specified by user that were not found in domain definition */
+ if (volumes) {
+ for (tok_i = 0; tok_i < nvolume_tokens; tok_i++) {
+ if (volume_tokens[tok_i]) {
+ vshError(ctl, _("Volume '%s' was not found in domain's "
+ "definition.\n"),
+ volume_tokens[tok_i]);
+ vol_not_found = true;
+ }
+ }
+
+ if (vol_not_found)
+ goto cleanup;
+ }
}
/* Generally we want to try the new API first. However, while
@@ -3202,96 +3294,15 @@ out:
}
/* try to undefine storage volumes associated with this domain, if it's requested */
- if (remove_storage || remove_all_storage) {
- ret = false;
-
- /* tokenize the string from user and save it's parts into an array */
- if (volumes) {
- /* count the delimiters */
- volume_tok = volumes;
- nvolume_tokens = 1; /* we need at least one member */
- while (*volume_tok) {
- if (*volume_tok == ',')
- nvolume_tokens++;
- volume_tok++;
- }
-
- volume_tokens = vshCalloc(ctl, nvolume_tokens, sizeof(char *));
-
- /* tokenize the input string */
- nvolume_tokens = 0;
- volume_tok = volumes;
- do {
- volume_tokens[nvolume_tokens] = strsep(&volume_tok, ",");
- nvolume_tokens++;
- } while (volume_tok);
- }
-
- doc = virXMLParseStringCtxt(def, _("(domain_definition)"), &ctxt);
- if (!doc)
- goto cleanup;
-
- nvolumes = virXPathNodeSet("./devices/disk", ctxt, &vol_nodes);
-
- if (nvolumes < 0)
- goto cleanup;
-
- for (vol_i = 0; vol_i < nvolumes; vol_i++) {
- ctxt->node = vol_nodes[vol_i];
- VIR_FREE(target);
- VIR_FREE(source);
- if (vol) {
- virStorageVolFree(vol);
- vol = NULL;
- }
-
- /* get volume source and target paths */
- if (!(target = virXPathString("string(./target/@dev)", ctxt))) {
- vshError(ctl, _("Failed to enumerate devices"));
- goto cleanup;
- }
-
- if (!(source = virXPathString("string("
- "./source/@file|"
- "./source/@dir|"
- "./source/@name|"
- "./source/@dev)", ctxt)) &&
- virGetLastError())
- goto cleanup;
-
- /* lookup if volume was selected by user */
- if (volumes) {
- volume_tok = NULL;
- for (tok_i = 0; tok_i < nvolume_tokens; tok_i++) {
- if (volume_tokens[tok_i] &&
- (STREQ_NULLABLE(volume_tokens[tok_i], target) ||
- STREQ_NULLABLE(volume_tokens[tok_i], source))) {
- volume_tok = volume_tokens[tok_i];
- volume_tokens[tok_i] = NULL;
- break;
- }
- }
- if (!volume_tok)
- continue;
- }
-
- if (!source)
- continue;
-
- if (!(vol = virStorageVolLookupByPath(ctl->conn, source))) {
- vshPrint(ctl,
- _("Storage volume '%s'(%s) is not managed by libvirt. "
- "Remove it manually.\n"), target, source);
- virResetLastError();
- continue;
- }
-
+ if (nvols) {
+ for (vol_i = 0; vol_i < nvols; vol_i++) {
if (wipe_storage) {
- vshPrint(ctl, _("Wiping volume '%s'(%s) ... "), target, source);
+ vshPrint(ctl, _("Wiping volume '%s'(%s) ... "),
+ vlist[vol_i].target, vlist[vol_i].source);
fflush(stdout);
- if (virStorageVolWipe(vol, 0) < 0) {
+ if (virStorageVolWipe(vlist[vol_i].vol, 0) < 0) {
vshError(ctl, _("Failed! Volume not removed."));
- vol_del_failed = true;
+ ret = false;
continue;
} else {
vshPrint(ctl, _("Done.\n"));
@@ -3299,41 +3310,38 @@ out:
}
/* delete the volume */
- if (virStorageVolDelete(vol, 0) < 0) {
+ if (virStorageVolDelete(vlist[vol_i].vol, 0) < 0) {
vshError(ctl, _("Failed to remove storage volume '%s'(%s)"),
- target, source);
- vol_del_failed = true;
- }
- vshPrint(ctl, _("Volume '%s' removed.\n"), volume_tok?volume_tok:source);
- }
-
- /* print volumes specified by user that were not found in domain definition */
- if (volumes) {
- for (tok_i = 0; tok_i < nvolume_tokens; tok_i++) {
- if (volume_tokens[tok_i])
- vshPrint(ctl, _("Volume '%s' was not found in domain's "
- "definition.\n"),
- volume_tokens[tok_i]);
+ vlist[vol_i].target, vlist[vol_i].source);
+ ret = false;
+ } else {
+ vshPrint(ctl, _("Volume '%s'(%s) removed.\n"),
+ vlist[vol_i].target, vlist[vol_i].source);
}
}
-
- if (!vol_del_failed)
- ret = true;
}
cleanup:
- VIR_FREE(source);
- VIR_FREE(target);
+ for (vol_i = 0; vol_i < nvols; vol_i++) {
+ VIR_FREE(vlist[vol_i].source);
+ VIR_FREE(vlist[vol_i].target);
+ if (vlist[vol_i].vol)
+ virStorageVolFree(vlist[vol_i].vol);
+ }
+ VIR_FREE(vlist);
+
VIR_FREE(volumes);
VIR_FREE(volume_tokens);
VIR_FREE(def);
VIR_FREE(vol_nodes);
- if (vol)
- virStorageVolFree(vol);
xmlFreeDoc(doc);
xmlXPathFreeContext(ctxt);
virDomainFree(dom);
return ret;
+
+error:
+ virshReportError(ctl);
+ goto cleanup;
}
--
1.7.8.6
12 years, 4 months
[libvirt] Intend to add OVA installation API
by Ata Bohra
Hi Everyone,
I am relatively new to libvirt community; have worked on it from last half year mostly towards adding few missing APIs especially for ESX driver. One of the features I worked was installing a domain (VM) using OVAs. It is been a long time OVA became defacto standard for distributing and installing Virtual Machines, but surprisingly libvirt does not provide support for it. I wanted to perform a quick sanity int the community so that I am not stepping on anyone feet here. So far, I have working code, but to contribute upstream would require a bit of a cleanup work.
One of the concern that I intend to get inputs on:
OVA is a tar format archive, the first pre-requisite is to parse OVA and get following information:
1. XML descriptor.
2. VMDKs for transfer after domain is created on the hypervisor. (in ESX world that is done by getting a lease object and then transmitting the disk bits to hypervisor)
I am wondering, where should I put the common code to parse OVA? My initial thought is to enhance conf/domain_conf.* file, given it already provides parsing routines for XML descriptor. Waiting for your feedback on this one.
As I am familiar with ESX libvirt interaction, so the immediate plan is to enhance ESX driver, hopefully in near future will contribute the same feature to KVM/Xen etc.
Thanks!
Ata
12 years, 4 months
[libvirt] Different mac address used in libvirtd
by Yong Sheng Gong
Hi,
I found libvirtd will create vnet0 with a different mac other than the one defined in domain file. The mac in Domain file will be used by qemu-kvm.
I want to know how libvirtd decides the mac for vnet0, Who can give me a hint about the location of the libvirtd codes which does this work?
I cannot find how the libvirtd translates the mac from one defined in domain file to vnet0's one in src/util/bridge.c: brSetInterfaceMac()
Thanks
Yong Sheng Gong
[root@robinlinux eclipsecdt]# virsh dumpxml 2
<domain type='kvm' id='2'>
<name>instance-00000002</name>
<uuid>03e9993b-eafa-4021-b929-4a51ce9635d5</uuid>
<memory>524288</memory>
<currentMemory>524288</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc-0.14'>hvm</type>
<kernel>/var/lib/nova/instances/instance-00000002/kernel</kernel>
<initrd>/var/lib/nova/instances/instance-00000002/ramdisk</initrd>
<cmdline>root=/dev/vda console=ttyS0</cmdline>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'>
<timer name='pit' tickpolicy='delay'/>
<timer name='rtc' tickpolicy='catchup'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/var/lib/nova/instances/instance-00000002/disk'/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</disk>
<interface type='bridge'>
<mac address='fa:16:3e:28:64:c2'/>
<source bridge='br100'/>
<target dev='vnet0'/>
<filterref filter='nova-instance-instance-00000002-fa163e2864c2'>
<parameter name='DHCPSERVER' value='10.0.1.1'/>
<parameter name='PROJNET' value='10.0.1.0'/>
<parameter name='PROJMASK' value='255.255.255.0'/>
<parameter name='IP' value='10.0.1.2'/>
</filterref>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='file'>
<source path='/var/lib/nova/instances/instance-00000002/console.log'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<serial type='pty'>
<source path='/dev/pts/1'/>
<target port='1'/>
<alias name='serial1'/>
</serial>
<console type='file'>
<source path='/var/lib/nova/instances/instance-00000002/console.log'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='tablet' bus='usb'>
<alias name='input0'/>
</input>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
</domain>
[root@robinlinux eclipsecdt]# ifconfig vnet0
vnet0 Link encap:Ethernet HWaddr FE:16:3E:28:64:C2
inet6 addr: fe80::fc16:3eff:fe28:64c2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:553 errors:0 dropped:0 overruns:0 frame:0
TX packets:1485 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:136360 (133.1 KiB) TX bytes:280590 (274.0 KiB)
12 years, 4 months
[libvirt] Linker error in gnulib test-binary-io.c
by Matthias Bolte
I get the following error on Ubuntu 11.04 with current libvirt git HEAD:
$ make check
[...]
CC test-binary-io.o
test-binary-io.c: In function 'main':
test-binary-io.c:54:7: warning: implicit declaration of function
'set_binary_mode'
CCLD test-binary-io
test-binary-io.o: In function `main':
[...]/test-binary-io.c:54: undefined reference to `set_binary_mode'
collect2: ld returned 1 exit status
--
Matthias Bolte
http://photron.blogspot.com
12 years, 4 months
[libvirt] [PATCH v3] storage backend: Add sheepdog support
by Sebastian Wiedenroth
This patch brings support to manage sheepdog pools and volumes to libvirt.
It uses the "collie" command-line utility that comes with sheepdog for that.
A sheepdog pool in libvirt maps to a sheepdog cluster.
It needs a host and port to connect to, which in most cases
is just going to be the default of localhost on port 7000.
A sheepdog volume in libvirt maps to a sheepdog vdi.
To create one specify the pool, a name and the capacity.
Volumes can also be resized later.
In the volume XML the vdi name has to be put into the <target><path>.
To use the volume as a disk source for virtual machines specify
the vdi name as "name" attribute of the <source>.
The host and port information from the pool are specified inside the host tag.
<disk type='network'>
...
<source protocol="sheepdog" name="vdi_name">
<host name="localhost" port="7000"/>
</source>
</disk>
To work right this patch parses the output of collie,
so it relies on the raw output option. There recently was a bug which caused
size information to be reported wrong. This is fixed upstream already and
will be in the next release.
Signed-off-by: Sebastian Wiedenroth <wiedi(a)frubar.net>
---
.gitignore | 1 +
configure.ac | 32 +++
docs/drivers.html.in | 1 +
docs/schemas/storagepool.rng | 17 ++
docs/schemas/storagevol.rng | 3 +-
docs/storage.html.in | 62 +++++
libvirt.spec.in | 35 ++-
po/POTFILES.in | 1 +
src/Makefile.am | 8 +
src/conf/storage_conf.c | 19 +-
src/conf/storage_conf.h | 1 +
src/storage/storage_backend.c | 6 +
src/storage/storage_backend_sheepdog.c | 311 +++++++++++++++++++++++++
src/storage/storage_backend_sheepdog.h | 39 ++++
tests/Makefile.am | 13 ++
tests/storagebackendsheepdogtest.c | 214 +++++++++++++++++
tests/storagepoolxml2xmlin/pool-sheepdog.xml | 8 +
tests/storagepoolxml2xmlout/pool-sheepdog.xml | 11 +
tests/storagepoolxml2xmltest.c | 1 +
tests/storagevolxml2xmlin/vol-sheepdog.xml | 10 +
tests/storagevolxml2xmlout/vol-sheepdog.xml | 17 ++
tests/storagevolxml2xmltest.c | 1 +
tools/virsh.c | 3 +
23 files changed, 799 insertions(+), 15 deletions(-)
create mode 100644 src/storage/storage_backend_sheepdog.c
create mode 100644 src/storage/storage_backend_sheepdog.h
create mode 100644 tests/storagebackendsheepdogtest.c
create mode 100644 tests/storagepoolxml2xmlin/pool-sheepdog.xml
create mode 100644 tests/storagepoolxml2xmlout/pool-sheepdog.xml
create mode 100644 tests/storagevolxml2xmlin/vol-sheepdog.xml
create mode 100644 tests/storagevolxml2xmlout/vol-sheepdog.xml
diff --git a/.gitignore b/.gitignore
index cd978d2..098ba09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,6 +145,7 @@
/tests/sockettest
/tests/ssh
/tests/statstest
+/tests/storagebackendsheepdogtest
/tests/utiltest
/tests/virauthconfigtest
/tests/virbuftest
diff --git a/configure.ac b/configure.ac
index c0ef9b1..13aa0e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1825,6 +1825,8 @@ AC_ARG_WITH([storage-disk],
AC_HELP_STRING([--with-storage-disk], [with GPartd Disk backend for the storage driver @<:@default=check@:>@]),[],[with_storage_disk=check])
AC_ARG_WITH([storage-rbd],
AC_HELP_STRING([--with-storage-rbd], [with RADOS Block Device backend for the storage driver @<:@default=check@:>@]),[],[with_storage_rbd=check])
+AC_ARG_WITH([storage-sheepdog],
+ AC_HELP_STRING([--with-storage-sheepdog], [with Sheepdog backend for the storage driver @<:@default=check@:>@]),[],[with_storage_sheepdog=check])
if test "$with_libvirtd" = "no"; then
with_storage_dir=no
@@ -1835,6 +1837,7 @@ if test "$with_libvirtd" = "no"; then
with_storage_mpath=no
with_storage_disk=no
with_storage_rbd=no
+ with_storage_sheepdog=no
fi
if test "$with_storage_dir" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver is enabled])
@@ -2009,6 +2012,34 @@ fi
AM_CONDITIONAL([WITH_STORAGE_RBD], [test "$with_storage_rbd" = "yes"])
AC_SUBST([LIBRBD_LIBS])
+if test "$with_storage_sheepdog" = "yes" ||
+ test "$with_storage_sheepdog" = "check"; then
+ AC_PATH_PROG([COLLIE], [collie], [], [$PATH:/sbin:/usr/sbin])
+
+ if test "$with_storage_sheepdog" = "yes"; then
+ if test -z "$COLLIE"; then
+ AC_MSG_ERROR([We need collie for Sheepdog storage driver])
+ fi
+ else
+ if test -z "$COLLIE"; then
+ with_storage_sheepdog=no
+ fi
+
+ if test "$with_storage_sheepdog" = "check"; then
+ with_storage_sheepdog=yes
+ fi
+ fi
+
+ if test "$with_storage_sheepdog" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_STORAGE_SHEEPDOG], 1,
+ [whether Sheepdog backend for storage driver is enabled])
+ AC_DEFINE_UNQUOTED([COLLIE],["$COLLIE"],[Location of collie program])
+ fi
+fi
+AM_CONDITIONAL([WITH_STORAGE_SHEEPDOG],
+ [test "$with_storage_sheepdog" = "yes"])
+
+
LIBPARTED_CFLAGS=
LIBPARTED_LIBS=
if test "$with_storage_disk" = "yes" ||
@@ -2824,6 +2855,7 @@ AC_MSG_NOTICE([ SCSI: $with_storage_scsi])
AC_MSG_NOTICE([ mpath: $with_storage_mpath])
AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([ RBD: $with_storage_rbd])
+AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([])
diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index 8ad2c33..90b6196 100644
--- a/docs/drivers.html.in
+++ b/docs/drivers.html.in
@@ -43,6 +43,7 @@
<li><strong><a href="storage.html#StorageBackendSCSI">SCSI backend</a></strong></li>
<li><strong><a href="storage.html#StorageBackendMultipath">Multipath backend</a></strong></li>
<li><strong><a href="storage.html#StorageBackendRBD">RBD (RADOS Block Device) backend</a></strong></li>
+ <li><strong><a href="storage.html#StorageBackendSheepdog">Sheepdog backend</a></strong></li>
</ul>
</body>
</html>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 75b6b51..039798a 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -20,6 +20,7 @@
<ref name='poolscsi'/>
<ref name='poolmpath'/>
<ref name='poolrbd'/>
+ <ref name='poolsheepdog'/>
</choice>
</element>
</define>
@@ -115,6 +116,15 @@
<ref name='sourcerbd'/>
</define>
+ <define name='poolsheepdog'>
+ <attribute name='type'>
+ <value>sheepdog</value>
+ </attribute>
+ <ref name='commonmetadata'/>
+ <ref name='sizing'/>
+ <ref name='sourcesheepdog'/>
+ </define>
+
<define name='sourceinfovendor'>
<optional>
<element name='vendor'>
@@ -496,6 +506,13 @@
</element>
</define>
+ <define name='sourcesheepdog'>
+ <element name='source'>
+ <ref name='sourceinfohost'/>
+ <ref name='sourceinfoname'/>
+ </element>
+ </define>
+
<define name='name'>
<data type='string'>
<param name="pattern">[a-zA-Z0-9_\+\-]+</param>
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 7a74331..0b9933d 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -67,7 +67,7 @@
<element name='target'>
<optional>
<element name='path'>
- <ref name='absFilePath'/>
+ <data type='anyURI'/>
</element>
</optional>
<ref name='format'/>
@@ -144,6 +144,7 @@
<define name='formatfile'>
<choice>
+ <value>unknown</value>
<value>raw</value>
<value>dir</value>
<value>bochs</value>
diff --git a/docs/storage.html.in b/docs/storage.html.in
index b3484e8..26a949a 100644
--- a/docs/storage.html.in
+++ b/docs/storage.html.in
@@ -110,6 +110,9 @@
<li>
<a href="#StorageBackendRBD">RBD (RADOS Block Device) backend</a>
</li>
+ <li>
+ <a href="#StorageBackendSheepdog">Sheepdog backend</a>
+ </li>
</ul>
<h2><a name="StorageBackendDir">Directory pool</a></h2>
@@ -565,5 +568,64 @@
The RBD pool does not use the volume format type element.
</p>
+ <h2><a name="StorageBackendSheepdog">Sheepdog pools</a></h2>
+ <p>
+ This provides a pool based on a Sheepdog Cluster.
+ Sheepdog is a distributed storage system for QEMU/KVM.
+ It provides highly available block level storage volumes that
+ can be attached to QEMU/KVM virtual machines.
+
+ The cluster must already be formatted.
+
+ <span class="since">Since 0.9.13</span>
+ </p>
+
+ <h3>Example pool input</h3>
+ <pre>
+ <pool type="sheepdog">
+ <name>mysheeppool</name>
+ <source>
+ <name>mysheeppool</name>
+ <host name='localhost' port='7000'/>
+ </source>
+ </pool></pre>
+
+ <h3>Example volume output</h3>
+ <pre>
+ <volume>
+ <name>myvol</name>
+ <key>sheep/myvol</key>
+ <source>
+ </source>
+ <capacity unit='bytes'>53687091200</capacity>
+ <allocation unit='bytes'>53687091200</allocation>
+ <target>
+ <path>sheepdog:myvol</path>
+ <format type='unknown'/>
+ <permissions>
+ <mode>00</mode>
+ <owner>0</owner>
+ <group>0</group>
+ </permissions>
+ </target>
+ </volume></pre>
+
+ <h3>Example disk attachment</h3>
+ <p>Sheepdog images can be attached to Qemu guests.
+ Information about attaching a Sheepdog image to a
+ guest can be found
+ at the <a href="formatdomain.html#elementsDisks">format domain</a>
+ page.</p>
+
+ <h3>Valid pool format types</h3>
+ <p>
+ The Sheepdog pool does not use the pool format type element.
+ </p>
+
+ <h3>Valid volume format types</h3>
+ <p>
+ The Sheepdog pool does not use the volume format type element.
+ </p>
+
</body>
</html>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 896ef51..e80259e 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -69,19 +69,24 @@
%define with_xenapi 0%{!?_without_xenapi:1}
# Then the secondary host drivers, which run inside libvirtd
-%define with_network 0%{!?_without_network:%{server_drivers}}
-%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
-%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
-%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
-%define with_storage_disk 0%{!?_without_storage_disk:%{server_drivers}}
-%define with_storage_mpath 0%{!?_without_storage_mpath:%{server_drivers}}
+%define with_network 0%{!?_without_network:%{server_drivers}}
+%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
+%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
+%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
+%define with_storage_disk 0%{!?_without_storage_disk:%{server_drivers}}
+%define with_storage_mpath 0%{!?_without_storage_mpath:%{server_drivers}}
%if 0%{?fedora} >= 16
-%define with_storage_rbd 0%{!?_without_storage_rbd:%{server_drivers}}
+%define with_storage_rbd 0%{!?_without_storage_rbd:%{server_drivers}}
%else
-%define with_storage_rbd 0
+%define with_storage_rbd 0
%endif
-%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
-%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
+%if 0%{?fedora} >= 17
+%define with_storage_sheepdog 0%{!?_without_storage_sheepdog:%{server_drivers}}
+%else
+%define with_storage_sheepdog 0
+%endif
+%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
+%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
# A few optional bits off by default, we enable later
%define with_polkit 0%{!?_without_polkit:0}
@@ -224,6 +229,7 @@
%define with_storage_iscsi 0
%define with_storage_mpath 0
%define with_storage_rbd 0
+%define with_storage_sheepdog 0
%define with_storage_disk 0
%endif
@@ -603,6 +609,10 @@ Requires: device-mapper
# For RBD support
Requires: ceph
%endif
+%if %{with_storage_sheepdog}
+# For Sheepdog support
+Requires: sheepdog
+%endif
%if %{with_cgconfig}
Requires: libcgroup
%endif
@@ -1080,6 +1090,10 @@ of recent versions of Linux (and other OSes).
%define _without_storage_rbd --without-storage-rbd
%endif
+%if ! %{with_storage_sheepdog}
+%define _without_storage_sheepdog --without-storage-sheepdog
+%endif
+
%if ! %{with_numactl}
%define _without_numactl --without-numactl
%endif
@@ -1178,6 +1192,7 @@ autoreconf -if
%{?_without_storage_disk} \
%{?_without_storage_mpath} \
%{?_without_storage_rbd} \
+ %{?_without_storage_sheepdog} \
%{?_without_numactl} \
%{?_without_numad} \
%{?_without_capng} \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 31246f7..33a2ace 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -108,6 +108,7 @@ src/storage/storage_backend_logical.c
src/storage/storage_backend_mpath.c
src/storage/storage_backend_rbd.c
src/storage/storage_backend_scsi.c
+src/storage/storage_backend_sheepdog.c
src/storage/storage_driver.c
src/test/test_driver.c
src/uml/uml_conf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 2309984..7effcd6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -515,6 +515,9 @@ STORAGE_DRIVER_DISK_SOURCES = \
STORAGE_DRIVER_RBD_SOURCES = \
storage/storage_backend_rbd.h storage/storage_backend_rbd.c
+STORAGE_DRIVER_SHEEPDOG_SOURCES = \
+ storage/storage_backend_sheepdog.h storage/storage_backend_sheepdog.c
+
STORAGE_HELPER_DISK_SOURCES = \
storage/parthelper.c
@@ -1019,6 +1022,10 @@ libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_RBD_SOURCES)
libvirt_driver_storage_la_LIBADD += $(LIBRBD_LIBS)
endif
+if WITH_STORAGE_SHEEPDOG
+libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SHEEPDOG_SOURCES)
+endif
+
if WITH_NODE_DEVICES
# Needed to keep automake quiet about conditionals
if WITH_DRIVER_MODULES
@@ -1117,6 +1124,7 @@ EXTRA_DIST += \
$(STORAGE_DRIVER_MPATH_SOURCES) \
$(STORAGE_DRIVER_DISK_SOURCES) \
$(STORAGE_DRIVER_RBD_SOURCES) \
+ $(STORAGE_DRIVER_SHEEPDOG_SOURCES) \
$(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index bf4567f..cd17db6 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -52,7 +52,7 @@ VIR_ENUM_IMPL(virStoragePool,
VIR_STORAGE_POOL_LAST,
"dir", "fs", "netfs",
"logical", "disk", "iscsi",
- "scsi", "mpath", "rbd")
+ "scsi", "mpath", "rbd", "sheepdog")
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
VIR_STORAGE_POOL_FS_LAST,
@@ -206,6 +206,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.formatToString = virStoragePoolFormatDiskTypeToString,
}
},
+ { .poolType = VIR_STORAGE_POOL_SHEEPDOG,
+ .poolOptions = {
+ .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+ VIR_STORAGE_POOL_SOURCE_NETWORK |
+ VIR_STORAGE_POOL_SOURCE_NAME),
+ },
+ .volOptions = {
+ .defaultFormat = VIR_STORAGE_FILE_RAW,
+ .formatToString = virStoragePoolFormatDiskTypeToString,
+ }
+ },
{ .poolType = VIR_STORAGE_POOL_MPATH,
.volOptions = {
.formatToString = virStoragePoolFormatDiskTypeToString,
@@ -1011,9 +1022,9 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
goto cleanup;
- /* RBD devices are not local block devs nor files, so it doesn't
+ /* RBD and Sheepdog devices are not local block devs nor files, so it doesn't
* have a target */
- if (def->type != VIR_STORAGE_POOL_RBD) {
+ if (def->type != VIR_STORAGE_POOL_RBD && def->type != VIR_STORAGE_POOL_SHEEPDOG) {
virBufferAddLit(&buf," <target>\n");
if (def->target.path)
@@ -1296,7 +1307,7 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool,
virBufferAddLit(&buf, "<volume>\n");
virBufferAsprintf(&buf," <name>%s</name>\n", def->name);
- virBufferAsprintf(&buf," <key>%s</key>\n", def->key);
+ virBufferAsprintf(&buf," <key>%s</key>\n", def->key ? def->key : "(null)");
virBufferAddLit(&buf, " <source>\n");
if (def->source.nextent) {
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 5733b57..dcf976f 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -121,6 +121,7 @@ enum virStoragePoolType {
VIR_STORAGE_POOL_SCSI, /* SCSI HBA */
VIR_STORAGE_POOL_MPATH, /* Multipath devices */
VIR_STORAGE_POOL_RBD, /* RADOS Block Device */
+ VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */
VIR_STORAGE_POOL_LAST,
};
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index e2e9b51..93964d6 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -80,6 +80,9 @@
#if WITH_STORAGE_RBD
# include "storage_backend_rbd.h"
#endif
+#if WITH_STORAGE_SHEEPDOG
+# include "storage_backend_sheepdog.h"
+#endif
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -109,6 +112,9 @@ static virStorageBackendPtr backends[] = {
#if WITH_STORAGE_RBD
&virStorageBackendRBD,
#endif
+#if WITH_STORAGE_SHEEPDOG
+ &virStorageBackendSheepdog,
+#endif
NULL
};
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
new file mode 100644
index 0000000..68633d4
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.c
@@ -0,0 +1,311 @@
+/*
+ * storage_backend_sheepdog.c: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Wido den Hollander
+ * Copyright (C) 2012 Frank Spijkerman
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Wido den Hollander <wido(a)widodh.nl>
+ * Frank Spijkerman <frank.spijkerman(a)avira.com>
+ * Sebastian Wiedenroth <sebastian.wiedenroth(a)skylime.net>
+ */
+
+#include <config.h>
+
+#include "virterror_internal.h"
+#include "storage_backend_sheepdog.h"
+#include "storage_conf.h"
+#include "util/command.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+static int virStorageBackendSheepdogRefreshVol(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol);
+
+void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd,
+ virStoragePoolObjPtr pool);
+
+int
+virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
+ char *output)
+{
+ /* fields:
+ * node id/total, size, used, use%, [total vdi size]
+ *
+ * example output:
+ * 0 15245667872 117571104 0%
+ * Total 15245667872 117571104 0% 20972341
+ */
+
+ const char *p, *next;
+
+ pool->allocation = pool->capacity = pool->available = 0;
+
+ p = output;
+ do {
+ char *end;
+
+ if ((next = strchr(p, '\n')))
+ ++next;
+ else
+ return -1;
+
+ if (!STRPREFIX(p, "Total "))
+ continue;
+
+ p = p + 6;
+
+ if (virStrToLong_ull(p, &end, 10, &pool->capacity) < 0)
+ return -1;
+
+ if ((p = end + 1) > next)
+ return -1;
+
+ if (virStrToLong_ull(p, &end, 10, &pool->allocation) < 0)
+ return -1;
+
+ pool->available = pool->capacity - pool->allocation;
+ return 0;
+
+ } while ((p = next));
+
+ return -1;
+}
+
+void
+virStorageBackendSheepdogAddHostArg(virCommandPtr cmd,
+ virStoragePoolObjPtr pool)
+{
+ const char *address = "localhost";
+ int port = 7000;
+ if (pool->def->source.nhost > 0) {
+ if (pool->def->source.hosts[0].name != NULL) {
+ address = pool->def->source.hosts[0].name;
+ }
+ if (pool->def->source.hosts[0].port) {
+ port = pool->def->source.hosts[0].port;
+ }
+ }
+ virCommandAddArg(cmd, "-a");
+ virCommandAddArgFormat(cmd, "%s", address);
+ virCommandAddArg(cmd, "-p");
+ virCommandAddArgFormat(cmd, "%d", port);
+}
+
+
+static int
+virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool)
+{
+ int ret;
+ char *output = NULL;
+ virCommandPtr cmd;
+
+ cmd = virCommandNewArgList(COLLIE, "node", "info", "-r", NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ virCommandSetOutputBuffer(cmd, &output);
+ ret = virCommandRun(cmd, NULL);
+ if (ret == 0)
+ ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);
+
+ virCommandFree(cmd);
+ VIR_FREE(output);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned int flags)
+{
+
+ virCheckFlags(0, -1);
+
+ virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "delete", vol->name, NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ int ret = virCommandRun(cmd, NULL);
+
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+
+ int ret;
+
+ if (vol->target.encryption != NULL) {
+ virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Sheepdog does not support encrypted volumes"));
+ return -1;
+ }
+
+ virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL);
+ virCommandAddArgFormat(cmd, "%llu", vol->capacity);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ ret = virCommandRun(cmd, NULL);
+
+ virStorageBackendSheepdogRefreshVol(conn, pool, vol);
+
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+int
+virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
+ char *output)
+{
+ /* fields:
+ * current/clone/snapshot, name, id, size, used, shared, creation time, vdi id, [tag]
+ *
+ * example output:
+ * s test 1 10 0 0 1336556634 7c2b25
+ * s test 2 10 0 0 1336557203 7c2b26
+ * = test 3 10 0 0 1336557216 7c2b27
+ */
+
+ int id;
+ const char *p, *next;
+
+ vol->allocation = vol->capacity = 0;
+
+ p = output;
+ do {
+ char *end;
+
+ if ((next = strchr(p, '\n')))
+ ++next;
+
+ /* ignore snapshots */
+ if (*p != '=')
+ continue;
+
+ /* skip space */
+ if (p + 2 < next) {
+ p += 2;
+ } else {
+ return -1;
+ }
+
+ /* skip name */
+ while (*p != '\0' && *p != ' ') {
+ if (*p == '\\')
+ ++p;
+ ++p;
+ }
+
+ if (virStrToLong_i(p, &end, 10, &id) < 0)
+ return -1;
+
+ p = end + 1;
+
+ if (virStrToLong_ull(p, &end, 10, &vol->capacity) < 0)
+ return -1;
+
+ p = end + 1;
+
+ if (virStrToLong_ull(p, &end, 10, &vol->allocation) < 0)
+ return -1;
+
+ return 0;
+ } while ((p = next));
+
+ return -1;
+}
+
+static int
+virStorageBackendSheepdogRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+ int ret;
+ char *output = NULL;
+
+ virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", vol->name, "-r", NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ virCommandSetOutputBuffer(cmd, &output);
+ ret = virCommandRun(cmd, NULL);
+
+ if (ret < 0)
+ goto cleanup;
+
+ if ((ret = virStorageBackendSheepdogParseVdiList(vol, output)) < 0)
+ goto cleanup;
+
+ vol->type = VIR_STORAGE_VOL_NETWORK;
+
+ VIR_FREE(vol->key);
+ if (virAsprintf(&vol->key, "%s/%s",
+ pool->def->source.name, vol->name) == -1) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ VIR_FREE(vol->target.path);
+ if (virAsprintf(&vol->target.path, "%s", vol->name) == -1) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags)
+{
+
+ virCheckFlags(0, -1);
+
+ virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "resize", vol->name, NULL);
+ virCommandAddArgFormat(cmd, "%llu", capacity);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ int ret = virCommandRun(cmd, NULL);
+
+ virCommandFree(cmd);
+ return ret;
+
+}
+
+
+
+virStorageBackend virStorageBackendSheepdog = {
+ .type = VIR_STORAGE_POOL_SHEEPDOG,
+
+ .refreshPool = virStorageBackendSheepdogRefreshPool,
+ .createVol = virStorageBackendSheepdogCreateVol,
+ .refreshVol = virStorageBackendSheepdogRefreshVol,
+ .deleteVol = virStorageBackendSheepdogDeleteVol,
+ .resizeVol = virStorageBackendSheepdogResizeVol,
+};
diff --git a/src/storage/storage_backend_sheepdog.h b/src/storage/storage_backend_sheepdog.h
new file mode 100644
index 0000000..51ef7a4
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.h
@@ -0,0 +1,39 @@
+/*
+ * storage_backend_sheepog.h: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Wido den Hollander
+ * Copyright (C) 2012 Frank Spijkerman
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Wido den Hollander <wido(a)widodh.nl>
+ * Frank Spijkerman <frank.spijkerman(a)avira.com>
+ * Sebastian Wiedenroth <sebastian.wiedenroth(a)skylime.net>
+ */
+
+#ifndef __VIR_STORAGE_BACKEND_SHEEPDOG_H__
+# define __VIR_STORAGE_BACKEND_SHEEPDOG_H__
+
+# include "storage_backend.h"
+
+int virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
+ char *output);
+int virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
+ char *output);
+
+extern virStorageBackend virStorageBackendSheepdog;
+
+#endif /* __VIR_STORAGE_BACKEND_SHEEPDOG_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e3bd6d1..a466480 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -141,6 +141,10 @@ if WITH_NETWORK
test_programs += networkxml2argvtest
endif
+if WITH_STORAGE_SHEEPDOG
+test_programs += storagebackendsheepdogtest
+endif
+
test_programs += nwfilterxml2xmltest
test_programs += storagevolxml2xmltest storagepoolxml2xmltest
@@ -398,6 +402,15 @@ else
EXTRA_DIST += networkxml2argvtest.c
endif
+if WITH_STORAGE_SHEEPDOG
+storagebackendsheepdogtest_SOURCES = \
+ storagebackendsheepdogtest.c \
+ testutils.c testutils.h
+storagebackendsheepdogtest_LDADD = ../src/libvirt_driver_storage.la $(LDADDS)
+else
+EXTRA_DIST += storagebackendsheepdogtest.c
+endif
+
nwfilterxml2xmltest_SOURCES = \
nwfilterxml2xmltest.c \
testutils.c testutils.h
diff --git a/tests/storagebackendsheepdogtest.c b/tests/storagebackendsheepdogtest.c
new file mode 100644
index 0000000..0870829
--- /dev/null
+++ b/tests/storagebackendsheepdogtest.c
@@ -0,0 +1,214 @@
+/*
+ * storagebackendsheepdogtest.c: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Sebastian Wiedenroth <sebastian.wiedenroth(a)skylime.net>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "storage/storage_backend_sheepdog.h"
+
+
+typedef struct {
+ const char *output;
+ int expected_return;
+ uint64_t expected_capacity;
+ uint64_t expected_allocation;
+} collie_test;
+
+
+static int
+test_node_info_parser(collie_test test, char *poolxml)
+{
+ int ret = -1;
+ char *output = NULL;
+ char *poolXmlData = NULL;
+ virStoragePoolDefPtr pool = NULL;
+
+ if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+ goto cleanup;
+
+ if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+ goto cleanup;
+
+ output = strdup(test.output);
+ if (!output)
+ goto cleanup;
+
+ if (virStorageBackendSheepdogParseNodeInfo(pool, output) !=
+ test.expected_return)
+ goto cleanup;
+
+ if (test.expected_return) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (pool->capacity == test.expected_capacity &&
+ pool->allocation == test.expected_allocation)
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(output);
+ VIR_FREE(poolXmlData);
+ virStoragePoolDefFree(pool);
+ return ret;
+}
+
+static int
+test_vdi_list_parser(collie_test test, char *poolxml, char *volxml)
+{
+ int ret = -1;
+ char *poolXmlData = NULL;
+ char *volXmlData = NULL;
+ char *output = NULL;
+ virStoragePoolDefPtr pool = NULL;
+ virStorageVolDefPtr vol = NULL;
+
+ if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+ goto cleanup;
+ if (virtTestLoadFile(volxml, &volXmlData) < 0)
+ goto cleanup;
+
+ if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+ goto cleanup;
+
+ if (!(vol = virStorageVolDefParseString(pool, volXmlData)))
+ goto cleanup;
+
+ output = strdup(test.output);
+ if (!output)
+ goto cleanup;
+
+ if (virStorageBackendSheepdogParseVdiList(vol, output) !=
+ test.expected_return)
+ goto cleanup;
+
+ if (test.expected_return) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (vol->capacity == test.expected_capacity &&
+ vol->allocation == test.expected_allocation)
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(output);
+ VIR_FREE(poolXmlData);
+ VIR_FREE(volXmlData);
+ virStoragePoolDefFree(pool);
+ virStorageVolDefFree(vol);
+ return ret;
+}
+
+
+static int
+mymain(void)
+{
+ int ret = -1;
+ char *poolxml = NULL;
+ char *volxml = NULL;
+
+ collie_test node_info_tests[] = {
+ {"", -1, 0, 0},
+ {"Total 15245667872 117571104 0% 20972341\n", 0, 15245667872, 117571104},
+ {"To", -1, 0, 0},
+ {"asdf\nasdf", -1, 0, 0},
+ {"Total ", -1, 0, 0},
+ {"Total 1", -1, 0, 0},
+ {"Total 1\n", -1, 0, 0},
+ {"Total 1 ", -1, 0, 0},
+ {"Total 1 2", -1, 0, 0},
+ {"Total 1 2 ", -1, 0, 0},
+ {"Total 1 2\n", 0, 1, 2},
+ {"Total 1 2 \n", 0, 1, 2},
+ {"Total a 2 \n", -1, 0, 0},
+ {"Total 1 b \n", -1, 0, 0},
+ {"Total a b \n", -1, 0, 0},
+ {"stuff\nTotal 1 2 \n", 0, 1, 2},
+ {"0 1 2 3\nTotal 1 2 \n", 0, 1, 2},
+ {NULL, 0, 0, 0}
+ };
+
+ collie_test vdi_list_tests[] = {
+ {"", -1, 0, 0},
+ {"= test 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+ {"= test\\ with\\ spaces 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+ {"= backslashattheend\\\\ 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+ {"s test 1 10 20 0 1336556634 7c2b25\n= test 3 50 60 0 1336557216 7c2b27\n", 0, 50, 60},
+ {"=", -1, 0, 0},
+ {"= test", -1, 0, 0},
+ {"= test ", -1, 0, 0},
+ {"= test 1", -1, 0, 0},
+ {"= test 1 ", -1, 0, 0},
+ {"= test 1 2", -1, 0, 0},
+ {"= test 1 2 ", -1, 0, 0},
+ {"= test 1 2 3", -1, 0, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ collie_test *test = node_info_tests;
+
+ if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/pool-sheepdog.xml",
+ abs_srcdir) < 0)
+ goto cleanup;
+
+ if (virAsprintf(&volxml, "%s/storagevolxml2xmlin/vol-sheepdog.xml",
+ abs_srcdir) < 0)
+ goto cleanup;
+
+ while (test->output != NULL) {
+ ret = test_node_info_parser(*test, poolxml);
+ virtTestResult("node_info_parser", ret, NULL);
+ ++test;
+ if (ret < 0)
+ return EXIT_FAILURE;
+ }
+
+ test = vdi_list_tests;
+
+ while (test->output != NULL) {
+ ret = test_vdi_list_parser(*test, poolxml, volxml);
+ virtTestResult("vdi_list_parser", ret, NULL);
+ ++test;
+ if (ret < 0)
+ return EXIT_FAILURE;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(poolxml);
+ VIR_FREE(volxml);
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
diff --git a/tests/storagepoolxml2xmlin/pool-sheepdog.xml b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
new file mode 100644
index 0000000..1287047
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
@@ -0,0 +1,8 @@
+<pool type='sheepdog'>
+ <name>sheepdog</name>
+ <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+ <source>
+ <host name='localhost' port='7000'/>
+ <name>sheepdog</name>
+ </source>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-sheepdog.xml b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
new file mode 100644
index 0000000..000c068
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
@@ -0,0 +1,11 @@
+<pool type='sheepdog'>
+ <name>sheepdog</name>
+ <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+ <capacity unit='bytes'>0</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <available unit='bytes'>0</available>
+ <source>
+ <host name='localhost' port='7000'/>
+ <name>sheepdog</name>
+ </source>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index d73fc8a..8cac978 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -93,6 +93,7 @@ mymain(void)
DO_TEST("pool-mpath");
DO_TEST("pool-iscsi-multiiqn");
DO_TEST("pool-iscsi-vendor-product");
+ DO_TEST("pool-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/tests/storagevolxml2xmlin/vol-sheepdog.xml b/tests/storagevolxml2xmlin/vol-sheepdog.xml
new file mode 100644
index 0000000..49e221c
--- /dev/null
+++ b/tests/storagevolxml2xmlin/vol-sheepdog.xml
@@ -0,0 +1,10 @@
+<volume>
+ <name>test2</name>
+ <source>
+ </source>
+ <capacity unit='bytes'>1024</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <target>
+ <path>sheepdog:test2</path>
+ </target>
+</volume>
diff --git a/tests/storagevolxml2xmlout/vol-sheepdog.xml b/tests/storagevolxml2xmlout/vol-sheepdog.xml
new file mode 100644
index 0000000..2f19af8
--- /dev/null
+++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml
@@ -0,0 +1,17 @@
+<volume>
+ <name>test2</name>
+ <key>(null)</key>
+ <source>
+ </source>
+ <capacity unit='bytes'>1024</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <target>
+ <path>sheepdog:test2</path>
+ <format type='unknown'/>
+ <permissions>
+ <mode>0600</mode>
+ <owner>4294967295</owner>
+ <group>4294967295</group>
+ </permissions>
+ </target>
+</volume>
diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c
index 37c92cd..ee85988 100644
--- a/tests/storagevolxml2xmltest.c
+++ b/tests/storagevolxml2xmltest.c
@@ -112,6 +112,7 @@ mymain(void)
DO_TEST("pool-disk", "vol-partition");
DO_TEST("pool-logical", "vol-logical");
DO_TEST("pool-logical", "vol-logical-backing");
+ DO_TEST("pool-sheepdog", "vol-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index 2b4cb2c..dd0261c 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -20696,6 +20696,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
#ifdef WITH_STORAGE_RBD
vshPrint(ctl, " RBD");
#endif
+#ifdef WITH_STORAGE_SHEEPDOG
+ vshPrint(ctl, " Sheepdog");
+#endif
vshPrint(ctl, "\n");
vshPrint(ctl, "%s", _(" Miscellaneous:"));
--
1.7.9.4
12 years, 4 months
[libvirt] IPs via DHCP for guest domains
by Fong Vang
I'm curious to know how you are providing IPs for your Windows VMs
when connected via a bridge. Since broadcasts from the VMs are going
out the bridged interface, I'm thinking about implementing ebtables to
block dhcp broadcasts from going in/out the interface so that dnsmasq
would only respond to dhcp requests from the local guest VMs. Before
I venture down this path, I thought I might ask if there's an easier
way to do this with libvirt.
Thanks for any help.
12 years, 4 months
[libvirt] [PATCH 0/4] qemu: configurable port boundaries for remote displays
by Martin Kletzander
This series introduces a possibility to change default minimal and
maximal port numbers that are used to specify a remote display port
for both VNC and SPICE.
Because the code was a bit messy, PATCH 1/4 cleans up few things
needed to make a clean run of PATCH 2/4, that does the main change in
the code.
I also noticed two things that could be changed and it made sense for
me to do that, but these are nowhere near any importance, so feel free
to reject them if your heart feels that way.
PATCH 3/4 rewords three messages and applying it would mean that they are not translated. Even though I think it makes more sense this way, I'm not a good English speaker, so that's more like an RFC.
PATCH 4/4 makes more flexible port searching available, but is used on one place and because there are so many ports, it won't be that used, I guess.
P.S.: this is basically v2 for
https://www.redhat.com/archives/libvir-list/2012-May/msg01081.html but
it changed a lot and the name is also different, so I didn't want to
create any confision.
Martin Kletzander (4):
qemu: Unify port-wise SPICE and VNC behavior
qemu: configurable remote display port boundaries
qemu: modify 3 error messages
qemu: allow searching for all open ports
src/conf/domain_conf.c | 2 +-
src/qemu/libvirtd_qemu.aug | 4 ++
src/qemu/qemu.conf | 14 ++++++
src/qemu/qemu_command.h | 11 ++++-
src/qemu/qemu_conf.c | 40 +++++++++++++++++-
src/qemu/qemu_conf.h | 4 +-
src/qemu/qemu_driver.c | 19 ++++-----
src/qemu/qemu_process.c | 81 +++++++++++++++++++++---------------
src/qemu/test_libvirtd_qemu.aug.in | 2 +
9 files changed, 128 insertions(+), 49 deletions(-)
--
1.7.8.6
12 years, 4 months
[libvirt] [PATCH v4 0/7] file descriptor passing using pass-fd
by Corey Bryant
libvirt's sVirt security driver provides SELinux MAC isolation for
Qemu guest processes and their corresponding image files. In other
words, sVirt uses SELinux to prevent a QEMU process from opening
files that do not belong to it.
sVirt provides this support by labeling guests and resources with
security labels that are stored in file system extended attributes.
Some file systems, such as NFS, do not support the extended
attribute security namespace, and therefore cannot support sVirt
isolation.
A solution to this problem is to provide fd passing support, where
libvirt opens files and passes file descriptors to QEMU. This,
along with SELinux policy to prevent QEMU from opening files, can
provide image file isolation for NFS files stored on the same NFS
mount.
This patch series adds the pass-fd QMP monitor command, which allows
an fd to be passed via SCM_RIGHTS, and returns the received file
descriptor. Support is also added to the block layer to allow QEMU
to dup the fd when the filename is of the /dev/fd/X format. This
is useful if MAC policy prevents QEMU from opening specific types
of files.
One nice thing about this approach is that no new SELinux policy is
required to prevent open of NFS files (files with type nfs_t). The
virt_use_nfs boolean type simply needs to be set to false, and open
will be prevented (and dup will be allowed). For example:
# setsebool virt_use_nfs 0
# getsebool virt_use_nfs
virt_use_nfs --> off
Corey Bryant (7):
qemu-char: Add MSG_CMSG_CLOEXEC flag to recvmsg
qapi: Convert getfd and closefd
qapi: Add pass-fd QMP command
qapi: Re-arrange monitor.c functions
block: Prevent /dev/fd/X filename from being detected as floppy
block: Convert open calls to qemu_open
osdep: Enable qemu_open to dup pre-opened fd
block/raw-posix.c | 22 +++++-----
block/raw-win32.c | 4 +-
block/vdi.c | 5 ++-
block/vmdk.c | 21 ++++------
block/vpc.c | 2 +-
block/vvfat.c | 21 +++++-----
cutils.c | 26 +++++++++---
dump.c | 3 +-
hmp-commands.hx | 6 +--
hmp.c | 18 ++++++++
hmp.h | 2 +
main-loop.c | 6 +--
migration-fd.c | 2 +-
monitor.c | 120 ++++++++++++++++++++++++++++++++---------------------
monitor.h | 2 +-
net.c | 6 ++-
osdep.c | 91 ++++++++++++++++++++++++++++++++++++++++
qapi-schema.json | 71 +++++++++++++++++++++++++++++++
qemu-char.c | 2 +-
qemu-common.h | 2 +-
qmp-commands.hx | 56 ++++++++++++++++++++++---
21 files changed, 378 insertions(+), 110 deletions(-)
--
1.7.10.2
12 years, 4 months