libvirt/src/datatypes.c

1650 lines
46 KiB
C
Raw Normal View History

/*
* datatypes.h: management of structs for public data types
*
build: consistently use C99 varargs macros Prior to this patch, there was an inconsistent mix between GNU and C99. For consistency, and potential portability to other compilers, stick with the C99 vararg macro syntax. * src/conf/cpu_conf.c (virCPUReportError): Use C99 rather than GNU vararg macro syntax. * src/conf/domain_conf.c (virDomainReportError): Likewise. * src/conf/domain_event.c (eventReportError): Likewise. * src/conf/interface_conf.c (virInterfaceReportError): Likewise. * src/conf/network_conf.c (virNetworkReportError): Likewise. * src/conf/node_device_conf.h (virNodeDeviceReportError): Likewise. * src/conf/secret_conf.h (virSecretReportError): Likewise. * src/conf/storage_conf.h (virStorageReportError): Likewise. * src/esx/esx_device_monitor.c (ESX_ERROR): Use C99 rather than GNU vararg macro syntax. * src/esx/esx_driver.c (ESX_ERROR): Likewise. * src/esx/esx_interface_driver.c (ESX_ERROR): Likewise. * src/esx/esx_network_driver.c (ESX_ERROR): Likewise. * src/esx/esx_secret_driver.c (ESX_ERROR): Likewise. * src/esx/esx_storage_driver.c (ESX_ERROR): Likewise. * src/esx/esx_util.c (ESX_ERROR): Likewise. * src/esx/esx_vi.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vi_methods.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vi_types.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vmx.c (ESX_ERROR): Likewise. * src/util/hostusb.c (usbReportError): Use C99 rather than GNU vararg macro syntax. * src/util/json.c (virJSONError): Likewise. * src/util/macvtap.c (ReportError): Likewise. * src/util/pci.c (pciReportError): Likewise. * src/util/stats_linux.c (virStatsError): Likewise. * src/util/util.c (virUtilError): Likewise. * src/util/xml.c (virXMLError): Likewise. * src/xen/proxy_internal.c (virProxyError): Use C99 rather than GNU vararg macro syntax. * src/xen/sexpr.c (virSexprError): Likewise. * src/xen/xen_driver.c (xenUnifiedError): Likewise. * src/xen/xen_hypervisor.c (virXenError): Likewise. * src/xen/xen_inotify.c (virXenInotifyError): Likewise. * src/xen/xend_internal.c (virXendError): Likewise. * src/xen/xm_internal.c (xenXMError): Likewise. * src/xen/xs_internal.c (virXenStoreError): Likewise. * src/cpu/cpu.h (virCPUReportError): Use C99 rather than GNU vararg macro syntax. * src/datatypes.c (virLibConnError): Likewise. * src/interface/netcf_driver.c (interfaceReportError): Likewise. * src/libvirt.c (virLibStreamError): Likewise. * src/lxc/lxc_conf.h (lxcError): Likewise. * src/network/bridge_driver.c (networkReportError): Likewise. * src/nodeinfo.c (nodeReportError): Likewise. * src/opennebula/one_conf.h (oneError): Likewise. * src/openvz/openvz_conf.h (openvzError): Likewise. * src/phyp/phyp_driver.c (PHYP_ERROR): Likewise. * src/qemu/qemu_conf.h (qemuReportError): Likewise. * src/remote/remote_driver.c (errorf): Likewise. * src/security/security_driver.h (virSecurityReportError): Likewise. * src/test/test_driver.c (testError): Likewise. * src/uml/uml_conf.h (umlReportError): Likewise. * src/vbox/vbox_driver.c (vboxError): Likewise. * src/vbox/vbox_tmpl.c (vboxError): Likewise.
2010-03-01 23:38:28 +00:00
* Copyright (C) 2006-2010 Red Hat, Inc.
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <unistd.h>
#include "datatypes.h"
#include "virterror_internal.h"
#include "logging.h"
#include "memory.h"
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
#include "uuid.h"
#include "util.h"
#define VIR_FROM_THIS VIR_FROM_NONE
#define virLibConnError(code, ...) \
virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \
build: consistently use C99 varargs macros Prior to this patch, there was an inconsistent mix between GNU and C99. For consistency, and potential portability to other compilers, stick with the C99 vararg macro syntax. * src/conf/cpu_conf.c (virCPUReportError): Use C99 rather than GNU vararg macro syntax. * src/conf/domain_conf.c (virDomainReportError): Likewise. * src/conf/domain_event.c (eventReportError): Likewise. * src/conf/interface_conf.c (virInterfaceReportError): Likewise. * src/conf/network_conf.c (virNetworkReportError): Likewise. * src/conf/node_device_conf.h (virNodeDeviceReportError): Likewise. * src/conf/secret_conf.h (virSecretReportError): Likewise. * src/conf/storage_conf.h (virStorageReportError): Likewise. * src/esx/esx_device_monitor.c (ESX_ERROR): Use C99 rather than GNU vararg macro syntax. * src/esx/esx_driver.c (ESX_ERROR): Likewise. * src/esx/esx_interface_driver.c (ESX_ERROR): Likewise. * src/esx/esx_network_driver.c (ESX_ERROR): Likewise. * src/esx/esx_secret_driver.c (ESX_ERROR): Likewise. * src/esx/esx_storage_driver.c (ESX_ERROR): Likewise. * src/esx/esx_util.c (ESX_ERROR): Likewise. * src/esx/esx_vi.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vi_methods.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vi_types.c (ESX_VI_ERROR): Likewise. * src/esx/esx_vmx.c (ESX_ERROR): Likewise. * src/util/hostusb.c (usbReportError): Use C99 rather than GNU vararg macro syntax. * src/util/json.c (virJSONError): Likewise. * src/util/macvtap.c (ReportError): Likewise. * src/util/pci.c (pciReportError): Likewise. * src/util/stats_linux.c (virStatsError): Likewise. * src/util/util.c (virUtilError): Likewise. * src/util/xml.c (virXMLError): Likewise. * src/xen/proxy_internal.c (virProxyError): Use C99 rather than GNU vararg macro syntax. * src/xen/sexpr.c (virSexprError): Likewise. * src/xen/xen_driver.c (xenUnifiedError): Likewise. * src/xen/xen_hypervisor.c (virXenError): Likewise. * src/xen/xen_inotify.c (virXenInotifyError): Likewise. * src/xen/xend_internal.c (virXendError): Likewise. * src/xen/xm_internal.c (xenXMError): Likewise. * src/xen/xs_internal.c (virXenStoreError): Likewise. * src/cpu/cpu.h (virCPUReportError): Use C99 rather than GNU vararg macro syntax. * src/datatypes.c (virLibConnError): Likewise. * src/interface/netcf_driver.c (interfaceReportError): Likewise. * src/libvirt.c (virLibStreamError): Likewise. * src/lxc/lxc_conf.h (lxcError): Likewise. * src/network/bridge_driver.c (networkReportError): Likewise. * src/nodeinfo.c (nodeReportError): Likewise. * src/opennebula/one_conf.h (oneError): Likewise. * src/openvz/openvz_conf.h (openvzError): Likewise. * src/phyp/phyp_driver.c (PHYP_ERROR): Likewise. * src/qemu/qemu_conf.h (qemuReportError): Likewise. * src/remote/remote_driver.c (errorf): Likewise. * src/security/security_driver.h (virSecurityReportError): Likewise. * src/test/test_driver.c (testError): Likewise. * src/uml/uml_conf.h (umlReportError): Likewise. * src/vbox/vbox_driver.c (vboxError): Likewise. * src/vbox/vbox_tmpl.c (vboxError): Likewise.
2010-03-01 23:38:28 +00:00
__FUNCTION__, __LINE__, __VA_ARGS__)
2009-04-01 10:31:01 +00:00
/************************************************************************
* *
* Domain and Connections allocations *
* *
************************************************************************/
/**
* virDomainFreeName:
* @domain: a domain object
*
* Destroy the domain object, this is just used by the domain hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefDomain(domain));
}
/**
* virNetworkFreeName:
* @network: a network object
*
* Destroy the network object, this is just used by the network hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefNetwork(network));
}
/**
* virInterfaceFreeName:
2009-10-26 23:02:46 +00:00
* @interface: an interface object
*
* Destroy the interface object, this is just used by the interface hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virInterfaceFreeName(virInterfacePtr iface, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefInterface(iface));
}
/**
* virStoragePoolFreeName:
* @pool: a pool object
*
* Destroy the pool object, this is just used by the pool hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virStoragePoolFreeName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefStoragePool(pool));
}
/**
* virStorageVolFreeName:
* @vol: a vol object
*
* Destroy the vol object, this is just used by the vol hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefStorageVol(vol));
}
/**
* virSecretFreeName:
* @secret_: a secret object
*
* Destroy the secret object, this is just used by the secret hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static void
virSecretFreeName(void *secret_, const char *name ATTRIBUTE_UNUSED)
{
virSecretPtr secret;
secret = secret_;
virUnrefSecret(secret);
}
/**
* virNWFilterPoolFreeName:
* @pool: a nwfilter pool object
*
* Destroy the nwfilter pool object, this is just used by the nwfilter pool hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virNWFilterPoolFreeName(virNWFilterPtr pool, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefNWFilter(pool));
}
/**
* virDomainSnapshotFreeName:
* @snapshot: a domain snapshotobject
*
* Destroy the domain snapshot object, this is just used by the domain hash callback.
*
* Returns 0 in case of success and -1 in case of failure.
*/
static int
virDomainSnapshotFreeName(virDomainSnapshotPtr snapshot, const char *name ATTRIBUTE_UNUSED)
{
return (virUnrefDomainSnapshot(snapshot));
}
/**
* virGetConnect:
*
* Allocates a new hypervisor connection structure
*
* Returns a new pointer or NULL in case of error.
*/
virConnectPtr
virGetConnect(void) {
virConnectPtr ret;
if (VIR_ALLOC(ret) < 0) {
virReportOOMError();
goto failed;
}
2009-01-15 19:56:05 +00:00
if (virMutexInit(&ret->lock) < 0) {
VIR_FREE(ret);
goto failed;
}
ret->magic = VIR_CONNECT_MAGIC;
ret->driver = NULL;
ret->networkDriver = NULL;
ret->privateData = NULL;
ret->networkPrivateData = NULL;
ret->interfacePrivateData = NULL;
ret->domains = virHashCreate(20);
if (ret->domains == NULL)
goto failed;
ret->networks = virHashCreate(20);
if (ret->networks == NULL)
goto failed;
ret->interfaces = virHashCreate(20);
if (ret->interfaces == NULL)
goto failed;
ret->storagePools = virHashCreate(20);
if (ret->storagePools == NULL)
goto failed;
ret->storageVols = virHashCreate(20);
if (ret->storageVols == NULL)
goto failed;
ret->nodeDevices = virHashCreate(256);
if (ret->nodeDevices == NULL)
goto failed;
ret->secrets = virHashCreate(20);
if (ret->secrets == NULL)
goto failed;
ret->nwfilterPools = virHashCreate(20);
if (ret->nwfilterPools == NULL)
goto failed;
ret->refs = 1;
return(ret);
failed:
if (ret != NULL) {
if (ret->domains != NULL)
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
if (ret->networks != NULL)
virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
if (ret->interfaces != NULL)
virHashFree(ret->interfaces, (virHashDeallocator) virInterfaceFreeName);
if (ret->storagePools != NULL)
virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName);
if (ret->storageVols != NULL)
virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
if (ret->nodeDevices != NULL)
virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
if (ret->secrets != NULL)
virHashFree(ret->secrets, virSecretFreeName);
if (ret->nwfilterPools != NULL)
virHashFree(ret->nwfilterPools, (virHashDeallocator) virNWFilterPoolFreeName);
2009-01-15 19:56:05 +00:00
virMutexDestroy(&ret->lock);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseConnect:
* @conn: the hypervisor connection to release
*
* Unconditionally release all memory associated with a connection.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The connection obj must not
* be used once this method returns.
*/
static void
virReleaseConnect(virConnectPtr conn) {
DEBUG("release connection %p", conn);
if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
if (conn->networks != NULL)
virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
if (conn->interfaces != NULL)
virHashFree(conn->interfaces, (virHashDeallocator) virInterfaceFreeName);
if (conn->storagePools != NULL)
virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName);
if (conn->storageVols != NULL)
virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName);
if (conn->nodeDevices != NULL)
virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
if (conn->secrets != NULL)
virHashFree(conn->secrets, virSecretFreeName);
if (conn->nwfilterPools != NULL)
virHashFree(conn->nwfilterPools, (virHashDeallocator) virNWFilterPoolFreeName);
virResetError(&conn->err);
xmlFreeURI(conn->uri);
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
virMutexDestroy(&conn->lock);
VIR_FREE(conn);
}
/**
* virUnrefConnect:
* @conn: the hypervisor connection to unreference
*
* Unreference the connection. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefConnect(virConnectPtr conn) {
int refs;
if ((!VIR_IS_CONNECT(conn))) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
refs = conn->refs;
if (refs == 0) {
/* make sure to release the connection lock before we call the
* close() callbacks, otherwise we will deadlock if an error
* is raised by any of the callbacks
*/
virMutexUnlock(&conn->lock);
if (conn->networkDriver)
conn->networkDriver->close (conn);
if (conn->interfaceDriver)
conn->interfaceDriver->close (conn);
if (conn->storageDriver)
conn->storageDriver->close (conn);
if (conn->deviceMonitor)
conn->deviceMonitor->close (conn);
if (conn->secretDriver)
conn->secretDriver->close (conn);
if (conn->nwfilterDriver)
conn->nwfilterDriver->close (conn);
if (conn->driver)
conn->driver->close (conn);
/* reacquire the connection lock since virReleaseConnect expects
* it to already be held
*/
virMutexLock(&conn->lock);
virReleaseConnect(conn);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return (refs);
}
/**
* virGetDomain:
* @conn: the hypervisor connection
* @name: pointer to the domain name
* @uuid: pointer to the uuid
*
* Lookup if the domain is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virUnrefDomain() is needed to not leak data.
*
* Returns a pointer to the domain, or NULL in case of failure
*/
virDomainPtr
2008-11-17 11:03:25 +00:00
virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virDomainPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
/* TODO search by UUID first as they are better differentiators */
ret = (virDomainPtr) virHashLookup(conn->domains, name);
/* TODO check the UUID */
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_DOMAIN_MAGIC;
ret->conn = conn;
ret->id = -1;
if (uuid != NULL)
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
ret->snapshots = virHashCreate(20);
if (virHashAddEntry(conn->domains, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add domain to connection hash table"));
goto error;
}
conn->refs++;
DEBUG("New hash entry %p", ret);
} else {
DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1);
}
ret->refs++;
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseDomain:
* @domain: the domain to release
*
* Unconditionally release all memory associated with a domain.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The domain obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseDomain(virDomainPtr domain) {
virConnectPtr conn = domain->conn;
DEBUG("release domain %p %s", domain, domain->name);
/* TODO search by UUID first as they are better differentiators */
if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain missing from connection hash table"));
conn = NULL;
}
domain->magic = -1;
domain->id = -1;
VIR_FREE(domain->name);
if (domain->snapshots != NULL)
virHashFree(domain->snapshots, (virHashDeallocator) virDomainSnapshotFreeName);
VIR_FREE(domain);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefDomain:
* @domain: the domain to unreference
*
* Unreference the domain. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefDomain(virDomainPtr domain) {
int refs;
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&domain->conn->lock);
DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs);
domain->refs--;
refs = domain->refs;
if (refs == 0) {
virReleaseDomain(domain);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&domain->conn->lock);
return (refs);
}
/**
* virGetNetwork:
* @conn: the hypervisor connection
* @name: pointer to the network name
* @uuid: pointer to the uuid
*
* Lookup if the network is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virUnrefNetwork() is needed to not leak data.
*
* Returns a pointer to the network, or NULL in case of failure
*/
virNetworkPtr
2008-11-17 11:03:25 +00:00
virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virNetworkPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
/* TODO search by UUID first as they are better differentiators */
ret = (virNetworkPtr) virHashLookup(conn->networks, name);
/* TODO check the UUID */
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_NETWORK_MAGIC;
ret->conn = conn;
if (uuid != NULL)
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
if (virHashAddEntry(conn->networks, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add network to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseNetwork:
* @network: the network to release
*
* Unconditionally release all memory associated with a network.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The network obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseNetwork(virNetworkPtr network) {
virConnectPtr conn = network->conn;
DEBUG("release network %p %s", network, network->name);
/* TODO search by UUID first as they are better differentiators */
if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("network missing from connection hash table"));
conn = NULL;
}
network->magic = -1;
VIR_FREE(network->name);
VIR_FREE(network);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefNetwork:
* @network: the network to unreference
*
* Unreference the network. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefNetwork(virNetworkPtr network) {
int refs;
if (!VIR_IS_CONNECTED_NETWORK(network)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&network->conn->lock);
DEBUG("unref network %p %s %d", network, network->name, network->refs);
network->refs--;
refs = network->refs;
if (refs == 0) {
virReleaseNetwork(network);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&network->conn->lock);
return (refs);
}
/**
* virGetInterface:
* @conn: the hypervisor connection
* @name: pointer to the interface name
* @mac: pointer to the mac
*
* Lookup if the interface is already registered for that connection,
* if yes return a new pointer to it (possibly updating the MAC
* address), if no allocate a new structure, and register it in the
* table. In any case a corresponding call to virUnrefInterface() is
* needed to not leak data.
*
* Returns a pointer to the interface, or NULL in case of failure
*/
virInterfacePtr
virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
virInterfacePtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
/* a NULL mac from caller is okay. Treat it as blank */
if (mac == NULL)
mac = "";
virMutexLock(&conn->lock);
ret = (virInterfacePtr) virHashLookup(conn->interfaces, name);
if (ret != NULL) {
if (STRCASENEQ(ret->mac, mac)) {
/*
* If the mac address has changed, try to modify it in
* place, which will only work if the new mac is the
* same length as, or shorter than, the old mac.
*/
size_t newmaclen = strlen(mac);
size_t oldmaclen = strlen(ret->mac);
if (newmaclen <= oldmaclen) {
strcpy(ret->mac, mac);
} else {
/*
* If it's longer, we're kind of screwed, because we
* can't add a new hashtable entry (it would clash
* with the existing entry of same name), and we can't
* free/re-alloc the existing entry's mac, as some
* other thread may already be using the existing mac
* pointer. Fortunately, this should never happen,
* since the length of the mac address for any
* interface is determined by the type of the
* interface, and that is unlikely to change.
*/
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
_("Failed to change interface mac address "
"from %s to %s due to differing lengths."),
ret->mac, mac);
ret = NULL;
goto error;
}
}
} else {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->mac = strdup(mac);
if (ret->mac == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_INTERFACE_MAGIC;
ret->conn = conn;
if (virHashAddEntry(conn->interfaces, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add interface to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret->mac);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseInterface:
* @interface: the interface to release
*
2009-10-26 23:02:46 +00:00
* Unconditionally release all memory associated with an interface.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The interface obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseInterface(virInterfacePtr iface) {
virConnectPtr conn = iface->conn;
DEBUG("release interface %p %s", iface, iface->name);
if (virHashRemoveEntry(conn->interfaces, iface->name, NULL) < 0) {
/* unlock before reporting error because error report grabs lock */
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("interface missing from connection hash table"));
/* don't decr the conn refct if we weren't connected to it */
conn = NULL;
}
iface->magic = -1;
VIR_FREE(iface->name);
VIR_FREE(iface->mac);
VIR_FREE(iface);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefInterface:
* @interface: the interface to unreference
*
* Unreference the interface. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefInterface(virInterfacePtr iface) {
int refs;
if (!VIR_IS_CONNECTED_INTERFACE(iface)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
virMutexLock(&iface->conn->lock);
DEBUG("unref interface %p %s %d", iface, iface->name, iface->refs);
iface->refs--;
refs = iface->refs;
if (refs == 0) {
virReleaseInterface(iface);
/* Already unlocked mutex */
return (0);
}
virMutexUnlock(&iface->conn->lock);
return (refs);
}
/**
* virGetStoragePool:
* @conn: the hypervisor connection
* @name: pointer to the storage pool name
* @uuid: pointer to the uuid
*
* Lookup if the storage pool is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virFreeStoragePool() is needed to not leak data.
*
* Returns a pointer to the network, or NULL in case of failure
*/
virStoragePoolPtr
2008-11-17 11:03:25 +00:00
virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virStoragePoolPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
/* TODO search by UUID first as they are better differentiators */
ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
/* TODO check the UUID */
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_STORAGE_POOL_MAGIC;
ret->conn = conn;
if (uuid != NULL)
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
if (virHashAddEntry(conn->storagePools, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to add storage pool to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseStoragePool:
* @pool: the pool to release
*
* Unconditionally release all memory associated with a pool.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The pool obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseStoragePool(virStoragePoolPtr pool) {
virConnectPtr conn = pool->conn;
DEBUG("release pool %p %s", pool, pool->name);
/* TODO search by UUID first as they are better differentiators */
if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("pool missing from connection hash table"));
conn = NULL;
}
pool->magic = -1;
VIR_FREE(pool->name);
VIR_FREE(pool);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefStoragePool:
* @pool: the pool to unreference
*
* Unreference the pool. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefStoragePool(virStoragePoolPtr pool) {
int refs;
if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&pool->conn->lock);
DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
pool->refs--;
refs = pool->refs;
if (refs == 0) {
virReleaseStoragePool(pool);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&pool->conn->lock);
return (refs);
}
/**
* virGetStorageVol:
* @conn: the hypervisor connection
* @pool: pool owning the volume
* @name: pointer to the storage vol name
* @uuid: pointer to the uuid
*
* Lookup if the storage vol is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virFreeStorageVol() is needed to not leak data.
*
* Returns a pointer to the storage vol, or NULL in case of failure
*/
virStorageVolPtr
2008-11-17 11:03:25 +00:00
virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) {
virStorageVolPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->pool = strdup(pool);
if (ret->pool == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
if (virStrcpyStatic(ret->key, key) == NULL) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
_("Volume key %s too large for destination"), key);
goto error;
}
ret->magic = VIR_STORAGE_VOL_MAGIC;
ret->conn = conn;
if (virHashAddEntry(conn->storageVols, key, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add storage vol to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret->pool);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseStorageVol:
* @vol: the vol to release
*
* Unconditionally release all memory associated with a vol.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The vol obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseStorageVol(virStorageVolPtr vol) {
virConnectPtr conn = vol->conn;
DEBUG("release vol %p %s", vol, vol->name);
/* TODO search by UUID first as they are better differentiators */
if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("vol missing from connection hash table"));
conn = NULL;
}
vol->magic = -1;
VIR_FREE(vol->name);
VIR_FREE(vol->pool);
VIR_FREE(vol);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefStorageVol:
* @vol: the vol to unreference
*
* Unreference the vol. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefStorageVol(virStorageVolPtr vol) {
int refs;
if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&vol->conn->lock);
DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs);
vol->refs--;
refs = vol->refs;
if (refs == 0) {
virReleaseStorageVol(vol);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&vol->conn->lock);
return (refs);
}
/**
* virGetNodeDevice:
* @conn: the hypervisor connection
* @name: device name (unique on node)
*
* Lookup if the device is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virFreeNodeDevice() is needed to not leak data.
*
* Returns a pointer to the node device, or NULL in case of failure
*/
virNodeDevicePtr
virGetNodeDevice(virConnectPtr conn, const char *name)
{
virNodeDevicePtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
2009-01-15 19:56:05 +00:00
virMutexLock(&conn->lock);
ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name);
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_NODE_DEVICE_MAGIC;
ret->conn = conn;
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
if (virHashAddEntry(conn->nodeDevices, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to add node dev to conn hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
2009-01-15 19:56:05 +00:00
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseNodeDevice:
* @dev: the dev to release
*
* Unconditionally release all memory associated with a dev.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The dev obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseNodeDevice(virNodeDevicePtr dev) {
virConnectPtr conn = dev->conn;
DEBUG("release dev %p %s", dev, dev->name);
if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
"%s", _("dev missing from connection hash table"));
conn = NULL;
}
dev->magic = -1;
VIR_FREE(dev->name);
VIR_FREE(dev->parent);
VIR_FREE(dev);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefNodeDevice:
* @dev: the dev to unreference
*
* Unreference the dev. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefNodeDevice(virNodeDevicePtr dev) {
int refs;
2009-01-15 19:56:05 +00:00
virMutexLock(&dev->conn->lock);
DEBUG("unref dev %p %s %d", dev, dev->name, dev->refs);
dev->refs--;
refs = dev->refs;
if (refs == 0) {
virReleaseNodeDevice(dev);
/* Already unlocked mutex */
return (0);
}
2009-01-15 19:56:05 +00:00
virMutexUnlock(&dev->conn->lock);
return (refs);
}
/**
* virGetSecret:
* @conn: the hypervisor connection
* @uuid: secret UUID
*
* Lookup if the secret is already registered for that connection, if so return
* a pointer to it, otherwise allocate a new structure, and register it in the
* table. In any case a corresponding call to virFreeSecret() is needed to not
* leak data.
*
* Returns a pointer to the secret, or NULL in case of failure
*/
virSecretPtr
virGetSecret(virConnectPtr conn, const unsigned char *uuid,
int usageType, const char *usageID)
{
virSecretPtr ret = NULL;
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
char uuidstr[VIR_UUID_STRING_BUFLEN];
if (!VIR_IS_CONNECT(conn) || uuid == NULL || usageID == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return NULL;
}
virMutexLock(&conn->lock);
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
virUUIDFormat(uuid, uuidstr);
ret = virHashLookup(conn->secrets, uuidstr);
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_SECRET_MAGIC;
ret->conn = conn;
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
ret->usageType = usageType;
if (!(ret->usageID = strdup(usageID))) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
if (virHashAddEntry(conn->secrets, uuidstr, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add secret to conn hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
virMutexUnlock(&conn->lock);
return ret;
error:
if (ret != NULL) {
VIR_FREE(ret->usageID);
VIR_FREE(ret->uuid);
VIR_FREE(ret);
}
return NULL;
}
/**
* virReleaseSecret:
* @secret: the secret to release
*
* Unconditionally release all memory associated with a secret. The conn.lock
* mutex must be held prior to calling this, and will be released prior to this
* returning. The secret obj must not be used once this method returns.
*
* It will also unreference the associated connection object, which may also be
* released if its ref count hits zero.
*/
static void
virReleaseSecret(virSecretPtr secret) {
virConnectPtr conn = secret->conn;
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
char uuidstr[VIR_UUID_STRING_BUFLEN];
DEBUG("release secret %p %p", secret, secret->uuid);
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
virUUIDFormat(secret->uuid, uuidstr);
if (virHashRemoveEntry(conn->secrets, uuidstr, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("secret missing from connection hash table"));
conn = NULL;
}
VIR_FREE(secret->usageID);
secret->magic = -1;
VIR_FREE(secret);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefSecret:
* @secret: the secret to unreference
*
* Unreference the secret. If the use count drops to zero, the structure is
* actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefSecret(virSecretPtr secret) {
int refs;
if (!VIR_IS_CONNECTED_SECRET(secret)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
}
virMutexLock(&secret->conn->lock);
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
DEBUG("unref secret %p %p %d", secret, secret->uuid, secret->refs);
secret->refs--;
refs = secret->refs;
if (refs == 0) {
virReleaseSecret(secret);
/* Already unlocked mutex */
return 0;
}
virMutexUnlock(&secret->conn->lock);
return refs;
}
virStreamPtr virGetStream(virConnectPtr conn) {
virStreamPtr ret = NULL;
virMutexLock(&conn->lock);
if (VIR_ALLOC(ret) < 0) {
virReportOOMError();
goto error;
}
ret->magic = VIR_STREAM_MAGIC;
ret->conn = conn;
conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
error:
virMutexUnlock(&conn->lock);
VIR_FREE(ret);
return(NULL);
}
static void
virReleaseStream(virStreamPtr st) {
virConnectPtr conn = st->conn;
DEBUG("release dev %p", st);
st->magic = -1;
VIR_FREE(st);
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
int virUnrefStream(virStreamPtr st) {
int refs;
virMutexLock(&st->conn->lock);
DEBUG("unref stream %p %d", st, st->refs);
st->refs--;
refs = st->refs;
if (refs == 0) {
virReleaseStream(st);
/* Already unlocked mutex */
return (0);
}
virMutexUnlock(&st->conn->lock);
return (refs);
}
/**
* virGetNWFilter:
* @conn: the hypervisor connection
* @name: pointer to the network filter pool name
* @uuid: pointer to the uuid
*
* Lookup if the network filter is already registered for that connection,
* if yes return a new pointer to it, if no allocate a new structure,
* and register it in the table. In any case a corresponding call to
* virFreeNWFilterPool() is needed to not leak data.
*
* Returns a pointer to the network, or NULL in case of failure
*/
virNWFilterPtr
virGetNWFilter(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virNWFilterPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
virMutexLock(&conn->lock);
/* TODO search by UUID first as they are better differentiators */
ret = (virNWFilterPtr) virHashLookup(conn->nwfilterPools, name);
/* TODO check the UUID */
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_NWFILTER_MAGIC;
ret->conn = conn;
if (uuid != NULL)
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
if (virHashAddEntry(conn->nwfilterPools, name, ret) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to add network filter pool to connection hash table"));
goto error;
}
conn->refs++;
}
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
/**
* virReleaseNWFilterPool:
* @pool: the pool to release
*
* Unconditionally release all memory associated with a pool.
* The conn.lock mutex must be held prior to calling this, and will
* be released prior to this returning. The pool obj must not
* be used once this method returns.
*
* It will also unreference the associated connection object,
* which may also be released if its ref count hits zero.
*/
static void
virReleaseNWFilterPool(virNWFilterPtr pool) {
virConnectPtr conn = pool->conn;
DEBUG("release pool %p %s", pool, pool->name);
/* TODO search by UUID first as they are better differentiators */
if (virHashRemoveEntry(conn->nwfilterPools, pool->name, NULL) < 0) {
virMutexUnlock(&conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
_("pool missing from connection hash table"));
conn = NULL;
}
pool->magic = -1;
VIR_FREE(pool->name);
VIR_FREE(pool);
if (conn) {
DEBUG("unref connection %p %d", conn, conn->refs);
conn->refs--;
if (conn->refs == 0) {
virReleaseConnect(conn);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&conn->lock);
}
}
/**
* virUnrefNWFilter:
* @pool: the nwfilter to unreference
*
* Unreference the networkf itler. If the use count drops to zero, the
* structure is actually freed.
*
* Returns the reference count or -1 in case of failure.
*/
int
virUnrefNWFilter(virNWFilterPtr pool) {
int refs;
if (!VIR_IS_CONNECTED_NWFILTER(pool)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
}
virMutexLock(&pool->conn->lock);
DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
pool->refs--;
refs = pool->refs;
if (refs == 0) {
virReleaseNWFilterPool(pool);
/* Already unlocked mutex */
return (0);
}
virMutexUnlock(&pool->conn->lock);
return (refs);
}
virDomainSnapshotPtr
virGetDomainSnapshot(virDomainPtr domain, const char *name)
{
virDomainSnapshotPtr ret = NULL;
if ((!VIR_IS_DOMAIN(domain)) || (name == NULL)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
virMutexLock(&domain->conn->lock);
ret = (virDomainSnapshotPtr) virHashLookup(domain->snapshots, name);
if (ret == NULL) {
if (VIR_ALLOC(ret) < 0) {
virMutexUnlock(&domain->conn->lock);
virReportOOMError();
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
virMutexUnlock(&domain->conn->lock);
virReportOOMError();
goto error;
}
ret->magic = VIR_SNAPSHOT_MAGIC;
ret->domain = domain;
if (virHashAddEntry(domain->snapshots, name, ret) < 0) {
virMutexUnlock(&domain->conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to add snapshot to domain hash table"));
goto error;
}
domain->refs++;
DEBUG("New hash entry %p", ret);
} else {
DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1);
}
ret->refs++;
virMutexUnlock(&domain->conn->lock);
return(ret);
error:
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret);
}
return(NULL);
}
static void
virReleaseDomainSnapshot(virDomainSnapshotPtr snapshot)
{
virDomainPtr domain = snapshot->domain;
DEBUG("release snapshot %p %s", snapshot, snapshot->name);
if (virHashRemoveEntry(domain->snapshots, snapshot->name, NULL) < 0) {
virMutexUnlock(&domain->conn->lock);
virLibConnError(VIR_ERR_INTERNAL_ERROR,
"%s", _("snapshot missing from domain hash table"));
domain = NULL;
}
snapshot->magic = -1;
VIR_FREE(snapshot->name);
VIR_FREE(snapshot);
if (domain) {
DEBUG("unref domain %p %d", domain, domain->refs);
domain->refs--;
if (domain->refs == 0) {
virReleaseDomain(domain);
/* Already unlocked mutex */
return;
}
virMutexUnlock(&domain->conn->lock);
}
}
int
virUnrefDomainSnapshot(virDomainSnapshotPtr snapshot)
{
int refs;
if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
virMutexLock(&snapshot->domain->conn->lock);
DEBUG("unref snapshot %p %s %d", snapshot, snapshot->name, snapshot->refs);
snapshot->refs--;
refs = snapshot->refs;
if (refs == 0) {
virReleaseDomainSnapshot(snapshot);
/* Already unlocked mutex */
return (0);
}
virMutexUnlock(&snapshot->domain->conn->lock);
return (refs);
}