<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi,<div><br></div><div>I created a patch for libvirt-php to support virDomainUndefineFlags and create snapshot from XML string.</div><div>The test case file is "examples/domain_undefine_flags_and_snapshot_create_xml_test_case.php".</div><div>Hoping this is useful for libvirt-php.</div><div><br></div><div><br></div><div><br></div><div><div>From e753d0014e8ce8cbcafb0fbd92159a6cc9f32168 Mon Sep 17 00:00:00 2001</div><div>From: Zhensheng Yuan <<a href="mailto:yuan@zhensheng.im">yuan@zhensheng.im</a>></div><div>Date: Wed, 20 Feb 2019 18:25:05 +0800</div><div>Subject: [libvirt-php PATCH] Add function libvirt_domain_undefine_flags and</div><div> libvirt_domain_snapshot_create_xml</div><div><br></div><div>---</div><div> ...lags_and_snapshot_create_xml_test_case.php | 136 ++++++++++++++++++</div><div> src/libvirt-domain.c                          |  23 +++</div><div> src/libvirt-domain.h                          |   2 +</div><div> src/libvirt-php.c                             |  12 ++</div><div> src/libvirt-snapshot.c                        |  35 +++++</div><div> src/libvirt-snapshot.h                        |   2 +</div><div> 6 files changed, 210 insertions(+)</div><div> create mode 100644 examples/domain_undefine_flags_and_snapshot_create_xml_test_case.php</div><div><br></div><div>diff --git a/examples/domain_undefine_flags_and_snapshot_create_xml_test_case.php b/examples/domain_undefine_flags_and_snapshot_create_xml_test_case.php</div><div>new file mode 100644</div><div>index 0000000..e6590ae</div><div>--- /dev/null</div><div>+++ b/examples/domain_undefine_flags_and_snapshot_create_xml_test_case.php</div><div>@@ -0,0 +1,136 @@</div><div>+<?php</div><div>+/**</div><div>+ * Created by PhpStorm.</div><div>+ * Date: 19-2-20</div><div>+ * Time: 下午4:57</div><div>+ */</div><div>+</div><div>+namespace YunInternet\Libvirt\Test\Unit;</div><div>+</div><div>+</div><div>+use PHPUnit\Framework\TestCase;</div><div>+</div><div>+class Test_libvirt_domain_undefine_flags extends TestCase</div><div>+{</div><div>+    public function testConstants()</div><div>+    {</div><div>+        $this->assertEquals(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, 1);</div><div>+        $this->assertEquals(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, 2);</div><div>+        $this->assertEquals(VIR_DOMAIN_UNDEFINE_NVRAM, 4);</div><div>+        $this->assertEquals(VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, 8);</div><div>+    }</div><div>+</div><div>+    public function testSnapshotAndUndefineFlags()</div><div>+    {</div><div>+        $libvirtResource = libvirt_connect("test:///default", false);</div><div>+        $this->assertTrue(is_resource($libvirtResource));</div><div>+</div><div>+        $domainResource = libvirt_domain_define_xml($libvirtResource, $this->getDomainXML());</div><div>+        $this->assertTrue(is_resource($domainResource));</div><div>+</div><div>+        // Create a snapshot named snapshot1</div><div>+        $snapshotResource = libvirt_domain_snapshot_create_xml($domainResource, <<<EOF</div><div>+<domainsnapshot></div><div>+  <name>snapshot1</name></div><div>+</domainsnapshot></div><div>+EOF</div><div>+, VIR_SNAPSHOT_CREATE_LIVE | VIR_SNAPSHOT_CREATE_ATOMIC);</div><div>+        $this->assertTrue(is_resource($snapshotResource));</div><div>+</div><div>+        // Domain with snapshot can not be undefined directly</div><div>+        $this->assertFalse(@libvirt_domain_undefine($domainResource));</div><div>+</div><div>+        // Use VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA flag to undefine the domain</div><div>+        $this->assertTrue(libvirt_domain_undefine_flags($domainResource, VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA));</div><div>+    }</div><div>+</div><div>+    private function getDomainXML()</div><div>+    {</div><div>+        return <<<EOF</div><div>+<domain type="test"></div><div>+  <name>Test</name></div><div>+  <memory unit="MiB">1024</memory></div><div>+  <vcpu placement="static">8</vcpu></div><div>+  <cpu mode="host-passthrough"></div><div>+    <topology sockets="4" cores="1" threads="2"/></div><div>+  </cpu></div><div>+  <os></div><div>+    <type arch="i686">hvm</type></div><div>+    <loader readonly='yes' type='pflash'>/usr/share/ovmf/OVMF.fd</loader></div><div>+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram></div><div>+    <bootmenu enable="yes" timeout="1000"/></div><div>+    <boot dev="hd"/></div><div>+    <boot dev="cdrom"/></div><div>+  </os></div><div>+  <pm></div><div>+    <suspend-to-mem enable="yes"/></div><div>+  </pm></div><div>+  <devices></div><div>+    <memballoon model="none"/></div><div>+    <disk type="volume" device="disk"></div><div>+      <driver name="qemu" type="qcow2"/></div><div>+      <source pool="testPool1" volume="testVolume1"/></div><div>+      <target bus="virtio" dev="vda"/></div><div>+    </disk></div><div>+    <disk type="volume" device="disk"></div><div>+      <driver name="qemu" type="qcow2"/></div><div>+      <source pool="testPool2" volume="testVolume2"/></div><div>+      <target bus="virtio" dev="vdb"/></div><div>+      <iotune></div><div>+        <total_bytes_sec>102400</total_bytes_sec></div><div>+      </iotune></div><div>+    </disk></div><div>+    <disk type="file" device="cdrom"></div><div>+      <driver name="qemu" type="raw"/></div><div>+      <source file="/iso/iso.iso"/></div><div>+      <target bus="ide" dev="hda"/></div><div>+    </disk></div><div>+    <interface type="network"></div><div>+      <source network="default"/></div><div>+      <mac address="52:54:00:00:00:01"/></div><div>+      <model type="virtio"/></div><div>+      <filterref filter="clean-traffic"></div><div>+        <parameter name="IP" value="192.168.122.2"/></div><div>+      </filterref></div><div>+      <bandwidth></div><div>+        <inbound average="10240" burst="20480" peak="20480"/></div><div>+        <outbound average="10240" burst="20480" peak="20480"/></div><div>+      </bandwidth></div><div>+    </interface></div><div>+    <input type="tablet" bus="usb"/></div><div>+    <graphics type="vnc" passwd="12345678" port="-1" autoport="yes"></div><div>+      <listen type="address" address="0.0.0.0"/></div><div>+    </graphics></div><div>+    <channel></div><div>+      <source mode="bind"/></div><div>+      <target type="virtio" name="org.qemu.guest_agent.0"/></div><div>+    </channel></div><div>+  </devices></div><div>+  <clock offset="utc"/></div><div>+  <features></div><div>+    <pae/></div><div>+    <acpi/></div><div>+    <apic/></div><div>+    <hyperv></div><div>+      <relaxed state="on"/></div><div>+      <vapic state="on"/></div><div>+      <spinlocks state="on" retries="8191"/></div><div>+    </hyperv></div><div>+  </features></div><div>+  <on_poweroff>destroy</on_poweroff></div><div>+  <on_reboot>restart</on_reboot></div><div>+  <on_crash>restart</on_crash></div><div>+  <blkiotune></div><div>+    <weight>1000</weight></div><div>+    <device></div><div>+      <path>/dev/sda</path></div><div>+      <weight>1000</weight></div><div>+      <read_bytes_sec>10240</read_bytes_sec></div><div>+      <write_bytes_sec>10240</write_bytes_sec></div><div>+    </device></div><div>+  </blkiotune></div><div>+</domain></div><div>+EOF</div><div>+            ;</div><div>+    }</div><div>+}</div><div>diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c</div><div>index 8b8bb45..e2dc33e 100644</div><div>--- a/src/libvirt-domain.c</div><div>+++ b/src/libvirt-domain.c</div><div>@@ -1467,6 +1467,29 @@ PHP_FUNCTION(libvirt_domain_undefine)</div><div>     RETURN_TRUE;</div><div> }</div><div> </div><div>+/*</div><div>+ * Function name:   libvirt_domain_undefine_flags</div><div>+ * Description:     Function is used to undefine(with flags) the domain identified by it's resource</div><div>+ * Arguments:       @res [resource]: libvirt domain resource, e.g. from libvirt_domain_lookup_by_*()</div><div>+ *                  @flags [int]: optional flags</div><div>+ * Returns:         TRUE for success, FALSE on error</div><div>+ */</div><div>+PHP_FUNCTION(libvirt_domain_undefine_flags)</div><div>+{</div><div>+    php_libvirt_domain *domain = NULL;</div><div>+    zval *zdomain;</div><div>+    int retval;</div><div>+    zend_long flags = 0;</div><div>+</div><div>+    GET_DOMAIN_FROM_ARGS("r|l", &zdomain, &flags);</div><div>+</div><div>+    retval = virDomainUndefineFlags(domain->domain, flags);</div><div>+    DPRINTF("%s: virDomainUndefineFlags(%p) returned %d\n", PHPFUNC, domain->domain, retval);</div><div>+    if (retval != 0)</div><div>+        RETURN_FALSE;</div><div>+    RETURN_TRUE;</div><div>+}</div><div>+</div><div> /*</div><div>  * Function name:   libvirt_domain_reboot</div><div>  * Since version:   0.4.1(-1)</div><div>diff --git a/src/libvirt-domain.h b/src/libvirt-domain.h</div><div>index dc0ab46..6d98544 100644</div><div>--- a/src/libvirt-domain.h</div><div>+++ b/src/libvirt-domain.h</div><div>@@ -73,6 +73,7 @@</div><div>     PHP_FE(libvirt_domain_suspend,               arginfo_libvirt_conn)                         \</div><div>     PHP_FE(libvirt_domain_managedsave,           arginfo_libvirt_conn)                         \</div><div>     PHP_FE(libvirt_domain_undefine,              arginfo_libvirt_conn)                         \</div><div>+    PHP_FE(libvirt_domain_undefine_flags,        arginfo_libvirt_conn_flags)                   \</div><div>     PHP_FE(libvirt_domain_reboot,                arginfo_libvirt_conn_flags)                   \</div><div>     PHP_FE(libvirt_domain_define_xml,            arginfo_libvirt_conn_xml)                     \</div><div>     PHP_FE(libvirt_domain_create_xml,            arginfo_libvirt_conn_xml)                     \</div><div>@@ -163,6 +164,7 @@ PHP_FUNCTION(libvirt_domain_shutdown);</div><div> PHP_FUNCTION(libvirt_domain_suspend);</div><div> PHP_FUNCTION(libvirt_domain_managedsave);</div><div> PHP_FUNCTION(libvirt_domain_undefine);</div><div>+PHP_FUNCTION(libvirt_domain_undefine_flags);</div><div> PHP_FUNCTION(libvirt_domain_reboot);</div><div> PHP_FUNCTION(libvirt_domain_define_xml);</div><div> PHP_FUNCTION(libvirt_domain_create_xml);</div><div>diff --git a/src/libvirt-php.c b/src/libvirt-php.c</div><div>index cf8fd7f..7e10b3d 100644</div><div>--- a/src/libvirt-php.c</div><div>+++ b/src/libvirt-php.c</div><div>@@ -468,6 +468,12 @@ ZEND_ARG_INFO(0, timeout)</div><div> ZEND_ARG_INFO(0, flags)</div><div> ZEND_END_ARG_INFO()</div><div> </div><div>+ZEND_BEGIN_ARG_INFO_EX(arginfo_libvirt_domain_snapshot_create_xml, 0, 0, 2)</div><div>+ZEND_ARG_INFO(0, conn)</div><div>+ZEND_ARG_INFO(0, xml)</div><div>+ZEND_ARG_INFO(0, flags)</div><div>+ZEND_END_ARG_INFO()</div><div>+</div><div> static zend_function_entry libvirt_functions[] = {</div><div>     PHP_FE_LIBVIRT_CONNECTION</div><div>     PHP_FE_LIBVIRT_STREAM</div><div>@@ -1491,6 +1497,12 @@ PHP_MINIT_FUNCTION(libvirt)</div><div>     REGISTER_LONG_CONSTANT("VIR_KEYCODE_SET_WIN32", VIR_KEYCODE_SET_WIN32, CONST_CS | CONST_PERSISTENT);</div><div>     REGISTER_LONG_CONSTANT("VIR_KEYCODE_SET_RFB", VIR_KEYCODE_SET_RFB, CONST_CS | CONST_PERSISTENT);</div><div> </div><div>+    /* virDomainUndefineFlagsValues */</div><div>+    REGISTER_LONG_CONSTANT("VIR_DOMAIN_UNDEFINE_MANAGED_SAVE", VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, CONST_CS | CONST_PERSISTENT);</div><div>+    REGISTER_LONG_CONSTANT("VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA", VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, CONST_CS | CONST_PERSISTENT);</div><div>+    REGISTER_LONG_CONSTANT("VIR_DOMAIN_UNDEFINE_NVRAM", VIR_DOMAIN_UNDEFINE_NVRAM, CONST_CS | CONST_PERSISTENT);</div><div>+    REGISTER_LONG_CONSTANT("VIR_DOMAIN_UNDEFINE_KEEP_NVRAM", VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, CONST_CS | CONST_PERSISTENT);</div><div>+</div><div>     REGISTER_INI_ENTRIES();</div><div> </div><div>     /* Initialize libvirt and set up error callback */</div><div>diff --git a/src/libvirt-snapshot.c b/src/libvirt-snapshot.c</div><div>index 1388d88..f7e3e2b 100644</div><div>--- a/src/libvirt-snapshot.c</div><div>+++ b/src/libvirt-snapshot.c</div><div>@@ -130,6 +130,41 @@ PHP_FUNCTION(libvirt_domain_snapshot_create)</div><div>     VIRT_REGISTER_RESOURCE(res_snapshot, le_libvirt_snapshot);</div><div> }</div><div> </div><div>+/*</div><div>+ * Function name:   libvirt_domain_snapshot_create_xml</div><div>+ * Description:     This function creates the domain snapshot from XML string for the domain identified by it's resource</div><div>+ * Arguments:       @res [resource]: libvirt domain resource</div><div>+ *                  @xml [string]: xml</div><div>+ *                  @flags [int]: libvirt snapshot flags</div><div>+ * Returns:         domain snapshot resource</div><div>+ */</div><div>+PHP_FUNCTION(libvirt_domain_snapshot_create_xml)</div><div>+{</div><div>+    php_libvirt_domain *domain = NULL;</div><div>+    php_libvirt_snapshot *res_snapshot;</div><div>+    zval *zdomain;</div><div>+    char *xml;</div><div>+    strsize_t xml_len;</div><div>+    virDomainSnapshotPtr snapshot = NULL;</div><div>+    zend_long flags = 0;</div><div>+</div><div>+    GET_DOMAIN_FROM_ARGS("rs|l", &zdomain, &xml, &xml_len, &flags);</div><div>+</div><div>+    snapshot = virDomainSnapshotCreateXML(domain->domain, xml, flags);</div><div>+    DPRINTF("%s: virDomainSnapshotCreateXML(%p, <xml>) returned %p\n", PHPFUNC, domain->domain, snapshot);</div><div>+    if (snapshot == NULL)</div><div>+        RETURN_FALSE;</div><div>+</div><div>+    res_snapshot = (php_libvirt_snapshot *)emalloc(sizeof(php_libvirt_snapshot));</div><div>+    res_snapshot->domain = domain;</div><div>+    res_snapshot->snapshot = snapshot;</div><div>+</div><div>+    DPRINTF("%s: returning %p\n", PHPFUNC, res_snapshot->snapshot);</div><div>+    resource_change_counter(INT_RESOURCE_SNAPSHOT, domain->conn->conn, res_snapshot->snapshot, 1 TSRMLS_CC);</div><div>+</div><div>+    VIRT_REGISTER_RESOURCE(res_snapshot, le_libvirt_snapshot);</div><div>+}</div><div>+</div><div> /*</div><div>  * Function name:   libvirt_domain_snapshot_get_xml</div><div>  * Since version:   0.4.1(-2)</div><div>diff --git a/src/libvirt-snapshot.h b/src/libvirt-snapshot.h</div><div>index e6092aa..970662c 100644</div><div>--- a/src/libvirt-snapshot.h</div><div>+++ b/src/libvirt-snapshot.h</div><div>@@ -16,6 +16,7 @@</div><div>     PHP_FE(libvirt_domain_has_current_snapshot,    arginfo_libvirt_conn_optflags)                  \</div><div>     PHP_FE(libvirt_domain_snapshot_lookup_by_name, arginfo_libvirt_domain_snapshot_lookup_by_name) \</div><div>     PHP_FE(libvirt_domain_snapshot_create,         arginfo_libvirt_conn_optflags)                  \</div><div>+    PHP_FE(libvirt_domain_snapshot_create_xml,     arginfo_libvirt_domain_snapshot_create_xml)     \</div><div>     PHP_FE(libvirt_domain_snapshot_get_xml,        arginfo_libvirt_conn_optflags)                  \</div><div>     PHP_FE(libvirt_domain_snapshot_revert,         arginfo_libvirt_conn_optflags)                  \</div><div>     PHP_FE(libvirt_domain_snapshot_delete,         arginfo_libvirt_conn_optflags)                  \</div><div>@@ -50,6 +51,7 @@ void php_libvirt_snapshot_dtor(virt_resource *rsrc TSRMLS_DC);</div><div> PHP_FUNCTION(libvirt_domain_has_current_snapshot);</div><div> PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name);</div><div> PHP_FUNCTION(libvirt_domain_snapshot_create);</div><div>+PHP_FUNCTION(libvirt_domain_snapshot_create_xml);</div><div> PHP_FUNCTION(libvirt_domain_snapshot_get_xml);</div><div> PHP_FUNCTION(libvirt_domain_snapshot_revert);</div><div> PHP_FUNCTION(libvirt_domain_snapshot_delete);</div><div>-- </div><div>2.17.1</div><div><br></div></div><div><br></div><div>Regards,</div><div>Zhensheng Yuan</div></div></div></div></div>