Hooks up the networking API methods in the qemu driver and extends the protocol to support the methods. Also, implements the protocol in qemud, but just hooks it up to driver stubs. Note, we share the connection to qemud with the qemud domains driver. Signed-off-by: Mark McLoughlin <markmc@xxxxxxxxxx> Index: libvirt-foo/qemud/dispatch.c =================================================================== --- libvirt-foo.orig/qemud/dispatch.c 2007-02-15 08:39:58.000000000 +0000 +++ libvirt-foo.orig/qemud/dispatch.c 2007-02-15 08:39:58.000000000 +0000 @@ -462,6 +462,243 @@ static int qemudDispatchDomainUndefine(s 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, }; /* Index: libvirt-foo/qemud/driver.c =================================================================== --- libvirt-foo.orig/qemud/driver.c 2007-02-15 08:39:58.000000000 +0000 +++ libvirt-foo.orig/qemud/driver.c 2007-02-15 08:39:58.000000000 +0000 @@ -545,6 +545,70 @@ int qemudDomainUndefine(struct qemud_ser 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: Index: libvirt-foo/qemud/driver.h =================================================================== --- libvirt-foo.orig/qemud/driver.h 2007-02-15 08:39:24.000000000 +0000 +++ libvirt-foo.orig/qemud/driver.h 2007-02-15 08:39:24.000000000 +0000 @@ -86,6 +86,34 @@ struct qemud_vm *qemudDomainDefine(struc 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 Index: libvirt-foo/qemud/internal.h =================================================================== --- libvirt-foo.orig/qemud/internal.h 2007-02-15 08:39:24.000000000 +0000 +++ libvirt-foo.orig/qemud/internal.h 2007-02-15 08:39:24.000000000 +0000 @@ -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; Index: libvirt-foo/qemud/protocol.h =================================================================== --- libvirt-foo.orig/qemud/protocol.h 2007-02-15 08:39:24.000000000 +0000 +++ libvirt-foo.orig/qemud/protocol.h 2007-02-15 08:39:24.000000000 +0000 @@ -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 */ Index: libvirt-foo/src/qemu_internal.c =================================================================== --- libvirt-foo.orig/src/qemu_internal.c 2007-02-15 08:39:59.000000000 +0000 +++ libvirt-foo.orig/src/qemu_internal.c 2007-02-15 08:39:59.000000000 +0000 @@ -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); + virRegisterNetworkDriver(&qemuNetworkDriver); } --