Add the functions to add/remove elements from the hashed secret obj list.
These will replace secret_driver functions secretAssignDef and secretObjRemove.
The virSecretObjListAddLocked will perform the necessary lookups and
decide whether to replace an existing hash entry or create a new one.
This includes setting up the configPath and base64Path as well as being
able to support the caller's need to restore from a previous definition
in case something goes wrong in the caller.
Need to also move and make global virSecretUsageIDForDef since it'll
be used by both secret_driver.c and secret_conf.c
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/conf/secret_conf.c | 173 +++++++++++++++++++++++++++++++++++++++++++++
src/conf/secret_conf.h | 15 ++++
src/libvirt_private.syms | 1 +
src/secret/secret_driver.c | 34 ++-------
4 files changed, 196 insertions(+), 27 deletions(-)
diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c
index d082ad8..d45910f 100644
--- a/src/conf/secret_conf.c
+++ b/src/conf/secret_conf.c
@@ -32,6 +32,7 @@
#include "virxml.h"
#include "viruuid.h"
#include "virhash.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_SECRET
@@ -296,6 +297,178 @@ virSecretObjListFindByUsage(virSecretObjListPtr secrets,
}
+const char *
+virSecretUsageIDForDef(virSecretDefPtr def)
+{
+ switch (def->usage_type) {
+ case VIR_SECRET_USAGE_TYPE_NONE:
+ return "";
+
+ case VIR_SECRET_USAGE_TYPE_VOLUME:
+ return def->usage.volume;
+
+ case VIR_SECRET_USAGE_TYPE_CEPH:
+ return def->usage.ceph;
+
+ case VIR_SECRET_USAGE_TYPE_ISCSI:
+ return def->usage.target;
+
+ default:
+ return NULL;
+ }
+}
+
+
+/*
+ * virSecretObjListRemove:
+ * @secrets: list of secret objects
+ * @secret: a secret object
+ *
+ * Remove the object from the hash table. The caller must hold the lock
+ * on the driver owning @secrets and must have also locked @secret to
+ * ensure no one else is either waiting for @secret or still using it.
+ */
+void
+virSecretObjListRemove(virSecretObjListPtr secrets,
+ virSecretObjPtr secret)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(secret->def->uuid, uuidstr);
+ virObjectRef(secret);
+ virObjectUnlock(secret);
+
+ virObjectLock(secrets);
+ virObjectLock(secret);
+ virHashRemoveEntry(secrets->objs, uuidstr);
+ virObjectUnlock(secret);
+ virObjectUnref(secret);
+ virObjectUnlock(secrets);
+}
+
+
+/*
+ * virSecretObjListAddLocked:
+ * @secrets: list of secret objects
+ * @def: new secret definition
+ * @configDir: directory to place secret config files
+ * @oldDef: Former secret def (e.g. a reload path perhaps)
+ *
+ * Add the new def to the secret obj table hash
+ *
+ * This functions requires @secrets to be locked already!
+ *
+ * Returns pointer to secret or NULL if failure to add
+ */
+virSecretObjPtr
+virSecretObjListAddLocked(virSecretObjListPtr secrets,
+ virSecretDefPtr def,
+ const char *configDir,
+ virSecretDefPtr *oldDef)
+{
+ virSecretObjPtr secret;
+ virSecretObjPtr ret = NULL;
+ const char *newUsageID = virSecretUsageIDForDef(def);
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *configFile = NULL, *base64File = NULL;
+
+ if (oldDef)
+ *oldDef = NULL;
+
+ /* Is there a secret already matching this UUID */
+ if ((secret = virSecretObjListFindByUUIDLocked(secrets, def->uuid))) {
+ const char *oldUsageID;
+
+ virObjectLock(secret);
+
+ oldUsageID = virSecretUsageIDForDef(secret->def);
+ if (STRNEQ(oldUsageID, newUsageID)) {
+ virUUIDFormat(secret->def->uuid, uuidstr);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("a secret with UUID %s is already defined for "
+ "use with %s"),
+ uuidstr, oldUsageID);
+ goto cleanup;
+ }
+
+ if (secret->def->private && !def->private) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot change private flag on existing
secret"));
+ goto cleanup;
+ }
+
+ if (oldDef)
+ *oldDef = secret->def;
+ else
+ virSecretDefFree(secret->def);
+ secret->def = def;
+ } else {
+ /* No existing secret with same UUID,
+ * try look for matching usage instead */
+ if ((secret = virSecretObjListFindByUsageLocked(secrets,
+ def->usage_type,
+ newUsageID))) {
+ virObjectLock(secret);
+ virUUIDFormat(secret->def->uuid, uuidstr);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("a secret with UUID %s already defined for "
+ "use with %s"),
+ uuidstr, newUsageID);
+ goto cleanup;
+ }
+
+ /* Generate the possible configFile and base64File strings
+ * using the configDir, uuidstr, and appropriate suffix
+ */
+ virUUIDFormat(def->uuid, uuidstr);
+ if (!(configFile = virFileBuildPath(configDir, uuidstr, ".xml")) ||
+ !(base64File = virFileBuildPath(configDir, uuidstr, ".base64"))) {
+ VIR_FREE(configFile);
+ goto cleanup;
+ }
+
+ if (!(secret = virSecretObjNew()))
+ goto cleanup;
+
+ virObjectLock(secret);
+
+ if (virHashAddEntry(secrets->objs, uuidstr, secret) < 0)
+ goto cleanup;
+
+ secret->def = def;
+ secret->configFile = configFile;
+ secret->base64File = base64File;
+ configFile = NULL;
+ base64File = NULL;
+ virObjectRef(secret);
+ }
+
+ ret = secret;
+ secret = NULL;
+
+ cleanup:
+ virSecretObjEndAPI(&secret);
+ VIR_FREE(configFile);
+ VIR_FREE(base64File);
+ return ret;
+}
+
+
+virSecretObjPtr
+virSecretObjListAdd(virSecretObjListPtr secrets,
+ virSecretDefPtr def,
+ const char *configDir,
+ virSecretDefPtr *oldDef)
+{
+ virSecretObjPtr ret;
+
+ virObjectLock(secrets);
+ ret = virSecretObjListAddLocked(secrets, def, configDir, oldDef);
+ virObjectUnlock(secrets);
+ return ret;
+}
+
+
void
virSecretDefFree(virSecretDefPtr def)
{
diff --git a/src/conf/secret_conf.h b/src/conf/secret_conf.h
index 53e03fe..7e0651d 100644
--- a/src/conf/secret_conf.h
+++ b/src/conf/secret_conf.h
@@ -77,6 +77,21 @@ virSecretObjPtr virSecretObjListFindByUsage(virSecretObjListPtr
secrets,
int usageType,
const char *usageID);
+const char *virSecretUsageIDForDef(virSecretDefPtr def);
+
+void virSecretObjListRemove(virSecretObjListPtr secrets,
+ virSecretObjPtr secret);
+
+virSecretObjPtr virSecretObjListAddLocked(virSecretObjListPtr secrets,
+ virSecretDefPtr def,
+ const char *configDir,
+ virSecretDefPtr *oldDef);
+
+virSecretObjPtr virSecretObjListAdd(virSecretObjListPtr secrets,
+ virSecretDefPtr def,
+ const char *configDir,
+ virSecretDefPtr *oldDef);
+
void virSecretDefFree(virSecretDefPtr def);
virSecretDefPtr virSecretDefParseString(const char *xml);
virSecretDefPtr virSecretDefParseFile(const char *filename);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5251dc0..3810604 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -785,6 +785,7 @@ virSecretDefFormat;
virSecretDefFree;
virSecretDefParseFile;
virSecretDefParseString;
+virSecretUsageIDForDef;
virSecretUsageTypeFromString;
virSecretUsageTypeToString;
diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index 8c1f79a..9d92619 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -566,26 +566,6 @@ secretConnectListSecrets(virConnectPtr conn,
return -1;
}
-static const char *
-secretUsageIDForDef(virSecretDefPtr def)
-{
- switch (def->usage_type) {
- case VIR_SECRET_USAGE_TYPE_NONE:
- return "";
-
- case VIR_SECRET_USAGE_TYPE_VOLUME:
- return def->usage.volume;
-
- case VIR_SECRET_USAGE_TYPE_CEPH:
- return def->usage.ceph;
-
- case VIR_SECRET_USAGE_TYPE_ISCSI:
- return def->usage.target;
-
- default:
- return NULL;
- }
-}
#define MATCH(FLAG) (flags & (FLAG))
static int
@@ -639,7 +619,7 @@ secretConnectListAllSecrets(virConnectPtr conn,
virGetSecret(conn,
secret->def->uuid,
secret->def->usage_type,
- secretUsageIDForDef(secret->def))))
+ virSecretUsageIDForDef(secret->def))))
goto cleanup;
}
ret_nsecrets++;
@@ -690,7 +670,7 @@ secretLookupByUUID(virConnectPtr conn,
ret = virGetSecret(conn,
secret->def->uuid,
secret->def->usage_type,
- secretUsageIDForDef(secret->def));
+ virSecretUsageIDForDef(secret->def));
cleanup:
secretDriverUnlock();
@@ -720,7 +700,7 @@ secretLookupByUsage(virConnectPtr conn,
ret = virGetSecret(conn,
secret->def->uuid,
secret->def->usage_type,
- secretUsageIDForDef(secret->def));
+ virSecretUsageIDForDef(secret->def));
cleanup:
secretDriverUnlock();
@@ -751,7 +731,7 @@ secretDefineXML(virConnectPtr conn,
if (!(secret = secretFindByUUID(new_attrs->uuid))) {
/* No existing secret with same UUID,
* try look for matching usage instead */
- const char *usageID = secretUsageIDForDef(new_attrs);
+ const char *usageID = virSecretUsageIDForDef(new_attrs);
char uuidstr[VIR_UUID_STRING_BUFLEN];
if ((secret = secretFindByUsage(new_attrs->usage_type, usageID))) {
@@ -784,8 +764,8 @@ secretDefineXML(virConnectPtr conn,
goto cleanup;
}
} else {
- const char *newUsageID = secretUsageIDForDef(new_attrs);
- const char *oldUsageID = secretUsageIDForDef(secret->def);
+ const char *newUsageID = virSecretUsageIDForDef(new_attrs);
+ const char *oldUsageID = virSecretUsageIDForDef(secret->def);
if (STRNEQ(oldUsageID, newUsageID)) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(secret->def->uuid, uuidstr);
@@ -830,7 +810,7 @@ secretDefineXML(virConnectPtr conn,
ret = virGetSecret(conn,
secret->def->uuid,
secret->def->usage_type,
- secretUsageIDForDef(secret->def));
+ virSecretUsageIDForDef(secret->def));
goto cleanup;
restore_backup:
--
2.5.0