mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
[LXC] Add XML parsing of container network interfaces.
This commit is contained in:
parent
e59eb52fad
commit
97e1fc3734
223
src/lxc_conf.c
223
src/lxc_conf.c
@ -71,6 +71,187 @@ void lxcError(virConnectPtr conn, virDomainPtr dom, int code,
|
|||||||
codeErrorMessage, errorMessage);
|
codeErrorMessage, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lxcParseInterfaceXML:
|
||||||
|
* @conn: pointer to connection
|
||||||
|
* @nodePtr: pointer to xml node structure
|
||||||
|
* @vm: pointer to net definition structure to fill in
|
||||||
|
*
|
||||||
|
* Parses the XML for a network interface and places the configuration
|
||||||
|
* in the given structure.
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int lxcParseInterfaceXML(virConnectPtr conn, xmlNodePtr nodePtr,
|
||||||
|
lxc_net_def_t *netDef)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
xmlNodePtr cur;
|
||||||
|
xmlChar *type = NULL;
|
||||||
|
xmlChar *parentIfName = NULL;
|
||||||
|
xmlChar *network = NULL;
|
||||||
|
xmlChar *bridge = NULL;
|
||||||
|
xmlChar *macaddr = NULL;
|
||||||
|
|
||||||
|
netDef->type = LXC_NET_NETWORK;
|
||||||
|
|
||||||
|
type = xmlGetProp(nodePtr, BAD_CAST "type");
|
||||||
|
if (type != NULL) {
|
||||||
|
if (xmlStrEqual(type, BAD_CAST "network")) {
|
||||||
|
netDef->type = LXC_NET_NETWORK;
|
||||||
|
}
|
||||||
|
else if (xmlStrEqual(type, BAD_CAST "bridge")) {
|
||||||
|
netDef->type = LXC_NET_BRIDGE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_XML_ERROR,
|
||||||
|
_("invalid interface type: %s"), type);
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = nodePtr->children;
|
||||||
|
for (cur = nodePtr->children; cur != NULL; cur = cur->next) {
|
||||||
|
if (cur->type == XML_ELEMENT_NODE) {
|
||||||
|
DEBUG("cur->name: %s", (char*)(cur->name));
|
||||||
|
if ((macaddr == NULL) &&
|
||||||
|
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
|
||||||
|
macaddr = xmlGetProp(cur, BAD_CAST "address");
|
||||||
|
} else if ((network == NULL) &&
|
||||||
|
(netDef->type == LXC_NET_NETWORK) &&
|
||||||
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
|
network = xmlGetProp(cur, BAD_CAST "network");
|
||||||
|
parentIfName = xmlGetProp(cur, BAD_CAST "dev");
|
||||||
|
} else if ((bridge == NULL) &&
|
||||||
|
(netDef->type == LXC_NET_BRIDGE) &&
|
||||||
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
|
bridge = xmlGetProp(cur, BAD_CAST "bridge");
|
||||||
|
} else if ((parentIfName == NULL) &&
|
||||||
|
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
|
||||||
|
parentIfName = xmlGetProp(cur, BAD_CAST "dev");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netDef->type == LXC_NET_NETWORK) {
|
||||||
|
if (network == NULL) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_XML_ERROR,
|
||||||
|
_("No <source> 'network' attribute specified with <interface type='network'/>"));
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
netDef->txName = strdup((char *)network);
|
||||||
|
if (NULL == netDef->txName) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_NO_MEMORY,
|
||||||
|
_("No storage for network name"));
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (netDef->type == LXC_NET_BRIDGE) {
|
||||||
|
if (bridge == NULL) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_XML_ERROR,
|
||||||
|
_("No <source> 'bridge' attribute specified with <interface type='bridge'/>"));
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
netDef->txName = strdup((char *)bridge);
|
||||||
|
if (NULL == netDef->txName) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_NO_MEMORY,
|
||||||
|
_("No storage for bridge name"));
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentIfName != NULL) {
|
||||||
|
DEBUG("set netDef->parentVeth: %s", netDef->parentVeth);
|
||||||
|
netDef->parentVeth = strdup((char *)parentIfName);
|
||||||
|
if (NULL == netDef->parentVeth) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_NO_MEMORY,
|
||||||
|
_("No storage for parent veth device name"));
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
netDef->parentVeth = NULL;
|
||||||
|
DEBUG0("set netDef->parentVeth: NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
error_out:
|
||||||
|
xmlFree(macaddr);
|
||||||
|
xmlFree(network);
|
||||||
|
xmlFree(bridge);
|
||||||
|
xmlFree(parentIfName);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lxcParseDomainInterfaces:
|
||||||
|
* @conn: pointer to connection
|
||||||
|
* @nets: on success, points to an list of net def structs
|
||||||
|
* @contextPtr: pointer to xml context
|
||||||
|
*
|
||||||
|
* Parses the domain network interfaces and returns the information in a list
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int lxcParseDomainInterfaces(virConnectPtr conn,
|
||||||
|
lxc_net_def_t **nets,
|
||||||
|
xmlXPathContextPtr contextPtr)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
int i;
|
||||||
|
lxc_net_def_t *netDef;
|
||||||
|
lxc_net_def_t *prevDef = NULL;
|
||||||
|
int numNets = 0;
|
||||||
|
xmlNodePtr *list;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
DEBUG0("parsing nets");
|
||||||
|
|
||||||
|
res = virXPathNodeSet("/domain/devices/interface", contextPtr, &list);
|
||||||
|
if (res > 0) {
|
||||||
|
for (i = 0; i < res; ++i) {
|
||||||
|
netDef = calloc(1, sizeof(lxc_net_def_t));
|
||||||
|
if (NULL == netDef) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_NO_MEMORY,
|
||||||
|
_("No storage for net def structure"));
|
||||||
|
free(list);
|
||||||
|
goto parse_complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = lxcParseInterfaceXML(conn, list[i], netDef);
|
||||||
|
if (0 > rc) {
|
||||||
|
DEBUG("failed parsing a net: %d", rc);
|
||||||
|
|
||||||
|
free(netDef);
|
||||||
|
free(list);
|
||||||
|
goto parse_complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG0("parsed a net");
|
||||||
|
|
||||||
|
/* set the linked list pointers */
|
||||||
|
numNets++;
|
||||||
|
netDef->next = NULL;
|
||||||
|
if (0 == i) {
|
||||||
|
*nets = netDef;
|
||||||
|
} else {
|
||||||
|
prevDef->next = netDef;
|
||||||
|
}
|
||||||
|
prevDef = netDef;
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = numNets;
|
||||||
|
|
||||||
|
parse_complete:
|
||||||
|
DEBUG("parsed %d nets", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr,
|
static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr,
|
||||||
lxc_mount_t *lxcMount)
|
lxc_mount_t *lxcMount)
|
||||||
{
|
{
|
||||||
@ -375,6 +556,13 @@ static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
containerDef->numNets = lxcParseDomainInterfaces(conn,
|
||||||
|
&(containerDef->nets),
|
||||||
|
contextPtr);
|
||||||
|
if (0 > containerDef->numNets) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (lxcParseDomainTty(conn, &(containerDef->tty), contextPtr) < 0) {
|
if (lxcParseDomainTty(conn, &(containerDef->tty), contextPtr) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -741,6 +929,7 @@ char *lxcGenerateXML(virConnectPtr conn,
|
|||||||
unsigned char *uuid;
|
unsigned char *uuid;
|
||||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
lxc_mount_t *mount;
|
lxc_mount_t *mount;
|
||||||
|
lxc_net_def_t *net;
|
||||||
|
|
||||||
if (lxcIsActiveVM(vm))
|
if (lxcIsActiveVM(vm))
|
||||||
virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n",
|
virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n",
|
||||||
@ -770,6 +959,27 @@ char *lxcGenerateXML(virConnectPtr conn,
|
|||||||
virBufferAddLit(&buf, " </filesystem>\n");
|
virBufferAddLit(&buf, " </filesystem>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* loop adding nets */
|
||||||
|
for (net = def->nets; net; net = net->next) {
|
||||||
|
if (net->type == LXC_NET_NETWORK) {
|
||||||
|
virBufferAddLit(&buf, " <interface type='network'>\n");
|
||||||
|
virBufferVSprintf(&buf, " <source network='%s'/>\n",
|
||||||
|
net->txName);
|
||||||
|
} else {
|
||||||
|
virBufferAddLit(&buf, " <interface type='bridge'>\n");
|
||||||
|
virBufferVSprintf(&buf, " <source bridge='%s'/>\n",
|
||||||
|
net->txName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != net->parentVeth) {
|
||||||
|
virBufferVSprintf(&buf, " <target dev='%s'/>\n",
|
||||||
|
net->parentVeth);
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAddLit(&buf, " </interface>\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virBufferVSprintf(&buf, " <console tty='%s'/>\n", def->tty);
|
virBufferVSprintf(&buf, " <console tty='%s'/>\n", def->tty);
|
||||||
virBufferAddLit(&buf, " </devices>\n");
|
virBufferAddLit(&buf, " </devices>\n");
|
||||||
virBufferAddLit(&buf, "</domain>\n");
|
virBufferAddLit(&buf, "</domain>\n");
|
||||||
@ -786,6 +996,8 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
|
|||||||
{
|
{
|
||||||
lxc_mount_t *curMount;
|
lxc_mount_t *curMount;
|
||||||
lxc_mount_t *nextMount;
|
lxc_mount_t *nextMount;
|
||||||
|
lxc_net_def_t *curNet;
|
||||||
|
lxc_net_def_t *nextNet;
|
||||||
|
|
||||||
if (vmdef == NULL)
|
if (vmdef == NULL)
|
||||||
return;
|
return;
|
||||||
@ -797,6 +1009,17 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
|
|||||||
curMount = nextMount;
|
curMount = nextMount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curNet = vmdef->nets;
|
||||||
|
while (curNet) {
|
||||||
|
nextNet = curNet->next;
|
||||||
|
printf("Freeing %s:%s\n", curNet->parentVeth, curNet->containerVeth);
|
||||||
|
VIR_FREE(curNet->parentVeth);
|
||||||
|
VIR_FREE(curNet->containerVeth);
|
||||||
|
VIR_FREE(curNet->txName);
|
||||||
|
VIR_FREE(curNet);
|
||||||
|
curNet = nextNet;
|
||||||
|
}
|
||||||
|
|
||||||
VIR_FREE(vmdef->name);
|
VIR_FREE(vmdef->name);
|
||||||
VIR_FREE(vmdef->init);
|
VIR_FREE(vmdef->init);
|
||||||
VIR_FREE(vmdef->tty);
|
VIR_FREE(vmdef->tty);
|
||||||
|
@ -36,6 +36,22 @@
|
|||||||
#define LXC_MAX_ERROR_LEN 1024
|
#define LXC_MAX_ERROR_LEN 1024
|
||||||
#define LXC_DOMAIN_TYPE "lxc"
|
#define LXC_DOMAIN_TYPE "lxc"
|
||||||
|
|
||||||
|
/* types of networks for containers */
|
||||||
|
enum lxc_net_type {
|
||||||
|
LXC_NET_NETWORK,
|
||||||
|
LXC_NET_BRIDGE
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct __lxc_net_def lxc_net_def_t;
|
||||||
|
struct __lxc_net_def {
|
||||||
|
int type;
|
||||||
|
char *parentVeth; /* veth device in parent namespace */
|
||||||
|
char *containerVeth; /* veth device in container namespace */
|
||||||
|
char *txName; /* bridge or network name */
|
||||||
|
|
||||||
|
lxc_net_def_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct __lxc_mount lxc_mount_t;
|
typedef struct __lxc_mount lxc_mount_t;
|
||||||
struct __lxc_mount {
|
struct __lxc_mount {
|
||||||
char source[PATH_MAX]; /* user's directory */
|
char source[PATH_MAX]; /* user's directory */
|
||||||
@ -61,6 +77,10 @@ struct __lxc_vm_def {
|
|||||||
|
|
||||||
/* tty device */
|
/* tty device */
|
||||||
char *tty;
|
char *tty;
|
||||||
|
|
||||||
|
/* network devices */
|
||||||
|
int numNets;
|
||||||
|
lxc_net_def_t *nets;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct __lxc_vm lxc_vm_t;
|
typedef struct __lxc_vm lxc_vm_t;
|
||||||
|
@ -291,6 +291,13 @@ static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((def->nets != NULL) && !(driver->have_netns)) {
|
||||||
|
lxcError(conn, NULL, VIR_ERR_NO_SUPPORT,
|
||||||
|
_("System lacks NETNS support"));
|
||||||
|
lxcFreeVMDef(def);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(vm = lxcAssignVMDef(conn, driver, def))) {
|
if (!(vm = lxcAssignVMDef(conn, driver, def))) {
|
||||||
lxcFreeVMDef(def);
|
lxcFreeVMDef(def);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user