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
This commit is contained in:
Mark McLoughlin 2007-02-14 15:37:18 +00:00
parent 24a92945d3
commit 5be54b40cb
9 changed files with 1172 additions and 35 deletions

View File

@ -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 * autogen.sh: run autoheader

View File

@ -443,6 +443,90 @@ int virDomainGetVcpus (virDomainPtr domain,
int virDomainAttachDevice(virDomainPtr domain, char *xml); int virDomainAttachDevice(virDomainPtr domain, char *xml);
int virDomainDetachDevice(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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -48,6 +48,7 @@ typedef enum {
VIR_FROM_PROXY, /* Error in the proxy code */ VIR_FROM_PROXY, /* Error in the proxy code */
VIR_FROM_CONF, /* Error in the configuration file handling */ VIR_FROM_CONF, /* Error in the configuration file handling */
VIR_FROM_QEMU, /* Error at the QEMU daemon */ VIR_FROM_QEMU, /* Error at the QEMU daemon */
VIR_FROM_NET, /* Error when operating on a network */
} virErrorDomain; } virErrorDomain;
@ -114,7 +115,9 @@ typedef enum {
VIR_ERR_PARSE_FAILED, /* failed to parse a conf file */ 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_CONF_SYNTAX, /* failed to parse the syntax of a conf file */
VIR_ERR_WRITE_FAILED, /* failed to write 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; } virErrorNumber;
/** /**

View File

@ -188,6 +188,65 @@ struct _virDriver {
virDrvDomainDetachDevice domainDetachDevice; 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 * Registration
@ -195,6 +254,7 @@ struct _virDriver {
* lookup based on the URI given in a virConnectOpen(ReadOnly) * lookup based on the URI given in a virConnectOpen(ReadOnly)
*/ */
int virRegisterDriver(virDriverPtr); int virRegisterDriver(virDriverPtr);
int virRegisterNetworkDriver(virNetworkDriverPtr);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -636,6 +636,20 @@ virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
return (virDomainFree(domain)); 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: * virGetConnect:
* *
@ -655,11 +669,16 @@ virGetConnect(void) {
memset(ret, 0, sizeof(virConnect)); memset(ret, 0, sizeof(virConnect));
ret->magic = VIR_CONNECT_MAGIC; ret->magic = VIR_CONNECT_MAGIC;
ret->nb_drivers = 0; ret->nb_drivers = 0;
ret->handle = -1;
ret->qemud_fd = -1;
ret->domains = virHashCreate(20); ret->domains = virHashCreate(20);
if (ret->domains == NULL) if (ret->domains == NULL)
goto failed; goto failed;
ret->domains_mux = xmlNewMutex(); ret->networks = virHashCreate(20);
if (ret->domains_mux == NULL) if (ret->networks == NULL)
goto failed;
ret->hashes_mux = xmlNewMutex();
if (ret->hashes_mux == NULL)
goto failed; goto failed;
ret->uses = 1; ret->uses = 1;
@ -669,8 +688,10 @@ failed:
if (ret != NULL) { if (ret != NULL) {
if (ret->domains != NULL) if (ret->domains != NULL)
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName); virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
if (ret->domains_mux != NULL) if (ret->networks != NULL)
xmlFreeMutex(ret->domains_mux); virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
if (ret->hashes_mux != NULL)
xmlFreeMutex(ret->hashes_mux);
free(ret); free(ret);
} }
return(NULL); return(NULL);
@ -689,22 +710,24 @@ int
virFreeConnect(virConnectPtr conn) { virFreeConnect(virConnectPtr conn) {
int ret; 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__); virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1); return(-1);
} }
xmlMutexLock(conn->domains_mux); xmlMutexLock(conn->hashes_mux);
conn->uses--; conn->uses--;
ret = conn->uses; ret = conn->uses;
if (ret > 0) { if (ret > 0) {
xmlMutexUnlock(conn->domains_mux); xmlMutexUnlock(conn->hashes_mux);
return(ret); return(ret);
} }
if (conn->domains != NULL) if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName); virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
if (conn->domains_mux != NULL) if (conn->networks != NULL)
xmlFreeMutex(conn->domains_mux); virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
if (conn->hashes_mux != NULL)
xmlFreeMutex(conn->hashes_mux);
free(conn); free(conn);
return(0); return(0);
} }
@ -727,11 +750,11 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virDomainPtr ret = NULL; virDomainPtr ret = NULL;
if ((!VIR_IS_CONNECT(conn)) || ((name == NULL) && (uuid == 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__); virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL); return(NULL);
} }
xmlMutexLock(conn->domains_mux); xmlMutexLock(conn->hashes_mux);
/* TODO search by UUID first as they are better differenciators */ /* 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++; conn->uses++;
done: done:
ret->uses++; ret->uses++;
xmlMutexUnlock(conn->domains_mux); xmlMutexUnlock(conn->hashes_mux);
return(ret); return(ret);
error: error:
xmlMutexUnlock(conn->domains_mux); xmlMutexUnlock(conn->hashes_mux);
if (ret != NULL) { if (ret != NULL) {
if (ret->name != NULL) if (ret->name != NULL)
free(ret->name ); free(ret->name );
@ -797,11 +820,11 @@ virFreeDomain(virConnectPtr conn, virDomainPtr domain) {
int ret = 0; int ret = 0;
if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_DOMAIN(domain)) || 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__); virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1); return(-1);
} }
xmlMutexLock(conn->domains_mux); xmlMutexLock(conn->hashes_mux);
/* /*
* decrement the count for the domain * decrement the count for the domain
@ -837,13 +860,13 @@ virFreeDomain(virConnectPtr conn, virDomainPtr domain) {
if (conn->domains != NULL) if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName); virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
if (conn->domains_mux != NULL) if (conn->hashes_mux != NULL)
xmlFreeMutex(conn->domains_mux); xmlFreeMutex(conn->hashes_mux);
free(conn); free(conn);
return(0); return(0);
done: done:
xmlMutexUnlock(conn->domains_mux); xmlMutexUnlock(conn->hashes_mux);
return(ret); return(ret);
} }
@ -868,7 +891,7 @@ virGetDomainByID(virConnectPtr conn, int id) {
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL); return(NULL);
} }
xmlMutexLock(conn->domains_mux); xmlMutexLock(conn->hashes_mux);
table = conn->domains; table = conn->domains;
if ((table == NULL) || (table->nbElems == 0)) if ((table == NULL) || (table->nbElems == 0))
@ -888,9 +911,142 @@ virGetDomainByID(virConnectPtr conn, int id) {
} }
} }
done: done:
xmlMutexUnlock(conn->domains_mux); xmlMutexUnlock(conn->hashes_mux);
return(ret); 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: * Local variables:
* indent-tabs-mode: nil * indent-tabs-mode: nil

View File

@ -84,6 +84,16 @@ extern "C" {
#define VIR_IS_DOMAIN(obj) ((obj) && (obj)->magic==VIR_DOMAIN_MAGIC) #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)) #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 #define MAX_DRIVERS 10
/* /*
@ -104,6 +114,10 @@ struct _virConnect {
virDriverPtr drivers[MAX_DRIVERS]; virDriverPtr drivers[MAX_DRIVERS];
int nb_drivers; int nb_drivers;
/* the list of available network drivers */
virNetworkDriverPtr networkDrivers[MAX_DRIVERS];
int nb_network_drivers;
/* extra data needed by drivers */ /* extra data needed by drivers */
int handle; /* internal handle used for hypercall */ int handle; /* internal handle used for hypercall */
struct xs_handle *xshandle;/* handle to talk to the xenstore */ 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_un addr_un; /* the unix address */
struct sockaddr_in addr_in; /* the inet address */ struct sockaddr_in addr_in; /* the inet address */
int qemud_fd; /* connection to qemud */
/* error stuff */ /* error stuff */
virError err; /* the last error */ virError err; /* the last error */
virErrorFunc handler; /* associated handlet */ virErrorFunc handler; /* associated handlet */
void *userData; /* the user data */ void *userData; /* the user data */
/* misc */ /* 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 domains;/* hash table for known domains */
virHashTablePtr networks;/* hash table for known domains */
int flags; /* a set of connection flags */ int flags; /* a set of connection flags */
}; };
@ -156,6 +173,19 @@ struct _virDomain {
char *xml; /* the XML description for defined domains */ 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 * Internal routines
*/ */
@ -194,6 +224,11 @@ int virFreeDomain (virConnectPtr conn,
virDomainPtr domain); virDomainPtr domain);
virDomainPtr virGetDomainByID(virConnectPtr conn, virDomainPtr virGetDomainByID(virConnectPtr conn,
int id); int id);
virNetworkPtr virGetNetwork (virConnectPtr conn,
const char *name,
const unsigned char *uuid);
int virFreeNetwork (virConnectPtr conn,
virNetworkPtr domain);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -42,6 +42,7 @@
*/ */
static virDriverPtr virDriverTab[MAX_DRIVERS]; static virDriverPtr virDriverTab[MAX_DRIVERS];
static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
static int initialized = 0; static int initialized = 0;
/** /**
@ -68,8 +69,10 @@ virInitialize(void)
/* /*
* should not be needed but... * should not be needed but...
*/ */
for (i = 0;i < MAX_DRIVERS;i++) for (i = 0;i < MAX_DRIVERS;i++) {
virDriverTab[i] = NULL; virDriverTab[i] = NULL;
virNetworkDriverTab[i] = NULL;
}
/* /*
* Note that the order is important the first ones have a higher priority * Note that the order is important the first ones have a higher priority
@ -135,16 +138,36 @@ virLibDomainError(virDomainPtr domain, virErrorNumber error,
} }
/** /**
* virRegisterDriver: * virLibNetworkError:
* @driver: pointer to a driver block * @conn: the connection if available
* @error: the error noumber
* @info: extra information string
* *
* Register a virtualization driver * Handle an error at the connection level
*
* Returns the driver priority or -1 in case of error.
*/ */
int static void
virRegisterDriver(virDriverPtr driver) 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; int i;
if (!initialized) if (!initialized)
@ -155,13 +178,14 @@ virRegisterDriver(virDriverPtr driver)
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1); return(-1);
} }
drivers = isNetwork ? (void **) virNetworkDriverTab : (void **) virDriverTab;
for (i = 0;i < MAX_DRIVERS;i++) { for (i = 0;i < MAX_DRIVERS;i++) {
if (virDriverTab[i] == driver) if (drivers[i] == driver)
return(i); return(i);
} }
for (i = 0;i < MAX_DRIVERS;i++) { for (i = 0;i < MAX_DRIVERS;i++) {
if (virDriverTab[i] == NULL) { if (drivers[i] == NULL) {
virDriverTab[i] = driver; drivers[i] = driver;
return(i); return(i);
} }
} }
@ -169,6 +193,34 @@ virRegisterDriver(virDriverPtr driver)
return(-1); 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: * virGetVersion:
* @libVer: return value for the library version (OUT) * @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 */ /* we failed to find an adequate driver */
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name); virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
goto failed; goto failed;
@ -279,6 +338,10 @@ failed:
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL)) if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
ret->drivers[i]->close(ret); 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); virFreeConnect(ret);
} }
return (NULL); return (NULL);
@ -321,6 +384,10 @@ virConnectOpenReadOnly(const char *name)
ret->drivers[ret->nb_drivers++] = virDriverTab[i]; 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 (ret->nb_drivers == 0) {
if (name == NULL) if (name == NULL)
@ -341,6 +408,10 @@ failed:
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL)) if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
ret->drivers[i]->close(ret); 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); virFreeConnect(ret);
} }
return (NULL); return (NULL);
@ -368,6 +439,10 @@ virConnectClose(virConnectPtr conn)
if ((conn->drivers[i] != NULL) && (conn->drivers[i]->close != NULL)) if ((conn->drivers[i] != NULL) && (conn->drivers[i]->close != NULL))
conn->drivers[i]->close(conn); 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) if (virFreeConnect(conn) < 0)
return (-1); return (-1);
return (0); return (0);
@ -2053,3 +2128,607 @@ virDomainDetachDevice(virDomainPtr domain, char *xml)
virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__); virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
return (-1); 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);
}

View File

@ -57,5 +57,24 @@
virDomainAttachDevice; virDomainAttachDevice;
virDomainDetachDevice; virDomainDetachDevice;
virConnectNumOfNetworks;
virConnectListNetworks;
virConnectNumOfDefinedNetworks;
virConnectListDefinedNetworks;
virNetworkLookupByName;
virNetworkLookupByUUID;
virNetworkLookupByUUIDString;
virNetworkCreateXML;
virNetworkDefineXML;
virNetworkUndefine;
virNetworkCreate;
virNetworkDestroy;
virNetworkFree;
virNetworkGetName;
virNetworkGetUUID;
virNetworkGetUUIDString;
virNetworkGetXMLDesc;
local: *; local: *;
}; };

View File

@ -271,6 +271,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_QEMU: case VIR_FROM_QEMU:
dom = "QEMU "; dom = "QEMU ";
break; break;
case VIR_FROM_NET:
dom = "Network ";
break;
} }
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) { if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
domain = err->dom->name; domain = err->dom->name;
@ -585,6 +588,18 @@ __virErrorMsg(virErrorNumber error, const char *info)
else else
errmsg = "%s"; errmsg = "%s";
break; 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); return (errmsg);
} }