[libvirt] [PATCH v2 07/19] virudev: Introduce virUdevMgrDump
Daniel P. Berrange
berrange at redhat.com
Thu Nov 3 12:57:39 UTC 2016
On Thu, Nov 03, 2016 at 08:18:57PM +0800, Michal Privoznik wrote:
> Now that we are able to store security labels for devices, next
> step is to flush them into a file. For more convenience I've
> chosen JSON format (as we have all the APIs needed for processing
> the format).
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
> po/POTFILES.in | 1 +
> src/libvirt_private.syms | 2 +
> src/util/virudev.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++
> src/util/virudev.h | 5 ++
> 4 files changed, 165 insertions(+)
>
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index 1469240..dabc612 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -248,6 +248,7 @@ src/util/virthreadpool.c
> src/util/virtime.c
> src/util/virtpm.c
> src/util/virtypedparam.c
> +src/util/virudev.c
> src/util/viruri.c
> src/util/virusb.c
> src/util/virutil.c
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 073b00f..ca64c80 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2579,6 +2579,8 @@ virTypedParamsValidate;
>
> # util/virudev.h
> virUdevMgrAddLabel;
> +virUdevMgrDumpFile;
> +virUdevMgrDumpStr;
> virUdevMgrNew;
> virUdevMgrRemoveAllLabels;
>
> diff --git a/src/util/virudev.c b/src/util/virudev.c
> index f4799e7..7f52149 100644
> --- a/src/util/virudev.c
> +++ b/src/util/virudev.c
> @@ -24,7 +24,9 @@
>
> #include "internal.h"
> #include "viralloc.h"
> +#include "virfile.h"
> #include "virhash.h"
> +#include "virjson.h"
> #include "virobject.h"
> #include "virudev.h"
>
> @@ -112,6 +114,68 @@ udevSeclabelUpdate(udevSeclabelPtr list,
> }
>
>
> +static virJSONValuePtr
> +udevSeclabelDump(const virSecurityDeviceLabelDef *seclabel)
> +{
> + virJSONValuePtr object;
> +
> + if (!(object = virJSONValueNewObject()) ||
> + virJSONValueObjectAppendString(object, "model", seclabel->model) < 0 ||
> + virJSONValueObjectAppendString(object, "label", seclabel->label) < 0)
> + goto error;
> +
> + return object;
> +
> + error:
> + virJSONValueFree(object);
> + return NULL;
> +}
> +
> +
> +static int
> +udevSeclabelsDump(void *payload,
> + const void *name,
> + void *opaque)
> +{
> + udevSeclabelPtr list = payload;
> + const char *device = name;
> + virJSONValuePtr seclabels = opaque;
> + virJSONValuePtr deviceLabels = NULL;
> + virJSONValuePtr deviceJSON = NULL;
> + size_t i;
> + int ret = -1;
> +
> + if (!(deviceLabels = virJSONValueNewArray()))
> + return ret;
> +
> + for (i = 0; i < list->nseclabels; i++) {
> + virJSONValuePtr seclabel = udevSeclabelDump(list->seclabels[i]);
> +
> + if (!seclabel ||
> + virJSONValueArrayAppend(deviceLabels, seclabel) < 0) {
> + virJSONValueFree(seclabel);
> + goto cleanup;
> + }
> + }
> +
> + if (!(deviceJSON = virJSONValueNewObject()) ||
> + virJSONValueObjectAppendString(deviceJSON, "device", device) < 0 ||
> + virJSONValueObjectAppend(deviceJSON, "labels", deviceLabels) < 0)
> + goto cleanup;
> + deviceLabels = NULL;
> +
> + if (virJSONValueArrayAppend(seclabels, deviceJSON) < 0)
> + goto cleanup;
> + deviceJSON = NULL;
> +
> + ret = 0;
> + cleanup:
> + virJSONValueFree(deviceJSON);
> + virJSONValueFree(deviceLabels);
> + return ret;
> +}
> +
> +
> static void
> virUdevMgrDispose(void *obj)
> {
> @@ -202,3 +266,96 @@ virUdevMgrRemoveAllLabels(virUdevMgrPtr mgr,
> virObjectUnlock(mgr);
> return ret;
> }
> +
> +
> +static virJSONValuePtr
> +virUdevSeclabelDump(virUdevMgrPtr mgr)
> +{
> + virJSONValuePtr seclabels;
> +
> + if (!(seclabels = virJSONValueNewArray()))
> + return NULL;
> +
> + if (virHashForEach(mgr->labels, udevSeclabelsDump, seclabels) < 0) {
> + virJSONValueFree(seclabels);
> + return NULL;
> + }
> +
> + return seclabels;
> +}
> +
> +
> +static char *
> +virUdevMgrDumpInternal(virUdevMgrPtr mgr)
> +{
> + virJSONValuePtr object = NULL;
> + virJSONValuePtr child = NULL;
> + char *ret = NULL;
> +
> + if (!(object = virJSONValueNewObject()))
> + goto cleanup;
> +
> + if (!(child = virUdevSeclabelDump(mgr)))
> + goto cleanup;
> +
> + if (virJSONValueObjectAppend(object, "labels", child) < 0) {
> + virJSONValueFree(child);
> + goto cleanup;
> + }
> +
> + ret = virJSONValueToString(object, true);
> + cleanup:
> + virJSONValueFree(object);
> + return ret;
> +}
> +
> +
> +char *
> +virUdevMgrDumpStr(virUdevMgrPtr mgr)
> +{
> + char *ret;
> +
> + virObjectLock(mgr);
> + ret = virUdevMgrDumpInternal(mgr);
> + virObjectUnlock(mgr);
> + return ret;
> +}
> +
> +
> +static int
> +virUdevMgrRewriter(int fd, void *opaque)
> +{
> + const char *str = opaque;
> +
> + return safewrite(fd, str, strlen(str));
> +}
> +
> +
> +int
> +virUdevMgrDumpFile(virUdevMgrPtr mgr,
> + const char *filename)
> +{
> + int ret = -1;
> + char *state;
> +
> + virObjectLock(mgr);
> +
> + if (!(state = virUdevMgrDumpInternal(mgr)))
> + goto cleanup;
> +
> + /* Here we shouldn't use pure virFileWriteStr() as that one is not atomic.
> + * We can be interrupted in the middle (e.g. due to a context switch) and
> + * thus leave the file partially written. */
> + if (virFileRewrite(filename, 0644, virUdevMgrRewriter, state) < 0) {
> + virReportSystemError(errno,
> + _("Unable to save state file %s"),
> + filename);
> + goto cleanup;
> + }
Dumping the entire DB as a single file is pretty inefficient when you consider
hosts with 1000's of guests with multiple disks attached. As suggested last
time, any database should be one-file per associated disk - there's no
compelling reason to require all disk info to be in a single file AFAICT.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
More information about the libvir-list
mailing list