mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-29 17:33:09 +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>
|
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
|
* 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 int nconnections = 0;
|
||||||
static time_t lastRefresh = 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_REFRESH_INTERVAL 10
|
||||||
|
|
||||||
#define XM_CONFIG_DIR "/etc/xen"
|
#define XM_CONFIG_DIR "/etc/xen"
|
||||||
@ -79,6 +85,7 @@ static time_t lastRefresh = 0;
|
|||||||
#define XEND_CONFIG_FILE "xend-config.sxp"
|
#define XEND_CONFIG_FILE "xend-config.sxp"
|
||||||
#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
|
#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
|
||||||
#define QEMU_IF_SCRIPT "qemu-ifup"
|
#define QEMU_IF_SCRIPT "qemu-ifup"
|
||||||
|
#define XM_XML_ERROR "Invalid xml"
|
||||||
|
|
||||||
struct xenUnifiedDriver xenXMDriver = {
|
struct xenUnifiedDriver xenXMDriver = {
|
||||||
xenXMOpen, /* open */
|
xenXMOpen, /* open */
|
||||||
@ -113,8 +120,8 @@ struct xenUnifiedDriver xenXMDriver = {
|
|||||||
xenXMDomainCreate, /* domainCreate */
|
xenXMDomainCreate, /* domainCreate */
|
||||||
xenXMDomainDefineXML, /* domainDefineXML */
|
xenXMDomainDefineXML, /* domainDefineXML */
|
||||||
xenXMDomainUndefine, /* domainUndefine */
|
xenXMDomainUndefine, /* domainUndefine */
|
||||||
NULL, /* domainAttachDevice */
|
xenXMDomainAttachDevice, /* domainAttachDevice */
|
||||||
NULL, /* domainDetachDevice */
|
xenXMDomainDetachDevice, /* domainDetachDevice */
|
||||||
NULL, /* domainGetAutostart */
|
NULL, /* domainGetAutostart */
|
||||||
NULL, /* domainSetAutostart */
|
NULL, /* domainSetAutostart */
|
||||||
NULL, /* domainGetSchedulerType */
|
NULL, /* domainGetSchedulerType */
|
||||||
@ -2515,6 +2522,635 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
|
|||||||
return virHashSize(nameConfigMap);
|
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 */
|
#endif /* WITH_XEN */
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
|
@ -61,6 +61,9 @@ int xenXMDomainUndefine(virDomainPtr domain);
|
|||||||
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
|
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
|
||||||
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
|
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
|
||||||
|
|
||||||
|
static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
|
||||||
|
static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user