]> xenbits.xensource.com Git - libvirt.git/commitdiff
Tue Feb 14 15:33:05 EST 2007 Mark McLoughlin <markmc@redhat.com>
authorMark McLoughlin <markmc@redhat.com>
Wed, 14 Feb 2007 15:37:18 +0000 (15:37 +0000)
committerMark McLoughlin <markmc@redhat.com>
Wed, 14 Feb 2007 15:37:18 +0000 (15:37 +0000)
        * include/libvirt/libvirt.h.in: add the networks APIs

        * include/libvirt/virterror.h: add some error codes

        * src/driver.h: add network driver vtable

        * src/hash.c: add networks hash

        * src/internal.h: add virNetwork

        * src/libvirt.c: hook up the APIs to the network
        driver

        * src/libvirt_sym.version: add the new APIs

        * src/virterror.c: handle the new error codes

ChangeLog
include/libvirt/libvirt.h.in
include/libvirt/virterror.h
src/driver.h
src/hash.c
src/internal.h
src/libvirt.c
src/libvirt_sym.version
src/virterror.c

index eb3ebfc34b9678a9a6108e92e5fd09ffd773d326..1446c02a6ce5da0a89c43e7d4a58f99712701146 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,90 @@
-Tue Feb 14 14:33:22 EST 2007 Mark McLoughlin <markmc@redhat.com
+Tue Feb 14 15:33:05 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * include/libvirt/libvirt.h.in: add the networks APIs
+       
+       * include/libvirt/virterror.h: add some error codes
+       
+       * src/driver.h: add network driver vtable
+       
+       * src/hash.c: add networks hash
+       
+       * src/internal.h: add virNetwork
+
+       * src/libvirt.c: hook up the APIs to the network
+       driver
+       
+       * src/libvirt_sym.version: add the new APIs
+       
+       * src/virterror.c: handle the new error codes
+       
+Tue Feb 14 15:07:26 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * src/conf.h: fix merge error - remove the argc argument
+       from qemudBuildCommandLine()
+       
+Tue Feb 14 15:03:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * src/virsh.c: Re-name some of the VSH_DOMBYFOO stuff
+       to VSH_BYFOO in order to re-use it for the network stuff.
+       
+Tue Feb 14 14:58:35 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * src/hash.c, src/internal.h: Re-name virConnect->domains_mux
+       to virConnect->hashes_mux since it will also be used to
+       protect the networks hash.
+       
+Tue Feb 14 14:57:52 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * qemud/conf.c: qemudSaveConfig() will always report a
+       more specific error, so we should avoid overwriting
+       this error.
+       
+Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * qemud/qemud.c: Re-factor out qemudExec() so that it can
+       be used to launch dnsmasq.
+
+       * qemud/conf.c: don't return argc from qemudBuildCommandLine()
+       as exec() doesn't need it.
+       
+Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * qemud/conf.c: Re-factor bits of conf.c so that:
+
+         - qemudMakeConfigPath() can be re-used given another configDir
+         - split qemudEnsureConfigDir() out of qemudSaveConfig() so
+           that it may be re-used to create another configDir
+         - split qemudScanConfigDir() out so that qemudScanConfigs()
+           can scan multiple configDirs
+       
+Tue Feb 14 14:50:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * qemud/conf.c: handle an unspecified MAC address, 
+       fix the argv freeing code in qemudBuildCommandLine()
+       and fix copy and paste error in qemudGenerateXML()
+       
+Tue Feb 14 14:42:38 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * src/internal.h: add virConnect->qemud_fd so that
+       xen and qemu don't share the handle member.
+
+       * src/hash.c, src/qemu_internal.c: update
+       
+Tue Feb 14 14:40:52 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * qemud/conf.c, qemud/dispatch.c, qemud/driver.c,
+         qemud/qemud.c: include autoconf's config.h
+       
+Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin <markmc@redhat.com>
+
+       * conf.[ch]: rename from config.[ch] so we can use
+       autoconf's config.h
+
+       * Makefile.am: update
+
+       * driver.c, qemud.c: upd.
+       
+Tue Feb 14 14:33:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
 
        * autogen.sh: run autoheader
 
