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

Miloslav Trmač mitr at redhat.com
Tue Aug 4 20:28:26 UTC 2009


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 first submission;
- Use <secret type='passphrase' secret_id='...'>
  instead of <passphrase> with in-line passphrase.
- Use a generic "sequence of secrets" representation.
- Output the <secret> elements unconditionally (they don't reveal the
  secrets any more).
- Add format "default", to be used during volume creation only.
- Use "%s", _("...") for all error messages without parameters.
- Add a schema for <encryption>.
- Document <encryption>.
---
 bootstrap                            |    1 +
 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    |  218 ++++++++++++++++++++++++++++++
 docs/formatstorageencryption.html.in |   70 ++++++++++
 docs/schemas/Makefile.am             |    1 +
 docs/schemas/storageencryption.rng   |   37 +++++
 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 ++++++++++
 19 files changed, 682 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/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/docs/format.html b/docs/format.html
index 8aed8d3..dbdc1e7 100644
--- a/docs/format.html
+++ b/docs/format.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatcaps.html b/docs/formatcaps.html
index 8e2e5d1..cb8130b 100644
--- a/docs/formatcaps.html
+++ b/docs/formatcaps.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <span class="active">Capabilities</span>
                         </div>
                       </li><li>
diff --git a/docs/formatdomain.html b/docs/formatdomain.html
index bbce989..f2d7855 100644
--- a/docs/formatdomain.html
+++ b/docs/formatdomain.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatnetwork.html b/docs/formatnetwork.html
index 6049492..87f15f7 100644
--- a/docs/formatnetwork.html
+++ b/docs/formatnetwork.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatnode.html b/docs/formatnode.html
index cca75ff..ea9c95a 100644
--- a/docs/formatnode.html
+++ b/docs/formatnode.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatsecret.html b/docs/formatsecret.html
index 8c6e0c6..53307a3 100644
--- a/docs/formatsecret.html
+++ b/docs/formatsecret.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatstorage.html b/docs/formatstorage.html
index e21e3d2..19936ae 100644
--- a/docs/formatstorage.html
+++ b/docs/formatstorage.html
@@ -64,6 +64,10 @@
                         </div>
                       </li><li>
                         <div>
+                          <a title="Storage volume encryption XML format" class="inactive" href="formatstorageencryption.html">Storage Encryption</a>
+                        </div>
+                      </li><li>
+                        <div>
                           <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
                         </div>
                       </li><li>
