[libvirt] API Proposal: virDomainBlockPull() (Block device streaming) V4
by Adam Litke
Here is version 4 of the BlockStream API (now called BlockPull). Hopefully this
version addresses all remaining concerns and I can begin to work on the code.
Does everyone approve of the new name 'virDomainBlockPull'?
Changes since V3:
- Renamed the API to 'Block Pull' to emphasize the effect of the API over its
method of operation.
- Changed virDomainGetBlockPullInfo() to accept a path argument and to return
information about that path alone.
- Added a new virDomainEvent to report final status when using CONTINUOUS mode.
/*
* Block Pull API
*/
typedef enum {
/*
* If set, virDomainBlockPull() will operate on the entire device in the
* background. The status can be checked and the operation aborted by
* using the functions virDomainBlockPullInfo() and
* virDomainBlockPullAbort().
*/
VIR_DOMAIN_BLOCK_PULL_CONTINUOUS = 1,
} virDomainBlockPullFlags;
/* An iterator for initiating and monitoring block pull operations */
typedef unsigned long long virDomainBlockPullCursor;
typedef struct _virDomainBlockPullInfo virDomainBlockPullInfo;
struct _virDomainBlockPullInfo {
/*
* The following fields provide an indication of block pull progress. @cur
* indicates the current position and will be between 0 and @end. @end is
* the final cursor position for this operation and represents completion.
* To approximate progress, divide @cur by @end.
*/
virDomainBlockPullCursor cur;
virDomainBlockPullCursor end;
};
typedef virDomainBlockPullInfo *virDomainBlockPullInfoPtr;
/**
* virDomainBlockPull:
* @dom: pointer to domain object
* @path: Fully-qualified filename of disk
* @cursor: pointer to a virDomainBlockPullCursor, or NULL
* @flags: One of virDomainBlockPullFlags, or zero
*
* Populate a disk image with data from its backing image. Once all data from
* its backing image has been pulled, the disk no longer depends on a backing
* image.
*
* If VIR_DOMAIN_BLOCK_PULL_CONTINUOUS is specified, the entire device will be
* streamed in the background. Otherwise, the value stored in @cursor will be
* used to stream an increment.
*
* Returns -1 in case of failure, 0 when successful. On success and when @flags
* does not contain VIR_DOMAIN_BLOCK_PULL_CONTINUOUS, the iterator @cursor will
* be updated to the proper value for use in a subsequent call.
*/
int virDomainBlockPull(virDomainPtr dom,
const char *path,
virDomainBlockPullCursor *cursor,
unsigned int flags);
/**
* virDomainBlockPullAbort:
* @dom: pointer to domain object
* @path: fully-qualified filename of disk
* @flags: currently unused, for future extension
*
* Cancel a pull operation that has been previously started by a call to
* virDomainBlockPull() with the VIR_DOMAIN_BLOCK_PULL_CONTINUOUS flag.
*
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainBlockPullAbort(virDomainPtr dom,
const char *path,
unsigned int flags);
/**
* virDomainGetBlockPullInfo:
* @dom: pointer to domain object
* @path: fully-qualified filename of disk
* @info: pointer to a virDomainBlockPullInfo structure
* @flags: currently unused, for future extension
*
* Request progress information on a block pull operation that has been started
* with the VIR_DOMAIN_BLOCK_PULL_CONTINUOUS flag set. If an operation is
* active for the given parameters, @info will be updated with the current
* progress.
*
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainGetBlockPullInfo(virDomainPtr dom,
const char *path,
virDomainBlockStreamInfoPtr info,
unsigned int flags);
The following new asynchronous event will be made available for subscription:
VIR_DOMAIN_EVENT_ID_BLOCK_PULL = 7,
typedef enum {
VIR_DOMAIN_BLOCK_PULL_COMPLETED,
VIR_DOMAIN_BLOCK_PULL_FAILED,
} virConnectDomainEventBlockPullStatus;
typedef void (*virConnectDomainEventBlockPullCallback(virConnectPtr conn,
virDomainPtr dom,
const char *path,
int status);
Upon receipt of this event and when the status field indicates success, libvirt
will revoke access to the backing file which is no longer needed by the domain.
NOTE: Qemu will emit an asynchronous event (VIR_DOMAIN_BLOCK_PULL_COMPLETED)
after any operation that eliminates the dependency on the backing file. This
could be a virDomainBlockPull() without VIR_DOMAIN_BLOCK_PULL_CONTINUOUS and
will allow libvirt to manage backing file security regardless of the pull mode
used.
--
Adam Litke
IBM Linux Technology Center
13 years, 7 months
[libvirt] [PATCH] Don't restore labels on network shares
by Christian Brunner
Restoring security labels on network shares doesn't work and will cause
an error. Therefore it should be skipped.
Signed-off-by: Christian Brunner <chb(a)muc.de>
---
src/security/security_dac.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index fba2d1d..02c0bc1 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -213,6 +213,13 @@ virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
if (!disk->src)
return 0;
+ /* Don't restore labels on network shares */
+ if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
+ VIR_DEBUG("Skipping image label restore on %s because FS is of type network",
+ disk->src);
+ return 0;
+ }
+
/* If we have a shared FS & doing migrated, we must not
* change ownership, because that kills access on the
* destination host which is sub-optimal for the guest
--
1.7.1
13 years, 7 months
[libvirt] [PATCH] python: Don't free must-not-free variables
by Michal Privoznik
py_str() function call PyString_AsString(). As written in documentation,
the caller must not free the returned value, because it points to some
internal structures.
---
python/libvirt-override.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index a151e78..7998723 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -35,6 +35,8 @@ extern void initcygvirtmod(void);
#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
+/* We don't want to free() returned value, as written in doc
+ * to PyString_AsString. */
static char *py_str(PyObject *obj)
{
PyObject *str = PyObject_Str(obj);
@@ -2660,7 +2662,6 @@ libvirt_virEventAddHandleFunc (int fd,
char *name = py_str(python_cb);
printf("%s: %s is not callable\n", __FUNCTION__,
name ? name : "libvirt.eventInvokeHandleCallback");
- free(name);
#endif
goto cleanup;
}
@@ -2805,7 +2806,6 @@ libvirt_virEventAddTimeoutFunc(int timeout,
char *name = py_str(python_cb);
printf("%s: %s is not callable\n", __FUNCTION__,
name ? name : "libvirt.eventInvokeTimeoutCallback");
- free(name);
#endif
goto cleanup;
}
@@ -2919,17 +2919,11 @@ libvirt_virEventRegisterImpl(ATTRIBUTE_UNUSED PyObject * self,
{
/* Unref the previously-registered impl (if any) */
Py_XDECREF(addHandleObj);
- free(addHandleName);
Py_XDECREF(updateHandleObj);
- free(updateHandleName);
Py_XDECREF(removeHandleObj);
- free(removeHandleName);
Py_XDECREF(addTimeoutObj);
- free(addTimeoutName);
Py_XDECREF(updateTimeoutObj);
- free(updateTimeoutName);
Py_XDECREF(removeTimeoutObj);
- free(removeTimeoutName);
/* Parse and check arguments */
if (!PyArg_ParseTuple(args, (char *) "OOOOOO:virEventRegisterImpl",
@@ -2944,7 +2938,10 @@ libvirt_virEventRegisterImpl(ATTRIBUTE_UNUSED PyObject * self,
!PyCallable_Check(removeTimeoutObj))
return VIR_PY_INT_FAIL;
- /* Get argument string representations (for error reporting) */
+ /* Get argument string representations (for error reporting).
+ * py_str calls PyString_AsString() which returns pointer to:
+ * 'internal buffer of string, not a copy.' and 'It must not be
+ * deallocated' (pyhton c-api documentation) */
addHandleName = py_str(addHandleObj);
updateHandleName = py_str(updateHandleObj);
removeHandleName = py_str(removeHandleObj);
--
1.7.5.rc3
13 years, 7 months
[libvirt] [PATCH] storage: Add comment to picking return value of qemu-img
by Michal Privoznik
Commit d7b2679253504d6defa9fc7159b572cfd6a25a95 introduced
a return value picking of qemu-img on '-h', but without any comment.
---
src/storage/storage_backend.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index c8e19c8..b423d11 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -628,6 +628,9 @@ static int virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
virCommandSetOutputBuffer(cmd, &help);
virCommandClearCaps(cmd);
+ /* qemuimg doesn't return zero exit status on -h,
+ * therefore we need to provide pointer for storing
+ * exit status, although we don't parse it any later */
if (virCommandRun(cmd, &exitstatus) < 0)
goto cleanup;
--
1.7.5.rc3
13 years, 7 months
[libvirt] [PATCH 0/3] add support for changing blkio parameters for inactive domains
by Hu Tao
This series enables user to change blkio parameters for inactive
domains from virsh command line.
Hu Tao (3):
Add new parameters for blkiotune
update qemuDomainGetBlkioParameters to use flags
Update qemuDomainSetBlkioParameters to use flags
include/libvirt/libvirt.h.in | 6 +
src/qemu/qemu_driver.c | 250 +++++++++++++++++++++++++++++-------------
tools/virsh.c | 26 ++++-
tools/virsh.pod | 6 +-
4 files changed, 210 insertions(+), 78 deletions(-)
--
1.7.3.1
13 years, 7 months
[libvirt] Suggested schedule for next release 0.9.2
by Daniel Veillard
To try to keep on the monthly release schedule, I suggest to start the
freeze for 0.9.2 at the beginning of next week. We are already at 227
commits since 0.9.1 and there is a number of patches that were sent and
not finished reviewing or ack'ing. So let's try to push those this week
and possibly over the week-end, with the target of entering freeze on
Monday 30, targetting a release at the end of the next week.
As usual if you submitted a patch which didn't get any review, please
raise the attention about it on list, hopefully we can get everything
reviewed in time.
thanks !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
13 years, 7 months
[libvirt] [PATCH] spice: support streaming-video parameter
by Alon Levy
This adds a streaming-video=filter|all|off attribute. It is used to change
the behavior of video stream detection in spice, the default is filter (the
default for libvirt is not to specify it - the actual default is defined in
libspice-server.so).
Usage:
<graphics type='spice' autoport='yes'>
<streaming mode='off'/>
</graphics>
Tested with the above and with tests/qemuxml2argvtest.
Signed-off-by: Alon Levy <alevy(a)redhat.com>
---
Sorry for the resend, don't have the message id of my original message (now
I'm registered to the list so won't happen again I hope).
Michal, is this version good?
---
docs/formatdomain.html.in | 6 ++++
docs/schemas/domain.rng | 12 ++++++++
src/conf/domain_conf.c | 30 ++++++++++++++++++++
src/conf/domain_conf.h | 11 +++++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_command.c | 3 ++
.../qemuxml2argv-graphics-spice.args | 2 +-
.../qemuxml2argv-graphics-spice.xml | 1 +
8 files changed, 66 insertions(+), 1 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 59c3d51..6146a5d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1798,6 +1798,7 @@ qemu-kvm -net nic,model=? /dev/null
<channel name='main' mode='secure'/>
<channel name='record' mode='insecure'/>
<image compression='auto_glz'/>
+ <streaming mode='filter'/>
</graphics></pre>
<p>
Spice supports variable compression settings for audio,
@@ -1816,6 +1817,11 @@ qemu-kvm -net nic,model=? /dev/null
and <code>playback</code> for enabling audio stream
compression (accepts <code>on</code> or <code>off</code>).
</p>
+ <p>
+ Streaming mode is set by the <code>streaming</code>
+ element, settings it's <code>mode</code> attribute to one
+ of <code>filter</code>,<code>all</code> or <code>off</code>.
+ </p>
</dd>
<dt><code>"rdp"</code></dt>
<dd>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index b252547..563981d 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1334,6 +1334,18 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="streaming">
+ <attribute name="mode">
+ <choice>
+ <value>filter</value>
+ <value>all</value>
+ <value>off</value>
+ </choice>
+ </attribute>
+ <empty/>
+ </element>
+ </optional>
</interleave>
</group>
<group>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6129bbc..c187450 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -359,6 +359,13 @@ VIR_ENUM_IMPL(virDomainGraphicsSpicePlaybackCompression,
"on",
"off");
+VIR_ENUM_IMPL(virDomainGraphicsSpiceStreamingMode,
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_LAST,
+ "default",
+ "filter",
+ "all",
+ "off");
+
VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
"subsystem",
"capabilities")
@@ -4168,6 +4175,26 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
VIR_FREE(compression);
def->data.spice.playback = compressionVal;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "streaming")) {
+ const char *mode = virXMLPropString(cur, "mode");
+ int modeVal;
+
+ if (!mode) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("spice streaming missing mode"));
+ goto error;
+ }
+ if ((modeVal =
+ virDomainGraphicsSpiceStreamingModeTypeFromString(mode)) <= 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown spice streaming mode"));
+ VIR_FREE(mode);
+ goto error;
+
+ }
+ VIR_FREE(mode);
+
+ def->data.spice.streaming = modeVal;
}
}
cur = cur->next;
@@ -8067,6 +8094,9 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
if (def->data.spice.playback)
virBufferAsprintf(buf, " <playback compression='%s'/>\n",
virDomainGraphicsSpicePlaybackCompressionTypeToString(def->data.spice.playback));
+ if (def->data.spice.streaming)
+ virBufferVSprintf(buf, " <streaming mode='%s'/>\n",
+ virDomainGraphicsSpiceStreamingModeTypeToString(def->data.spice.streaming));
}
if (children) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5fe31d4..9d4349e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -697,6 +697,15 @@ enum virDomainGraphicsSpicePlaybackCompression {
VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST
};
+enum virDomainGraphicsSpiceStreamingMode {
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_DEFAULT = 0,
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_FILTER,
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_ALL,
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_OFF,
+
+ VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_LAST
+};
+
typedef struct _virDomainGraphicsDef virDomainGraphicsDef;
typedef virDomainGraphicsDef *virDomainGraphicsDefPtr;
struct _virDomainGraphicsDef {
@@ -738,6 +747,7 @@ struct _virDomainGraphicsDef {
int jpeg;
int zlib;
int playback;
+ int streaming;
} spice;
} data;
};
@@ -1506,6 +1516,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression)
VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression)
VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression)
VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression)
+VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode)
/* from libvirt.h */
VIR_ENUM_DECL(virDomainState)
VIR_ENUM_DECL(virDomainNostateReason)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7b6151c..d4f03fc 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -276,6 +276,8 @@ virDomainGraphicsSpicePlaybackCompressionTypeFromString;
virDomainGraphicsSpicePlaybackCompressionTypeToString;
virDomainGraphicsSpiceZlibCompressionTypeFromString;
virDomainGraphicsSpiceZlibCompressionTypeToString;
+virDomainGraphicsSpiceStreamingModeTypeFromString;
+virDomainGraphicsSpiceStreamingModeTypeToString;
virDomainGraphicsTypeFromString;
virDomainGraphicsTypeToString;
virDomainHostdevDefFree;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2828823..1d30a6f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4037,6 +4037,9 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->graphics[0]->data.spice.playback)
virBufferAsprintf(&opt, ",playback-compression=%s",
virDomainGraphicsSpicePlaybackCompressionTypeToString(def->graphics[0]->data.spice.playback));
+ if (def->graphics[0]->data.spice.streaming)
+ virBufferVSprintf(&opt, ",streaming-video=%s",
+ virDomainGraphicsSpiceStreamingModeTypeToString(def->graphics[0]->data.spice.streaming));
virCommandAddArg(cmd, "-spice");
virCommandAddArgBuffer(cmd, &opt);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
index 70cd35b..084a100 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
@@ -4,6 +4,6 @@ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \
/dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\
x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs,\
image-compression=auto_glz,jpeg-wan-compression=auto,zlib-glz-wan-compression=auto,\
-playback-compression=on -vga \
+playback-compression=on,streaming-video=filter -vga \
qxl -global qxl.vram_size=18874368 -device qxl,id=video1,vram_size=33554432,bus=pci.0,addr=0x4 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
index a29f50d..0d3dd48 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
@@ -28,6 +28,7 @@
<jpeg compression='auto'/>
<zlib compression='auto'/>
<playback compression='on'/>
+ <streaming mode='filter'/>
</graphics>
<video>
<model type='qxl' vram='18432' heads='1'/>
--
1.7.5.1
13 years, 7 months
[libvirt] [PATCH] Fix peer2peer migration with transient VMs
by Daniel P. Berrange
The qemuMigrationConfirm method shouldn't deal with final VM
cleanup, since it can be called from the peer2peer migration,
which expects to still use the 'vm' object afterwards.
Push the cleanup code out of qemuMigrationConfirm, into its
caller, qemuDomainMigrateConfirm3
* src/qemu/qemu_driver.c: Add VM cleanup code to
qemuDomainMigrateConfirm3
* src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Remove
job handling cleanup from qemuMigrationConfirm
---
src/qemu/qemu_driver.c | 25 +++++++++++++++++++++-
src/qemu/qemu_migration.c | 51 +++++++++++++++------------------------------
src/qemu/qemu_migration.h | 3 +-
3 files changed, 42 insertions(+), 37 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4fdf5e9..771e401 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6292,6 +6292,7 @@ qemuDomainMigrateConfirm3(virDomainPtr domain,
struct qemud_driver *driver = domain->conn->privateData;
virDomainObjPtr vm;
int ret = -1;
+ virErrorPtr orig_err;
virCheckFlags(VIR_MIGRATE_LIVE |
VIR_MIGRATE_PEER2PEER |
@@ -6312,11 +6313,33 @@ qemuDomainMigrateConfirm3(virDomainPtr domain,
goto cleanup;
}
+ if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
+ goto cleanup;
+
ret = qemuMigrationConfirm(driver, domain->conn, vm,
cookiein, cookieinlen,
- flags, cancelled, false);
+ flags, cancelled);
+
+ orig_err = virSaveLastError();
+
+ if (qemuDomainObjEndJob(vm) == 0) {
+ vm = NULL;
+ } else if (!virDomainObjIsActive(vm) &&
+ (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
+ if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
+ virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+
+ if (orig_err) {
+ virSetError(orig_err);
+ virFreeError(orig_err);
+ }
cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
qemuDriverUnlock(driver);
return ret;
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 40c40f3..88cab77 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1920,7 +1920,7 @@ finish:
cookieoutlen = 0;
ret = qemuMigrationConfirm(driver, sconn, vm,
cookiein, cookieinlen,
- flags, cancelled, true);
+ flags, cancelled);
/* If Confirm3 returns -1, there's nothing more we can
* do, but fortunately worst case is that there is a
* domain left in 'paused' state on source.
@@ -2086,12 +2086,6 @@ int qemuMigrationPerform(struct qemud_driver *driver,
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
- if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
- virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
- if (qemuDomainObjEndJob(vm) > 0)
- virDomainRemoveInactive(&driver->domains, vm);
- vm = NULL;
- }
}
ret = 0;
@@ -2113,9 +2107,17 @@ endjob:
VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
}
- if (vm &&
- qemuDomainObjEndJob(vm) == 0)
- vm = NULL;
+ if (vm) {
+ if (qemuDomainObjEndJob(vm) == 0) {
+ vm = NULL;
+ } else if (!virDomainObjIsActive(vm) &&
+ (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
+ if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
+ virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+ }
cleanup:
if (vm)
@@ -2306,9 +2308,8 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
virDomainObjPtr vm,
const char *cookiein,
int cookieinlen,
- unsigned int flags,
- int retcode,
- bool skipJob)
+ unsigned int flags ATTRIBUTE_UNUSED,
+ int retcode)
{
qemuMigrationCookiePtr mig;
virDomainEventPtr event = NULL;
@@ -2317,14 +2318,10 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0)))
return -1;
- if (!skipJob &&
- qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
- goto cleanup;
-
if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
- goto endjob;
+ goto cleanup;
}
/* Did the migration go as planned? If yes, kill off the
@@ -2337,12 +2334,6 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
- if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
- virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
- if (qemuDomainObjEndJob(vm) > 0)
- virDomainRemoveInactive(&driver->domains, vm);
- vm = NULL;
- }
} else {
/* run 'cont' on the destination, which allows migration on qemu
@@ -2354,7 +2345,7 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
if (virGetLastError() == NULL)
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("resume operation failed"));
- goto endjob;
+ goto cleanup;
}
event = virDomainEventNewFromObj(vm,
@@ -2362,22 +2353,14 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
VIR_WARN("Failed to save status on vm %s", vm->def->name);
- goto endjob;
+ goto cleanup;
}
}
qemuMigrationCookieFree(mig);
rv = 0;
-endjob:
- if (vm &&
- !skipJob &&
- qemuDomainObjEndJob(vm) == 0)
- vm = NULL;
-
cleanup:
- if (vm)
- virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
return rv;
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index a350579..08e3acc 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -90,8 +90,7 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
const char *cookiein,
int cookieinlen,
unsigned int flags,
- int retcode,
- bool skipJob);
+ int retcode);
int qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm,
--
1.7.4.4
13 years, 7 months
[libvirt] [RESEND][PATCH v2] qemu allow persistent modifications of NICs
by KAMEZAWA Hiroyuki
Slightly updated against the latest git tree. but didn't update version number.
==
Now, only attach/detatch/update for disks are supporeted for inactive
domains.
This patch allows to modify network interfaces of inactive domains.
Users can modify inactive domains with --persistent flag.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
* src/conf/domain_conf.c:
(virDomainNetInsert) : Insert a network device to domain definition.
(virDomainNetIndexByMac) : Returns an index of net device in array.
(virDomainNetRemoveByMac): Remove a NIC of passed MAC address.
* src/qemu/qemu_driver.c
(qemuDomainAttachDeviceConfig): add codes for NIC.
(qemuDomainDetachDeviceConfig): add codes for NIC.
Changelog v1->v2:
- fixed virDomainNetInsert
- removed target name check. (It seems I misunderstood something.)
- fixed error check in qemuDomainAttachDeviceConfig
- fixed error message in qemuDomainDetachDeviceConfig
---
src/conf/domain_conf.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 4 ++++
src/libvirt_private.syms | 3 +++
src/qemu/qemu_driver.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6129bbc..d85c8bc 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5177,6 +5177,51 @@ int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name)
return 0;
}
+int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net)
+{
+ if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+ return -1;
+ def->nets[def->nnets] = net;
+ def->nnets++;
+ return 0;
+}
+
+int virDomainNetIndexByMac(virDomainDefPtr def, const unsigned char *mac)
+{
+ int i;
+
+ for (i = 0; i < def->nnets; i++)
+ if (!memcmp(def->nets[i]->mac, mac, VIR_MAC_BUFLEN))
+ return i;
+ return -1;
+}
+
+static void virDomainNetRemove(virDomainDefPtr def, size_t i)
+{
+ if (def->nnets > 1) {
+ memmove(def->nets + i,
+ def->nets + i + 1,
+ sizeof(*def->nets) * (def->nnets - (i + 1)));
+ def->nnets--;
+ if (VIR_REALLOC_N(def->nets, def->nnets) < 0) {
+ /* ignore harmless */
+ }
+ } else {
+ VIR_FREE(def->nets);
+ def->nnets = 0;
+ }
+}
+
+int virDomainNetRemoveByMac(virDomainDefPtr def, const unsigned char *mac)
+{
+ int i = virDomainNetIndexByMac(def, mac);
+
+ if (i < 0)
+ return -1;
+ virDomainNetRemove(def, i);
+ return 0;
+}
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5fe31d4..f195caa 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1360,6 +1360,10 @@ int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def);
void virDomainDiskRemove(virDomainDefPtr def, size_t i);
int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name);
+int virDomainNetIndexByMac(virDomainDefPtr def, const unsigned char *mac);
+int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
+int virDomainNetRemoveByMac(virDomainDefPtr def, const unsigned char *mac);
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller);
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7b6151c..eb55025 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -290,6 +290,9 @@ virDomainLoadAllConfigs;
virDomainMemballoonModelTypeFromString;
virDomainMemballoonModelTypeToString;
virDomainNetDefFree;
+virDomainNetIndexByMac;
+virDomainNetInsert;
+virDomainNetRemoveByMac;
virDomainNetTypeToString;
virDomainObjAssignDef;
virDomainObjCopyPersistentDef;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 691965d..ef2c5f0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4245,6 +4245,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
@@ -4267,6 +4268,24 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
return -1;
break;
+ case VIR_DOMAIN_DEVICE_NET:
+ net = dev->data.net;
+ if (virDomainNetIndexByMac(vmdef, net->mac) >= 0) {
+ char macbuf[VIR_MAC_STRING_BUFLEN];
+
+ virFormatMacAddr(net->mac, macbuf);
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("mac %s already exists"), macbuf);
+ return -1;
+ }
+ if (virDomainNetInsert(vmdef, net)) {
+ virReportOOMError();
+ return -1;
+ }
+ dev->data.net = NULL;
+ if (qemuDomainAssignPCIAddresses(vmdef) < 0)
+ return -1;
+ break;
default:
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("persistent attach of device is not supported"));
@@ -4281,6 +4300,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk;
+ virDomainNetDefPtr net;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
@@ -4291,6 +4311,17 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
return -1;
}
break;
+ case VIR_DOMAIN_DEVICE_NET:
+ net = dev->data.net;
+ if (virDomainNetRemoveByMac(vmdef, net->mac)) {
+ char macbuf[VIR_MAC_STRING_BUFLEN];
+
+ virFormatMacAddr(net->mac, macbuf);
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("mac %s doesn't exist."), macbuf);
+ return -1;
+ }
+ break;
default:
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("persistent detach of device is not supported"));
--
1.7.4.1
13 years, 7 months