[libvirt] [PATCH] Add PKG_CONFIG_PATH to run.in script.
by Daniel P. Berrange
Allow people to build external bindings using the 'run' script
by defining the PKG_CONFIG_PATH var in it. eg to build Python
you could do
../libvirt/run python setup.py build
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
run.in | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/run.in b/run.in
index 1a379dd..cbef61a 100644
--- a/run.in
+++ b/run.in
@@ -53,6 +53,13 @@ else
fi
export LD_LIBRARY_PATH
+if [ -z "$PKG_CONFIG_PATH" ]; then
+ PKG_CONFIG_PATH="$b/src"
+else
+ PKG_CONFIG_PATH="$b/src:$PKG_CONFIG_PATH"
+fi
+export PKG_CONFIG_PATH
+
export LIBVIRT_DRIVER_DIR="$b/src/.libs"
export LIBVIRT_LOCK_MANAGER_PLUGIN_DIR="$b/src/.libs"
export VIRTLOCKD_PATH="$b/src"
--
1.9.3
10 years, 5 months
[libvirt] [PATCH] Initial implementation of new job control api
by Tucker DiNapoli
This is my initial definition of a new internal job control api. I am
working on this as a part of the google summer of code. These patches
contain the core job control api and deal only with managing individual
jobs. I am currently working on writing code using this api to manage
jobs in domains, in such a way that I will be able to replace the
current job control code in qemu and libxl. Ultimately I will use this
to implement job control in the storage driver which is my ultimate
goal for the summer of code.
---
src/Makefile.am | 1 +
src/util/virjobcontrol.c | 574 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virjobcontrol.h | 342 ++++++++++++++++++++++++++++
3 files changed, 917 insertions(+)
create mode 100644 src/util/virjobcontrol.c
create mode 100644 src/util/virjobcontrol.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b9ac61..77de0e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,7 @@ UTIL_SOURCES = \
util/virinitctl.c util/virinitctl.h \
util/viriptables.c util/viriptables.h \
util/viriscsi.c util/viriscsi.h \
+ util/virjobcontrol.h util/virjobcontrol.c \
util/virjson.c util/virjson.h \
util/virkeycode.c util/virkeycode.h \
util/virkeyfile.c util/virkeyfile.h \
diff --git a/src/util/virjobcontrol.c b/src/util/virjobcontrol.c
new file mode 100644
index 0000000..04a5246
--- /dev/null
+++ b/src/util/virjobcontrol.c
@@ -0,0 +1,574 @@
+/*
+ * virjobcontrol.c Core implementation of job control
+ *
+ * Copyright (C) 2014 Tucker DiNapoli
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Tucker DiNapoli
+ */
+
+#include <config.h>
+
+#include "virjobcontrol.h"
+#include "viralloc.h"
+#include "virtime.h"
+#include "virlog.h"
+VIR_LOG_INIT("virjobcontrol");
+
+VIR_ENUM_IMPL(virJob, 4,
+ "none",
+ "query",
+ "modify",
+ "destroy",
+);
+/*
+ No files other then this and virjobcontrol.c should need to
+ have access to the core implmentation of jobs. The code in these
+ files is intended to serve as a base for job control independent of
+ drivers.
+*/
+
+#define LOCK_JOB(job) \
+ virMutexLock(&job->lock)
+#define UNLOCK_JOB(job) \
+ virMutexUnlock(&job->lock)
+#define LOCK_JOB_INFO(job) \
+ virMutexLock(&job->info->lock)
+#define UNLOCK_JOB_INFO(job) \
+ virMutexUnlock(&job->info->lock)
+#define GET_CURRENT_TIME(time) \
+ if (virTimeMillisNow(&time) < 0) { \
+ return -1; \
+ }
+
+
+#define CHECK_FLAG_ATOMIC(job, flag) (virAtomicIntGet(&job->flags) & VIR_JOB_FLAG_##flag)
+#define CHECK_FLAG(job, flag) (job->flags & VIR_JOB_FLAG_##flag)
+#define SET_FLAG_ATOMIC(job, flag) (virAtomicIntOr(&job->flags, VIR_JOB_FLAG_##flag))
+#define SET_FLAG(job, flag) (job->flags |= VIR_JOB_FLAG_##flag)
+#define UNSET_FLAG_ATOMIC(job, flag) (virAtomicIntAnd(&job->flags, (~VIR_JOB_FLAG_##flag)))
+#define UNSET_FLAG(job, flag) (job->flags &= (~VIR_JOB_FLAG_##flag))
+#define CLEAR_FLAGS_ATOMIC(job) (virAtomicIntSet(&job->flags, VIR_JOB_FLAG_NONE))
+#define CLEAR_FLAGS(job) (job->flags = VIR_JOB_FLAG_NONE)
+
+typedef struct _jobHashEntry {
+ virJobID id;
+ virJobObjPtr job;
+ struct _jobHashEntry *next;
+} jobHashEntry;
+
+typedef struct _jobHash {
+ jobHashEntry **table;
+ size_t size;
+ size_t num_entries;
+ virRWLock lock;
+} jobHash;
+
+/* Using this incures a cost on every call to a job control function
+ that uses the job control hash table, but it means that no one using
+ job control needs to call an initialization function to use it.
+
+ The other option would be to have a function:
+ virJobControlInit(void)
+ {
+ return virOnce(job_once, jobControlInit);
+ }
+ and require anyone using job control to call it.
+ */
+static struct _jobHash *job_hash; /* Hash table that contians all current jobs */
+static int init_err = 0;
+static virOnceControl job_once = VIR_ONCE_CONTROL_INITIALIZER;
+static void
+jobControlInit(void)
+{
+ if (VIR_ALLOC_QUIET(job_hash) < 0) {
+ init_err = 1;
+ }
+ if (virRWLockInit(&job_hash->lock) < 0) {
+ init_err = 1;
+ }
+ if (VIR_ALLOC_N_QUIET(job_hash->table, 16) <0) {
+ init_err = 1;
+ }
+}
+
+/* global job id
+
+ Because it gets incremented before it's first use 0 is
+ never a valid job id
+
+ Only ever touched with atomic instructions.
+*/
+static unsigned int global_id = 0;
+
+
+
+/* Simple hash table implementation for jobs.
+ It is keyed by job id's which are just integers so there isn't acutally
+ a hash function. Using the existing hash table in libvirt would be overkill.
+*/
+
+#ifndef VIR_JOB_REHASH_THRESHOLD
+#define VIR_JOB_REHASH_THRESHOLD 0.8
+#endif
+
+#ifndef VIR_JOB_BUCKET_LEN
+#define VIR_JOB_BUCKET_LEN 5
+#endif
+
+#ifndef VIR_JOB_GROWTH_FACTOR
+#define VIR_JOB_GROWTH_FACTOR 2
+#endif
+
+#define READ_LOCK_TABLE(ht) virRWLockRead((virRWLockPtr)&ht->lock)
+#define WRITE_LOCK_TABLE(ht) virRWLockWrite((virRWLockPtr)&ht->lock)
+#define UNLOCK_TABLE(ht) virRWLockUnlock((virRWLockPtr)&ht->lock)
+
+static int jobHashRehash(jobHash *ht);
+#define maybe_rehash(ht) \
+ if (((double)ht->size*VIR_JOB_BUCKET_LEN)/(ht->num_entries) >= \
+ VIR_JOB_REHASH_THRESHOLD){ \
+ jobHashRehash(ht); \
+ }
+
+
+/* Doesn't lock ht, so should only be called with a write lock held on ht*/
+static int jobHashRehash(jobHash *ht);
+
+/* look for id in the hash table ht and return the entry associated with it
+ if id isn't it the table return null*/
+static jobHashEntry*
+jobLookup(const jobHash *ht, virJobID id)
+{
+ if (virOnce(&job_once, jobControlInit) < 0) {
+ return NULL;
+ }
+ READ_LOCK_TABLE(ht);
+ int bucket = id % ht->size;
+ jobHashEntry *retval = NULL, *job_entry;
+ if (!ht->table[bucket]) {
+ goto end;
+ }
+ job_entry = ht->table[bucket];
+ do {
+ if (job_entry->id == id) {
+ retval = job_entry;
+ goto end;
+ }
+ } while ((job_entry = job_entry->next));
+
+ end:
+ UNLOCK_TABLE(ht);
+ return retval;
+}
+
+/* add job the hashtable of currently existing jobs, job should
+ have already been initialized via virJobObjInit.
+ returns 0 if job is already in the hash,
+ returns the id of the job if it was successfully added
+ returns -1 on error.
+ */
+static int
+jobHashAdd(jobHash *ht, virJobObjPtr job)
+{
+ if (virOnce(&job_once, jobControlInit) < 0) {
+ return -1;
+ }
+ virJobID id = job->id;
+ if (jobLookup(ht, id)) { /* check if job is in the table*/
+ return 0;
+ }
+ int bucket = id % ht->size;
+ jobHashEntry *new_entry;
+ if (VIR_ALLOC_QUIET(new_entry) < 0) {
+ return -1;
+ }
+ jobHashEntry *last_entry = ht->table[bucket];
+ *new_entry = (jobHashEntry) {.id = id, .job = job};
+
+ WRITE_LOCK_TABLE(ht);
+ if (!last_entry) {
+ ht->table[bucket] = new_entry;
+ } else {
+ while (last_entry->next) {
+ last_entry = last_entry->next;
+ }
+ last_entry->next = new_entry;
+ }
+ ht->num_entries++;
+ maybe_rehash(ht);
+ UNLOCK_TABLE(ht);
+ return id;
+}
+
+/* Remove the job with the given id from the list of currently existing jobs,
+ this doesn't free/cleanup the actual job object, it just removes
+ the hash entry, this is called by virJobObjFree, so there shouldn't
+ be any reason to call it directly.
+
+ return values are the same as for jobAlist add, 0 if no job found,
+ job id on success, -1 on some other error;
+*/
+static int
+jobHashRemove(jobHash *ht, virJobID id)
+{
+ int bucket = id % ht->size;
+ /*we can't just call jobLookup because we need the entry before the one
+ we want to free*/
+ WRITE_LOCK_TABLE(ht);
+ jobHashEntry *entry = ht->table[bucket], *old_entry;
+ if (!entry) {
+ goto error;
+ }
+ if (entry->id != id) {
+ while (entry && entry->next->id != id) {
+ entry = entry->next;
+ }
+ }
+ if (!entry) {
+ goto error;
+ }
+ old_entry = entry->next;
+ entry->next = old_entry->next;
+ VIR_FREE(old_entry);
+ UNLOCK_TABLE(ht);
+ return id;
+ error:
+ UNLOCK_TABLE(ht);
+ return 0;
+}
+static int
+jobHashRehash(jobHash *ht)
+{
+ size_t new_size = ht->size*VIR_JOB_GROWTH_FACTOR;
+ jobHashEntry **new_table;
+ if (VIR_ALLOC_N_QUIET(new_table, new_size)) {
+ return -1;
+ }
+ jobHashEntry **old_table = ht->table;
+ int index;
+ for (index = 0; index<ht->size; index++) {
+ jobHashEntry *old_entry = old_table[index];
+ while (old_entry) {
+ int bucket = old_entry->id % new_size;
+ jobHashEntry *new_entry = new_table[bucket];
+ if (!new_entry) {
+ new_table[bucket] = old_entry;
+ } else {
+ while (new_entry->next) {
+ new_entry = new_entry->next;
+ }
+ new_entry->next = old_entry;
+ }
+ old_entry = old_entry->next;
+ }
+ }
+ ht->size = new_size;
+ ht->table = new_table;
+ VIR_FREE(old_table);
+ return 1;
+}
+
+#define jobIDFromJobInternal(job) (job->id)
+
+static inline virJobObjPtr
+jobFromIDInternal(virJobID id)
+{
+ jobHashEntry *entry = jobLookup(job_hash, id);
+ if (entry) {
+ return entry->job;
+ } else {
+ return NULL;
+ }
+}
+
+virJobObjPtr
+virJobFromID(virJobID id)
+{
+ return jobFromIDInternal(id);
+
+}
+virJobID
+virJobIDFromJob(virJobObjPtr job)
+{
+ return jobIDFromJobInternal(job);
+}
+
+int
+virJobObjInit(virJobObjPtr job)
+{
+ /* This code checks to see if job was already initialized,
+ I don't know if this is needed or not.*/
+ if (job->id != 0) {
+ VIR_DEBUG("job %d has already been initialized", job->id);
+ return 0;
+ }
+ job->id = virAtomicIntInc(&global_id);
+ job->maxJobsWaiting = INT_MAX;
+
+ if (virCondInit(&job->cond) < 0) {
+ return -1;
+ }
+
+ if (virMutexInit(&job->lock) < 0) {
+ virCondDestroy(&job->cond);
+ return -1;
+ }
+
+ jobHashAdd(job_hash, job);
+
+ return job->id;
+}
+
+void
+virJobObjFree(virJobObjPtr job)
+{
+ virCondDestroy(&job->cond);
+ jobHashRemove(job_hash, job->id);
+ VIR_FREE(job);
+}
+
+void
+virJobObjCleanup(virJobObjPtr job)
+{
+
+ virCondDestroy(&job->cond);
+ jobHashRemove(job_hash, job->id);
+ memset(job, '\0', sizeof(virJobObj));
+ return;
+}
+
+int
+virJobObjBegin(virJobObjPtr job,
+ virJobType type)
+{
+ LOCK_JOB(job);
+ if (CHECK_FLAG(job, ACTIVE)) {
+ VIR_DEBUG("Job %d is already running", job->id);
+ UNLOCK_JOB(job);
+ return 0;
+ }
+ VIR_DEBUG("Starting job %d with type %s",
+ job->id, virJobTypeToString(type));
+ unsigned long long now;
+ if (job->id <= 0) {
+ goto error; /* job wasn't initialiazed*/
+ }
+ if (virTimeMillisNow(&now) < 0) {
+ goto error;
+ }
+ job->type = type;
+ SET_FLAG(job, ACTIVE);
+ job->start = now;
+ job->owner = virThreadSelfID();
+ return job->id;
+ error:
+ UNLOCK_JOB(job);
+ return -1;
+}
+
+int
+virJobObjEnd(virJobObjPtr job)
+{
+ if (job->type == VIR_JOB_NONE) {
+ return -1;
+ }
+ virJobObjReset(job);
+ virCondSignal(&job->cond);
+
+ return job->id;
+}
+
+/* There shouldn't be any threads waiting on job when this is called*/
+int
+virJobObjReset(virJobObjPtr job)
+{
+ LOCK_JOB(job);
+ job->type = VIR_JOB_NONE;
+ job->flags = VIR_JOB_FLAG_NONE;
+ job->owner = 0;
+ job->jobsWaiting = 0;
+ UNLOCK_JOB(job);
+
+ return job->id;
+}
+
+int
+virJobObjAbort(virJobObjPtr job)
+{
+ int retval;
+ LOCK_JOB(job);
+ if (CHECK_FLAG(job, ACTIVE) || CHECK_FLAG(job, SUSPENDED)) {
+ SET_FLAG(job, ABORTED);
+ retval = job->id;
+ } else {
+ retval = -1;
+ }
+ UNLOCK_JOB(job);
+ return retval;
+}
+
+int
+virJobObjAbortAndSignal(virJobObjPtr job)
+{
+ int retval;
+ LOCK_JOB(job);
+ if (CHECK_FLAG(job, ACTIVE) || CHECK_FLAG(job, SUSPENDED)) {
+ SET_FLAG(job, ABORTED);
+ retval = job->id;
+ virCondBroadcast(&job->cond);
+ } else {
+ retval = -1;
+ }
+ UNLOCK_JOB(job);
+ return retval;
+}
+
+/* lock should be held by the calling function*/
+int
+virJobObjWait(virJobObjPtr job,
+ virMutexPtr lock,
+ unsigned long long limit)
+{
+
+ bool job_lock = false;
+ int retval;
+ if (CHECK_FLAG_ATOMIC(job, ACTIVE)) { /* if the job isn't active we're fine*/
+ if (virAtomicIntInc(&job->jobsWaiting) > job->maxJobsWaiting) {
+ errno = 0;
+ goto error;
+ }
+ if (!lock) {
+ LOCK_JOB(job);
+ lock = &job->lock;
+ job_lock = true;
+ }
+ while (CHECK_FLAG_ATOMIC(job, ACTIVE)) {
+ if (limit) {
+ retval = virCondWaitUntil(&job->cond, lock, limit);
+ } else {
+ retval = virCondWait(&job->cond, lock);
+ }
+ if (retval < 0) {
+ goto error;
+ }
+ }
+ }
+ virAtomicIntDec(&job->jobsWaiting);
+ if (job_lock) {
+ UNLOCK_JOB(job);
+ }
+ return job->id;
+
+ error:
+ virAtomicIntDec(&job->jobsWaiting);
+ if (job_lock) {
+ UNLOCK_JOB(job);
+ }
+ if (!errno) {
+ return -3;
+ } else if (errno == ETIMEDOUT) {
+ return -2;
+ } else {
+ return -1;
+ }
+}
+
+int
+virJobObjSuspend(virJobObjPtr job)
+{
+ if (!CHECK_FLAG_ATOMIC(job, ACTIVE)) {
+ return -1;
+ }
+ LOCK_JOB(job);
+ SET_FLAG(job, SUSPENDED);
+ UNSET_FLAG(job, ACTIVE);
+ UNLOCK_JOB(job);
+ return job->id;
+}
+int
+virJobObjResume(virJobObjPtr job)
+{
+ if (!CHECK_FLAG_ATOMIC(job, SUSPENDED)) {
+ return -1;
+ }
+ LOCK_JOB(job);
+ UNSET_FLAG(job, SUSPENDED);
+ SET_FLAG(job, ACTIVE);
+ UNLOCK_JOB(job);
+ return job->id;
+}
+int
+virJobObjResumeIfNotAborted(virJobObjPtr job)
+{
+ int retval;
+ LOCK_JOB(job);
+ if (!CHECK_FLAG(job, SUSPENDED)) {
+ retval = -1;
+ } else if (CHECK_FLAG(job, ABORTED)) {
+ retval = 0;
+ } else {
+ UNSET_FLAG(job, SUSPENDED);
+ SET_FLAG(job, ACTIVE);
+ retval = job->id;
+ }
+ UNLOCK_JOB(job);
+ return retval;
+}
+
+void
+virJobObjSetMaxWaiters(virJobObjPtr job, int max)
+{
+ virAtomicIntSet(&job->maxJobsWaiting, max);
+}
+
+bool
+virJobObjCheckAbort(virJobObjPtr job)
+{
+ return CHECK_FLAG_ATOMIC(job, ABORTED);
+}
+bool
+virJobObjActive(virJobObjPtr job)
+{
+ return CHECK_FLAG_ATOMIC(job, ACTIVE);
+}
+
+/* since we need to be able to return a negitive answer on error
+ the time difference we can return is only half of the maximum
+ possible time. This shouldn't pose any real issue.
+*/
+long long
+virJobObjCheckTime(virJobObjPtr job)
+{
+ if (!CHECK_FLAG(job, ACTIVE)) {
+ return 0;
+ }
+ unsigned long long now;
+ if (virTimeMillisNow(&now) < 0) {
+ return -1;
+ }
+ return now - job->start;
+}
+
+void
+virJobObjSignal(virJobObjPtr job, bool all)
+{
+ if (all) {
+ virCondBroadcast(&job->cond);
+ } else {
+ virCondSignal(&job->cond);
+ }
+}
diff --git a/src/util/virjobcontrol.h b/src/util/virjobcontrol.h
new file mode 100644
index 0000000..235cc06
--- /dev/null
+++ b/src/util/virjobcontrol.h
@@ -0,0 +1,342 @@
+/*
+ * virjobcontrol.h Core implementation of job control
+ *
+ * Copyright (C) 2014 Tucker DiNapoli
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Tucker DiNapoli
+ */
+
+
+#ifndef __JOB_CONTROL_H__
+#define __JOB_CONTROL_H__
+
+#include <stdlib.h>
+
+#include "viratomic.h"
+#include "virthread.h"
+#include "virutil.h"
+
+
+/* The general type of the job, specifically if it will modify
+ the object it is acting on.*/
+typedef enum {
+ VIR_JOB_NONE = 0, /*no job running*/
+ VIR_JOB_QUERY = 0x1, /* job will not change object state (read-only)*/
+ VIR_JOB_MODIFY = 0x2, /* job may change object state (read-write)*/
+ VIR_JOB_DESTROY = 0x4, /* job will destroy the object it is acting on */
+ VIR_JOB_LAST
+} virJobType;
+VIR_ENUM_DECL(virJob);
+
+
+/* General metadata/flags for jobs
+
+ more specific flags can be added for speciic drivers,
+ to do this the first value of the enum for the extra flags
+ should be set to (VIR_JOB_FLAG_LAST << 1) and each additional
+ flag should be set to the last flag shifted to the left by 1.
+
+*/
+typedef enum {
+ VIR_JOB_FLAG_NONE = 0x000, /* No job is active */
+ VIR_JOB_FLAG_ACTIVE = 0x001, /* Job is active */
+ /* These next flags are used to indicate how progress should be measured
+ and are currently unused
+ */
+ VIR_JOB_FLAG_TIME_BOUND = 0x002, /* Job is bound by a specific ammount of time */
+ VIR_JOB_FLAG_MEM_BOUND = 0x004, /* Job is bound by a specific ammount of memory */
+ VIR_JOB_FLAG_FILE_BOUND = 0x008, /* Job is bound by a specific number of files */
+ VIR_JOB_FLAG_DATA_BOUND = 0x010, /* Job is bound by a specific ammount of data */
+ VIR_JOB_FLAG_UNBOUNDED = 0x020, /* Job has no specific bound */
+ /* These flags indicate a job is no longer active but still exists
+ */
+ VIR_JOB_FLAG_SUSPENDED = 0x040, /* Job is Suspended and can be resumed */
+ VIR_JOB_FLAG_COMPLETED = 0x080, /* Job has finished, but isn't cleaned up */
+ VIR_JOB_FLAG_FAILED = 0x100, /* Job hit error, but isn't cleaned up */
+ VIR_JOB_FLAG_ABORTED = 0x200, /* Job was aborted, but isn't cleaned up */
+ VIR_JOB_FLAG_LAST = 0x400
+} virJobFlag;
+
+
+typedef int virJobID; /*signed so negitive values can be returned on error*/
+typedef struct _virJobObj virJobObj;
+typedef virJobObj *virJobObjPtr;
+typedef struct _virJobInfo virJobInfo;
+typedef virJobInfo *virJobInfoPtr;
+
+struct _virJobObj {
+ /* this should only be locked when changing the job object, not while running a job
+ it's use is mostly optional, but it is needed for waiting on a job*/
+ virMutex lock;/*should have a compile time option to enable/disable locking */
+ virCond cond; /* Use to coordinate jobs (is this necessary?) */
+ virJobType type; /* The type of the job */
+ unsigned long long owner; /* Thread id which set current job */
+ unsigned long long start; /* when the job started*/
+ int jobsWaiting; /* number jobs waiting on cond */
+ int maxJobsWaiting; /* max number of jobs that can wait on cond */
+ /* information about the job, this is a private struct, access to information
+ about the job should be obtained by functions */
+ virJobInfoPtr info;
+ virJobID id; /* the job id, constant, and unique */
+ virJobFlag flags; /* The current state of the job */
+ void *privateData;
+};
+
+/* Getting information on a currently running job is currently unimplmeneted and
+ any suggestions on what should go into the api for querying/setting job
+ progress information would be appreciated
+*/
+typedef enum {
+ VIR_JOB_INFO_NONE = 0,
+ VIR_JOB_INFO_TIME,
+ VIR_JOB_INFO_MEM,
+ VIR_JOB_INFO_FILE,
+ VIR_JOB_INFO_DATA,
+ VIR_JOB_INFO_LAST
+} virJobInfoType;
+
+struct _virJobInfo {
+ /* these fields are for compatability with existing job
+ information structs.
+ */
+ virDomainBlockJobInfoPtr blockJobInfoPtr;
+ virDomainJobInfoPtr domainJobInfoPtr;
+
+ unsigned long long progressTotal;
+ unsigned long long dataTotal;
+ unsigned long long memTotal;
+ unsigned long long filesTotal;
+ unsigned long long timeTotal;
+
+ unsigned long long progressProcessed;
+ unsigned long long timeProcessed;
+ unsigned long long memProcessed;
+ unsigned long long filesProcessed;
+ unsigned long long dataProcessed;
+
+ unsigned long long progressRemaining;
+ unsigned long long dataRemaining;
+ unsigned long long memRemaining;
+ unsigned long long filesRemaining;
+ unsigned long long timeRemaining;
+};
+
+/**
+ * virJobObjInit:
+ * @job: Pointer to the job object to initialize
+ *
+ * Initialize the job object given, should be called before any other
+ * job function.
+ *
+ * Like all job functions it returns the job id on success and -1 on error
+ */
+int virJobObjInit(virJobObjPtr job);
+/**
+ * virJobObjFree:
+ * @job: Pointer to the job object to free
+ *
+ * Cleanup/free all resources/memory assoicated with job
+ */
+void virJobObjFree(virJobObjPtr job);
+/**
+ * virJobObjCleanup:
+ * @job: Pointer to the job object to cleanup
+ *
+ * Cleanup all resources assoicated with job, and zero out the
+ * corrsponding memory, but do not free it.
+ */
+
+void virJobObjCleanup(virJobObjPtr job);
+/**
+ * virJobObjBegin:
+ * @job: The job to begin
+ * @type: The type of job that is being started
+ *
+ * Marks job as active, sets the calling thread as the owner of the job,
+ * sets the job's start time to the current time and sets it's type to type.
+ *
+ * End job should be called after this, once the job is done
+ *
+ * Returns the job id of job on success, 0 if job is already active
+ * and -1 on error.
+ */
+int virJobObjBegin(virJobObjPtr job,
+ virJobType type);
+/**
+ * virJobObjEnd:
+ *
+ * @job: The job to end
+ *
+ * Ends job, calls virJobObjReset and signals all threads waiting on job.
+ *
+ * Ending a job does not invalidate the job object, and a new job can be
+ * started using the same job object, call virJobObjFree or virJobObjCleanup
+ * in order to destroy a job object.
+ *
+ * returns the job's id on success and -1 if the job was not active.
+ */
+int virJobObjEnd(virJobObjPtr job);
+/**
+ * virJobObjReset:
+ *
+ * @job: The job to reset
+ *
+ * Clears all fields of job related to running a job. This does not
+ * clear the job id, any configurable parameters (currently just the
+ * maximum number of waiting threads), or the mutex/condition variable
+ * assoicated with the job. This is called internally by virJobObjEnd
+ * and there should be few reasons to call this explicitly.
+ */
+int virJobObjReset(virJobObjPtr job);
+/**
+ * virJobObjAbort:
+ * @job: The job to abort
+ *
+ * Marks job as aborted, since jobs are asyncronous this doesn't actually
+ * stop the job. The abort status of a job can be checked by
+ * virJobObjCheckAbort. A suspended job can be aborted.
+ *
+ * returns the job id on success and -1 if
+ * job is not currently running/suspended.
+ */
+int virJobObjAbort(virJobObjPtr job);
+/**
+ * virJobObjAbort:
+ * @job: The job to abort/signal waiters
+ *
+ * Behaves identically to virJobObjAbort except all threads waiting
+ * on job are signaled after the abort status is set.
+ */
+int virJobObjAbortAndSignal(virJobObjPtr job);
+/**
+ * virJobObjSuspend:
+ * @job: The job to suspend
+ *
+ * Marks job as suspended, it is up to the caller of the function
+ * to actually save any state assoicated with the job
+ *
+ * This function returns the job's id on success and -1 if the job
+ * was not active.
+ */
+int virJobObjSuspend(virJobObjPtr job);
+/**
+ * virJobObjResume:
+ * @job The job to resume
+ *
+ * Resume job, as with virJobObjSuspend it is up to the caller to
+ * insure that the work being done by job is actually restarted.
+ *
+ * Since a job can be aborted while it is suspended the caller should
+ * check to see if job has been aborted, a convenience function
+ * virJobObjResumeIfNotAborted is provided.
+ *
+ * returns the job id if job was resumed and -1 if the job was not suspended.
+ */
+int virJobObjResume(virJobObjPtr job);
+
+/**
+ * virJobObjResumeIfNotAborted:
+ * @job The job to resume
+ *
+ * Behaves the same as virJobObjResume except it returns 0 and does not
+ * resume the job if the job was aborted while suspended.
+ */
+int virJobObjResumeIfNotAborted(virJobObjPtr job);
+
+/* returns -3 if max waiters is exceeded, -2 on timeout, -1 on other error*/
+/**
+ * virJobObjWait:
+ * @job: The job to wait on
+ * @lock: The lock to use in the call to virCondWait
+ * @limit: If not 0 the maximum ammount of time to wait (in milliseconds)
+ *
+ * This function waits for job to be completed, or to otherwise signal on it's
+ * condition variable.
+ *
+ * If lock is NULL the internal job lock will be used, otherwise lock should
+ * be held by the calling thread.
+ * (NOTE: I'm not sure if it's a good idea or not to use the internal lock)
+ *
+ * If limit is > 0 virCondWaitUntil is called instead of virCondWait with limit
+ * being used as the time parameter.
+ *
+ * If job is not currently active return successfully.
+ *
+ * Like all job functions returns the job's id on success.
+ *
+ * On Failure returns a negitive number to indicate the cause of failure
+ * -3 indicates the maximum number of threads were alread waiting on job
+ * -2 indicates that virCondWaitUntil timed out
+ * -1 indicates some other error in virCondWait/virCondWaitUntil
+ */
+int virJobObjWait(virJobObjPtr job,
+ virMutexPtr lock,
+ unsigned long long limit);
+/* Should I provide a function to wait for a suspended job to resume? */
+
+/**
+ * virJobObjSignal:
+ * @job: The job to signal from
+ * @all: If true signal all waiting threads, otherwise just signal one
+ *
+ * Signal a thread/threads waiting on job. In most cases waiting threads
+ * are signaled when needed internally, but this is provided if for
+ * some reason waiting threads need to be manually signaled.
+ */
+
+void virJobObjSignal(virJobObjPtr job, bool all);
+
+/* accessor functions*/
+/**
+ * virJobObjCheckAbort:
+ * @job: The job whoes status should be checked
+ *
+ * Returns true if job has been aborted, false otherwise
+ */
+bool virJobObjCheckAbort(virJobObjPtr job);
+/**
+ * virJobObjCheckTime:
+ * @job: The job whoes time should be checked
+ *
+ * Returns the time in milliseconds that job has been running for.
+ * returns 0 if job is not active and -1 if there is an error in
+ * getting the current time.
+ */
+long long virJobObjCheckTime(virJobObjPtr job);
+/**
+ * virJobObjActive:
+ * @job: The job whoes status should be checked
+ *
+ * Returns true if job is currently active, false otherwise
+ */
+bool virJobObjActive(virJobObjPtr job);
+/**
+ * virJobObjSetMaxWaiters:
+ * @job: The job to modify
+ * @max: The maximum number of threads to allow to wait on job at once
+ *
+ * Sets the maximum number of threads that can simultaneously wait on job.
+ * By default there is essentially no limit (in reality the limit is the
+ * maximum value that can be held by an int)
+ */
+void virJobObjSetMaxWaiters(virJobObjPtr job, int max);
+
+/* These convert between a job object and a job id.
+*/
+virJobObjPtr virJobFromID(virJobID id);
+virJobID virJobIDFromJob(virJobObjPtr job);
+#endif
--
2.0.0
10 years, 5 months
[libvirt] [PATCHv3 0/3] lxc keep/drop capabilities
by Cédric Bosdonnat
I found out that the previous versions were not building on older kernels.
Thus n lxc/lxc_container.c I added a bunch of
#ifndef CAP_XXX
#define CAP_XXX -1
#endif
And capabilities are handled later only if they are valid. I'm not sure the
lxc_container.c file is the best place to put those, but at least it's not
far away from the only place these are actually used.
Cédric Bosdonnat (3):
lxc: allow to keep or drop capabilities
lxc domain from xml: convert lxc.cap.drop
lxc: update doc to mention features/capabilities/* domain
configuration
docs/drvlxc.html.in | 47 ++++
docs/schemas/domaincommon.rng | 207 ++++++++++++++++++
src/conf/domain_conf.c | 126 ++++++++++-
src/conf/domain_conf.h | 56 +++++
src/libvirt_private.syms | 3 +
src/lxc/lxc_cgroup.c | 8 +
src/lxc/lxc_container.c | 241 +++++++++++++++++++--
src/lxc/lxc_native.c | 25 +++
src/util/vircgroup.c | 74 ++++++-
src/util/vircgroup.h | 2 +
tests/domainschemadata/domain-caps-features.xml | 28 +++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 2 +
tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml | 2 +
tests/lxcconf2xmldata/lxcconf2xml-cputune.xml | 2 +
tests/lxcconf2xmldata/lxcconf2xml-idmap.xml | 2 +
.../lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml | 4 +
tests/lxcconf2xmldata/lxcconf2xml-memtune.xml | 2 +
tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml | 4 +
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml | 2 +
tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml | 4 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 8 +
tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml | 4 +
22 files changed, 828 insertions(+), 25 deletions(-)
create mode 100644 tests/domainschemadata/domain-caps-features.xml
--
1.8.4.5
10 years, 5 months
[libvirt] [PATCH] libxl: detect support for save and restore
by Jim Fehlig
libxl does not support save, restore, or migrate on all architectures,
notably ARM. Detect whether libxl supports these operations using
LIBXL_HAVE_NO_SUSPEND_RESUME. If not supported, drop advertisement of
<migration_features>.
Found by Ian Campbell while improving Xen's OSSTEST infrastructure
http://lists.xen.org/archives/html/xen-devel/2014-06/msg02171.html
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
Derived from a test patch I sent to Ian Campbell
http://lists.xen.org/archives/html/xen-devel/2014-06/msg03150.html
Includes fixups Ian provided later in the thread.
src/libxl/libxl_conf.c | 4 ++++
src/libxl/libxl_driver.c | 8 ++++++++
2 files changed, 12 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 4b6b5c0..8eeaf82 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -1340,7 +1340,11 @@ libxlMakeCapabilities(libxl_ctx *ctx)
{
virCapsPtr caps;
+#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
+ if ((caps = virCapabilitiesNew(virArchFromHost(), 0, 0)) == NULL)
+#else
if ((caps = virCapabilitiesNew(virArchFromHost(), 1, 1)) == NULL)
+#endif
return NULL;
if (libxlCapsInitHost(ctx, caps) < 0)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 1ea99e2..ac440d2 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -1370,6 +1370,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
return ret;
}
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
static int
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
unsigned int flags)
@@ -1488,6 +1489,7 @@ libxlDomainRestore(virConnectPtr conn, const char *from)
{
return libxlDomainRestoreFlags(conn, from, NULL, 0);
}
+#endif /* ifndef LIBXL_HAVE_NO_SUSPEND_RESUME */
static int
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
@@ -4340,6 +4342,7 @@ libxlNodeDeviceReset(virNodeDevicePtr dev)
return ret;
}
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
static char *
libxlDomainMigrateBegin3Params(virDomainPtr domain,
virTypedParameterPtr params,
@@ -4559,6 +4562,7 @@ libxlDomainMigrateConfirm3Params(virDomainPtr domain,
return libxlDomainMigrationConfirm(driver, vm, flags, cancelled);
}
+#endif /* ifndef LIBXL_HAVE_NO_SUSPEND_RESUME */
static virDriver libxlDriver = {
@@ -4594,10 +4598,12 @@ static virDriver libxlDriver = {
.domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
.domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
.domainGetState = libxlDomainGetState, /* 0.9.2 */
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
.domainSave = libxlDomainSave, /* 0.9.2 */
.domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
.domainRestore = libxlDomainRestore, /* 0.9.2 */
.domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
+#endif
.domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
.domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
.domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
@@ -4650,11 +4656,13 @@ static virDriver libxlDriver = {
.nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
.nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
.nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
.domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.6 */
.domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.6 */
.domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.6 */
.domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.6 */
.domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
+#endif
};
static virStateDriver libxlStateDriver = {
--
1.8.4.5
10 years, 5 months
[libvirt] Issue about do Auto Core Dump with compress file format on FC 20
by zhengqin
Hi,
I'm trying to do Auto Core Dump with compress file format for
dump_image_format (such as: bzip2) on Fedora Core 20, but the generated
dump image format is not "bzip2".
Here are my steps:
1. Prepare a running guest with following configuration in guest's xml
# virsh dumpxml domU
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
...
<on_crash>coredump-destroy</on_crash>
<qemu:commandline>
<qemu:arg value='-device'/>
<qemu:arg value='pvpanic'/>
</qemu:commandline>
</domain>
2. Set following values in /etc/libvirt/qemu.conf
dump_image_format = "bzip2"
auto_dump_path = "/var/lib/libvirt/qemu/dump"
3. Restart libvirtd service
4. Crash the guest os with the following command in guest
#sync
#echo c >/proc/sysrq-trigger
5. Check the core dump file under "/var/lib/libvirt/qemu/dump" with
file command
The output for file command is: (not bzip2 compress format)
#file coreDumpFile
ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style
So, I want to confirm whether compress file format for dump_image_format
is supported by Auto Core Dump?
Thanks.
Zhengqin
10 years, 5 months
[libvirt] [PATCHv3 00/26] Work In Progress: Refactor handling of disk image metadata
by Peter Krempa
In my quest to fix various issues with image chain handling I've set out to
fix labelling of the image files. While I'm not far enough yet, the series has grown
rather large and contains a few fixes of other stuff.
I'm posting it incomplete to star review on the trivial parts.
Peter Krempa (26):
utils:
s/virStorageSourceClearBackingStore/virStorageSourceBackingStoreClear
security: Rename virSecurityManagerRestoreImageLabel to *Disk*
security: manager: Avoid forward decl of virSecurityManagerDispose
security: manager: Unify function header format
security: manager: Document behavior of disk label manipulation funcs
security: Fix header formatting of a few functions
security: nop: Avoid very long lines
storage: Move readonly and shared flags to disk source from disk def
util: storagesource: Add helper to copy and free storage source
seclabels
util: storagefile: Add deep copy for struct virStorageSource
util: cgroup: Add helper to convert device mode to string
qemu: cgroup: Add functions to set cgroup image stuff on individual
imgs
qemu: cgroup: Setup only the top level disk image for read-write
access
locking: Add APIs to lock individual image files
security: Introduce APIs to label single images
security: selinux: Implement per-image seclabel restore
security: selinux: Implement per-image seclabel set
security: DAC: Implement per-image seclabel restore
security: DAC: Implement per-image seclabel set
security: AppArmor: Implement per-image seclabel restore
security: AppArmor: Implement per-image seclabel set
util: storage: Add helper to determine whether storage is local
util: storage: Make virStorageFileChainLookup more network storage
aware
util: storage: Return complete parent info from
virStorageFileChainLookup
qemu: blockcopy: Use the mirror disk source to label the files
qemu: blockcopy: Don't remove existing disk mirror info
src/conf/domain_conf.c | 18 +-
src/conf/domain_conf.h | 2 -
src/libvirt_private.syms | 10 +-
src/libxl/libxl_conf.c | 2 +-
src/locking/domain_lock.c | 65 +++++---
src/locking/domain_lock.h | 8 +
src/lxc/lxc_cgroup.c | 2 +-
src/lxc/lxc_controller.c | 2 +-
src/lxc/lxc_driver.c | 2 +-
src/qemu/qemu_cgroup.c | 110 +++++++------
src/qemu/qemu_cgroup.h | 3 +
src/qemu/qemu_command.c | 14 +-
src/qemu/qemu_conf.c | 4 +-
src/qemu/qemu_domain.c | 2 +-
src/qemu/qemu_driver.c | 65 +++-----
src/qemu/qemu_hotplug.c | 24 +--
src/qemu/qemu_migration.c | 16 +-
src/security/security_apparmor.c | 52 ++++--
src/security/security_dac.c | 115 ++++++-------
src/security/security_driver.h | 22 ++-
src/security/security_manager.c | 347 +++++++++++++++++++++++++++------------
src/security/security_manager.h | 22 ++-
src/security/security_nop.c | 166 ++++++++++++-------
src/security/security_selinux.c | 154 +++++++++--------
src/security/security_stack.c | 50 +++++-
src/security/virt-aa-helper.c | 2 +-
src/util/vircgroup.c | 62 +++++--
src/util/vircgroup.h | 2 +
src/util/virstoragefile.c | 239 +++++++++++++++++++++++----
src/util/virstoragefile.h | 17 +-
src/vbox/vbox_tmpl.c | 30 ++--
src/xenxs/xen_sxpr.c | 10 +-
src/xenxs/xen_xm.c | 10 +-
tests/virstoragetest.c | 86 +++++-----
34 files changed, 1140 insertions(+), 595 deletions(-)
--
1.9.3
10 years, 5 months
[libvirt] RFC: network interface "tags" vs. portgroups
by Laine Stump
A couple releases ago (commit 7d5bf484, first appeared in 1.2.2) I
modified the domain interface status xml to show what resources are
actually in use for an interface, superseding the interface config in
the cases where they conflict with each other.
In particular, if there is an interface of type='network' that
references a portgroup of the network in the <source> element, the
interface status will not contain a <source> element showing the network
and portgroup names, but instead the <source resulting from applying the
config is shown. For example, given the following domain interface and
network definitions:
<interface type='network'>
<source network='mynet' portgroup='xyzzy'/>
...
</interface>
<network>
<name>mynet</name>
<forward mode='bridge'/>\
<bridge name='br0'/>
<portgroup name='xyzzy'>
<bandwidth>
<inbound average='1000' peak='5000' floor='200' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
</portgroup>
</network>
the status that was previously displayed when the domain was running
would be identical to the config above (except that it would also
contain the tap device name and alias). But now the status will be this:
<interface type='bridge'>
<source bridge='br0'/>
<bandwidth>
<inbound average='1000' peak='5000' floor='200' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
...
</interface>
The advantage here is that a hook script for the domain will be able to
see the bandwidth (and vlan and physical device, if any) that are
actually being used by the domain's interface. Because the config and
status both use the same elements/attributes, we can only show one or
the other; the thinking was that normally the status will be what is
desired, and anyone who really wants to look at the config should use
the VIR_DOMAIN_XML_INACTIVE flag when calling virDomainGetXMLDesc().
As you would expect, a few months later (after the release of 1.2.4)
someone on IRC checked in with a problem caused by this change - they
had been using the portgroup name in the <source> element of the
interface to determine what action to take during migration; they didn't
even have any libvirt config stored in the portgroup, but were just
using its name as a tag. Since the portgroup name is only a part of the
<source> element when the interface is type='network', they now don't
have a tag in the xml to use for their decision (and since they aren't
explicitly calling virDomainGetXMLDesc() themselves, they can't simply
get the INACTIVE xml to solve their problem).
This use of a portgroup name struck me as potentially useful (although
it is a slight hijacking of the original intent of portgroups), so I
would like to restore that functionality. I came up with a couple
different ways to solve the problem, and am looking for opinions before
I spend any time on either.
Solution 1:
My initial thought was to just restore the portgroup name in the status
XML; that could be done by moving the portgroup name out of the
network-specific part of the object and into common data for all
interface types (this way it could show up in the <source> element no
matter what is the network type). However, once we've done that it
becomes enticing to allow specification of a portgroup even in cases
where the interface type != network; in those cases though, the
portgroup would be *only* a tag to be used by external entities; this
would lead to lax checking for existence of the specified portgroup, and
may end up with people misspelling a portgroup name, then mistakenly
believing that (e.g.) they had a bandwidth limit applied to a domain
interface when none was in fact in effect. (alternately, we could allow
it only if the interface *config* was for type='network', but that seems
somehow logically broken, and you can bet that eventually someone would
ask for us to allow it for all types)
Solution 2:
An alternate idea I had was to add a new <tag name='x'/> element to
interfaces, networks, and portgroups. An interface could have multiple
tags, and would assume the tags of its <network> when active. A <tag>
would be purely for use by external entities - it would mean nothing to
libvirt. For example, given this extreme example:
<interface type='network'>
<source network='mynet' portgroup='xyzzy'/>
<tag name='wumpus'/>
...
</interface>
<network>
<name>mynet</name>
<tag name='twisty'/>
<forward mode='bridge'/>\
<bridge name='br0'/>
<portgroup name='xyzzy'>
<tag name='xyzzytag'/>
<bandwidth>
<inbound average='1000' peak='5000' floor='200' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
</portgroup>
</network>
<network>
when the interface was active, its status xml would look like this:
<interface type='bridge'>
<tag name='wumpus'/>
<tag name='twisty'/>
<tag name='xyzzytag'/>
<source bridge='br0'/>
<bandwidth>
<inbound average='1000' peak='5000' floor='200' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
...
</interface>
These tags would mean nothing to libvirt, but would be available for
management applications to make decisions during domain
start/stop/migration/etc.
The advantages of solution 1 are that it is simpler, wouldn't require
any new XML elements, and any existing code using the portgroup name in
this manner would once again work (I don't know if anyone else uses it
this way).
The advantages of solution 2 are that it doesn't try to make a single
element work for two different functions which may not always mesh with
each other, and it allows for more than one tag per interface, so
different parts of a management application may use the tag element
without fear of breaking some other use. It may be a case of
over-engineering though :-)
So which should I do?
10 years, 5 months
[libvirt] Fix a typo in a localized string
by Daniel Veillard
As pointed by Yuri Chornoivan in transifex:
https://fedora.transifex.com/projects/p/libvirt/translate/#uk/strings/270...
pushed as trivial since same string is used before and after that broken
one,
Daniel
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 4ba9ad7..b27ab02 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -7279,7 +7279,7 @@ int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
rc = imediumattach->vtbl->GetPort(imediumattach, &devicePort);
if (NS_FAILED(rc)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachchment type"));
+ _("cannot get medium attachment type"));
goto cleanup;
}
rc = imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot);
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
10 years, 5 months
[libvirt] [PATCH] build: link virstoragetest with libxml
by Martin Kletzander
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
Notes:
To be honest, I have no idea why this fails for me in one situation,
but it prevents the following error during compilation:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/../../../../x86_64-pc-linux-gnu/bin/ld: ../src/.libs/libvirt_driver_storage_impl.a(libvirt_driver_storage_impl_la-storage_backend.o): undefined reference to symbol 'xmlFreeDoc@(a)LIBXML2_2.4.30'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/../../../../lib64/libxml2.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Makefile:4228: recipe for target 'virstoragetest' failed
Therefore I'm not pushing it as a build-breaker since this might not
be the root cause or the best solution.
The other fix (and probably more appropriate one) would be to add
LIBXML_LIBS into libvirt_conf_la_LIBADD since the xmlFreeDoc() is
called in storage_conf.c.
Any other preferred way is accepted as well, feel free to comment.
tests/Makefile.am | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 025b847..457eb99 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -899,6 +899,7 @@ virstoragetest_LDADD = $(LDADDS) \
../src/libvirt_util.la \
../src/libvirt_driver_storage_impl.la \
../gnulib/lib/libgnu.la \
+ $(LIBXML_LIBS) \
$(NULL)
viridentitytest_SOURCES = \
--
2.0.0
10 years, 5 months
[libvirt] [PATCH 0/6] Support for per-guest-node binding
by Martin Kletzander
Currently we are only able to bind the whole domain to some host nodes
using the /domain/numatune/memory element. Numerous requests were
made to support host<->guest numa node bindings, so this series tries
to pinch an idea on how to do that using /domain/numatune/memnode
elements.
That is incompatible with automatic numa placement (numad) since that
makes no sense. Also this disables any live changes to numa
parameters (the /domain/numatune/memory settings) since we cannot
change the settings given to qemu.
Martin Kletzander (6):
conf, schema: add 'id' field for cells
conf, schema: add support for numatune memnode element
conf: add virDomainGetMemsForGuestCpu()
qemu: purely a code movement
qemu: memory-ram capability probing
qemu: pass numa node binding preferences to qemu
docs/formatdomain.html.in | 26 ++-
docs/schemas/domaincommon.rng | 22 ++
src/conf/cpu_conf.c | 39 +++-
src/conf/domain_conf.c | 259 ++++++++++++++++++---
src/conf/domain_conf.h | 4 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_cgroup.c | 18 +-
src/qemu/qemu_command.c | 160 +++++++++++--
src/qemu/qemu_command.h | 3 +-
src/qemu/qemu_domain.c | 23 +-
src/qemu/qemu_driver.c | 23 +-
src/qemu/qemu_process.c | 3 +-
src/util/virnuma.h | 14 +-
tests/qemuxml2argvdata/qemuxml2argv-cpu-numa1.xml | 6 +-
tests/qemuxml2argvdata/qemuxml2argv-cpu-numa2.xml | 6 +-
tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml | 25 ++
.../qemuxml2argv-numatune-auto-prefer.xml | 29 +++
.../qemuxml2argv-numatune-auto.args | 6 +
.../qemuxml2argv-numatune-auto.xml | 26 +++
.../qemuxml2argv-numatune-memnode-nocpu.xml | 25 ++
.../qemuxml2argv-numatune-memnodes-problematic.xml | 31 +++
.../qemuxml2argv-numatune-memnodes.args | 8 +
.../qemuxml2argv-numatune-memnodes.xml | 31 +++
.../qemuxml2argv-numatune-prefer.args | 6 +
.../qemuxml2argv-numatune-prefer.xml | 29 +++
tests/qemuxml2argvtest.c | 51 ++--
.../qemuxml2xmlout-cpu-numa1.xml | 28 +++
.../qemuxml2xmlout-cpu-numa2.xml | 28 +++
tests/qemuxml2xmltest.c | 4 +
tests/qemuxmlnstest.c | 2 +-
32 files changed, 845 insertions(+), 94 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-numa3.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-prefer.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode-nocpu.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnodes-problematic.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnodes.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-memnodes.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-prefer.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-prefer.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa1.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-cpu-numa2.xml
--
2.0.0
10 years, 5 months