---
src/libvirt-php.c | 246 +++++++++++++++++++++++++----------------------------
1 file changed, 114 insertions(+), 132 deletions(-)
diff --git a/src/libvirt-php.c b/src/libvirt-php.c
index 0b8345a..24e8606 100644
--- a/src/libvirt-php.c
+++ b/src/libvirt-php.c
@@ -4232,11 +4232,12 @@ PHP_FUNCTION(libvirt_domain_change_boot_devices)
Since version: 0.4.2
Description: Function is used to add the disk to the virtual machine using set of API
functions to make it as simple as possible for the user
Arguments: @res [resource]: libvirt domain resource
- @img [string]: string for the image file on the host system
+ @path [string]: string for the image file or device node on the system
@dev [string]: string for the device to be presented to the guest (e.g. hda)
@typ [string]: bus type for the device in the guest, usually 'ide' or
'scsi'
- @driver [string]: driver type to be specified, like 'raw'
or 'qcow2'
- @flags [int]: flags for getting the XML description
+ @driver [string]: driver type to be specified, like 'raw' or 'qcow2'
+ @cache [string]: cache mode, can be 'default', 'none',
'writeback' or 'writethrough'
+ @io [string]: io mode, can be 'default', 'native' or
'threads'
Returns: new domain resource
*/
PHP_FUNCTION(libvirt_domain_disk_add)
@@ -4244,46 +4245,40 @@ PHP_FUNCTION(libvirt_domain_disk_add)
php_libvirt_domain *domain=NULL;
zval *zdomain;
char *tmp1 = NULL;
- char *tmp2 = NULL;
char *xml;
- char *img = NULL;
- int img_len;
+ char *path = NULL;
+ int path_len;
char *dev = NULL;
int dev_len;
char *driver = NULL;
int driver_len;
char *typ = NULL;
int typ_len;
- char *new_xml = NULL;
- int new_len;
+ char *cache = "default";
+ int cache_len;
+ char *io = "default";
+ int io_len;
char new[4096] = { 0 };
- long xflags = 0;
int retval = -1;
- int pos = -1;
- php_libvirt_domain *res_domain = NULL;
- php_libvirt_connection *conn = NULL;
- virDomainPtr dom=NULL;
+ int block_device = 0; // whether the path leads to a block device (1) or to an image
(0)
+ char cache_attr[32] = ""; // store the complete cache attribute, or an empty
string to denote default
+ char io_attr[32] = ""; // store the complete io attribute, or an empty string
to denote default
- GET_DOMAIN_FROM_ARGS("rssss|l",&zdomain,&img,&img_len,&dev,&dev_len,&typ,&typ_len,&driver,&driver_len,&xflags);
+ GET_DOMAIN_FROM_ARGS("rssss|ss",&zdomain,&path,&path_len,&dev,&dev_len,&typ,&typ_len,&driver,&driver_len,&cache,&cache_len,&io,&io_len);
- DPRINTF("%s: Domain %p, device = %s, image = %s, type = %s, driver = %s\n",
PHPFUNC,
- domain->domain, dev, img, typ, driver);
+ DPRINTF("%s: Domain %p, device = %s, path = %s, type = %s, driver = %s, cache = %s,
io = %s\n", PHPFUNC,
+ domain->domain, dev, path, typ, driver, cache, io);
- xml=virDomainGetXMLDesc(domain->domain,xflags);
+ // check whether the path leads to a block device
+ if (strncmp(path, "/dev/", 5) == 0)
+ block_device = 1;
+
+ xml=virDomainGetXMLDesc(domain->domain, 0);
if (xml==NULL) {
set_error_if_unset("Cannot get the XML description" TSRMLS_CC);
RETURN_FALSE;
}
- snprintf(new, sizeof(new),
"//domain/devices/disk/source[@file=\"%s\"]/./(a)file", img);
- tmp1 = get_string_from_xpath(xml, new, NULL, &retval);
- if (tmp1 != NULL) {
- free(tmp1);
- snprintf(new, sizeof(new), "Domain already has image <i>%s</i>
connected", img);
- set_error(new TSRMLS_CC);
- RETURN_FALSE;
- }
-
snprintf(new, sizeof(new),
"//domain/devices/disk/target[@dev='%s']/./(a)dev", dev);
tmp1 = get_string_from_xpath(xml, new, NULL, &retval);
if (tmp1 != NULL) {
@@ -4293,58 +4288,72 @@ PHP_FUNCTION(libvirt_domain_disk_add)
RETURN_FALSE;
}
- if (access(img, R_OK) != 0) {
- snprintf(new, sizeof(new), "Image file <i>%s</i> doesn't
exist", img);
- set_error(new TSRMLS_CC);
- RETURN_FALSE;
- }
-
- snprintf(new, sizeof(new),
- " <disk type='file' device='disk'>\n"
- " <driver name='qemu' type='%s'/>\n"
- " <source file='%s'/>\n"
- " <target dev='%s' bus='%s'/>\n"
- " </disk>", driver, img, dev, typ);
- tmp1 = strstr(xml, "</emulator>") +
strlen("</emulator>");
- pos = strlen(xml) - strlen(tmp1);
+ // do we want to use a non-default cache mode?
+ if (strncmp(cache, "default", 7) != 0)
+ snprintf(cache_attr, sizeof(cache_attr), "cache='%s'", cache);
- tmp2 = emalloc( ( pos + 1 )* sizeof(char) );
- memset(tmp2, 0, pos + 1);
- memcpy(tmp2, xml, pos);
+ // or a non-default io mode perhaps?
+ if (strncmp(io, "default", 7) != 0)
+ snprintf(io_attr, sizeof(io_attr), "io='%s'", io);
- new_len = strlen(tmp1) + strlen(tmp2) + strlen(new) + 2;
- new_xml = emalloc( new_len * sizeof(char) );
- snprintf(new_xml, new_len, "%s\n%s%s", tmp2, new, tmp1);
-
- conn = domain->conn;
+ // check for valid image file or device node
+ if (block_device == 0) {
+ // check whether the image already appears in the xml
+ snprintf(new, sizeof(new),
"//domain/devices/disk/source[@file=\"%s\"]/./(a)file", path);
+ tmp1 = get_string_from_xpath(xml, new, NULL, &retval);
+ if (tmp1 != NULL) {
+ free(tmp1);
+ snprintf(new, sizeof(new), "Domain already has image <i>%s</i>
connected", path);
+ set_error(new TSRMLS_CC);
+ RETURN_FALSE;
+ }
- virDomainUndefine(domain->domain);
- virDomainFree(domain->domain);
+ if (access(path, R_OK) != 0) {
+ snprintf(new, sizeof(new), "Image file <i>%s</i> doesn't
exist", path);
+ set_error(new TSRMLS_CC);
+ RETURN_FALSE;
+ }
- retval = virDomainFree(domain->domain);
- if (retval != 0) {
- DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC,
domain->domain, retval, LIBVIRT_G(last_error));
- }
+ // create the xml to add the device
+ snprintf(new, sizeof(new),
+ " <disk type='file' device='disk'>\n"
+ " <driver name='qemu' type='%s' %s %s/>\n"
+ " <source file='%s'/>\n"
+ " <target dev='%s' bus='%s'/>\n"
+ " </disk>", driver, cache_attr, io_attr, path, dev, typ);
+ }
else {
- resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0
TSRMLS_CC);
- DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain);
- }
-
- dom=virDomainDefineXML(conn->conn, new_xml);
- if (dom==NULL) {
- DPRINTF("%s: Function failed, restoring original XML\n", PHPFUNC);
- dom=virDomainDefineXML(conn->conn, xml);
- if (dom == NULL)
+ // check whether the device already appears in the xml
+ snprintf(new, sizeof(new),
"//domain/devices/disk/source[@dev=\"%s\"]/./(a)dev", path);
+ tmp1 = get_string_from_xpath(xml, new, NULL, &retval);
+ if (tmp1 != NULL) {
+ free(tmp1);
+ snprintf(new, sizeof(new), "Domain already has device <i>%s</i>
connected", path);
+ set_error(new TSRMLS_CC);
RETURN_FALSE;
+ }
+
+ // create the xml to add the device
+ snprintf(new, sizeof(new),
+ " <disk type='block' device='disk'>\n"
+ " <driver name='qemu' type='%s' %s %s/>\n"
+ " <source dev='%s'/>\n"
+ " <target dev='%s' bus='%s'/>\n"
+ " </disk>", driver, cache_attr, io_attr, path, dev, typ);
}
- res_domain = emalloc(sizeof(php_libvirt_domain));
- res_domain->domain = dom;
- res_domain->conn = conn;
+ // attach the disk to the domain
+ retval = virDomainAttachDeviceFlags(domain->domain, new, VIR_DOMAIN_AFFECT_CURRENT);
+ if (retval != 0) {
+ snprintf(new, sizeof(new), "%s: Cannot add device to domain %p, error code = %d
(%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error));
+ set_error(new TSRMLS_CC);
+ RETURN_FALSE;
+ }
- DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain);
- resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1
TSRMLS_CC);
- ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain);
+ // the disk was successfully added
+ DPRINTF("%s: returning %p\n", PHPFUNC, domain->domain);
+ zend_list_addref(Z_LVAL_P(zdomain));
+ RETURN_RESOURCE(Z_LVAL_P(zdomain));
}
/*
@@ -4360,96 +4369,69 @@ PHP_FUNCTION(libvirt_domain_disk_remove)
{
php_libvirt_domain *domain=NULL;
zval *zdomain;
- char *tmp1 = NULL;
- char *tmp2 = NULL;
+ char *type = NULL;
+ char *path = NULL;
+ char *source = NULL;
char *xml;
char *dev = NULL;
int dev_len;
char *new_xml = NULL;
int new_len;
char new[4096] = { 0 };
- long xflags = 0;
int retval = -1;
- int pos = -1;
- int i, idx = 0;
- php_libvirt_domain *res_domain=NULL;
- php_libvirt_connection *conn = NULL;
- virDomainPtr dom = NULL;
- GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&dev,&dev_len,&xflags);
+ GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&dev,&dev_len);
DPRINTF("%s: Trying to remove %s from domain %p\n", PHPFUNC, dev,
domain->domain);
- xml=virDomainGetXMLDesc(domain->domain,xflags);
+ xml=virDomainGetXMLDesc(domain->domain, 0);
if (xml==NULL) {
set_error_if_unset("Cannot get the XML description" TSRMLS_CC);
RETURN_FALSE;
}
- snprintf(new, sizeof(new),
"//domain/devices/disk/target[@dev='%s']/./(a)dev", dev);
- tmp1 = get_string_from_xpath(xml, new, NULL, &retval);
- if (tmp1 == NULL) {
+ // check for the type, if no result is found, the disk does not exist
+ snprintf(new, sizeof(new),
"//domain/devices/disk/target[@dev='%s']/../(a)type", dev);
+ type = get_string_from_xpath(xml, new, NULL, &retval);
+ if (type == NULL) {
snprintf(new, sizeof(new), "Device <i>%s</i> is not connected to the
guest", dev);
set_error(new TSRMLS_CC);
RETURN_FALSE;
}
- free(tmp1);
-
- snprintf(new, sizeof(new), "<target dev='%s'", dev);
- tmp1 = strstr(xml, new) + strlen(new);
- pos = strlen(xml) - strlen(tmp1);
-
- tmp2 = emalloc( ( pos + 1 )* sizeof(char) );
- memset(tmp2, 0, pos + 1);
- memcpy(tmp2, xml, pos);
-
- for (i = strlen(tmp2) - 5; i > 0; i--)
- if ((tmp2[i] == '<') && (tmp2[i+1] == 'd')
- && (tmp2[i+2] == 'i') && (tmp2[i+3] == 's')
- && (tmp2[i+4] == 'k')) {
- tmp2[i-5] = 0;
- break;
- }
+ // are we dealing with a file or a block device?
+ if (strcmp(type, "file") == 0)
+ source = "file";
+ else
+ source = "dev";
- for (i = 0; i < strlen(tmp1) - 7; i++)
- if ((tmp1[i] == '<') && (tmp1[i+1] == '/')
- && (tmp1[i+2] == 'd') && (tmp1[i+3] == 'i')
- && (tmp1[i+4] == 's') && (tmp1[i+5] == 'k')
- && (tmp1[i+6] == '>')) {
- idx = i + 6;
- break;
- }
+ // retrieve the device or file
+ snprintf(new, sizeof(new),
"//domain/devices/disk/target[@dev='%s']/../source/(a)%s", dev, source);
+ path = get_string_from_xpath(xml, new, NULL, &retval);
- new_len = strlen(tmp2) + (strlen(tmp1) - idx);
- new_xml = emalloc( new_len * sizeof(char) );
- memset(new_xml, 0, new_len);
- strcpy(new_xml, tmp2);
- for (i = idx; i < strlen(tmp1) - 1; i++)
- new_xml[ strlen(tmp2) + i - idx ] = tmp1[i];
+ // define the xml to remove the device
+ snprintf(new, sizeof(new),
+ " <disk type='%s' device='disk'>"
+ " <source %s='%s'/>"
+ " <target dev='%s'/>"
+ " </disk>", type, source, path, dev);
- conn = domain->conn;
- virDomainUndefine(domain->domain);
+ // cleanup temporary resources
+ free(type);
+ free(path);
- retval = virDomainFree(domain->domain);
+ // remove the disk from the domain
+ retval = virDomainDetachDeviceFlags(domain->domain, new, VIR_DOMAIN_AFFECT_CURRENT);
if (retval != 0) {
- DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC,
domain->domain, retval, LIBVIRT_G(last_error));
- }
- else {
- resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0
TSRMLS_CC);
- DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain);
+ snprintf(new, sizeof(new), "%s: Cannot remove device from domain %p, error code =
%d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error));
+ set_error(new TSRMLS_CC);
+ RETURN_FALSE;
}
- dom=virDomainDefineXML(conn->conn,new_xml);
- if (dom==NULL) RETURN_FALSE;
-
- res_domain = emalloc(sizeof(php_libvirt_domain));
- res_domain->domain = dom;
- res_domain->conn = conn;
-
- DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain);
- resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1
TSRMLS_CC);
- ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain);
+ // the disk was successfully removed
+ DPRINTF("%s: returning %p\n", PHPFUNC, domain->domain);
+ zend_list_addref(Z_LVAL_P(zdomain));
+ RETURN_RESOURCE(Z_LVAL_P(zdomain));
}
/*
@@ -5172,7 +5154,7 @@ PHP_FUNCTION(libvirt_domain_get_block_info) {
GET_DOMAIN_FROM_ARGS("rs",&zdomain,&dev,&dev_len);
/* Get XML for the domain */
- xml=virDomainGetXMLDesc(domain->domain, VIR_DOMAIN_XML_INACTIVE);
+ xml=virDomainGetXMLDesc(domain->domain, 0);
if (xml==NULL) {
set_error("Cannot get domain XML" TSRMLS_CC);
RETURN_FALSE;
--
1.7.9.5