[patch 01/12] Add the virtual networks API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>

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);
 }

-- 


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]