storage: optional 'refresh' elemement on pool

The new 'refresh' element can override the default refresh operations
for a storage pool. The only currently supported override is to set
the volume allocation size to the volume capacity. This can be specified
by adding the following snippet:

<pool>
...
  <refresh>
    <volume allocation='capacity'/>
  </refresh>
...
</pool>

This is useful for certain backends where computing the actual allocation
of a volume might be an expensive operation.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Jason Dillaman 2019-03-19 09:42:17 -04:00 committed by Michal Privoznik
parent 21deeaf02f
commit 669018bc9c
9 changed files with 172 additions and 0 deletions

View File

@ -508,6 +508,32 @@
device, measured in bytes. <span class="since">Since 0.4.1</span>
</p>
<h3><a id="StoragePoolRefresh">Refresh overrides</a></h3>
<p>
The optional <code>refresh</code> element can control how the pool and
associated volumes are refreshed (pool type <code>rbd</code>). The
<code>allocation</code> attribute of the <code>volume</code> child element
controls the method used for computing the allocation of a volume. The
valid attribute values are <code>default</code> to compute the actual
usage or <code>capacity</code> to use the logical capacity for cases where
computing the allocation is too expensive. The following XML snippet
shows the syntax:
<pre>
&lt;pool type="rbd"&gt;
&lt;name&gt;myrbdpool&lt;/name&gt;
...
&lt;source/&gt;
...
&lt;refresh&gt;
&lt;volume allocation='capacity'/&gt;
&lt;/refresh&gt;
...
&lt;/pool&gt;
</pre>
<span class="since">Since 5.2.0</span>
</p>
<h3><a id="StoragePoolNamespaces">Storage Pool Namespaces</a></h3>
<p>

View File

@ -236,4 +236,11 @@
</optional>
</define>
<define name='refreshVolumeAllocation'>
<choice>
<value>default</value>
<value>capacity</value>
</choice>
</define>
</grammar>

View File

@ -155,6 +155,7 @@
<ref name='commonMetadataNameOptional'/>
<ref name='sizing'/>
<ref name='sourcerbd'/>
<ref name='refresh'/>
</interleave>
<optional>
<ref name='rbd_config_opts'/>
@ -691,6 +692,28 @@
</data>
</define>
<define name='refresh'>
<optional>
<element name='refresh'>
<interleave>
<ref name='refreshVolume'/>
</interleave>
</element>
</optional>
</define>
<define name='refreshVolume'>
<optional>
<element name='volume'>
<optional>
<attribute name='allocation'>
<ref name="refreshVolumeAllocation"/>
</attribute>
</optional>
</element>
</optional>
</define>
<!--
Optional storage pool extensions in their own namespace:
"fs" or "netfs"

View File

