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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
lxc_mount_t *lxcMount)
|
||||
{
|
||||
@ -375,6 +556,13 @@ static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
|
||||
goto error;
|
||||
}
|
||||
|
||||
containerDef->numNets = lxcParseDomainInterfaces(conn,
|
||||
&(containerDef->nets),
|
||||
contextPtr);
|
||||
if (0 > containerDef->numNets) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (lxcParseDomainTty(conn, &(containerDef->tty), contextPtr) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@ -741,6 +929,7 @@ char *lxcGenerateXML(virConnectPtr conn,
|
||||
unsigned char *uuid;
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
lxc_mount_t *mount;
|
||||
lxc_net_def_t *net;
|
||||
|
||||
if (lxcIsActiveVM(vm))
|
||||
virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n",
|
||||
@ -770,6 +959,27 @@ char *lxcGenerateXML(virConnectPtr conn,
|
||||
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);
|
||||
virBufferAddLit(&buf, " </devices>\n");
|
||||
virBufferAddLit(&buf, "</domain>\n");
|
||||
@ -786,6 +996,8 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
|
||||
{
|
||||
lxc_mount_t *curMount;
|
||||
lxc_mount_t *nextMount;
|
||||
lxc_net_def_t *curNet;
|
||||
lxc_net_def_t *nextNet;
|
||||
|
||||
if (vmdef == NULL)
|
||||
return;
|
||||
@ -797,6 +1009,17 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
|
||||
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->init);
|
||||
VIR_FREE(vmdef->tty);
|
||||
|
@ -36,6 +36,22 @@
|
||||
#define LXC_MAX_ERROR_LEN 1024
|
||||
#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;
|
||||
struct __lxc_mount {
|
||||
char source[PATH_MAX]; /* user's directory */
|
||||
@ -61,6 +77,10 @@ struct __lxc_vm_def {
|
||||
|
||||
/* tty device */
|
||||
char *tty;
|
||||
|
||||
/* network devices */
|
||||
int numNets;
|
||||
lxc_net_def_t *nets;
|
||||
};
|
||||
|
||||
typedef struct __lxc_vm lxc_vm_t;
|
||||
|
@ -291,6 +291,13 @@ static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml)
|
||||
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))) {
|
||||
lxcFreeVMDef(def);
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user