diff --git a/docs/formatstorageencryption.html b/docs/formatstorageencryption.html
new file mode 100644
index 0000000..dd7add2
--- /dev/null
+++ b/docs/formatstorageencryption.html
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+        This file is autogenerated from formatstorageencryption.html.in
+        Do not edit this file. Changes will be lost.
+      -->
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+    <link rel="stylesheet" type="text/css" href="main.css" />
+    <link rel="SHORTCUT ICON" href="32favicon.png" />
+    <title>libvirt: Storage volume encryption XML format</title>
+    <meta name="description" content="libvirt, virtualization, virtualization API" />
+  </head>
+  <body>
+    <div id="header">
+      <div id="headerLogo"></div>
+      <div id="headerSearch">
+        <form action="search.php" enctype="application/x-www-form-urlencoded" method="get"><div>
+            <input id="query" name="query" type="text" size="12" value="" />
+            <input id="submit" name="submit" type="submit" value="Search" />
+          </div></form>
+      </div>
+    </div>
+    <div id="body">
+      <div id="menu">
+        <ul class="l0"><li>
+            <div>
+              <a title="Front page of the libvirt website" class="inactive" href="index.html">Home</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Details of new features and bugs fixed in each release" class="inactive" href="news.html">News</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Get the latest source releases, binary builds and get access to the source repository" class="inactive" href="downloads.html">Downloads</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Information for users, administrators and developers" class="active" href="docs.html">Documentation</a>
+              <ul class="l1"><li>
+                  <div>
+                    <a title="Information about deploying and using libvirt" class="inactive" href="deployment.html">Deployment</a>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Overview of the logical subsystems in the libvirt API" class="inactive" href="intro.html">Architecture</a>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Description of the XML formats used in libvirt" class="active" href="format.html">XML format</a>
+                    <ul class="l2"><li>
+                        <div>
+                          <a title="The domain XML format" class="inactive" href="formatdomain.html">Domains</a>
+                        </div>
+                      </li><li>
+                        <div>
+                          <a title="The virtual network XML format" class="inactive" href="formatnetwork.html">Networks</a>
+                        </div>
+                      </li><li>
+                        <div>
+                          <a title="The storage pool and volume XML format" class="inactive" href="formatstorage.html">Storage</a>
+                        </div>
+                      </li><li>
+                        <div>
+                          <span class="active">Storage Encryption</span>
+                        </div>
+                      </li><li>
+                        <div>
+                          <a title="The driver capabilities XML format" class="inactive" href="formatcaps.html">Capabilities</a>
+                        </div>
+                      </li><li>
+                        <div>
+                          <a title="The host device XML format" class="inactive" href="formatnode.html">Node Devices</a>
+                        </div>
+                      </li><li>
+                        <div>
+                          <a title="The secret attribute XML format" class="inactive" href="formatsecret.html">Secrets</a>
+                        </div>
+                      </li></ul>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Hypervisor specific driver information" class="inactive" href="drivers.html">Drivers</a>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Reference manual for the C public API" class="inactive" href="html/index.html">API reference</a>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Bindings of the libvirt API for other languages" class="inactive" href="bindings.html">Language bindings</a>
+                  </div>
+                </li><li>
+                  <div>
+                    <a title="Working on the internals of libvirt API, driver and daemon code" class="inactive" href="internals.html">Internals</a>
+                  </div>
+                </li></ul>
+            </div>
+          </li><li>
+            <div>
+              <a title="User contributed content" class="inactive" href="http://wiki.libvirt.org">Wiki</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Frequently asked questions" class="inactive" href="FAQ.html">FAQ</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="How and where to report bugs and request features" class="inactive" href="bugs.html">Bug reports</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="How to contact the developers via email and IRC" class="inactive" href="contact.html">Contact</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Miscellaneous links of interest related to libvirt" class="inactive" href="relatedlinks.html">Related Links</a>
+            </div>
+          </li><li>
+            <div>
+              <a title="Overview of all content on the website" class="inactive" href="sitemap.html">Sitemap</a>
+            </div>
+          </li></ul>
+      </div>
+      <div id="content">
+        <h1>Storage volume encryption XML format</h1>
+        <ul><li>
+            <a href="#StorageEncryption">Storage volume encryption XML</a>
+            <ul><li>
+                <a href="#StorageEncryptionUnencrypted">"unencrypted" format</a>
+              </li><li>
+                <a href="#StorageEncryptionDefault">"default" format</a>
+              </li><li>
+                <a href="#StorageEncryptionQcow">"qcow" format</a>
+              </li></ul>
+          </li><li>
+            <a href="#example">Example</a>
+          </li></ul>
+        <h2>
+          <a name="StorageEncryption" id="StorageEncryption">Storage volume encryption XML</a>
+        </h2>
+        <p>
+      Storage volumes may be encrypted, the XML snippet described below is used
+      to represent the details of the encryption.  It can be used as a part
+      of a domain or storage configuration.
+    </p>
+        <p>
+      The top-level tag of volume encryption specification
+      is <code>encryption</code>, with a mandatory
+      attribute <code>format</code>.  Currently defined values
+      of <code>format</code> are <code>unencrypted</code>, <code>default</code>
+      and <code>qcow</code>.  Each value of <code>format</code> implies some
+      expectations about the content of the <code>encryption</code> tag.  Other
+      format values may be defined in the future.
+    </p>
+        <p>
+      The <code>encryption</code> tag can currently contain a sequence of
+      <code>secret</code> tags, each with mandatory attributes <code>type</code>
+      and <code>secret_id</code>.  The only currently defined value of
+      <code>type</code> is <code>passphrase</code>.  <code>secret_id</code>
+      refers to a secret known to libvirt.  libvirt can use a secret value
+      previously set using <code>virSecretSetValue()</code>, or, if supported
+      by the particular volume format and driver, automatically generate a
+      secret value at the time of volume creation, and store it using the
+      specified <code>secret_id</code>.
+    </p>
+        <p>
+    </p>
+        <h3>
+          <a name="StorageEncryptionUnencrypted" id="StorageEncryptionUnencrypted">"unencrypted" format</a>
+        </h3>
+        <p>
+      Specifying an <code><encryption type="unencrypted"/></code> is
+      equivalent to omitting the <code>encryption</code> tag altogether.
+    </p>
+        <h3>
+          <a name="StorageEncryptionDefault" id="StorageEncryptionDefault">"default" format</a>
+        </h3>
+        <p>
+      <code><encryption type="default"/></code> can be specified only
+      when creating a volume.  If the volume is successfully created, the
+      encryption formats, parameters and secrets will be auto-generated by
+      libvirt and the attached <code>encryption</code> tag will be updated.
+      The unmodified contents of the <code>encryption</code> tag can be used
+      in later operations with the volume, or when setting up a domain that
+      uses the volume.
+    </p>
+        <h3>
+          <a name="StorageEncryptionQcow" id="StorageEncryptionQcow">"qcow" format</a>
+        </h3>
+        <p>
+      The <code>qcow</code> format specifies that the built-in encryption
+      support in <code>qcow</code>- or <code>qcow2</code>-formatted volume
+      images should be used.  A single
+      <code><secret type='passphrase'></code> element is expected.  If
+      the <code>secret</code> element is not present during volume creation,
+      a secret is automatically generated and attached to the volume.
+    </p>
+        <h2>
+          <a name="example" id="example">Example</a>
+        </h2>
+        <p>
+      Here is a simple example, specifying use of the <code>qcow</code> format:
+    </p>
+        <pre>
+      <encryption format='qcow'>
+         <secret type='passphrase' secret_id='c1f11a6d-8c5d-4a3e-ac7a-4e171c5e0d4a' />
+      </encryption></pre>
+      </div>
+    </div>
+    <div id="footer">
+      <p id="sponsor">
+	    Sponsored by:<br /><a href="http://et.redhat.com/"><img src="et.png" alt="Project sponsored by Red Hat Emerging Technology" /></a></p>
+    </div>
+  </body>
+</html>
diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in
new file mode 100644
index 0000000..739b018
--- /dev/null
+++ b/docs/formatstorageencryption.html.in
@@ -0,0 +1,70 @@
+<html>
+  <body>
+    <h1>Storage volume encryption XML format</h1>
+
+    <ul id="toc"></ul>
+
+    <h2><a name="StorageEncryption">Storage volume encryption XML</a></h2>
+
+    <p>
+      Storage volumes may be encrypted, the XML snippet described below is used
+      to represent the details of the encryption.  It can be used as a part
+      of a domain or storage configuration.
+    </p>
+    <p>
+      The top-level tag of volume encryption specification
+      is <code>encryption</code>, with a mandatory
+      attribute <code>format</code>.  Currently defined values
+      of <code>format</code> are <code>unencrypted</code>, <code>default</code>
+      and <code>qcow</code>.  Each value of <code>format</code> implies some
+      expectations about the content of the <code>encryption</code> tag.  Other
+      format values may be defined in the future.
+    </p>
+    <p>
+      The <code>encryption</code> tag can currently contain a sequence of
+      <code>secret</code> tags, each with mandatory attributes <code>type</code>
+      and <code>secret_id</code>.  The only currently defined value of
+      <code>type</code> is <code>passphrase</code>.  <code>secret_id</code>
+      refers to a secret known to libvirt.  libvirt can use a secret value
+      previously set using <code>virSecretSetValue()</code>, or, if supported
+      by the particular volume format and driver, automatically generate a
+      secret value at the time of volume creation, and store it using the
+      specified <code>secret_id</code>.
+    <p>
+    <h3><a name="StorageEncryptionUnencrypted">"unencrypted" format</a></h3>
+    <p>
+      Specifying an <code><encryption type="unencrypted"/></code> is
+      equivalent to omitting the <code>encryption</code> tag altogether.
+    </p>
+    <h3><a name="StorageEncryptionDefault">"default" format</a></h3>
+    <p>
+      <code><encryption type="default"/></code> can be specified only
+      when creating a volume.  If the volume is successfully created, the
+      encryption formats, parameters and secrets will be auto-generated by
+      libvirt and the attached <code>encryption</code> tag will be updated.
+      The unmodified contents of the <code>encryption</code> tag can be used
+      in later operations with the volume, or when setting up a domain that
+      uses the volume.
+    </p>
+    <h3><a name="StorageEncryptionQcow">"qcow" format</a></h3>
+    <p>
+      The <code>qcow</code> format specifies that the built-in encryption
+      support in <code>qcow</code>- or <code>qcow2</code>-formatted volume
+      images should be used.  A single
+      <code><secret type='passphrase'></code> element is expected.  If
+      the <code>secret</code> element is not present during volume creation,
+      a secret is automatically generated and attached to the volume.
+    </p>
+
+    <h2><a name="example">Example</a></h2>
+
+    <p>
+      Here is a simple example, specifying use of the <code>qcow</code> format:
+    </p>
+
+    <pre>
+      <encryption format='qcow'>
+         <secret type='passphrase' secret_id='c1f11a6d-8c5d-4a3e-ac7a-4e171c5e0d4a' />
+      </encryption></pre>
+  </body>
+</html>
diff --git a/docs/schemas/Makefile.am b/docs/schemas/Makefile.am
index a064518..c217d69 100644
--- a/docs/schemas/Makefile.am
+++ b/docs/schemas/Makefile.am
@@ -6,6 +6,7 @@ schema_DATA = \
 	interface.rng \
 	network.rng \
 	secret.rng \
