From f391be00e9e546aee0f4fffbee0a4e97cec67a4d Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 14 Feb 2007 15:54:10 +0000 Subject: [PATCH] Tue Feb 14 15:52:34 EST 2007 Mark McLoughlin * qemud/protocol.h: add the protocol for virtual networks * qemud/dispatch.c: implement the protocol * qemud/driver.[ch]: add stubs for the driver * qemud/internal.h: add struct qemud_network * src/qemu_internal.c: add a virtual networks driver --- ChangeLog | 94 +++++++++++++- qemud/dispatch.c | 263 ++++++++++++++++++++++++++++++++++++++- qemud/driver.c | 64 ++++++++++ qemud/driver.h | 28 +++++ qemud/internal.h | 12 ++ qemud/protocol.h | 70 +++++++++++ src/qemu_internal.c | 290 +++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 813 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index eef7640e4d..345f79a54a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,86 @@ -Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin + + * qemud/protocol.h: add the protocol for virtual networks + + * qemud/dispatch.c: implement the protocol + + * qemud/driver.[ch]: add stubs for the driver + + * qemud/internal.h: add struct qemud_network + + * src/qemu_internal.c: add a virtual networks driver + +Tue Feb 14 15:43:28 EST 2007 Mark McLoughlin + + * src/virsh.c: add the net-* commands. + +Tue Feb 14 15:37:17 EST 2007 Mark McLoughlin + + Note: potential ABI break here, but people should + only really be using virError structs returned from + libvirt itself. + + * include/libvirt/virterror.h: add virNetwork + to virError + + * src/internal.h, src/virterror.c: add network param + to __virRaiseError() + + * src/conf.c, src/hash.c, src/libvirt.c, src/proxy_internal.c, + src/qemu_internal.c, src/sexpr.c, src/test.c, src/xen_internal.c, + src/xend_internal.c, src/xm_internal.c, src/xml.c, src/xmlrpc.c, + src/xs_internal.c: update. + +Tue Feb 14 15:33:05 EST 2007 Mark McLoughlin + + * 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 + + * src/conf.h: fix merge error - remove the argc argument + from qemudBuildCommandLine() + +Tue Feb 14 15:03:22 EST 2007 Mark McLoughlin + + * 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 + + * 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 + + * 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 + + * 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 * qemud/conf.c: Re-factor bits of conf.c so that: @@ -8,25 +90,25 @@ Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin * 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 * 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 * 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 * conf.[ch]: rename from config.[ch] so we can use autoconf's config.h @@ -35,7 +117,7 @@ Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin * autogen.sh: run autoheader diff --git a/qemud/dispatch.c b/qemud/dispatch.c index 13d3a263b9..195b3d85c2 100644 --- a/qemud/dispatch.c +++ b/qemud/dispatch.c @@ -462,6 +462,243 @@ static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud return 0; } +static int qemudDispatchNumNetworks(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != 0) + return -1; + + int nnetworks = qemudNumNetworks(server); + if (nnetworks < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NUM_NETWORKS; + out->header.dataSize = sizeof(out->data.numNetworksReply); + out->data.numNetworksReply.numNetworks = nnetworks; + } + return 0; +} + +static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + char **names; + int i; + if (in->header.dataSize != 0) + return -1; + + if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS))) + return -1; + + for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) { + names[i] = out->data.listNetworksReply.networks[i]; + } + + int nnetworks = qemudListNetworks(server, + names, + QEMUD_MAX_NUM_NETWORKS); + free(names); + if (nnetworks < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_LIST_NETWORKS; + out->header.dataSize = sizeof(out->data.listNetworksReply); + out->data.listNetworksReply.numNetworks = nnetworks; + } + return 0; +} + +static int qemudDispatchNumDefinedNetworks(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != 0) + return -1; + + int nnetworks = qemudNumDefinedNetworks(server); + if (nnetworks < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS; + out->header.dataSize = sizeof(out->data.numDefinedNetworksReply); + out->data.numDefinedNetworksReply.numNetworks = nnetworks; + } + return 0; +} + +static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + char **names; + int i; + if (in->header.dataSize != 0) + return -1; + + if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS))) + return -1; + + for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) { + names[i] = out->data.listDefinedNetworksReply.networks[i]; + } + + int nnetworks = qemudListDefinedNetworks(server, + names, + QEMUD_MAX_NUM_NETWORKS); + free(names); + if (nnetworks < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS; + out->header.dataSize = sizeof(out->data.listDefinedNetworksReply); + out->data.listDefinedNetworksReply.numNetworks = nnetworks; + } + return 0; +} + +static int qemudDispatchNetworkLookupByName(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkLookupByNameRequest)) + return -1; + + /* Paranoia NULL termination */ + in->data.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + struct qemud_network *network = qemudFindNetworkByName(server, in->data.networkLookupByNameRequest.name); + if (!network) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_NAME; + out->header.dataSize = sizeof(out->data.networkLookupByNameReply); + memcpy(out->data.networkLookupByNameReply.uuid, network->def.uuid, QEMUD_UUID_RAW_LEN); + } + return 0; +} + +static int qemudDispatchNetworkLookupByUUID(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkLookupByUUIDRequest)) + return -1; + + struct qemud_network *network = qemudFindNetworkByUUID(server, in->data.networkLookupByUUIDRequest.uuid); + if (!network) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID; + out->header.dataSize = sizeof(out->data.networkLookupByUUIDReply); + strncpy(out->data.networkLookupByUUIDReply.name, network->def.name, QEMUD_MAX_NAME_LEN-1); + out->data.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + } + return 0; +} + +static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkCreateRequest)) + return -1; + + in->data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0'; + + struct qemud_network *network = qemudNetworkCreate(server, in->data.networkCreateRequest.xml); + if (!network) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_CREATE; + out->header.dataSize = sizeof(out->data.networkCreateReply); + memcpy(out->data.networkCreateReply.uuid, network->def.uuid, QEMUD_UUID_RAW_LEN); + strncpy(out->data.networkCreateReply.name, network->def.name, QEMUD_MAX_NAME_LEN-1); + out->data.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + } + return 0; +} + +static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkDefineRequest)) + return -1; + + in->data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0'; + + struct qemud_network *network = qemudNetworkDefine(server, in->data.networkDefineRequest.xml); + if (!network) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_DEFINE; + out->header.dataSize = sizeof(out->data.networkDefineReply); + memcpy(out->data.networkDefineReply.uuid, network->def.uuid, QEMUD_UUID_RAW_LEN); + strncpy(out->data.networkDefineReply.name, network->def.name, QEMUD_MAX_NAME_LEN-1); + out->data.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + } + return 0; +} + +static int qemudDispatchNetworkUndefine(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkUndefineRequest)) + return -1; + + int ret = qemudNetworkUndefine(server, in->data.networkUndefineRequest.uuid); + if (ret < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_UNDEFINE; + out->header.dataSize = 0; + } + return 0; +} + +static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkStartRequest)) + return -1; + + struct qemud_network *network = qemudFindNetworkByUUID(server, in->data.networkStartRequest.uuid); + if (!network || qemudNetworkStart(server, network) < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_START; + out->header.dataSize = 0; + } + return 0; +} + +static int qemudDispatchNetworkDestroy(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkDestroyRequest)) + return -1; + + int ret = qemudNetworkDestroy(server, in->data.networkDestroyRequest.uuid); + if (ret < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_DESTROY; + out->header.dataSize = 0; + } + return 0; +} + +static int qemudDispatchNetworkDumpXML(struct qemud_server *server, struct qemud_client *client, + struct qemud_packet *in, struct qemud_packet *out) { + if (in->header.dataSize != sizeof(in->data.networkDumpXMLRequest)) + return -1; + + int ret = qemudNetworkDumpXML(server, + in->data.networkDumpXMLRequest.uuid, + out->data.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN); + if (ret < 0) { + if (qemudDispatchFailure(server, client, out) < 0) + return -1; + } else { + out->header.type = QEMUD_PKT_NETWORK_DUMP_XML; + out->header.dataSize = sizeof(out->data.networkDumpXMLReply); + } + return 0; +} + typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client, struct qemud_packet *in, struct qemud_packet *out); @@ -490,7 +727,19 @@ clientFunc funcsTransmitRW[QEMUD_PKT_MAX] = { qemudDispatchNumDefinedDomains, qemudDispatchDomainStart, qemudDispatchDomainDefine, - qemudDispatchDomainUndefine + qemudDispatchDomainUndefine, + qemudDispatchNumNetworks, + qemudDispatchListNetworks, + qemudDispatchNumDefinedNetworks, + qemudDispatchListDefinedNetworks, + qemudDispatchNetworkLookupByUUID, + qemudDispatchNetworkLookupByName, + qemudDispatchNetworkCreate, + qemudDispatchNetworkDefine, + qemudDispatchNetworkUndefine, + qemudDispatchNetworkStart, + qemudDispatchNetworkDestroy, + qemudDispatchNetworkDumpXML, }; clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = { @@ -515,6 +764,18 @@ clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = { NULL, NULL, NULL, + qemudDispatchNumNetworks, + qemudDispatchListNetworks, + qemudDispatchNumDefinedNetworks, + qemudDispatchListDefinedNetworks, + qemudDispatchNetworkLookupByUUID, + qemudDispatchNetworkLookupByName, + NULL, + NULL, + NULL, + NULL, + NULL, + qemudDispatchNetworkDumpXML, }; /* diff --git a/qemud/driver.c b/qemud/driver.c index 1ccfceb47b..9b16f3247d 100644 --- a/qemud/driver.c +++ b/qemud/driver.c @@ -545,6 +545,70 @@ int qemudDomainUndefine(struct qemud_server *server, const unsigned char *uuid) return 0; } +struct qemud_network *qemudFindNetworkByUUID(const struct qemud_server *server, + const unsigned char *uuid) { + server = NULL; uuid = NULL; + return NULL; +} + +struct qemud_network *qemudFindNetworkByName(const struct qemud_server *server, + const char *name) { + server = NULL; name = NULL; + return NULL; +} + +int qemudNumNetworks(struct qemud_server *server) { + server = NULL; + return 0; +} + +int qemudListNetworks(struct qemud_server *server, char *const*names, int nnames) { + server = NULL; names = NULL; nnames = 0; + return 0; +} + +int qemudNumDefinedNetworks(struct qemud_server *server) { + server = NULL; + return 0; +} + +int qemudListDefinedNetworks(struct qemud_server *server, char *const*names, int nnames) { + server = NULL; names = NULL; nnames = 0; + return 0; +} + +struct qemud_network *qemudNetworkCreate(struct qemud_server *server, const char *xml) { + server = NULL; xml = NULL; + return NULL; +} + +struct qemud_network *qemudNetworkDefine(struct qemud_server *server, const char *xml) { + server = NULL; xml = NULL; + return NULL; +} + +int qemudNetworkUndefine(struct qemud_server *server, const unsigned char *uuid) { + qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); + uuid = NULL; + return -1; +} + +int qemudNetworkStart(struct qemud_server *server, struct qemud_network *network) { + server = NULL; network = NULL; + return 1; +} + +int qemudNetworkDestroy(struct qemud_server *server, const unsigned char *uuid) { + uuid = NULL; + qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); + return -1; +} + +int qemudNetworkDumpXML(struct qemud_server *server, const unsigned char *uuid, char *xml, int xmllen) { + qemudReportError(server, VIR_ERR_INVALID_NETWORK, "no network with matching uuid"); + uuid = NULL; xml = NULL; xmllen = 0; + return -1; +} /* * Local variables: diff --git a/qemud/driver.h b/qemud/driver.h index 1b264c3f24..3f56bb45c1 100644 --- a/qemud/driver.h +++ b/qemud/driver.h @@ -86,6 +86,34 @@ struct qemud_vm *qemudDomainDefine(struct qemud_server *server, int qemudDomainUndefine(struct qemud_server *server, const unsigned char *uuid); +struct qemud_network *qemudFindNetworkByUUID(const struct qemud_server *server, + const unsigned char *uuid); +struct qemud_network *qemudFindNetworkByName(const struct qemud_server *server, + const char *name); + +int qemudNumNetworks(struct qemud_server *server); +int qemudListNetworks(struct qemud_server *server, + char *const*names, + int nnames); +int qemudNumDefinedNetworks(struct qemud_server *server); +int qemudListDefinedNetworks(struct qemud_server *server, + char *const*names, + int nnames); +struct qemud_network *qemudNetworkCreate(struct qemud_server *server, + const char *xml); +struct qemud_network *qemudNetworkDefine(struct qemud_server *server, + const char *xml); +int qemudNetworkUndefine(struct qemud_server *server, + const unsigned char *uuid); +int qemudNetworkStart(struct qemud_server *server, + struct qemud_network *network); +int qemudNetworkDestroy(struct qemud_server *server, + const unsigned char *uuid); +int qemudNetworkDumpXML(struct qemud_server *server, + const unsigned char *uuid, + char *xml, + int xmllen); + #endif diff --git a/qemud/internal.h b/qemud/internal.h index b308f7c887..a52d3895b3 100644 --- a/qemud/internal.h +++ b/qemud/internal.h @@ -199,6 +199,18 @@ struct qemud_vm { struct qemud_vm *next; }; +/* Virtual Network main configuration */ +struct qemud_network_def { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + char name[QEMUD_MAX_NAME_LEN]; +}; + +/* Virtual Network runtime state */ +struct qemud_network { + struct qemud_network_def def; + struct qemud_network *next; +}; + /* Stores the per-client connection state */ struct qemud_client { int fd; diff --git a/qemud/protocol.h b/qemud/protocol.h index 85392ba352..176428c91f 100644 --- a/qemud/protocol.h +++ b/qemud/protocol.h @@ -50,6 +50,18 @@ enum { QEMUD_PKT_DOMAIN_START, QEMUD_PKT_DOMAIN_DEFINE, QEMUD_PKT_DOMAIN_UNDEFINE, + QEMUD_PKT_NUM_NETWORKS, + QEMUD_PKT_LIST_NETWORKS, + QEMUD_PKT_NUM_DEFINED_NETWORKS, + QEMUD_PKT_LIST_DEFINED_NETWORKS, + QEMUD_PKT_NETWORK_LOOKUP_BY_UUID, + QEMUD_PKT_NETWORK_LOOKUP_BY_NAME, + QEMUD_PKT_NETWORK_CREATE, + QEMUD_PKT_NETWORK_DEFINE, + QEMUD_PKT_NETWORK_UNDEFINE, + QEMUD_PKT_NETWORK_START, + QEMUD_PKT_NETWORK_DESTROY, + QEMUD_PKT_NETWORK_DUMP_XML, QEMUD_PKT_MAX, } qemud_packet_type; @@ -62,6 +74,7 @@ enum { #define QEMUD_MAX_NAME_LEN 50 #define QEMUD_MAX_XML_LEN 4096 #define QEMUD_MAX_NUM_DOMAINS 100 +#define QEMUD_MAX_NUM_NETWORKS 100 #define QEMUD_MAX_ERROR_LEN 1024 /* Possible guest VM states */ @@ -200,6 +213,63 @@ union qemud_packet_data { struct { unsigned char uuid[QEMUD_UUID_RAW_LEN]; } domainUndefineRequest; + struct { + int32_t numNetworks; + } numNetworksReply; + struct { + int32_t numNetworks; + char networks[QEMUD_MAX_NUM_NETWORKS][QEMUD_MAX_NAME_LEN]; + } listNetworksReply; + struct { + int32_t numNetworks; + } numDefinedNetworksReply; + struct { + int32_t numNetworks; + char networks[QEMUD_MAX_NUM_NETWORKS][QEMUD_MAX_NAME_LEN]; + } listDefinedNetworksReply; + struct { + char name[QEMUD_MAX_NAME_LEN]; + } networkLookupByNameRequest; + struct { + int32_t id; + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkLookupByNameReply; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkLookupByUUIDRequest; + struct { + int32_t id; + char name[QEMUD_MAX_NAME_LEN]; + } networkLookupByUUIDReply; + struct { + char xml[QEMUD_MAX_XML_LEN]; + } networkCreateRequest; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + char name[QEMUD_MAX_NAME_LEN]; + } networkCreateReply; + struct { + char xml[QEMUD_MAX_XML_LEN]; + } networkDefineRequest; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + char name[QEMUD_MAX_NAME_LEN]; + } networkDefineReply; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkUndefineRequest; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkStartRequest; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkDestroyRequest; + struct { + unsigned char uuid[QEMUD_UUID_RAW_LEN]; + } networkDumpXMLRequest; + struct { + char xml[QEMUD_MAX_XML_LEN]; + } networkDumpXMLReply; }; /* Each packet has header & data */ diff --git a/src/qemu_internal.c b/src/qemu_internal.c index dce3e32441..ca82af48c6 100644 --- a/src/qemu_internal.c +++ b/src/qemu_internal.c @@ -61,7 +61,7 @@ qemuError(virConnectPtr con, return; errmsg = __virErrorMsg(error, info); - __virRaiseError(con, dom, VIR_FROM_QEMU, error, VIR_ERR_ERROR, + __virRaiseError(con, dom, NULL, VIR_FROM_QEMU, error, VIR_ERR_ERROR, errmsg, info, NULL, 0, 0, errmsg, info, 0); } @@ -806,6 +806,276 @@ static int qemuUndefine(virDomainPtr dom) { return ret; } +static int qemuNetworkOpen(virConnectPtr conn, + const char *name, + int flags) { + xmlURIPtr uri = NULL; + int ret = -1; + + if (conn->qemud_fd == -1) + return 0; + + if (name) + uri = xmlParseURI(name); + + if (uri && !strcmp(uri->scheme, "qemu")) + ret = qemuOpen(conn, name, flags); + else if (geteuid() == 0) + ret = qemuOpen(conn, "qemu:///system", flags); + else + ret = qemuOpen(conn, "qemu:///session", flags); + + if (uri) + xmlFreeURI(uri); + + return ret; +} + +static int qemuNumOfNetworks(virConnectPtr conn) { + struct qemud_packet req, reply; + + req.header.type = QEMUD_PKT_NUM_NETWORKS; + req.header.dataSize = 0; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return -1; + } + + return reply.data.numNetworksReply.numNetworks; +} + +static int qemuListNetworks(virConnectPtr conn, + const char **names, + int maxnames) { + struct qemud_packet req, reply; + int i, nNetworks; + + req.header.type = QEMUD_PKT_LIST_NETWORKS; + req.header.dataSize = 0; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return -1; + } + + nNetworks = reply.data.listNetworksReply.numNetworks; + if (nNetworks > maxnames) + return -1; + + for (i = 0 ; i < nNetworks ; i++) { + reply.data.listNetworksReply.networks[i][QEMUD_MAX_NAME_LEN-1] = '\0'; + names[i] = strdup(reply.data.listNetworksReply.networks[i]); + } + + return nNetworks; +} + +static int qemuNumOfDefinedNetworks(virConnectPtr conn) { + struct qemud_packet req, reply; + + req.header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS; + req.header.dataSize = 0; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return -1; + } + + return reply.data.numDefinedNetworksReply.numNetworks; +} + +static int qemuListDefinedNetworks(virConnectPtr conn, + const char **names, + int maxnames) { + struct qemud_packet req, reply; + int i, nNetworks; + + req.header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS; + req.header.dataSize = 0; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return -1; + } + + nNetworks = reply.data.listDefinedNetworksReply.numNetworks; + if (nNetworks > maxnames) + return -1; + + for (i = 0 ; i < nNetworks ; i++) { + reply.data.listDefinedNetworksReply.networks[i][QEMUD_MAX_NAME_LEN-1] = '\0'; + names[i] = strdup(reply.data.listDefinedNetworksReply.networks[i]); + } + + return nNetworks; +} + +static virNetworkPtr qemuNetworkLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) { + struct qemud_packet req, reply; + virNetworkPtr network; + + req.header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID; + req.header.dataSize = sizeof(req.data.networkLookupByUUIDRequest); + memmove(req.data.networkLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN); + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return NULL; + } + + reply.data.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + + if (!(network = virGetNetwork(conn, + reply.data.networkLookupByUUIDReply.name, + uuid))) + return NULL; + + return network; +} + +static virNetworkPtr qemuNetworkLookupByName(virConnectPtr conn, + const char *name) { + struct qemud_packet req, reply; + virNetworkPtr network; + + if (strlen(name) > (QEMUD_MAX_NAME_LEN-1)) + return NULL; + + req.header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_NAME; + req.header.dataSize = sizeof(req.data.networkLookupByNameRequest); + strcpy(req.data.networkLookupByNameRequest.name, name); + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return NULL; + } + + if (!(network = virGetNetwork(conn, + name, + reply.data.networkLookupByNameReply.uuid))) + return NULL; + + return network; +} + +static virNetworkPtr qemuNetworkCreateXML(virConnectPtr conn, + const char *xmlDesc) { + struct qemud_packet req, reply; + virNetworkPtr network; + int len = strlen(xmlDesc); + + if (len > (QEMUD_MAX_XML_LEN-1)) { + return NULL; + } + + req.header.type = QEMUD_PKT_NETWORK_CREATE; + req.header.dataSize = sizeof(req.data.networkCreateRequest); + strcpy(req.data.networkCreateRequest.xml, xmlDesc); + req.data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0'; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return NULL; + } + + reply.data.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + + if (!(network = virGetNetwork(conn, + reply.data.networkCreateReply.name, + reply.data.networkCreateReply.uuid))) + return NULL; + + return network; +} + + +static virNetworkPtr qemuNetworkDefineXML(virConnectPtr conn, + const char *xml) { + struct qemud_packet req, reply; + virNetworkPtr network; + int len = strlen(xml); + + if (len > (QEMUD_MAX_XML_LEN-1)) { + return NULL; + } + + req.header.type = QEMUD_PKT_NETWORK_DEFINE; + req.header.dataSize = sizeof(req.data.networkDefineRequest); + strcpy(req.data.networkDefineRequest.xml, xml); + req.data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0'; + + if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) { + return NULL; + } + + reply.data.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0'; + + if (!(network = virGetNetwork(conn, + reply.data.networkDefineReply.name, + reply.data.networkDefineReply.uuid))) + return NULL; + + return network; +} + +static int qemuNetworkUndefine(virNetworkPtr network) { + struct qemud_packet req, reply; + int ret = 0; + + req.header.type = QEMUD_PKT_NETWORK_UNDEFINE; + req.header.dataSize = sizeof(req.data.networkUndefineRequest); + memcpy(req.data.networkUndefineRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN); + + if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) { + ret = -1; + goto cleanup; + } + + cleanup: + if (virFreeNetwork(network->conn, network) < 0) + ret = -1; + + return ret; +} + +static int qemuNetworkCreate(virNetworkPtr network) { + struct qemud_packet req, reply; + + req.header.type = QEMUD_PKT_NETWORK_START; + req.header.dataSize = sizeof(req.data.networkStartRequest); + memcpy(req.data.networkStartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN); + + if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) { + return -1; + } + + return 0; +} + +static int qemuNetworkDestroy(virNetworkPtr network) { + struct qemud_packet req, reply; + + req.header.type = QEMUD_PKT_NETWORK_DESTROY; + req.header.dataSize = sizeof(req.data.networkDestroyRequest); + memcpy(req.data.networkDestroyRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN); + + if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) { + return -1; + } + + return 0; +} + +static char * qemuNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { + struct qemud_packet req, reply; + + req.header.type = QEMUD_PKT_NETWORK_DUMP_XML; + req.header.dataSize = sizeof(req.data.networkDumpXMLRequest); + memmove(req.data.networkDumpXMLRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN); + + if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) { + return NULL; + } + + reply.data.networkDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0'; + + return strdup(reply.data.networkDumpXMLReply.xml); +} static virDriver qemuDriver = { VIR_DRV_QEMU, @@ -849,8 +1119,26 @@ static virDriver qemuDriver = { NULL, /* domainDetachDevice */ }; +static virNetworkDriver qemuNetworkDriver = { + qemuNetworkOpen, /* open */ + qemuClose, /* close */ + qemuNumOfNetworks, /* numOfNetworks */ + qemuListNetworks, /* listNetworks */ + qemuNumOfDefinedNetworks, /* numOfDefinedNetworks */ + qemuListDefinedNetworks, /* listDefinedNetworks */ + qemuNetworkLookupByUUID, /* networkLookupByUUID */ + qemuNetworkLookupByName, /* networkLookupByName */ + qemuNetworkCreateXML , /* networkCreateXML */ + qemuNetworkDefineXML , /* networkDefineXML */ + qemuNetworkUndefine, /* networkUndefine */ + qemuNetworkCreate, /* networkCreate */ + qemuNetworkDestroy, /* networkDestroy */ + qemuNetworkDumpXML, /* networkDumpXML */ +}; + void qemuRegister(void) { virRegisterDriver(&qemuDriver); + virRegisterDriver(&qemuNetworkDriver); }