storage: add auth to virDomainDiskDef

Add additional fields to let you specify the how to authenticate with a disk.
The secret to use may be referenced by a usage string or a UUID, i.e.:

<auth username='myuser'>
 <secret type='ceph' usage='secretname'/>
</auth>

or

<auth username='myuser'>
 <secret type='ceph' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/>
</auth>

Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
This commit is contained in:
Josh Durgin 2011-10-28 12:29:39 -06:00 committed by Eric Blake
parent 536d1f8746
commit 5bd6271f59
7 changed files with 176 additions and 9 deletions

View File

@ -200,6 +200,7 @@ Patches have also been contributed by:
Sage Weil <sage@newdream.net>
David L Stevens <dlstevens@us.ibm.com>
Tyler Coumbes <coumbes@gmail.com>
Josh Durgin <josh.durgin@dreamhost.com>
[....send patches to get your name here....]

View File

@ -913,6 +913,16 @@
&lt;transient/&gt;
&lt;address type='drive' controller='0' bus='1' unit='0'/&gt;
&lt;/disk&gt;
&lt;disk type='network'&gt;
&lt;driver name="qemu" type="raw"/&gt;
&lt;source protocol="rbd" name="image_name2"&gt;
&lt;host name="hostname" port="7000"/&gt;
&lt;/source&gt;
&lt;target dev="hdd" bus="ide"/&gt;
&lt;auth username='myuser'&gt;
&lt;secret type='ceph' usage='mypassid'/&gt;
&lt;/auth&gt;
&lt;/disk&gt;
&lt;disk type='block' device='cdrom'&gt;
&lt;driver name='qemu' type='raw'/&gt;
&lt;target def='hdc' bus='ide'/&gt;
@ -1160,7 +1170,24 @@
"drive" controller, additional attributes
<code>controller</code>, <code>bus</code>,
and <code>unit</code> are available, each defaulting to 0.
</dd>
<dt><code>auth</code></dt>
<dd>If present, the <code>auth</code> element provides the
authentication credentials needed to access the source. It
includes a mandatory attribute <code>username</code>, which
identifies the username to use during authentication, as well
as a sub-element <code>secret</code> with mandatory
attribute <code>type</code>, to tie back to
a <a href="formatsecret.html">libvirt secret object</a> that
holds the actual password or other credentials (the domain XML
intentionally does not expose the password, only the reference
to the object that does manage the password). For now, the
only known secret <code>type</code> is "ceph", for Ceph RBD
network sources, and requires either an
attribute <code>uuid</code> with the UUID of the Ceph secret
object, or an attribute <code>usage</code> with the name
associated with the Ceph secret
object. <span class="since">libvirt 0.9.7</span>
</dd>
</dl>

View File

@ -602,6 +602,9 @@
<optional>
<ref name="driver"/>
</optional>
<optional>
<ref name="diskAuth"/>
</optional>
<ref name="target"/>
<optional>
<ref name="deviceBoot"/>
@ -2535,6 +2538,32 @@
<empty/>
</element>
</define>
<define name="diskAuth">
<element name="auth">
<attribute name="username">
<ref name="genericName"/>
</attribute>
<ref name="diskAuthSecret"/>
</element>
</define>
<define name='diskAuthSecret'>
<element name='secret'>
<attribute name='type'>
<choice>
<value>ceph</value>
</choice>
</attribute>
<choice>
<attribute name='uuid'>
<ref name="UUID"/>
</attribute>
<attribute name="usage">
<ref name="genericName"/>
</attribute>
</choice>
</element>
</define>
<!--
Optional hypervisor extensions in their own namespace:

View File

@ -1475,6 +1475,7 @@ libvirt_lxc_SOURCES = \
$(NODE_INFO_SOURCES) \
$(ENCRYPTION_CONF_SOURCES) \
$(DOMAIN_CONF_SOURCES) \
$(SECRET_CONF_SOURCES) \
$(CPU_CONF_SOURCES) \
$(NWFILTER_PARAM_CONF_SOURCES)
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)

