[libvirt] [PATCH] XenXs: Update documentation
by Philipp Hahn
Fix several references to now renamed functions and parameters when the
functions were moved from src/xen/ to src/xenxs/.
Signed-off-by: Philipp Hahn <hahn(a)univention.de>
---
src/xenxs/xen_sxpr.c | 222 +++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 185 insertions(+), 37 deletions(-)
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
index 09e7730..03a0eb1 100644
--- a/src/xenxs/xen_sxpr.c
+++ b/src/xenxs/xen_sxpr.c
@@ -37,7 +37,7 @@
#include "xenxs_private.h"
#include "xen_sxpr.h"
-/* Get a domain id from a sexpr string */
+/* Get a domain id from a S-expression string */
int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion)
{
struct sexpr *root = string2sexpr(sexpr);
@@ -50,7 +50,7 @@ int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion)
return id;
}
-/* Get a domain id from a sexpr */
+/* Get a domain id from a S-expression */
int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion)
{
int id = -1;
@@ -66,16 +66,15 @@ int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion)
/*****************************************************************
******
- ****** Parsing of SEXPR into virDomainDef objects
+ ****** Parsing of S-Expression into virDomainDef objects
******
*****************************************************************/
/**
- * xenParseSxprOS
+ * xenParseSxprOS:
* @node: the root of the parsed S-Expression
* @def: the domain config
- * @hvm: true or 1 if no contains HVM S-Expression
- * @bootloader: true or 1 if a bootloader is defined
+ * @hvm: true or 1 if node contains HVM S-Expression
*
* Parse the xend sexp for description of os and append it to buf.
*
@@ -166,6 +165,16 @@ no_memory:
return -1;
}
+
+/**
+ * xenParseSxprChar:
+ * @value: A string describing a character device.
+ * @tty: the console pty path
+ *
+ * Parse the xend S-expression for description of a character device.
+ *
+ * Returns a character device object or NULL in case of failure.
+ */
virDomainChrDefPtr
xenParseSxprChar(const char *value,
const char *tty)
@@ -316,13 +325,15 @@ error:
return NULL;
}
+
/**
- * xend_parse_sexp_desc_disks
- * @conn: connection
- * @root: root sexpr
+ * xenParseSxprDisks:
+ * @def: the domain config
+ * @root: root S-expression
+ * @hvm: true or 1 if node contains HVM S-Expression
* @xendConfigVersion: version of xend
*
- * This parses out block devices from the domain sexpr
+ * This parses out block devices from the domain S-expression
*
* Returns 0 if successful or -1 if failed.
*/
@@ -518,6 +529,15 @@ error:
}
+/**
+ * xenParseSxprNets:
+ * @def: the domain config
+ * @root: root S-expression
+ *
+ * This parses out network devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
static int
xenParseSxprNets(virDomainDefPtr def,
const struct sexpr *root)
@@ -614,6 +634,15 @@ cleanup:
}
+/**
+ * xenParseSxprSound:
+ * @def: the domain config
+ * @str: comma separated list of sound models
+ *
+ * This parses out sound devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
int
xenParseSxprSound(virDomainDefPtr def,
const char *str)
@@ -692,6 +721,15 @@ error:
}
+/**
+ * xenParseSxprUSB:
+ * @def: the domain config
+ * @root: root S-expression
+ *
+ * This parses out USB devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
static int
xenParseSxprUSB(virDomainDefPtr def,
const struct sexpr *root)
@@ -733,6 +771,19 @@ no_memory:
return -1;
}
+
+/*
+ * xenParseSxprGraphicsOld:
+ * @def: the domain config
+ * @root: root S-expression
+ * @hvm: true or 1 if root contains HVM S-Expression
+ * @xendConfigVersion: version of xend
+ * @vncport: VNC port number
+ *
+ * This parses out VNC devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
static int
xenParseSxprGraphicsOld(virDomainDefPtr def,
const struct sexpr *root,
@@ -821,6 +872,16 @@ error:
}
+/*
+ * xenParseSxprGraphicsNew:
+ * @def: the domain config
+ * @root: root S-expression
+ * @vncport: VNC port number
+ *
+ * This parses out VNC devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
static int
xenParseSxprGraphicsNew(virDomainDefPtr def,
const struct sexpr *root, int vncport)
@@ -918,11 +979,13 @@ error:
return -1;
}
+
/**
- * xenParseSxprPCI
+ * xenParseSxprPCI:
+ * @def: the domain config
* @root: root sexpr
*
- * This parses out block devices from the domain sexpr
+ * This parses out PCI devices from the domain sexpr
*
* Returns 0 if successful or -1 if failed.
*/
@@ -1044,16 +1107,17 @@ error:
/**
* xenParseSxpr:
- * @conn: the connection associated with the XML
* @root: the root of the parsed S-Expression
* @xendConfigVersion: version of xend
* @cpus: set of cpus the domain may be pinned to
+ * @tty: the console pty path
+ * @vncport: VNC port number
*
- * Parse the xend sexp description and turn it into the XML format similar
- * to the one unsed for creation.
+ * Parse the xend S-expression description and turn it into a virDomainDefPtr
+ * representing these settings as closeley as is practical.
*
- * Returns the 0 terminated XML string or NULL in case of error.
- * the caller must free() the returned value.
+ * Returns the domain config or NULL in case of error.
+ * The caller must free() the returned value.
*/
virDomainDefPtr
xenParseSxpr(const struct sexpr *root,
@@ -1424,6 +1488,20 @@ error:
return NULL;
}
+
+/**
+ * xenParseSxprString:
+ * @sexpr: the root of the parsed S-Expression
+ * @xendConfigVersion: version of xend
+ * @tty: the console pty path
+ * @vncport: VNC port number
+ *
+ * Parse the xend S-expression description and turn it into a virDomainDefPtr
+ * representing these settings as closeley as is practical.
+ *
+ * Returns the domain config or NULL in case of error.
+ * The caller must free() the returned value.
+ */
virDomainDefPtr
xenParseSxprString(const char *sexpr,
int xendConfigVersion, char *tty, int vncport)
@@ -1449,15 +1527,12 @@ xenParseSxprString(const char *sexpr,
/**
- * virtDomainParseXMLGraphicsDescVFB:
- * @conn: pointer to the hypervisor connection
- * @node: node containing graphics description
- * @buf: a buffer for the result S-Expr
+ * xenFormatSxprGraphicsNew:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
*
- * Parse the graphics part of the XML description and add it to the S-Expr
- * in buf. This is a temporary interface as the S-Expr interface will be
- * replaced by XML-RPC in the future. However the XML format should stay
- * valid over time.
+ * Convert the graphics part of the domain description into a S-expression
+ * in buf. (HVM > 3.0.4 or PV > 3.0.3)
*
* Returns 0 in case of success, -1 in case of error
*/
@@ -1508,6 +1583,17 @@ xenFormatSxprGraphicsNew(virDomainGraphicsDefPtr def,
}
+/**
+ * xenFormatSxprGraphicsOld:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ * @xendConfigVersion: version of xend
+ *
+ * Convert the graphics part of the domain description into a S-expression
+ * in buf. (HVM <= 3.0.4 or PV <= 3.0.3)
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
static int
xenFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
virBufferPtr buf,
@@ -1553,6 +1639,17 @@ xenFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
return 0;
}
+
+/**
+ * xenFormatSxprChr:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert the character deivce part of the domain config into a S-expression
+ * in buf.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
int
xenFormatSxprChr(virDomainChrDefPtr def,
virBufferPtr buf)
@@ -1631,15 +1728,14 @@ xenFormatSxprChr(virDomainChrDefPtr def,
/**
- * virDomainParseXMLDiskDesc:
- * @node: node containing disk description
- * @buf: a buffer for the result S-Expr
+ * xenFormatSxprDisk:
+ * @node: node containing the disk description
+ * @buf: a buffer for the result S-expression
+ * @hvm: true or 1 if domain is HVM
* @xendConfigVersion: xend configuration file format
+ * @isAttach: create expression for device attach (1).
*
- * Parse the one disk in the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
+ * Convert the disk device part of the domain config into a S-expresssion in buf.
*
* Returns 0 in case of success, -1 in case of error.
*/
@@ -1757,12 +1853,15 @@ xenFormatSxprDisk(virDomainDiskDefPtr def,
}
/**
- * xenFormatSxprNet
- * @node: node containing the interface description
- * @buf: a buffer for the result S-Expr
+ * xenFormatSxprNet:
+ * @conn: connection
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ * @hvm: true or 1 if domain is HVM
* @xendConfigVersion: xend configuration file format
+ * @isAttach: create expression for device attach (1).
*
- * Parse the one interface the XML description and add it to the S-Expr in buf
+ * Convert the interface description of the domain config into a S-expression in buf.
* This is a temporary interface as the S-Expr interface
* will be replaced by XML-RPC in the future. However the XML format should
* stay valid over time.
@@ -1893,6 +1992,15 @@ xenFormatSxprNet(virConnectPtr conn,
}
+/**
+ * xenFormatSxprPCI:
+ * @def: the device config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert a single PCI device part of the domain config into a S-expresssion in buf.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
static void
xenFormatSxprPCI(virDomainHostdevDefPtr def,
virBufferPtr buf)
@@ -1904,6 +2012,17 @@ xenFormatSxprPCI(virDomainHostdevDefPtr def,
def->source.subsys.u.pci.function);
}
+
+/**
+ * xenFormatSxprOnePCI:
+ * @def: the device config
+ * @buf: a buffer for the result S-expression
+ * @detach: create expression for device detach (1).
+ *
+ * Convert a single PCI device part of the domain config into a S-expresssion in buf.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
int
xenFormatSxprOnePCI(virDomainHostdevDefPtr def,
virBufferPtr buf,
@@ -1926,6 +2045,16 @@ xenFormatSxprOnePCI(virDomainHostdevDefPtr def,
return 0;
}
+
+/**
+ * xenFormatSxprAllPCI:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert all PCI device parts of the domain config into a S-expresssion in buf.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
static int
xenFormatSxprAllPCI(virDomainDefPtr def,
virBufferPtr buf)
@@ -1973,6 +2102,16 @@ xenFormatSxprAllPCI(virDomainDefPtr def,
return 0;
}
+
+/**
+ * xenFormatSxprSound:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert all sound device parts of the domain config into S-expression in buf.
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
int
xenFormatSxprSound(virDomainDefPtr def,
virBufferPtr buf)
@@ -2001,6 +2140,15 @@ xenFormatSxprSound(virDomainDefPtr def,
}
+/**
+ * xenFormatSxprInput:
+ * @input: the input config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert all input device parts of the domain config into S-expression in buf.
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
static int
xenFormatSxprInput(virDomainInputDefPtr input,
virBufferPtr buf)
@@ -2033,7 +2181,7 @@ verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
* @def: domain config definition
* @xendConfigVersion: xend configuration file format
*
- * Generate an SEXPR representing the domain configuration.
+ * Generate an S-expression representing the domain configuration.
*
* Returns the 0 terminated S-Expr string or NULL in case of error.
* the caller must free() the returned value.
--
1.7.1
12 years, 9 months
[libvirt] [PATCH RFC 0/4] Allow hibernation on guests
by Michal Privoznik
As we've added guest agent recently, the whole world
of new functionality has opened. As this patch set,
which allows domains to enter S4 state.
What is needed for this?
Patched qemu. As this is not in qemu git, but patches
are await to be pushed in very short future. They can
be found here:
http://lists.gnu.org/archive/html/qemu-devel/2012-01/msg03261.html
Despite that, if anybody is willing to give me review
if I am going the right way, I'd appreciate it.
One thing, that you'll probably notice is this
'set-support-level' command. Basically, it tells GA what qemu version
is it running on. Ideally, this should be done as soon as
GA starts up. However, that cannot be determined from outside
world as GA doesn't emit any events yet.
Ideally^2 this command should be left out as it should be qemu
who tells its own agent this kind of information.
Anyway, I was going to call this command in qemuProcess{Startup,
Reconnect,Attach}, but it won't work. We need to un-pause guest CPUs
so guest can boot and start GA, but that implies returning from qemuProcess*.
So I am setting this just before 'guest-suspend' command, as
there is one more thing about GA. It is unable to remember anything
upon its restart (GA process). Which has BTW show flaw
in our current code with FS freeze & thaw. If we freeze guest
FS, and somebody restart GA, the simple FS Thaw will not succeed as
GA thinks FS are not frozen. But that's a different cup of tea.
Because of what written above, we need to call set-level
on every suspend.
Michal Privoznik (4):
qemu-agent: Allow setting supported level
qemu-agent: Create suspend function
Create new virDrvDomainSuspendFlags API
Wire up qemu agent for suspend
include/libvirt/libvirt.h.in | 8 +++
src/driver.h | 4 ++
src/libvirt.c | 55 ++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/qemu/qemu_agent.c | 105 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 13 +++++
src/qemu/qemu_driver.c | 57 +++++++++++++++++++---
src/qemu/qemu_process.c | 45 +++++++++++++++++-
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 9 +++-
src/remote_protocol-structs | 5 ++
tools/virsh.c | 30 ++++++++++--
12 files changed, 317 insertions(+), 16 deletions(-)
--
1.7.3.4
12 years, 9 months
[libvirt] [PATCHv2] simplify block of codes
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
Using new function 'virTypedParameterArrayClear' to simplify block of codes.
* daemon/remote.c, src/remote/remote_driver.c: simplify codes.
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
daemon/remote.c | 6 +-----
src/remote/remote_driver.c | 16 ++++------------
2 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index cb8423a..e7d9b2f 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -848,11 +848,7 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
cleanup:
if (rv < 0) {
- int j;
- for (j = 0; j < i; ++j) {
- if (params[j].type == VIR_TYPED_PARAM_STRING)
- VIR_FREE(params[j].value.s);
- }
+ virTypedParameterArrayClear(params, i);
VIR_FREE(params);
}
return params;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 61b96e9..15a20ff 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -46,6 +46,7 @@
#include "virfile.h"
#include "command.h"
#include "intprops.h"
+#include "virtypedparam.h"
#define VIR_FROM_THIS VIR_FROM_REMOTE
@@ -1417,12 +1418,8 @@ remoteDeserializeTypedParameters(remote_typed_param *ret_params_val,
rv = 0;
cleanup:
- if (rv < 0) {
- int j;
- for (j = 0; j < i; j++)
- if (params[j].type == VIR_TYPED_PARAM_STRING)
- VIR_FREE(params[j].value.s);
- }
+ if (rv < 0)
+ virTypedParameterArrayClear(params, *nparams);
return rv;
}
@@ -2386,12 +2383,7 @@ static int remoteDomainGetCPUStats(virDomainPtr domain,
cleanup:
if (rv < 0) {
int max = nparams * ncpus;
- int i;
-
- for (i = 0; i < max; i++) {
- if (params[i].type == VIR_TYPED_PARAM_STRING)
- VIR_FREE(params[i].value.s);
- }
+ virTypedParameterArrayClear(params, max);
}
xdr_free ((xdrproc_t) xdr_remote_domain_get_cpu_stats_ret,
(char *) &ret);
--
1.7.1
12 years, 9 months
[libvirt] [PATCH 0/6] qemu: add suport for "romfile", and associated cleanups
by Laine Stump
This patchset started out as cleanup to make it easier to add in
support for doing PCI passthrough via the <interface> element (to be
used to attach a host network device to a guest after performing some
network-device-specific setup), but turned out to also make it much
easier to add support for QEMU's "romfile" option, as requested in
https://bugzilla.redhat.com/show_bug.cgi?id=781562
Patch 1 is trivial, and probably qualifies for pushing under the
trivial rule, but it's just as easy to leave it in with the
rest. Patches 2-4 reorganize some data definitions, and the code
associated with them, with no functional change. Patch 5 expands
support for "rombar" to network devices (as long as they attach to the
guest PCI bus), and Patch 6 adds support for "romfile" to both generic
PCI devices and network devices.
12 years, 9 months
[libvirt] Segfault fixed
by Hendrik Schwartke
Hi,
there is a segfault in qemu_monitor_text.c. If some error accurs in
qemuMonitorTextGetBlockInfo then the cleanup code calls VIR_FREE(info)
without ensuring that info is initialized.
Patch based on c6ec021b3c19c3ecc97d60d35b12eaa0b94da701:
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index a33d192..fb3309b 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -774,7 +774,7 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
virHashTablePtr table)
{
- struct qemuDomainDiskInfo *info;
+ struct qemuDomainDiskInfo *info=NULL;
char *reply = NULL;
int ret = -1;
char *dummy;
12 years, 9 months
[libvirt] [PATCH] xen: Don't add <console> to xml for dom0
by Cole Robinson
It just doesn't really make sense and confuses virt-manager
---
src/xenxs/xen_sxpr.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
index 7a53f94..09e7730 100644
--- a/src/xenxs/xen_sxpr.c
+++ b/src/xenxs/xen_sxpr.c
@@ -1392,7 +1392,7 @@ xenParseSxpr(const struct sexpr *root,
chr->target.port = 0;
def->parallels[def->nparallels++] = chr;
}
- } else {
+ } else if (def->id != 0) {
def->nconsoles = 1;
if (VIR_ALLOC_N(def->consoles, 1) < 0)
goto no_memory;
--
1.7.7.5
12 years, 9 months
[libvirt] [PATCH] Add virt-host-validate.1 to Mingw32 RPM spec file list
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Pushed under trivial rule
---
mingw32-libvirt.spec.in | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/mingw32-libvirt.spec.in b/mingw32-libvirt.spec.in
index 961c3ba..7937e22 100644
--- a/mingw32-libvirt.spec.in
+++ b/mingw32-libvirt.spec.in
@@ -185,6 +185,7 @@ rm -rf $RPM_BUILD_ROOT
%{_mingw32_mandir}/man1/virsh.1*
%{_mingw32_mandir}/man1/virt-xml-validate.1*
%{_mingw32_mandir}/man1/virt-pki-validate.1*
+%{_mingw32_mandir}/man1/virt-host-validate.1*
%changelog
--
1.7.7.6
12 years, 9 months
[libvirt] [libvirt-glib] Add virStorageVolResize()
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
Add a new function to allow changing of capacity of storage volumes.
---
include/libvirt/libvirt.h.in | 5 ++
src/driver.h | 5 ++
src/libvirt.c | 50 ++++++++++++++++++
src/libvirt_public.syms | 1 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 9 +++-
src/remote_protocol-structs | 6 ++
src/storage/storage_backend.h | 6 ++
src/storage/storage_backend_fs.c | 18 +++++++
src/storage/storage_driver.c | 83 ++++++++++++++++++++++++++++++
src/util/storage_file.c | 105 ++++++++++++++++++++++++++++++++++++++
src/util/storage_file.h | 4 ++
tools/virsh.c | 53 +++++++++++++++++++
13 files changed, 345 insertions(+), 1 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index e99cd00..b169592 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2386,6 +2386,11 @@ char * virStorageVolGetXMLDesc (virStorageVolPtr pool,
char * virStorageVolGetPath (virStorageVolPtr vol);
+int virStorageVolResize (virStorageVolPtr vol,
+ unsigned long long capacity,
+ unsigned int flags);
+
+
/**
* virKeycodeSet:
*
diff --git a/src/driver.h b/src/driver.h
index df2aa60..c850926 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1261,6 +1261,10 @@ typedef int
unsigned long long offset,
unsigned long long length,
unsigned int flags);
+typedef int
+ (*virDrvStorageVolResize) (virStorageVolPtr vol,
+ unsigned long long capacity,
+ unsigned int flags);
typedef int
(*virDrvStoragePoolIsActive)(virStoragePoolPtr pool);
@@ -1323,6 +1327,7 @@ struct _virStorageDriver {
virDrvStorageVolGetInfo volGetInfo;
virDrvStorageVolGetXMLDesc volGetXMLDesc;
virDrvStorageVolGetPath volGetPath;
+ virDrvStorageVolResize volResize;
virDrvStoragePoolIsActive poolIsActive;
virDrvStoragePoolIsPersistent poolIsPersistent;
};
diff --git a/src/libvirt.c b/src/libvirt.c
index e9d638b..44865e8 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -12927,6 +12927,56 @@ error:
return NULL;
}
+/**
+ * virStorageVolResize:
+ * @vol: pointer to storage volume
+ * @capacity: new capacity
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Changes the capacity of the storage volume @vol to @capacity. The new
+ * capacity must not exceed the sum of current capacity of the volume and
+ * remainining free space of its parent pool. Also the new capacity must
+ * be greater than or equal to current allocation of the volume.
+ *
+ * Returns 0 on success, or -1 on error.
+ */
+int
+virStorageVolResize(virStorageVolPtr vol,
+ unsigned long long capacity,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ VIR_DEBUG("vol=%p", vol);
+
+ virResetLastError();
+
+ if (!VIR_IS_STORAGE_VOL(vol)) {
+ virLibStorageVolError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = vol->conn;
+
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->storageDriver && conn->storageDriver->volResize) {
+ int ret;
+ ret = conn->storageDriver->volResize(vol, capacity, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(vol->conn);
+ return -1;
+}
/**
* virNodeNumOfDevices:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 1340b0c..67c113e 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -520,6 +520,7 @@ LIBVIRT_0.9.10 {
global:
virDomainShutdownFlags;
virStorageVolWipePattern;
+ virStorageVolResize;
} LIBVIRT_0.9.9;
# .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index f79f53e..2bb4cbf 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -4837,6 +4837,7 @@ static virStorageDriver storage_driver = {
.volGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */
.volGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */
.volGetPath = remoteStorageVolGetPath, /* 0.4.1 */
+ .volResize = remoteStorageVolResize, /* 0.9.10 */
.poolIsActive = remoteStoragePoolIsActive, /* 0.7.3 */
.poolIsPersistent = remoteStoragePoolIsPersistent, /* 0.7.3 */
};
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 0f354bb..29f98fc 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -1676,6 +1676,12 @@ struct remote_storage_vol_get_path_ret {
remote_nonnull_string name;
};
+struct remote_storage_vol_resize_args {
+ remote_nonnull_storage_vol vol;
+ unsigned hyper capacity;
+ unsigned int flags;
+};
+
/* Node driver calls: */
struct remote_node_num_of_devices_args {
@@ -2667,7 +2673,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258, /* autogen autogen */
- REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259 /* autogen autogen */
+ REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259, /* autogen autogen */
+ REMOTE_PROC_STORAGE_VOL_RESIZE = 300 /* autogen autogen */
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index de85862..9a60fc2 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1260,6 +1260,11 @@ struct remote_storage_vol_get_path_args {
struct remote_storage_vol_get_path_ret {
remote_nonnull_string name;
};
+struct remote_storage_vol_resize_args {
+ remote_nonnull_storage_vol vol;
+ uint64_t capacity;
+ u_int flags;
+};
struct remote_node_num_of_devices_args {
remote_string cap;
u_int flags;
@@ -2101,4 +2106,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257,
REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258,
REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259,
+ REMOTE_PROC_STORAGE_VOL_RESIZE = 300,
};
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index 75ed676..a37bf7c 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -44,6 +44,11 @@ typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjP
typedef int (*virStorageBackendBuildVolFrom)(virConnectPtr conn, virStoragePoolObjPtr pool,
virStorageVolDefPtr origvol, virStorageVolDefPtr newvol,
unsigned int flags);
+typedef int (*virStorageBackendVolumeResize)(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags);
/* File creation/cloning functions used for cloning between backends */
int virStorageBackendCreateRaw(virConnectPtr conn,
@@ -78,6 +83,7 @@ struct _virStorageBackend {
virStorageBackendCreateVol createVol;
virStorageBackendRefreshVol refreshVol;
virStorageBackendDeleteVol deleteVol;
+ virStorageBackendVolumeResize resizeVol;
};
virStorageBackendPtr virStorageBackendForType(int type);
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index d8dc29c..20f5534 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1187,6 +1187,21 @@ virStorageBackendFileSystemVolRefresh(virConnectPtr conn,
return 0;
}
+/**
+ * Resize a volume
+ */
+static int
+virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ return virStorageFileResize(vol->target.path,
+ vol->target.format,
+ capacity);
+}
+
virStorageBackend virStorageBackendDirectory = {
.type = VIR_STORAGE_POOL_DIR,
@@ -1199,6 +1214,7 @@ virStorageBackend virStorageBackendDirectory = {
.createVol = virStorageBackendFileSystemVolCreate,
.refreshVol = virStorageBackendFileSystemVolRefresh,
.deleteVol = virStorageBackendFileSystemVolDelete,
+ .resizeVol = virStorageBackendFileSystemVolResize,
};
#if WITH_STORAGE_FS
@@ -1216,6 +1232,7 @@ virStorageBackend virStorageBackendFileSystem = {
.createVol = virStorageBackendFileSystemVolCreate,
.refreshVol = virStorageBackendFileSystemVolRefresh,
.deleteVol = virStorageBackendFileSystemVolDelete,
+ .resizeVol = virStorageBackendFileSystemVolResize,
};
virStorageBackend virStorageBackendNetFileSystem = {
.type = VIR_STORAGE_POOL_NETFS,
@@ -1232,5 +1249,6 @@ virStorageBackend virStorageBackendNetFileSystem = {
.createVol = virStorageBackendFileSystemVolCreate,
.refreshVol = virStorageBackendFileSystemVolRefresh,
.deleteVol = virStorageBackendFileSystemVolDelete,
+ .resizeVol = virStorageBackendFileSystemVolResize,
};
#endif /* WITH_STORAGE_FS */
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index a332ada..d3eff93 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1695,7 +1695,89 @@ out:
return ret;
}
+static int
+storageVolumeResize(virStorageVolPtr obj,
+ unsigned long long capacity,
+ unsigned int flags)
+{
+ virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
+ virStorageBackendPtr backend;
+ virStoragePoolObjPtr pool = NULL;
+ virStorageVolDefPtr vol = NULL;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ storageDriverLock(driver);
+ pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
+ storageDriverUnlock(driver);
+ if (!pool) {
+ virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
+ "%s", _("no storage pool with matching uuid"));
+ goto out;
+ }
+
+ if (!virStoragePoolObjIsActive(pool)) {
+ virStorageReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("storage pool is not active"));
+ goto out;
+ }
+
+ if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
+ goto out;
+
+ vol = virStorageVolDefFindByName(pool, obj->name);
+
+ if (vol == NULL) {
+ virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
+ _("no storage vol with matching name '%s'"),
+ obj->name);
+ goto out;
+ }
+
+ if (vol->building) {
+ virStorageReportError(VIR_ERR_OPERATION_INVALID,
+ _("volume '%s' is still being allocated."),
+ vol->name);
+ goto out;
+ }
+
+ if (capacity < vol->allocation) {
+ virStorageReportError(VIR_ERR_INVALID_ARG,
+ "%s", _("can not shrink capacity below "
+ "existing allocation"));
+
+ goto out;
+ }
+
+ if (capacity > vol->allocation + pool->def->available) {
+ virStorageReportError(VIR_ERR_INVALID_ARG,
+ "%s", _("Not enough space left on storage pool"));
+
+ goto out;
+ }
+
+ if (!backend->resizeVol) {
+ virStorageReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("storage pool does not support changing "
+ "of volume capacity"));
+
+ goto out;
+ }
+
+ if (backend->resizeVol(obj->conn, pool, vol, capacity, flags) < 0)
+ goto out;
+
+ vol->capacity = capacity;
+ ret = 0;
+
+out:
+ if (pool)
+ virStoragePoolObjUnlock(pool);
+
+ return ret;
+}
/* If the volume we're wiping is already a sparse file, we simply
* truncate and extend it to its original size, filling it with
@@ -2243,6 +2325,7 @@ static virStorageDriver storageDriver = {
.volGetInfo = storageVolumeGetInfo, /* 0.4.0 */
.volGetXMLDesc = storageVolumeGetXMLDesc, /* 0.4.0 */
.volGetPath = storageVolumeGetPath, /* 0.4.0 */
+ .volResize = storageVolumeResize, /* 0.9.10 */
.poolIsActive = storagePoolIsActive, /* 0.7.3 */
.poolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index ba9cfc5..f84feab 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -931,6 +931,111 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta)
VIR_FREE(meta);
}
+static int
+virStorageFileResizeForFD(const char *path,
+ int fd,
+ int format,
+ unsigned long long capacity)
+{
+ unsigned char *head = NULL;
+ ssize_t len = STORAGE_MAX_HEAD;
+ int ret = -1;
+ struct stat sb;
+
+ if (fstat(fd, &sb) < 0) {
+ virReportSystemError(errno,
+ _("cannot stat file '%s'"),
+ path);
+ return -1;
+ }
+
+ /* No header to probe for directories */
+ if (S_ISDIR(sb.st_mode)) {
+ return 0;
+ }
+
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
+ virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
+ return -1;
+ }
+
+ if (VIR_ALLOC_N(head, len) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if ((len = read(fd, head, len)) < 0) {
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
+ goto cleanup;
+ }
+
+ if (format == VIR_STORAGE_FILE_AUTO)
+ format = virStorageFileProbeFormatFromBuf(path, head, len);
+
+ if (format < 0 ||
+ format >= VIR_STORAGE_FILE_LAST) {
+ virReportSystemError(EINVAL, _("unknown storage file format %d"),
+ format);
+ goto cleanup;
+ }
+
+ if (fileTypeInfo[format].sizeOffset != -1) {
+ unsigned long long *file_capacity;
+
+ if ((fileTypeInfo[format].sizeOffset + 8) > len)
+ return -1;
+
+ file_capacity = (unsigned long long *)(head + fileTypeInfo[format].sizeOffset);
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN)
+ *file_capacity = htole64(capacity);
+ else
+ *file_capacity = htobe64(capacity);
+
+ *file_capacity /= fileTypeInfo[format].sizeMultiplier;
+ }
+
+ /* Move to start of file to write the header back with adjusted capacity */
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
+ virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
+ return -1;
+ }
+
+ if ((len = write(fd, head, len)) < 0) {
+ virReportSystemError(errno, _("cannot write header '%s'"), path);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(head);
+ return ret;
+}
+
+/**
+ * virStorageFileResize:
+ *
+ * Change the capacity of the storage file at 'path'.
+ */
+int
+virStorageFileResize(const char *path,
+ int format,
+ unsigned long long capacity)
+{
+ int fd, ret;
+
+ if ((fd = open(path, O_RDWR)) < 0) {
+ virReportSystemError(errno, _("cannot open file '%s'"), path);
+ return -1;
+ }
+
+ ret = virStorageFileResizeForFD(path, fd, format, capacity);
+
+ VIR_FORCE_CLOSE(fd);
+
+ return ret;
+}
+
#ifdef __linux__
# ifndef NFS_SUPER_MAGIC
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index b8920d0..f6c6048 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -72,6 +72,10 @@ int virStorageFileGetMetadataFromFD(const char *path,
void virStorageFileFreeMetadata(virStorageFileMetadata *meta);
+int virStorageFileResize(const char *path,
+ int format,
+ unsigned long long capacity);
+
enum {
VIR_STORAGE_FILE_SHFS_NFS = (1 << 0),
VIR_STORAGE_FILE_SHFS_GFS2 = (1 << 1),
diff --git a/tools/virsh.c b/tools/virsh.c
index 74655c2..20d4bd0 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -11279,6 +11279,58 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+/*
+ * "vol-resize" command
+ */
+static const vshCmdInfo info_vol_resize[] = {
+ {"help", N_("resize a vol")},
+ {"desc", N_("Resizes a storage vol.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_resize[] = {
+ {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
+ {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ, N_("new capacity for the vol with optional k,M,G,T suffix")},
+ {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVolResize(vshControl *ctl, const vshCmd *cmd)
+{
+ virStorageVolPtr vol;
+ const char *capacityStr = NULL;
+ unsigned long long capacity = 0;
+ bool ret = true;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+ return false;
+
+ if (vshCommandOptString(cmd, "capacity", &capacityStr) <= 0)
+ goto cleanup;
+ if (cmdVolSize(capacityStr, &capacity) < 0) {
+ vshError(ctl, _("Malformed size %s"), capacityStr);
+ goto cleanup;
+ }
+
+ if (virStorageVolResize(vol, capacity, 0) == 0) {
+ vshPrint(ctl, "Size of volume '%s' successfully changed to %s\n",
+ virStorageVolGetName(vol), capacityStr);
+ ret = true;
+ } else {
+ vshError(ctl, "Failed to change size of volume '%s' to %s\n",
+ virStorageVolGetName(vol), capacityStr);
+ ret = false;
+ }
+
+cleanup:
+ virStorageVolFree(vol);
+ return ret;
+}
+
/*
* "vol-dumpxml" command
@@ -16141,6 +16193,7 @@ static const vshCmdDef storageVolCmds[] = {
{"vol-pool", cmdVolPool, opts_vol_pool, info_vol_pool, 0},
{"vol-upload", cmdVolUpload, opts_vol_upload, info_vol_upload, 0},
{"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe, 0},
+ {"vol-resize", cmdVolResize, opts_vol_resize, info_vol_resize, 0},
{NULL, NULL, NULL, NULL, 0}
};
--
1.7.7.5
12 years, 9 months