+	storageencryption.rng \
 	storagepool.rng \
 	storagevol.rng \
 	nodedev.rng \
diff --git a/docs/schemas/storageencryption.rng b/docs/schemas/storageencryption.rng
new file mode 100644
index 0000000..69a2841
--- /dev/null
+++ b/docs/schemas/storageencryption.rng
@@ -0,0 +1,37 @@
+<!-- A Relax NG schema for the libvirt volume encryption XML format -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+
+  <define name='encryption'>
+    <optional>
+      <element name='encryption'>
+	<attribute name='format'>
+	  <choice>
+	    <value>unencrypted</value>
+	    <value>default</value>
+	    <value>qcow</value>
+	  </choice>
+	</attribute>
+	<zeroOrMore>
+	  <ref name='secret'/>
+	</zeroOrMore>
+      </element>
+    </optional>
+  </define>
+
+  <define name='secret'>
+    <element name='secret'>
+      <attribute name='type'>
+	<choice>
+	  <value>passphrase</value>
+	</choice>
+      </attribute>
+      <optional>
+        <attribute name='secret_id'>
+          <text/>
+        </attribute>
+      </optional>
+    </element>
+  </define>
+
+</grammar>
diff --git a/docs/sitemap.html b/docs/sitemap.html
index cf43088..21516be 100644
--- a/docs/sitemap.html
+++ b/docs/sitemap.html
@@ -136,6 +136,9 @@
                 <a href="formatstorage.html">Storage</a>
                 <span>The storage pool and volume XML format</span>
               </li><li>
