mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
add/change/delete a Disk/NIC of an inactive domains
* src/xm_internal.[ch]: applied patch from Shigeki Sakamoto to add/change/delete a Disk/NIC of an inactive domains Daniel
This commit is contained in:
parent
eecd68364a
commit
594af3eb22
@ -1,3 +1,8 @@
|
||||
Wed Feb 6 18:55:37 CET 2008 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* src/xm_internal.[ch]: applied patch from Shigeki Sakamoto to
|
||||
add/change/delete a Disk/NIC of an inactive domains
|
||||
|
||||
Wed Feb 6 17:22:34 CET 2008 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* src/qemu_conf.c: applied 2 patches from Guido Guenther to avoid
|
||||
|
@ -72,6 +72,12 @@ static virHashTablePtr nameConfigMap = NULL;
|
||||
static int nconnections = 0;
|
||||
static time_t lastRefresh = 0;
|
||||
|
||||
char * xenXMAutoAssignMac(void);
|
||||
static int xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
|
||||
xmlNodePtr node, xenXMConfCachePtr entry);
|
||||
static int xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
|
||||
xmlNodePtr node, xenXMConfCachePtr entry);
|
||||
|
||||
#define XM_REFRESH_INTERVAL 10
|
||||
|
||||
#define XM_CONFIG_DIR "/etc/xen"
|
||||
@ -79,6 +85,7 @@ static time_t lastRefresh = 0;
|
||||
#define XEND_CONFIG_FILE "xend-config.sxp"
|
||||
#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
|
||||
#define QEMU_IF_SCRIPT "qemu-ifup"
|
||||
#define XM_XML_ERROR "Invalid xml"
|
||||
|
||||
struct xenUnifiedDriver xenXMDriver = {
|
||||
xenXMOpen, /* open */
|
||||
@ -113,8 +120,8 @@ struct xenUnifiedDriver xenXMDriver = {
|
||||
xenXMDomainCreate, /* domainCreate */
|
||||
xenXMDomainDefineXML, /* domainDefineXML */
|
||||
xenXMDomainUndefine, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
xenXMDomainAttachDevice, /* domainAttachDevice */
|
||||
xenXMDomainDetachDevice, /* domainDetachDevice */
|
||||
NULL, /* domainGetAutostart */
|
||||
NULL, /* domainSetAutostart */
|
||||
NULL, /* domainGetSchedulerType */
|
||||
@ -2515,6 +2522,635 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
|
||||
return virHashSize(nameConfigMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* xenXMDomainAttachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of device
|
||||
*
|
||||
* Create a virtual device attachment to backend.
|
||||
* XML description is translated into config file.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
static int
|
||||
xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
|
||||
const char *filename = NULL;
|
||||
xenXMConfCachePtr entry = NULL;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr node = NULL;
|
||||
xmlXPathContextPtr ctxt = NULL;
|
||||
xmlXPathObjectPtr obj = NULL;
|
||||
char *domxml = NULL;
|
||||
int ret = -1, hvm = 0;
|
||||
|
||||
if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
|
||||
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
||||
__FUNCTION__);
|
||||
goto cleanup;
|
||||
}
|
||||
if (domain->conn->flags & VIR_CONNECT_RO)
|
||||
goto cleanup;
|
||||
if (domain->id != -1)
|
||||
goto cleanup;
|
||||
if (!(filename = virHashLookup(nameConfigMap, domain->name)))
|
||||
goto cleanup;
|
||||
if (!(entry = virHashLookup(configCache, filename)))
|
||||
goto cleanup;
|
||||
if (!(entry->conf))
|
||||
goto cleanup;
|
||||
|
||||
if (!(domxml = xenXMDomainDumpXML(domain, 0)))
|
||||
goto cleanup;
|
||||
|
||||
doc = xmlReadDoc((const xmlChar *) domxml, "domain.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (!doc) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "cannot read XML domain definition");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(ctxt = xmlXPathNewContext(doc))) {
|
||||
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot create XPath context");
|
||||
goto cleanup;
|
||||
}
|
||||
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt);
|
||||
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
||||
(obj->stringval) && (STREQ((char *)obj->stringval, "hvm")))
|
||||
hvm = 1;
|
||||
|
||||
if (ctxt)
|
||||
xmlXPathFreeContext(ctxt);
|
||||
ctxt = NULL;
|
||||
if (doc)
|
||||
xmlFreeDoc(doc);
|
||||
doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (!doc) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR,
|
||||
"cannot read XML domain definition");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(ctxt = xmlXPathNewContext(doc))) {
|
||||
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"cannot create XPath context");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((node = virXPathNode("/disk", ctxt))) {
|
||||
if (xenXMAttachDisk(domain, ctxt, hvm, node, entry))
|
||||
goto cleanup;
|
||||
} else if ((node = virXPathNode("/interface", ctxt))) {
|
||||
if (xenXMAttachInterface(domain, ctxt, hvm, node, entry))
|
||||
goto cleanup;
|
||||
} else {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "unknown device");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* If this fails, should we try to undo our changes to the
|
||||
* in-memory representation of the config file. I say not!
|
||||
*/
|
||||
if (virConfWriteFile(entry->filename, entry->conf) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (domxml)
|
||||
free(domxml);
|
||||
if (obj)
|
||||
xmlXPathFreeObject(obj);
|
||||
if (ctxt)
|
||||
xmlXPathFreeContext(ctxt);
|
||||
if (doc)
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
|
||||
xmlNodePtr node, xenXMConfCachePtr entry) {
|
||||
virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL;
|
||||
xenUnifiedPrivatePtr priv = NULL;
|
||||
xmlChar *type = NULL, *source = NULL, *target = NULL;
|
||||
int ret = -1;
|
||||
char *dev;
|
||||
|
||||
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
|
||||
xenXMParseXMLDisk(node, hvm, ((xenUnifiedPrivatePtr) domain->conn->privateData)->xendConfigVersion, &dev);
|
||||
if (!dev)
|
||||
goto cleanup;
|
||||
|
||||
if (!(type = xmlGetProp(node, BAD_CAST "type"))) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(node = virXPathNode("/disk/source", ctxt))) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!strcmp((const char *) type, "block"))
|
||||
source = xmlGetProp(node, BAD_CAST "dev");
|
||||
else if (!strcmp((const char *) type, "file"))
|
||||
source = xmlGetProp(node, BAD_CAST "file");
|
||||
else {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(node = virXPathNode("/disk/target", ctxt))) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
target = xmlGetProp(node, BAD_CAST "dev");
|
||||
|
||||
list_item = virConfGetValue(entry->conf, "disk");
|
||||
if (list_item && list_item->type == VIR_CONF_LIST) {
|
||||
prev = list_item;
|
||||
list_val = list_item->list;
|
||||
while (list_val) {
|
||||
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
|
||||
goto skip;
|
||||
char domdev[NAME_MAX];
|
||||
char *head;
|
||||
char *offset;
|
||||
char *tmp;
|
||||
|
||||
head = list_val->str;
|
||||
|
||||
/* Extract the source */
|
||||
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
|
||||
goto skip;
|
||||
if ((offset - head) >= (PATH_MAX-1))
|
||||
goto skip;
|
||||
head = offset + 1;
|
||||
|
||||
/* Extract the dest */
|
||||
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
|
||||
goto skip;
|
||||
if ((offset - head) >= (PATH_MAX-1))
|
||||
goto skip;
|
||||
strncpy(domdev, head, (offset - head));
|
||||
domdev[(offset-head)] = '\0';
|
||||
head = offset + 1;
|
||||
|
||||
/* Remove legacy ioemu: junk */
|
||||
if (!strncmp(domdev, "ioemu:", 6)) {
|
||||
memmove(domdev, domdev+6, strlen(domdev)-5);
|
||||
}
|
||||
|
||||
/* Check for a :cdrom/:disk postfix */
|
||||
if ((tmp = strchr(domdev, ':')))
|
||||
tmp[0] = '\0';
|
||||
|
||||
if (!(strcmp(domdev, (const char *) target)))
|
||||
break;
|
||||
skip:
|
||||
prev = list_val;
|
||||
list_val = list_val->next;
|
||||
}
|
||||
} else if (!list_item) {
|
||||
if (!(list_item = calloc(1, sizeof(virConfValue))))
|
||||
goto cleanup;
|
||||
list_item->type = VIR_CONF_LIST;
|
||||
if(virConfSetValue(entry->conf, "disk", list_item)) {
|
||||
free(list_item);
|
||||
goto cleanup;
|
||||
}
|
||||
list_val = NULL;
|
||||
prev = list_item;
|
||||
} else
|
||||
goto cleanup;
|
||||
|
||||
if (!list_val) {
|
||||
/* insert */
|
||||
if (!(list_val = malloc(sizeof(virConfValue))))
|
||||
goto cleanup;
|
||||
list_val->type = VIR_CONF_STRING;
|
||||
list_val->next = NULL;
|
||||
list_val->str = dev;
|
||||
if (prev->type == VIR_CONF_LIST)
|
||||
prev->list = list_val;
|
||||
else
|
||||
prev->next = list_val;
|
||||
} else {
|
||||
/* configure */
|
||||
if (list_val->str)
|
||||
free(list_val->str);
|
||||
list_val->str = dev;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (type)
|
||||
free(type);
|
||||
if (source)
|
||||
free(source);
|
||||
if (target)
|
||||
free(target);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
|
||||
xmlNodePtr node, xenXMConfCachePtr entry) {
|
||||
virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL;
|
||||
xmlChar *type = NULL, *source = NULL, *mac = NULL;
|
||||
int ret = -1, autoassign = 0;
|
||||
char *dev;
|
||||
|
||||
xmlNodePtr node_cur = NULL, node_tmp = NULL;
|
||||
xmlAttrPtr attr_node = NULL;
|
||||
xmlNodePtr text_node = NULL;
|
||||
|
||||
if(!(type = xmlGetProp(node, BAD_CAST "type"))) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(node = virXPathNode("/interface/source", ctxt))) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
source = xmlGetProp(node, BAD_CAST type);
|
||||
|
||||
if (!(node = virXPathNode("/interface/mac", ctxt))) {
|
||||
if (!(mac = (xmlChar *)xenXMAutoAssignMac()))
|
||||
goto cleanup;
|
||||
autoassign = 1;
|
||||
} else
|
||||
mac = xmlGetProp(node, BAD_CAST "address");
|
||||
|
||||
list_item = virConfGetValue(entry->conf, "vif");
|
||||
if (list_item && list_item->type == VIR_CONF_LIST) {
|
||||
prev = list_item;
|
||||
list_val = list_item->list;
|
||||
while (list_val) {
|
||||
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
|
||||
goto skip;
|
||||
char dommac[18];
|
||||
char *key;
|
||||
|
||||
dommac[0] = '\0';
|
||||
|
||||
key = list_val->str;
|
||||
while (key) {
|
||||
char *data;
|
||||
char *nextkey = strchr(key, ',');
|
||||
|
||||
if (!(data = strchr(key, '=')) || (data[0] == '\0'))
|
||||
goto skip;
|
||||
data++;
|
||||
|
||||
if (!strncmp(key, "mac=", 4)) {
|
||||
int len = nextkey ? (nextkey - data) : 17;
|
||||
if (len > 17)
|
||||
len = 17;
|
||||
strncpy(dommac, data, len);
|
||||
dommac[len] = '\0';
|
||||
}
|
||||
|
||||
while (nextkey && (nextkey[0] == ',' ||
|
||||
nextkey[0] == ' ' ||
|
||||
nextkey[0] == '\t'))
|
||||
nextkey++;
|
||||
key = nextkey;
|
||||
}
|
||||
|
||||
if (!(strcmp(dommac, (const char *) mac))) {
|
||||
if (autoassign) {
|
||||
if (mac)
|
||||
free(mac);
|
||||
mac = NULL;
|
||||
if (!(mac = (xmlChar *)xenXMAutoAssignMac()))
|
||||
goto cleanup;
|
||||
/* initialize the list */
|
||||
list_item = virConfGetValue(entry->conf, "vif");
|
||||
prev = list_item;
|
||||
list_val = list_item->list;
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
skip:
|
||||
prev = list_val;
|
||||
list_val = list_val->next;
|
||||
}
|
||||
} else if (!list_item) {
|
||||
if (!(list_item = calloc(1, sizeof(virConfValue))))
|
||||
goto cleanup;
|
||||
list_item->type = VIR_CONF_LIST;
|
||||
if(virConfSetValue(entry->conf, "vif", list_item)) {
|
||||
free(list_item);
|
||||
goto cleanup;
|
||||
}
|
||||
list_val = NULL;
|
||||
prev = list_item;
|
||||
} else
|
||||
goto cleanup;
|
||||
|
||||
if ((node = virXPathNode("/interface", ctxt))) {
|
||||
if (autoassign) {
|
||||
node_cur = node->children;
|
||||
|
||||
while (node_cur->next)
|
||||
node_cur = node_cur->next;
|
||||
|
||||
if (!(node_tmp = calloc(1, sizeof(xmlNode))))
|
||||
goto node_cleanup;
|
||||
node_tmp->type = XML_ELEMENT_NODE;
|
||||
if (!(node_tmp->name = malloc(4)))
|
||||
goto node_cleanup;
|
||||
strcpy((char *)node_tmp->name, "mac");
|
||||
node_tmp->children = NULL;
|
||||
|
||||
if (!(attr_node = calloc(1, sizeof(xmlAttr))))
|
||||
goto node_cleanup;
|
||||
attr_node->type = XML_ATTRIBUTE_NODE;
|
||||
attr_node->ns = NULL;
|
||||
if (!(attr_node->name = malloc(8)))
|
||||
goto node_cleanup;
|
||||
strcpy((char *) attr_node->name, "address");
|
||||
node_tmp->properties = attr_node;
|
||||
|
||||
if (!(text_node = calloc(1, sizeof(xmlNode))))
|
||||
goto node_cleanup;
|
||||
text_node->type = XML_TEXT_NODE;
|
||||
text_node->_private = NULL;
|
||||
if (!(text_node->name = malloc(8)))
|
||||
goto node_cleanup;
|
||||
strcpy((char *) text_node->name, "text");
|
||||
text_node->children = NULL;
|
||||
text_node->parent = (xmlNodePtr)attr_node;
|
||||
text_node->content = mac;
|
||||
mac = NULL;
|
||||
attr_node->children = text_node;
|
||||
attr_node->last = text_node;
|
||||
attr_node->parent = node_tmp;
|
||||
|
||||
node_cur->next = node_tmp;
|
||||
}
|
||||
if (!(dev = xenXMParseXMLVif(domain->conn, node, hvm)))
|
||||
goto cleanup;
|
||||
} else
|
||||
goto cleanup;
|
||||
|
||||
if (!list_val) {
|
||||
/* insert */
|
||||
if (!(list_val = malloc(sizeof(virConfValue))))
|
||||
goto cleanup;
|
||||
list_val->type = VIR_CONF_STRING;
|
||||
list_val->next = NULL;
|
||||
list_val->str = dev;
|
||||
if (prev->type == VIR_CONF_LIST)
|
||||
prev->list = list_val;
|
||||
else
|
||||
prev->next = list_val;
|
||||
} else {
|
||||
/* configure */
|
||||
if (list_val->str)
|
||||
free(list_val->str);
|
||||
list_val->str = dev;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
node_cleanup:
|
||||
if (node_tmp)
|
||||
xmlFree(node_tmp);
|
||||
if (attr_node)
|
||||
xmlFree(attr_node);
|
||||
if (text_node)
|
||||
xmlFree(text_node);
|
||||
cleanup:
|
||||
if (type)
|
||||
free(type);
|
||||
if (source)
|
||||
free(source);
|
||||
if (mac)
|
||||
free(mac);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xenXMAutoAssignMac:
|
||||
* @mac: pointer to Mac String
|
||||
*
|
||||
* a mac is assigned automatically.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
char *
|
||||
xenXMAutoAssignMac() {
|
||||
char *buf;
|
||||
|
||||
if (!(buf = malloc(18)))
|
||||
return 0;
|
||||
srand((unsigned)time(NULL));
|
||||
sprintf(buf, "00:16:3e:%02x:%02x:%02x"
|
||||
,1 + (int)(256*(rand()/(RAND_MAX+1.0)))
|
||||
,1 + (int)(256*(rand()/(RAND_MAX+1.0)))
|
||||
,1 + (int)(256*(rand()/(RAND_MAX+1.0))));
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* xenXMDomainDetachDevice:
|
||||
* @domain: pointer to domain object
|
||||
* @xml: pointer to XML description of device
|
||||
*
|
||||
* Destroy a virtual device attachment to backend.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure.
|
||||
*/
|
||||
static int
|
||||
xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
|
||||
const char *filename = NULL;
|
||||
char device[8], *domdevice = NULL;
|
||||
xenXMConfCachePtr entry = NULL;
|
||||
virConfValuePtr prev = NULL, list_ptr = NULL, list_val = NULL;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr node = NULL;
|
||||
xmlXPathContextPtr ctxt = NULL;
|
||||
xmlChar *key = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
|
||||
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
||||
__FUNCTION__);
|
||||
goto cleanup;
|
||||
}
|
||||
if (domain->conn->flags & VIR_CONNECT_RO)
|
||||
goto cleanup;
|
||||
if (domain->id != -1)
|
||||
goto cleanup;
|
||||
if (!(filename = virHashLookup(nameConfigMap, domain->name)))
|
||||
goto cleanup;
|
||||
|
||||
doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (!doc) {
|
||||
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "cannot read XML domain definition");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(ctxt = xmlXPathNewContext(doc))) {
|
||||
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot create XPath context");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((node = virXPathNode("/disk", ctxt))) {
|
||||
strcpy(device, "disk");
|
||||
if (!(node = virXPathNode("/disk/target", ctxt)))
|
||||
goto cleanup;
|
||||
key = xmlGetProp(node, BAD_CAST "dev");
|
||||
} else if ((node = virXPathNode("/interface", ctxt))) {
|
||||
strcpy(device, "vif");
|
||||
if (!(node = virXPathNode("/interface/mac", ctxt)))
|
||||
goto cleanup;
|
||||
key = xmlGetProp(node, BAD_CAST "address");
|
||||
} else
|
||||
goto cleanup;
|
||||
if (!key || (strlen((char *)key) == 0))
|
||||
goto cleanup;
|
||||
|
||||
if (!(entry = virHashLookup(configCache, filename)))
|
||||
goto cleanup;
|
||||
if (!entry->conf)
|
||||
goto cleanup;
|
||||
|
||||
list_ptr = virConfGetValue(entry->conf, device);
|
||||
if (!list_ptr)
|
||||
goto cleanup;
|
||||
else if (list_ptr && list_ptr->type == VIR_CONF_LIST) {
|
||||
list_val = list_ptr->list;
|
||||
while (list_val) {
|
||||
if (!(strcmp(device, "disk"))) {
|
||||
char domdev[NAME_MAX];
|
||||
char *head;
|
||||
char *offset;
|
||||
char *tmp;
|
||||
|
||||
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
|
||||
goto skip;
|
||||
head = list_val->str;
|
||||
|
||||
/* Extract the source */
|
||||
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
|
||||
goto skip;
|
||||
if ((offset - head) >= (PATH_MAX-1))
|
||||
goto skip;
|
||||
head = offset + 1;
|
||||
|
||||
/* Extract the dest */
|
||||
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
|
||||
goto skip;
|
||||
if ((offset - head) >= (PATH_MAX-1))
|
||||
goto skip;
|
||||
strncpy(domdev, head, (offset - head));
|
||||
domdev[(offset-head)] = '\0';
|
||||
head = offset + 1;
|
||||
|
||||
/* Remove legacy ioemu: junk */
|
||||
if (!strncmp(domdev, "ioemu:", 6)) {
|
||||
memmove(domdev, domdev+6, strlen(domdev)-5);
|
||||
}
|
||||
|
||||
/* Check for a :cdrom/:disk postfix */
|
||||
if ((tmp = strchr(domdev, ':')))
|
||||
tmp[0] = '\0';
|
||||
|
||||
if (!(strcmp(domdev, (const char *) key)))
|
||||
break;
|
||||
} else {
|
||||
char dommac[18];
|
||||
char *mac;
|
||||
|
||||
dommac[0] = '\0';
|
||||
|
||||
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
|
||||
goto skip;
|
||||
|
||||
mac = list_val->str;
|
||||
while (mac) {
|
||||
char *data;
|
||||
char *nextmac = strchr(mac, ',');
|
||||
|
||||
if (!(data = strchr(mac, '=')) || (data[0] == '\0'))
|
||||
goto skip;
|
||||
data++;
|
||||
|
||||
if (!strncmp(mac, "mac=", 4)) {
|
||||
int len = nextmac ? (nextmac - data) : 17;
|
||||
if (len > 17)
|
||||
len = 17;
|
||||
strncpy(dommac, data, len);
|
||||
dommac[len] = '\0';
|
||||
}
|
||||
|
||||
while (nextmac && (nextmac[0] == ',' ||
|
||||
nextmac[0] == ' ' ||
|
||||
nextmac[0] == '\t'))
|
||||
nextmac++;
|
||||
mac = nextmac;
|
||||
}
|
||||
|
||||
if (!(strcmp(dommac, (const char *) key)))
|
||||
break;
|
||||
}
|
||||
skip:
|
||||
prev = list_val;
|
||||
list_val = list_val->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_val)
|
||||
goto cleanup;
|
||||
else {
|
||||
if (!prev) {
|
||||
virConfValuePtr value;
|
||||
if (!(value = calloc(1, sizeof(virConfValue))))
|
||||
goto cleanup;
|
||||
value->type = VIR_CONF_LIST;
|
||||
value->list = list_val->next;
|
||||
list_val->next = NULL;
|
||||
if (virConfSetValue(entry->conf, device, value)) {
|
||||
free(value);
|
||||
goto cleanup;
|
||||
}
|
||||
} else
|
||||
prev->next = list_val->next;
|
||||
}
|
||||
|
||||
/* If this fails, should we try to undo our changes to the
|
||||
* in-memory representation of the config file. I say not!
|
||||
*/
|
||||
if (virConfWriteFile(entry->filename, entry->conf) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (ctxt)
|
||||
xmlXPathFreeContext(ctxt);
|
||||
if (doc)
|
||||
xmlFreeDoc(doc);
|
||||
if (domdevice)
|
||||
free(domdevice);
|
||||
if (key)
|
||||
free(key);
|
||||
if (list_val)
|
||||
free(list_val);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* WITH_XEN */
|
||||
/*
|
||||
* Local variables:
|
||||
|
@ -61,6 +61,9 @@ int xenXMDomainUndefine(virDomainPtr domain);
|
||||
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
|
||||
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
|
||||
|
||||
static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
|
||||
static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user