---
 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\"]/./@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']/./@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\"]/./@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\"]/./@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']/./@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']/../@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/@%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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to