[libvirt] ANNOUNCE: virt-manager 0.9.0 and virtinst 0.600.0 released
by Cole Robinson
I'm happy to announce two new releases:
virt-manager 0.9.0: virt-manager is a desktop application for managing
KVM and Xen virtual machines via libvirt.
virtinst 0.600.0: virtinst is a collection of command line tools for
provisioning libvirt virtual machines, including virt-install and
virt-clone.
The releases can be downloaded from:
http://virt-manager.org/download.html
The direct download links are:
http://virt-manager.org/download/sources/virt-manager/virt-manager-0.9.0....
http://virt-manager.org/download/sources/virtinst/virtinst-0.600.0.tar.gz
The virt-manager release includes:
- Use a hiding toolbar for fullscreen mode
- Use libguestfs to show guest packagelist and more (Richard W.M. Jones)
- Basic 'New VM' wizard support for LXC guests
- Remote serial console access (with latest libvirt)
- Remote URL guest installs (with latest libvirt)
- Add Hardware: Support <filesystem> devices
- Add Hardware: Support <smartcard> devices (Marc-André Lureau)
- Enable direct interface selection for qemu/kvm (Gerhard Stenzel)
- Allow viewing and changing disk serial number
The virtinst release includes:
- virt-install: Various improvements to enable LXC/container guests:
- New --filesystem option for <filesystem> devices
- New --init option for container <init> path
- New --container option (similar to --paravirt or --hvm)
- virt-install: Make --location remotely (with latest libvirt)
- virt-install: New --smartcard option for <smartcard> devices
(Marc-André Lureau)
- virt-install: New --numatune option for building guest <numatune> XML
- virt-install: option to set --disk error_policy=
- virt-install: option to set --disk serial=
Thanks to everyone who has contributed to this release through testing,
bug reporting, submitting patches, and otherwise sending in feedback!
Thanks,
Cole
13 years, 4 months
[libvirt] [PATCH] freebsd: Add gnulib environ module for the commandtest
by Matthias Bolte
---
bootstrap.conf | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index f006a47..3b105b1 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -36,6 +36,7 @@ configmake
count-one-bits
crypto/md5
dirname-lgpl
+environ
fclose
fcntl-h
ffs
--
1.7.4.1
13 years, 4 months
[libvirt] [PATCH] Fix bug #611823 prohibit pools with duplicate storage
by Lei Li
To make sure the unique storage pool defined and created from different directory to avoid inconsistent version of volume pool created, I add two API be called by storage driver to check for the probable duplicate pools and refused the duplicate pool.
virStoragePoolObjFindByPath() provide a method to find pool object by target path in pool list.
virStoragePoolTargetDuplicate() implement the function to check if there is duplicate pool.
Add judgement for storagePoolCreate&storagePoolDefine by calling virStoragePoolTargetDuplicate() to avoid both transient storage pool and persistent storage pool be created repeatedly in storage driver.
Signed-off-by: Lei Li<lilei(a)linux.vnet.ibm.com>
---
src/conf/storage_conf.c | 39 +++++++++++++++++++++++++++++++++++++++
src/conf/storage_conf.h | 4 ++++
src/libvirt_private.syms | 2 ++
src/storage/storage_driver.c | 6 ++++++
4 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 995f9a6..a499e82 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1317,6 +1317,22 @@ virStoragePoolObjFindByName(virStoragePoolObjListPtr pools,
return NULL;
}
+virStoragePoolObjPtr
+virStoragePoolObjFindByPath(virStoragePoolObjListPtr pools,
+ const char *path)
+{
+ unsigned int i;
+
+ for (i = 0 ; i< pools->count ; i++) {
+ virStoragePoolObjLock(pools->objs[i]);
+ if (STREQ(pools->objs[i]->def->target.path, path))
+ return pools->objs[i];
+ virStoragePoolObjUnlock(pools->objs[i]);
+ }
+
+ return NULL;
+}
+
void
virStoragePoolObjClearVols(virStoragePoolObjPtr pool)
{
@@ -1707,6 +1723,29 @@ cleanup:
return ret;
}
+int virStoragePoolTargetDuplicate(virStoragePoolObjListPtr pools,
+ virStoragePoolDefPtr def)
+{
+ int ret = 1;
+ virStoragePoolObjPtr pool = NULL;
+
+ /*check pool list if defined target path already exist*/
+ pool = virStoragePoolObjFindByPath(pools, def->target.path);
+
+ if (pool) {
+ virStorageReportError(VIR_ERR_OPERATION_FAILED,
+ _("target path '%s' is already in use"),
+ pool->def->target.path);
+ ret = -1;
+ goto cleanup;
+ }
+
+
+cleanup:
+ if (pool)
+ virStoragePoolObjUnlock(pool);
+ return ret;
+}
void virStoragePoolObjLock(virStoragePoolObjPtr obj)
{
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 271441a..454c43d 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -335,6 +335,8 @@ virStoragePoolObjPtr virStoragePoolObjFindByUUID(virStoragePoolObjListPtr pools,
const unsigned char *uuid);
virStoragePoolObjPtr virStoragePoolObjFindByName(virStoragePoolObjListPtr pools,
const char *name);
+virStoragePoolObjPtr virStoragePoolObjFindByPath(virStoragePoolObjListPtr pools,
+ const char *path);
virStorageVolDefPtr virStorageVolDefFindByKey(virStoragePoolObjPtr pool,
const char *key);
@@ -387,6 +389,8 @@ char *virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def);
int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def,
unsigned int check_active);
+int virStoragePoolTargetDuplicate(virStoragePoolObjListPtr pools,
+ virStoragePoolDefPtr def);
void virStoragePoolObjLock(virStoragePoolObjPtr obj);
void virStoragePoolObjUnlock(virStoragePoolObjPtr obj);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 853ee62..ef323f5 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -930,7 +930,9 @@ virStoragePoolObjClearVols;
virStoragePoolObjDeleteDef;
virStoragePoolObjFindByName;
virStoragePoolObjFindByUUID;
+virStoragePoolObjFindByPath;
virStoragePoolObjIsDuplicate;
+virStoragePoolTargetDuplicate;
virStoragePoolObjListFree;
virStoragePoolObjLock;
virStoragePoolObjRemove;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 9c353e3..8ee63f6 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -536,6 +536,9 @@ storagePoolCreate(virConnectPtr conn,
if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1)< 0)
goto cleanup;
+ if (virStoragePoolTargetDuplicate(&driver->pools, def)< 0)
+ goto cleanup;
+
if ((backend = virStorageBackendForType(def->type)) == NULL)
goto cleanup;
@@ -589,6 +592,9 @@ storagePoolDefine(virConnectPtr conn,
if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0)< 0)
goto cleanup;
+ if (virStoragePoolTargetDuplicate(&driver->pools, def)< 0)
+ goto cleanup;
+
if (virStorageBackendForType(def->type) == NULL)
goto cleanup;
--
1.7.1
13 years, 5 months
[libvirt] [PATCHv4 0/2] vnc/spice listen address as a network name
by Laine Stump
This is the latest reincarnation of this patch series:
https://www.redhat.com/archives/libvir-list/2011-July/msg01717.html
In the previous version, I had created a new subelement of <graphics>,
called <listen>, and placed all listen address and port attributes
there. After discussion on the list and in IRC with Dan Berrange and
Eric Blake, I became convinced that was overdoing things, and that
really only the address or network name should be in the <listen>
element, but that port/tlsPort/autoport should stay put.
This version removes all changes to port-related attributes, paring it
down to just the listen address (and the new listen network)
attribute. This greatly simplifies the patch, so new review of it
should be easier.
Based on Eric's review, the nwe version tries to be more concise about
what is accepted, what is ignored, and what is rejected in the XML,
both by the parser and by the RNG. (since there is less to deal with,
this is also easier.)
Having a single port value but multiple addresses does create some
potential future restrictions, which we can deal with an eliminate
later if they become problematic. In particular, each graphics device
will have only a single port, but could have multiple listen
addresses; in this case, all the listen addresses would have to listen
on the same port. (This isn't a problem right now, because all of our
drivers can only listen on a single address anyway).
(Note to Eric: I did consider putting the switch to helper functions
into its own patch, but after removing all the ports from <listen>,
the number of helper functions (and thus the number of changes created
by switching to using them, has been reduced considerably, so the gain
wouldn't be as much. (also, it's very late, and I'd like to get some
sleep tonight :-)
13 years, 5 months
[libvirt] [PATCH] openvz: detect when a domain was shut down from the inside
by Jean-Baptiste Rouault
This patch adds an internal function openvzGetVEStatus to
get the real state of the domain. This function is used in
various places in the driver, in particular to detect when
the domain has been shut down by the user with the "halt"
command.
---
src/openvz/openvz_driver.c | 76 +++++++++++++++++++++++++++++++++++++++-----
1 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 4e7cb03..3b3b079 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -72,6 +72,7 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
unsigned int nvcpus);
static int openvzDomainSetMemoryInternal(virDomainObjPtr vm,
unsigned long memory);
+static int openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason);
static void openvzDriverLock(struct openvz_driver *driver)
{
@@ -340,6 +341,7 @@ static int openvzDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info) {
struct openvz_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
+ int state;
int ret = -1;
openvzDriverLock(driver);
@@ -352,9 +354,11 @@ static int openvzDomainGetInfo(virDomainPtr dom,
goto cleanup;
}
- info->state = virDomainObjGetState(vm, NULL);
+ if (openvzGetVEStatus(vm, &state, NULL) == -1)
+ goto cleanup;
+ info->state = state;
- if (!virDomainObjIsActive(vm)) {
+ if (info->state != VIR_DOMAIN_RUNNING) {
info->cpuTime = 0;
} else {
if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
@@ -398,8 +402,7 @@ openvzDomainGetState(virDomainPtr dom,
goto cleanup;
}
- *state = virDomainObjGetState(vm, reason);
- ret = 0;
+ ret = openvzGetVEStatus(vm, state, reason);
cleanup:
if (vm)
@@ -584,6 +587,7 @@ openvzDomainShutdownFlags(virDomainPtr dom,
virDomainObjPtr vm;
const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL};
int ret = -1;
+ int status;
virCheckFlags(0, -1);
@@ -596,9 +600,12 @@ openvzDomainShutdownFlags(virDomainPtr dom,
_("no domain with matching uuid"));
goto cleanup;
}
+
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
openvzSetProgramSentinal(prog, vm->def->name);
- if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
+ if (status != VIR_DOMAIN_RUNNING) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain is not in running state"));
goto cleanup;
@@ -631,6 +638,7 @@ static int openvzDomainReboot(virDomainPtr dom,
virDomainObjPtr vm;
const char *prog[] = {VZCTL, "--quiet", "restart", PROGRAM_SENTINAL, NULL};
int ret = -1;
+ int status;
virCheckFlags(0, -1);
@@ -644,8 +652,11 @@ static int openvzDomainReboot(virDomainPtr dom,
goto cleanup;
}
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
+
openvzSetProgramSentinal(prog, vm->def->name);
- if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
+ if (status != VIR_DOMAIN_RUNNING) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain is not in running state"));
goto cleanup;
@@ -1052,6 +1063,7 @@ openvzDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
virDomainObjPtr vm;
const char *prog[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL };
int ret = -1;
+ int status;
virCheckFlags(0, -1);
@@ -1064,8 +1076,11 @@ openvzDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
_("no domain with matching id"));
goto cleanup;
}
+
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
- if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
+ if (status != VIR_DOMAIN_SHUTOFF) {
openvzError(VIR_ERR_OPERATION_DENIED, "%s",
_("domain is not in shutoff state"));
goto cleanup;
@@ -1102,6 +1117,7 @@ openvzDomainUndefineFlags(virDomainPtr dom,
virDomainObjPtr vm;
const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL };
int ret = -1;
+ int status;
virCheckFlags(0, -1);
@@ -1113,7 +1129,10 @@ openvzDomainUndefineFlags(virDomainPtr dom,
goto cleanup;
}
- if (virDomainObjIsActive(vm)) {
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
+
+ if (status != VIR_DOMAIN_SHUTOFF) {
openvzError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot delete active domain"));
goto cleanup;
@@ -1610,6 +1629,47 @@ cleanup:
return -1;
}
+static int
+openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
+{
+ virCommandPtr cmd;
+ char *outbuf;
+ char *line;
+ int state;
+ int ret = -1;
+
+ cmd = virCommandNewArgList(VZLIST, vm->def->name, "-ostatus", "-H", NULL);
+ virCommandSetOutputBuffer(cmd, &outbuf);
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ if ((line = strchr(outbuf, '\n')) == NULL) {
+ openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to parse vzlist output"));
+ goto cleanup;
+ }
+ *line++ = '\0';
+
+ state = virDomainObjGetState(vm, reason);
+
+ if (STREQ(outbuf, "running")) {
+ // There is no way to detect whether a domain is paused or not with vzlist
+ if (state == VIR_DOMAIN_PAUSED)
+ *status = state;
+ else
+ *status = VIR_DOMAIN_RUNNING;
+ } else {
+ *status = VIR_DOMAIN_SHUTOFF;
+ }
+
+ ret = 0;
+
+cleanup:
+ virCommandFree(cmd);
+ VIR_FREE(outbuf);
+ return ret;
+}
+
static virDriver openvzDriver = {
.no = VIR_DRV_OPENVZ,
.name = "OPENVZ",
--
1.7.5.4
13 years, 5 months
[libvirt] [PATCH RFC] virsh: Add option to undefine storage with domains
by Peter Krempa
Adds an option to virsh undefine command to undefine managed
storage volumes along with (inactive) domains. Storage volumes
are enumerated and the user may interactivly choose volumes
to delete.
Unmanaged volumes are listed and the user shall delete them
manualy.
---
I marked this as a RFC because I am concerned about my "naming scheme" of the added parameters.
I couldn't decide which of the following "volumes/storage/disks/..." to use. I'd appreciate your
comments on this.
This is my second approach to this problem after I got some really good critique from Eric,
Daniel and Dave. The user has the choice to activate an interactive mode, that allows to select on a
per-device basis which volumes/disks to remove along with the domain.
To avoid possible problems, I only allowed to remove storage for inactive domains and unmanaged
images (which sidetracked me a lot on my previous attempt) are left to a action of the user.
(the user is notified about any unmanaged image for the domain).
My next concern is about interactive of the user. I tried to implement a boolean query function,
but I'd like to know if I took the right path, as I couldn't find any example in virsh from which I
could learn.
Thanks for your comments (and time) :)
Peter Krempa
tools/virsh.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 259 insertions(+), 6 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 61f69f0..3795d2b 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -295,6 +295,9 @@ static int vshCommandOptULongLong(const vshCmd *cmd, const char *name,
static bool vshCommandOptBool(const vshCmd *cmd, const char *name);
static const vshCmdOpt *vshCommandOptArgv(const vshCmd *cmd,
const vshCmdOpt *opt);
+static int vshInteractiveBoolPrompt(vshControl *ctl,
+ const char *prompt,
+ bool *confirm);
#define VSH_BYID (1 << 1)
#define VSH_BYUUID (1 << 2)
@@ -1422,6 +1425,8 @@ static const vshCmdInfo info_undefine[] = {
static const vshCmdOptDef opts_undefine[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")},
{"managed-save", VSH_OT_BOOL, 0, N_("remove domain managed state file")},
+ {"disks", VSH_OT_BOOL, 0, N_("remove associated disk images managed in storage pools (interactive)")},
+ {"disks-all", VSH_OT_BOOL, 0, N_("remove all associated disk images managed in storage pools")},
{NULL, 0, 0, NULL}
};
@@ -1434,9 +1439,25 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
int id;
int flags = 0;
int managed_save = vshCommandOptBool(cmd, "managed-save");
+ int remove_disks = vshCommandOptBool(cmd, "disks");
+ int remove_all_disks = vshCommandOptBool(cmd, "disks-all");
int has_managed_save = 0;
int rc = -1;
+ char *domxml;
+ xmlDocPtr xml = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlXPathObjectPtr obj = NULL;
+ xmlNodePtr cur = NULL;
+ int i = 0;
+ char *source = NULL;
+ char *target = NULL;
+ char *type = NULL;
+ xmlBufferPtr xml_buf = NULL;
+ virStorageVolPtr volume = NULL;
+ int state;
+ bool confirm = false;
+
if (managed_save)
flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE;
@@ -1475,15 +1496,172 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
}
}
- if (flags == -1) {
- if (has_managed_save == 1) {
+
+ if (flags == -1 && has_managed_save == 1) {
+ vshError(ctl,
+ _("Refusing to undefine while domain managed save "
+ "image exists"));
+ virDomainFree(dom);
+ return false;
+ }
+
+ if (remove_disks || remove_all_disks) {
+ if ((state = vshDomainState(ctl, dom, NULL)) < 0) {
+ vshError(ctl, _("Failed to get domain state"));
+ goto disk_error;
+ }
+
+ /* removal of storage is possible only for inactive domains */
+ if (!((state == VIR_DOMAIN_SHUTOFF) ||
+ (state == VIR_DOMAIN_CRASHED))) {
vshError(ctl,
- _("Refusing to undefine while domain managed save "
- "image exists"));
- virDomainFree(dom);
- return false;
+ _("Domain needs to be inactive to delete it with associated storage"));
+ goto disk_error;
+ }
+
+ if (remove_disks && !ctl->imode) {
+ vshError(ctl, "%s\n", _("Option --disks is available only in interactive mode"));
+ goto disk_error;
+ }
+
+ domxml = virDomainGetXMLDesc(dom, 0);
+ if (!domxml) {
+ vshError(ctl, "%s", _("Failed to get disk information"));
+ goto disk_error;
+ }
+
+ xml = xmlReadDoc((const xmlChar *) domxml, "domain.xml", NULL,
+ XML_PARSE_NOENT |
+ XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ VIR_FREE(domxml);
+
+ if (!xml) {
+ vshError(ctl, "%s", _("Failed to get disk information"));
+ goto disk_error;
+ }
+
+ ctxt = xmlXPathNewContext(xml);
+ if (!ctxt) {
+ vshError(ctl, "%s", _("Failed to get disk information"));
+ goto disk_error;
+ }
+
+ obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+ (obj->nodesetval == NULL)) {
+ vshError(ctl, "%s", _("Failed to get disk information"));
+ goto disk_error;
+ }
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ cur = obj->nodesetval->nodeTab[i]->children;
+
+ type = virXMLPropString(cur, "device");
+
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "target"))
+ target = virXMLPropString(cur, "dev");
+ else if (xmlStrEqual(cur->name, BAD_CAST "source"))
+ source = virXMLPropString(cur, "file");
+ }
+ cur = cur->next;
+ }
+
+ if (!source) {
+ VIR_FREE(target);
+ VIR_FREE(type);
+ }
+
+ volume = virStorageVolLookupByPath(ctl->conn, (const char *) source);
+ if (!volume) {
+ vshPrint(ctl, "%s %s %s %s\n",
+ _("Volume: Source:"), (const char *)source,
+ _("Target:"), (const char *) target);
+ vshPrint(ctl, _("This volume isn't managed by any storage pool, "
+ "please delete it manualy\n\n"));
+ /* remove error indication */
+ virFreeError(last_error);
+ last_error = NULL;
+ } else {
+ vshPrint(ctl, "%s %s %s %s\n",
+ _("Volume: Source:"), (const char *)source,
+ _("Target:"), (const char *) target);
+
+ if (remove_all_disks) {
+ confirm = true;
+ } else {
+ if (vshInteractiveBoolPrompt(ctl,
+ _("Do you want to undefine this volume?"),
+ &confirm) < 0) {
+ vshError(ctl, _("\nError while geting response from user"));
+ virStorageVolFree(volume);
+ goto disk_error;
+ }
+ }
+
+ /* removal of volume */
+ if (confirm) {
+ if (virStorageVolDelete(volume, 0) == 0) {
+ virStorageVolFree(volume);
+
+ vshPrint(ctl, _("Volume deleted\n\n"));
+
+ /* remove definition of volume from xml */
+ xml_buf = xmlBufferCreate();
+ if (!xml_buf) {
+ vshPrint(ctl, _("Failed to create XML buffer. "
+ "If domain undefinition fails, domain will be left in inconsistent state.\n\n"));
+ goto disk_next;
+ }
+
+ if (xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0) {
+ vshPrint(ctl, _("Failed to extract XML volume description. "
+ "If domain undefinition fails, domain will be left in inconsistent state.\n\n"));
+
+ xmlBufferFree(xml_buf);
+ xml_buf = NULL;
+ goto disk_next;
+ }
+
+ if (virDomainDetachDeviceFlags(dom,
+ (char *) xmlBufferContent(xml_buf),
+ VIR_DOMAIN_AFFECT_CONFIG) < 0) {
+ vshPrint(ctl,
+ _("Failed to remove volume \"%s\" from configuration. "
+ "If domain undefinition fails, domain will be left in inconsistent state.\n\n"),
+ source);
+
+ xmlBufferFree(xml_buf);
+ xml_buf = NULL;
+ goto disk_next;
+ }
+
+ xmlBufferFree(xml_buf);
+ xml_buf = NULL;
+
+ } else {
+ virStorageVolFree(volume);
+
+ vshError(ctl, _("Failed to delete volume."));
+ goto disk_error;
+ }
+ }
+ }
+
+disk_next:
+ VIR_FREE(source);
+ VIR_FREE(target);
+ VIR_FREE(type);
}
+ xmlXPathFreeObject(obj);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml);
+ } /* end of disk undefine stuff */
+
+ if (flags == -1) {
rc = virDomainUndefine(dom);
} else {
rc = virDomainUndefineFlags(dom, flags);
@@ -1520,6 +1698,21 @@ end:
virDomainFree(dom);
return ret;
+
+disk_error:
+ VIR_FREE(source);
+ VIR_FREE(target);
+ VIR_FREE(type);
+
+ xmlXPathFreeObject(obj);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml);
+ xmlBufferFree(xml_buf);
+
+ virDomainFree(dom);
+
+ vshError(ctl, _("\nFailed to undefine domain %s"), name);
+ return false;
}
@@ -14736,6 +14929,66 @@ vshReadline (vshControl *ctl, const char *prompt)
#endif /* !USE_READLINE */
+
+/*
+ * Propmpt for boolean question (yes/no)
+ *
+ * Returns "true" on positive answer, "false" on negative
+ * -1 on error.
+ */
+static int
+vshInteractiveBoolPrompt(vshControl *ctl,
+ const char *prompt,
+ bool *confirm) {
+ const char *positive = _("yes");
+ const char *negative = _("no");
+ char *r;
+ char buff[100];
+ int ret = -1;
+ int len;
+ int c;
+
+ if (confirm == NULL)
+ return ret;
+
+ if (!ctl->imode)
+ return ret;
+
+ while (ret == -1) {
+ vshPrint(ctl, "%s (%s/%s)? ", prompt, positive, negative);
+
+ r = fgets(buff, sizeof(buff), stdin);
+ if (r == NULL)
+ break;
+ len = strlen(buff);
+ if (len > 0 && buff[len-1] == '\n')
+ buff[len-1] = '\0';
+ else
+ /* eat rest of line */
+ while ((c = fgetc(stdin) != EOF))
+ if (c == '\n')
+ break;
+
+ /* compare */
+ if (STRCASEEQLEN(buff, positive, strlen(positive))) {
+ ret = 0;
+ *confirm = true;
+ break;
+ }
+
+ if (STRCASEEQLEN(buff, negative, strlen(negative))) {
+ ret = 0;
+ *confirm = false;
+ break;
+ }
+
+ /* errorneus response - warn and ask again*/
+ vshPrint(ctl, "\"%s\" %s\n", buff, _("Response not understood"));
+
+ }
+ return ret;
+}
+
/*
* Deinitialize virsh
*/
--
1.7.6
13 years, 5 months
[libvirt] [PATCH] support qemuMonitorSend() to be called at the same time
by Wen Congyang
Current, we support run sync job and async job at the same time. It means that the
monitor commands for two jobs can be run in any order.
In the function qemuDomainObjEnterMonitorInternal():
if (priv->job.active == QEMU_JOB_NONE && priv->job.asyncJob) {
if (qemuDomainObjBeginNestedJob(driver, obj) < 0)
We check whether the caller is an async job by priv->job.active and
priv->job.asynJob. But when an async job is running, priv->job.active
is QEMU_JOB_NONE if no sync job is running, or priv->job.active is not
QEMU_JOB_NONE if a sync job is running. So we cannot check whether the
caller is an async job in the function qemuDomainObjEnterMonitorInternal().
Unfortunately, if sync job and async job are running at the same time, we may
try to send monitor command at the same time in two threads. It's very
dangerous, and it will cause libvirtd crashed.
We should enhance the function qemuMonitorSend() to support it to be called
at the same time.
If the last monitor command does not finish, the other monitor commands should
wait it to finish.
---
src/qemu/qemu_monitor.c | 22 +++++++++++++++++++++-
1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index db6107c..a10f53f 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -46,6 +46,8 @@ struct _qemuMonitor {
virMutex lock; /* also used to protect fd */
virCond notify;
+ virCond send_notify;
+
int refs;
int fd;
@@ -675,7 +677,8 @@ qemuMonitorOpen(virDomainObjPtr vm,
VIR_FREE(mon);
return NULL;
}
- if (virCondInit(&mon->notify) < 0) {
+ if ((virCondInit(&mon->notify) < 0) ||
+ (virCondInit(&mon->send_notify) < 0)) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize monitor condition"));
virMutexDestroy(&mon->lock);
@@ -795,6 +798,22 @@ int qemuMonitorSend(qemuMonitorPtr mon,
return -1;
}
+ while (mon->msg) {
+ if (virCondWait(&mon->send_notify, &mon->lock) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to wait on monitor condition"));
+ goto cleanup;
+ }
+ }
+
+ /* Check whether qemu quited unexpectedly again */
+ if (mon->lastError.code != VIR_ERR_OK) {
+ VIR_DEBUG("Attempt to send command while error is set %s",
+ NULLSTR(mon->lastError.message));
+ virSetError(&mon->lastError);
+ return -1;
+ }
+
mon->msg = msg;
qemuMonitorUpdateWatch(mon);
@@ -818,6 +837,7 @@ int qemuMonitorSend(qemuMonitorPtr mon,
cleanup:
mon->msg = NULL;
qemuMonitorUpdateWatch(mon);
+ virCondBroadcast(&mon->send_notify);
return ret;
}
--
1.7.1
13 years, 5 months
[libvirt] [PATCH] Correct the default value of lock_manager in qemu.conf
by Guannan Ren
* src/qemu/qemu.conf lock_manager = "sanlock"
---
src/qemu/qemu.conf | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 8058352..79c6e85 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -304,9 +304,8 @@
#
# max_processes = 0
-# To enable strict 'fcntl' based locking of the file
+# To enable 'Sanlock' project based locking of the file
# content (to prevent two VMs writing to the same
-# disk), start the 'virtlockd' service, and uncomment
-# this
+# disk), uncomment this
#
-# lock_manager = "fcntl"
+# lock_manager = "sanlock"
--
1.7.1
13 years, 5 months
[libvirt] ANNOUNCE: Guest filesystem browser (guestfs-browser) 0.2.1 released
by Richard W.M. Jones
The guest filesystem browser lets you browse guest filesystems, the
Windows Registry, and other bits from guests.
You can see some screenshots here:
https://rwmj.wordpress.com/2011/07/29/some-screenshots-from-the-new-guest...
The 0.2.1 release includes lots of new functionality, including:
- looking at inspection data, applications, drive mappings and more
- looking at detailed file information, extended attrs
- ability to view arbitrary disk images
The home page is here:
http://people.redhat.com/~rjones/guestfs-browser/
I have pushed relatively recent builds into Fedora 15, Fedora 16 and
Rawhide. For F15 and F16 you'll need to get the latest from
updates-testing:
https://admin.fedoraproject.org/updates/search/guestfs-browser
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
New in Fedora 11: Fedora Windows cross-compiler. Compile Windows
programs, test, and build Windows installers. Over 70 libraries supprt'd
http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw
13 years, 5 months