+                <a href="formatstorageencryption.html">Storage Encryption</a>
+                <span>Storage volume encryption XML format</span>
+              </li><li>
                 <a href="formatcaps.html">Capabilities</a>
                 <span>The driver capabilities XML format</span>
               </li><li>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index 4c4dfa4..cb0cb89 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -99,6 +99,10 @@
                 <span>The storage pool and volume XML format</span>
               </li>
               <li>
+                <a href="formatstorageencryption.html">Storage Encryption</a>
+                <span>Storage volume encryption XML format</span>
+              </li>
+              <li>
                 <a href="formatcaps.html">Capabilities</a>
                 <span>The driver capabilities XML format</span>
               </li>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index cf0ec8d..36b83a2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -40,6 +40,7 @@ src/storage_backend_logical.c
 src/storage_backend_scsi.c
 src/storage_conf.c
 src/storage_driver.c
+src/storage_encryption.c
 src/test.c
 src/uml_conf.c
 src/uml_driver.c
diff --git a/src/Makefile.am b/src/Makefile.am
index ce33695..2c1c9b4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,6 +52,7 @@ UTIL_SOURCES =							\
 		memory.c memory.h				\
 		pci.c pci.h					\
 		qparams.c qparams.h				\
+		storage_encryption.h storage_encryption.c	\
 		threads.c threads.h				\
 		threads-pthread.h				\
 		threads-win32.h					\
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 343a71e..de4e413 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -332,6 +332,11 @@ virStoragePartedFsTypeTypeToString;
 virStoragePoolObjLock;
 virStoragePoolObjUnlock;
 
+virStorageEncryptionFree;
+virStorageEncryptionDropSecrets;
+virStorageEncryptionParseNode;
+virStorageEncryptionFormat;
+
 
 # threads.h
 virMutexInit;