View File

@ -49,6 +49,7 @@
#include "virfile.h"
#include "bitmap.h"
#include "count-one-bits.h"
#include "secret_conf.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@ -185,6 +186,11 @@ VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
"rbd",
"sheepdog")
VIR_ENUM_IMPL(virDomainDiskSecretType, VIR_DOMAIN_DISK_SECRET_TYPE_LAST,
"none",
"uuid",
"usage")
VIR_ENUM_IMPL(virDomainDiskIo, VIR_DOMAIN_DISK_IO_LAST,
"default",
"native",
@ -788,6 +794,9 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->dst);
VIR_FREE(def->driverName);
VIR_FREE(def->driverType);
VIR_FREE(def->auth.username);
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
VIR_FREE(def->auth.secret.usage);
virStorageEncryptionFree(def->encryption);
virDomainDeviceInfoClear(&def->info);
@ -2304,7 +2313,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
unsigned int flags)
{
virDomainDiskDefPtr def;
xmlNodePtr cur, host;
xmlNodePtr cur, child;
char *type = NULL;
char *device = NULL;
char *snapshot = NULL;
@ -2326,6 +2335,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
virStorageEncryptionPtr encryption = NULL;
char *serial = NULL;
char *startupPolicy = NULL;
char *authUsername = NULL;
char *authUsage = NULL;
char *authUUID = NULL;
char *usageType = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@ -2382,10 +2395,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
_("missing name for disk source"));
goto error;
}
host = cur->children;
while (host != NULL) {
if (host->type == XML_ELEMENT_NODE &&
xmlStrEqual(host->name, BAD_CAST "host")) {
child = cur->children;
while (child != NULL) {
if (child->type == XML_ELEMENT_NODE &&
xmlStrEqual(child->name, BAD_CAST "host")) {
if (VIR_REALLOC_N(hosts, nhosts + 1) < 0) {
virReportOOMError();
goto error;
@ -2394,20 +2407,20 @@ virDomainDiskDefParseXML(virCapsPtr caps,
hosts[nhosts].port = NULL;
nhosts++;
hosts[nhosts - 1].name = virXMLPropString(host, "name");
hosts[nhosts - 1].name = virXMLPropString(child, "name");
if (!hosts[nhosts - 1].name) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing name for host"));
goto error;
}
hosts[nhosts - 1].port = virXMLPropString(host, "port");
hosts[nhosts - 1].port = virXMLPropString(child, "port");
if (!hosts[nhosts - 1].port) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing port for host"));
goto error;
}
}
host = host->next;
child = child->next;
}
break;
default:
@ -2444,6 +2457,58 @@ virDomainDiskDefParseXML(virCapsPtr caps,
iotag = virXMLPropString(cur, "io");
ioeventfd = virXMLPropString(cur, "ioeventfd");
event_idx = virXMLPropString(cur, "event_idx");
} else if (xmlStrEqual(cur->name, BAD_CAST "auth")) {
authUsername = virXMLPropString(cur, "username");
if (authUsername == NULL) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("missing username for auth"));
goto error;
}
def->auth.secretType = VIR_DOMAIN_DISK_SECRET_TYPE_NONE;
child = cur->children;
while (child != NULL) {
if (child->type == XML_ELEMENT_NODE &&
xmlStrEqual(child->name, BAD_CAST "secret")) {
usageType = virXMLPropString(child, "type");
if (usageType == NULL) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("missing type for secret"));
goto error;
}
if (virSecretUsageTypeTypeFromString(usageType) !=
VIR_SECRET_USAGE_TYPE_CEPH) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("invalid secret type %s"),
usageType);
goto error;
}
authUUID = virXMLPropString(child, "uuid");
authUsage = virXMLPropString(child, "usage");
if (authUUID != NULL && authUsage != NULL) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("only one of uuid and usage can be specfied"));
goto error;
}
if (authUUID != NULL) {
def->auth.secretType = VIR_DOMAIN_DISK_SECRET_TYPE_UUID;
if (virUUIDParse(authUUID,
def->auth.secret.uuid) < 0) {
virDomainReportError(VIR_ERR_XML_ERROR,
_("malformed uuid %s"),
authUUID);
goto error;
}
} else if (authUsage != NULL) {
def->auth.secretType = VIR_DOMAIN_DISK_SECRET_TYPE_USAGE;
def->auth.secret.usage = authUsage;
authUsage = NULL;
}
}
child = child->next;
}
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
def->readonly = 1;
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
@ -2683,6 +2748,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
hosts = NULL;
def->nhosts = nhosts;
nhosts = 0;
def->auth.username = authUsername;
authUsername = NULL;
def->driverName = driverName;
driverName = NULL;
def->driverType = driverType;
@ -2719,6 +2786,10 @@ cleanup:
VIR_FREE(hosts);
VIR_FREE(protocol);
VIR_FREE(device);
VIR_FREE(authUsername);
VIR_FREE(usageType);
VIR_FREE(authUUID);
VIR_FREE(authUsage);
VIR_FREE(driverType);
VIR_FREE(driverName);
VIR_FREE(cachetag);
@ -9208,6 +9279,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
char uuidstr[VIR_UUID_STRING_BUFLEN];
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %d"), def->type);
@ -9265,6 +9338,23 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
if (def->auth.username) {
virBufferEscapeString(buf, " <auth username='%s'>\n",
def->auth.username);
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) {
virUUIDFormat(def->auth.secret.uuid, uuidstr);
virBufferAsprintf(buf,
" <secret type='ceph' uuid='%s'/>\n",
uuidstr);
}
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE) {
virBufferEscapeString(buf,
" <secret type='ceph' usage='%s'/>\n",
def->auth.secret.usage);
}
virBufferAddLit(buf, " </auth>\n");
}
if (def->src || def->nhosts > 0 ||
def->startupPolicy) {
switch (def->type) {

View File

@ -278,6 +278,14 @@ enum virDomainStartupPolicy {
VIR_DOMAIN_STARTUP_POLICY_LAST
};
enum virDomainDiskSecretType {
VIR_DOMAIN_DISK_SECRET_TYPE_NONE,
VIR_DOMAIN_DISK_SECRET_TYPE_UUID,
VIR_DOMAIN_DISK_SECRET_TYPE_USAGE,
VIR_DOMAIN_DISK_SECRET_TYPE_LAST
};
/* Stores the virtual disk configuration */
typedef struct _virDomainDiskDef virDomainDiskDef;
typedef virDomainDiskDef *virDomainDiskDefPtr;
@ -290,6 +298,14 @@ struct _virDomainDiskDef {
int protocol;
int nhosts;
virDomainDiskHostDefPtr hosts;
struct {
char *username;
int secretType; /* enum virDomainDiskSecretType */
union {
unsigned char uuid[VIR_UUID_BUFLEN];
char *usage;
} secret;
} auth;
char *driverName;
char *driverType;
char *serial;
@ -1881,6 +1897,7 @@ VIR_ENUM_DECL(virDomainDiskCache)
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
VIR_ENUM_DECL(virDomainDiskProtocol)
VIR_ENUM_DECL(virDomainDiskIo)
VIR_ENUM_DECL(virDomainDiskSecretType)
VIR_ENUM_DECL(virDomainDiskSnapshot)
VIR_ENUM_DECL(virDomainIoEventFd)
VIR_ENUM_DECL(virDomainVirtioEventIdx)

View File

@ -930,6 +930,8 @@ virSecretDefFormat;
virSecretDefFree;
virSecretDefParseFile;
virSecretDefParseString;
virSecretUsageTypeTypeFromString;
virSecretUsageTypeTypeToString;
# security_driver.h