index 489a83d4576d1fa653e2b92014b11667d30cb789..72d5730ae397d58ba0a1eccd6c58fe5f9a3bd4fb 100644 (file)
@@ -443,6 +443,90 @@ int                        virDomainGetVcpus       (virDomainPtr domain,
 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 8a7959eb5da778533a2756e2e5d38445872d92e4..80d43f9cd9bc3c292a91e22fe49d36560265b379 100644 (file)
@@ -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 838f70eb0cfca347310609a49ddd4771bc5a799f..360904110643b3024f5bd4bb84aa0da7f5e58eb9 100644 (file)
@@ -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 6c39918c5dd618b2dcb95762d20a263a7d252a57..8d7dd73063c5971413250c50ff222a55ecc6556a 100644 (file)
@@ -636,6 +636,20 @@ virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
     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:
  *
@@ -655,11 +669,16 @@ virGetConnect(void) {
     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;
@@ -669,8 +688,10 @@ failed:
     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);
@@ -689,22 +710,24 @@ int
 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);
 }
@@ -727,11 +750,11 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     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 */
 
@@ -769,11 +792,11 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
     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 );
@@ -797,11 +820,11 @@ virFreeDomain(virConnectPtr conn, virDomainPtr domain) {
     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
@@ -837,13 +860,13 @@ virFreeDomain(virConnectPtr conn, virDomainPtr 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);
 }
 
@@ -868,7 +891,7 @@ virGetDomainByID(virConnectPtr conn, int id) {
         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))
@@ -888,9 +911,142 @@ virGetDomainByID(virConnectPtr conn, int id) {
        }
     }
 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
index a8938cd02fb74daf9352a6fdba1d481a524db358..d30a0a0d3b2c99c859a7cf35307f912f0102bfd1 100644 (file)
@@ -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 */
@@ -117,14 +131,17 @@ struct _virConnect {
     struct sockaddr_un addr_un;     /* the unix address */
     struct sockaddr_in addr_in;     /* the inet address */
 
+    int qemud_fd;           /* connection to qemud */
+
     /* error stuff */
     virError err;           /* the last error */
     virErrorFunc handler;   /* associated handlet */
     void *userData;         /* the user data */
 
     /* misc */
-    xmlMutexPtr domains_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 */
 };
 
@@ -156,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
 */
@@ -194,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 b0ecafb50c9f997dbc7b42fed3b22f6d11b78a7b..c93058c6f8a30369504881a12aa55bbcba63f040 100644 (file)
@@ -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, virErrorNumber error,
 }
 
 /**
- * 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);
        }
     }
@@ -169,6 +193,34 @@ virRegisterDriver(virDriverPtr driver)
     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)
@@ -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 domain, char *xml)
     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 2d009da44c0059ea8b1984f9afdd1373afa0c76b..d19ee7552bbc2ae51babb4c75227424bd65b912b 100644 (file)
 
     virDomainAttachDevice;
     virDomainDetachDevice;
+
+       virConnectNumOfNetworks;
+       virConnectListNetworks;
+       virConnectNumOfDefinedNetworks;
+       virConnectListDefinedNetworks;
+       virNetworkLookupByName;
+       virNetworkLookupByUUID;
+       virNetworkLookupByUUIDString;
+       virNetworkCreateXML;
+       virNetworkDefineXML;
+       virNetworkUndefine;
+       virNetworkCreate;
+       virNetworkDestroy;
+       virNetworkFree;
+       virNetworkGetName;
+       virNetworkGetUUID;
+       virNetworkGetUUIDString;
+       virNetworkGetXMLDesc;
+
     local: *;
 };
index b180c4e72a064870704699f61f705b7cacda876c..23446c1f453b9d597e58ae9d7e1c209615dd523d 100644 (file)
@@ -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, const char *info)
            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);
 }