Re: [libvirt] [PATCH] Small fixes for qemu save compression.

2009-08-20 Thread Chris Lalancette
Daniel Veillard wrote:
 On Mon, Aug 17, 2009 at 12:37:31PM +0200, Chris Lalancette wrote:
 Fix up a small memory leak pointed out by DanB; I was forgetting
 to release memory allocated to driver-saveImageFormat.
 Also add the save_image_format and security entries to
 the augeas lens.
 
   ACK !

Thanks, committed.

-- 
Chris Lalancette

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] libvirt with libssh2?

2009-08-20 Thread Emre Erenoglu
Hi,
I'm the package maintainer of libvirt for the Pardus distribution. While
trying to update the package to the latest 0.7.0, I recognized that
configure script does not find libssh.

I checked our system and found out that we are using libssh2 instead of
libssh.

From this website (http://www.libssh2.org/libssh2-vs-libssh.html), libssh2
developers summarize their differences.

My questions:
1) Is there a specific reason why we are using libssh? Is there a patch to
make libvirt use libssh2 instead?
2) What functionality do we loose if we don't have libssh in the system?
(depending on this, I'll also package libssh or not)

Thanks a lot for any comments,

Best regards,
Emre Erenoglu
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] libvirt with libssh2?

2009-08-20 Thread Daniel Veillard
On Thu, Aug 20, 2009 at 10:50:37AM +0200, Emre Erenoglu wrote:
 Hi,
 I'm the package maintainer of libvirt for the Pardus distribution. While
 trying to update the package to the latest 0.7.0, I recognized that
 configure script does not find libssh.
 
 I checked our system and found out that we are using libssh2 instead of
 libssh.
 
 From this website (http://www.libssh2.org/libssh2-vs-libssh.html), libssh2
 developers summarize their differences.
 
 My questions:
 1) Is there a specific reason why we are using libssh? Is there a patch to
 make libvirt use libssh2 instead?
 2) What functionality do we loose if we don't have libssh in the system?
 (depending on this, I'll also package libssh or not)

  I guess you activated --with-phyp which currently requires libssh,
but this will be fixed in the future, the result is just that that
driver gets desactivated for now if you don't have libssh

   see http://www.mail-archive.com/libvir-list@redhat.com/msg15086.html

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
dan...@veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Power Hypervisor: Fix potential segfault and memleak in phypOpen

2009-08-20 Thread Chris Lalancette
Matthias Bolte wrote:
 Hi,
 
 I came across this line in the phypOpen function:
 
 char string[strlen(conn-uri-path)];
 
 Here the path part of the given URI is used without checking it for
 NULL, this can cause a segfault as strlen expects a string != NULL.
 Beside that uuid_db and connection_data leak in case of an error.
 
 In this line
 
 conn-uri-path = string;
 
 the original path of the URI leaks. The patch adds a VIR_FREE call
 before setting the new path.
 
 The attached patch is compile-tested but I don't have a Power
 Hypervisor installation at hand to test it for real.

I've now committed this patch (with some slight munging to get it to apply to
recent libvirt.git).

Thanks,
-- 
Chris Lalancette

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Power Hypervisor: Fix potential segfault and memleak in phypOpen

2009-08-20 Thread Matthias Bolte
2009/8/20 Chris Lalancette clala...@redhat.com:
 Matthias Bolte wrote:
 Hi,

 I came across this line in the phypOpen function:

 char string[strlen(conn-uri-path)];

 Here the path part of the given URI is used without checking it for
 NULL, this can cause a segfault as strlen expects a string != NULL.
 Beside that uuid_db and connection_data leak in case of an error.

 In this line

 conn-uri-path = string;

 the original path of the URI leaks. The patch adds a VIR_FREE call
 before setting the new path.

 The attached patch is compile-tested but I don't have a Power
 Hypervisor installation at hand to test it for real.

 I've now committed this patch (with some slight munging to get it to apply to
 recent libvirt.git).

 Thanks,
 --
 Chris Lalancette


Well, you should have applied version 2 of this patch, because version
1 was invalidated by changes to escape_specialcharacters(). It now
takes a length argument, but string isn't an array anymore (but a char
pointer), so sizeof(string) does no longer the right thing:

escape_specialcharacters(conn-uri-path, string, sizeof(string))

I attached patch version 2 again.

Matthias
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index f457cf4..9b46696 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -63,25 +63,18 @@ static virDrvOpenStatus
 phypOpen(virConnectPtr conn,
  virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
 {
-SSH_SESSION *session;
-ConnectionData *connection_data;
-char string[strlen(conn-uri-path)];
-
+SSH_SESSION *session = NULL;
+ConnectionData *connection_data = NULL;
+char *string = NULL;
+size_t len = 0;
 uuid_dbPtr uuid_db = NULL;
 
-if (VIR_ALLOC(uuid_db)  0)
-virReportOOMError(conn);
-
-if (VIR_ALLOC(connection_data)  0)
-virReportOOMError(conn);
-
 if (!conn || !conn-uri)
 return VIR_DRV_OPEN_DECLINED;
 
 if (conn-uri-scheme == NULL || STRNEQ(conn-uri-scheme, phyp))
 return VIR_DRV_OPEN_DECLINED;
 
-
 if (conn-uri-server == NULL) {
 virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
   VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, %s,
@@ -96,20 +89,38 @@ phypOpen(virConnectPtr conn,
 return VIR_DRV_OPEN_ERROR;
 }
 
-if (escape_specialcharacters(conn-uri-path, string, sizeof(string)) == -1) {
+if (VIR_ALLOC(uuid_db)  0) {
+virReportOOMError(conn);
+goto failure;
+}
+
+if (VIR_ALLOC(connection_data)  0) {
+virReportOOMError(conn);
+goto failure;
+}
+
+len = strlen(conn-uri-path) + 1;
+
+if (VIR_ALLOC_N(string, len)  0) {
+virReportOOMError(conn);
+goto failure;
+}
+
+if (escape_specialcharacters(conn-uri-path, string, len) == -1) {
 virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
   VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, %s,
   _(Error parsing 'path'. Invalid characters.));
-return VIR_DRV_OPEN_ERROR;
+goto failure;
 }
 
 if ((session = openSSHSession(conn, auth)) == NULL) {
 virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
   VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, %s,
   _(Error while opening SSH session.));
-return VIR_DRV_OPEN_ERROR;
+goto failure;
 }
 
+VIR_FREE(conn-uri-path);
 conn-uri-path = string;
 connection_data-session = session;
 connection_data-auth = auth;
@@ -122,6 +133,13 @@ phypOpen(virConnectPtr conn,
 init_uuid_db(conn);
 
 return VIR_DRV_OPEN_SUCCESS;
+
+  failure:
+VIR_FREE(uuid_db);
+VIR_FREE(connection_data);
+VIR_FREE(string);
+
+return VIR_DRV_OPEN_ERROR;
 }
 
 static int
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] Introduce virStrcpy.

2009-08-20 Thread Chris Lalancette
Daniel P. Berrange wrote:
 On Fri, Aug 07, 2009 at 11:06:29AM +0200, Chris Lalancette wrote:
 diff --git a/proxy/libvirt_proxy.c b/proxy/libvirt_proxy.c
 index e008a7f..42084c7 100644
 --- a/proxy/libvirt_proxy.c
 +++ b/proxy/libvirt_proxy.c
 @@ -167,10 +167,13 @@ proxyListenUnixSocket(const char *path) {
   * Abstract socket do not hit the filesystem, way more secure and
   * guaranteed to be atomic
   */
 -memset(addr, 0, sizeof(addr));
  addr.sun_family = AF_UNIX;
  addr.sun_path[0] = '\0';
 -strncpy(addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
 +if (virStrcpy(addr.sun_path[1], path, sizeof(addr.sun_path) - 1) == 
 NULL) {
 +fprintf(stderr, Path %s too long to fit into destination\n, path);
 +close(fd);
 +return -1;
 +}
 
 Removing the memset is not safe - the abstract namesapce defines
 the name to be the *entire* addr.sun_path  array. So it must be
 null filled, otherwise the name will be the string copied + whatever
 trailing garbage exists

Ug, OK, thanks, I've fixed all instances of this.

 diff --git a/src/qemu_driver.c b/src/qemu_driver.c
 index 37fdec2..bcacd41 100644
 --- a/src/qemu_driver.c
 +++ b/src/qemu_driver.c
 @@ -5802,8 +5806,11 @@ static int qemuGetSchedulerParameters(virDomainPtr 
 dom,
  goto cleanup;
  }
  params[0].value.ul = val;
 -strncpy(params[0].field, cpu_shares, sizeof(params[0].field));
 -params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
 +if (virStrcpy(params[0].field, cpu_shares, sizeof(params[0].field)) 
 == NULL) {
 +qemudReportError(dom-conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
 + %s, _(Field cpu_shares too long for 
 destination));
 +goto cleanup;
 +}
 
 Why remove the assginemnt to 'type' here ?

Oversight on my part, thanks for pointing it out.  Fixed now.

 @@ -1573,6 +1572,28 @@ virAsprintf(char **strp, const char *fmt, ...)
  return ret;
  }
  
 +/**
 + * virStrcpy
 + *
 + * A safe version of strcpy.  The last parameter is the number of bytes
 + * available in the destination string, *not* the number of bytes you want
 + * to copy.  If the destination is not large enough to hold all of the
 + * src string, NULL is returned and no data is copied.  If the destination
 + * is large enough to hold all of the src, then the string is copied and
 + * a pointer to the destination string is returned.
 + */
 +char *
 +virStrcpy(char *dest, const char *src, size_t destbytes)
 +{
 +int len;
 +
 +len = strlen(src) + 1;
 +if (len  destbytes)
 +return NULL;
 +
 +return memcpy(dest, src, len);
 +}
 
 Why not just use strncpy() and ensure the trailing null. Seems
 like it would be more efficient than requiring 2 passes over
 the string.

Hm, I'm not entirely sure I understand you.  Do you mean something like:

char *
virStrcpy(char *dest, const char *src, size_t destbytes)
{
char *ret;

ret = strncpy(dest, src, destbytes);
if (ret)
   ret[destbytes - 1] = '\0';

return ret;
}

But in this case, there is nowhere that I can return NULL if the destination is
too short.  Any solution I can think of in the current form requires me to run
strlen over the source to check that it isn't too big for the dest.

Hm, here's another thought.  Maybe I should make the signature:

char *
virStrcpy(char *dest, const char *src, size_t srclen, size_t destbytes);

Then, the first three parameters would actually be exactly the same as for
strncpy() (meaning that you could tell it to stop copying short of the \0 in
src).  The additional destbytes parameter is the safety parameter to make sure
the dest is big enough.  Of course, this sort of just punts the two-pass
strlen() problem off to the callers, but for callers that already know the
length they can just pass it in here without an additional penalty.

Or did you have another idea?

 index b3e628a..ffbf2b3 100644
 --- a/src/util.h
 +++ b/src/util.h
 @@ -164,6 +164,7 @@ void virSkipSpaces(const char **str);
  int virParseNumber(const char **str);
  int virAsprintf(char **strp, const char *fmt, ...)
  ATTRIBUTE_FMT_PRINTF(2, 3);
 +char *virStrcpy(char *dest, const char *src, size_t destbytes);
 
 THis is probably a candidate for ATTRIBUTE_RETURN_CHECK to 
 guarentee that all callers are dealing with the failure case
 at compile time

Done.

 
 
 @@ -1026,42 +1043,46 @@ xenXMDomainConfigParse(virConnectPtr conn, 
 virConfPtr conf) {
  data++;
  
  if (STRPREFIX(key, mac=)) {
 -int len = nextkey ? (nextkey - data) : 17;
 -if (len  17)
 -len = 17;
 -strncpy(mac, data, len);
 -mac[len] = '\0';
 +if (virStrcpy(mac, data, sizeof(mac)) == NULL) {
 +xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
 +   _(MAC address %s too big for 
 destination),
 + 

Re: [libvirt] Power Hypervisor: Fix potential segfault and memleak in phypOpen

2009-08-20 Thread Chris Lalancette
Matthias Bolte wrote:
 2009/8/20 Chris Lalancette clala...@redhat.com:
 Matthias Bolte wrote:
 Hi,

 I came across this line in the phypOpen function:

 char string[strlen(conn-uri-path)];

 Here the path part of the given URI is used without checking it for
 NULL, this can cause a segfault as strlen expects a string != NULL.
 Beside that uuid_db and connection_data leak in case of an error.

 In this line

 conn-uri-path = string;

 the original path of the URI leaks. The patch adds a VIR_FREE call
 before setting the new path.

 The attached patch is compile-tested but I don't have a Power
 Hypervisor installation at hand to test it for real.
 I've now committed this patch (with some slight munging to get it to apply to
 recent libvirt.git).

 Thanks,
 --
 Chris Lalancette

 
 Well, you should have applied version 2 of this patch, because version
 1 was invalidated by changes to escape_specialcharacters(). It now
 takes a length argument, but string isn't an array anymore (but a char
 pointer), so sizeof(string) does no longer the right thing:
 
 escape_specialcharacters(conn-uri-path, string, sizeof(string))
 
 I attached patch version 2 again.

Gah, sorry, I totally missed (or forgot about) that.  I'll apply the incremental
diff, thanks.

-- 
Chris Lalancette

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] libvirt with libssh2?

2009-08-20 Thread Emre Erenoglu

 -- Forwarded message --
 From: Daniel Veillard veill...@redhat.com
 To: Emre Erenoglu ereno...@gmail.com
 Date: Thu, 20 Aug 2009 11:14:53 +0200
 Subject: Re: [libvirt] libvirt with libssh2?
 On Thu, Aug 20, 2009 at 10:50:37AM +0200, Emre Erenoglu wrote:
  Hi,
  I'm the package maintainer of libvirt for the Pardus distribution. While
  trying to update the package to the latest 0.7.0, I recognized that
  configure script does not find libssh.
 
  I checked our system and found out that we are using libssh2 instead of
  libssh.
 
  From this website (http://www.libssh2.org/libssh2-vs-libssh.html),
 libssh2
  developers summarize their differences.
 
  My questions:
  1) Is there a specific reason why we are using libssh? Is there a patch
 to
  make libvirt use libssh2 instead?
  2) What functionality do we loose if we don't have libssh in the system?
  (depending on this, I'll also package libssh or not)

  I guess you activated --with-phyp which currently requires libssh,
 but this will be fixed in the future, the result is just that that
 driver gets desactivated for now if you don't have libssh

   see http://www.mail-archive.com/libvir-list@redhat.com/msg15086.html


Thanks Daniel. I'm a bit foreign to this Power Hypervisor thing, but if
I'm not wrong from the information that I got from this site:
http://publib.boulder.ibm.com/infocenter/systems/scope/hw/index.jsp?topic=/iphb2/iphb2hypervisor.htm

than it's nothing that we support in Pardus at the moment. In fact, we only
support KVM in our libvirt at the moment, possibly virtualbox in the future.

In this case, I'm disabling this pyhp as well as the libssh dependency.

Thanks a lot for the info and let me know if my understanding is wrong :)

-- 
Emre
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] Migration fail

