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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list