[libvirt] [PATCH] qemu: Use correct permissions when determining the image chain
by Peter Krempa
The code took into account only the global permissions. The domains now
support per-vm DAC lables and per-image DAC labels. Use the most
specific label available.
---
src/qemu/qemu_domain.c | 35 +++++++++++++++++++++++++++++++++--
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 8 ++++----
src/qemu/qemu_hotplug.c | 2 +-
src/qemu/qemu_process.c | 2 +-
5 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index c947e2e..d45210b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2210,7 +2210,7 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
if (!disk->src)
continue;
- if (qemuDomainDetermineDiskChain(driver, disk, false) >= 0 &&
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) >= 0 &&
qemuDiskChainCheckBroken(disk) >= 0)
continue;
@@ -2319,13 +2319,41 @@ qemuDiskChainCheckBroken(virDomainDiskDefPtr disk)
return 0;
}
+static void
+qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ uid_t *uid, gid_t *gid)
+{
+ virSecurityLabelDefPtr vmlabel;
+ virSecurityDeviceLabelDefPtr disklabel;
+
+ if (cfg) {
+ if (uid)
+ *uid = cfg->user;
+
+ if (gid)
+ *gid = cfg->group;
+ }
+
+ if (vm && (vmlabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")))
+ virParseOwnershipIds(vmlabel->label, uid, gid);
+
+ if ((disklabel = virDomainDiskDefGetSecurityLabelDef(disk, "dac")))
+ virParseOwnershipIds(disklabel->label, uid, gid);
+}
+
+
int
qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
virDomainDiskDefPtr disk,
bool force)
{
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
int ret = 0;
+ uid_t uid;
+ gid_t gid;
if (!disk->src ||
disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK ||
@@ -2340,8 +2368,11 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
goto cleanup;
}
}
+
+ qemuDomainGetImageIds(cfg, vm, disk, &uid, &gid);
+
disk->backingChain = virStorageFileGetMetadata(disk->src, disk->format,
- cfg->user, cfg->group,
+ uid, gid,
cfg->allowDiskFormatProbing);
if (!disk->backingChain)
ret = -1;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 84624f9..3826d0b 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -353,6 +353,7 @@ int qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
int qemuDiskChainCheckBroken(virDomainDiskDefPtr disk);
int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
virDomainDiskDefPtr disk,
bool force);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 944facb..94844df 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6499,7 +6499,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
if (qemuTranslateDiskSourcePool(conn, disk) < 0)
goto end;
- if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
goto end;
if (qemuSetupDiskCgroup(vm, disk) < 0)
@@ -14632,7 +14632,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
disk->src = disk->mirror;
disk->format = disk->mirrorFormat;
disk->backingChain = NULL;
- if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) {
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) {
disk->src = oldsrc;
disk->format = oldformat;
disk->backingChain = oldchain;
@@ -14983,7 +14983,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
goto endjob;
}
- if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
goto endjob;
if ((flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) &&
@@ -15190,7 +15190,7 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
disk->dst);
goto endjob;
}
- if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
goto endjob;
if (!top) {
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4a885d2..7066be6 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -719,7 +719,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
if (qemuSetUnprivSGIO(dev) < 0)
goto end;
- if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
goto end;
if (qemuSetupDiskCgroup(vm, disk) < 0)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 8bcd98e..c1f60cd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -997,7 +997,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL ||
type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
- qemuDomainDetermineDiskChain(driver, disk, true);
+ qemuDomainDetermineDiskChain(driver, vm, disk, true);
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
status == VIR_DOMAIN_BLOCK_JOB_READY)
disk->mirroring = true;
--
1.8.5.3
10 years, 9 months
[libvirt] why mac are different between inside and outside of vm
by yue
hi, all
nwfilter has many rules which depends on mac of vm, but i find the mac address inside vm is different from mac outside of vm.
outside mac:
vnet0 Link encap:Ethernet HWaddr FE:54:00:71:15:7B ,
inside mac:
eth0 Link encap:Ethernet HWaddr 52:54:00:71:15:7B ,virtio
why?
i am afraid that nwfilter use the wrong one.
how nwfilter chooses mac? and what is the usage of vnet0's mac?
thanks very much.
10 years, 9 months
[libvirt] [PATCH v5] bhyve: add a basic driver
by Roman Bogorodskiy
Changes from v4:
- Set acpi and apic flags based on domain definition
- Add more detailed description about -H and -P flags
of bhyve to justify theirs usage
Roman Bogorodskiy (1):
bhyve: add a basic driver
configure.ac | 7 +
daemon/libvirtd.c | 9 +
include/libvirt/virterror.h | 1 +
m4/virt-driver-bhyve.m4 | 57 +++++
po/POTFILES.in | 3 +
src/Makefile.am | 30 +++
src/bhyve/bhyve_command.c | 279 ++++++++++++++++++++++
src/bhyve/bhyve_command.h | 41 ++++
src/bhyve/bhyve_driver.c | 566 ++++++++++++++++++++++++++++++++++++++++++++
src/bhyve/bhyve_driver.h | 28 +++
src/bhyve/bhyve_process.c | 216 +++++++++++++++++
src/bhyve/bhyve_process.h | 36 +++
src/bhyve/bhyve_utils.h | 48 ++++
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 1 +
src/driver.h | 1 +
src/libvirt.c | 3 +
src/util/virerror.c | 1 +
18 files changed, 1329 insertions(+), 1 deletion(-)
create mode 100644 m4/virt-driver-bhyve.m4
create mode 100644 src/bhyve/bhyve_command.c
create mode 100644 src/bhyve/bhyve_command.h
create mode 100644 src/bhyve/bhyve_driver.c
create mode 100644 src/bhyve/bhyve_driver.h
create mode 100644 src/bhyve/bhyve_process.c
create mode 100644 src/bhyve/bhyve_process.h
create mode 100644 src/bhyve/bhyve_utils.h
--
1.8.4.3
10 years, 9 months
[libvirt] [PATCH 00/14] Avoid unsafe usage of /proc/$PID/root in LXC driver
by Daniel P. Berrange
This is a followup to Eric's original proposal
https://www.redhat.com/archives/libvir-list/2013-December/msg01242.html
The first 5 patches fix non-security bugs in the LXC hotplug
code. Then there's a couple of helper patches. Finally the
last 6 fix the actual security issue previously publically
reported.
Eric originally had a huge cleanup of virFork, but I'd
prefer that be done afterwards, to minimize the backporting
pain for stable branches.
Daniel P. Berrange (13):
Don't block use of USB with containers
Fix path used for USB device attach with LXC
Record hotplugged USB device in LXC live guest config
Fix reset of cgroup when detaching USB device from LXC guests
Disks are always block devices, never character devices
Move check for cgroup devices ACL upfront in LXC hotplug
Add virFileMakeParentPath helper function
Add helper for running code in separate namespaces
Avoid unsafe use of /proc/$PID/root in LXC disk hotplug
Avoid unsafe use of /proc/$PID/root in LXC USB hotplug
Avoid unsafe use of /proc/$PID/root in LXC block hostdev hotplug
Avoid unsafe use of /proc/$PID/root in LXC chardev hostdev hotplug
Avoid unsafe use of /proc/$PID/root in LXC hotunplug code
Eric Blake (1):
Avoid unsafe use of /proc/$PID/root in LXC shutdown/reboot code
src/conf/domain_conf.c | 1 +
src/libvirt_private.syms | 2 +
src/lxc/lxc_driver.c | 552 +++++++++++++++++++++++------------------------
src/util/virfile.c | 27 +++
src/util/virfile.h | 1 +
src/util/virinitctl.c | 26 +--
src/util/virinitctl.h | 5 +-
src/util/virprocess.c | 114 ++++++++++
src/util/virprocess.h | 11 +
9 files changed, 442 insertions(+), 297 deletions(-)
--
1.8.5.3
10 years, 9 months
[libvirt] [PATCHv3 0/3] Add HyperV timer enlightenment
by Peter Krempa
See patch 3/3 for changes.
Peter Krempa (3):
schema: Fix guest timer specification schema according to the docs
conf: Enforce supported options for certain timers
qemu: hyperv: Add support for timer enlightenments
docs/formatdomain.html.in | 7 +-
docs/schemas/domaincommon.rng | 156 +++++++++++++--------
src/conf/domain_conf.c | 59 +++++++-
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 31 ++--
.../qemuxml2argv-clock-timer-hyperv-rtc.args | 5 +
.../qemuxml2argv-clock-timer-hyperv-rtc.xml | 26 ++++
tests/qemuxml2argvtest.c | 1 +
tests/qemuxml2xmltest.c | 1 +
9 files changed, 212 insertions(+), 75 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
--
1.8.5.3
10 years, 9 months
[libvirt] [PATCH v5 0/6] Support keyboard device
by Li Zhang
From: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
This patchset is to add keyboard input device.
For PPC64, it doesn't support a default keyboard device when the graphic
is enabled. Libvirt supports QEMU command line as "-device VGA" which
won't create any keyboard device for it. So it requires libvirt to add
a default USB keyboard device for it.
This patchset is to add keyboard input device and a default USB keyboard
for PPC64.
The related discussion in QEMU community:
http://lists.nongnu.org/archive/html/qemu-devel/2013-11/msg01734.html
Li Zhang (6):
conf: Add a keyboard input device type
conf: Add one interface to add default input devices.
conf: Remove PS2 mouse device for non-X86 platforms
qemu_cap: Add USB keyboard capability
qemu: parse qemu command line for USB keyboard
Add a default USB keyboard and USB mouse for PPC64
v5 -> v4:
* Add PS/2 KBD definition in XML file. (Daniel.P.Berrange)
* Allow PS/2 KBD devices and set KBD default bus as PS2 for X86, USB for non-x86. (Daniel.P.Berrange)
* Add an implicit PS/2 KBD as PS/2 mouse. (Danniel.P.Berrange)
v4 -> v3:
* Don't remove PS2 mouse device for other virtualization drivers (Jan Tomko).
v3 -> v2:
* Handle the KBD device type in xen and QEMU driver. (Daniel.P.Berrange)
* Remove PS2 mouse device for non-X86 platforms.
* Move virDomainDefMaybeAddInput to a new patch. (Jan Tomko)
* Replace VIR_REALLOC_N with VIR_APPEND_ELEMENT. (Jan Tomoko)
* Fix several typos. (Jan Tomoko)
* Add a virReportError when QEMU_CAPS_DEVICE_USB_KBD can't be gotten. (Jan Tomoko)
v2 -> v1:
* change ifs to switch clause.
* reconstruct the patches
docs/schemas/domaincommon.rng | 1 +
src/conf/domain_conf.c | 92 ++++++++++++++--------
src/conf/domain_conf.h | 5 ++
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 41 +++++++---
src/qemu/qemu_domain.c | 23 +++++-
src/util/virarch.h | 2 +
src/xenxs/xen_sxpr.c | 27 +++++--
src/xenxs/xen_xm.c | 30 +++++--
tests/qemucapabilitiesdata/caps_1.2.2-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.3.1-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.4.2-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.5.3-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 2 +
tests/qemucapabilitiesdata/caps_1.6.50-1.caps | 1 +
tests/qemuhelptest.c | 8 ++
.../qemuxml2argvdata/qemuxml2argv-pseries-disk.xml | 3 +-
.../qemuxml2argv-pseries-usb-kbd.args | 9 +++
.../qemuxml2argv-pseries-usb-kbd.xml | 19 +++++
tests/qemuxml2argvtest.c | 3 +
22 files changed, 212 insertions(+), 62 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-kbd.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-kbd.xml
--
1.8.2.1
10 years, 9 months
[libvirt] [PATCH v2] qemu: introduce spiceport serial backend
by Martin Kletzander
Adding a new backend that makes the chardev available to be backed up
by a port in spice connection (different to spicevmc). This can be
used (as well as other backends) for any chardev libvirt supports.
Apart from spicevmc, spiceport-backed chardev will not be formatted
into the command-line if there is no spice to use (with test for that
as well). For this I moved the def->graphics caounting to the start
of the function so its results can be used in rest of the code even in
the future.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
Notes:
v2:
- No longer applies on top of "qemu: minor cleanups", but is now
based purely on master
- Addressed Christophe's comments
docs/formatdomain.html.in | 18 ++++
docs/schemas/domaincommon.rng | 4 +
src/conf/domain_audit.c | 3 +-
src/conf/domain_conf.c | 39 +++++++-
src/conf/domain_conf.h | 6 +-
src/qemu/qemu_capabilities.c | 12 ++-
src/qemu/qemu_capabilities.h | 3 +-
src/qemu/qemu_command.c | 100 ++++++++++++---------
src/qemu/qemu_monitor_json.c | 3 +-
tests/qemucapabilitiesdata/caps_1.5.3-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.6.50-1.caps | 1 +
.../qemuxml2argv-serial-spiceport-nospice.args | 6 ++
.../qemuxml2argv-serial-spiceport-nospice.xml | 40 +++++++++
.../qemuxml2argv-serial-spiceport.args | 13 +++
.../qemuxml2argv-serial-spiceport.xml | 43 +++++++++
tests/qemuxml2argvtest.c | 7 ++
tests/qemuxml2xmltest.c | 2 +
18 files changed, 255 insertions(+), 47 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fd02864..117f64d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4718,6 +4718,24 @@ qemu-kvm -net nic,model=? /dev/null
</devices>
...</pre>
+ <h6><a name="elementsCharSpiceport">Spice channel</a></h6>
+
+ <p>
+ The character device is accessible through spice connection
+ under a channel name specified in the <code>channel</code>
+ attribute. <span class="since">Since 1.2.2</span>
+ </p>
+
+<pre>
+ ...
+ <devices>
+ <serial type="spiceport">
+ <source channel="org.qemu.console.serial.0"/>
+ <target port="1"/>
+ </serial>
+ </devices>
+ ...</pre>
+
<h4><a name="elementsSound">Sound devices</a></h4>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 7f55f24..3063d5a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2876,6 +2876,7 @@
<value>vc</value>
<value>pty</value>
<value>spicevmc</value>
+ <value>spiceport</value>
</choice>
</define>
@@ -2946,6 +2947,9 @@
<attribute name="wiremode"/>
</optional>
<optional>
+ <attribute name="channel"/>
+ </optional>
+ <optional>
<ref name='devSeclabel'/>
</optional>
</element>
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 11cf5c8..b6564c2 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -1,7 +1,7 @@
/*
* domain_audit.c: Domain audit management
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -81,6 +81,7 @@ virDomainAuditChardevPath(virDomainChrSourceDefPtr chr)
case VIR_DOMAIN_CHR_TYPE_VC:
case VIR_DOMAIN_CHR_TYPE_STDIO:
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
case VIR_DOMAIN_CHR_TYPE_LAST:
return NULL;
}
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 512fe51..c7f5345 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -437,7 +437,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
"udp",
"tcp",
"unix",
- "spicevmc")
+ "spicevmc",
+ "spiceport")
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
"raw",
@@ -1583,6 +1584,11 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src,
STREQ_NULLABLE(src->data.nix.path, tgt->data.nix.path);
break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ return STREQ_NULLABLE(src->data.spiceport.channel,
+ tgt->data.spiceport.channel);
+ break;
+
case VIR_DOMAIN_CHR_TYPE_VC:
case VIR_DOMAIN_CHR_TYPE_STDIO:
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
@@ -7084,6 +7090,9 @@ error:
return ret;
}
+#define SERIAL_CHANNEL_NAME_CHARS \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-."
+
/* Parse the source half of the XML definition for a character device,
* where node is the first element of node->children of the parent
* element. def->type must already be valid. Return -1 on failure,
@@ -7104,6 +7113,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
char *path = NULL;
char *mode = NULL;
char *protocol = NULL;
+ char *channel = NULL;
int remaining = 0;
while (cur != NULL) {
@@ -7148,6 +7158,11 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
VIR_FREE(mode);
break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ if (!channel)
+ channel = virXMLPropString(cur, "channel");
+ break;
+
case VIR_DOMAIN_CHR_TYPE_LAST:
case VIR_DOMAIN_CHR_TYPE_NULL:
case VIR_DOMAIN_CHR_TYPE_VC:
@@ -7287,6 +7302,21 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
def->data.nix.path = path;
path = NULL;
break;
+
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ if (!channel) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing source channel attribute for char device"));
+ goto error;
+ }
+ if (strspn(channel, SERIAL_CHANNEL_NAME_CHARS) < strlen(channel)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Invalid character in source channel for char device"));
+ goto error;
+ }
+ def->data.spiceport.channel = channel;
+ channel = NULL;
+ break;
}
cleanup:
@@ -7297,6 +7327,7 @@ cleanup:
VIR_FREE(connectHost);
VIR_FREE(connectService);
VIR_FREE(path);
+ VIR_FREE(channel);
return remaining;
@@ -15629,6 +15660,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, " path='%s'", def->data.nix.path);
virBufferAddLit(buf, "/>\n");
break;
+
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ virBufferAsprintf(buf, " <source channel='%s'/>\n",
+ def->data.spiceport.channel);
+ break;
+
}
return 0;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9acb105..7b213b8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1,7 +1,7 @@
/*
* domain_conf.h: domain XML processing
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -1104,6 +1104,7 @@ enum virDomainChrType {
VIR_DOMAIN_CHR_TYPE_TCP,
VIR_DOMAIN_CHR_TYPE_UNIX,
VIR_DOMAIN_CHR_TYPE_SPICEVMC,
+ VIR_DOMAIN_CHR_TYPE_SPICEPORT,
VIR_DOMAIN_CHR_TYPE_LAST
};
@@ -1152,6 +1153,9 @@ struct _virDomainChrSourceDef {
bool listen;
} nix;
int spicevmc;
+ struct {
+ char *channel;
+ } spiceport;
} data;
};
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 8420047..51b4e02 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1,7 +1,7 @@
/*
* qemu_capabilities.c: QEMU capabilities generation
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -247,7 +247,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"boot-strict", /* 160 */
"pvpanic",
"enable-fips",
- "spice-file-xfer-disable"
+ "spice-file-xfer-disable",
+ "spiceport",
);
struct _virQEMUCaps {
@@ -1012,6 +1013,8 @@ virQEMUCapsComputeCmdFlags(const char *help,
virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV);
if (strstr(help, "-chardev spicevmc"))
virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEVMC);
+ if (strstr(help, "-chardev spiceport"))
+ virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT);
}
if (strstr(help, "-balloon"))
virQEMUCapsSet(qemuCaps, QEMU_CAPS_BALLOON);
@@ -2567,6 +2570,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
if (qemuCaps->version >= 1003001)
virQEMUCapsSet(qemuCaps, QEMU_CAPS_VNC_WEBSOCKET);
+ /* -chardev spiceport is supported from 1.4.0,
+ * but it's in qapi only since 1.5.0 */
+ if (qemuCaps->version >= 1005000)
+ virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT);
+
if (qemuCaps->version >= 1006000)
virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 23dccce..a4eecb6 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -1,7 +1,7 @@
/*
* qemu_capabilities.h: QEMU capabilities generation
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -202,6 +202,7 @@ enum virQEMUCapsFlags {
QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */
QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */
QEMU_CAPS_SPICE_FILE_XFER_DISABLE = 163, /* -spice disable-agent-file-xfer */
+ QEMU_CAPS_CHARDEV_SPICEPORT = 164, /* -chardev spiceport */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6cc32f9..37d38f1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1,7 +1,7 @@
/*
* qemu_command.c: QEMU command generation
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -5977,6 +5977,16 @@ qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias,
virDomainChrSpicevmcTypeToString(dev->data.spicevmc));
break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("spiceport not supported in this QEMU binary"));
+ goto error;
+ }
+ virBufferAsprintf(&buf, "spiceport,id=char%s,name=%s", alias,
+ dev->data.spiceport.channel);
+ break;
+
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported chardev '%s'"),
@@ -6072,6 +6082,10 @@ qemuBuildChrArgStr(virDomainChrSourceDefPtr dev, const char *prefix)
dev->data.nix.path,
dev->data.nix.listen ? ",server,nowait" : "");
break;
+
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ case VIR_DOMAIN_CHR_TYPE_LAST:
+ break;
}
if (virBufferError(&buf)) {
@@ -7707,6 +7721,7 @@ qemuBuildCommandLine(virConnectPtr conn,
int vnc = 0;
int spice = 0;
int usbcontroller = 0;
+ int actualSerials = 0;
bool usblegacy = false;
bool mlock = false;
int contOrder[] = {
@@ -7736,6 +7751,20 @@ qemuBuildCommandLine(virConnectPtr conn,
emulator = def->emulator;
+ for (i = 0; i < def->ngraphics; ++i) {
+ switch (def->graphics[i]->type) {
+ case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
+ ++sdl;
+ break;
+ case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+ ++vnc;
+ break;
+ case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+ ++spice;
+ break;
+ }
+ }
+
/*
* do not use boot=on for drives when not using KVM since this
* is not supported at all in upstream QEmu.
@@ -8802,35 +8831,39 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArgBuffer(cmd, &opt);
}
- if (!def->nserials) {
- /* If we have -device, then we set -nodefault already */
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))
- virCommandAddArgList(cmd, "-serial", "none", NULL);
- } else {
- for (i = 0; i < def->nserials; i++) {
- virDomainChrDefPtr serial = def->serials[i];
- char *devstr;
+ for (i = 0; i < def->nserials; i++) {
+ virDomainChrDefPtr serial = def->serials[i];
+ char *devstr;
- /* Use -chardev with -device if they are available */
- if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) {
- virCommandAddArg(cmd, "-chardev");
- if (!(devstr = qemuBuildChrChardevStr(&serial->source,
- serial->info.alias,
- qemuCaps)))
- goto error;
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
+ if (serial->source.type == VIR_DOMAIN_CHR_TYPE_SPICEPORT && !spice)
+ continue;
- if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0)
- goto error;
- } else {
- virCommandAddArg(cmd, "-serial");
- if (!(devstr = qemuBuildChrArgStr(&serial->source, NULL)))
- goto error;
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
- }
+ /* Use -chardev with -device if they are available */
+ if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) {
+ virCommandAddArg(cmd, "-chardev");
+ if (!(devstr = qemuBuildChrChardevStr(&serial->source,
+ serial->info.alias,
+ qemuCaps)))
+ goto error;
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+
+ if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0)
+ goto error;
+ } else {
+ virCommandAddArg(cmd, "-serial");
+ if (!(devstr = qemuBuildChrArgStr(&serial->source, NULL)))
+ goto error;
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
}
+ actualSerials++;
+ }
+
+ if (!actualSerials) {
+ /* If we have -device, then we set -nodefault already */
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))
+ virCommandAddArgList(cmd, "-serial", "none", NULL);
}
if (!def->nparallels) {
@@ -9017,19 +9050,6 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
- for (i = 0; i < def->ngraphics; ++i) {
- switch (def->graphics[i]->type) {
- case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
- ++sdl;
- break;
- case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
- ++vnc;
- break;
- case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
- ++spice;
- break;
- }
- }
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_0_10) && sdl + vnc + spice > 1) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("only 1 graphics device is supported"));
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ec3b958..5e825ac 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1,7 +1,7 @@
/*
* qemu_monitor_json.c: interaction with QEMU monitor console
*
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -5318,6 +5318,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
break;
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
case VIR_DOMAIN_CHR_TYPE_PIPE:
case VIR_DOMAIN_CHR_TYPE_STDIO:
case VIR_DOMAIN_CHR_TYPE_LAST:
diff --git a/tests/qemucapabilitiesdata/caps_1.5.3-1.caps b/tests/qemucapabilitiesdata/caps_1.5.3-1.caps
index 1e5bb74..adf8531 100644
--- a/tests/qemucapabilitiesdata/caps_1.5.3-1.caps
+++ b/tests/qemucapabilitiesdata/caps_1.5.3-1.caps
@@ -134,4 +134,5 @@
<flag name='boot-strict'/>
<flag name='pvpanic'/>
<flag name='reboot-timeout'/>
+ <flag name='spiceport'/>
</qemuCaps>
diff --git a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
index 61542a8..e6b2f76 100644
--- a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
+++ b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
@@ -140,4 +140,5 @@
<flag name='reboot-timeout'/>
<flag name='enable-fips'/>
<flag name='spice-file-xfer-disable'/>
+ <flag name='spiceport'/>
</qemuCaps>
diff --git a/tests/qemucapabilitiesdata/caps_1.6.50-1.caps b/tests/qemucapabilitiesdata/caps_1.6.50-1.caps
index 8ce17aa..e6b8117 100644
--- a/tests/qemucapabilitiesdata/caps_1.6.50-1.caps
+++ b/tests/qemucapabilitiesdata/caps_1.6.50-1.caps
@@ -138,4 +138,5 @@
<flag name='pvpanic'/>
<flag name='reboot-timeout'/>
<flag name='spice-file-xfer-disable'/>
+ <flag name='spiceport'/>
</qemuCaps>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args
new file mode 100644
index 0000000..1e27394
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args
@@ -0,0 +1,6 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-usb -hda /dev/HostVG/QEMUGuest1 -net none -serial \
+none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml
new file mode 100644
index 0000000..06a99a3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <title>A description of the test machine.</title>
+ <description>
+ A test of qemu's minimal configuration.
+ This test also tests the description and title elements.
+ </description>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <serial type='spiceport'>
+ <source channel='org.qemu.console.serial.0'/>
+ <target port='0'/>
+ </serial>
+ <console type='spiceport'>
+ <source channel='org.qemu.console.serial.0'/>
+ <target type='serial' port='0'/>
+ </console>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args
new file mode 100644
index 0000000..8c631b1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \
+/usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefconfig -nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi -boot c -usb \
+-hda /dev/HostVG/QEMUGuest1 \
+-chardev spiceport,id=charserial0,name=org.qemu.console.serial.0 \
+-device isa-serial,chardev=charserial0,id=serial0 \
+-device usb-tablet,id=input0 \
+-spice port=5903,tls-port=5904,addr=127.0.0.1,x509-dir=/etc/pki/libvirt-spice \
+-device \
+qxl-vga,id=video0,ram_size=67107840,vram_size=67107840,bus=pci.0,addr=0x2 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml
new file mode 100644
index 0000000..1e42ee6
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml
@@ -0,0 +1,43 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <serial type='spiceport'>
+ <source channel='org.qemu.console.serial.0'/>
+ <target port='0'/>
+ </serial>
+ <console type='spiceport'>
+ <source channel='org.qemu.console.serial.0'/>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='tablet' bus='usb'/>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <video>
+ <model type='qxl' ram='65535' vram='65535' heads='1'/>
+ </video>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index dae08d5..ec03aa2 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -947,6 +947,13 @@ mymain(void)
DO_TEST("serial-udp", NONE);
DO_TEST("serial-tcp-telnet", NONE);
DO_TEST("serial-many", NONE);
+ DO_TEST("serial-spiceport",
+ QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE,
+ QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+ QEMU_CAPS_DEVICE_QXL, QEMU_CAPS_DEVICE_QXL_VGA,
+ QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEPORT);
+ DO_TEST("serial-spiceport-nospice", QEMU_CAPS_NAME);
+
DO_TEST("parallel-tcp", NONE);
DO_TEST("console-compat", NONE);
DO_TEST("console-compat-auto", NONE);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 41d1904..c57d7af 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -239,6 +239,8 @@ mymain(void)
DO_TEST("serial-udp");
DO_TEST("serial-tcp-telnet");
DO_TEST("serial-many");
+ DO_TEST("serial-spiceport");
+ DO_TEST("serial-spiceport-nospice");
DO_TEST("parallel-tcp");
DO_TEST("console-compat");
DO_TEST("console-virtio-many");
--
1.8.5.4
10 years, 9 months
[libvirt] [PATCH v6] bhyve: add a basic driver
by Roman Bogorodskiy
Changes from v5:
- Obtain version using uname(3)
- Cleanup driver global objects in StateCleanup instead
of ConnectClose
Changes from v4:
- Set acpi and apic flags based on domain definition
- Add more detailed description about -H and -P flags
of bhyve to justify theirs usage
Roman Bogorodskiy (1):
bhyve: add a basic driver
configure.ac | 7 +
daemon/libvirtd.c | 9 +
include/libvirt/virterror.h | 1 +
m4/virt-driver-bhyve.m4 | 57 +++++
po/POTFILES.in | 3 +
src/Makefile.am | 30 +++
src/bhyve/bhyve_command.c | 290 +++++++++++++++++++++++
src/bhyve/bhyve_command.h | 41 ++++
src/bhyve/bhyve_driver.c | 566 ++++++++++++++++++++++++++++++++++++++++++++
src/bhyve/bhyve_driver.h | 28 +++
src/bhyve/bhyve_process.c | 216 +++++++++++++++++
src/bhyve/bhyve_process.h | 36 +++
src/bhyve/bhyve_utils.h | 48 ++++
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 1 +
src/driver.h | 1 +
src/libvirt.c | 3 +
src/util/virerror.c | 1 +
18 files changed, 1340 insertions(+), 1 deletion(-)
create mode 100644 m4/virt-driver-bhyve.m4
create mode 100644 src/bhyve/bhyve_command.c
create mode 100644 src/bhyve/bhyve_command.h
create mode 100644 src/bhyve/bhyve_driver.c
create mode 100644 src/bhyve/bhyve_driver.h
create mode 100644 src/bhyve/bhyve_process.c
create mode 100644 src/bhyve/bhyve_process.h
create mode 100644 src/bhyve/bhyve_utils.h
--
1.8.4.3
10 years, 9 months
[libvirt] [PATCH v2] Add helper program to create custom leases
by Nehal J Wani
Introduce helper program to catch events from dnsmasq and maintain a custom
lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
"<interface-name>.status".
Each lease contains the following info:
<expiry-time (epoch time)> <mac> <iaid> <ip-address> <hostname> <clientid>
Example of custom leases file content:
[
{
"expiry-time": "1390775837",
"mac-address": "52:54:00:93:8c:63",
"iaid": "*",
"ip-address": "192.168.150.209",
"hostname": "iit-ad885e4aa1",
"client-id": "01:52:54:00:44:7c:d7"
},
{
"expiry-time": "1390775950",
"mac-address": "52:54:00:7b:6f:ba",
"iaid": "8089530",
"ip-address": "2001:db8:ca2:2:1::6d",
"hostname": "*",
"client-id": "00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec"
}
]
src/Makefile.am:
* Add options to compile the helper program
src/network/bridge_driver.c:
* Introduce networkDnsmasqLeaseFileNameCustom()
* Invoke helper program along with dnsmasq
* Delete the .status file when corresponding n/w is destroyed.
src/util/leaseshelper.c
* Helper program to create the custom lease file
---
v2:
* Changed format to JSON
v1:
* Refer: https://www.redhat.com/archives/libvir-list/2014-January/msg00626.html
src/Makefile.am | 20 ++++
src/network/bridge_driver.c | 19 ++++
src/util/leaseshelper.c | 271 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 310 insertions(+)
create mode 100644 src/util/leaseshelper.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7844efa..1fa6263 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -840,6 +840,9 @@ STORAGE_HELPER_DISK_SOURCES = \
UTIL_IO_HELPER_SOURCES = \
util/iohelper.c
+UTIL_LEASES_HELPER_SOURCES = \
+ util/leaseshelper.c
+
# Network filters
NWFILTER_DRIVER_SOURCES = \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
@@ -2410,6 +2413,23 @@ libvirt_iohelper_CFLAGS = \
$(NULL)
endif WITH_LIBVIRTD
+if WITH_LIBVIRTD
+libexec_PROGRAMS += libvirt_leaseshelper
+libvirt_leaseshelper_SOURCES = $(UTIL_LEASES_HELPER_SOURCES)
+libvirt_leaseshelper_LDFLAGS = \
+ $(NULL)
+libvirt_leaseshelper_LDADD = \
+ libvirt_util.la \
+ ../gnulib/lib/libgnu.la
+if WITH_DTRACE_PROBES
+libvirt_leaseshelper_LDADD += libvirt_probes.lo
+endif WITH_DTRACE_PROBES
+
+libvirt_leaseshelper_CFLAGS = \
+ $(PIE_CFLAGS) \
+ $(NULL)
+endif WITH_LIBVIRTD
+
if WITH_STORAGE_DISK
if WITH_LIBVIRTD
libexec_PROGRAMS += libvirt_parthelper
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0b43a67..5440aef 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -148,6 +148,16 @@ networkDnsmasqLeaseFileNameFunc networkDnsmasqLeaseFileName =
networkDnsmasqLeaseFileNameDefault;
static char *
+networkDnsmasqLeaseFileNameCustom(const char *bridge)
+{
+ char *leasefile;
+
+ ignore_value(virAsprintf(&leasefile, "%s/%s.status",
+ driverState->dnsmasqStateDir, bridge));
+ return leasefile;
+}
+
+static char *
networkDnsmasqConfigFileName(const char *netname)
{
char *conffile;
@@ -183,6 +193,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
virNetworkObjPtr net)
{
char *leasefile = NULL;
+ char *customleasefile = NULL;
char *radvdconfigfile = NULL;
char *configfile = NULL;
char *radvdpidbase = NULL;
@@ -201,6 +212,9 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
if (!(leasefile = networkDnsmasqLeaseFileName(def->name)))
goto cleanup;
+ if (!(customleasefile = networkDnsmasqLeaseFileNameCustom(def->bridge)))
+ goto cleanup;
+
if (!(radvdconfigfile = networkRadvdConfigFileName(def->name)))
goto cleanup;
@@ -217,6 +231,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
/* dnsmasq */
dnsmasqDelete(dctx);
unlink(leasefile);
+ unlink(customleasefile);
unlink(configfile);
/* radvd */
@@ -1063,6 +1078,10 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps));
virCommandAddArgFormat(cmd, "--conf-file=%s", configfile);
+
+ /* This helper is used to create cutom leases file for libvirt */
+ virCommandAddArgFormat(cmd, "--dhcp-script=%s", LIBEXECDIR "/libvirt_leaseshelper");
+
*cmdout = cmd;
ret = 0;
cleanup:
diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
new file mode 100644
index 0000000..a9aaf3f
--- /dev/null
+++ b/src/util/leaseshelper.c
@@ -0,0 +1,271 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Nehal J Wani <nehaljw.kkd1(a)gmail.com>
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "virutil.h"
+#include "virthread.h"
+#include "virfile.h"
+#include "virbuffer.h"
+#include "virstring.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virjson.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define EMPTY_STR(s) ((s) ? (s) : "*")
+
+int
+main(int argc, char **argv) {
+
+ /* Doesn't hurt to check */
+ if (argc < 4) {
+ /* Refer man page of dnsmasq --dhcp-script for more details */
+ fprintf(stderr, "Usage: $program $action ${mac|clientid} $ip\n");
+ return -1;
+ }
+
+ char *lease_file = NULL;
+ char *lease_entries = NULL;
+ const char *ip = argv[3];
+ const char *mac = argv[2];
+ const char *action = argv[1];
+ const char *program_name = argv[0];
+ const char *iaid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_IAID"));
+ const char *clientid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_CLIENT_ID"));
+ const char *interface = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_INTERFACE"));
+ const char *exptime = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_LEASE_EXPIRES"));
+ const char *hostname = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_SUPPLIED_HOSTNAME"));
+ const char *leases_str = NULL;
+ size_t i = 0;
+ int rv = -1;
+ int size = 0;
+ int lease_file_len = 0;
+ FILE *fp = NULL;
+ bool add = false;
+ bool delete = false;
+ virJSONValuePtr lease_new;
+ virJSONValuePtr lease_tmp;
+ virJSONValuePtr leases_array;
+ virJSONValuePtr lease_new_tmp;
+ virJSONValuePtr leases_array_new;
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+ textdomain(PACKAGE) == NULL) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ if (virThreadInitialize() < 0 ||
+ virErrorInitialize() < 0) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ if (virAsprintf(&lease_file, "%s/%s.status", LOCALSTATEDIR
+ "/lib/libvirt/dnsmasq/", interface) < 0)
+ goto cleanup;
+
+ if (virGetEnvAllowSUID("DNSMASQ_IAID")) {
+ mac = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_MAC"));
+ clientid = argv[2];
+ }
+
+ /* Make sure dnsmasq knows the interface, otherwise something is wrong */
+ if (STREQ(interface, "*"))
+ goto cleanup;
+
+ /* Make sure the file exists. If not, 'touch' it */
+ if (virFileTouch(lease_file, 0644) < 0)
+ goto cleanup;
+
+ /* Read entire contents */
+ if ((lease_file_len = virFileReadAll(lease_file,
+ VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+ &lease_entries)) < 0) {
+ goto cleanup;
+ }
+
+ if (STREQ(action, "add") || STREQ(action, "old") || STREQ(action, "del")) {
+ if (mac || STREQ(action, "del")) {
+ /* Delete the corresponding lease */
+ delete = true;
+ if (STREQ(action, "add") || STREQ(action, "old")) {
+ add = true;
+ /* Enter new lease */
+ if (!(lease_new = virJSONValueNewObject())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ if (virJSONValueObjectAppendString(lease_new, "expiry-time",
+ exptime) < 0 ||
+ virJSONValueObjectAppendString(lease_new, "mac-address",
+ mac) < 0 ||
+ virJSONValueObjectAppendString(lease_new, "iaid",
+ iaid) < 0 ||
+ virJSONValueObjectAppendString(lease_new, "ip-address",
+ ip) < 0 ||
+ virJSONValueObjectAppendString(lease_new, "hostname",
+ hostname) < 0 ||
+ virJSONValueObjectAppendString(lease_new, "client-id",
+ clientid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ /* Check for previous leases */
+ if (lease_file_len) {
+ if (!(leases_array = virJSONValueFromString(lease_entries))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid json in file: %s"), lease_file);
+ goto cleanup;
+ }
+
+ if ((size = virJSONValueArraySize(leases_array)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("couldn't fetch array of leases"));
+ goto cleanup;
+ }
+ }
+
+ if (!(leases_array_new = virJSONValueNewArray())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < size; i++) {
+ const char *ip_tmp = NULL;
+ const char *mac_tmp = NULL;
+ const char *iaid_tmp = NULL;
+ const char *exptime_tmp = NULL;
+ const char *clientid_tmp = NULL;
+ const char *hostname_tmp = NULL;
+ long long expirytime_tmp = 0;
+
+ if (!(lease_tmp = virJSONValueArrayGet(leases_array, i))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse json"));
+ goto cleanup;
+ }
+
+ if (!(iaid_tmp = virJSONValueObjectGetString(lease_tmp, "iaid")) ||
+ !(ip_tmp = virJSONValueObjectGetString(lease_tmp, "ip-address")) ||
+ !(mac_tmp = virJSONValueObjectGetString(lease_tmp, "mac-address")) ||
+ !(hostname_tmp = virJSONValueObjectGetString(lease_tmp, "hostname")) ||
+ !(clientid_tmp = virJSONValueObjectGetString(lease_tmp, "client-id")) ||
+ !(exptime_tmp = virJSONValueObjectGetString(lease_tmp, "expiry-time"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse json"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ll(exptime_tmp, NULL, 10, &expirytime_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to convert lease expiry time to integer: %s"),
+ exptime_tmp);
+ goto cleanup;
+ }
+
+ /* Check whether lease has expired or not */
+ if (expirytime_tmp < (long long) time(NULL))
+ continue;
+ else if (delete && STREQ(ip_tmp, ip))
+ continue;
+ else {
+ if (!(lease_new_tmp = virJSONValueNewObject())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ if (virJSONValueObjectAppendString(lease_new_tmp, "expiry-time",
+ exptime_tmp) < 0 ||
+ virJSONValueObjectAppendString(lease_new_tmp, "mac-address",
+ mac_tmp) < 0 ||
+ virJSONValueObjectAppendString(lease_new_tmp, "iaid",
+ iaid_tmp) < 0 ||
+ virJSONValueObjectAppendString(lease_new_tmp, "ip-address",
+ ip_tmp) < 0 ||
+ virJSONValueObjectAppendString(lease_new_tmp, "hostname",
+ hostname_tmp) < 0 ||
+ virJSONValueObjectAppendString(lease_new_tmp, "client-id",
+ clientid_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ if (virJSONValueArrayAppend(leases_array_new, lease_new_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ }
+ }
+
+ if (add) {
+ if (virJSONValueArrayAppend(leases_array_new, lease_new) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ }
+
+ rv = 0;
+
+ /* Write to file */
+ leases_str = virJSONValueToString(leases_array_new, true);
+ if (!leases_str)
+ leases_str = "";
+
+ if (virFileWriteStr(lease_file, leases_str, 0) < 0)
+ rv = -1;
+
+cleanup:
+ VIR_FREE(lease_file);
+ virJSONValueFree(lease_new);
+ virJSONValueFree(leases_array);
+ virJSONValueFree(lease_new_tmp);
+ virJSONValueFree(leases_array_new);
+ return rv;
+}
--
1.8.1.4
10 years, 9 months