2009-08-20 Thread Christian Hennig
hi,

i am trying to migrate a VM from my local system pc38  to a remote on
pc36:


virsh # list --all
 Id Name State
--
  - scalaris1shut off

virsh # migrate scalaris1 qemu+ssh://csr-u...@pc36/system
error: monitor socket did not show up.: No such file or directory


What is the monitor socket?

Both system are  ubuntu server 9.04 :


christ...@pc38:~$ virsh --version
Connecting to uri: qemu:///system
0.6.1
christ...@pc38:~$

Thx for help!

Christian
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Migration fail

2009-08-20 Thread Chris Lalancette
Christian Hennig wrote:
 hi,
 
 i am trying to migrate a VM from my local system pc38  to a remote on
 pc36:
 
 
 virsh # list --all
  Id Name State
 --
   - scalaris1shut off
 
 virsh # migrate scalaris1 qemu+ssh://csr-u...@pc36/system
 error: monitor socket did not show up.: No such file or directory
 
 
 What is the monitor socket?

The monitor socket is how libvirt talks to the qemu monitor to issue commands.
Things like virsh suspend are implemented by issuing a stop command to the
qemu monitor, and it's fundamental to libvirt operation.

The monitor socket did not show up error occurs if libvirt could not connect
to the monitor after trying for 3 seconds; it usually means that qemu forked
successfully, but failed to really start.  You should be able to get a bit more
information by looking at /var/log/libvirt/qemu/guestname on the destination
of your migration.

That being said, I think 0.6.1 had a number of race conditions, so it's probably
worthwhile to try and get a newer version of libvirt; 0.6.4 or later should be
pretty good.

-- 
Chris Lalancette

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] Add support for (qcow*) volume encryption (v4)

2009-08-20 Thread Miloslav Trmač
Hello,
the following patches add full support for qcow/qcow2 volume encryption,
assuming a client that supports it.

(Main changes since the previous version:
 * Add flags argument to virSecretDefineXML(), virSecretGetXMLDesc(),
   virSecretSetValue(), virSecretGetValue()
 * Various clean-ups and bug fixes in the local secret storage driver
 * Make the Python API more consistent with other objects
 See the specific patch change logs for more details; patches without
 change logs are unchanged.)

New XML tags are defined to represent encryption parameters (currently
format and passphrase, more can be added in the future), e.g.
 encryption format='qcow'
   secret type='passphrase'
   uuid='724d95f2-0ed2-6ff9-84d0-0f3d1618428d'/
 /encryption

The encryption tag can be added to a volume node passed to
virStorageVolCreateXML() to create an encrypted volume, or to a
disk node inside a domain to specify what encryption parameters to
use for a domain.

uuid above refers to a separately-managed secret, which was created
using virSecretDefineXML() and set using virSecretSetValue().  Other
properties of the secret can be managed using an XML representation.

Detailed documentation of the formats and features is inside the patches.


--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 01/20] Secret manipulation step 1: Public API

2009-08-20 Thread Miloslav Trmač
This patch adds a secret as a separately managed object, using a
special-purpose API to transfer the secret values between nodes and
libvirt users.

Rather than add explicit accessors for attributes of secrets, and
hard-code the secrets are related to storage volumes association in
the API, the API uses XML to manipulate the association as well as
other attributes, similarly to other areas of libvirt.

The user can set attributes of the secret using XML, e.g.
  secret ephemeral='no' private='yes'
uuidb8eecf55-798e-4db7-b2dd-025b0cf08a36/uuid
volume/var/lib/libvirt/images/mail.img/volume
descriptionLUKS passphrase for our mail server/description
  /secret
If uuid/ is not specified, it is chosen automatically.

The secret value can be either generated and stored by libvirt during
volume creation, or supplied by the user using virSecretSetValue().

A simple API is provided for enumeration of all secrets.  Very large
deployments will manage secret IDs automatically, so it is probably not
necessary to provide a specialized lookup function (allowing the volume
key - secret ID lookup in less than O(number of secrets)).  These
functions can eventually be added later.

Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 docs/format.html |4 +
 docs/formatcaps.html |4 +
 docs/formatdomain.html   |4 +
 docs/formatnetwork.html  |4 +
 docs/formatnode.html |4 +
 docs/formatsecret.html   |  170 ++
 docs/formatsecret.html.in|   52 +
 docs/formatstorage.html  |4 +
 docs/schemas/Makefile.am |1 +
 docs/schemas/secret.rng  |   44 +++
 docs/sitemap.html|3 +
 docs/sitemap.html.in |4 +
 include/libvirt/libvirt.h|   38 +
 include/libvirt/libvirt.h.in |   38 +
 src/libvirt_public.syms  |   16 
 15 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 docs/formatsecret.html
 create mode 100644 docs/formatsecret.html.in
 create mode 100644 docs/schemas/secret.rng

diff --git a/docs/format.html b/docs/format.html
index e97d0e7..3c20b5f 100644
--- a/docs/format.html
+++ b/docs/format.html
@@ -70,6 +70,10 @@
 div
   a title=The host device XML format 
class=inactive href=formatnode.htmlNode Devices/a
 /div
+  /lili
+div
+  a title=The secret XML format class=inactive 
href=formatsecret.htmlSecrets/a
+/div
   /li/ul
   /div
 /lili
diff --git a/docs/formatcaps.html b/docs/formatcaps.html
index 5b20aac..5f2bc72 100644
--- a/docs/formatcaps.html
+++ b/docs/formatcaps.html
@@ -70,6 +70,10 @@
 div
   a title=The host device XML format 
class=inactive href=formatnode.htmlNode Devices/a
 /div
+  /lili
+div
+  a title=The secret XML format class=inactive 
href=formatsecret.htmlSecrets/a
+/div
   /li/ul
   /div
 /lili
diff --git a/docs/formatdomain.html b/docs/formatdomain.html
index 5415200..6b655ad 100644
--- a/docs/formatdomain.html
+++ b/docs/formatdomain.html
@@ -70,6 +70,10 @@
 div
   a title=The host device XML format 
class=inactive href=formatnode.htmlNode Devices/a
 /div
+  /lili
+div
+  a title=The secret XML format class=inactive 
href=formatsecret.htmlSecrets/a
+/div
   /li/ul
   /div
 /lili
diff --git a/docs/formatnetwork.html b/docs/formatnetwork.html
index 0b25a0b..72a3cda 100644
--- a/docs/formatnetwork.html
+++ b/docs/formatnetwork.html
@@ -70,6 +70,10 @@
 div
   a title=The host device XML format 
class=inactive href=formatnode.htmlNode Devices/a
 /div
+  /lili
+div
+  a title=The secret XML format class=inactive 
href=formatsecret.htmlSecrets/a
+/div
   /li/ul
   /div
 /lili
diff --git a/docs/formatnode.html b/docs/formatnode.html
index 4d30b0c..516c27b 100644
--- a/docs/formatnode.html
+++ b/docs/formatnode.html
@@ -70,6 +70,10 @@
 div
   span class=activeNode Devices/span
 /div
+  /lili
+div
+

[libvirt] [PATCH 02/20] Secret manipulation step 2: Internal API

2009-08-20 Thread Miloslav Trmač
Adds a new driver type.

Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
- Fix a copypasted comment
---
 include/libvirt/virterror.h |1 +
 src/datatypes.c |  155 +++
 src/datatypes.h |   28 
 src/driver.h|   61 +
 src/libvirt.c   |   53 +++
 src/libvirt_private.syms|2 +
 src/virterror.c |6 ++
 7 files changed, 306 insertions(+), 0 deletions(-)

diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e4d013f..5cbb120 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -166,6 +166,7 @@ typedef enum {
 VIR_ERR_NO_INTERFACE, /* interface driver not running */
 VIR_ERR_INVALID_INTERFACE, /* invalid interface object */
 VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
+VIR_WAR_NO_SECRET, /* failed to start secret storage */
 } virErrorNumber;
 
 /**
diff --git a/src/datatypes.c b/src/datatypes.c
index d03a679..2e85196 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -109,6 +109,23 @@ virStorageVolFreeName(virStorageVolPtr vol, const char 
*name ATTRIBUTE_UNUSED)
 }
 
 /**
+ * virSecretFreeName:
+ * @secret_: a secret object
+ *
+ * Destroy the secret object, this is just used by the secret hash callback.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+static void
+virSecretFreeName(void *secret_, const char *name ATTRIBUTE_UNUSED)
+{
+virSecretPtr secret;
+
+secret = secret_;
+virUnrefSecret(secret);
+}
+
+/**
  * virGetConnect:
  *
  * Allocates a new hypervisor connection structure
@@ -152,6 +169,9 @@ virGetConnect(void) {
 ret-nodeDevices = virHashCreate(256);
 if (ret-nodeDevices == NULL)
 goto failed;
+ret-secrets = virHashCreate(20);
+if (ret-secrets == NULL)
+goto failed;
 
 ret-refs = 1;
 return(ret);
@@ -170,6 +190,8 @@ failed:
 virHashFree(ret-storageVols, (virHashDeallocator) 
virStorageVolFreeName);
 if (ret-nodeDevices != NULL)
 virHashFree(ret-nodeDevices, (virHashDeallocator) 
virNodeDeviceFree);
+if (ret-secrets != NULL)
+virHashFree(ret-secrets, virSecretFreeName);
 
 virMutexDestroy(ret-lock);
 VIR_FREE(ret);
@@ -201,6 +223,8 @@ virReleaseConnect(virConnectPtr conn) {
 virHashFree(conn-storageVols, (virHashDeallocator) 
virStorageVolFreeName);
 if (conn-nodeDevices != NULL)
 virHashFree(conn-nodeDevices, (virHashDeallocator) virNodeDeviceFree);
+if (conn-secrets != NULL)
+virHashFree(conn-secrets, virSecretFreeName);
 
 virResetError(conn-err);
 
@@ -246,6 +270,8 @@ virUnrefConnect(virConnectPtr conn) {
 conn-storageDriver-close (conn);
 if (conn-deviceMonitor)
 conn-deviceMonitor-close (conn);
+if (conn-secretDriver)
+conn-secretDriver-close (conn);
 if (conn-driver)
 conn-driver-close (conn);
 
@@ -1129,3 +1155,132 @@ virUnrefNodeDevice(virNodeDevicePtr dev) {
 virMutexUnlock(dev-conn-lock);
 return (refs);
 }
+
+/**
+ * virGetSecret:
+ * @conn: the hypervisor connection
+ * @uuid: secret UUID
+ *
+ * Lookup if the secret is already registered for that connection, if so return
+ * a pointer to it, otherwise allocate a new structure, and register it in the
+ * table. In any case a corresponding call to virFreeSecret() is needed to not
+ * leak data.
+ *
+ * Returns a pointer to the secret, or NULL in case of failure
+ */
+virSecretPtr
+virGetSecret(virConnectPtr conn, const char *uuid)
+{
+virSecretPtr ret = NULL;
+
+if (!VIR_IS_CONNECT(conn) || uuid == NULL) {
+virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+return NULL;
+}
+virMutexLock(conn-lock);
+
+ret = virHashLookup(conn-secrets, uuid);
+if (ret == NULL) {
+if (VIR_ALLOC(ret)  0) {
+virMutexUnlock(conn-lock);
+virReportOOMError(conn);
+goto error;
+}
+ret-magic = VIR_SECRET_MAGIC;
+ret-conn = conn;
+ret-uuid = strdup(uuid);
+if (ret-uuid == NULL) {
+virMutexUnlock(conn-lock);
+virReportOOMError(conn);
+goto error;
+}
+
+if (virHashAddEntry(conn-secrets, uuid, ret)  0) {
+virMutexUnlock(conn-lock);
+virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
+%s, _(failed to add secret to conn hash 
table));
+goto error;
+}
+conn-refs++;
+}
+ret-refs++;
+virMutexUnlock(conn-lock);
+return ret;
+
+error:
+if (ret != NULL) {
+VIR_FREE(ret-uuid);
+VIR_FREE(ret);
+}
+return NULL;
+}
+
+/**
+ * virReleaseSecret:
+ * @secret: 

[libvirt] [PATCH 03/20] Secret manipulation step 3: Public API implementation

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 include/libvirt/virterror.h |2 +
 src/libvirt.c   |  504 +++
 src/virterror.c |9 +
 3 files changed, 515 insertions(+), 0 deletions(-)

diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 5cbb120..62cad88 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -67,6 +67,7 @@ typedef enum {
 VIR_FROM_ONE,   /* Error from OpenNebula driver */
 VIR_FROM_ESX,   /* Error from ESX driver */
 VIR_FROM_PHYP,  /* Error from IBM power hypervisor */
