[libvirt] [Patch v2] vmware: detect when a domain was shut down from the inside
by Jean-Baptiste Rouault
This patch adds an internal function vmwareUpdateVMStatus to
update 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.
---
v2:
- Replace internal function vmwareGetVMStatus by vmwareUpdateVMStatus
- Improve vmrun list output parsing
- variable initialization and coding-style fixes
src/vmware/vmware_driver.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 95 insertions(+), 0 deletions(-)
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index 8f9d922..53e28e7 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -28,6 +28,7 @@
#include "datatypes.h"
#include "virfile.h"
#include "memory.h"
+#include "util.h"
#include "uuid.h"
#include "command.h"
#include "vmx.h"
@@ -181,6 +182,64 @@ vmwareGetVersion(virConnectPtr conn, unsigned long *version)
}
static int
+vmwareUpdateVMStatus(struct vmware_driver *driver, virDomainObjPtr vm)
+{
+ virCommandPtr cmd;
+ char *outbuf = NULL;
+ char *vmxAbsolutePath = NULL;
+ char *parsedVmxPath = NULL;
+ char *str;
+ char *saveptr = NULL;
+ bool found = false;
+ int oldState = virDomainObjGetState(vm, NULL);
+ int newState;
+ int ret = -1;
+
+ cmd = virCommandNewArgList(VMRUN, "-T", vmw_types[driver->type],
+ "list", NULL);
+ virCommandSetOutputBuffer(cmd, &outbuf);
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ if (virFileResolveAllLinks(((vmwareDomainPtr) vm->privateData)->vmxPath,
+ &vmxAbsolutePath) < 0)
+ goto cleanup;
+
+ for(str = outbuf ; (parsedVmxPath = strtok_r(str, "\n", &saveptr)) != NULL;
+ str = NULL) {
+
+ if (parsedVmxPath[0] != '/')
+ continue;
+
+ if (STREQ(parsedVmxPath, vmxAbsolutePath)) {
+ found = true;
+ /* If the vmx path is in the output, the domain is running or
+ * is paused but we have no way to detect if it is paused or not. */
+ if (oldState == VIR_DOMAIN_PAUSED)
+ newState = oldState;
+ else
+ newState = VIR_DOMAIN_RUNNING;
+ break;
+ }
+ }
+
+ if (!found) {
+ vm->def->id = -1;
+ newState = VIR_DOMAIN_SHUTOFF;
+ }
+
+ virDomainObjSetState(vm, newState, 0);
+
+ ret = 0;
+
+cleanup:
+ virCommandFree(cmd);
+ VIR_FREE(outbuf);
+ VIR_FREE(vmxAbsolutePath);
+ return ret;
+}
+
+static int
vmwareStopVM(struct vmware_driver *driver,
virDomainObjPtr vm,
virDomainShutoffReason reason)
@@ -331,6 +390,9 @@ vmwareDomainShutdownFlags(virDomainPtr dom,
goto cleanup;
}
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
+
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain is not in running state"));
@@ -485,6 +547,8 @@ vmwareDomainReboot(virDomainPtr dom, unsigned int flags)
vmwareSetSentinal(cmd, vmw_types[driver->type]);
vmwareSetSentinal(cmd, vmxPath);
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -596,6 +660,9 @@ vmwareDomainCreateWithFlags(virDomainPtr dom,
goto cleanup;
}
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
+
if (virDomainObjIsActive(vm)) {
vmwareError(VIR_ERR_OPERATION_INVALID,
"%s", _("Domain is already running"));
@@ -645,6 +712,9 @@ vmwareDomainUndefineFlags(virDomainPtr dom,
goto cleanup;
}
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
+
if (virDomainObjIsActive(vm)) {
vm->persistent = 0;
} else {
@@ -874,6 +944,21 @@ vmwareDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
return xml;
}
+static void vmwareDomainObjListUpdateDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *data)
+{
+ struct vmware_driver *driver = data;
+ virDomainObjPtr vm = payload;
+ virDomainObjLock(vm);
+ vmwareUpdateVMStatus(driver, vm);
+ virDomainObjUnlock(vm);
+}
+
+static void
+vmwareDomainObjListUpdateAll(virDomainObjListPtr doms, struct vmware_driver *driver)
+{
+ virHashForEach(doms->objs, vmwareDomainObjListUpdateDomain, driver);
+}
+
static int
vmwareNumDefinedDomains(virConnectPtr conn)
{
@@ -881,6 +966,7 @@ vmwareNumDefinedDomains(virConnectPtr conn)
int n;
vmwareDriverLock(driver);
+ vmwareDomainObjListUpdateAll(&driver->domains, driver);
n = virDomainObjListNumOfDomains(&driver->domains, 0);
vmwareDriverUnlock(driver);
@@ -894,6 +980,7 @@ vmwareNumDomains(virConnectPtr conn)
int n;
vmwareDriverLock(driver);
+ vmwareDomainObjListUpdateAll(&driver->domains, driver);
n = virDomainObjListNumOfDomains(&driver->domains, 1);
vmwareDriverUnlock(driver);
@@ -908,6 +995,7 @@ vmwareListDomains(virConnectPtr conn, int *ids, int nids)
int n;
vmwareDriverLock(driver);
+ vmwareDomainObjListUpdateAll(&driver->domains, driver);
n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
vmwareDriverUnlock(driver);
@@ -922,6 +1010,7 @@ vmwareListDefinedDomains(virConnectPtr conn,
int n;
vmwareDriverLock(driver);
+ vmwareDomainObjListUpdateAll(&driver->domains, driver);
n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
vmwareDriverUnlock(driver);
return n;
@@ -944,6 +1033,9 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
goto cleanup;
}
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
+
info->state = virDomainObjGetState(vm, NULL);
info->cpuTime = 0;
info->maxMem = vm->def->mem.max_balloon;
@@ -979,6 +1071,9 @@ vmwareDomainGetState(virDomainPtr dom,
goto cleanup;
}
+ if (vmwareUpdateVMStatus(driver, vm) < 0)
+ goto cleanup;
+
*state = virDomainObjGetState(vm, reason);
ret = 0;
--
1.7.9.1
12 years, 9 months
[libvirt] [PATCH] Allow byte[] arrays to be set as a secretValue
by Wido den Hollander
Signed-off-by: Wido den Hollander <wido(a)widodh.nl>
---
src/main/java/org/libvirt/Secret.java | 11 +++++++++++
src/main/java/org/libvirt/jna/Libvirt.java | 1 +
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/src/main/java/org/libvirt/Secret.java b/src/main/java/org/libvirt/Secret.java
index e536cf4..48f7895 100644
--- a/src/main/java/org/libvirt/Secret.java
+++ b/src/main/java/org/libvirt/Secret.java
@@ -146,6 +146,17 @@ public class Secret {
}
/**
+ * Sets the value of the secret
+ *
+ * @return 0 on success, -1 on failure.
+ */
+ public int setValue(byte[] value) throws LibvirtException {
+ int returnValue = libvirt.virSecretSetValue(VSP, value, new NativeLong(value.length), 0);
+ processError();
+ return returnValue;
+ }
+
+ /**
* Undefines, but does not free, the Secret.
*
* @return 0 on success, -1 on failure.
diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java
index 2c8c03d..b1e53a2 100644
--- a/src/main/java/org/libvirt/jna/Libvirt.java
+++ b/src/main/java/org/libvirt/jna/Libvirt.java
@@ -336,6 +336,7 @@ public interface Libvirt extends Library {
public SecretPointer virSecretLookupByUUID(ConnectionPointer virConnectPtr, byte[] uuidBytes);
public SecretPointer virSecretLookupByUUIDString(ConnectionPointer virConnectPtr, String uuidstr);
public int virSecretSetValue(SecretPointer virSecretPtr, String value, NativeLong value_size, int flags);
+ public int virSecretSetValue(SecretPointer virSecretPtr, byte[] value, NativeLong value_size, int flags);
public int virSecretUndefine(SecretPointer virSecretPtr);
//Stream Methods
--
1.7.5.4
12 years, 9 months
[libvirt] Potential deadlock in libvirt lxc driver
by Thomas Hunger
Hi,
I'm running version 0.9.10 on debian [1]. When starting and stopping
containers I see deadlocks every so often. I attached a full backtrace
(see at the end of the log). This seems to happen in conditions
similar to the segfault I wrote about recently. I.e. usually when
destroying domains.
I'm unsure why but it seems to me that lxcMonitorEvent gets called
after a vm has been freed. This happens despite
lxcVmCleanup calling "virEventRemoveHandle(priv->monitorWatch);" to
remove the handle.
best,
Tom
[1]
Linux zap 3.1.0-1-amd64 #1 SMP Tue Jan 10 05:01:58 UTC 2012 x86_64 GNU/Linux
12 years, 9 months
[libvirt] [PATCH] Add support for RAM filesystems for LXC
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Introduce a new syntax for filesystems to allow use of a RAM
filesystem
<filesystem type='ram'>
<source usage='1024'/>
<target dir='/mnt'/>
</filesystem>
The usasge is in KB to limit consumption of host memory.
* docs/formatdomain.html.in: Document new syntax
* docs/schemas/domaincommon.rng: Add new attributes
* src/conf/domain_conf.c: Parsing/formatting of RAM filesystems
* src/lxc/lxc_container.c: Mounting of RAM filesystems
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
docs/formatdomain.html.in | 9 +++++++-
docs/schemas/domaincommon.rng | 13 +++++++++++
src/conf/domain_conf.c | 43 ++++++++++++++++++++----------------
src/lxc/lxc_container.c | 49 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 94 insertions(+), 20 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e1fe0c4..9d1e02b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1617,6 +1617,12 @@
format will be autodetected. Only used by LXC driver
<span class="since">(since 0.9.5)</span>.
</dd>
+ <dt><code>type='ram'</code></dt>
+ <dd>
+ An in-memory filesystem, using memory from the host OS.
+ The source element has a single attribute <code>usage</code>
+ which gives the memory usage limit in kilobytes.
+ <span class="since"> (since 0.9.13)</span></dd>
</dl>
The filesystem block has an optional attribute <code>accessmode</code>
@@ -1656,7 +1662,8 @@
The resource on the host that is being accessed in the guest. The
<code>name</code> attribute must be used with
<code>type='template'</code>, and the <code>dir</code> attribute must
- be used with <code>type='mount'</code>
+ be used with <code>type='mount'</code>. The <code>usage</code> attribute
+ is used with <code>type='ram'</code> to set the memory limit in KB.
</dd>
<dt><code>target</code></dt>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 8419ccc..884680a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1271,6 +1271,19 @@
</element>
</interleave>
</group>
+ <group>
+ <attribute name="type">
+ <value>ram</value>
+ </attribute>
+ <interleave>
+ <element name="source">
+ <attribute name="usage">
+ <ref name="unsignedLong"/>
+ </attribute>
+ <empty/>
+ </element>
+ </interleave>
+ </group>
</choice>
<interleave>
<element name="target">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c82971a..5d692d6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4177,7 +4177,8 @@ virDomainFSDefParseXML(xmlNodePtr node,
def->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
}
- if (source == NULL) {
+ if (source == NULL &&
+ def->type != VIR_DOMAIN_FS_TYPE_RAM) {
virDomainReportError(VIR_ERR_NO_SOURCE,
target ? "%s" : NULL, target);
goto error;
@@ -11086,27 +11087,31 @@ virDomainFSDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
- if (def->src) {
- switch (def->type) {
- case VIR_DOMAIN_FS_TYPE_MOUNT:
- virBufferEscapeString(buf, " <source dir='%s'/>\n",
- def->src);
- break;
+ switch (def->type) {
+ case VIR_DOMAIN_FS_TYPE_MOUNT:
+ virBufferEscapeString(buf, " <source dir='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_BLOCK:
- virBufferEscapeString(buf, " <source dev='%s'/>\n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_BLOCK:
+ virBufferEscapeString(buf, " <source dev='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_FILE:
- virBufferEscapeString(buf, " <source file='%s'/>\n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_FILE:
+ virBufferEscapeString(buf, " <source file='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_TEMPLATE:
- virBufferEscapeString(buf, " <source name='%s'/>\n",
- def->src);
- }
+ case VIR_DOMAIN_FS_TYPE_TEMPLATE:
+ virBufferEscapeString(buf, " <source name='%s'/>\n",
+ def->src);
+ break;
+
+ case VIR_DOMAIN_FS_TYPE_RAM:
+ virBufferAsprintf(buf, " <source usage='%lld'/>\n",
+ def->usage);
+ break;
}
virBufferEscapeString(buf, " <target dir='%s'/>\n",
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 0636eab..f35b8f9 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -338,6 +338,8 @@ static int lxcContainerPivotRoot(virDomainFSDefPtr root)
ret = -1;
+ VIR_DEBUG("Pivot via %s", root->src);
+
/* root->parent must be private, so make / private. */
if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
virReportSystemError(errno, "%s",
@@ -995,6 +997,47 @@ cleanup:
}
+static int lxcContainerMountFSTmpfs(virDomainFSDefPtr fs)
+{
+ int ret = -1;
+ char *data = NULL;
+
+ if (virAsprintf(&data, "size=%lldk", fs->usage) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virFileMakePath(fs->dst) < 0) {
+ virReportSystemError(errno,
+ _("Failed to create %s"),
+ fs->dst);
+ goto cleanup;
+ }
+
+ if (mount("tmpfs", fs->dst, "tmpfs", 0, data) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mount directory %s as tmpfs"),
+ fs->dst);
+ goto cleanup;
+ }
+
+ if (fs->readonly) {
+ VIR_DEBUG("Binding %s readonly", fs->dst);
+ if (mount(fs->dst, fs->dst, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
+ virReportSystemError(errno,
+ _("Failed to make directory %s readonly"),
+ fs->dst);
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(data);
+ return ret;
+}
+
+
static int lxcContainerMountFS(virDomainFSDefPtr fs,
const char *srcprefix)
{
@@ -1007,6 +1050,10 @@ static int lxcContainerMountFS(virDomainFSDefPtr fs,
if (lxcContainerMountFSBlock(fs, srcprefix) < 0)
return -1;
break;
+ case VIR_DOMAIN_FS_TYPE_RAM:
+ if (lxcContainerMountFSTmpfs(fs) < 0)
+ return -1;
+ break;
case VIR_DOMAIN_FS_TYPE_FILE:
lxcError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected filesystem type %s"),
@@ -1196,6 +1243,8 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
for (i = 0 ; i < vmDef->nfss ; i++) {
virDomainFSDefPtr fs = vmDef->fss[i];
+ if (!fs->src)
+ continue;
if (virFileResolveAllLinks(fs->src, &newroot) < 0)
return -1;
--
1.7.10.1
12 years, 9 months
[libvirt] [PATCH] qemu: fix potential dead lock
by Wen Congyang
If we lock the qemu_driver, we should call qemuDomainObjBeginJobWithDriver()
not qemuDomainObjBeginJob().
---
src/qemu/qemu_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 39b27b1..3d62aab 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8905,7 +8905,7 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
goto cleanup;
asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT;
} else {
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
asyncJob = QEMU_ASYNC_JOB_NONE;
}
--
1.7.1
12 years, 10 months
[libvirt] [libvirt-sandbox][PATCH] module lookup and rundir fix
by Radu C.
Hello,
I've been trying to get libvirt-sandbox working on my Gentoo box but I ran into some difficulties. The version I'm using is the latest git one.
The first problem was the following when running virt-sandbox:
"Unable to start sandbox: Error opening file '/tmp/libvirt-sandbox-9ivpRN/9pnet.ko': File exists"
I pinpointed the problem to the following diff in commit [05fb94d2c42abe9cfd86c3663d704c268f325503]:
- gchar *moddirpath = g_strdup_printf("/lib/modules/%s/kernel",
+ gchar *moddirpath = g_strdup_printf("/lib/modules/%s",
The problem is that symlinks are made to the build directory and it finds a module multiple times.
I inserted a printf in the lookup loop so here's what I mean:
dmns libvirt-sandbox # virt-sandbox -c qemu:///system -n test1323 -v
-d /usr/bin/yes
found: /lib/modules/3.4.0-gentoo/kernel/fs/fscache/fscache.ko
found: /lib/modules/3.4.0-gentoo/source/fs/fscache/fscache.ko
found: /lib/modules/3.4.0-gentoo/build/fs/fscache/fscache.ko
found: /lib/modules/3.4.0-gentoo/kernel/net/9p/9pnet.ko
found: /lib/modules/3.4.0-gentoo/source/net/9p/9pnet.ko
found: /lib/modules/3.4.0-gentoo/build/net/9p/9pnet.ko
found: /lib/modules/3.4.0-gentoo/kernel/fs/9p/9p.ko
found: /lib/modules/3.4.0-gentoo/source/fs/9p/9p.ko
found: /lib/modules/3.4.0-gentoo/build/fs/9p/9p.ko
found: /lib/modules/3.4.0-gentoo/kernel/net/9p/9pnet_virtio.ko
found: /lib/modules/3.4.0-gentoo/source/net/9p/9pnet_virtio.ko
found: /lib/modules/3.4.0-gentoo/build/net/9p/9pnet_virtio.ko
The next problem was the following:
dmns libvirt-sandbox # virt-sandbox -c qemu:///system -n test123 -v -d
/usr/bin/yes
Unable to start sandbox: Failed to create domain: internal error
Process exited while reading console log output: char device
redirected to /dev/pts/1
char device redirected to /dev/pts/3
Virtio-9p Failed to initialize fs-driver with id:fsdev-fs1 and export
path:libvirt-sandbox/test123/config
It appears when running as root because of the following line:
./libvirt-sandbox/libvirt-sandbox-context.c: cachedir = (getuid() ? g_get_user_cache_dir() : RUNDIR);
RUNDIR is always "" due to being compiled with -DRUNDIR=\"\" . This is because there's a typo in makefile.am
Both of these are fixed in the diff attachment.
Having these fixes in place everything works fine when using libvirt 0.9.10 but for newer versions I noticed every time I ran virt-sandbox the libvirtd daemon would segfault.
Using git bisect I traced the problem back to commit [1]. So I reverted back to libvirt 0.9.10 but I believe there is a problem both in the commit and somewhere in libvirt-sandbox.
Please have a look and tell me if you need extra info.
[1] http://libvirt.org/git/?p=libvirt.git;a=commit;h=4716138229ae47c5492c1...
Radu Caragea.
12 years, 10 months
[libvirt] [PATCH 0/4] virsh snapshot-info
by Eric Blake
I'm working on a patch series to allow offline disk snapshots,
and in the process, I found that I either don't have enough
information ('virsh snapshot-list' is great for a summary, but not
for an individual snapshot) or too much ('virsh snapshot-dumpxml'
means I have to wade through the XML). This provides an intermediate
view, designed for ease of use.
Eric Blake (4):
snapshot: new query APIs
snapshot: add 'virsh snapshot-info'
snapshot: RPC for new query APIs
snapshot: implement new APIs for qemu, esx, and vbox
include/libvirt/libvirt.h.in | 9 +++
src/driver.h | 10 +++
src/esx/esx_driver.c | 71 ++++++++++++++++++++++++
src/libvirt.c | 85 ++++++++++++++++++++++++++++
src/libvirt_public.syms | 6 ++
src/qemu/qemu_driver.c | 83 ++++++++++++++++++++++++++++
src/remote/remote_driver.c | 2 +
src/remote/remote_protocol.x | 23 +++++++-
src/remote_protocol-structs | 16 +++++
src/vbox/vbox_tmpl.c | 97 ++++++++++++++++++++++++++++++++
tools/virsh.c | 125 ++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 5 ++
12 files changed, 531 insertions(+), 1 deletions(-)
--
1.7.7.6
12 years, 10 months
[libvirt] [PATCH 1/2] Add VSCSI bus type and VSCSI controller type for pseries guest.
by Li Zhang
Now, there is only SCSI bus and controller type in libvirt.
And when configuring VSCSI controller, it needs to configure
the spapr-vio bus address type externally. It's a little
inconvenient to configure the controller type.
This patch is to add VSCSI bus type and VSCSI controller type.
And handle with the problems when VSCSI and SCSI devices
working together, by assign the even number to index of
VSCSI controller and odd number to index of SCSI controller.
And when the VSCSI controller is always assigned as SPAPRVIO
bus address type and SCSI controller will be always assigned
as PCI bus address, which is implemented according to the
controllers' type.
So when one disk is based on VSCSI controller, then assign
the bus as 'vscsi', and one right VSCSI controller will be
selected.
If one disk is based on VSCSI controller, the XML file is
as the following:
<disk type='file' device='disk' >
<driver name='qemu' type='raw'/>
<source file='/path/file'/>
<target dev='sda' bus='vscsi'/>
</disk>
VSCSI controllers' configuration in XML file will be like
this:
<controller type='vscsi' index='0'>
</controller>
If one disk is based on 'vscsi', the 'vscsi' bus should be assigned
externally. Otherwise, it will be set as 'scsi' bus according
to the 'sd' target prefix of the disk.
Signed-off-by: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 62 ++++++++++++++++++++++++++++++++++++++++++-----
src/conf/domain_conf.h | 2 ++
src/qemu/qemu_command.c | 11 +++++++--
3 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 184ff23..99005b7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -177,7 +177,8 @@ VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
"xen",
"usb",
"uml",
- "sata")
+ "sata",
+ "vscsi")
VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
"default",
@@ -236,7 +237,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"sata",
"virtio-serial",
"ccid",
- "usb")
+ "usb",
+ "vscsi")
VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
"auto",
@@ -2973,6 +2975,7 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
switch (def->bus) {
case VIR_DOMAIN_DISK_BUS_SCSI:
+ case VIR_DOMAIN_DISK_BUS_VSCSI:
def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
if (caps->hasWideScsiBus) {
@@ -2981,6 +2984,16 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
* Unit 7 is the SCSI controller itself. Therefore unit 7
* cannot be assigned to disks and is skipped.
*/
+
+ /* assign even number to index of vscsi controller,
+ * and odd number to index of scsi controller, which can
+ * make vscsi controller and scsi controller work together.
+ */
+ if (def->bus == VIR_DOMAIN_DISK_BUS_VSCSI)
+ def->info.addr.drive.controller = (idx / 15) * 2;
+ else
+ def->info.addr.drive.controller = (idx / 15) * 2 + 1;
+
def->info.addr.drive.controller = idx / 15;
def->info.addr.drive.bus = 0;
def->info.addr.drive.unit = idx % 15;
@@ -2992,6 +3005,17 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
} else {
/* For a narrow SCSI bus we define the default mapping to be
* 7 units per bus, 1 bus per controller, many controllers */
+
+ /* assign even number to index of vscsi controller,
+ * and odd number to index of scsi controller, which can
+ * make vscsi controller and scsi controller work together.
+ */
+
+ if (def->bus == VIR_DOMAIN_DISK_BUS_VSCSI)
+ def->info.addr.drive.controller = (idx / 7) * 2;
+ else
+ def->info.addr.drive.controller = (idx / 7 ) * 2 + 1;
+
def->info.addr.drive.controller = idx / 7;
def->info.addr.drive.bus = 0;
def->info.addr.drive.unit = idx % 7;
@@ -4061,6 +4085,10 @@ virDomainControllerDefParseXML(xmlNodePtr node,
break;
}
+ case VIR_DOMAIN_CONTROLLER_TYPE_VSCSI:
+ def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+ break;
+
default:
break;
}
@@ -7606,6 +7634,9 @@ static int virDomainDefMaybeAddController(virDomainDefPtr def,
cont->idx = idx;
cont->model = -1;
+ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_VSCSI)
+ cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+
if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
cont->opts.vioserial.ports = -1;
cont->opts.vioserial.vectors = -1;
@@ -10133,9 +10164,19 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
maxController = def->disks[i]->info.addr.drive.controller;
}
- for (i = 0 ; i <= maxController ; i++) {
- if (virDomainDefMaybeAddController(def, controllerType, i) < 0)
- return -1;
+ /* To make scsi and vscsi can work together correctly,
+ * assign even number to index of vscsi controller
+ * and odd number of scsi controller.*/
+ if (diskBus == VIR_DOMAIN_DISK_BUS_VSCSI) {
+ for (i = 0 ; i * 2 <= maxController ; i ++ ) {
+ if (virDomainDefMaybeAddController(def, controllerType, 2 * i) < 0)
+ return -1;
+ }
+ } else {
+ for (i = 0 ; i * 2 + 1 <= maxController ; i ++ ) {
+ if (virDomainDefMaybeAddController(def, controllerType, 2 * i + 1) < 0)
+ return -1;
+ }
}
return 0;
@@ -10247,6 +10288,11 @@ int virDomainDefAddImplicitControllers(virDomainDefPtr def)
VIR_DOMAIN_DISK_BUS_SATA) < 0)
return -1;
+ if (virDomainDefAddDiskControllersForType(def,
+ VIR_DOMAIN_CONTROLLER_TYPE_VSCSI,
+ VIR_DOMAIN_DISK_BUS_VSCSI) < 0)
+ return -1;
+
if (virDomainDefMaybeAddVirtioSerialController(def) < 0)
return -1;
@@ -13175,7 +13221,11 @@ int virDiskNameToBusDeviceIndex(const virDomainDiskDefPtr disk,
*devIdx = idx % 2;
break;
case VIR_DOMAIN_DISK_BUS_SCSI:
- *busIdx = idx / 7;
+ *busIdx = (idx / 7) * 2 + 1;
+ *devIdx = idx % 7;
+ break;
+ case VIR_DOMAIN_DISK_BUS_VSCSI:
+ *busIdx = (idx / 7) * 2;
*devIdx = idx % 7;
break;
case VIR_DOMAIN_DISK_BUS_FDC:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5aa8fc1..0066eba 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -418,6 +418,7 @@ enum virDomainDiskBus {
VIR_DOMAIN_DISK_BUS_USB,
VIR_DOMAIN_DISK_BUS_UML,
VIR_DOMAIN_DISK_BUS_SATA,
+ VIR_DOMAIN_DISK_BUS_VSCSI,
VIR_DOMAIN_DISK_BUS_LAST
};
@@ -597,6 +598,7 @@ enum virDomainControllerType {
VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
VIR_DOMAIN_CONTROLLER_TYPE_CCID,
VIR_DOMAIN_CONTROLLER_TYPE_USB,
+ VIR_DOMAIN_CONTROLLER_TYPE_VSCSI,
VIR_DOMAIN_CONTROLLER_TYPE_LAST
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 070d13e..bb3be17 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -57,7 +57,8 @@ VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
"xen",
"usb",
"uml",
- "sata")
+ "sata",
+ "vscsi")
VIR_ENUM_DECL(qemuDiskCacheV1)
@@ -429,6 +430,7 @@ static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk)
ret = virAsprintf(&dev_name, "ide%d-cd%d", busid, devid);
break;
case VIR_DOMAIN_DISK_BUS_SCSI:
+ case VIR_DOMAIN_DISK_BUS_VSCSI:
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
ret = virAsprintf(&dev_name, "scsi%d-hd%d", busid, devid);
else
@@ -1836,6 +1838,7 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
switch (disk->bus) {
case VIR_DOMAIN_DISK_BUS_SCSI:
+ case VIR_DOMAIN_DISK_BUS_VSCSI:
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unexpected address type for scsi disk"));
@@ -2223,6 +2226,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
disk->info.addr.drive.unit);
break;
case VIR_DOMAIN_DISK_BUS_SCSI:
+ case VIR_DOMAIN_DISK_BUS_VSCSI:
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
if (!qemuCapsGet(qemuCaps, QEMU_CAPS_SCSI_BLOCK)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -6447,6 +6451,8 @@ qemuParseCommandLineDisk(virCapsPtr caps,
def->bus = VIR_DOMAIN_DISK_BUS_IDE;
else if (STREQ(values[i], "scsi"))
def->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+ else if (STREQ(values[i], "vscsi"))
+ def->bus = VIR_DOMAIN_DISK_BUS_VSCSI;
else if (STREQ(values[i], "virtio"))
def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
else if (STREQ(values[i], "xen"))
@@ -6577,7 +6583,8 @@ qemuParseCommandLineDisk(virCapsPtr caps,
if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
def->dst = strdup("hda");
- } else if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+ } else if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
+ def->bus == VIR_DOMAIN_DISK_BUS_VSCSI) {
def->dst = strdup("sda");
} else if (def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
def->dst = strdup("vda");
--
1.7.9.5
12 years, 10 months