[libvirt] [PATCH] Bind connection close callback APIs to python binding
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Add code in the python binding to cope with the new APIs
virConnectRegisterCloseCallback and
virConnectDeregisterCloseCallback. Also demonstrate their
use in the python domain events demo
---
examples/domain-events/events-python/event-test.py | 14 ++-
python/generator.py | 5 +-
python/libvirt-override-virConnect.py | 24 +++++
python/libvirt-override.c | 107 ++++++++++++++++++++
4 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py
index 736c225..8193d18 100644
--- a/examples/domain-events/events-python/event-test.py
+++ b/examples/domain-events/events-python/event-test.py
@@ -490,6 +490,16 @@ def myDomainEventPMSuspendCallback(conn, dom, reason, opaque):
dom.name(), dom.ID())
def myDomainEventBalloonChangeCallback(conn, dom, utcoffset, actual):
print "myDomainEventBalloonChangeCallback: Domain %s(%s) %d" % (dom.name(), dom.ID(), actual)
+
+run = True
+
+def myConnectionCloseCallback(conn, reason, opaque):
+ reasonStrings = (
+ "Error", "End-of-file", "Keepalive", "Client",
+ )
+ print "myConnectionCloseCallback: %s: %s" % (conn.getURI(), reasonStrings[reason])
+ run = False
+
def usage(out=sys.stderr):
print >>out, "usage: "+os.path.basename(sys.argv[0])+" [-hdl] [uri]"
print >>out, " uri will default to qemu:///system"
@@ -539,6 +549,8 @@ def main():
if (old_exitfunc): old_exitfunc()
sys.exitfunc = exit
+ vc.registerCloseCallback(myConnectionCloseCallback, None)
+
#Add 2 callbacks to prove this works with more than just one
vc.domainEventRegister(myDomainEventCallback1,None)
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback2, None)
@@ -559,7 +571,7 @@ def main():
# of demo we'll just go to sleep. The other option is to
# run the event loop in your main thread if your app is
# totally event based.
- while vc.isAlive() == 1:
+ while run:
time.sleep(1)
diff --git a/python/generator.py b/python/generator.py
index 6559ece..6ccbf56 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -425,8 +425,6 @@ skip_impl = (
'virDomainGetInterfaceParameters',
'virDomainGetCPUStats',
'virDomainGetDiskErrors',
- 'virConnectUnregisterCloseCallback',
- 'virConnectRegisterCloseCallback',
)
qemu_skip_impl = (
@@ -464,6 +462,9 @@ skip_function = (
'virStreamRecv', # overridden in libvirt-override-virStream.py
'virStreamSend', # overridden in libvirt-override-virStream.py
+ 'virConnectDeregisterCloseCallback', # overriden in virConnect.py
+ 'virConnectRegisterCloseCallback', # overriden in virConnect.py
+
# 'Ref' functions have no use for bindings users.
"virConnectRef",
"virDomainRef",
diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py
index 50177ab..de8167e 100644
--- a/python/libvirt-override-virConnect.py
+++ b/python/libvirt-override-virConnect.py
@@ -206,3 +206,27 @@
retlist.append(virDomain(self, _obj=domptr))
return retlist
+
+ def _dispatchCloseCallback(self, reason, cbData):
+ """Dispatches events to python user close callback"""
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(self, reason, opaque)
+ return 0
+
+
+ def deregisterCloseCallback(self):
+ """Removes a close event callback"""
+ ret = libvirtmod.virConnectDeregisterCloseCallback(self._o)
+ if ret == -1: raise libvirtError ('virConnectDeregisterCloseCallback() failed', conn=self)
+
+ def registerCloseCallback(self, cb, opaque):
+ """Adds a close event callback, providing a notification
+ when a connection fails / closes"""
+ cbData = { "cb": cb, "conn": self, "opaque": opaque }
+ ret = libvirtmod.virConnectRegisterCloseCallback(self._o, cbData)
+ if ret == -1:
+ raise libvirtError ('virConnectRegisterCloseCallback() failed', conn=self)
+ return ret
+
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 8b41dff..b7269fc 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -5521,6 +5521,111 @@ libvirt_virConnectDomainEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self,
return py_retval;
}
+
+static void
+libvirt_virConnectCloseCallbackDispatch(virConnectPtr conn ATTRIBUTE_UNUSED,
+ int reason,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ Py_INCREF(pyobj_cbData);
+
+ dictKey = libvirt_constcharPtrWrap("conn");
+ pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+ Py_DECREF(dictKey);
+
+ /* Call the Callback Dispatcher */
+ pyobj_ret = PyObject_CallMethod(pyobj_conn,
+ (char*)"_dispatchCloseCallback",
+ (char*)"iO",
+ reason,
+ pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+
+ if(!pyobj_ret) {
+ DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ }
+
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+static PyObject *
+libvirt_virConnectRegisterCloseCallback(ATTRIBUTE_UNUSED PyObject * self,
+ PyObject * args)
+{
+ PyObject *py_retval; /* return value */
+ PyObject *pyobj_conn; /* virConnectPtr */
+ PyObject *pyobj_cbData; /* hash of callback data */
+ virConnectPtr conn;
+ int ret = 0;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "OO:virConnectRegisterCloseCallback",
+ &pyobj_conn, &pyobj_cbData)) {
+ DEBUG("%s failed parsing tuple\n", __FUNCTION__);
+ return VIR_PY_INT_FAIL;
+ }
+
+ DEBUG("libvirt_virConnectRegisterCloseCallback(%p %p) called\n",
+ pyobj_conn, pyobj_cbData);
+ conn = PyvirConnect_Get(pyobj_conn);
+
+ Py_INCREF(pyobj_cbData);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ret = virConnectRegisterCloseCallback(conn,
+ libvirt_virConnectCloseCallbackDispatch,
+ pyobj_cbData,
+ libvirt_virConnectDomainEventFreeFunc);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (ret < 0) {
+ Py_DECREF(pyobj_cbData);
+ }
+
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+
+static PyObject *
+libvirt_virConnectDeregisterCloseCallback(ATTRIBUTE_UNUSED PyObject * self,
+ PyObject * args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ virConnectPtr conn;
+ int ret = 0;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "O:virConnectDomainEventDeregister",
+ &pyobj_conn))
+ return NULL;
+
+ DEBUG("libvirt_virConnectDomainEventDeregister(%p) called\n",
+ pyobj_conn);
+
+ conn = PyvirConnect_Get(pyobj_conn);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+
+ ret = virConnectDeregisterCloseCallback(conn,
+ libvirt_virConnectCloseCallbackDispatch);
+
+ LIBVIRT_END_ALLOW_THREADS;
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+
static void
libvirt_virStreamEventFreeFunc(void *opaque)
{
@@ -5822,10 +5927,12 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virConnectListDomainsID", libvirt_virConnectListDomainsID, METH_VARARGS, NULL},
{(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL},
{(char *) "virConnectListAllDomains", libvirt_virConnectListAllDomains, METH_VARARGS, NULL},
+ {(char *) "virConnectDeregisterCloseCallback", libvirt_virConnectDeregisterCloseCallback, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL},
{(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL},
+ {(char *) "virConnectRegisterCloseCallback", libvirt_virConnectRegisterCloseCallback, METH_VARARGS, NULL},
{(char *) "virStreamEventAddCallback", libvirt_virStreamEventAddCallback, METH_VARARGS, NULL},
{(char *) "virStreamRecv", libvirt_virStreamRecv, METH_VARARGS, NULL},
{(char *) "virStreamSend", libvirt_virStreamSend, METH_VARARGS, NULL},
--
1.7.10.4
12 years, 8 months
[libvirt] [PATCH] s/Un/De in virConnectUnregisterCloseCallback
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Previous APIs have used the word 'Deregister' rather than
'Unregister', so rename the recently added API to match.
---
include/libvirt/libvirt.h.in | 2 +-
src/libvirt.c | 8 ++++----
src/libvirt_public.syms | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index d21d029..7fed091 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1197,7 +1197,7 @@ int virConnectRegisterCloseCallback(virConnectPtr conn,
virConnectCloseFunc cb,
void *opaque,
virFreeCallback freecb);
-int virConnectUnregisterCloseCallback(virConnectPtr conn,
+int virConnectDeregisterCloseCallback(virConnectPtr conn,
virConnectCloseFunc cb);
/*
diff --git a/src/libvirt.c b/src/libvirt.c
index 8e789be..a97976c 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -13945,7 +13945,7 @@ error:
* funtion.
*
* Use of this method is no longer recommended. Instead applications
- * should try virConnectDomainEventUnregisterAny which has a more flexible
+ * should try virConnectDomainEventDeregisterAny which has a more flexible
* API contract
*
* Returns 0 on success, -1 on failure
@@ -16541,7 +16541,7 @@ error:
*
* The return value from this method is a positive integer identifier
* for the callback. To unregister a callback, this callback ID should
- * be passed to the virDomainEventUnregisterAny method
+ * be passed to the virDomainEventDeregisterAny method
*
* Returns a callback identifier on success, -1 on failure
*/
@@ -18687,7 +18687,7 @@ error:
}
/**
- * virConnectUnregisterCloseCallback:
+ * virConnectDeregisterCloseCallback:
* @conn: pointer to connection object
* @cb: pointer to the current registered callback
*
@@ -18699,7 +18699,7 @@ error:
*
* Returns 0 on success, -1 on error
*/
-int virConnectUnregisterCloseCallback(virConnectPtr conn,
+int virConnectDeregisterCloseCallback(virConnectPtr conn,
virConnectCloseFunc cb)
{
VIR_DEBUG("conn=%p", conn);
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 5004182..d465a57 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -548,7 +548,7 @@ LIBVIRT_0.9.14 {
global:
virDomainGetHostname;
virConnectRegisterCloseCallback;
- virConnectUnregisterCloseCallback;
+ virConnectDeregisterCloseCallback;
} LIBVIRT_0.9.13;
# .... define new API here using predicted next version number ....
--
1.7.10.4
12 years, 8 months
[libvirt] [PATCH] Add support for disabling S3 and S4 states
by Martin Kletzander
There a two new elements in <features> implemented, which control what
ACPI sleeping states will be advertised. The default is to have both
states enabled, so this means no change for current machines.
---
docs/schemas/domaincommon.rng | 10 ++++++
src/conf/domain_conf.c | 4 ++-
src/conf/domain_conf.h | 2 +
src/qemu/qemu_command.c | 17 +++++++++++
src/qemu/qemu_driver.c | 15 ++++++++++
tests/qemuargv2xmltest.c | 3 ++
.../qemuxml2argv-misc-disable-s3.args | 4 ++
.../qemuxml2argv-misc-disable-s3.xml | 29 +++++++++++++++++++
.../qemuxml2argv-misc-disable-s4.args | 4 ++
.../qemuxml2argv-misc-disable-s4.xml | 29 +++++++++++++++++++
.../qemuxml2argv-misc-disable-suspends.args | 4 ++
.../qemuxml2argv-misc-disable-suspends.xml | 30 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 3 ++
tests/qemuxml2xmltest.c | 3 ++
14 files changed, 156 insertions(+), 1 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.xml
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index b7562ad..859cb26 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2788,6 +2788,16 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="disable_s3">
+ <empty/>
+ </element>
+ </optional>
+ <optional>
+ <element name="disable_s4">
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 143d92e..1bfb8d0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -107,7 +107,9 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"pae",
"hap",
"viridian",
- "privnet")
+ "privnet",
+ "disable_s3",
+ "disable_s4")
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
"destroy",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bc02caf..b7ee95e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1346,6 +1346,8 @@ enum virDomainFeature {
VIR_DOMAIN_FEATURE_HAP,
VIR_DOMAIN_FEATURE_VIRIDIAN,
VIR_DOMAIN_FEATURE_PRIVNET,
+ VIR_DOMAIN_FEATURE_DISABLE_S3,
+ VIR_DOMAIN_FEATURE_DISABLE_S4,
VIR_DOMAIN_FEATURE_LAST
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4033644..ee9e169 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4691,6 +4691,12 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, "-no-acpi");
}
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_DISABLE_S3))
+ virCommandAddArgList(cmd, "-global", "PIIX4_PM.disable_s3=1", NULL);
+
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_DISABLE_S4))
+ virCommandAddArgList(cmd, "-global", "PIIX4_PM.disable_s4=1", NULL);
+
if (!def->os.bootloader) {
/*
* We prefer using explicit bootindex=N parameters for predictable
@@ -8191,6 +8197,17 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
*monConfig = chr;
}
+ } else if (STREQ(arg, "-global") &&
+ STREQ(progargv[i + 1], "PIIX4_PM.disable_s3=1")) {
+ /* We want to parse only the known "-global" parameters,
+ * so the ones that we don't know are still added to the
+ * namespace */
+ i++;
+ def->features |= (1 << VIR_DOMAIN_FEATURE_DISABLE_S3);
+ } else if (STREQ(arg, "-global") &&
+ STREQ(progargv[i + 1], "PIIX4_PM.disable_s4=1")) {
+ i++;
+ def->features |= (1 << VIR_DOMAIN_FEATURE_DISABLE_S4);
} else if (STREQ(arg, "-S")) {
/* ignore, always added by libvirt */
} else {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0da5c5a..76dd374 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13060,6 +13060,21 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
goto cleanup;
}
+ if (vm->def->features & (1 << VIR_DOMAIN_FEATURE_DISABLE_S3) &&
+ (target == VIR_NODE_SUSPEND_TARGET_MEM ||
+ target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S3 signals are disabled for this domain"));
+ goto cleanup;
+ }
+
+ if (vm->def->features & (1 << VIR_DOMAIN_FEATURE_DISABLE_S4) &&
+ target == VIR_NODE_SUSPEND_TARGET_DISK) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S4 signals are disabled for this domain"));
+ goto cleanup;
+ }
+
if (priv->agentError) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("QEMU guest agent is not available due to an error"));
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 439218e..7fae39a 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -205,6 +205,9 @@ mymain(void)
/* Can't rountrip xenner arch */
/*DO_TEST("input-xen");*/
DO_TEST("misc-acpi");
+ DO_TEST("misc-disable-s3");
+ DO_TEST("misc-disable-s4");
+ DO_TEST("misc-disable-suspends");
DO_TEST("misc-no-reboot");
DO_TEST("misc-uuid");
DO_TEST("net-user");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.args b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.args
new file mode 100644
index 0000000..dbee64d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
+-M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi -global PIIX4_PM.disable_s3=1 -boot c -hda /dev/HostVG/QEMUGuest1 \
+-net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.xml b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.xml
new file mode 100644
index 0000000..4b2d13e
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s3.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>8caaa98c-e7bf-5845-126a-1fc316bd1089</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <disable_s3/>
+ </features>
+ <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'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.args b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.args
new file mode 100644
index 0000000..9177904
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
+-M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi -global PIIX4_PM.disable_s4=1 -boot c -hda /dev/HostVG/QEMUGuest1 \
+-net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.xml b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.xml
new file mode 100644
index 0000000..1a27e9f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-s4.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>8caaa98c-e7bf-5845-126a-1fc316bd1089</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <disable_s4/>
+ </features>
+ <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'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.args b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.args
new file mode 100644
index 0000000..6f63d8b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
+-M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot c \
+-hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.xml b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.xml
new file mode 100644
index 0000000..587e80a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-misc-disable-suspends.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>8caaa98c-e7bf-5845-126a-1fc316bd1089</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <disable_s3/>
+ <disable_s4/>
+ </features>
+ <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'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c4aa7c4..c7a3d50 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -561,6 +561,9 @@ mymain(void)
DO_TEST("input-usbtablet", NONE);
DO_TEST_ERROR("input-xen", QEMU_CAPS_DOMID);
DO_TEST("misc-acpi", NONE);
+ DO_TEST("misc-disable-s3", NONE);
+ DO_TEST("misc-disable-s4", NONE);
+ DO_TEST("misc-disable-suspends", NONE);
DO_TEST("misc-no-reboot", NONE);
DO_TEST("misc-uuid", QEMU_CAPS_NAME, QEMU_CAPS_UUID);
DO_TEST("net-user", NONE);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index dcdba4f..f7622b7 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -170,6 +170,9 @@ mymain(void)
DO_TEST("input-usbtablet");
DO_TEST("input-xen");
DO_TEST("misc-acpi");
+ DO_TEST("misc-disable-s3");
+ DO_TEST("misc-disable-s4");
+ DO_TEST("misc-disable-suspends");
DO_TEST("misc-no-reboot");
DO_TEST("net-user");
DO_TEST("net-virtio");
--
1.7.8.6
12 years, 8 months
[libvirt] [PATCH 0/2] Fix segfault when destroying domain with console open
by Peter Krempa
In some cases when a newly created domain was destroyed the daemon crashed as
it freed the console access data structure sooner than the stream could be
freed so that the stream actually called the closing callback taht referenced
freed data.
Peter Krempa (2):
conf: Remove dead code from virConsoleOpen()
conf: Remove callback from stream when freeing entries in console
hash
src/conf/virconsole.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
--
1.7.8.6
12 years, 8 months
[libvirt] [PATCH] python: Don't generate bodies for close callback functions
by Peter Krempa
Commit 6ed5a1b9bd6240b8f2736790e48dd1c284c2e0e1 adds close callback
functions to the public API but doesn't add python implementation. This
patch sets the function to be written manually (to fix the build), but
doesn't implement them yet.
---
Pushing under build-breaker rule.
---
python/generator.py | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/python/generator.py b/python/generator.py
index 2dada6e..6559ece 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -425,6 +425,8 @@ skip_impl = (
'virDomainGetInterfaceParameters',
'virDomainGetCPUStats',
'virDomainGetDiskErrors',
+ 'virConnectUnregisterCloseCallback',
+ 'virConnectRegisterCloseCallback',
)
qemu_skip_impl = (
--
1.7.8.6
12 years, 8 months
[libvirt] [PATCH][TCK] Add test for memory set and get
by Kyla Zhang
Add test for memory/maxmem set and get
---
scripts/domain/310-memory-set-get.t | 98 +++++++++++++++++++++++++++++++++++
1 files changed, 98 insertions(+), 0 deletions(-)
create mode 100644 scripts/domain/310-memory-set-get.t
diff --git a/scripts/domain/310-memory-set-get.t b/scripts/domain/310-memory-set-get.t
new file mode 100644
index 0000000..b4dde65
--- /dev/null
+++ b/scripts/domain/310-memory-set-get.t
@@ -0,0 +1,98 @@
+# -*- perl -*-
+#
+# Copyright (C) 2012-2013 Red Hat, Inc.
+# Copyright (C) 2012-2013 Kyla Zhang <weizhan(a)redhat.com>
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+domain/310-memory-set-get.t: test set and get memory/max memory
+
+=head1 DESCRIPTION
+
+The test case validates that the set memory, set max memory and get
+max memory works well for domain.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 15;
+
+use Sys::Virt::TCK;
+use Sys::Virt::TCK::NetworkHelpers;
+use Test::Exception;
+use File::Spec::Functions qw(catfile catdir rootdir);
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+diag "Define a new real domain, default memory is 524288";
+my $dom_name ="tck310memtest";
+
+my $dom = prepare_test_disk_and_vm($tck, $conn, $dom_name);
+
+diag "Set max memory for domain";
+lives_ok(sub { $dom->set_max_memory("1048576") }, "Set max memory succeed");
+
+diag "Get max memory for domain when domain is inactive";
+is($dom->get_max_memory(), 1048576, "Get max memory is same as set value 1048576");
+
+diag "Start inactive domain";
+$dom->create;
+ok($dom->get_id() > 0, "running domain has an ID > 0");
+sleep(30);
+
+diag "Set memory for current state";
+lives_ok(sub { $dom->set_memory("624288", Sys::Virt::Domain::MEM_CONFIG) }, "Set memory succeed in persistent config");
+
+diag "get memory of running domain";
+is($dom->get_info()->{memory}, 524288, "Get current memory is 524288");
+
+diag "Get max memory for domain when domain is active";
+is($dom->get_max_memory(), 1048576, "Get max memory is same as set value 1048576");
+
+diag "Set memory for current state";
+lives_ok(sub { $dom->set_memory("724288", Sys::Virt::Domain::MEM_CURRENT) }, "Set memory succeed in current state");
+sleep(3);
+
+diag "Check memory of running domain";
+is($dom->get_info()->{memory}, 724288, "Get current memory is same as set value 724288");
+
+diag "Set memory for live state";
+lives_ok(sub { $dom->set_memory("824288", Sys::Virt::Domain::MEM_LIVE) }, "Set memory succeed in live state");
+sleep(3);
+
+diag "Check memory of running domain";
+is($dom->get_info()->{memory}, 824288, "Get current memory is same as set value 824288");
+
+diag "Try setting max memory when domain is running";
+ok_error(sub { $dom->set_max_memory("1048576") }, "not allowed to set max memory when domain is running");
+
+diag "Destroying the transient domain";
+$dom->destroy;
+
+diag "Check memory of shutdown domain";
+is($dom->get_info()->{memory}, 624288, "Get memory is 624288 when domain is shutdown");
+
+diag "Set max memory with set_memory";
+lives_ok(sub { $dom->set_memory("1148576", Sys::Virt::Domain::MEM_MAXIMUM) }, "Set max memory succeed with set_memory");
+
+diag "Get max memory for domain";
+is($dom->get_info()->{maxMem}, 1148576, "Get max memory is same as set value 1148576");
+
+diag "Try setting live state memory when domain is shutdown";
+ok_error(sub { $dom->set_memory("824288", Sys::Virt::Domain::MEM_LIVE) }, "not allowed to set live state memory when domain is shutdown");
--
1.7.1
12 years, 8 months
[libvirt] [glib PATCH V4] Add bindings for virDomainRestore*()
by Jovanka Gulicoska
---
libvirt-gobject/libvirt-gobject-connection.c | 164 ++++++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-connection.h | 20 ++++
libvirt-gobject/libvirt-gobject.sym | 3 +
3 files changed, 187 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index 3a99034..b4a7af4 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -1605,3 +1605,167 @@ gvir_connection_get_capabilities_finish(GVirConnection *conn,
return g_object_ref(caps);
}
+
+/**
+ * gvir_connection_restore_domain_from_file:
+ * @conn: a #GVirConnection
+ * @filename: path to input file
+ * @custom_conf: (allow-none): configuration for domain or NULL
+ * @flags: the flags
+ *
+ * Returns: TRUE on success, FALSE otherwise
+ *
+ * Restores the domain saved with #gvir_domain_save_to_file
+ */
+gboolean gvir_connection_restore_domain_from_file(GVirConnection *conn,
+ gchar *filename,
+ GVirConfigDomain *custom_conf,
+ guint flags,
+ GError **err)
+{
+ GVirConnectionPrivate *priv;
+ int ret;
+
+ g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
+ g_return_val_if_fail((filename != NULL), FALSE);
+ g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
+
+ priv = conn->priv;
+
+ if (flags || (custom_conf != NULL)) {
+ gchar *custom_xml = NULL;
+
+ if (custom_conf != NULL)
+ custom_xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(custom_conf));
+
+ ret = virDomainRestoreFlags(priv->conn, filename, custom_xml, flags);
+ g_free (custom_xml);
+ }
+ else {
+ ret = virDomainRestore(priv->conn, filename);
+ }
+
+ if (ret < 0) {
+ gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
+ 0,
+ "Unable to restore domain");
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+typedef struct {
+ gchar *filename;
+ GVirConfigDomain *custom_conf;
+ guint flags;
+} DomainRestoreFromFileData;
+
+static void restore_domain_from_file_data_free(DomainRestoreFromFileData *data)
+{
+ g_free(data->filename);
+ if (custom_conf != NULL)
+ g_object_unref(data->custom_conf);
+ g_slice_free(DomainRestoreFromFileData, data);
+}
+
+
+static void
+gvir_connection_restore_domain_from_file_helper
+ (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable G_GNUC_UNUSED)
+{
+ GVirConnection *conn = GVIR_CONNECTION(object);
+ DomainRestoreFromFileData *data;
+ GError *err = NULL;
+
+ data = g_simple_async_result_get_op_res_gpointer(res);
+
+ if (!gvir_connection_restore_domain_from_file(conn, data->filename,
+ data->custom_conf,
+ data->flags, &err))
+ g_simple_async_result_take_error(res, err);
+}
+
+/**
+ * gvir_connection_restore_domain_from_file_async:
+ * @conn: a #GVirConnection
+ * @filename: path to input file
+ * @custom_conf: (allow-none): configuration for domain
+ * @flags: the flags
+ * @cancellable: (allow-none) (transfer none):cancallation object
+ * @callback: (scope async): completion callback
+ * @user_data: (closure): opaque data for callback
+ *
+ * Asynchronous variant of #gvir_connection_restore_domain_from_file
+ */
+void
+gvir_connection_restore_domain_from_file_async(GVirConnection *conn,
+ gchar *filename,
+ GVirConfigDomain *custom_conf,
+ guint flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ DomainRestoreFromFileData *data;
+
+ g_return_if_fail(GVIR_IS_CONNECTION(conn));
+ g_return_if_fail(filename != NULL);
+ g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
+
+ data = g_slice_new0(DomainRestoreFromFileData);
+ data->filename = g_strdup(filename);
+ if (custom_conf != NULL)
+ data->custom_conf = g_object_ref(custom_conf);
+ data->flags = flags;
+
+ res = g_simple_async_result_new
+ (G_OBJECT(conn),
+ callback,
+ user_data,
+ gvir_connection_restore_domain_from_file_async);
+ g_simple_async_result_set_op_res_gpointer
+ (res,
+ data,
+ (GDestroyNotify)restore_domain_from_file_data_free);
+
+ g_simple_async_result_run_in_thread
+ (res,
+ gvir_connection_restore_domain_from_file_helper,
+ G_PRIORITY_DEFAULT,
+ cancellable);
+
+ g_object_unref(res);
+}
+
+/**
+ * gvir_connection_restore_domain_from_file_finish:
+ * @conn: a #GVirConnection
+ * @result: (transfer none): async method result
+ * @err: Place-holder for possible errors
+ *
+ * Finishes the operation started by #gvir_restore_domain_from_file_async.
+ *
+ * Returns: TRUE if domain was restored successfully, FALSE otherwise.
+ */
+gboolean
+gvir_connection_restore_domain_from_file_finish(GVirConnection *conn,
+ GAsyncResult *result,
+ GError **err)
+{
+ g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
+ g_return_val_if_fail(g_simple_async_result_is_valid
+ (result, G_OBJECT(conn),
+ gvir_connection_restore_domain_from_file_async),
+ FALSE);
+
+ if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result),
+ err))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h
index c80eecf..d658b01 100644
--- a/libvirt-gobject/libvirt-gobject-connection.h
+++ b/libvirt-gobject/libvirt-gobject-connection.h
@@ -202,6 +202,26 @@ gvir_connection_get_capabilities_finish(GVirConnection *conn,
GAsyncResult *result,
GError **err);
+gboolean
+gvir_connection_restore_domain_from_file(GVirConnection *conn,
+ gchar *filename,
+ GVirConfigDomain *custom_conf,
+ guint flags,
+ GError **err);
+
+void
+gvir_connection_restore_domain_from_file_async(GVirConnection *conn,
+ gchar *filename,
+ GVirConfigDomain *custom_conf,
+ guint flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean
+gvir_connection_restore_domain_from_file_finish(GVirConnection *conn,
+ GAsyncResult *result,
+ GError **err);
G_END_DECLS
#endif /* __LIBVIRT_GOBJECT_CONNECTION_H__ */
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index 54a093a..42c90ef 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -31,6 +31,9 @@ LIBVIRT_GOBJECT_0.0.8 {
gvir_connection_create_storage_pool;
gvir_connection_start_domain;
gvir_connection_get_node_info;
+ gvir_connection_restore_domain_from_file;
+ gvir_connection_restore_domain_from_file_async;
+ gvir_connection_restore_domain_from_file_finish;
gvir_domain_device_get_type;
gvir_domain_device_get_domain;
--
1.7.10.4
12 years, 8 months
[libvirt] [PATCH] daemon: libvirtd quit after timeout period without resources checking
by Guannan Ren
Remove resources checking code for libvirtd to quit after timeout
period. The way we support this is the same as the libvirtd
signal handling, just set srv->quit to 1.
---
daemon/libvirtd.c | 16 +---------------
daemon/libvirtd.pod.in | 5 +----
src/rpc/virnetserver.c | 18 +++---------------
src/rpc/virnetserver.h | 6 +-----
4 files changed, 6 insertions(+), 39 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index ffbe067..d53f020 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -575,17 +575,6 @@ error:
return -1;
}
-
-static int daemonShutdownCheck(virNetServerPtr srv ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- if (virStateActive())
- return 0;
-
- return 1;
-}
-
-
/*
* Set up the logging environment
* By default if daemonized all errors go to the logfile libvirtd.log,
@@ -1242,10 +1231,7 @@ int main(int argc, char **argv) {
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
- virNetServerAutoShutdown(srv,
- timeout,
- daemonShutdownCheck,
- NULL);
+ virNetServerAutoShutdown(srv, timeout);
}
if ((daemonSetupSignals(srv)) < 0) {
diff --git a/daemon/libvirtd.pod.in b/daemon/libvirtd.pod.in
index 57a3b27..6b77f21 100644
--- a/daemon/libvirtd.pod.in
+++ b/daemon/libvirtd.pod.in
@@ -54,10 +54,7 @@ Use this name for the PID file, overriding the default value.
=item B<-t, --timeout> I<SECONDS>
-Exit after timeout period (in seconds) elapse with no client connections
-or registered resources. Be aware that resources such as autostart
-networks will result in never reaching the timeout, even when there are
-no client connections.
+Exit after timeout period (in seconds) elapse with no client connections.
=item B<-v, --verbose>
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 248ad9f..515ad79 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -105,8 +105,6 @@ struct _virNetServer {
virNetTLSContextPtr tls;
unsigned int autoShutdownTimeout;
- virNetServerAutoShutdownFunc autoShutdownFunc;
- void *autoShutdownOpaque;
virNetServerClientInitHook clientInitHook;
void *clientInitOpaque;
@@ -433,16 +431,10 @@ bool virNetServerIsPrivileged(virNetServerPtr srv)
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque)
+ unsigned int timeout)
{
virNetServerLock(srv);
-
srv->autoShutdownTimeout = timeout;
- srv->autoShutdownFunc = func;
- srv->autoShutdownOpaque = opaque;
-
virNetServerUnlock(srv);
}
@@ -663,12 +655,8 @@ static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
virNetServerPtr srv = opaque;
virNetServerLock(srv);
-
- if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) {
- VIR_DEBUG("Automatic shutdown triggered");
- srv->quit = 1;
- }
-
+ VIR_DEBUG("Automatic shutdown triggered");
+ srv->quit = 1;
virNetServerUnlock(srv);
}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 92f741a..d0231e5 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -46,16 +46,12 @@ virNetServerPtr virNetServerNew(size_t min_workers,
virNetServerClientInitHook clientInitHook,
void *opaque);
-typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
-
void virNetServerRef(virNetServerPtr srv);
bool virNetServerIsPrivileged(virNetServerPtr srv);
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque);
+ unsigned int timeout);
typedef void (*virNetServerSignalFunc)(virNetServerPtr srv, siginfo_t *info, void *opaque);
--
1.7.7.5
12 years, 8 months
[libvirt] Dumping network traffic
by Hendrik Schwartke
I'm currently working on a feature that dumps the network traffic of a virtual interface over the streaming api of libvirt.
The goal is to offer the possiblity to debug network related problems of guests without the need to have access to a shell on the host.
E.g. "virsh iface-dumptraffic virbr0 icmp | tcpdump -n -r -" prints all icmp traffic on virbr0 to stdout.
The code below is only a proof of concept, but it should be possible to recognize what I have in mind and how I want to implement it.
So I would appreciate any comments on that!
12 years, 8 months