return (virDomainFree(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 (virNetworkFree(network));
+}
+
/**
* virGetConnect:
*
memset(ret, 0, sizeof(virConnect));
ret->magic = VIR_CONNECT_MAGIC;
ret->nb_drivers = 0;
+ ret->handle = -1;
+ ret->qemud_fd = -1;
ret->domains = virHashCreate(20);
if (ret->domains == NULL)
goto failed;
- ret->domains_mux = xmlNewMutex();
- if (ret->domains_mux == NULL)
+ ret->networks = virHashCreate(20);
+ if (ret->networks == NULL)
+ goto failed;
+ ret->hashes_mux = xmlNewMutex();
+ if (ret->hashes_mux == NULL)
goto failed;
ret->uses = 1;
if (ret != NULL) {
if (ret->domains != NULL)
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
- if (ret->domains_mux != NULL)
- xmlFreeMutex(ret->domains_mux);
+ if (ret->networks != NULL)
+ virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
+ if (ret->hashes_mux != NULL)
+ xmlFreeMutex(ret->hashes_mux);
free(ret);
}
return(NULL);
virFreeConnect(virConnectPtr conn) {
int ret;
- if ((!VIR_IS_CONNECT(conn)) || (conn->domains_mux == NULL)) {
+ if ((!VIR_IS_CONNECT(conn)) || (conn->hashes_mux == NULL)) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
- xmlMutexLock(conn->domains_mux);
+ xmlMutexLock(conn->hashes_mux);
conn->uses--;
ret = conn->uses;
if (ret > 0) {
- xmlMutexUnlock(conn->domains_mux);
+ xmlMutexUnlock(conn->hashes_mux);
return(ret);
}
if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
- if (conn->domains_mux != NULL)
- xmlFreeMutex(conn->domains_mux);
+ if (conn->networks != NULL)
+ virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
+ if (conn->hashes_mux != NULL)
+ xmlFreeMutex(conn->hashes_mux);
free(conn);
return(0);
}
virDomainPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || ((name == NULL) && (uuid == NULL)) ||
- (conn->domains_mux == NULL)) {
+ (conn->hashes_mux == NULL)) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
- xmlMutexLock(conn->domains_mux);
+ xmlMutexLock(conn->hashes_mux);
/* TODO search by UUID first as they are better differenciators */
conn->uses++;
done:
ret->uses++;
- xmlMutexUnlock(conn->domains_mux);
+ xmlMutexUnlock(conn->hashes_mux);
return(ret);
error:
- xmlMutexUnlock(conn->domains_mux);
+ xmlMutexUnlock(conn->hashes_mux);
if (ret != NULL) {
if (ret->name != NULL)
free(ret->name );
int ret = 0;
if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_DOMAIN(domain)) ||
- (domain->conn != conn) || (conn->domains_mux == NULL)) {
+ (domain->conn != conn) || (conn->hashes_mux == NULL)) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
- xmlMutexLock(conn->domains_mux);
+ xmlMutexLock(conn->hashes_mux);
/*
* decrement the count for the domain
if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
- if (conn->domains_mux != NULL)
- xmlFreeMutex(conn->domains_mux);
+ if (conn->hashes_mux != NULL)
+ xmlFreeMutex(conn->hashes_mux);
free(conn);
return(0);
done:
- xmlMutexUnlock(conn->domains_mux);
+ xmlMutexUnlock(conn->hashes_mux);
return(ret);
}
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
- xmlMutexLock(conn->domains_mux);
+ xmlMutexLock(conn->hashes_mux);
table = conn->domains;
if ((table == NULL) || (table->nbElems == 0))
}
}
done:
- xmlMutexUnlock(conn->domains_mux);
+ xmlMutexUnlock(conn->hashes_mux);
return(ret);
}
+
+/**
+ * virGetNetwork:
+ * @conn: the hypervisor connection
+ * @name: pointer to the network name or NULL
+ * @uuid: pointer to the uuid or NULL
+ *
+ * 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
+ * virFreeNetwork() is needed to not leak data.
+ *
+ * Returns a pointer to the network, or NULL in case of failure
+ */
+virNetworkPtr
+virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
+ virNetworkPtr ret = NULL;
+
+ if ((!VIR_IS_CONNECT(conn)) || ((name == NULL) && (uuid == NULL)) ||
+ (conn->hashes_mux == NULL)) {
+ virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(NULL);
+ }
+ xmlMutexLock(conn->hashes_mux);
+
+ /* TODO search by UUID first as they are better differenciators */
+
+ ret = (virNetworkPtr) virHashLookup(conn->networks, name);
+ if (ret != NULL) {
+ /* TODO check the UUID */
+ goto done;
+ }
+
+ /*
+ * not found, allocate a new one
+ */
+ ret = (virNetworkPtr) malloc(sizeof(virNetwork));
+ if (ret == NULL) {
+ virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network"));
+ goto error;
+ }
+ memset(ret, 0, sizeof(virNetwork));
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network"));
+ 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) {
+ virHashError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("failed to add network to connection hash table"));
+ goto error;
+ }
+ conn->uses++;
+done:
+ ret->uses++;
+ xmlMutexUnlock(conn->hashes_mux);
+ return(ret);
+
+error:
+ xmlMutexUnlock(conn->hashes_mux);
+ if (ret != NULL) {
+ if (ret->name != NULL)
+ free(ret->name );
+ free(ret);
+ }
+ return(NULL);
+}
+
+/**
+ * virFreeNetwork:
+ * @conn: the hypervisor connection
+ * @network: the network to release
+ *
+ * Release the given network, if the reference count drops to zero, then
+ * the network is really freed.
+ *
+ * Returns the reference count or -1 in case of failure.
+ */
+int
+virFreeNetwork(virConnectPtr conn, virNetworkPtr network) {
+ int ret = 0;
+
+ if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_NETWORK(network)) ||
+ (network->conn != conn) || (conn->hashes_mux == NULL)) {
+ virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(-1);
+ }
+ xmlMutexLock(conn->hashes_mux);
+
+ /*
+ * decrement the count for the network
+ */
+ network->uses--;
+ ret = network->uses;
+ if (ret > 0)
+ goto done;
+
+ /* TODO search by UUID first as they are better differenciators */
+
+ if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0) {
+ virHashError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("network missing from connection hash table"));
+ goto done;
+ }
+ network->magic = -1;
+ if (network->name)
+ free(network->name);
+ free(network);
+
+ /*
+ * decrement the count for the connection
+ */
+ conn->uses--;
+ if (conn->uses > 0)
+ goto done;
+
+ if (conn->networks != NULL)
+ virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
+ if (conn->hashes_mux != NULL)
+ xmlFreeMutex(conn->hashes_mux);
+ free(conn);
+ return(0);
+
+done:
+ xmlMutexUnlock(conn->hashes_mux);
+ return(ret);
+}
+
/*
* Local variables:
* indent-tabs-mode: nil
*/
static virDriverPtr virDriverTab[MAX_DRIVERS];
+static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
static int initialized = 0;
/**
/*
* should not be needed but...
*/
- for (i = 0;i < MAX_DRIVERS;i++)
+ for (i = 0;i < MAX_DRIVERS;i++) {
virDriverTab[i] = NULL;
+ virNetworkDriverTab[i] = NULL;
+ }
/*
* Note that the order is important the first ones have a higher priority
}
/**
- * virRegisterDriver:
- * @driver: pointer to a driver block
- *
- * Register a virtualization driver
+ * virLibNetworkError:
+ * @conn: the connection if available
+ * @error: the error noumber
+ * @info: extra information string
*
- * Returns the driver priority or -1 in case of error.
+ * Handle an error at the connection level
*/
-int
-virRegisterDriver(virDriverPtr driver)
+static void
+virLibNetworkError(virNetworkPtr network, virErrorNumber error,
+ const char *info)
+{
+ virConnectPtr conn = NULL;
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK)
+ return;
+
+ errmsg = __virErrorMsg(error, info);
+ if (error != VIR_ERR_INVALID_NETWORK) {
+ conn = network->conn;
+ }
+ /* XXX: should be able to pass network pointer here */
+ __virRaiseError(conn, NULL, VIR_FROM_NET, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+static int
+_virRegisterDriver(void *driver, int isNetwork)
{
+ void **drivers;
int i;
if (!initialized)
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
+ drivers = isNetwork ? (void **) virNetworkDriverTab : (void **) virDriverTab;
for (i = 0;i < MAX_DRIVERS;i++) {
- if (virDriverTab[i] == driver)
+ if (drivers[i] == driver)
return(i);
}
for (i = 0;i < MAX_DRIVERS;i++) {
- if (virDriverTab[i] == NULL) {
- virDriverTab[i] = driver;
+ if (drivers[i] == NULL) {
+ drivers[i] = driver;
return(i);
}
}
return(-1);
}
+/**
+ * virRegisterNetworkDriver:
+ * @driver: pointer to a network driver block
+ *
+ * Register a network virtualization driver
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+virRegisterNetworkDriver(virNetworkDriverPtr driver)
+{
+ return _virRegisterDriver(driver, 1);
+}
+
+/**
+ * virRegisterDriver:
+ * @driver: pointer to a driver block
+ *
+ * Register a virtualization driver
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+virRegisterDriver(virDriverPtr driver)
+{
+ return _virRegisterDriver(driver, 0);
+}
+
/**
* virGetVersion:
* @libVer: return value for the library version (OUT)
}
}
- if (ret->nb_drivers == 0) {
+ for (i = 0;i < MAX_DRIVERS;i++) {
+ if ((virNetworkDriverTab[i] != NULL) && (virNetworkDriverTab[i]->open != NULL) &&
+ (res = virNetworkDriverTab[i]->open(ret, name, VIR_DRV_OPEN_QUIET)) == 0) {
+ ret->networkDrivers[ret->nb_network_drivers++] = virNetworkDriverTab[i];
+ }
+ }
+
+ if (ret->nb_drivers == 0 || ret->nb_network_drivers == 0) {
/* we failed to find an adequate driver */
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
goto failed;
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
ret->drivers[i]->close(ret);
}
+ for (i = 0;i < ret->nb_network_drivers;i++) {
+ if ((ret->networkDrivers[i] != NULL) && (ret->networkDrivers[i]->close != NULL))
+ ret->networkDrivers[i]->close(ret);
+ }
virFreeConnect(ret);
}
return (NULL);
ret->drivers[ret->nb_drivers++] = virDriverTab[i];
}
+ if ((virNetworkDriverTab[i] != NULL) && (virNetworkDriverTab[i]->open != NULL) &&
+ (res = virNetworkDriverTab[i]->open(ret, name, VIR_DRV_OPEN_QUIET)) == 0) {
+ ret->networkDrivers[ret->nb_network_drivers++] = virNetworkDriverTab[i];
+ }
}
if (ret->nb_drivers == 0) {
if (name == NULL)
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
ret->drivers[i]->close(ret);
}
+ for (i = 0;i < ret->nb_network_drivers;i++) {
+ if ((ret->networkDrivers[i] != NULL) && (ret->networkDrivers[i]->close != NULL))
+ ret->networkDrivers[i]->close(ret);
+ }
virFreeConnect(ret);
}
return (NULL);
if ((conn->drivers[i] != NULL) && (conn->drivers[i]->close != NULL))
conn->drivers[i]->close(conn);
}
+ for (i = 0;i < conn->nb_network_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) && (conn->networkDrivers[i]->close != NULL))
+ conn->networkDrivers[i]->close(conn);
+ }
if (virFreeConnect(conn) < 0)
return (-1);
return (0);
virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
return (-1);
}
+
+/**
+ * virConnectNumOfNetworks:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active networks.
+ *
+ * Returns the number of network found or -1 in case of error
+ */
+int
+virConnectNumOfNetworks(virConnectPtr conn)
+{
+ int ret = -1;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (-1);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_network_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->numOfNetworks != NULL)) {
+ ret = conn->networkDrivers[i]->numOfNetworks(conn);
+ if (ret >= 0)
+ return(ret);
+ }
+ }
+
+ return(-1);
+}
+
+/**
+ * virConnectListNetworks:
+ * @conn: pointer to the hypervisor connection
+ * @names: array to collect the list of names of active networks
+ * @maxnames: size of @names
+ *
+ * Collect the list of active networks, and store their names in @names
+ *
+ * Returns the number of networks found or -1 in case of error
+ */
+int
+virConnectListNetworks(virConnectPtr conn, const char **names, int maxnames)
+{
+ int ret = -1;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (-1);
+ }
+
+ if ((names == NULL) || (maxnames <= 0)) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (-1);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->listNetworks != NULL)) {
+ ret = conn->networkDrivers[i]->listNetworks(conn, names, maxnames);
+ if (ret >= 0)
+ return(ret);
+ }
+ }
+
+ return (-1);
+}
+
+/**
+ * virConnectNumOfDefinedNetworks:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of inactive networks.
+ *
+ * Returns the number of networks found or -1 in case of error
+ */
+int
+virConnectNumOfDefinedNetworks(virConnectPtr conn)
+{
+ int ret = -1;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (-1);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->numOfDefinedNetworks != NULL)) {
+ ret = conn->networkDrivers[i]->numOfDefinedNetworks(conn);
+ if (ret >= 0)
+ return(ret);
+ }
+ }
+
+ return(-1);
+}
+
+/**
+ * virConnectListDefinedNetworks:
+ * @conn: pointer to the hypervisor connection
+ * @names: pointer to an array to store the names
+ * @maxnames: size of the array
+ *
+ * list the inactive networks, stores the pointers to the names in @names
+ *
+ * Returns the number of names provided in the array or -1 in case of error
+ */
+int
+virConnectListDefinedNetworks(virConnectPtr conn, const char **names,
+ int maxnames) {
+ int ret = -1;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (-1);
+ }
+
+ if ((names == NULL) || (maxnames <= 0)) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (-1);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->listDefinedNetworks != NULL)) {
+ ret = conn->networkDrivers[i]->listDefinedNetworks(conn, names, maxnames);
+ if (ret >= 0)
+ return(ret);
+ }
+ }
+
+ return (-1);
+}
+
+/**
+ * virNetworkLookupByName:
+ * @conn: pointer to the hypervisor connection
+ * @name: name for the network
+ *
+ * Try to lookup a network on the given hypervisor based on its name.
+ *
+ * Returns a new network object or NULL in case of failure
+ */
+virNetworkPtr
+virNetworkLookupByName(virConnectPtr conn, const char *name)
+{
+ virNetworkPtr ret = NULL;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (NULL);
+ }
+ if (name == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkLookupByName != NULL)) {
+ ret = conn->networkDrivers[i]->networkLookupByName(conn, name);
+ if (ret)
+ return(ret);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ * virNetworkLookupByUUID:
+ * @conn: pointer to the hypervisor connection
+ * @uuid: the raw UUID for the network
+ *
+ * Try to lookup a network on the given hypervisor based on its UUID.
+ *
+ * Returns a new network object or NULL in case of failure
+ */
+virNetworkPtr
+virNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+ virNetworkPtr ret;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (NULL);
+ }
+ if (uuid == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkLookupByUUID != NULL)) {
+ ret = conn->networkDrivers[i]->networkLookupByUUID(conn, uuid);
+ if (ret)
+ return(ret);
+ }
+ }
+
+ return (NULL);
+}
+
+/**
+ * virNetworkLookupByUUIDString:
+ * @conn: pointer to the hypervisor connection
+ * @uuidstr: the string UUID for the network
+ *
+ * Try to lookup a network on the given hypervisor based on its UUID.
+ *
+ * Returns a new network object or NULL in case of failure
+ */
+virNetworkPtr
+virNetworkLookupByUUIDString(virConnectPtr conn, const char *uuidstr)
+{
+ int raw[VIR_UUID_BUFLEN], i;
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ int ret;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (NULL);
+ }
+ if (uuidstr == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+
+ /* XXX: sexpr_uuid() also supports 'xxxx-xxxx-xxxx-xxxx' format.
+ * We needn't it here. Right?
+ */
+ ret = sscanf(uuidstr,
+ "%02x%02x%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x-"
+ "%02x%02x%02x%02x%02x%02x",
+ raw + 0, raw + 1, raw + 2, raw + 3,
+ raw + 4, raw + 5, raw + 6, raw + 7,
+ raw + 8, raw + 9, raw + 10, raw + 11,
+ raw + 12, raw + 13, raw + 14, raw + 15);
+
+ if (ret!=VIR_UUID_BUFLEN) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+ for (i = 0; i < VIR_UUID_BUFLEN; i++)
+ uuid[i] = raw[i] & 0xFF;
+
+ return virNetworkLookupByUUID(conn, &uuid[0]);
+}
+
+/**
+ * virNetworkCreateXML:
+ * @conn: pointer to the hypervisor connection
+ * @xmlDesc: an XML description of the network
+ *
+ * Create and start a new virtual network, based on an XML description
+ * similar to the one returned by virNetworkGetXMLDesc()
+ *
+ * Returns a new network object or NULL in case of failure
+ */
+virNetworkPtr
+virNetworkCreateXML(virConnectPtr conn, const char *xmlDesc)
+{
+ virNetworkPtr ret;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (NULL);
+ }
+ if (xmlDesc == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (NULL);
+ }
+
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkCreateXML != NULL)) {
+ ret = conn->networkDrivers[i]->networkCreateXML(conn, xmlDesc);
+ if (ret != NULL)
+ return(ret);
+ }
+ }
+ return(NULL);
+}
+
+/**
+ * virNetworkDefineXML:
+ * @conn: pointer to the hypervisor connection
+ * @xml: the XML description for the network, preferably in UTF-8
+ *
+ * Define a network, but does not create it
+ *
+ * Returns NULL in case of error, a pointer to the network otherwise
+ */
+virNetworkPtr
+virNetworkDefineXML(virConnectPtr conn, const char *xml) {
+ virNetworkPtr ret = NULL;
+ int i;
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return (NULL);
+ }
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (NULL);
+ }
+ if (xml == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkDefineXML != NULL)) {
+ ret = conn->networkDrivers[i]->networkDefineXML(conn, xml);
+ if (ret)
+ return(ret);
+ }
+ }
+
+ return(ret);
+}
+
+/**
+ * virNetworkUndefine:
+ * @network: pointer to a defined network
+ *
+ * Undefine a network but does not stop it if it is running
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+virNetworkUndefine(virNetworkPtr network) {
+ int ret, i;
+ virConnectPtr conn;
+
+ if (!VIR_IS_CONNECTED_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+ conn = network->conn;
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (-1);
+ }
+
+ /* Go though the driver registered entry points */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkUndefine != NULL)) {
+ ret = conn->networkDrivers[i]->networkUndefine(network);
+ if (ret >= 0)
+ return(ret);
+ }
+ }
+
+ return(-1);
+}
+
+/**
+ * virNetworkCreate:
+ * @network: pointer to a defined network
+ *
+ * Create and start a defined network. If the call succeed the network
+ * moves from the defined to the running networks pools.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+virNetworkCreate(virNetworkPtr network) {
+ int i, ret = -1;
+ virConnectPtr conn;
+ if (network == NULL) {
+ TODO
+ return (-1);
+ }
+ if (!VIR_IS_CONNECTED_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+ conn = network->conn;
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (-1);
+ }
+
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkCreate != NULL)) {
+ ret = conn->networkDrivers[i]->networkCreate(network);
+ if (ret == 0)
+ return(ret);
+ }
+ }
+ return(ret);
+}
+
+/**
+ * virNetworkDestroy:
+ * @network: a network object
+ *
+ * Destroy the network object. The running instance is shutdown if not down
+ * already and all resources used by it are given back to the hypervisor.
+ * The data structure is freed and should not be used thereafter if the
+ * call does not return an error.
+ * This function may requires priviledged access
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNetworkDestroy(virNetworkPtr network)
+{
+ int i;
+ virConnectPtr conn;
+
+ if (!VIR_IS_CONNECTED_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+
+ conn = network->conn;
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ return (-1);
+ }
+
+ /*
+ * Go though the driver registered entry points
+ */
+ for (i = 0;i < conn->nb_drivers;i++) {
+ if ((conn->networkDrivers[i] != NULL) &&
+ (conn->networkDrivers[i]->networkDestroy != NULL)) {
+ if (conn->networkDrivers[i]->networkDestroy(network) == 0)
+ return (0);
+ }
+ }
+
+ virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
+ return (-1);
+}
+
+/**
+ * virNetworkFree:
+ * @network: a network object
+ *
+ * Free the network object. The running instance is kept alive.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNetworkFree(virNetworkPtr network)
+{
+ if (!VIR_IS_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+ if (virFreeNetwork(network->conn, network) < 0)
+ return (-1);
+ return(0);
+}
+
+/**
+ * virNetworkGetName:
+ * @network: a network object
+ *
+ * Get the public name for that network
+ *
+ * Returns a pointer to the name or NULL, the string need not be deallocated
+ * its lifetime will be the same as the network object.
+ */
+const char *
+virNetworkGetName(virNetworkPtr network)
+{
+ if (!VIR_IS_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (NULL);
+ }
+ return (network->name);
+}
+
+/**
+ * virNetworkGetUUID:
+ * @network: a network object
+ * @uuid: pointer to a VIR_UUID_BUFLEN bytes array
+ *
+ * Get the UUID for a network
+ *
+ * Returns -1 in case of error, 0 in case of success
+ */
+int
+virNetworkGetUUID(virNetworkPtr network, unsigned char *uuid)
+{
+ if (!VIR_IS_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+ if (uuid == NULL) {
+ virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (-1);
+ }
+
+ memcpy(uuid, &network->uuid[0], VIR_UUID_BUFLEN);
+
+ return (0);
+}
+
+/**
+ * virNetworkGetUUIDString:
+ * @network: a network object
+ * @buf: pointer to a VIR_UUID_STRING_BUFLEN bytes array
+ *
+ * Get the UUID for a network as string. For more information about
+ * UUID see RFC4122.
+ *
+ * Returns -1 in case of error, 0 in case of success
+ */
+int
+virNetworkGetUUIDString(virNetworkPtr network, char *buf)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (!VIR_IS_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (-1);
+ }
+ if (buf == NULL) {
+ virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (-1);
+ }
+
+ if (virNetworkGetUUID(network, &uuid[0]))
+ return (-1);
+
+ snprintf(buf, VIR_UUID_STRING_BUFLEN,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ return (0);
+}
+
+/**
+ * virNetworkGetXMLDesc:
+ * @network: a network object
+ * @flags: and OR'ed set of extraction flags, not used yet
+ *
+ * Provide an XML description of the network. The description may be reused
+ * later to relaunch the network with virNetworkCreateXML().
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+char *
+virNetworkGetXMLDesc(virNetworkPtr network, int flags)
+{
+ int i;
+ char *ret = NULL;
+ if (!VIR_IS_NETWORK(network)) {
+ virLibNetworkError(network, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+ return (NULL);
+ }
+ if (flags != 0) {
+ virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return (NULL);
+ }
+
+ for (i = 0;i < network->conn->nb_network_drivers;i++) {
+ if ((network->conn->networkDrivers[i] != NULL) &&
+ (network->conn->networkDrivers[i]->networkDumpXML != NULL)) {
+ ret = network->conn->networkDrivers[i]->networkDumpXML(network, flags);
+ if (ret)
+ break;
+ }
+ }
+ if (!ret) {
+ virLibConnError(network->conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
+ return (NULL);
+ }
+ return(ret);
+}