diff --git a/src/storage_encryption.c b/src/storage_encryption.c
new file mode 100644
index 0000000..15caafd
--- /dev/null
+++ b/src/storage_encryption.c
@@ -0,0 +1,241 @@
+/*
+ * storage_encryption.h: volume encryption information
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Red Hat Author: Miloslav Trmač <mitr at redhat.com>
+ */
+
+#include <config.h>
+
+#include "internal.h"
+
+#include "base64.h"
+#include "buf.h"
+#include "memory.h"
+#include "storage_conf.h"
+#include "storage_encryption.h"
+#include "util.h"
+#include "xml.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+VIR_ENUM_IMPL(virStorageEncryptionSecretType,
+              VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST, "passphrase")
+
+VIR_ENUM_IMPL(virStorageEncryptionFormat,
+              VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
+              "unencrypted", "default", "qcow")
+
+static void
+virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret)
+{
+    if (!secret)
+        return;
+    VIR_FREE(secret->secret_id);
+    VIR_FREE(secret);
+}
+
+void
+virStorageEncryptionFree(virStorageEncryptionPtr enc)
+{
+    size_t i;
+
+    if (!enc)
+        return;
+
+    for (i = 0; i < enc->nsecrets; i++)
+        virStorageEncryptionSecretFree(enc->secrets[i]);
+    VIR_FREE(enc->secrets);
+    VIR_FREE(enc);
+}
+
+static virStorageEncryptionSecretPtr
+virStorageEncryptionSecretParse(virConnectPtr conn, xmlXPathContextPtr ctxt,
+                                xmlNodePtr node)
+{
+    xmlNodePtr old_node;
+    virStorageEncryptionSecretPtr ret;
+    char *type_str;
+    int type;
+
+    if (VIR_ALLOC(ret) < 0) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    old_node = ctxt->node;
+    ctxt->node = node;
+
+    type_str = virXPathString(conn, "string(./@type)", ctxt);
+    if (type_str == NULL) {
+        virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
+                              _("unknown volume encryption secret type"));
+        goto cleanup;
+    }
+    type = virStorageEncryptionSecretTypeTypeFromString(type_str);
+    if (type < 0) {
+        virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                              _("unknown volume encryption secret type %s"),
+                              type_str);
+        VIR_FREE(type_str);
+        goto cleanup;
+    }
+    VIR_FREE(type_str);
+    ret->type = type;
+
+    ret->secret_id = virXPathString(conn, "string(./@secret_id)", ctxt);
+    ctxt->node = old_node;
+    return ret;
+
+  cleanup:
+    virStorageEncryptionSecretFree(ret);
+    ctxt->node = old_node;
+    return NULL;
+}
+
+static virStorageEncryptionPtr
+virStorageEncryptionParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt)
+{
+    xmlNodePtr *nodes = NULL;
+    virStorageEncryptionPtr ret;
+    char *format_str;
+    int format, i, n;
+
+    if (VIR_ALLOC(ret) < 0) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    format_str = virXPathString(conn, "string(./@format)", ctxt);
+    if (format_str == NULL) {
+        virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
+                              _("unknown volume encryption format"));
+        goto cleanup;
+    }
+    format = virStorageEncryptionFormatTypeFromString(format_str);
+    if (format < 0) {
+        virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                              _("unknown volume encryption format type %s"),
+                              format_str);
+        VIR_FREE(format_str);
+        goto cleanup;
+    }
+    VIR_FREE(format_str);
+    ret->format = format;
+
+    n = virXPathNodeSet(conn, "./secret", ctxt, &nodes);
+    if (n < 0){
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                              _("cannot extract volume encryption secrets"));
+        goto cleanup;
+    }
+    if (n != 0 && VIR_ALLOC_N(ret->secrets, n) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+    ret->nsecrets = n;
+    for (i = 0; i < n; i++) {
+        ret->secrets[i] = virStorageEncryptionSecretParse(conn, ctxt, nodes[i]);
+        if (ret->secrets[i] == NULL)
+            goto cleanup;
+    }
+    VIR_FREE(nodes);
+
+    return ret;
+
+  cleanup:
+    VIR_FREE(nodes);
+    virStorageEncryptionFree(ret);
+    return NULL;
+}
+
+virStorageEncryptionPtr
+virStorageEncryptionParseNode(virConnectPtr conn,
+                              xmlDocPtr xml, xmlNodePtr root)
+{
+    xmlXPathContextPtr ctxt = NULL;
+    virStorageEncryptionPtr enc = NULL;
+
+    if (STRNEQ((const char *) root->name, "encryption")) {
+        virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                              "%s", _("unknown root element for volume "
+                                      "encryption information"));
+        goto cleanup;
+    }
+
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    ctxt->node = root;
+    enc = virStorageEncryptionParseXML(conn, ctxt);
+
+  cleanup:
+    xmlXPathFreeContext(ctxt);
+    return enc;
+}
+
+static int
+virStorageEncryptionSecretFormat(virConnectPtr conn,
+                                 virBufferPtr buf,
+                                 virStorageEncryptionSecretPtr secret)
+{
+    const char *type;
+
+    type = virStorageEncryptionSecretTypeTypeToString(secret->type);
+    if (!type) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                              _("unexpected volume encryption secret type"));
+        return -1;
+    }
+
+    virBufferVSprintf(buf, "    <secret type='%s'", type);
+    if (secret->secret_id != NULL)
+      virBufferEscapeString(buf, " secret_id='%s'", secret->secret_id);
+    virBufferAddLit(buf, "/>\n");
+    return 0;
+}
+
+int
+virStorageEncryptionFormat(virConnectPtr conn,
+                           virBufferPtr buf,
+                           virStorageEncryptionPtr enc)
+{
+    const char *format;
+    size_t i;
+
+    format = virStorageEncryptionFormatTypeToString(enc->format);
+    if (!format) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("unexpected encryption format"));
+        return -1;
+    }
+    virBufferVSprintf(buf, "  <encryption format='%s'>\n", format);
+
+    for (i = 0; i < enc->nsecrets; i++) {
+      if (virStorageEncryptionSecretFormat(conn, buf, enc->secrets[i]) < 0)
+        return -1;
+    }
+
+    virBufferAddLit(buf, "  </encryption>\n");
+
+    return 0;
+}
diff --git a/src/storage_encryption.h b/src/storage_encryption.h
new file mode 100644
index 0000000..3153ec8
--- /dev/null
+++ b/src/storage_encryption.h
@@ -0,0 +1,72 @@
+/*
+ * storage_encryption.h: volume encryption information
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Red Hat Author: Miloslav Trmač <mitr at redhat.com>
+ */
+
+#ifndef __VIR_STORAGE_ENCRYPTION_H__
+#define __VIR_STORAGE_ENCRYPTION_H__
+
+#include "internal.h"
+#include "buf.h"
+#include "util.h"
+
+#include <stdbool.h>
+#include <libxml/tree.h>
+
+enum virStorageEncryptionSecretType {
+    VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE = 0,
+
+    VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST
+};
+VIR_ENUM_DECL(virStorageEncryptionSecretType)
+
+typedef struct _virStorageEncryptionSecret virStorageEncryptionSecret;
+typedef virStorageEncryptionSecret *virStorageEncryptionSecretPtr;
+struct _virStorageEncryptionSecret {
+    int type;                   /* enum virStorageEncryptionSecretType */
+    char *secret_id;
+};
+
+enum virStorageEncryptionFormat {
+    VIR_STORAGE_ENCRYPTION_FORMAT_UNENCRYPTED = 0,
+    VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT, /* Only valid for volume creation */
+    VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */
+
+    VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
+};
+VIR_ENUM_DECL(virStorageEncryptionFormat)
+
+typedef struct _virStorageEncryption virStorageEncryption;
+typedef virStorageEncryption *virStorageEncryptionPtr;
+struct _virStorageEncryption {
+    int format;            /* enum virStorageEncryptionFormat */
+
+    size_t nsecrets;
+    virStorageEncryptionSecretPtr *secrets;
+};
+
+void virStorageEncryptionFree(virStorageEncryptionPtr enc);
+virStorageEncryptionPtr virStorageEncryptionParseNode(virConnectPtr conn,
+                                                      xmlDocPtr xml,
+                                                      xmlNodePtr root);
+int virStorageEncryptionFormat(virConnectPtr conn, virBufferPtr buf,
+                               virStorageEncryptionPtr enc);
+
+#endif /* __VIR_STORAGE_ENCRYPTION_H__ */
-- 
1.6.2.5




More information about the libvir-list mailing list