Adds the virNetwork API and hooks up the API to driver
methods.
The API closely mirrors the domains API with the following
exceptions:
- Networks don't have IDs - only names and UUIDs
- There is no virNetworkCreateFlags
We use a seperate driver vtable for the networks support
and require at least one network driver.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
Index: libvirt/include/libvirt/libvirt.h.in
===================================================================
--- libvirt.orig/include/libvirt/libvirt.h.in
+++ libvirt/include/libvirt/libvirt.h.in
@@ -443,6 +443,90 @@ int virDomainGetVcpus (virDomainPtr do
int virDomainAttachDevice(virDomainPtr domain, char *xml);
int virDomainDetachDevice(virDomainPtr domain, char *xml);
+/*
+ * Virtual Networks API
+ */
+
+/**
+ * virNetwork:
+ *
+ * a virNetwork is a private structure representing a virtual network.
+ */
+typedef struct _virNetwork virNetwork;
+
+/**
+ * virNetworkPtr:
+ *
+ * a virNetworkPtr is pointer to a virNetwork private structure, this is the
+ * type used to reference a virtual network in the API.
+ */
+typedef virNetwork *virNetworkPtr;
+
+/*
+ * List active networks
+ */
+int virConnectNumOfNetworks (virConnectPtr conn);
+int virConnectListNetworks (virConnectPtr conn,
+ const char **names,
+ int maxnames);
+
+/*
+ * List inactive networks
+ */
+int virConnectNumOfDefinedNetworks (virConnectPtr conn);
+int virConnectListDefinedNetworks (virConnectPtr conn,
+ const char **names,
+ int maxnames);
+
+/*
+ * Lookup network by name or uuid
+ */
+virNetworkPtr virNetworkLookupByName (virConnectPtr conn,
+ const char *name);
+virNetworkPtr virNetworkLookupByUUID (virConnectPtr conn,
+ const unsigned char *uuid);
+virNetworkPtr virNetworkLookupByUUIDString (virConnectPtr conn,
+ const char *uuid);
+
+/*
+ * Create active transient network
+ */
+virNetworkPtr virNetworkCreateXML (virConnectPtr conn,
+ const char *xmlDesc);
+
+/*
+ * Define inactive persistent network
+ */
+virNetworkPtr virNetworkDefineXML (virConnectPtr conn,
+ const char *xmlDesc);
+
+/*
+ * Delete persistent network
+ */
+int virNetworkUndefine (virNetworkPtr network);
+
+/*
+ * Activate persistent network
+ */
+int virNetworkCreate (virNetworkPtr network);
+
+/*
+ * Network destroy/free
+ */
+int virNetworkDestroy (virNetworkPtr network);
+int virNetworkFree (virNetworkPtr network);
+
+/*
+ * Network informations
+ */
+const char* virNetworkGetName (virNetworkPtr network);
+int virNetworkGetUUID (virNetworkPtr network,
+ unsigned char *uuid);
+int virNetworkGetUUIDString (virNetworkPtr network,
+ char *buf);
+char * virNetworkGetXMLDesc (virNetworkPtr network,
+ int flags);
+
#ifdef __cplusplus
}
#endif
Index: libvirt/include/libvirt/virterror.h
===================================================================
--- libvirt.orig/include/libvirt/virterror.h
+++ libvirt/include/libvirt/virterror.h
@@ -48,6 +48,7 @@ typedef enum {
VIR_FROM_PROXY, /* Error in the proxy code */
VIR_FROM_CONF, /* Error in the configuration file handling */
VIR_FROM_QEMU, /* Error at the QEMU daemon */
+ VIR_FROM_NET, /* Error when operating on a network */
} virErrorDomain;
@@ -114,7 +115,9 @@ typedef enum {
VIR_ERR_PARSE_FAILED, /* failed to parse a conf file */
VIR_ERR_CONF_SYNTAX, /* failed to parse the syntax of a conf file */
VIR_ERR_WRITE_FAILED, /* failed to write a conf file */
- VIR_ERR_XML_DETAIL /* detail of an XML error */
+ VIR_ERR_XML_DETAIL, /* detail of an XML error */
+ VIR_ERR_INVALID_NETWORK, /* invalid network object */
+ VIR_ERR_NETWORK_EXIST, /* the network already exist */
} virErrorNumber;
/**
Index: libvirt/src/driver.h
===================================================================
--- libvirt.orig/src/driver.h
+++ libvirt/src/driver.h
@@ -188,6 +188,65 @@ struct _virDriver {
virDrvDomainDetachDevice domainDetachDevice;
};
+typedef int
+ (*virDrvNumOfNetworks) (virConnectPtr conn);
+typedef int
+ (*virDrvListNetworks) (virConnectPtr conn,
+ const char **names,
+ int maxnames);
+typedef int
+ (*virDrvNumOfDefinedNetworks) (virConnectPtr conn);
+typedef int
+ (*virDrvListDefinedNetworks) (virConnectPtr conn,
+ const char **names,
+ int maxnames);
+typedef virNetworkPtr
+ (*virDrvNetworkLookupByUUID) (virConnectPtr conn,
+ const unsigned char *uuid);
+typedef virNetworkPtr
+ (*virDrvNetworkLookupByName) (virConnectPtr conn,
+ const char *name);
+typedef virNetworkPtr
+ (*virDrvNetworkCreateXML) (virConnectPtr conn,
+ const char *xmlDesc);
+typedef virNetworkPtr
+ (*virDrvNetworkDefineXML) (virConnectPtr conn, const char *xml);
+typedef int
+ (*virDrvNetworkUndefine) (virNetworkPtr network);
+typedef int
+ (*virDrvNetworkCreate) (virNetworkPtr network);
+typedef int
+ (*virDrvNetworkDestroy) (virNetworkPtr network);
+typedef char *
+ (*virDrvNetworkDumpXML) (virNetworkPtr network,
+ int flags);
+
+typedef struct _virNetworkDriver virNetworkDriver;
+typedef virNetworkDriver *virNetworkDriverPtr;
+
+/**
+ * _virNetworkDriver:
+ *
+ * Structure associated to a network virtualization driver, defining the various
+ * entry points for it.
+ */
+struct _virNetworkDriver {
+ virDrvOpen open;
+ virDrvClose close;
+ virDrvNumOfNetworks numOfNetworks;
+ virDrvListNetworks listNetworks;
+ virDrvNumOfDefinedNetworks numOfDefinedNetworks;
+ virDrvListDefinedNetworks listDefinedNetworks;
+ virDrvNetworkLookupByUUID networkLookupByUUID;
+ virDrvNetworkLookupByName networkLookupByName;
+ virDrvNetworkCreateXML networkCreateXML;
+ virDrvNetworkDefineXML networkDefineXML;
+ virDrvNetworkUndefine networkUndefine;
+ virDrvNetworkCreate networkCreate;
+ virDrvNetworkDestroy networkDestroy;
+ virDrvNetworkDumpXML networkDumpXML;
+};
+
/*
* Registration
@@ -195,6 +254,7 @@ struct _virDriver {
* lookup based on the URI given in a virConnectOpen(ReadOnly)
*/
int virRegisterDriver(virDriverPtr);
+int virRegisterNetworkDriver(virNetworkDriverPtr);
#ifdef __cplusplus
}
Index: libvirt/src/hash.c
===================================================================
--- libvirt.orig/src/hash.c
+++ libvirt/src/hash.c
@@ -637,6 +637,20 @@ virDomainFreeName(virDomainPtr domain, c
}
/**
+ * 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:
*
* Allocates a new hypervisor connection structure
@@ -660,6 +674,9 @@ virGetConnect(void) {
ret->domains = virHashCreate(20);
if (ret->domains == NULL)
goto failed;
+ ret->networks = virHashCreate(20);
+ if (ret->networks == NULL)
+ goto failed;
ret->hashes_mux = xmlNewMutex();
if (ret->hashes_mux == NULL)
goto failed;
@@ -671,6 +688,8 @@ failed:
if (ret != NULL) {
if (ret->domains != NULL)
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
+ if (ret->networks != NULL)
+ virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
if (ret->hashes_mux != NULL)
xmlFreeMutex(ret->hashes_mux);
free(ret);
@@ -705,6 +724,8 @@ virFreeConnect(virConnectPtr conn) {
if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
+ if (conn->networks != NULL)
+ virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
if (conn->hashes_mux != NULL)
xmlFreeMutex(conn->hashes_mux);
free(conn);
@@ -893,6 +914,139 @@ done:
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
Index: libvirt/src/internal.h
===================================================================
--- libvirt.orig/src/internal.h
+++ libvirt/src/internal.h
@@ -84,6 +84,16 @@ extern "C" {
#define VIR_IS_DOMAIN(obj) ((obj) && (obj)->magic==VIR_DOMAIN_MAGIC)
#define VIR_IS_CONNECTED_DOMAIN(obj) (VIR_IS_DOMAIN(obj) &&
VIR_IS_CONNECT((obj)->conn))
+/**
+ * VIR_NETWORK_MAGIC:
+ *
+ * magic value used to protect the API when pointers to network structures
+ * are passed down by the uers.
+ */
+#define VIR_NETWORK_MAGIC 0xDEAD1234
+#define VIR_IS_NETWORK(obj) ((obj) && (obj)->magic==VIR_NETWORK_MAGIC)
+#define VIR_IS_CONNECTED_NETWORK(obj) (VIR_IS_NETWORK(obj) &&
VIR_IS_CONNECT((obj)->conn))
+
#define MAX_DRIVERS 10
/*
@@ -104,6 +114,10 @@ struct _virConnect {
virDriverPtr drivers[MAX_DRIVERS];
int nb_drivers;
+ /* the list of available network drivers */
+ virNetworkDriverPtr networkDrivers[MAX_DRIVERS];
+ int nb_network_drivers;
+
/* extra data needed by drivers */
int handle; /* internal handle used for hypercall */
struct xs_handle *xshandle;/* handle to talk to the xenstore */
@@ -125,8 +139,9 @@ struct _virConnect {
void *userData; /* the user data */
/* misc */
- xmlMutexPtr hashes_mux;/* a mutex to protect the domain hash table */
+ xmlMutexPtr hashes_mux;/* a mutex to protect the domain and networks hash tables */
virHashTablePtr domains;/* hash table for known domains */
+ virHashTablePtr networks;/* hash table for known domains */
int flags; /* a set of connection flags */
};
@@ -158,6 +173,19 @@ struct _virDomain {
char *xml; /* the XML description for defined domains */
};
+/**
+* _virNetwork:
+*
+* Internal structure associated to a domain
+*/
+struct _virNetwork {
+ unsigned int magic; /* specific value to check */
+ int uses; /* reference count */
+ virConnectPtr conn; /* pointer back to the connection */
+ char *name; /* the network external name */
+ unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */
+};
+
/*
* Internal routines
*/
@@ -196,6 +224,11 @@ int virFreeDomain (virConnectPtr conn,
virDomainPtr domain);
virDomainPtr virGetDomainByID(virConnectPtr conn,
int id);
+virNetworkPtr virGetNetwork (virConnectPtr conn,
+ const char *name,
+ const unsigned char *uuid);
+int virFreeNetwork (virConnectPtr conn,
+ virNetworkPtr domain);
#ifdef __cplusplus
}
Index: libvirt/src/libvirt.c
===================================================================
--- libvirt.orig/src/libvirt.c
+++ libvirt/src/libvirt.c
@@ -42,6 +42,7 @@
*/
static virDriverPtr virDriverTab[MAX_DRIVERS];
+static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
static int initialized = 0;
/**
@@ -68,8 +69,10 @@ virInitialize(void)
/*
* 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
@@ -135,16 +138,36 @@ virLibDomainError(virDomainPtr domain, v
}
/**
- * 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)
@@ -155,13 +178,14 @@ virRegisterDriver(virDriverPtr driver)
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);
}
}
@@ -170,6 +194,34 @@ virRegisterDriver(virDriverPtr driver)
}
/**
+ * 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)
* @type: the type of connection/driver looked at
@@ -265,7 +317,14 @@ virConnectOpen(const char *name)
}
}
- 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;
@@ -279,6 +338,10 @@ 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);
@@ -321,6 +384,10 @@ virConnectOpenReadOnly(const char *name)
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)
@@ -341,6 +408,10 @@ 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);
@@ -368,6 +439,10 @@ virConnectClose(virConnectPtr conn)
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);
@@ -2053,3 +2128,607 @@ virDomainDetachDevice(virDomainPtr domai
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);
+}
Index: libvirt/src/libvirt_sym.version
===================================================================
--- libvirt.orig/src/libvirt_sym.version
+++ libvirt/src/libvirt_sym.version
@@ -57,5 +57,24 @@
virDomainAttachDevice;
virDomainDetachDevice;
+
+ virConnectNumOfNetworks;
+ virConnectListNetworks;
+ virConnectNumOfDefinedNetworks;
+ virConnectListDefinedNetworks;
+ virNetworkLookupByName;
+ virNetworkLookupByUUID;
+ virNetworkLookupByUUIDString;
+ virNetworkCreateXML;
+ virNetworkDefineXML;
+ virNetworkUndefine;
+ virNetworkCreate;
+ virNetworkDestroy;
+ virNetworkFree;
+ virNetworkGetName;
+ virNetworkGetUUID;
+ virNetworkGetUUIDString;
+ virNetworkGetXMLDesc;
+
local: *;
};
Index: libvirt/src/virterror.c
===================================================================
--- libvirt.orig/src/virterror.c
+++ libvirt/src/virterror.c
@@ -271,6 +271,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_QEMU:
dom = "QEMU ";
break;
+ case VIR_FROM_NET:
+ dom = "Network ";
+ break;
}
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
domain = err->dom->name;
@@ -585,6 +588,18 @@ __virErrorMsg(virErrorNumber error, cons
else
errmsg = "%s";
break;
+ case VIR_ERR_INVALID_NETWORK:
+ if (info == NULL)
+ errmsg = _("invalid network pointer in");
+ else
+ errmsg = _("invalid network pointer in %s");
+ break;
+ case VIR_ERR_NETWORK_EXIST:
+ if (info == NULL)
+ errmsg = _("this network exists already");
+ else
+ errmsg = _("network %s exists already");
+ break;
}
return (errmsg);
}
--