+VIR_FROM_SECRET,/* Error from secret storage */
 } virErrorDomain;
 
 
@@ -167,6 +168,7 @@ typedef enum {
 VIR_ERR_INVALID_INTERFACE, /* invalid interface object */
 VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
 VIR_WAR_NO_SECRET, /* failed to start secret storage */
+VIR_ERR_INVALID_SECRET, /* invalid secret */
 } virErrorNumber;
 
 /**
diff --git a/src/libvirt.c b/src/libvirt.c
index bea60f4..c544297 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -562,6 +562,31 @@ virLibNodeDeviceError(virNodeDevicePtr dev, virErrorNumber 
error,
 }
 
 /**
+ * virLibSecretError:
+ * @secret: the secret if available
+ * @error: the error number
+ * @info: extra information string
+ *
+ * Handle an error at the secret level
+ */
+static void
+virLibSecretError(virSecretPtr secret, virErrorNumber error, const char *info)
+{
+virConnectPtr conn = NULL;
+const char *errmsg;
+
+if (error == VIR_ERR_OK)
+return;
+
+errmsg = virErrorMsg(error, info);
+if (error != VIR_ERR_INVALID_SECRET)
+conn = secret-conn;
+
+virRaiseError(conn, NULL, NULL, VIR_FROM_SECRET, error, VIR_ERR_ERROR,
+  errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/**
  * virRegisterNetworkDriver:
  * @driver: pointer to a network driver block
  *
@@ -8679,3 +8704,482 @@ error:
 virSetConnError(conn);
 return -1;
 }
+
+/**
+ * virSecretGetConnect:
+ * @secret: A virSecret secret
+ *
+ * Provides the connection pointer associated with a secret.  The reference
+ * counter on the connection is not increased by this call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do not use this
+ * function.  Instead, store the connection and the secret object together.
+ *
+ * Returns the virConnectPtr or NULL in case of failure.
+ */
+virConnectPtr
+virSecretGetConnect (virSecretPtr secret)
+{
+DEBUG(secret=%p, secret);
+
+virResetLastError();
+
+if (!VIR_IS_CONNECTED_SECRET (secret)) {
+virLibSecretError (NULL, VIR_ERR_INVALID_SECRET, __FUNCTION__);
+return NULL;
+}
+return secret-conn;
+}
+
+/**
+ * virConnectNumOfSecrets:
+ * @conn: virConnect connection
+ *
+ * Fetch number of currently defined secrets.
+ *
+ * Returns the number currently defined secrets.
+ */
+int
+virConnectNumOfSecrets(virConnectPtr conn)
+{
+VIR_DEBUG(conn=%p, conn);
+
+virResetLastError();
+
+if (!VIR_IS_CONNECT(conn)) {
+virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+return -1;
+}
+
+if (conn-secretDriver != NULL 
+conn-secretDriver-numOfSecrets != NULL) {
+int ret;
+
+ret = conn-secretDriver-numOfSecrets(conn);
+if (ret  0)
+goto error;
+return ret;
+}
+
+virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+/* Copy to connection error object for back compatability */
+virSetConnError(conn);
+return -1;
+}
+
+/**
+ * virConnectListSecrets:
+ * @conn: virConnect connection
+ * @uuids: Pointer to an array to store the UUIDs
+ * @maxuuids: size of the array.
+ *
+ * List UUIDs of defined secrets, store pointers to names in uuids.
+ *
+ * Returns the number of UUIDs provided in the array, or -1 on failure.
+ */
+int
+virConnectListSecrets(virConnectPtr conn, char **uuids, int maxuuids)
+{
+VIR_DEBUG(conn=%p, uuids=%p, maxuuids=%d, conn, uuids, maxuuids);
+
+virResetLastError();
+
+if (!VIR_IS_CONNECT(conn)) {
+virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+return -1;
+}
+if (uuids == NULL || maxuuids  0) {
+virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+goto error;
+}
+
+if (conn-secretDriver != NULL  conn-secretDriver-listSecrets != NULL) 
{
+int ret;
+
+ret = conn-secretDriver-listSecrets(conn, uuids, maxuuids);
+if (ret  0)
+goto error;
+return ret;
+}
+
+virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+/* Copy to connection error object for back compatability */
+virSetConnError(conn);
+return -1;
+}
+
+/**
+ * virSecretLookupByUUIDString:
+ * @conn: virConnect 

[libvirt] [PATCH 04/20] Secret manipulation step 4: Wire protocol

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 qemud/remote_dispatch_args.h   |7 ++
 qemud/remote_dispatch_prototypes.h |   56 ++
 qemud/remote_dispatch_ret.h|6 ++
 qemud/remote_dispatch_table.h  |   40 ++
 qemud/remote_protocol.c|  140 
 qemud/remote_protocol.h|  122 +++
 qemud/remote_protocol.x|   83 +-
 7 files changed, 453 insertions(+), 1 deletions(-)

diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h
index 9dacfb8..dcf7ddf 100644
--- a/qemud/remote_dispatch_args.h
+++ b/qemud/remote_dispatch_args.h
@@ -117,3 +117,10 @@
 remote_domain_xml_from_native_args val_remote_domain_xml_from_native_args;
 remote_domain_xml_to_native_args val_remote_domain_xml_to_native_args;
 remote_list_defined_interfaces_args 
val_remote_list_defined_interfaces_args;
+remote_list_secrets_args val_remote_list_secrets_args;
+remote_secret_lookup_by_uuid_string_args 
val_remote_secret_lookup_by_uuid_string_args;
+remote_secret_define_xml_args val_remote_secret_define_xml_args;
+remote_secret_get_xml_desc_args val_remote_secret_get_xml_desc_args;
+remote_secret_set_value_args val_remote_secret_set_value_args;
+remote_secret_get_value_args val_remote_secret_get_value_args;
+remote_secret_undefine_args val_remote_secret_undefine_args;
diff --git a/qemud/remote_dispatch_prototypes.h 
b/qemud/remote_dispatch_prototypes.h
index d9f6aad..647f5bb 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -513,6 +513,13 @@ static int remoteDispatchListNetworks(
 remote_error *err,
 remote_list_networks_args *args,
 remote_list_networks_ret *ret);
+static int remoteDispatchListSecrets(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_list_secrets_args *args,
+remote_list_secrets_ret *ret);
 static int remoteDispatchListStoragePools(
 struct qemud_server *server,
 struct qemud_client *client,
@@ -758,6 +765,13 @@ static int remoteDispatchNumOfNetworks(
 remote_error *err,
 void *args,
 remote_num_of_networks_ret *ret);
+static int remoteDispatchNumOfSecrets(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+void *args,
+remote_num_of_secrets_ret *ret);
 static int remoteDispatchNumOfStoragePools(
 struct qemud_server *server,
 struct qemud_client *client,
@@ -772,6 +786,48 @@ static int remoteDispatchOpen(
 remote_error *err,
 remote_open_args *args,
 void *ret);
+static int remoteDispatchSecretDefineXml(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_define_xml_args *args,
+remote_secret_define_xml_ret *ret);
+static int remoteDispatchSecretGetValue(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_get_value_args *args,
+remote_secret_get_value_ret *ret);
+static int remoteDispatchSecretGetXmlDesc(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_get_xml_desc_args *args,
+remote_secret_get_xml_desc_ret *ret);
+static int remoteDispatchSecretLookupByUuidString(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_lookup_by_uuid_string_args *args,
+remote_secret_lookup_by_uuid_string_ret *ret);
+static int remoteDispatchSecretSetValue(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_set_value_args *args,
+void *ret);
+static int remoteDispatchSecretUndefine(
+struct qemud_server *server,
+struct qemud_client *client,
+virConnectPtr conn,
+remote_error *err,
+remote_secret_undefine_args *args,
+void *ret);
 static int remoteDispatchStoragePoolBuild(
 struct qemud_server *server,
 struct qemud_client *client,
diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h
index 5376960..9d74a27 100644
--- a/qemud/remote_dispatch_ret.h
+++ b/qemud/remote_dispatch_ret.h
@@ -99,3 +99,9 @@
 remote_domain_xml_to_native_ret val_remote_domain_xml_to_native_ret;
 remote_num_of_defined_interfaces_ret 
val_remote_num_of_defined_interfaces_ret;
 remote_list_defined_interfaces_ret val_remote_list_defined_interfaces_ret;
+remote_num_of_secrets_ret val_remote_num_of_secrets_ret;
+remote_list_secrets_ret val_remote_list_secrets_ret;
+

[libvirt] [PATCH 06/20] Secret manipulation step 6: RPC dispatcher

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 qemud/remote.c |  203 
 1 files changed, 203 insertions(+), 0 deletions(-)

diff --git a/qemud/remote.c b/qemud/remote.c
index d32d513..2258dec 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -64,12 +64,14 @@ static virNetworkPtr get_nonnull_network (virConnectPtr 
conn, remote_nonnull_net
 static virInterfacePtr get_nonnull_interface (virConnectPtr conn, 
remote_nonnull_interface iface);
 static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, 
remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, 
remote_nonnull_storage_vol vol);
+static virSecretPtr get_nonnull_secret (virConnectPtr conn, 
remote_nonnull_secret secret);
 static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr 
dom_src);
 static void make_nonnull_network (remote_nonnull_network *net_dst, 
virNetworkPtr net_src);
 static void make_nonnull_interface (remote_nonnull_interface *interface_dst, 
virInterfacePtr interface_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, 
virStoragePoolPtr pool_src);
 static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, 
virStorageVolPtr vol_src);
 static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, 
virNodeDevicePtr dev_src);
+static void make_nonnull_secret (remote_nonnull_secret *secret_dst, 
virSecretPtr secret_src);
 
 
 #include remote_dispatch_prototypes.h
@@ -4515,6 +4517,195 @@ error:
 VIR_FREE(msg);
 }
 
+static int
+remoteDispatchNumOfSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
+struct qemud_client *client ATTRIBUTE_UNUSED,
+virConnectPtr conn, remote_error *err,
+void *args ATTRIBUTE_UNUSED,
+remote_num_of_secrets_ret *ret)
+{
+ret-num = virConnectNumOfSecrets (conn);
+if (ret-num == -1) {
+remoteDispatchConnError (err, conn);
+return -1;
+}
+
+return 0;
+}
+
+static int
+remoteDispatchListSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
+   struct qemud_client *client ATTRIBUTE_UNUSED,
+   virConnectPtr conn, remote_error *err,
+   remote_list_secrets_args *args,
+   remote_list_secrets_ret *ret)
+{
+if (args-maxuuids  REMOTE_SECRET_UUID_LIST_MAX) {
+remoteDispatchFormatError (err, %s,
+   _(maxuuids  
REMOTE_SECRET_UUID_LIST_MAX));
+return -1;
+}
+
+if (VIR_ALLOC_N (ret-uuids.uuids_val, args-maxuuids)  0) {
+remoteDispatchOOMError (err);
+return -1;
+}
+
+ret-uuids.uuids_len = virConnectListSecrets (conn, ret-uuids.uuids_val,
+  args-maxuuids);
+if (ret-uuids.uuids_len == -1) {
+VIR_FREE (ret-uuids.uuids_val);
+remoteDispatchConnError (err, conn);
+return -1;
+}
+
+return 0;
+}
+
+static int
+remoteDispatchSecretDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+   struct qemud_client *client ATTRIBUTE_UNUSED,
+   virConnectPtr conn, remote_error *err,
+   remote_secret_define_xml_args *args,
+   remote_secret_define_xml_ret *ret)
+{
+virSecretPtr secret;
+
+secret = virSecretDefineXML (conn, args-xml, args-flags);
+if (secret == NULL) {
+remoteDispatchConnError (err, conn);
+return -1;
+}
+
+make_nonnull_secret (ret-secret, secret);
+virSecretFree (secret);
+return 0;
+}
+
+static int
+remoteDispatchSecretGetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
+  struct qemud_client *client ATTRIBUTE_UNUSED,
+  virConnectPtr conn, remote_error *err,
+  remote_secret_get_value_args *args,
+  remote_secret_get_value_ret *ret)
+{
+virSecretPtr secret;
+size_t value_size;
+unsigned char *value;
+
+secret = get_nonnull_secret (conn, args-secret);
+if (secret == NULL) {
+remoteDispatchConnError (err, conn);
+return -1;
+}
+
+value = virSecretGetValue (secret, value_size, args-flags);
+if (value == NULL) {
+remoteDispatchConnError (err, conn);
+virSecretFree(secret);
+return -1;
+}
+
+ret-value.value_len = value_size;
+ret-value.value_val = (char *)value;
+virSecretFree(secret);
+return 0;
+}
+
+static int
+remoteDispatchSecretGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
+

[libvirt] [PATCH 05/20] Secret manipulation step 5: RPC client

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 src/datatypes.h   |1 +
 src/remote_internal.c |  328 +
 2 files changed, 329 insertions(+), 0 deletions(-)

diff --git a/src/datatypes.h b/src/datatypes.h
index 56c3777..aa60b63 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -140,6 +140,7 @@ struct _virConnect {
 void *interfacePrivateData;
 void *storagePrivateData;
 void *devMonPrivateData;
+void *secretPrivateData;
 
 /*
  * The lock mutex must be acquired before accessing/changing
diff --git a/src/remote_internal.c b/src/remote_internal.c
index de3c288..682a904 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -221,11 +221,13 @@ static virInterfacePtr get_nonnull_interface 
(virConnectPtr conn, remote_nonnull
 static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, 
remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, 
remote_nonnull_storage_vol vol);
 static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, 
remote_nonnull_node_device dev);
+static virSecretPtr get_nonnull_secret (virConnectPtr conn, 
remote_nonnull_secret secret);
 static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr 
dom_src);
 static void make_nonnull_network (remote_nonnull_network *net_dst, 
virNetworkPtr net_src);
 static void make_nonnull_interface (remote_nonnull_interface *interface_dst, 
virInterfacePtr interface_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, 
virStoragePoolPtr vol_src);
 static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, 
virStorageVolPtr vol_src);
+static void make_nonnull_secret (remote_nonnull_secret *secret_dst, 
virSecretPtr secret_src);
 void remoteDomainEventFired(int watch, int fd, int event, void *data);
 static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr);
 void remoteDomainEventQueueFlush(int timer, void *opaque);
@@ -6319,6 +6321,305 @@ done:
 return rv;
 }
 
+static virDrvOpenStatus
+remoteSecretOpen (virConnectPtr conn,
+  virConnectAuthPtr auth,
+  int flags)
+{
+if (inside_daemon)
+return VIR_DRV_OPEN_DECLINED;
+
+if (conn 
+conn-driver 
+STREQ (conn-driver-name, remote)) {
+struct private_data *priv;
+
+/* If we're here, the remote driver is already
+ * in use due to a) a QEMU uri, or b) a remote
+ * URI. So we can re-use existing connection
+ */
+priv = conn-privateData;
+remoteDriverLock(priv);
+priv-localUses++;
+conn-secretPrivateData = priv;
+remoteDriverUnlock(priv);
+return VIR_DRV_OPEN_SUCCESS;
+} else if (conn-networkDriver 
+   STREQ (conn-networkDriver-name, remote)) {
+struct private_data *priv = conn-networkPrivateData;
+remoteDriverLock(priv);
+conn-secretPrivateData = priv;
+priv-localUses++;
+remoteDriverUnlock(priv);
+return VIR_DRV_OPEN_SUCCESS;
+} else {
+/* Using a non-remote driver, so we need to open a
+ * new connection for secret APIs, forcing it to
+ * use the UNIX transport.
+ */
+struct private_data *priv;
+int ret;
+ret = remoteOpenSecondaryDriver(conn,
+auth,
+flags,
+priv);
+if (ret == VIR_DRV_OPEN_SUCCESS)
+conn-secretPrivateData = priv;
+return ret;
+}
+}
+
+static int
+remoteSecretClose (virConnectPtr conn)
+{
+int rv = 0;
+struct private_data *priv = conn-secretPrivateData;
+
+conn-secretPrivateData = NULL;
+remoteDriverLock(priv);
+priv-localUses--;
+if (!priv-localUses) {
+rv = doRemoteClose(conn, priv);
+remoteDriverUnlock(priv);
+virMutexDestroy(priv-lock);
+VIR_FREE(priv);
+}
+if (priv)
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
+remoteSecretNumOfSecrets (virConnectPtr conn)
+{
+int rv = -1;
+remote_num_of_secrets_ret ret;
+struct private_data *priv = conn-secretPrivateData;
+
+remoteDriverLock (priv);
+
+memset (ret, 0, sizeof (ret));
+if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_SECRETS,
+  (xdrproc_t) xdr_void, (char *) NULL,
+  (xdrproc_t) xdr_remote_num_of_secrets_ret, (char *) ret) == -1)
+goto done;
+
+rv = ret.num;
+
+done:
+remoteDriverUnlock (priv);
+return rv;
+}
+
+static int
+remoteSecretListSecrets (virConnectPtr conn, char **uuids, int maxuuids)
+{
+int rv = -1;
+int i;
+remote_list_secrets_args 

[libvirt] [PATCH 07/20] Secret manipulation step 7: Local driver

2009-08-20 Thread Miloslav Trmač
This implementation stores the secrets in an unencrypted text file,
for simplicity in implementation and debugging.

(Symmetric encryption, e.g. using gpgme, will not be difficult to add.
Because the TLS private key used by libvirtd is stored unencrypted,
encrypting the secrets file does not currently provide much additional
security.)

Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
- Add the base64 gnulib module here, not in a later patch
- Don't use fprintf(stderr) for logging
- Move an assignment out of loop termination test
- fchmod() a newly created temporary file before writing secrets to it
- Reject invalid XML attribute values
- Use more verbose errors in parseKeyValue()
- Use open()+fstat() instead of stat()+open()
- Fix structure declaration formatting
- Fix error message formatting
- Remove a comment suggesting use of abort()
---
 bootstrap   |1 +
 include/libvirt/virterror.h |1 +
 po/POTFILES.in  |1 +
 qemud/qemud.c   |3 +
 src/Makefile.am |   14 +
 src/libvirt_private.syms|2 +
 src/secret_driver.c | 1152 +++
 src/secret_driver.h |   28 +
 src/test.c  |   21 +
 src/virterror.c |5 +
 10 files changed, 1228 insertions(+), 0 deletions(-)
 create mode 100644 src/secret_driver.c
 create mode 100644 src/secret_driver.h

diff --git a/bootstrap b/bootstrap
index 8b81e0e..885b299 100755
--- a/bootstrap
+++ b/bootstrap
@@ -65,6 +65,7 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
 $gnulib_tool || exit
 
 modules='
+base64
 c-ctype
 close
 connect
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 62cad88..fa5cac4 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -169,6 +169,7 @@ typedef enum {
 VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
 VIR_WAR_NO_SECRET, /* failed to start secret storage */
 VIR_ERR_INVALID_SECRET, /* invalid secret */
+VIR_ERR_NO_SECRET, /* secret not found */
 } virErrorNumber;
 
 /**
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 66d3ebd..e9d388a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -30,6 +30,7 @@ src/proxy_internal.c
 src/qemu_conf.c
 src/qemu_driver.c
 src/remote_internal.c
+src/secret_driver.c
 src/security.c
 src/security_selinux.c
 src/storage_backend.c
diff --git a/qemud/qemud.c b/qemud/qemud.c
index e657cf2..ec7c021 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -92,6 +92,7 @@
 #ifdef WITH_NODE_DEVICES
 #include node_device.h
 #endif
+#include secret_driver.h
 #endif
 
 
@@ -814,6 +815,7 @@ static struct qemud_server *qemudInitialize(int sigread) {
 virDriverLoadModule(network);
 virDriverLoadModule(storage);
 virDriverLoadModule(nodedev);
+virDriverLoadModule(secret);
 virDriverLoadModule(qemu);
 virDriverLoadModule(lxc);
 virDriverLoadModule(uml);
@@ -832,6 +834,7 @@ static struct qemud_server *qemudInitialize(int sigread) {
 (defined(HAVE_HAL) || defined(HAVE_DEVKIT))
 nodedevRegister();
 #endif
+secretRegister();
 #ifdef WITH_QEMU
 qemuRegister();
 #endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 9567490..ce33695 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -176,6 +176,9 @@ NETWORK_DRIVER_SOURCES =
\
 INTERFACE_DRIVER_SOURCES = \
interface_driver.h interface_driver.c
 
+SECRET_DRIVER_SOURCES =\
+   secret_driver.h secret_driver.c
+
 # Storage backend specific impls
 STORAGE_DRIVER_SOURCES =   \
storage_driver.h storage_driver.c   \
@@ -448,6 +451,17 @@ endif
 libvirt_driver_interface_la_SOURCES = $(INTERFACE_DRIVER_SOURCES)
 endif
 
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_secret.la
+else
+noinst_LTLIBRARIES += libvirt_driver_secret.la
+libvirt_la_LIBADD += libvirt_driver_secret.la
+endif
+if WITH_DRIVER_MODULES
+libvirt_driver_secret_la_LDFLAGS = -module -avoid-version
+endif
+libvirt_driver_secret_la_SOURCES = $(SECRET_DRIVER_SOURCES)
+
 # Needed to keep automake quiet about conditionals
 libvirt_driver_storage_la_SOURCES =
 if WITH_STORAGE_DIR
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f2c0736..8b22030 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -299,6 +299,8 @@ qparam_get_query;
 qparam_query_parse;
 free_qparam_set;
 
+# secret.h
+secretRegister;
 
 # security.h
 virSecurityDriverVerify;
diff --git a/src/secret_driver.c b/src/secret_driver.c
new file mode 100644
index 000..f8180ad
--- /dev/null
+++ b/src/secret_driver.c
@@ -0,0 +1,1152 @@
+/*
+ * secret_driver.c: local driver for secret manipulation API
+ *
+ * 

[libvirt] [PATCH 08/20] Secret manipulation step 8: Add virsh commands

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
- Add documentation to virsh.1
---
 docs/virsh.pod |   43 
 src/virsh.c|  323 
 virsh.1|   34 ++-
 3 files changed, 399 insertions(+), 1 deletions(-)

diff --git a/docs/virsh.pod b/docs/virsh.pod
index 10bb991..55ec64a 100644
--- a/docs/virsh.pod
+++ b/docs/virsh.pod
@@ -543,6 +543,49 @@ Convert a network name to network UUID.
 
 =back
 
+=head1 SECRET COMMMANDS
+
+The following commands manipulate secrets (e.g. passwords, passphrases and
+encryption keys).  Libvirt can store secrets independently from their use, and
+other objects (e.g. volumes or domains) can refer to the secrets for encryption
+or possibly other uses.  Secrets are identified using an UUID.  See
+Lhttp://libvirt.org/formatsecret.html for documentation of the XML format
+used to represent properties of secrets.
+
+=over 4
+
+=item Bsecret-define Ifile
+
+Create a secret with the properties specified in Ifile, with no associated
+secret value.  If Ifile does not specify a UUID, choose one automatically.
+If Ifile specifies an UUID of an existing secret, replace its properties by
+properties defined in Ifile, without affecting the secret value.
+
+=item Bsecret-dumpxml Isecret
+
+Output properties of Isecret (specified by its UUID) as an XML dump to 
stdout.
+
+=item Bsecret-set-value Isecret Ibase64
+
+Set the value associated with Isecret (specified by its UUID) to the value
+Base64-encoded value Ibase64.
+
+=item Bsecret-get-value Isecret
+
+Output the value associated with Isecret (specified by its UUID) to stdout,
+encoded using Base64.
+
+=item Bsecret-undefine Isecret
+
+Delete a Isecret (specified by its UUID), including the associated value, if
+any.
+
+=item Bsecret-list
+
+Output a list of UUIDs of known secrets to stdout.
+
+=back
+
 =head1 ENVIRONMENT
 
 The following environment variables can be set to alter the behaviour
diff --git a/src/virsh.c b/src/virsh.c
index 2d0cf81..1b073ef 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -41,6 +41,7 @@
 #endif
 
 #include internal.h
+#include base64.h
 #include buf.h
 #include console.h
 #include util.h
@@ -271,6 +272,9 @@ static virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, 
const vshCmd *cmd,
 vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
VSH_BYUUID|VSH_BYNAME)
 
+static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd,
+char **name);
+
 static void vshPrintExtra(vshControl *ctl, const char *format, ...)
 ATTRIBUTE_FMT_PRINTF(2, 3);
 static void vshDebug(vshControl *ctl, int level, const char *format, ...)
@@ -5249,9 +5253,291 @@ cmdVolPath(vshControl *ctl, const vshCmd *cmd)
 }
 
 
+/*
+ * secret-define command
+ */
+static const vshCmdInfo info_secret_define[] = {
+{help, gettext_noop(define or modify a secret from an XML file)},
+{desc, gettext_noop(Define or modify a secret.)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_secret_define[] = {
+{file, VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop(file containing secret 
attributes in XML)},
+{NULL, 0, 0, NULL}
+};
+
+static int
+cmdSecretDefine(vshControl *ctl, const vshCmd *cmd)
+{
+char *from, *buffer, *uuid;
+virSecretPtr res;
+
+if (!vshConnectionUsability(ctl, ctl-conn, TRUE))
+return FALSE;
+
+from = vshCommandOptString(cmd, file, NULL);
+if (!from)
+return FALSE;
+
+if (virFileReadAll(from, VIRSH_MAX_XML_FILE, buffer)  0)
+return FALSE;
+
+res = virSecretDefineXML(ctl-conn, buffer, 0);
+free (buffer);
+
+if (res == NULL) {
+vshError(ctl, FALSE, _(Failed to set attributes from %s), from);
+return FALSE;
+}
+uuid = virSecretGetUUIDString(res);
+if (uuid == NULL) {
+vshError(ctl, FALSE, %s,
+ _(Failed to get UUID of created secret));
+virSecretFree(res);
+return FALSE;
+}
+vshPrint(ctl, _(Secret %s created\n), uuid);
+free(uuid);
+virSecretFree(res);
+return TRUE;
+}
+
+/*
+ * secret-dumpxml command
+ */
+static const vshCmdInfo info_secret_dumpxml[] = {
+{help, gettext_noop(secret attributes in XML)},
+{desc, gettext_noop(Output attributes of a secret as an XML dump to 
stdout.)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_secret_dumpxml[] = {
+{secret, VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop(secret UUID)},
+{NULL, 0, 0, NULL}
+};
+
+static int
+cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd)
+{
+virSecretPtr secret;
+int ret = FALSE;
+char *xml;
+
+if (!vshConnectionUsability(ctl, ctl-conn, TRUE))
+return FALSE;
+
+secret = vshCommandOptSecret(ctl, cmd, NULL);
+if (secret == NULL)
+return FALSE;
+
+xml = 

[libvirt] [PATCH 10/20] Secret manipulation step 10: Add Python API

2009-08-20 Thread Miloslav Trmač
Sample session:

 import libvirt
 c = libvirt.open('qemu:///session')

 c.listSecrets()
['12247729-47d2-a783-88ce-b329d4781cd3', 'reee', 'abc']

 s = c.secretDefineXML(secret ephemeral='no' 
 private='no'\ndescriptionSomething for 
 use/description\nvolume/foo/bar/volume\n/secret\n)

 s.UUIDString()
'340c2dfb-811b-eda8-da9e-25ccd7bfd650'

 s.XMLDesc()
secret ephemeral='no' private='no'\n  
uuid340c2dfb-811b-eda8-da9e-25ccd7bfd650/uuid\n  descriptionSomething for 
use/description\n  volume/foo/bar/volume\n/secret\n

 s.setValue('abc\0xx\xffx')
0

 s.value()
'abc\x00xx\xffx'

 s.undefine()
0

Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
- remove get prefix from method names of virSecret, to be more
  consistent with other classes.
---
 python/generator.py   |   31 +++--
 python/libvir.c   |  100 +
 python/libvirt-python-api.xml |   18 +++
 python/libvirt_wrap.h |9 
 python/types.c|   13 +
 5 files changed, 167 insertions(+), 4 deletions(-)

diff --git a/python/generator.py b/python/generator.py
index feff7a3..4dbad1c 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -270,6 +270,11 @@ py_types = {
 'const virNodeDevicePtr':  ('O', virNodeDevice, virNodeDevicePtr, 
virNodeDevicePtr),
 'virNodeDevice *':  ('O', virNodeDevice, virNodeDevicePtr, 
virNodeDevicePtr),
 'const virNodeDevice *':  ('O', virNodeDevice, virNodeDevicePtr, 
virNodeDevicePtr),
+
+'virSecretPtr':  ('O', virSecret, virSecretPtr, virSecretPtr),
+'const virSecretPtr':  ('O', virSecret, virSecretPtr, virSecretPtr),
+'virSecret *':  ('O', virSecret, virSecretPtr, virSecretPtr),
+'const virSecret *':  ('O', virSecret, virSecretPtr, virSecretPtr),
 }
 
 py_return_types = {
@@ -296,6 +301,7 @@ skip_impl = (
 'virConnectListDefinedNetworks',
 'virConnectListInterfaces',
 'virConnectListDefinedInterfaces',
+'virConnectListSecrets',
 'virConnectListStoragePools',
 'virConnectListDefinedStoragePools',
 'virConnectListStorageVols',
@@ -320,6 +326,8 @@ skip_impl = (
 'virDomainSetSchedulerParameters',
 'virDomainGetVcpus',
 'virDomainPinVcpu',
+'virSecretGetValue',
+'virSecretSetValue',
 'virStoragePoolGetUUID',
 'virStoragePoolGetUUIDString',
 'virStoragePoolLookupByUUID',
@@ -623,6 +631,8 @@ classes_type = {
 virStorageVol *: (._o, virStorageVol(self, _obj=%s), 
virStorageVol),
 virNodeDevicePtr: (._o, virNodeDevice(self, _obj=%s), 
virNodeDevice),
 virNodeDevice *: (._o, virNodeDevice(self, _obj=%s), 
virNodeDevice),
+virSecretPtr: (._o, virSecret(self, _obj=%s), virSecret),
+virSecret *: (._o, virSecret(self, _obj=%s), virSecret),
 virConnectPtr: (._o, virConnect(_obj=%s), virConnect),
 virConnect *: (._o, virConnect(_obj=%s), virConnect),
 }
@@ -632,7 +642,7 @@ converter_type = {
 
 primary_classes = [virDomain, virNetwork, virInterface,
virStoragePool, virStorageVol,
-   virConnect, virNodeDevice ]
+   virConnect, virNodeDevice, virSecret ]
 
 classes_ancestor = {
 }
@@ -642,7 +652,8 @@ classes_destructors = {
 virInterface: virInterfaceFree,
 virStoragePool: virStoragePoolFree,
 virStorageVol: virStorageVolFree,
-virNodeDevice : virNodeDeviceFree
+virNodeDevice : virNodeDeviceFree,
+virSecret: virSecretFree
 }
 
 functions_noexcept = {
@@ -714,6 +725,12 @@ def nameFixup(name, classe, type, file):
 elif name[0:18] == virInterfaceLookup:
 func = name[3:]
 func = string.lower(func[0:1]) + func[1:]
+elif name[0:15] == virSecretDefine:
+func = name[3:]
+func = string.lower(func[0:1]) + func[1:]
+elif name[0:15] == virSecretLookup:
+func = name[3:]
+func = string.lower(func[0:1]) + func[1:]
 elif name[0:20] == virStoragePoolDefine:
 func = name[3:]
 func = string.lower(func[0:1]) + func[1:]
@@ -747,6 +764,12 @@ def nameFixup(name, classe, type, file):
 elif name[0:12] == virInterface:
 func = name[10:]
 func = string.lower(func[0:1]) + func[1:]
+elif name[0:12] == 'virSecretGet':
+func = name[12:]
+func = string.lower(func[0:1]) + func[1:]
+elif name[0:9] == 'virSecret':
+func = name[9:]
+func = string.lower(func[0:1]) + func[1:]
 elif name[0:17] == virStoragePoolGet:
 func = name[17:]
 func = string.lower(func[0:1]) + func[1:]
@@ -1018,7 +1041,7 @@ def buildWrappers():
else:
txt.write(Class %s()\n % (classname))
classes.write(class %s:\n % (classname))
-if classname in [ virDomain, virNetwork, virInterface, 
virStoragePool, virStorageVol, virNodeDevice ]:
+if classname in [ virDomain, 

[libvirt] [PATCH 11/20] Add volume encryption information handling.

2009-08-20 Thread Miloslav Trmač
Define an encryption tag specifying volume encryption format and
format-depenedent parameters (e.g. passphrase, cipher name, key
length, key).

Currently the only defined parameter is a reference to a secret
(passphrase/key) managed using the virSecret* API.

Only the qcow/qcow2 encryption format, and a default format used to
let libvirt choose the format during volume creation, is currently
supported.

This patch does not add any users; the encryption tag is added in
the following patches to both volumes (to support encrypted volume
creation) and domains.

Changes since the third submission:
- Move base64 gnulib module inclusion to an earlier patch
---
 docs/format.html |4 +
 docs/formatcaps.html |4 +
 docs/formatdomain.html   |4 +
 docs/formatnetwork.html  |4 +
 docs/formatnode.html |4 +
 docs/formatsecret.html   |4 +
 docs/formatstorage.html  |4 +
 docs/formatstorageencryption.html|  209 +
 docs/formatstorageencryption.html.in |   65 +
 docs/schemas/Makefile.am |1 +
 docs/schemas/storageencryption.rng   |   34 +
 docs/sitemap.html|3 +
 docs/sitemap.html.in |4 +
 po/POTFILES.in   |1 +
 src/Makefile.am  |1 +
 src/libvirt_private.syms |5 +
 src/storage_encryption.c |  241 ++
 src/storage_encryption.h |   72 ++
 18 files changed, 664 insertions(+), 0 deletions(-)
 create mode 100644 docs/formatstorageencryption.html
 create mode 100644 docs/formatstorageencryption.html.in
 create mode 100644 docs/schemas/storageencryption.rng
 create mode 100644 src/storage_encryption.c
 create mode 100644 src/storage_encryption.h

diff --git a/docs/format.html b/docs/format.html
index 3c20b5f..e8b1498 100644
--- a/docs/format.html
+++ b/docs/format.html
@@ -64,6 +64,10 @@
 /div
   /lili
 div
+  a title=Storage volume encryption XML format 
class=inactive href=formatstorageencryption.htmlStorage Encryption/a
+/div
+  /lili
+div
   a title=The driver capabilities XML format 
class=inactive href=formatcaps.htmlCapabilities/a
 /div
   /lili
diff --git a/docs/formatcaps.html b/docs/formatcaps.html
index 5f2bc72..3240101 100644
--- a/docs/formatcaps.html
+++ b/docs/formatcaps.html
@@ -64,6 +64,10 @@
 /div
   /lili
 div
+  a title=Storage volume encryption XML format 
class=inactive href=formatstorageencryption.htmlStorage Encryption/a
+/div
+  /lili
+div
   span class=activeCapabilities/span
 /div
   /lili
diff --git a/docs/formatdomain.html b/docs/formatdomain.html
index 6b655ad..efba65a 100644
--- a/docs/formatdomain.html
+++ b/docs/formatdomain.html
@@ -64,6 +64,10 @@
 /div
   /lili
 div
+  a title=Storage volume encryption XML format 
class=inactive href=formatstorageencryption.htmlStorage Encryption/a
+/div
+  /lili
+div
   a title=The driver capabilities XML format 
class=inactive href=formatcaps.htmlCapabilities/a
 /div
   /lili
diff --git a/docs/formatnetwork.html b/docs/formatnetwork.html
index 72a3cda..845e558 100644
--- a/docs/formatnetwork.html
+++ b/docs/formatnetwork.html
@@ -64,6 +64,10 @@
 /div
   /lili
 div
+  a title=Storage volume encryption XML format 
class=inactive href=formatstorageencryption.htmlStorage Encryption/a
+/div
+  /lili
+div
   a title=The driver capabilities XML format 
class=inactive href=formatcaps.htmlCapabilities/a
 /div
   /lili
diff --git a/docs/formatnode.html b/docs/formatnode.html
index 516c27b..b269baa 100644
--- a/docs/formatnode.html
+++ b/docs/formatnode.html
@@ -64,6 +64,10 @@
 /div
   /lili
 div
+  a title=Storage volume encryption XML format 
class=inactive href=formatstorageencryption.htmlStorage Encryption/a
+/div
+  /lili
+div
   a title=The 

[libvirt] [PATCH 12/20] Attach encryption information to virStorageVolDef.

2009-08-20 Thread Miloslav Trmač
The XML allows encryption format='unencrypted'/, this implementation
canonicalizes the internal representation so that vol-encryption is
non-NULL iff the volume is encrypted.

Note that partial encryption information (e.g. specifying an encryption
format, but not the key/passphrase) is valid, libvirt will automatically
choose value for the missing information during volume creation.  The
user can read the volume XML, and use the unmodified encryption tag in
future operations (without having to be able to understand) its contents.
---
 docs/formatstorage.html  |6 ++
 docs/formatstorage.html.in   |8 
 docs/schemas/storagevol.rng  |5 +
 src/storage_conf.c   |   15 +++
 src/storage_conf.h   |3 +++
 tests/storagevolschemadata/vol-qcow2.xml |3 +++
 6 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/docs/formatstorage.html b/docs/formatstorage.html
index 8c16a0f..cb95263 100644
--- a/docs/formatstorage.html
+++ b/docs/formatstorage.html
@@ -252,6 +252,9 @@
 lt;modegt;0744lt;/modegt;
 lt;labelgt;virt_image_tlt;/labelgt;
   lt;/permissionsgt;
+  lt;encryption type='...'gt;
+...
+  lt;/encryptiongt;
 lt;/targetgt;
   lt;/poolgt;/pre
 dldtcodepath/code/dtddProvides the location at which the 
pool will be mapped into
@@ -274,6 +277,9 @@
element contains the numeric group ID. The codelabel/code element
contains the MAC (eg SELinux) label string.
span class=sinceSince 0.4.1/span
+  /dddtcodeencryption/code/dtddIf present, specifies how the 
volume is encrypted.  See
+the a href=formatstorageencryption.htmlStorage Encryption/a page
+for more information.
   /dd/dl
 h3
   a name=StoragePoolExtents id=StoragePoolExtentsDevice 
extents/a
diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 4878d72..3ed88a2 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -124,6 +124,9 @@
 lt;modegt;0744lt;/modegt;
 lt;labelgt;virt_image_tlt;/labelgt;
   lt;/permissionsgt;
+  lt;encryption type='...'gt;
+...
+  lt;/encryptiongt;
 lt;/targetgt;
   lt;/poolgt;/pre
 
@@ -152,6 +155,11 @@
contains the MAC (eg SELinux) label string.
span class=sinceSince 0.4.1/span
   /dd
+  dtcodeencryption/code/dt
+  ddIf present, specifies how the volume is encrypted.  See
+the a href=formatstorageencryption.htmlStorage Encryption/a page
+for more information.
+  /dd
 /dl
 
 h3a name=StoragePoolExtentsDevice extents/a/h3
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 5b0b038..00b70f6 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -5,6 +5,8 @@
 ref name='vol'/
   /start
 
+  include href='storageencryption.rng'/
+
 
   define name='vol'
 element name='volume'
@@ -73,6 +75,9 @@
   /optional
   ref name='format'/
   ref name='permissions'/
+  optional
+ref name='encryption'/
+  /optional
 /element
   /define
 
diff --git a/src/storage_conf.c b/src/storage_conf.c
index 245b2d0..c446069 100644
--- a/src/storage_conf.c
+++ b/src/storage_conf.c
@@ -260,8 +260,10 @@ virStorageVolDefFree(virStorageVolDefPtr def) {
 
 VIR_FREE(def-target.path);
 VIR_FREE(def-target.perms.label);
+virStorageEncryptionFree(def-target.encryption);
 VIR_FREE(def-backingStore.path);
 VIR_FREE(def-backingStore.perms.label);
+virStorageEncryptionFree(def-backingStore.encryption);
 VIR_FREE(def);
 }
 
@@ -955,6 +957,7 @@ virStorageVolDefParseXML(virConnectPtr conn,
 char *allocation = NULL;
 char *capacity = NULL;
 char *unit = NULL;
+xmlNodePtr node;
 
 options = virStorageVolOptionsForPoolType(pool-type);
 if (options == NULL)
@@ -1019,6 +1022,14 @@ virStorageVolDefParseXML(virConnectPtr conn,
 ./target/permissions, 0600)  0)
 goto cleanup;
 
+node = virXPathNode(conn, ./target/encryption, ctxt);
+if (node != NULL) {
+ret-target.encryption = virStorageEncryptionParseNode(conn, ctxt-doc,
+   node);
+if (ret-target.encryption == NULL)
+goto cleanup;
+}
+
 
 
 ret-backingStore.path = virXPathString(conn, 
string(./backingStore/path), ctxt);
@@ -1189,6 +1200,10 @@ virStorageVolTargetDefFormat(virConnectPtr conn,
 
 virBufferAddLit(buf,/permissions\n);
 
+if (def-encryption != NULL 
+virStorageEncryptionFormat(conn, buf, def-encryption)  0)
+return -1;
+
 virBufferVSprintf(buf,   /%s\n, type);
 
 return 0;
diff --git a/src/storage_conf.h b/src/storage_conf.h
index a6c3650..2fa14e9 100644
--- a/src/storage_conf.h
+++ 

[libvirt] [PATCH 14/20] Add support for encrypted (qcow) volume creation.

2009-08-20 Thread Miloslav Trmač
Supports only virStorageVolCreateXML, not virStorageVolCreateXMLFrom.

Curiously, qemu-img does not need the passphrase for anything to create
an encrypted volume.  This implementation thus does not need to touch
any secrets to work with cooperating clients.  More generic passphrase
handling is added in the next patch.
---
 src/storage_backend.c |   47 +++-
 src/storage_backend_disk.c|7 ++
 src/storage_backend_fs.c  |7 ++
 src/storage_backend_logical.c |7 ++
 4 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/src/storage_backend.c b/src/storage_backend.c
index 8824218..c818142 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -246,6 +246,13 @@ virStorageBackendCreateRaw(virConnectPtr conn,
 unsigned long long remain;
 char *buf = NULL;
 
+if (vol-target.encryption != NULL) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+  %s, _(storage pool does not support encrypted 

+  volumes));
+return -1;
+}
+
 if ((fd = open(vol-target.path, O_RDWR | O_CREAT | O_EXCL,
vol-target.perms.mode))  0) {
 virReportSystemError(conn, errno,
@@ -346,15 +353,17 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
 NULL;
 
 const char **imgargv;
+/* The extra NULL field is for indicating encryption (-e). */
 const char *imgargvnormal[] = {
 NULL, create,
 -f, type,
 vol-target.path,
 size,
 NULL,
+NULL
 };
 /* Extra NULL fields are for including backingType when using
- * kvm-img. It's -F backingType
+ * kvm-img (-F backingType), and for indicating encryption (-e).
  */
 const char *imgargvbacking[] = {
 NULL, create,
@@ -364,6 +373,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
 size,
 NULL,
 NULL,
+NULL,
 NULL
 };
 const char *convargv[] = {
@@ -417,6 +427,28 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
 }
 }
 
+if (vol-target.encryption != NULL) {
+if (vol-target.format != VIR_STORAGE_VOL_FILE_QCOW 
+vol-target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+  _(qcow volume encryption unsupported with 
+volume format %s), type);
+return -1;
+}
+if (vol-target.encryption-format !=
+VIR_STORAGE_ENCRYPTION_FORMAT_QCOW) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+  _(unsupported volume encryption format %d),
+  vol-target.encryption-format);
+return -1;
+}
+if (vol-target.encryption-nsecrets  1) {
+virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL,
+  _(too many secrets for qcow encryption));
+return -1;
+}
+}
+
 if ((create_tool = virFindFileInPath(kvm-img)) != NULL)
 use_kvmimg = 1;
 else if ((create_tool = virFindFileInPath(qemu-img)) != NULL)
@@ -437,11 +469,16 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
 imgargvbacking[7] = backingType;
 imgargvbacking[8] = vol-target.path;
 imgargvbacking[9] = size;
-}
+if (vol-target.encryption != NULL)
+imgargvbacking[10] = -e;
+} else if (vol-target.encryption != NULL)
+imgargvbacking[8] = -e;
 imgargv = imgargvbacking;
 } else {
 imgargvnormal[0] = create_tool;
 imgargv = imgargvnormal;
+if (vol-target.encryption != NULL)
+imgargv[6] = -e;
 }
 
 
@@ -489,6 +526,12 @@ virStorageBackendCreateQcowCreate(virConnectPtr conn,
   qcow-create));
 return -1;
 }
+if (vol-target.encryption != NULL) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+  %s, _(encrypted volumes not supported with 
+  qcow-create));
+return -1;
+}
 
 /* Size in MB - yes different units to qemu-img :-( */
 snprintf(size, sizeof(size), %llu, vol-capacity/1024/1024);
