[libvirt] Add spice support
by Songwen Liao
Hi,everyone,
I used the patch file to modify the libvirt,but it seems not to work right.
It looks like that libvirt accpet the graphices type of spice,but it's can
use "virsh start xp" to start the machine,with the error is:
internal error unable to start guest:Supported machines are:
pc Standard PC(default)
isapc ISA-only PC
So,anyone have ideas about that?
thanks,
PATCH file:
This adds an element
<graphics type='spice' port='5903' tlsPort='5904' listen='127.0.0.1'/>
This is the bare minimum that should be exposed in the guest
config for SPICE. Other parameters are better handled as per
host level configuration tunables
* docs/schemas/domain.rng: Define the SPICE <graphics> schema
* src/domain_conf.h, src/domain_conf.c: Add parsing and formatting
for SPICE graphics config
* src/qemu_conf.c: Complain about unsupported graphics types
---
docs/schemas/domain.rng | 30 +++++++++++++++++++++
src/conf/domain_conf.c | 65
++++++++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 8 ++++++
src/qemu/qemu_conf.c | 9 ++++++
4 files changed, 111 insertions(+), 1 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index f9d6d7e..8aa2079 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -746,6 +746,36 @@
</group>
<group>
<attribute name="type">
+ <value>spice</value>
+ </attribute>
+ <optional>
+ <attribute name="port">
+ <ref name="PortNumber"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="tlsPort">
+ <ref name="PortNumber"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="listen">
+ <ref name="addrIP"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="passwd">
+ <text/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="keymap">
+ <text/>
+ </attribute>
+ </optional>
+ </group>
+ <group>
+ <attribute name="type">
<value>rdp</value>
</attribute>
<optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4930c38..ca5dfc3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -165,7 +165,8 @@ VIR_ENUM_IMPL(virDomainGraphics,
VIR_DOMAIN_GRAPHICS_TYPE_LAST,
"sdl",
"vnc",
"rdp",
- "desktop")
+ "desktop",
+ "spice")
VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
"subsystem",
@@ -267,6 +268,12 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr
def)
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
VIR_FREE(def->data.desktop.display);
break;
+
+ case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+ VIR_FREE(def->data.spice.listenAddr);
+ VIR_FREE(def->data.spice.keymap);
+ VIR_FREE(def->data.spice.passwd);
+ break;
}
VIR_FREE(def);
@@ -1692,6 +1699,38 @@ virDomainGraphicsDefParseXML(virConnectPtr conn,
def->data.desktop.fullscreen = 0;
def->data.desktop.display = virXMLPropString(node, "display");
+ } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ char *port = virXMLPropString(node, "port");
+ char *tlsPort;
+
+ if (port) {
+ if (virStrToLong_i(port, NULL, 10, &def->data.spice.port) < 0)
{
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse spice port %s"),
port);
+ VIR_FREE(port);
+ goto error;
+ }
+ VIR_FREE(port);
+ } else {
+ def->data.spice.port = 5900;
+ }
+
+ tlsPort = virXMLPropString(node, "tlsPort");
+ if (tlsPort) {
+ if (virStrToLong_i(tlsPort, NULL, 10, &def->data.spice.tlsPort)
< 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse spice tlsPort %s"),
tlsPort);
+ VIR_FREE(tlsPort);
+ goto error;
+ }
+ VIR_FREE(tlsPort);
+ } else {
+ def->data.spice.tlsPort = 0;
+ }
+
+ def->data.spice.listenAddr = virXMLPropString(node, "listen");
+ def->data.spice.passwd = virXMLPropString(node, "passwd");
+ def->data.spice.keymap = virXMLPropString(node, "keymap");
}
cleanup:
@@ -4100,6 +4139,30 @@ virDomainGraphicsDefFormat(virConnectPtr conn,
break;
+ case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+ if (def->data.spice.port)
+ virBufferVSprintf(buf, " port='%d'",
+ def->data.spice.port);
+
+ if (def->data.spice.tlsPort)
+ virBufferVSprintf(buf, " tlsPort='%d'",
+ def->data.spice.tlsPort);
+
+ if (def->data.spice.listenAddr)
+ virBufferVSprintf(buf, " listen='%s'",
+ def->data.spice.listenAddr);
+
+ if (def->data.spice.keymap)
+ virBufferEscapeString(buf, " keymap='%s'",
+ def->data.spice.keymap);
+
+ if (def->data.spice.passwd &&
+ (flags & VIR_DOMAIN_XML_SECURE))
+ virBufferEscapeString(buf, " passwd='%s'",
+ def->data.spice.passwd);
+
+ break;
+
}
virBufferAddLit(buf, "/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7ea1152..4cb10d3 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -334,6 +334,7 @@ enum virDomainGraphicsType {
VIR_DOMAIN_GRAPHICS_TYPE_VNC,
VIR_DOMAIN_GRAPHICS_TYPE_RDP,
VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
VIR_DOMAIN_GRAPHICS_TYPE_LAST,
};
@@ -366,6 +367,13 @@ struct _virDomainGraphicsDef {
char *display;
int fullscreen : 1;
} desktop;
+ struct {
+ int port;
+ int tlsPort;
+ char *listenAddr;
+ char *keymap;
+ char *passwd;
+ } spice;
} data;
};
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 7ba0ac2..ae171bc 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2067,6 +2067,12 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
+ if (def->ngraphics > 1) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("only one graphics output is currently
supported"));
+ goto error;
+ }
+
if ((def->ngraphics == 1) &&
def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
virBuffer opt = VIR_BUFFER_INITIALIZER;
@@ -2155,6 +2161,9 @@ int qemudBuildCommandLine(virConnectPtr conn,
*/
ADD_ENV_COPY("QEMU_AUDIO_DRV");
ADD_ENV_COPY("SDL_AUDIODRIVER");
+ } else if (def->ngraphics) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unsupported graphics output requested"));
}
if (def->nvideos) {
--
--
Name: Ben
-------------------------------------------
Msn: liaosongwen(a)live.cn
14 years, 3 months
[libvirt] [PATCH] esx: Use MD5 sum of mount path as storage pool UUID
by Matthias Bolte
With the previous storage pool UUID source not all storage pools
had a proper UUID, especially GSX storage pools. The mount path
is unique per host and cannot change during the lifetime of the
datastore. Therefore, its MD5 sum can be used as UUID.
Use gnulib's crypto/md5 module to generate the MD5 sum.
---
bootstrap.conf | 1 +
src/esx/esx_storage_driver.c | 107 +++++++++++-------------------------------
2 files changed, 28 insertions(+), 80 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index 5af77a7..ca31a6e 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -26,6 +26,7 @@ canonicalize-lgpl
close
connect
count-one-bits
+crypto/md5
dirname-lgpl
fcntl-h
getaddrinfo
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 644e66c..adbe8c6 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -24,6 +24,7 @@
#include <config.h>
+#include "md5.h"
#include "internal.h"
#include "util.h"
#include "memory.h"
@@ -197,10 +198,7 @@ esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
esxPrivate *priv = conn->storagePrivateData;
esxVI_ObjectContent *datastore = NULL;
esxVI_DatastoreHostMount *hostMount = NULL;
- char *suffix = NULL;
- int suffixLength;
- char uuid_string[VIR_UUID_STRING_BUFLEN] = "00000000-00000000-0000-000000000000";
- unsigned char uuid[VIR_UUID_BUFLEN];
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
virStoragePoolPtr pool = NULL;
if (esxVI_EnsureSession(priv->primary) < 0) {
@@ -213,53 +211,22 @@ esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
}
/*
- * Datastores don't have a UUID. We can use the 'host.mountInfo.path'
- * property as source for a "UUID" on ESX, because the property value has
- * this format:
+ * Datastores don't have a UUID, but we can use the 'host.mountInfo.path'
+ * property as source for a UUID. The mount path is unique per host and
+ * cannot change during the lifetime of the datastore.
*
- * host.mountInfo.path = /vmfs/volumes/4b0beca7-7fd401f3-1d7f-000ae484a6a3
- * host.mountInfo.path = /vmfs/volumes/b24b7a78-9d82b4f5 (short format)
- *
- * The 'host.mountInfo.path' property comes in two forms, with a complete
- * "UUID" and a short "UUID".
- *
- * But this trailing "UUID" is not guaranteed to be there. On the other
- * hand we already rely on another implementation detail of the ESX server:
- * The object name of virtual machine contains an integer, we use that as
- * domain ID.
+ * The MD5 sum of the mount path can be used as UUID, assuming MD5 is
+ * considered to be collision-free enough for this use case.
*/
if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
&hostMount) < 0) {
goto cleanup;
}
- if ((suffix = STRSKIP(hostMount->mountInfo->path, "/vmfs/volumes/")) != NULL) {
- suffixLength = strlen(suffix);
+ md5_buffer(hostMount->mountInfo->path,
+ strlen(hostMount->mountInfo->path), md5);
- if ((suffixLength == 35 && /* = strlen("4b0beca7-7fd401f3-1d7f-000ae484a6a3") */
- suffix[8] == '-' && suffix[17] == '-' && suffix[22] == '-') ||
- (suffixLength == 17 && /* = strlen("b24b7a78-9d82b4f5") */
- suffix[8] == '-')) {
- /*
- * Intentionally use memcpy here, because we want to be able to
- * replace a prefix of the initial Zero-UUID. virStrncpy would
- * null-terminate the string in an unwanted place.
- */
- memcpy(uuid_string, suffix, suffixLength);
- } else {
- VIR_WARN("Datastore host mount path suffix '%s' has unexpected "
- "format, cannot deduce a UUID from it", suffix);
- }
- }
-
- if (virUUIDParse(uuid_string, uuid) < 0) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not parse UUID from string '%s'"),
- uuid_string);
- goto cleanup;
- }
-
- pool = virGetStoragePool(conn, name, uuid);
+ pool = virGetStoragePool(conn, name, md5);
cleanup:
esxVI_ObjectContent_Free(&datastore);
@@ -275,9 +242,11 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
esxPrivate *priv = conn->storagePrivateData;
esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
- char *absolutePath = NULL;
char *name = NULL;
virStoragePoolPtr pool = NULL;
@@ -285,48 +254,26 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
return NULL;
}
- /*
- * Convert UUID to 'host.mountInfo.path' form by stripping the second '-':
- *
- * <---- 14 ----><-------- 22 --------> <---- 13 ---><-------- 22 -------->
- * 4b0beca7-7fd4-01f3-1d7f-000ae484a6a3 -> 4b0beca7-7fd401f3-1d7f-000ae484a6a3
- */
- virUUIDFormat(uuid, uuid_string);
- memmove(uuid_string + 13, uuid_string + 14, 22 + 1);
-
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s", uuid_string) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
- esxVI_LookupDatastoreByAbsolutePath(priv->primary, absolutePath,
- propertyNameList, &datastore,
- esxVI_Occurrence_OptionalItem) < 0) {
+ esxVI_LookupDatastoreList(priv->primary, propertyNameList,
+ &datastoreList) < 0) {
goto cleanup;
}
- /*
- * If the first try didn't succeed and the trailing 16 digits are zero then
- * the "UUID" could be a short one. Strip the 16 zeros and try again:
- *
- * <------ 17 -----> <------ 17 ----->
- * b24b7a78-9d82b4f5-0000-000000000000 -> b24b7a78-9d82b4f5
- */
- if (datastore == NULL && STREQ(uuid_string + 17, "-0000-000000000000")) {
- uuid_string[17] = '\0';
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ esxVI_DatastoreHostMount_Free(&hostMount);
- VIR_FREE(absolutePath);
-
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s", uuid_string) < 0) {
- virReportOOMError();
+ if (esxVI_LookupDatastoreHostMount(priv->primary, datastore->obj,
+ &hostMount) < 0) {
goto cleanup;
}
- if (esxVI_LookupDatastoreByAbsolutePath(priv->primary, absolutePath,
- propertyNameList, &datastore,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
+ md5_buffer(hostMount->mountInfo->path,
+ strlen(hostMount->mountInfo->path), md5);
+
+ if (memcmp(uuid, md5, VIR_UUID_BUFLEN) == 0) {
+ break;
}
}
@@ -348,9 +295,9 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
pool = virGetStoragePool(conn, name, uuid);
cleanup:
- VIR_FREE(absolutePath);
esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
+ esxVI_ObjectContent_Free(&datastoreList);
+ esxVI_DatastoreHostMount_Free(&hostMount);
return pool;
}
--
1.7.0.4
14 years, 3 months
[libvirt] [PATCH] esx: Make sure dumpxml outputs proper ID for active domains
by Matthias Bolte
---
src/esx/esx_driver.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 4fb357b..c6bd3b8 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2624,6 +2624,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
esxPrivate *priv = domain->conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
+ esxVI_VirtualMachinePowerState powerState;
+ int id;
char *vmPathName = NULL;
char *datastoreName = NULL;
char *directoryName = NULL;
@@ -2640,11 +2642,14 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
return NULL;
}
- if (esxVI_String_AppendValueToList(&propertyNameList,
- "config.files.vmPathName") < 0 ||
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "config.files.vmPathName\0"
+ "runtime.powerState\0") < 0 ||
esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0 ||
+ esxVI_GetVirtualMachineIdentity(virtualMachine, &id, NULL, NULL) < 0 ||
esxVI_GetStringValue(virtualMachine, "config.files.vmPathName",
&vmPathName, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
@@ -2693,6 +2698,10 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
priv->primary->productVersion);
if (def != NULL) {
+ if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
+ def->id = id;
+ }
+
xml = virDomainDefFormat(def, flags);
}
--
1.7.0.4
14 years, 3 months
[libvirt] inability to open local read-only connection
by Tavares, John
I have been experimenting with using libvirt (0.3.3) on a variety of systems (RHEL, CentOS and Oracle VM). I have run into an issue when I try to open a local read-only connection to the hypervisor that is failing only on Oracle VM server release 2.2.0. I have created a root owned setuid executable that is effectively running as root, but even so, still cannot open the local read-only connection of the hypervisor. It only works if I run it directly as root. This is not an option. I do not understand why it works as is on my RHEL and CentOS machines, but not my Oracle machine. It would seem as thought it is not checking if the effective uid is root, just the uid.
Has anyone run into a similar issue or have any suggestions of what I might try to fix this issue or can tell me that this is a defect that needs (is) fixed??
Thanks.
14 years, 3 months
[libvirt] [PATCH] qemu: Remove code duplication
by Jiri Denemark
We already filled the PCI address structure when we checked whether it's
free or not, so let's just use the structure here instead of filling it
again.
---
src/qemu/qemu_conf.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index c7ed0a3..1c98447 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2258,9 +2258,7 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
}
dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
- dev->addr.pci.domain = 0;
- dev->addr.pci.bus = 0;
- dev->addr.pci.slot = i;
+ dev->addr.pci = maybe.addr.pci;
addrs->nextslot = i + 1;
if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
--
1.7.2
14 years, 3 months
[libvirt] [PATCH] qemu: Check for errors when converting PCI address to string
by Jiri Denemark
---
src/qemu/qemu_conf.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index fb85220..c7ed0a3 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2096,6 +2096,8 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
char *addr = qemuPCIAddressAsString(dev);
+ if (!addr)
+ return -1;
VIR_DEBUG("Remembering PCI addr %s", addr);
@@ -2239,7 +2241,8 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
maybe.addr.pci.bus = 0;
maybe.addr.pci.slot = i;
- addr = qemuPCIAddressAsString(&maybe);
+ if (!(addr = qemuPCIAddressAsString(&maybe)))
+ return -1;
if (virHashLookup(addrs->used, addr)) {
VIR_DEBUG("PCI addr %s already in use", addr);
--
1.7.2
14 years, 3 months
[libvirt] [PATCH] qemu: Fix JSON migrate_set_downtime command
by Jiri Denemark
---
src/qemu/qemu_monitor_json.c | 9 ++-------
1 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e8609aa..8a586bc 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1481,17 +1481,12 @@ int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
unsigned long long downtime)
{
int ret;
- char *downtimestr;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
- if (virAsprintf(&downtimestr, "%llums", downtime) < 0) {
- virReportOOMError();
- return -1;
- }
+
cmd = qemuMonitorJSONMakeCommand("migrate_set_downtime",
- "s:value", downtimestr,
+ "d:value", downtime / 1000.0,
NULL);
- VIR_FREE(downtimestr);
if (!cmd)
return -1;
--
1.7.2
14 years, 3 months
[libvirt] how to Create virtual machine
by Saravanan S
Hi,
I am working on a virtualization project that involves setting up virtual
appliances to implement the same, which tool is required to
1) create virtual appliances
2) deploy virtual appliances
3) manage virtual appliances/virtual machines
Could you please guide me with some pointers or resources to get started
with the creation of virtual machines?
I am little confused with libvirt with Xen and qemu.
how does xen or qemu related with libvirt ?
Thank you.
Saravanan Sundaramoorthy
Red Hat Certified Engineer
http://www.google.com/profiles/dearsaravanan#about
+91 99404 32545
14 years, 3 months
[libvirt] [PATCH 0/2] qemu: Update next usable PCI slot on domain reconnect
by Jiri Denemark
When libvirtd restarted and reconnected to existing domains, we didn't update
nextslot so that hotplug starts with a slot next to the last used one.
Jiri Denemark (2):
qemu: Use structured PCI address as hash payload
qemu: Update next usable PCI slot on domain reconnect
src/qemu/qemu_conf.c | 118 +++++++++++++++++++++++++++++++++++++-----------
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_driver.c | 2 +
3 files changed, 94 insertions(+), 27 deletions(-)
--
1.7.2
14 years, 3 months