[libvirt] [test-API][PATCH 1/2] update xmlgenerator.py to support for spice graphics type
by Nan Zhang
This extends graphics element for spice XML composing, and support
sub-elements settings for audio, images, streaming and so on:
<graphics type='spice' autoport='yes'>
<image compression='auto_glz'/>
<jpeg compression='auto'/>
<zlib compression='auto'/>
<playback compression='on'/>
<streaming mode='filter'/>
<clipboard copypaste='no'/>
</graphics>
---
utils/Python/xmlbuilder.py | 9 ++++++-
utils/Python/xmlgenerator.py | 51 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/utils/Python/xmlbuilder.py b/utils/Python/xmlbuilder.py
index 5a0f8c8..3dbe576 100644
--- a/utils/Python/xmlbuilder.py
+++ b/utils/Python/xmlbuilder.py
@@ -297,6 +297,13 @@ if __name__ == "__main__":
params['memory'] = '1048576'
params['vcpu'] = '2'
params['inputbus'] = 'usb'
+ params['graphtype'] = 'spice'
+ params['image'] = 'auto_glz'
+ params['jpeg'] = 'auto'
+ params['zlib'] = 'auto'
+ params['playback'] = 'on'
+ params['streaming'] = 'filter'
+ params['clipboard'] = 'no'
params['sound'] = 'ac97'
params['bootcd'] = '/iso/rhel5.iso'
@@ -367,7 +374,7 @@ if __name__ == "__main__":
#----------------------------------------
# get domain snapshot xml string
#----------------------------------------
- params['name'] = 'hello'
+ params['snapshotname'] = 'hello'
params['description'] = 'hello snapshot'
snapshot_xml = xmlobj.build_domain_snapshot(params)
diff --git a/utils/Python/xmlgenerator.py b/utils/Python/xmlgenerator.py
index d57dd33..b61ceb1 100644
--- a/utils/Python/xmlgenerator.py
+++ b/utils/Python/xmlgenerator.py
@@ -235,9 +235,54 @@ def domain_xml(params, install = False):
# <graphics>
graphics_element = domain.createElement('graphics')
- graphics_element.setAttribute('type', 'vnc')
- graphics_element.setAttribute('port', '-1')
- graphics_element.setAttribute('keymap', 'en-us')
+ if not params.has_key('graphtype'):
+ params['graphtype'] == 'vnc'
+
+ graphics_element.setAttribute('type', params['graphtype'])
+ if params['graphtype'] == 'vnc':
+ graphics_element.setAttribute('port', '-1')
+ graphics_element.setAttribute('keymap', 'en-us')
+ elif params['graphtype'] == 'spice':
+ graphics_element.setAttribute('autoport', 'yes')
+ if params.has_key('image'):
+ image_element = domain.createElement('image')
+ # image to set image compression (accepts
+ # auto_glz, auto_lz, quic, glz, lz, off)
+ image_element.setAttribute('compression', params['image'])
+ graphics_element.appendChild(image_element)
+ if params.has_key('jpeg'):
+ jpeg_element = domain.createElement('jpeg')
+ # jpeg for JPEG compression for images over wan (accepts
+ # auto, never, always)
+ jpeg_element.setAttribute('compression', params['jpeg'])
+ graphics_element.appendChild(jpeg_element)
+ if params.has_key('zlib'):
+ zlib_element = domain.createElement('zlib')
+ # zlib for configuring wan image compression (accepts
+ # auto, never, always)
+ zlib_element.setAttribute('compression', params['zlib'])
+ graphics_element.appendChild(zlib_element)
+ if params.has_key('playback'):
+ playback_element = domain.createElement('playback')
+ # playback for enabling audio stream compression (accepts on or off)
+ playback_element.setAttribute('compression', params['playback'])
+ graphics_element.appendChild(playback_element)
+ if params.has_key('streaming'):
+ streaming_element = domain.createElement('streaming')
+ # streamming for settings it's mode attribute to one of
+ # filter, all or off
+ streaming_element.setAttribute('mode', params['streaming'])
+ graphics_element.appendChild(streaming_element)
+ if params.has_key('clipboard'):
+ clipboard_element = domain.createElement('clipboard')
+ # Copy & Paste functionality is enabled by default, and can
+ # be disabled by setting the copypaste property to no
+ clipboard_element.setAttribute('copypaste', params['clipboard'])
+ graphics_element.appendChild(clipboard_element)
+ else:
+ print 'Wrong graphics type was specified.'
+ sys.exit(1)
+
devices_element.appendChild(graphics_element)
domain_element.appendChild(devices_element)
--
1.7.4.4
13 years, 2 months
[libvirt] [test-API][PATCH] Add test case update_devflag.py for update device flag
by Nan Zhang
---
repos/domain/update_devflag.py | 163 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 163 insertions(+), 0 deletions(-)
create mode 100644 repos/domain/update_devflag.py
diff --git a/repos/domain/update_devflag.py b/repos/domain/update_devflag.py
new file mode 100644
index 0000000..30f75b0
--- /dev/null
+++ b/repos/domain/update_devflag.py
@@ -0,0 +1,163 @@
+#!/usr/bin/evn python
+"""Update virtual device to guest from an XML file
+"""
+
+__author__ = 'Nan Zhang: nzhang(a)redhat.com'
+__date__ = 'Fri Sep 2, 2011'
+__version__ = '0.1.0'
+__credits__ = 'Copyright (C) 2011 Red Hat, Inc.'
+__all__ = ['usage', 'update_devflag']
+
+import os
+import re
+import sys
+import commands
+from xml.dom import minidom
+
+def append_path(path):
+ """Append root path of package"""
+ if path in sys.path:
+ pass
+ else:
+ sys.path.append(path)
+
+pwd = os.getcwd()
+result = re.search('(.*)libvirt-test-API', pwd)
+append_path(result.group(0))
+
+from lib import connectAPI
+from lib import domainAPI
+from utils.Python import utils
+from utils.Python import xmlbuilder
+from exception import LibvirtAPI
+
+def usage():
+ print '''usage: mandatory arguments:
+ guestname
+ devtype
+ '''
+
+def check_params(params):
+ """Verify inputing parameter dictionary"""
+ logger = params['logger']
+ keys = ['guestname', 'devtype']
+ for key in keys:
+ if key not in params:
+ logger.error("%s is required" %key)
+ usage()
+ return 1
+ return 0
+
+def create_image(params, img_name, img_size):
+ """Create an image file"""
+ logger = params['logger']
+ stat, ret = commands.getstatusoutput("dd if=/dev/zero of=%s bs=1 \
+ count=1 seek=%s" % (img_name, img_size))
+ if stat == 0:
+ logger.debug("create image result:\n%s" % ret)
+ return True
+ else:
+ return False
+
+def check_updated_device(params, guestname, domobj, srcfile):
+ """Check if the device is updated"""
+ logger = params['logger']
+ xmlobj = domobj.get_xml_desc(guestname)
+ domxml = minidom.parseString(xmlobj)
+
+ for diskTag in domxml.getElementsByTagName("source"):
+ if diskTag.parentNode.getAttribute("device") == 'cdrom':
+ upfile = diskTag.getAttribute("file")
+ elif diskTag.parentNode.getAttribute('device') == 'floppy':
+ upfile = diskTag.getAttribute("file")
+
+ if upfile == srcfile:
+ return False, upfile
+ else:
+ return True, upfile
+
+def update_devflag(params):
+ """Update virtual device to a domain from xml"""
+
+ # Initiate and check parameters
+ params_check_result = check_params(params)
+ if params_check_result:
+ return 1
+ logger = params['logger']
+ guestname = params['guestname']
+ devtype = params['devtype']
+ if devtype == 'cdrom':
+ xmlargs = {}
+ xmlargs['guestname'] = guestname
+ xmlargs['guesttype'] = 'kvm'
+ xmlargs['hdmodel'] = 'ide'
+ xmlargs['bootcd'] = '/var/lib/libvirt/boot/cdrom.img'
+ srcfile = xmlargs['bootcd']
+ create_image(params, srcfile, '100M')
+ elif devtype == 'floppy':
+ xmlargs = {}
+ xmlargs['guestname'] = guestname
+ xmlargs['floppysource'] = '/var/lib/libvirt/boot/floppy.img'
+ srcfile = xmlargs['floppysource']
+ create_image(params, srcfile, '2M')
+ else:
+ srcfile = None
+ logger.error("Wrong device type was specified.")
+ return 1
+
+ if not params.has_key('flag'):
+ flag = domainAPI.VIR_DOMAIN_AFFECT_CONFIG
+
+ # Connect to local hypervisor connection URI
+ util = utils.Utils()
+ uri = util.get_uri('127.0.0.1')
+ conn = connectAPI.ConnectAPI()
+ virconn = conn.open(uri)
+
+ caps = conn.get_caps()
+ logger.debug(caps)
+
+ # Generate device XML for updating
+ domobj = domainAPI.DomainAPI(virconn)
+ newxmlobj = xmlbuilder.XmlBuilder()
+
+ if devtype == 'cdrom':
+ newdevxml = newxmlobj.build_cdrom(xmlargs)
+ elif devtype == 'floppy':
+ newdevxml = newxmlobj.build_floppy(xmlargs)
+
+ logger.debug("block device xml desc:\n%s" %newdevxml)
+
+ try:
+ try:
+ domobj.update_device_flag(guestname, newdevxml, flag)
+ res, upfile = check_updated_device(params, guestname, \
+ domobj, srcfile)
+ if res:
+ logger.info("success to update '%s' device: %s\n" % \
+ (devtype, upfile))
+ else:
+ logger.error("fail to update '%s' device: %s\n" % \
+ (devtype, upfile))
+ except LibvirtAPI, e:
+ logger.error("API error message: %s, error code is %s" %
+ (e.response()['message'], e.response()['code']))
+ conn.close()
+ logger.info("closed hypervisor connection")
+ return 1
+ finally:
+ conn.close()
+ logger.info("closed hypervisor connection")
+
+ return 0
+
+def update_devflag_clean(params):
+ """Clean testing environment"""
+ logger = params['logger']
+
+ if params['devtype'] == 'cdrom':
+ os.system('rm -f /var/lib/libvirt/boot/cdrom.img')
+ elif params['devtype'] == 'floppy':
+ os.system('rm -f /var/lib/libvirt/boot/floppy.img')
+ else:
+ logger.debug("image file was not found.")
--
1.7.4.4
13 years, 2 months
[libvirt] [PATCH] security: chown/label bidrectional and unidirectional fifos
by Laine Stump
This patch fixes the regression with using named pipes for qemu serial
devices noted in:
https://bugzilla.redhat.com/show_bug.cgi?id=740478
The problem was that, while new code in libvirt looks for a single
bidirectional fifo of the name given in the config, then relabels that
and continues without looking for / relabelling the two unidirectional
fifos named ${name}.in and ${name}.out, qemu looks in the opposite
order. So if the user had naively created all three fifos, libvirt
would relabel the bidirectional fifo to allow qemu access, but qemu
would attempt to use the two unidirectional fifos and fail (because it
didn't have proper permissions/rights).
The solution implemented here is to always look for and chown/relabel
both types of fifos, then let qemu decide which one it wants to use
(in the unusual case that both are present). If one of the types is
present, libvirt will silently ignore when the other type is missing
(since that will be the most common case), but if neither type is
present, there will be an error logged about failing to relabel/chown
one of the bidirectional pipes. (Likewise, if one direction of the
unidirectional pipes is present but the other is missing, this will
also result in an error log).
(Note commit d37c6a3a (which first appeared in libvirt-0.9.2) added
the code that checked for a bidirectional fifo. Prior to that commit,
bidirectional fifos fdor serial devices didn't work unless the fifo
was pre-owned/labelled such that qemu could access it.)
---
src/security/security_dac.c | 39 ++++++++++++++++++++++++++++++---------
src/security/security_selinux.c | 39 ++++++++++++++++++++++++++++++---------
2 files changed, 60 insertions(+), 18 deletions(-)
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index af02236..f97d2d6 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -397,6 +397,7 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
{
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
char *in = NULL, *out = NULL;
+ bool found_bipipe = false;
int ret = -1;
switch (dev->type) {
@@ -406,19 +407,28 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
+ /* look for / chown both bidirectional pipe and dual uni-directional
+ * pipes if found; let the hypervisor decide which to use.
+ */
if (virFileExists(dev->data.file.path)) {
+ found_bipipe = true;
if (virSecurityDACSetOwnership(dev->data.file.path, priv->user, priv->group) < 0)
goto done;
- } else {
- if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
- (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
- virReportOOMError();
- goto done;
- }
- if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) ||
- (virSecurityDACSetOwnership(out, priv->user, priv->group) < 0))
- goto done;
}
+ if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
+ (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
+ virReportOOMError();
+ goto done;
+ }
+ if (found_bipipe &&
+ !(virFileExists(in) || virFileExists(out))) {
+ ret = 0;
+ goto done;
+ }
+ if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) ||
+ (virSecurityDACSetOwnership(out, priv->user, priv->group) < 0))
+ goto done;
+
ret = 0;
break;
@@ -438,6 +448,7 @@ virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainChrSourceDefPtr dev)
{
char *in = NULL, *out = NULL;
+ bool found_bipipe = false;
int ret = -1;
switch (dev->type) {
@@ -447,11 +458,21 @@ virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
+ if (virFileExists(dev->data.file.path)) {
+ found_bipipe = true;
+ if (virSecurityDACRestoreSecurityFileLabel(dev->data.file.path) < 0)
+ goto done;
+ }
if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
(virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
virReportOOMError();
goto done;
}
+ if (found_bipipe &&
+ !(virFileExists(in) || virFileExists(out))) {
+ ret = 0;
+ goto done;
+ }
if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
(virSecurityDACRestoreSecurityFileLabel(in) < 0))
goto done;
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 0807a34..e7a18a6 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -794,6 +794,7 @@ SELinuxSetSecurityChardevLabel(virDomainObjPtr vm,
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
char *in = NULL, *out = NULL;
+ bool found_bipipe = false;
int ret = -1;
if (secdef->norelabel)
@@ -806,19 +807,28 @@ SELinuxSetSecurityChardevLabel(virDomainObjPtr vm,
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
+ /* look for / chown both bidirectional pipe and dual uni-directional
+ * pipes if found; let the hypervisor decide which to use.
+ */
if (virFileExists(dev->data.file.path)) {
+ found_bipipe = true;
if (SELinuxSetFilecon(dev->data.file.path, secdef->imagelabel) < 0)
goto done;
- } else {
- if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
- (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
- virReportOOMError();
- goto done;
- }
- if ((SELinuxSetFilecon(in, secdef->imagelabel) < 0) ||
- (SELinuxSetFilecon(out, secdef->imagelabel) < 0))
- goto done;
}
+ if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
+ (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
+ virReportOOMError();
+ goto done;
+ }
+ if (found_bipipe &&
+ !(virFileExists(in) || virFileExists(out))) {
+ ret = 0;
+ goto done;
+ }
+ if ((SELinuxSetFilecon(in, secdef->imagelabel) < 0) ||
+ (SELinuxSetFilecon(out, secdef->imagelabel) < 0))
+ goto done;
+
ret = 0;
break;
@@ -840,6 +850,7 @@ SELinuxRestoreSecurityChardevLabel(virDomainObjPtr vm,
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
char *in = NULL, *out = NULL;
+ bool found_bipipe = false;
int ret = -1;
if (secdef->norelabel)
@@ -853,11 +864,21 @@ SELinuxRestoreSecurityChardevLabel(virDomainObjPtr vm,
ret = 0;
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
+ if (virFileExists(dev->data.file.path)) {
+ found_bipipe = true;
+ if (SELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0)
+ goto done;
+ }
if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
(virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
virReportOOMError();
goto done;
}
+ if (found_bipipe &&
+ !(virFileExists(in) || virFileExists(out))) {
+ ret = 0;
+ goto done;
+ }
if ((SELinuxRestoreSecurityFileLabel(out) < 0) ||
(SELinuxRestoreSecurityFileLabel(in) < 0))
goto done;
--
1.7.3.4
13 years, 2 months
[libvirt] [PATCH v2] qemu: add return value check
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
* src/qemu/qemu_migration.c: if 'vmdef' is NULL, the function
virDomainSaveConfig still dereferences it, it doesn't make
sense, so should add return value check to make sure 'vmdef'
is non-NULL before calling virDomainSaveConfig, in addition,
in order to debug later, also should record error information
into log.
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
src/qemu/qemu_migration.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index ef48d65..a009a57 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2582,7 +2582,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
vm->newDef = vmdef = mig->persistent;
else
vmdef = virDomainObjGetPersistentDef(driver->caps, vm);
- if (virDomainSaveConfig(driver->configDir, vmdef) < 0) {
+ if (!vmdef || virDomainSaveConfig(driver->configDir, vmdef) < 0) {
/* Hmpf. Migration was successful, but making it persistent
* was not. If we report successful, then when this domain
* shuts down, management tools are in for a surprise. On the
@@ -2603,6 +2603,9 @@ qemuMigrationFinish(struct qemud_driver *driver,
if (newVM)
vm->persistent = 0;
}
+ if (!vmdef)
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("can't get vmdef"));
goto endjob;
}
--
1.7.1
13 years, 2 months
[libvirt] [PATCH] formatdomain.html.in: fix tickpolicy
by Douglas Schilling Landgraf
there is no option "none":
>From libvirt/src/conf/domain_conf.c
<snip>
VIR_ENUM_IMPL(virDomainTimerTickpolicy,
VIR_DOMAIN_TIMER_TICKPOLICY_LAST,
"delay",
"catchup",
"merge",
"discard");
</snip>
Replacing with delay.
Signed-off-by: Douglas Schilling Landgraf <dougsland(a)redhat.com>
---
docs/formatdomain.html.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 9c3c2e8..49a2c09 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -746,7 +746,7 @@
<timer name="rtc" tickpolicy="catchup" track="guest">
<catchup threshold=123 slew=120 limit=10000/>
</timer>
- <timer name="pit" tickpolicy="none"/>
+ <timer name="pit" tickpolicy="delay"/>
</clock>
...</pre>
--
1.7.1
13 years, 2 months
[libvirt] [PATCH] Improve LXC startup error messages
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The LXC controller and container attempt to run in lockstep
using a series of handshakes. There was a flaw in the container
side though, causing it todo partial setup work, before waiting
for the initial controller handshake.
This in turn meant some of the controller setup could fail,
and obscure the real error from the container setup. Moving
the lxcContainerWaitForContinue call to be the first thing
the container does solves that.
The controller still, however, pollutes the log with a message
about the container handshake failing, when the container
shuts down during startup.
To deal with this requires special handling of the EOF condition
on the controllers lxcContainerWaitForContinue() call.
* src/lxc/lxc_container.c: Wait for continue message from
controller before doing anything at all
* src/lxc/lxc_controller.c: Don't pollute log with error
message if EOF was returned from lxcContainerWaitForContinue.
* src/lxc/lxc_driver.c: Handle EOF from controller handshake
---
src/lxc/lxc_container.c | 38 ++++++++++++++++++++++++++------------
src/lxc/lxc_controller.c | 31 ++++++++++++++++++++++++++++---
src/lxc/lxc_driver.c | 2 +-
3 files changed, 55 insertions(+), 16 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 787df9a..ee5ca9f 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -214,7 +214,7 @@ error_out:
* parent process. It will send this message on the socket pair stored in
* the vm structure once it has completed the post clone container setup.
*
- * Returns 0 on success or -1 in case of error
+ * Returns 1 on success, 0 on EOF, or -1 in case of error
*/
int lxcContainerWaitForContinue(int control)
{
@@ -222,12 +222,18 @@ int lxcContainerWaitForContinue(int control)
int readLen;
readLen = saferead(control, &msg, sizeof(msg));
- if (readLen != sizeof(msg) ||
- msg != LXC_CONTINUE_MSG) {
+ if (readLen < 0)
+ return -1;
+
+ if (readLen != sizeof(msg))
+ return 0;
+
+ if (msg != LXC_CONTINUE_MSG) {
+ errno = EINVAL;
return -1;
}
- return 0;
+ return 1;
}
@@ -1036,6 +1042,20 @@ static int lxcContainerChild( void *data )
char *ttyPath = NULL;
virDomainFSDefPtr root;
virCommandPtr cmd = NULL;
+ int rc;
+
+ /* Wait for interface devices to show up */
+ if ((rc = lxcContainerWaitForContinue(argv->monitor)) <= 0) {
+ if (rc < 0)
+ virReportSystemError(errno, "%s",
+ _("Failed to read the container continue message"));
+ else
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Controller unexpectedly quit"));
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Received container continue message");
if (NULL == vmDef) {
lxcError(VIR_ERR_INTERNAL_ERROR,
@@ -1079,14 +1099,6 @@ static int lxcContainerChild( void *data )
goto cleanup;
}
- /* Wait for interface devices to show up */
- if (lxcContainerWaitForContinue(argv->monitor) < 0) {
- virReportSystemError(errno, "%s",
- _("Failed to read the container continue message"));
- goto cleanup;
- }
- VIR_DEBUG("Received container continue message");
-
/* rename and enable interfaces */
if (lxcContainerRenameAndEnableInterfaces(argv->nveths,
argv->veths) < 0) {
@@ -1120,6 +1132,8 @@ cleanup:
}
virCommandFree(cmd);
+ if (ret < 0)
+ virDispatchError(NULL);
return ret;
}
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 52d382e..8c3a54f 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -780,6 +780,9 @@ static int lxcSetPersonality(virDomainDefPtr def)
# define MS_SLAVE (1<<19)
#endif
+/*
+ * Returns -1 on error, 0 if container quit unexpected, 1 on success
+ */
static int
lxcControllerRun(virDomainDefPtr def,
unsigned int nveths,
@@ -801,6 +804,7 @@ lxcControllerRun(virDomainDefPtr def,
size_t nloopDevs = 0;
int *loopDevs = NULL;
size_t i;
+ int ret;
if (socketpair(PF_UNIX, SOCK_STREAM, 0, control) < 0) {
virReportSystemError(errno, "%s",
@@ -935,12 +939,25 @@ lxcControllerRun(virDomainDefPtr def,
goto cleanup;
}
- if (lxcContainerWaitForContinue(containerhandshake[0]) < 0) {
+ if ((ret = lxcContainerWaitForContinue(containerhandshake[0])) < 0) {
virReportSystemError(errno, "%s",
_("error receiving signal from container"));
goto cleanup;
}
+ if (ret == 0) {
+ rc = 0;
+ /* We're not raising an error, since the container will have
+ * done that already and we don't want to confuse the driver
+ * when it fetches the error message from logs
+ */
+#if 0
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("container quit during startup handshake"));
+#endif
+ goto cleanup;
+ }
+
/* Now the container is fully setup... */
/* ...we can close the loop devices... */
@@ -959,7 +976,10 @@ lxcControllerRun(virDomainDefPtr def,
}
VIR_FORCE_CLOSE(handshakefd);
- rc = lxcControllerMain(monitor, client, appPty, containerPty, container);
+ if (lxcControllerMain(monitor, client, appPty, containerPty, container) != 0)
+ goto cleanup;
+
+ rc = 1;
cleanup:
VIR_FREE(devptmx);
@@ -1186,5 +1206,10 @@ cleanup:
unlink(sockpath);
VIR_FREE(sockpath);
- return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+ /* If rc == 0, we have an error, but the lxc container
+ * startup will have printed it already.*/
+ if (rc < 0)
+ virDispatchError(NULL);
+
+ return rc <=0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 4b62600..759e3a9 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1622,7 +1622,7 @@ static int lxcVmStart(virConnectPtr conn,
vm->def->id = vm->pid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
- if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
+ if (lxcContainerWaitForContinue(handshakefds[0]) <= 0) {
char out[1024];
if (!(lxcReadLogOutput(vm, logfile, pos, out, 1024) < 0)) {
--
1.7.6.2
13 years, 2 months
[libvirt] [PATCH] virsh: update man page for cpu_shares parameter
by Daniel Veillard
The man page suggest that the cpu_shares parameter of schedinfo
allows values 0-262144, but the kernel remaps values 0 and 1 to
the minimum 2, just document that behaviour:
[root@test ~]# cat /cgroup/cpu/libvirt/qemu/cpu.shares
1024
[root@test ~]# echo 0 > /cgroup/cpu/libvirt/qemu/cpu.shares
[root@test ~]# cat /cgroup/cpu/libvirt/qemu/cpu.shares
2
[root@test ~]# echo 1 > /cgroup/cpu/libvirt/qemu/cpu.shares
[root@test ~]# cat /cgroup/cpu/libvirt/qemu/cpu.shares
2
[root@test ~]#
* tools/virsh.pod: update description of the cpu_shares parameter
to indicate the values 0 and 1 are automatically changed by the
kernel to minimal value 2
diff --git a/tools/virsh.pod b/tools/virsh.pod
index a01d723..6e3febb 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -914,7 +914,9 @@ If I<--current> is specified, affect the current guest state.
B<Note>: The cpu_shares parameter has a valid value range of 0-262144; Negative
values are wrapped to positive, and larger values are capped at the maximum.
-Therefore, -1 is a useful shorthand for 262144.
+Therefore, -1 is a useful shorthand for 262144. The values 0 and 1 seems to
+also be automatically changed by the Linux kernel to 2 which consider this
+the minimal value.
B<Note>: The weight and cap parameters are defined only for the
XEN_CREDIT scheduler and are now I<DEPRECATED>.
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
13 years, 2 months
[libvirt] [PATCH] nodedev: document virsh nodedev-* commands
by Eric Blake
This section of the man page was completely missing; I stumbled on
it when I had no clue that I had to use nodedev-reattach after
I was done playing with <hostdev> device passthrough to one of my
guests.
* tools/virsh.pod (NODEDEV COMMANDS): New section.
---
I also need to write something useful for http://libvirt.org/formatnode.html,
but that's a patch for another day.
Please double-check this for technical accuracy.
tools/virsh.pod | 315 ++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 241 insertions(+), 74 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 43ed1ea..e9f415a 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1163,84 +1163,251 @@ is not available the processes will provide an exit code of 1.
=back
-=head1 DEVICE COMMANDS
+=head1 NODEDEV COMMANDS
+
+The following commands manipulate host devices that are intended to be
+passed through to guest domains via <hostdev> elements in a domain's
+<devices> section. A node device key is generally specified by the bus
+name followed by its address, using underscores between all components,
+such as pci_0000_00_02_1, usb_1_5_3, or net_eth1_00_27_13_6a_fe_00.
+The B<nodedev-list> gives the full list of host devices that are known
+to libvirt, although this includes devices that cannot be assigned to
+a guest (for example, attempting to detach the PCI device that controls
+the host's hard disk controller where the guest's disk images live could
+cause the host system to lock up or reboot).
+
+For more information on node device definition see:
+L<http://libvirt.org/formatnode.html>.
+
+Passthrough devices cannot be simultaneously used by the host and its
+guest domains. Attempts to use a passthrough <hostdev> for a guest may
+have the ability to behave as if B<nodedev-dettach> had been called,
+although making this call explicitly is safe. Once a guest no longer
+needs a passthrough device, reversing the process so that the host can
+again use the device requires the explicit use of B<nodedev-reattach>.
-The following commands manipulate devices associated to domains.
-The domain-id can be specified as a short integer, a name or a full UUID.
-To better understand the values allowed as options for the command
-reading the documentation at L<http://libvirt.org/formatdomain.html> on the
-format of the device sections to get the most accurate set of accepted values.
+=over 4
+
+=item B<nodedev-create> I<FILE>
+
+Create a device on the host node that can then be assigned to virtual
+machines. Normally, libvirt is able to automatically determine which
+host nodes are available for use, but this allows registration of
+host hardware that libvirt did not automatically detect. I<file>
+contains xml for a top-level <device> description of a node device.
+
+=item B<nodedev-destroy> I<nodedev>
+
+Destroy (stop) a device on the host. Note that this makes libvirt
+quit managing a host device, and may even make that device unusable
+by the rest of the physical host until a reboot.
+
+=item B<nodedev-dettach> I<nodedev>
+
+Detach I<nodedev> from the host, so that it can safely be used by
+guests via <hostdev> passthrough. This is reversed with
+B<nodedev-reattach>.
+
+=item B<nodedev-dumpxml> I<nodedev>
+
+Dump a <device> XML representation for the given node device, including
+such information as the device name, which bus owns the device, the
+vendor and product id, and any capabilities of the device usable by
+libvirt (such as whether device reset is supported).
+
+=item B<nodedev-list> I<cap> I<--tree>
+
+List all of the devices available on the node that are known by libvirt.
+If I<cap> is used, the list is filtered to show only the nodes that
+include the given capability. If I<--tree> is used, the output is
+formatted in a tree representing parents of each node.
+
+=item B<nodedev-reattach> I<nodedev>
+
+Declare that I<nodedev> is no longer in use by any guests, and that
+the host can resume normal use of the device. While libvirt can
+sometimes perform an implicit B<nodedev-dettach> when creating a
+guest, it currently requires an explicit B<nodedev-reattach> after
+the last guest use of the device before the host regains full control.
+
+=item B<nodedev-reset> I<nodedev>
+
+Trigger a device reset for I<nodedev>, useful prior to transferring
+a node device between guest passthrough or the host. Libvirt will
+often do this action implicitly when required, but this command
+allows an explicit reset when needed.
+
+=back
+
+=head1 SNAPSHOT COMMMANDS
+
+The following commands manipulate domain snapshots. Snapshots take the
+disk, memory, and device state of a domain at a point-of-time, and save it
+for future use. They have many uses, from saving a "clean" copy of an OS
+image to saving a domain's state before a potentially destructive operation.
+Snapshots are identified with a unique name. See
+L<http://libvirt.org/formatsnapshot.html> for documentation of the XML format
+used to represent properties of snapshots.
=over 4
-=item B<attach-device> I<domain-id> I<FILE>
-
-Attach a device to the domain, using a device definition in an XML file.
-See the documentation to learn about libvirt XML format for a device.
-For cdrom and floppy devices, this command only replaces the media within
-the single existing device; consider using B<update-device> for this usage.
-
-=item B<attach-disk> I<domain-id> I<source> I<target>
-[I<--driver driver>] [I<--subdriver subdriver>] [I<--cache cache>]
-[I<--type type>] [I<--mode mode>] [I<--persistent>] [I<--sourcetype soucetype>]
-[I<--serial serial>] [I<--shareable>] [I<--address address>]
-
-Attach a new disk device to the domain.
-I<source> and I<target> are paths for the files and devices.
-I<driver> can be I<file>, I<tap> or I<phy> for the Xen hypervisor depending on
-the kind of access; or I<qemu> for the QEMU emulator.
-I<type> can indicate I<cdrom> or I<floppy> as alternative to the disk default,
-although this use only replaces the media within the existing virtual cdrom or
-floppy device; consider using B<update-device> for this usage instead.
-I<mode> can specify the two specific mode I<readonly> or I<shareable>.
-I<persistent> indicates the changes will affect the next boot of the domain.
-I<sourcetype> can indicate the type of source (block|file)
-I<cache> can be one of "default", "none", "writethrough", "writeback",
-"directsync" or "unsafe".
-I<serial> is the serial of disk device. I<shareable> indicates the disk device
-is shareable between domains.
-I<address> is the address of disk device in the form of pci:domain.bus.slot.function,
-scsi:controller.bus.unit or ide:controller.bus.unit.
-
-=item B<attach-interface> I<domain-id> I<type> I<source>
-[I<--target target>] [I<--mac mac>] [I<--script script>] [I<--model model>]
-[I<--persistent>]
-
-Attach a new network interface to the domain.
-I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
-I<source> indicates the source device.
-I<target> allows to indicate the target device in the guest.
-I<mac> allows to specify the MAC address of the network interface.
-I<script> allows to specify a path to a script handling a bridge instead of
-the default one.
-I<model> allows to specify the model type.
-I<persistent> indicates the changes will affect the next boot of the domain.
-
-=item B<detach-device> I<domain-id> I<FILE>
-
-Detach a device from the domain, takes the same kind of XML descriptions
-as command B<attach-device>.
-
-=item B<detach-disk> I<domain-id> I<target>
-
-Detach a disk device from a domain. The I<target> is the device as seen
-from the domain.
-
-=item B<detach-interface> I<domain-id> I<type> [I<--mac mac>]
-
-Detach a network interface from a domain.
-I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
-It is recommended to use the I<mac> option to distinguish between the interfaces
-if more than one are present on the domain.
-
-=item B<update-device> I<domain-id> I<file> [I<--persistent>] [I<--force>]
-
-Update the characteristics of a device associated with I<domain-id>, based on
-the device definition in an XML I<file>. If the I<--persistent> option is
-used, the changes will affect the next boot of the domain. The I<--force>
-option can be used to force device update, e.g., to eject a CD-ROM even if it
-is locked/mounted in the domain. See the documentation to learn about libvirt
-XML format for a device.
+=item B<snapshot-create> I<domain> [I<xmlfile>] {[I<--redefine> [I<--current>]]
+| [I<--no-metadata>] [I<--halt>] [I<--disk-only>]}
+
+Create a snapshot for domain I<domain> with the properties specified in
+I<xmlfile>. Normally, the only properties settable for a domain snapshot
+are the <name> and <description> elements, as well as <disks> if
+I<--disk-only> is given; the rest of the fields are
+ignored, and automatically filled in by libvirt. If I<xmlfile> is
+completely omitted, then libvirt will choose a value for all fields.
+The new snapshot will become current, as listed by B<snapshot-current>.
+
+If I<--halt> is specified, the domain will be left in an inactive state
+after the snapshot is created.
+
+If I<--disk-only> is specified, the snapshot will only include disk
+state rather than the usual system checkpoint with vm state. Disk
+snapshots are faster than full system checkpoints, but reverting to a
+disk snapshot may require fsck or journal replays, since it is like
+the disk state at the point when the power cord is abruptly pulled;
+and mixing I<--halt> and I<--disk-only> loses any data that was not
+flushed to disk at the time.
+
+If I<--redefine> is specified, then all XML elements produced by
+B<snapshot-dumpxml> are valid; this can be used to migrate snapshot
+hierarchy from one machine to another, to recreate hierarchy for the
+case of a transient domain that goes away and is later recreated with
+the same name and UUID, or to make slight alterations in the snapshot
+metadata (such as host-specific aspects of the domain XML embedded in
+the snapshot). When this flag is supplied, the I<xmlfile> argument
+is mandatory, and the domain's current snapshot will not be altered
+unless the I<--current> flag is also given.
+
+If I<--no-metadata> is specified, then the snapshot data is created,
+but any metadata is immediately discarded (that is, libvirt does not
+treat the snapshot as current, and cannot revert to the snapshot
+unless I<--redefine> is later used to teach libvirt about the
+metadata again).
+
+Existence of snapshot metadata will prevent attempts to B<undefine>
+a persistent domain. However, for transient domains, snapshot
+metadata is silently lost when the domain quits running (whether
+by command such as B<destroy> or by internal guest action).
+
+=item B<snapshot-create-as> I<domain> {[I<--print-xml>]
+| [I<--no-metadata>] [I<--halt>]} [I<name>] [I<description>]
+[I<--disk-only> [[I<--diskspec>] B<diskspec>]...
+
+Create a snapshot for domain I<domain> with the given <name> and
+<description>; if either value is omitted, libvirt will choose a
+value. If I<--print-xml> is specified, then XML appropriate for
+I<snapshot-create> is output, rather than actually creating a snapshot.
+Otherwise, if I<--halt> is specified, the domain will be left in an
+inactive state after the snapshot is created, and if I<--disk-only>
+is specified, the snapshot will not include vm state.
+
+The I<--disk-only> flag is used to request a disk-only snapshot. When
+this flag is in use, the command can also take additional I<diskspec>
+arguments to add <disk> elements to the xml. Each <diskspec> is in the
+form B<disk[,snapshot=type][,driver=type][,file=name]>. To include a
+literal comma in B<disk> or in B<file=name>, escape it with a second
+comma. A literal I<--diskspec> must preceed each B<diskspec> unless
+all three of I<domain>, I<name>, and I<description> are also present.
+For example, a diskspec of "vda,snapshot=external,file=/path/to,,new"
+results in the following XML:
+ <disk name='vda' snapshot='external'>
+ <source file='/path/to,new'/>
+ </disk>
+
+If I<--no-metadata> is specified, then the snapshot data is created,
+but any metadata is immediately discarded (that is, libvirt does not
+treat the snapshot as current, and cannot revert to the snapshot
+unless B<snapshot-create> is later used to teach libvirt about the
+metadata again). This flag is incompatible with I<--print-xml>.
+
+=item B<snapshot-current> I<domain> {[I<--name>] | [I<--security-info]
+| [I<snapshotname>]}
+
+Without I<snapshotname>, this will output the snapshot XML for the domain's
+current snapshot (if any). If I<--name> is specified, just the
+current snapshot name instead of the full xml. Otherwise, using
+I<--security-info> will also include security sensitive information in
+the XML.
+
+With I<snapshotname>, this is a request to make the existing named
+snapshot become the current snapshot, without reverting the domain.
+
+=item B<snapshot-edit> I<domain> I<snapshotname> [I<--current>]
+
+Edit the XML configuration file for I<snapshotname> of a domain. If
+I<--current> is specified, also force the edited snapshot to become
+the current snapshot.
+
+This is equivalent to:
+
+ virsh snapshot-dumpxml dom name > snapshot.xml
+ vi snapshot.xml (or make changes with your other text editor)
+ virsh snapshot-create dom snapshot.xml --redefine [--current]
+
+except that it does some error checking.
+
+The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment
+variables, and defaults to C<vi>.
+
+=item B<snapshot-list> I<domain> [{I<--parent> | I<--roots>}] [I<--metadata>]
+
+List all of the available snapshots for the given domain.
+
+If I<--parent> is specified, add a column to the output table giving
+the name of the parent of each snapshot.
+
+If I<--roots> is specified, the list will be filtered to just snapshots
+that have no parents; this option is not compatible with I<--parent>.
+
+If I<--metadata> is specified, the list will be filtered to just
+snapshots that involve libvirt metadata, and thus would prevent
+B<undefine> of a persistent domain, or be lost on B<destroy> of
+a transient domain.
+
+=item B<snapshot-dumpxml> I<domain> I<snapshot> [I<--security-info>]
+
+Output the snapshot XML for the domain's snapshot named I<snapshot>.
+Using I<--security-info> will also include security sensitive information.
+
+=item B<snapshot-parent> I<domain> I<snapshot>
+
+Output the name of the parent snapshot for the given I<snapshot>, if any.
+
+=item B<snapshot-revert> I<domain> I<snapshot> [{I<--running> | I<--paused>}]
+
+Revert the given domain to the snapshot specified by I<snapshot>. Be aware
+that this is a destructive action; any changes in the domain since the last
+snapshot was taken will be lost. Also note that the state of the domain after
+snapshot-revert is complete will be the state of the domain at the time
+the original snapshot was taken.
+
+Normally, reverting to a snapshot leaves the domain in the state it was
+at the time the snapshot was created, except that a disk snapshot with
+no vm state leaves the domain in an inactive state. Passing either the
+I<--running> or I<--paused> flag will perform additional state changes
+(such as booting an inactive domain, or pausing a running domain). Since
+transient domains cannot be inactive, it is required to use one of these
+flags when reverting to a disk snapshot of a transient domain.
+
+=item B<snapshot-delete> I<domain> I<snapshot> [I<--metadata>]
+[{I<--children> | I<--children-only>}]
+
+Delete the snapshot for the domain named I<snapshot>. If this snapshot
+has child snapshots, changes from this snapshot will be merged into the
+children. If I<--children> is passed, then delete this snapshot and any
+children of this snapshot. If I<--children-only> is passed, then delete
+any children of this snapshot, but leave this snapshot intact. These
+two flags are mutually exclusive.
+
+If I<--metadata> is specified, then only delete the snapshot metadata
+maintained by libvirt, while leaving the snapshot contents intact for
+access by external tools; otherwise deleting a snapshot also removes
+the data contents from that point in time.
=back
--
1.7.4.4
13 years, 2 months
[libvirt] [PATCH 0/5] snapshot-list --tree
by Eric Blake
I liked 'nodedev-list --tree' so much that I wanted the same
for 'snapshot-list domain --tree'.
Eric Blake (5):
snapshot: new virDomainSnapshotGetParent API
snapshot: remote protocol for getparent
snapshot: refactor virsh snapshot parent computation
snapshot: add virsh snapshot-list --tree
snapshot: implement getparent in qemu
include/libvirt/libvirt.h.in | 4 +
src/driver.h | 5 ++
src/libvirt.c | 44 +++++++++++++
src/libvirt_public.syms | 5 ++
src/qemu/qemu_driver.c | 46 +++++++++++++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 12 +++-
src/remote_protocol-structs | 8 ++
src/rpc/gendispatch.pl | 4 +-
tools/virsh.c | 147 ++++++++++++++++++++++++++++++++++--------
tools/virsh.pod | 14 ++--
11 files changed, 254 insertions(+), 36 deletions(-)
--
1.7.4.4
13 years, 2 months
[libvirt] AHCI support in qemu driver
by Jim Fehlig
I have some time this week to work on libvirt and thought Daniel's
suggestion [1] for adding AHCI support in the qemu driver would be a
useful endeavor.
I've managed to start a qemu instance using AHCI with attached hackery,
iff I have a controller defined. E.g.
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/test/disk0.raw'/>
<target dev='sda' bus='sata'/>
</disk>
<controller type='sata' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</controller>
which results in qemu args
-device ahci,id=ahci0,bus=pci.0,multifunction=on,addr=0x3.0x0 -drive
file=/var/lib/libvirt/images/test/disk0.raw,if=none,id=drive-sata-dik0,format=raw
-device
ide-drive,bus=ahci0.0,drive=drive-sata-disk0,id=sata-disk0,bootindex=1
If the controller is not explicitly defined, the AHCI device (-device
ahci,...) is not created and qemu fails with
qemu-kvm: -device
ide-drive,bus=ahci0.0,drive=drive-sata-disk0,id=sata-disk0,bootindex=1:
Bus 'a
hci0.0' not found
I'm not quite sure how to create the controller when not explicitly
defined in the config.
Also, I suspect there are many things I'm missing in adding support for
this controller. E.g., I've ignored hotplug for the moment. What would
be considered minimal functionality for supporting this controller?
Thanks!
Jim
[1] http://www.redhat.com/archives/libvir-list/2011-August/msg01034.html
13 years, 2 months