diff --git a/src/storage_backend_disk.c b/src/storage_backend_disk.c
index ae2acae..6fdb566 100644
--- a/src/storage_backend_disk.c
+++ b/src/storage_backend_disk.c
@@ -557,6 +557,13 @@ virStorageBackendDiskCreateVol(virConnectPtr conn,
 NULL
 };
 
+if (vol-target.encryption != NULL) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+  %s, _(storage pool does not support encrypted 

+  volumes));
+return -1;
+}
+
 if 

[libvirt] [PATCH 15/20] Provide missing passphrase when creating a volume.

2009-08-20 Thread Miloslav Trmač
If the encryption format='qcow' element does not specify a secret
during volume creation, generate a suitable secret and add it to the
encryption tag.  The caller can view the updated encryption tag
using virStorageVolGetXMLDesc().

Similarly, when encryption format='default'/ is specified while
creating a qcow or qcow2-formatted volume, change the format to qcow
and generate a secret as described above.

Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 src/storage_backend.c |  127 +++-
 1 files changed, 124 insertions(+), 3 deletions(-)

diff --git a/src/storage_backend.c b/src/storage_backend.c
index c818142..5fa0035 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -43,6 +43,7 @@
 #include selinux/selinux.h
 #endif
 
+#include datatypes.h
 #include virterror_internal.h
 #include util.h
 #include memory.h