@ -94,6 +94,11 @@ VIR_ENUM_IMPL(virStorageVolFormatDisk,
"extended",
);
VIR_ENUM_IMPL(virStorageVolDefRefreshAllocation,
VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_LAST,
"default", "capacity",
);
VIR_ENUM_IMPL(virStoragePartedFs,
VIR_STORAGE_PARTED_FS_TYPE_LAST,
"ext2", "ext2", "fat16",
@ -789,6 +794,51 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
}
static int
virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,
virStoragePoolDefPtr def)
{
VIR_AUTOFREE(virStoragePoolDefRefreshPtr) refresh = NULL;
VIR_AUTOFREE(char *) allocation = NULL;
int tmp;
allocation = virXPathString("string(./refresh/volume/@allocation)", ctxt);
if (!allocation)
return 0;
if ((tmp = virStorageVolDefRefreshAllocationTypeFromString(allocation)) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unknown storage pool volume refresh allocation type %s"),
allocation);
return -1;
}
if (VIR_ALLOC(refresh) < 0)
return -1;
refresh->volume.allocation = tmp;
VIR_STEAL_PTR(def->refresh, refresh);
return 0;
}
static void
virStoragePoolDefRefreshFormat(virBufferPtr buf,
virStoragePoolDefRefreshPtr refresh)
{
if (!refresh)
return;
virBufferAddLit(buf, "<refresh>\n");
virBufferAdjustIndent(buf, 2);
virBufferAsprintf(buf, "<volume allocation='%s'/>\n",
virStorageVolDefRefreshAllocationTypeToString(refresh->volume.allocation));
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</refresh>\n");
}
virStoragePoolDefPtr
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
@ -799,6 +849,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
VIR_AUTOFREE(char *) type = NULL;
VIR_AUTOFREE(char *) uuid = NULL;
VIR_AUTOFREE(char *) target_path = NULL;
VIR_AUTOFREE(char *) refresh_volume_allocation = NULL;
if (VIR_ALLOC(def) < 0)
return NULL;
@ -931,6 +982,9 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
return NULL;
}
if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
return NULL;
/* Make a copy of all the callback pointers here for easier use,
* especially during the virStoragePoolSourceClear method */
def->ns = options->ns;
@ -1163,6 +1217,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf,
virBufferAddLit(buf, "</target>\n");
}
virStoragePoolDefRefreshFormat(buf, def->refresh);
if (def->namespaceData && def->ns.format) {
if ((def->ns.format)(buf, def->namespaceData) < 0)
return -1;

View File

@ -83,6 +83,13 @@ struct _virStorageVolSource {
* backend for partition type creation */
};
typedef enum {
VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_DEFAULT, /* compute actual allocation */
VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_CAPACITY, /* use logical capacity */
VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_LAST,
} virStorageVolDefRefreshAllocation;
VIR_ENUM_DECL(virStorageVolDefRefreshAllocation);
typedef struct _virStorageVolDef virStorageVolDef;
typedef virStorageVolDef *virStorageVolDefPtr;
@ -236,6 +243,21 @@ struct _virStoragePoolTarget {
virStoragePerms perms; /* Default permissions for volumes */
};
typedef struct _virStorageVolDefRefresh virStorageVolDefRefresh;
typedef virStorageVolDefRefresh *virStorageVolDefRefreshPtr;
struct _virStorageVolDefRefresh {
int allocation; /* virStorageVolDefRefreshAllocation */
};
typedef struct _virStoragePoolDefRefresh virStoragePoolDefRefresh;
typedef virStoragePoolDefRefresh *virStoragePoolDefRefreshPtr;
struct _virStoragePoolDefRefresh {
virStorageVolDefRefresh volume;
};
typedef struct _virStoragePoolDef virStoragePoolDef;
typedef virStoragePoolDef *virStoragePoolDefPtr;
struct _virStoragePoolDef {
@ -243,6 +265,8 @@ struct _virStoragePoolDef {
unsigned char uuid[VIR_UUID_BUFLEN];
int type; /* virStoragePoolType */
virStoragePoolDefRefreshPtr refresh;
unsigned long long allocation; /* bytes */
unsigned long long capacity; /* bytes */
unsigned long long available; /* bytes */

View File

@ -942,6 +942,8 @@ virStorageVolDefFree;
virStorageVolDefParseFile;
virStorageVolDefParseNode;
virStorageVolDefParseString;
virStorageVolDefRefreshAllocationTypeFromString;
virStorageVolDefRefreshAllocationTypeToString;
virStorageVolTypeFromString;
virStorageVolTypeToString;

View File

@ -0,0 +1,15 @@
<pool type='rbd'>
<name>ceph</name>
<uuid>47c1faee-0207-e741-f5ae-d9b019b98fe2</uuid>
<source>
<name>rbd</name>
<host name='localhost' port='6789'/>
<host name='localhost' port='6790'/>
<auth username='admin' type='ceph'>
<secret uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/>
</auth>
</source>
<refresh>
<volume allocation='capacity'/>
</refresh>
</pool>

View File

@ -0,0 +1,18 @@
<pool type='rbd'>
<name>ceph</name>
<uuid>47c1faee-0207-e741-f5ae-d9b019b98fe2</uuid>
<capacity unit='bytes'>0</capacity>
<allocation unit='bytes'>0</allocation>
<available unit='bytes'>0</available>
<source>
<host name='localhost' port='6789'/>
<host name='localhost' port='6790'/>
<name>rbd</name>
<auth type='ceph' username='admin'>
<secret uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/>
</auth>
</source>
<refresh>
<volume allocation='capacity'/>
</refresh>
</pool>

View File

@ -95,6 +95,7 @@ mymain(void)
DO_TEST("pool-zfs-sourcedev");
DO_TEST("pool-rbd");
#ifdef WITH_STORAGE_RBD
DO_TEST("pool-rbd-refresh-volume-allocation");
DO_TEST("pool-rbd-ns-configopts");
#endif
DO_TEST("pool-vstorage");