[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, 2 months
[libvirt] [Libvirt] [PATCH v3] Fix bug #611823 prohibit pools with duplicate storage
by Lei Li
Make sure the unique storage pool defined and create from different
directory to avoid inconsistent version of volume pool created.
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
src/conf/storage_conf.c | 25 +++++++++++++++++++++++++
src/conf/storage_conf.h | 2 ++
src/libvirt_private.syms | 1 +
3 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 995f9a6..1d9fe25 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1317,6 +1317,21 @@ 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)
{
@@ -1700,6 +1715,16 @@ int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
}
}
+ /* Check the 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);
+ dupPool = -1;
+ goto cleanup;
+ }
+
ret = dupPool;
cleanup:
if (pool)
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 271441a..9239977 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);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 830222b..19f5f92 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -937,6 +937,7 @@ virStoragePoolObjClearVols;
virStoragePoolObjDeleteDef;
virStoragePoolObjFindByName;
virStoragePoolObjFindByUUID;
+virStoragePoolObjFindByPath;
virStoragePoolObjIsDuplicate;
virStoragePoolObjListFree;
virStoragePoolObjLock;
--
1.7.1
13 years, 2 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, 2 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, 2 months
[libvirt] [PATCH] virsh: fix memory leak in cmdNetworkInfo
by ajia@redhat.com
I have ever discussed this issue with Matthias, and he has fixed this leak in
cmdNetworkInfo codes, but he hasn't committed a patch to upstream so that
bug 722806 is always assigned status, so commit it to avoid this patch missing.
* tools/virsh.c: avoid memory leak in cmdNetworkInfo.
* how to reproduce?
% valgrind -v --leak-check=yes virsh net-info default
https://bugzilla.redhat.com/show_bug.cgi?id=722806
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
tools/virsh.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 23e71d7..cf8e2a5 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -5597,6 +5597,7 @@ cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd)
if (bridge)
vshPrint(ctl, "%-15s %s\n", _("Bridge:"), bridge);
+ VIR_FREE(bridge);
virNetworkFree(network);
return true;
}
--
1.7.1
13 years, 2 months
[libvirt] [PATCH] doc: fix incorrect option in blockjob
by ajia@redhat.com
* tools/virsh.pod: change 'live' to 'abort' based on actual option.
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
tools/virsh.pod | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index f6f9908..01b8fd6 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -445,7 +445,7 @@ I<bandwidth> specifies copying bandwidth limit in Mbps.
Manage active block operations.
I<path> specifies fully-qualified path of the disk.
-If I<--live> is specified, the active job on the specified disk will
+If I<--abort> is specified, the active job on the specified disk will
be aborted.
If I<--info> is specified, the active job information on the specified
disk will be printed.
--
1.7.1
13 years, 2 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, 2 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, 2 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, 2 months
[libvirt] [PATCH] daemon: Unlink unix socket paths on shutdown
by Osier Yang
This patch introduces a internal RPC API "virNetServerClose", which
is standalone with "virNetServerFree". it closes all the socket fds,
and unlinks the unix socket paths, regardless of whether the socket
is still referenced or not.
This is to address regression bug:
https://bugzilla.redhat.com/show_bug.cgi?id=725702
---
daemon/libvirtd.c | 1 +
src/rpc/virnetserver.c | 12 ++++++++++++
src/rpc/virnetserver.h | 1 +
src/rpc/virnetserverservice.c | 12 ++++++++++++
src/rpc/virnetserverservice.h | 2 ++
src/rpc/virnetsocket.c | 16 ++++++++++++++++
src/rpc/virnetsocket.h | 2 ++
7 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 9e044e2..53f1002 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1558,6 +1558,7 @@ int main(int argc, char **argv) {
cleanup:
virNetServerProgramFree(remoteProgram);
virNetServerProgramFree(qemuProgram);
+ virNetServerClose(srv);
virNetServerFree(srv);
if (statuswrite != -1) {
if (ret != 0) {
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 2dae2ff..d2a6fef 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -794,3 +794,15 @@ void virNetServerFree(virNetServerPtr srv)
virMutexDestroy(&srv->lock);
VIR_FREE(srv);
}
+
+void virNetServerClose(virNetServerPtr srv)
+{
+ int i;
+
+ if (!srv)
+ return;
+
+ for (i = 0; i < srv->nservices; i++) {
+ virNetServerServiceClose(srv->services[i]);
+ }
+}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 810d8a3..324cfb7 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -85,5 +85,6 @@ void virNetServerQuit(virNetServerPtr srv);
void virNetServerFree(virNetServerPtr srv);
+void virNetServerClose(virNetServerPtr srv);
#endif
diff --git a/src/rpc/virnetserverservice.c b/src/rpc/virnetserverservice.c
index d5648dc..8c9ed1e 100644
--- a/src/rpc/virnetserverservice.c
+++ b/src/rpc/virnetserverservice.c
@@ -280,3 +280,15 @@ void virNetServerServiceToggle(virNetServerServicePtr svc,
VIR_EVENT_HANDLE_READABLE :
0);
}
+
+void virNetServerServiceClose(virNetServerServicePtr svc)
+{
+ int i;
+
+ if (!svc)
+ return;
+
+ for (i = 0; i < svc->nsocks; i++) {
+ virNetSocketClose(svc->socks[i]);
+ }
+}
diff --git a/src/rpc/virnetserverservice.h b/src/rpc/virnetserverservice.h
index 9357598..8540bd9 100644
--- a/src/rpc/virnetserverservice.h
+++ b/src/rpc/virnetserverservice.h
@@ -66,4 +66,6 @@ void virNetServerServiceFree(virNetServerServicePtr svc);
void virNetServerServiceToggle(virNetServerServicePtr svc,
bool enabled);
+void virNetServerServiceClose(virNetServerServicePtr svc);
+
#endif
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 41b691a..b94b629 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -1222,3 +1222,19 @@ void virNetSocketRemoveIOCallback(virNetSocketPtr sock)
virMutexUnlock(&sock->lock);
}
+
+void virNetSocketClose(virNetSocketPtr sock)
+{
+ if (!sock)
+ return;
+
+ VIR_FORCE_CLOSE(sock->fd);
+
+#ifdef HAVE_SYS_UN_H
+ /* If a server socket, then unlink UNIX path */
+ if (!sock->client &&
+ sock->localAddr.data.sa.sa_family == AF_UNIX &&
+ sock->localAddr.data.un.sun_path[0] != '\0')
+ unlink(sock->localAddr.data.un.sun_path);
+#endif
+}
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index dfb3c5d..3735a88 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -118,6 +118,8 @@ void virNetSocketUpdateIOCallback(virNetSocketPtr sock,
void virNetSocketRemoveIOCallback(virNetSocketPtr sock);
+void virNetSocketClose(virNetSocketPtr sock);
+
#endif /* __VIR_NET_SOCKET_H__ */
--
1.7.6
13 years, 2 months