@@ -331,6 +332,118 @@ cleanup:
 }
 
 static int
+virStorageGenerateQcowEncryption(virConnectPtr conn,
+ virStorageVolDefPtr vol)
+{
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+virStorageEncryptionPtr enc;
+virStorageEncryptionSecretPtr enc_secret = NULL;
+virSecretPtr secret = NULL;
+char *uuid = NULL, *xml;
+unsigned char value[16];
+int ret = -1, fd = -1;
+size_t i;
+
+if (conn-secretDriver == NULL || conn-secretDriver-defineXML == NULL ||
+conn-secretDriver-setValue == NULL) {
+virStorageReportError(conn, VIR_ERR_NO_SUPPORT, %s,
+  _(secret storage not supported));
+goto cleanup;
+}
+
+enc = vol-target.encryption;
+if (enc-nsecrets != 0) {
+virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, %s,
+  _(secrets already defined));
+goto cleanup;
+}
+
+if (VIR_ALLOC(enc_secret)  0 || VIR_REALLOC_N(enc-secrets, 1)  0) {
+virReportOOMError(conn);
+goto cleanup;
+}
+
+virBufferAddLit(buf, secret ephemeral='no' private='no');
+/* uuid/ is chosen by the secret driver */
+virBufferEscapeString(buf,
+  descriptionqcow passphrase for %s/description,
+  vol-target.path);
+virBufferEscapeString(buf, volume%s/volume, vol-target.path);
+virBufferAddLit(buf, /secret);
+if (virBufferError(buf)) {
+virReportOOMError(conn);
+goto cleanup;
+}
+xml = virBufferContentAndReset(buf);
+secret = conn-secretDriver-defineXML(conn, xml, 0);
+if (secret == NULL) {
+VIR_FREE(xml);
+goto cleanup;
+}
+VIR_FREE(xml);
+
+uuid = strdup(secret-uuid);
+if (uuid == NULL) {
+virReportOOMError(conn);
+goto cleanup;
+}
+
+/* A qcow passphrase is up to 16 bytes, with any data following a NUL
+   ignored.  Prohibit control and non-ASCII characters to avoid possible
+   unpleasant surprises with the qemu monitor input mechanism. */
+fd = open(/dev/urandom, O_RDONLY);
+if (fd  0) {
+virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, %s,
+  _(Cannot open /dev/urandom));
+goto cleanup;
+}
+i = 0;
+while (i  sizeof (value)) {
+ssize_t r;
+
+while ((r = read(fd, value + i, 1)) == -1  errno == EINTR)
+;
+if (r = 0) {
+virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, %s,
+  _(Cannot read from /dev/urandom));
+goto cleanup;
+}
+if (value[i] = 0x20  value[i] = 0x7E)
+i++; /* Got an acceptable character */
+}
+close(fd);
+fd = -1;
+
+if (conn-secretDriver-setValue(secret, value, sizeof(value), 0)  0)
+goto cleanup;
+secret = NULL;
+
+enc_secret-type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
+enc_secret-uuid = uuid;
+uuid = NULL;
+enc-format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
+enc-secrets[0] = enc_secret; /* Space for secrets[0] allocated above */
+enc_secret = NULL;
+enc-nsecrets = 1;
+
+ret = 0;
+
+cleanup:
+if (fd != -1)
+close(fd);
+VIR_FREE(uuid);
+if (secret != NULL) {
+if (conn-secretDriver-undefine != NULL)
+conn-secretDriver-undefine(secret);
+virSecretFree(secret);
+}
+xml = virBufferContentAndReset(buf);
+VIR_FREE(xml);
+VIR_FREE(enc_secret);
+return ret;
+}
+
+static int
 virStorageBackendCreateQemuImg(virConnectPtr conn,
virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol,
@@ -428,6 +541,8 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
 }
 
 if (vol-target.encryption != NULL) {
+virStorageEncryptionPtr enc;
+
 if (vol-target.format != VIR_STORAGE_VOL_FILE_QCOW 
 

[libvirt] [PATCH 16/20] Attach encryption information to virDomainDiskDef.

2009-08-20 Thread Miloslav Trmač
The XML allows encryption format='unencrypted'/, this implementation
canonicalizes the internal representation so that disk-encryption is
non-NULL iff encryption information is available.

A domain with partial encryption information can be defined,
completeness of the information is not verified.  The domain won't
start until the remaining information is added, of course.
---
 docs/formatdomain.html|6 ++
 docs/formatdomain.html.in |8 
 docs/schemas/domain.rng   |5 +
 src/domain_conf.c |   14 ++
 src/domain_conf.h |2 ++
 5 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/docs/formatdomain.html b/docs/formatdomain.html
index efba65a..3368ad5 100644
--- a/docs/formatdomain.html
+++ b/docs/formatdomain.html
@@ -453,6 +453,9 @@
lt;driver name=tap type=aiogt;
lt;source file='/var/lib/xen/images/fv0'/gt;
lt;target dev='hda' bus='ide'/gt;
+lt;encryption type='...'gt;
+  ...
+lt;/encryptiongt;
  lt;/diskgt;
  .../pre
 dldtcodedisk/code/dtddThe codedisk/code element is the 
main container for describing
@@ -478,6 +481,9 @@
codedriver/code element allows them to be selected. The 
codename/code
attribute is the primary backend driver name, while the optional 
codetype/code
attribute provides the sub-type. span class=sinceSince 0.1.8/span
+  /dddtcodeencryption/code/dtddIf present, specifies how the 
volume is encrypted.  See
+the a href=formatstorageencryption.htmlStorage Encryption/a page
+for more information.
   /dd/dl
 h4
   a name=elementsUSB id=elementsUSBUSB and PCI devices/a
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index eb12784..211f7ed 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -338,6 +338,9 @@
lt;driver name=tap type=aiogt;
lt;source file='/var/lib/xen/images/fv0'/gt;
lt;target dev='hda' bus='ide'/gt;
+lt;encryption type='...'gt;
+  ...
+lt;/encryptiongt;
  lt;/diskgt;
  .../pre
 
@@ -373,6 +376,11 @@
attribute is the primary backend driver name, while the optional 
codetype/code
attribute provides the sub-type. span class=sinceSince 0.1.8/span
   /dd
+  dtcodeencryption/code/dt
+  ddIf present, specifies how the volume is encrypted.  See
+the a href=formatstorageencryption.htmlStorage Encryption/a page
+for more information.
+  /dd
 /dl
 
 h4a name=elementsUSBUSB and PCI devices/a/h4
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index f857301..df31f4a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -4,6 +4,8 @@
   start
 ref name=domain/
   /start
+
+  include href='storageencryption.rng'/
   !--
   We handle only document defining a domain
 --
@@ -336,6 +338,9 @@
 empty/
   /element
 /optional
+optional
+  ref name=encryption/
+/optional
   /define
   !--
   A disk description can be either of type file or block
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 1d2cc7c..46acf5e 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -288,6 +288,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
 VIR_FREE(def-dst);
 VIR_FREE(def-driverName);
 VIR_FREE(def-driverType);
+virStorageEncryptionFree(def-encryption);
 
 VIR_FREE(def);
 }
@@ -661,6 +662,7 @@ virDomainDiskDefParseXML(virConnectPtr conn,
 char *bus = NULL;
 char *cachetag = NULL;
 char *devaddr = NULL;
+virStorageEncryptionPtr encryption = NULL;
 
 if (VIR_ALLOC(def)  0) {
 virReportOOMError(conn);
@@ -718,6 +720,12 @@ virDomainDiskDefParseXML(virConnectPtr conn,
 } else if ((flags  VIR_DOMAIN_XML_INTERNAL_STATUS) 
xmlStrEqual(cur-name, BAD_CAST state)) {
 devaddr = virXMLPropString(cur, devaddr);
+} else if (encryption == NULL 
+   xmlStrEqual(cur-name, BAD_CAST encryption)) {
+encryption = virStorageEncryptionParseNode(conn, node-doc,
+   cur);
+if (encryption == NULL)
+goto error;
 }
 }
 cur = cur-next;
@@ -836,6 +844,8 @@ virDomainDiskDefParseXML(virConnectPtr conn,
 driverName = NULL;
 def-driverType = driverType;
 driverType = NULL;
+def-encryption = encryption;
+encryption = NULL;
 
 cleanup:
 VIR_FREE(bus);
@@ -847,6 +857,7 @@ cleanup:
 VIR_FREE(driverName);
 VIR_FREE(cachetag);
 VIR_FREE(devaddr);
+virStorageEncryptionFree(encryption);
 
 return def;
 
@@ -3519,6 +3530,9 @@ virDomainDiskDefFormat(virConnectPtr conn,
 virBufferAddLit(buf,   readonly/\n);
 if (def-shared)
 

[libvirt] [PATCH 17/20] Don't assume buffered output echoes the command.

2009-08-20 Thread Miloslav Trmač
The if ((nlptr...)) implicitly assumes commptr != NULL (and that buf
starts with cmd).  Make the assumption explicit, it will be broken in
a future patch.
---
 src/qemu_driver.c |7 ---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index eb22940..e92276e 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -2473,10 +2473,11 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
  * occurence, and inbetween the command and the newline 
starting
  * the response
  */
-if ((commptr = strstr(buf, cmd)))
+if ((commptr = strstr(buf, cmd))) {
 memmove(buf, commptr, strlen(commptr)+1);
-if ((nlptr = strchr(buf, '\n')))
-memmove(buf+strlen(cmd), nlptr, strlen(nlptr)+1);
+if ((nlptr = strchr(buf, '\n')))
+memmove(buf+strlen(cmd), nlptr, strlen(nlptr)+1);
+}
 
 break;
 }
-- 
1.6.2.5

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 18/20] Make handling of monitor prompts more general.

2009-08-20 Thread Miloslav Trmač
Support arbitrary callbacks for secondary prompts.  Reimplement
qemudMonitorCommandExtra using such a callback.
---
 src/qemu_driver.c |   84 +---
 1 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index e92276e..3ab0fcc 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -88,6 +88,12 @@ static void qemuDriverUnlock(struct qemud_driver *driver)
 virMutexUnlock(driver-lock);
 }
 
+/* Return -1 for error, 0 for success */
+typedef int qemudMonitorExtraPromptHandler(const virDomainObjPtr vm,
+   const char *buf,
+   const char *prompt,
+   void *data);
+
 static void qemuDomainEventFlush(int timer, void *opaque);
 static void qemuDomainEventQueue(struct qemud_driver *driver,
  virDomainEventPtr event);
@@ -116,6 +122,13 @@ static int qemudMonitorCommandWithFd(const virDomainObjPtr 
vm,
  const char *cmd,
  int scm_fd,
  char **reply);
+static int qemudMonitorCommandWithHandler(const virDomainObjPtr vm,
+  const char *cmd,
+  const char *extraPrompt,
+  qemudMonitorExtraPromptHandler 
extraHandler,
+  void *handlerData,
+  int scm_fd,
+  char **reply);
 static int qemudMonitorCommandExtra(const virDomainObjPtr vm,
 const char *cmd,
 const char *extra,
@@ -2406,12 +2419,13 @@ out:
 }
 
 static int
-qemudMonitorCommandExtra(const virDomainObjPtr vm,
- const char *cmd,
- const char *extra,
- const char *extraPrompt,
- int scm_fd,
- char **reply) {
+qemudMonitorCommandWithHandler(const virDomainObjPtr vm,
+   const char *cmd,
+   const char *extraPrompt,
+   qemudMonitorExtraPromptHandler extraHandler,
+   void *handlerData,
+   int scm_fd,
+   char **reply) {
 int size = 0;
 char *buf = NULL;
 
@@ -2455,12 +2469,20 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
 
 /* Look for QEMU prompt to indicate completion */
 if (buf) {
-if (extra) {
-if (strstr(buf, extraPrompt) != NULL) {
-if (qemudMonitorSend(vm, extra, -1)  0)
-return -1;
-extra = NULL;
-}
+char *foundPrompt;
+
+if (extraPrompt 
+(foundPrompt = strstr(buf, extraPrompt)) != NULL) {
+char *promptEnd;
+
+if (extraHandler(vm, buf, foundPrompt, handlerData)  0)
+return -1;
+/* Discard output so far, necessary to detect whether
+   extraPrompt appears again.  We don't need the output between
+   original command and this prompt anyway. */
+promptEnd = foundPrompt + strlen(extraPrompt);
+memmove(buf, promptEnd, strlen(promptEnd)+1);
+size -= promptEnd - buf;
 } else if ((tmp = strstr(buf, QEMU_CMD_PROMPT)) != NULL) {
 char *commptr = NULL, *nlptr = NULL;
 /* Preserve the newline */
@@ -2498,6 +2520,44 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
 return -1;
 }
 
+struct extraHandlerData
+{
+const char *reply;
+bool first;
+};
+
+static int
+qemudMonitorCommandSimpleExtraHandler(const virDomainObjPtr vm,
+  const char *buf ATTRIBUTE_UNUSED,
+  const char *prompt ATTRIBUTE_UNUSED,
+  void *data_)
+{
+struct extraHandlerData *data = data_;
+
+if (!data-first)
+return 0;
+if (qemudMonitorSend(vm, data-reply, -1)  0)
+return -1;
+data-first = false;
+return 0;
+}
+
+static int
+qemudMonitorCommandExtra(const virDomainObjPtr vm,
+ const char *cmd,
+ const char *extra,
+ const char *extraPrompt,
+ int scm_fd,
+ char **reply) {
+struct extraHandlerData data;
+
+data.reply = extra;
+data.first = true;
+return qemudMonitorCommandWithHandler(vm, cmd, extraPrompt,
+  
qemudMonitorCommandSimpleExtraHandler,
+   

[libvirt] [PATCH 19/20] Consolidate cont into qemudMonitorSendCont()

2009-08-20 Thread Miloslav Trmač
The interface allows qemudMonitorSendCont() to report errors that are
not overridden by its callers.

Also fix a potential infinite loop in qemuDomainCoreDump() if sending
cont repeatedly fails.
---
 src/qemu_driver.c |   89 +++--
 1 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 3ab0fcc..d013007 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -28,6 +28,7 @@
 #include dirent.h
 #include limits.h
 #include string.h
+#include stdbool.h
 #include stdio.h
 #include strings.h
 #include stdarg.h
@@ -135,6 +136,9 @@ static int qemudMonitorCommandExtra(const virDomainObjPtr 
vm,
 const char *extraPrompt,
 int scm_fd,
 char **reply);
+static int qemudMonitorSendCont(virConnectPtr conn,
+const virDomainObjPtr vm,
+bool *error_reported);
 static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
virDomainObjPtr vm,
unsigned long newmem);
@@ -1237,7 +1241,6 @@ static int
 qemudInitCpus(virConnectPtr conn,
   virDomainObjPtr vm,
   const char *migrateFrom) {
-char *info = NULL;
 #if HAVE_SCHED_GETAFFINITY
 cpu_set_t mask;
 int i, maxcpu = QEMUD_CPUMASK_LEN;
@@ -1272,13 +1275,15 @@ qemudInitCpus(virConnectPtr conn,
 #endif /* HAVE_SCHED_GETAFFINITY */
 
 if (migrateFrom == NULL) {
+bool error_reported;
+
 /* Allow the CPUS to start executing */
-if (qemudMonitorCommand(vm, cont, info)  0) {
-qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- %s, _(resume operation failed));
+if (qemudMonitorSendCont(conn, vm, error_reported)  0) {
+if (!error_reported)
+qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ %s, _(resume operation failed));
 return -1;
 }
-VIR_FREE(info);
 }
 
 return 0;
@@ -2573,6 +2578,20 @@ qemudMonitorCommand(const virDomainObjPtr vm,
 return qemudMonitorCommandWithFd(vm, cmd, -1, reply);
 }
 
+static int
+qemudMonitorSendCont(virConnectPtr conn ATTRIBUTE_UNUSED,
+ const virDomainObjPtr vm,
+ bool *error_reported) {
+char *reply;
+
+*error_reported = false;
+if (qemudMonitorCommand(vm, cont, reply)  0)
+return -1;
+qemudDebug (%s: cont reply: %s, vm-def-name, info);
+VIR_FREE(reply);
+return 0;
+}
+
 static virDrvOpenStatus qemudOpen(virConnectPtr conn,
   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
   int flags ATTRIBUTE_UNUSED) {
@@ -3057,7 +3076,6 @@ cleanup:
 
 static int qemudDomainResume(virDomainPtr dom) {
 struct qemud_driver *driver = dom-conn-privateData;
-char *info;
 virDomainObjPtr vm;
 int ret = -1;
 virDomainEventPtr event = NULL;
@@ -3078,17 +3096,18 @@ static int qemudDomainResume(virDomainPtr dom) {
 goto cleanup;
 }
 if (vm-state == VIR_DOMAIN_PAUSED) {
-if (qemudMonitorCommand(vm, cont, info)  0) {
-qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- %s, _(resume operation failed));
+bool error_reported;
+
+if (qemudMonitorSendCont(dom-conn, vm, error_reported)  0) {
+if (!error_reported)
+qemudReportError(dom-conn, dom, NULL, 
VIR_ERR_OPERATION_FAILED,
+ %s, _(resume operation failed));
 goto cleanup;
 }
 vm-state = VIR_DOMAIN_RUNNING;
-qemudDebug(Reply %s, info);
 event = virDomainEventNewFromObj(vm,
  VIR_DOMAIN_EVENT_RESUMED,
  VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
-VIR_FREE(info);
 }
 if (virDomainSaveStatus(dom-conn, driver-stateDir, vm)  0)
 goto cleanup;
@@ -3822,13 +3841,13 @@ cleanup:
will support synchronous operations so we always get here after
the migration is complete.  */
 if (resume  paused) {
-if (qemudMonitorCommand(vm, cont, info)  0) {
-qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- %s, _(resuming after dump failed));
-goto cleanup;
+bool error_reported;
+
+if (qemudMonitorSendCont(dom-conn, vm, error_reported)  0) {
+if (!error_reported)
+qemudReportError(dom-conn, dom, NULL, 
VIR_ERR_OPERATION_FAILED,
+ %s, _(resuming after dump failed));
 }
-DEBUG (%s: cont reply: %s, vm-def-name, info);
-VIR_FREE(info);
 }
 if (vm)
  

[libvirt] [PATCH 20/20] Add support for qcow encrypted volumes to qemu.

2009-08-20 Thread Miloslav Trmač
Changes since the third submission:
- Add flags parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
  virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
 src/qemu_driver.c |  161 ++---
 1 files changed, 153 insertions(+), 8 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index d013007..b73d665 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1296,12 +1296,6 @@ qemudInitPasswords(virConnectPtr conn,
virDomainObjPtr vm) {
 char *info = NULL;
 
-/*
- * NB: Might have more passwords to set in the future. eg a qcow
- * disk decryption password, but there's no monitor command
- * for that yet...
- */
-
 if ((vm-def-ngraphics == 1) 
 vm-def-graphics[0]-type == VIR_DOMAIN_GRAPHICS_TYPE_VNC 
 (vm-def-graphics[0]-data.vnc.passwd || driver-vncPassword)) {
@@ -2578,14 +2572,165 @@ qemudMonitorCommand(const virDomainObjPtr vm,
 return qemudMonitorCommandWithFd(vm, cmd, -1, reply);
 }
 
+static virStorageEncryptionPtr
+findDomainDiskEncryption(virConnectPtr conn, virDomainObjPtr vm,
+ const char *path)
+{
+bool seen_volume;
+int i;
+
+seen_volume = false;
+for (i = 0; i  vm-def-ndisks; i++) {
+virDomainDiskDefPtr disk;
+
+disk = vm-def-disks[i];
+if (disk-src != NULL  STREQ(disk-src, path)) {
+seen_volume = true;
+if (disk-encryption != NULL)
+return disk-encryption;
+}
+}
+if (seen_volume)
+qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
+ _(missing encryption for volume %s), path);
+else
+qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _(unexpected passphrase request for volume %s),
+ path);
+return NULL;
+}
+
+static char *
+findVolumeQcowPassphrase(virConnectPtr conn, virDomainObjPtr vm,
+ const char *path, size_t *passphrase_len)
+{
+virStorageEncryptionPtr enc;
+virSecretPtr secret;
+char *passphrase;
+unsigned char *data;
+size_t size;
+
+if (conn-secretDriver == NULL ||
+conn-secretDriver-lookupByUUIDString == NULL ||
+conn-secretDriver-getValue == NULL) {
+qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, %s,
+ _(secret storage not supported));
+return NULL;
+}
+
+enc = findDomainDiskEncryption(conn, vm, path);
+if (enc == NULL)
+return NULL;
+
+if (enc-format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
+enc-nsecrets != 1 ||
+enc-secrets[0]-type !=
+VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
+qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
+ _(invalid encryption for volume %s), path);
+return NULL;
+}
+
+if (enc-secrets[0]-uuid == NULL) {
+qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
+ _(missing secret uuid for volume %s), path);
+return NULL;
+}
+secret = conn-secretDriver-lookupByUUIDString(conn,
+enc-secrets[0]-uuid);
+if (secret == NULL)
+return NULL;
+data = conn-secretDriver-getValue(secret, size, true, 0);
+virUnrefSecret(secret);
+if (data == NULL)
+return NULL;
+
+if (memchr(data, '\0', size) != NULL) {
+memset(data, 0, size);
+VIR_FREE(data);
+qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_SECRET,
+ _(format='qcow' passphrase for %s must not contain a 

+   '\\0'), path);
+return NULL;
+}
+
+if (VIR_ALLOC_N(passphrase, size + 1)  0) {
+memset(data, 0, size);
+VIR_FREE(data);
+virReportOOMError(conn);
+return NULL;
+}
+memcpy(passphrase, data, size);
+passphrase[size] = '\0';
+
+memset(data, 0, size);
+VIR_FREE(data);
+
+*passphrase_len = size;
+return passphrase;
+}
+
+struct sendVolumePassphraseState {
+virConnectPtr conn;
+bool *error_reported;
+};
+
+static int
+qemudMonitorSendVolumePassphrase(const virDomainObjPtr vm,
+ const char *buf,
+ const char *prompt,
+ void *data)
+{
+const struct sendVolumePassphraseState *state = data;
+char *passphrase, *path;
+const char *prompt_path;
+size_t path_len, passphrase_len = 0;
+int res;
+
+/* The complete prompt looks like this:
+   ide0-hd0 (/path/to/volume) is encrypted.
+   Password:
+   prompt starts with ) is encrypted.  Extract /path/to/volume. */
+for (prompt_path = prompt; prompt_path  buf  prompt_path[-1] != '(';
+ prompt_path--)
+;
+if (prompt_path == buf)
+ 

[libvirt] [PATCH] Ignores EOPNOTSUPP when attempting to access an image on an NFS share.

2009-08-20 Thread Darryl L. Pierce
rhbz#517157

Signed-off-by: Darryl L. Pierce dpie...@redhat.com
---
 src/security_selinux.c |   23 ---
 1 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/security_selinux.c b/src/security_selinux.c
index 0db9f49..f1e3f17 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -323,6 +323,8 @@ SELinuxSetFilecon(virConnectPtr conn, const char *path, 
char *tcon)
 VIR_INFO(Setting SELinux context on '%s' to '%s', path, tcon);
 
 if (setfilecon(path, tcon)  0) {
+int setfilecon_errno = errno;
+
 if (getfilecon(path, econ) = 0) {
 if (STREQ(tcon, econ)) {
 freecon(econ);
@@ -331,14 +333,21 @@ SELinuxSetFilecon(virConnectPtr conn, const char *path, 
char *tcon)
 }
 freecon(econ);
 }
-virSecurityReportError(conn, VIR_ERR_ERROR,
-   _(%s: unable to set security context 
- '\%s\' on %s: %s.), __func__,
-   tcon,
-   path,
-   virStrerror(errno, ebuf, sizeof ebuf));
-if (security_getenforce() == 1)
+
+   /* if the error complaint is related to an image hosted on
+* an nfs mount, then ignore it.
+* rhbz 517157
+*/
+   if (setfilecon_errno != EOPNOTSUPP) {
+ virSecurityReportError(conn, VIR_ERR_ERROR,
+_(%s: unable to set security context 
+  '\%s\' on %s: %s.), __func__,
+tcon,
+path,
+virStrerror(errno, ebuf, sizeof ebuf));
+ if (security_getenforce() == 1)
 return -1;
+   }
 }
 return 0;
 }
-- 
1.6.2.5

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] Re: OpenVZ : The restriction of domain name should be addressed

2009-08-20 Thread Yuji NISHIDA



2009/7/24 Daniel P. Berrange berra...@redhat.com



We should make use of this --name parameter then - I guess it didn't
exist when we first wrote the driver. It is useful to users to have
separate ID vs Name parameters - and in fact the current reusing of
'ID' for the name, causes a little confusion in virsh's lookup  
routines
because it can't tell whether the parameter its given is a name or  
an

ID, since they are identical.


There is still a question of how to specify both a name and CTID in  
XML

description.
By default, CTID can be obtained as openvzGimmeFirstUnusedCTID(), but
actually
I think that there exists a number of persons interested in giving  
CTIDs

manually.


Well, can domain id='' be used for CTID remaining name for
alphabetical domain name?



I worte a small patch and tried with following XML setting.

### Patch ###
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -130,9 +130,6 @@
 ADD_ARG_LIT(VZCTL);
 ADD_ARG_LIT(--quiet);
 ADD_ARG_LIT(create);
-ADD_ARG_LIT(vmdef-id);
-
-ADD_ARG_LIT(--name);
 ADD_ARG_LIT(vmdef-name);

### XML ###
domain id='100'
nameabc/name

I found the type of id was identified as number( obj-type ==  
XPATH_NUMBER ) in virXPathLongBase,

but it is clearly string before converted.
I think correct path is to go in the first if context( obj-type ==  
XPATH_STRING ) and run strtol.


Then I tried with following XML.

### XML ###
domain id=100
nameabc/name

I got following error.

AttValue:  or ' expected

I'm not sure from which function should return this result.

Maybe this is the first step to go forward.
I am doubting openvz*LookupBy* functions be also modified, right?

-
Yuji Nishida
nish...@nict.go.jp

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list