[libvirt] PATCH: Domain XML import/export from/to native formats

Daniel P. Berrange berrange at redhat.com
Fri Apr 17 10:56:47 UTC 2009


This is an initial patch providing an API to import and export the Domain
XML from/to native hypervisor formats.

This implementation provides

 - Import from Xen XM config file format
 - Export to Xen XM config file format
 - Import from Xen SEXPR format
 - Export to Xen SEXPR format
 - Export to QEMU argv list

Still todo is the more complex, 

 - Import from QEMU argv list

which is actually the most interesting & useful one, since that helps
people currently using QEMU migrate over to using libvirt.

The two new public APIs are


 /**
  * virConnectImportDomainXML:
  * @conn: a connection object
  * @format: configuration format importing from
  * @config: the configuration data to import
  * @flags: currently unused, pass 0
  *
  * Reads native configuration data  describing a domain, and 
  * generates libvirt domain XML. The format of the native
  * data is hypervisor dependant.
  *
  * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
  *         the caller must free() the returned value.
  */
 char *                  virConnectImportDomainXML(virConnectPtr conn,
                                                   const char *format,
                                                   const char *config,
                                                   unsigned int flags);

 /**
  * virConnectExportDomainXML:
  * @conn: a connection object
  * @format: configuration format exporting to
  * @xml: the domain configuration to export
  * @flags: currently unused, pass 0
  *
  * Reads a domain XML configuration document, and generates
  * generates a native configuration file describing the domain.
  * The format of the native data is hypervisor dependant.
  *
  * Returns a 0 terminated UTF-8 encoded native config datafile, or NULL in case of error.
  *         the caller must free() the returned value.
  */
 char *                  virConnectExportDomainXML(virConnectPtr conn,
                                                   const char *format,
                                                   const char *xml,
                                                   unsigned int flags);


This is integrated via virsh

eg import a Xen SEXPR config to libvirt domain XML

  # virsh import-domxml xen-sxpr demo.sxpr
  <domain type='xen' id='78'>
    <name>rhel5pv</name>
    <uuid>8f07fe28-753f-2729-d76d-bdbd892f949a</uuid>
    <memory>2560000</memory>
    <currentMemory>307200</currentMemory>
    ...snip rest...
      <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
    </devices>
  </domain>

eg, export libvirt domain XML to Xen SEXPR format

  # virsh export-domxml xen-sxpr demo.xml
  (vm (name 'Xen')(memory 256)(maxmem 256)(vcpus 1)
   (uuid '971784f4-523b-1a8c-99eb-7e66a539c3ac')
    ...snip...
   (script 'vif-bridge'))))

eg import a Xen XM config file

  # virsh import-domxml xen-xm demo.cfg
  <domain type='xen'>
    <name>rhel5pv</name>
    <uuid>8f07fe28-753f-2729-d76d-bdbd892f949a</uuid>
    <memory>2560000</memory>
    <currentMemory>307200</currentMemory>
    <vcpu>4</vcpu>
    <bootloader>/usr/bin/pygrub</bootloader>
    ....snip...
  </domain>

eg  export to Xen XM config file

  # virsh export-domxml xen-xm demo.xml
  name = "Xen"
  uuid = "971784f4-523b-1a8c-99eb-7e66a539c3ac"
  maxmem = 256
  memory = 256
  vcpus = 1
  kernel = "/var/lib/xen/vmlinuz"
  ...snip...
  vif = [ "mac=00:16:3e:53:45:a9,bridge=virbr0" ]


eg export to QEMU ARGV format

  # virsh -c qemu:///session export-domxml qemu-argv ~/rhel5xen.xml 
  LC_ALL=C LD_LIBRARY_PATH=/home/berrange/usr/lib 
  PATH=/usr/bin:/bin HOME=/home/berrange USER=berrange LOGNAME=berrange
  /usr/bin/qemu-kvm -S -M pc -m 1967 -smp 4 -name rhel5xen -uuid 
  be8b4f9a-492a-db25-7aed-f831dcec9127 -monitor pty -pidfile 
  /home/berrange/.libvirt/qemu/run/rhel5xen.pid -boot c -drive 
  file=/dev/HostVG/rhel5xen,if=ide,index=0,boot=on -net 
  nic,macaddr=00:16:3e:09:f2:eb,vlan=0 -net tap,vlan=0 -net 
  nic,macaddr=00:16:3e:09:f3:eb,vlan=1 -net tap,vlan=1 -net 
  nic,macaddr=00:16:3e:09:f4:eb,vlan=2 -net tap,vlan=2 -net 
  nic,macaddr=00:16:3e:09:f5:eb,vlan=3 -net tap,vlan=3 -serial 
  file:/tmp/rhel5xen.log -parallel none -usb -vnc 0.0.0.0:0 -k en-us 


The import thing to note here is that the import/export process is done
via the real libvirt drivers, but the destination / source configs are 
not loaded into the hypervisor / mangement app at all. It is purely a
put a string in, get a string out process.  What you do with the generated
config is up to you. Also note that you can't export a Xen config using
the QEMU driver, and vica-verca.

The openvz, test, uml drivers don't implement these new APIs, though
openvz & uml could be made to. The Remote driver & daemon is implemented
here, and python bindings are provided too.

 docs/devhelp/libvirt-libvirt.html  |   12 ++
 docs/html/libvirt-libvirt.html     |    8 +
 docs/libvirt-api.xml               |   20 ++++
 docs/libvirt-refs.xml              |  158 +++++++++++++++++++++++++------------
 include/libvirt/libvirt.h          |   10 ++
 include/libvirt/libvirt.h.in       |   10 ++
 qemud/remote.c                     |   34 +++++++
 qemud/remote_dispatch_args.h       |    2 
 qemud/remote_dispatch_prototypes.h |   14 +++
 qemud/remote_dispatch_ret.h        |    2 
 qemud/remote_dispatch_table.h      |   14 ++-
 qemud/remote_protocol.c            |   44 ++++++++++
 qemud/remote_protocol.h            |   34 +++++++
 qemud/remote_protocol.x            |   27 ++++++
 src/driver.h                       |   12 ++
 src/libvirt.c                      |   99 +++++++++++++++++++++++
 src/libvirt_public.syms            |    6 +
 src/lxc_driver.c                   |    2 
 src/openvz_driver.c                |    2 
 src/qemu_conf.c                    |   25 ++---
 src/qemu_conf.h                    |    3 
 src/qemu_driver.c                  |  127 +++++++++++++++++++++++++++++
 src/remote_internal.c              |   64 ++++++++++++++
 src/test.c                         |    2 
 src/uml_driver.c                   |    2 
 src/virsh.c                        |   94 ++++++++++++++++++++++
 src/xen_unified.c                  |   93 +++++++++++++++++++++
 src/xen_unified.h                  |    3 
 28 files changed, 853 insertions(+), 70 deletions(-)


Daniel


diff -r ba47cd6949a4 docs/devhelp/libvirt-libvirt.html
--- a/docs/devhelp/libvirt-libvirt.html	Thu Apr 16 12:44:17 2009 +0100
+++ b/docs/devhelp/libvirt-libvirt.html	Fri Apr 17 10:22:22 2009 +0100
@@ -126,6 +126,7 @@ int	<a href="#virNodeDeviceDettach">virN
 int	<a href="#virDomainGetSecurityLabel">virDomainGetSecurityLabel</a>	(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain, <br/>					 <a href="libvirt-libvirt.html#virSecurityLabelPtr">virSecurityLabelPtr</a> seclabel);
 int	<a href="#virConnectDomainEventDeregister">virConnectDomainEventDeregister</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb);
 int	<a href="#virDomainGetSchedulerParameters">virDomainGetSchedulerParameters</a>	(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain, <br/>					 <a href="libvirt-libvirt.html#virSchedParameterPtr">virSchedParameterPtr</a> params, <br/>					 int * nparams);
+char *	<a href="#virConnectImportDomainXML">virConnectImportDomainXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * format, <br/>					 const char * config, <br/>					 unsigned int flags);
 <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a>	<a href="#virDomainLookupByUUIDString">virDomainLookupByUUIDString</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>						 const char * uuidstr);
 int	<a href="#virConnectNumOfDefinedNetworks">virConnectNumOfDefinedNetworks</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn);
 int	<a href="#virConnectNumOfDomains">virConnectNumOfDomains</a>		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn);
@@ -218,7 +219,7 @@ int	<a href="#virDomainResume">virDomain
 int	<a href="#virNodeListDevices">virNodeListDevices</a>		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * cap, <br/>					 char ** const names, <br/>					 int maxnames, <br/>					 unsigned int flags);
 int	<a href="#virNetworkRef">virNetworkRef</a>			(<a href="libvirt-libvirt.html#virNetworkPtr">virNetworkPtr</a> network);
 int	<a href="#virStoragePoolRefresh">virStoragePoolRefresh</a>		(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br/>					 unsigned int flags);
-int	<a href="#virConnectNumOfDefinedDomains">virConnectNumOfDefinedDomains</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn);
+char *	<a href="#virConnectExportDomainXML">virConnectExportDomainXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * format, <br/>					 const char * xml, <br/>					 unsigned int flags);
 <a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	<a href="#virStorageVolLookupByKey">virStorageVolLookupByKey</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>							 const char * key);
 int	<a href="#virDomainUndefine">virDomainUndefine</a>		(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain);
 int	<a href="#virDomainReboot">virDomainReboot</a>			(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain, <br/>					 unsigned int flags);
@@ -260,6 +261,7 @@ int	<a href="#virConnectNumOfDefinedStor
 const char *	<a href="#virNodeDeviceGetParent">virNodeDeviceGetParent</a>	(<a href="libvirt-libvirt.html#virNodeDevicePtr">virNodeDevicePtr</a> dev);
 <a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a>	<a href="#virConnectOpen">virConnectOpen</a>		(const char * name);
 <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a>	<a href="#virDomainCreateXML">virDomainCreateXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * xmlDesc, <br/>					 unsigned int flags);
+int	<a href="#virConnectNumOfDefinedDomains">virConnectNumOfDefinedDomains</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn);
 int	<a href="#virNodeDeviceRef">virNodeDeviceRef</a>		(<a href="libvirt-libvirt.html#virNodeDevicePtr">virNodeDevicePtr</a> dev);
 int	<a href="#virDomainSetVcpus">virDomainSetVcpus</a>		(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain, <br/>					 unsigned int nvcpus);
 int	<a href="#virDomainRef">virDomainRef</a>			(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain);
@@ -792,6 +794,10 @@ The content of this structure is not mad
 </pre><p>Adds a Domain Event Callback. Registering for a domain callback will enable delivery of the events The <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> object handle passed into the callback upon delivery of an event is only valid for the duration of execution of the callback. If the callback wishes to keep the domain object after the callback</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the connection</td></tr><tr><td><span class="term"><i><tt>cb</tt></i>:</span></td><td>callback to the function handling domain events</td></tr><tr><td><span class="term"><i><tt>opaque</tt></i>:</span></td><td>opaque data to pass on to the callback</td></tr><tr><td><span class="term"><i><tt>freecb</tt></i>:</span></td><td>optional function to deallocate opaque when not used anymore</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>it shall take a reference to it, by calling virDomainRef. The reference can be released once the object is no longer required by calling virDomainFree. Returns 0 on success, -1 on failure</td></tr></tbody></table></div></div>
         <hr/>
+        <div class="refsect2" lang="en"><h3><a name="virConnectExportDomainXML"/>virConnectExportDomainXML ()</h3><pre class="programlisting">char *	virConnectExportDomainXML	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * format, <br/>					 const char * xml, <br/>					 unsigned int flags)<br/>
+</pre><p>Reads a domain XML configuration document, and generates generates a native configuration file describing the domain. The format of the native data is hypervisor dependant.</p>
+<div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>a connection object</td></tr><tr><td><span class="term"><i><tt>format</tt></i>:</span></td><td>configuration format exporting to</td></tr><tr><td><span class="term"><i><tt>xml</tt></i>:</span></td><td>the domain configuration to export</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>currently unused, pass 0</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a 0 terminated UTF-8 encoded native config datafile, or NULL in case of error. the caller must free() the returned value.</td></tr></tbody></table></div></div>
+        <hr/>
         <div class="refsect2" lang="en"><h3><a name="virConnectFindStoragePoolSources"/>virConnectFindStoragePoolSources ()</h3><pre class="programlisting">char *	virConnectFindStoragePoolSources	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>						 const char * type, <br/>						 const char * srcSpec, <br/>						 unsigned int flags)<br/>
 </pre><p>Talks to a storage backend and attempts to auto-discover the set of available storage pool sources. e.g. For iSCSI this would be a set of iSCSI targets. For NFS this would be a list of exported paths. The srcSpec (optional for some storage pool types, e.g. local ones) is an instance of the storage pool's source element specifying where to look for the pools. srcSpec is not required for some types (e.g., those querying local storage resources only)</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to hypervisor connection</td></tr><tr><td><span class="term"><i><tt>type</tt></i>:</span></td><td>type of storage pool sources to discover</td></tr><tr><td><span class="term"><i><tt>srcSpec</tt></i>:</span></td><td>XML document specifying discovery source</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for discovery (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>an xml document consisting of a SourceList element containing a source document appropriate to the given pool type for each discovered source.</td></tr></tbody></table></div></div>
@@ -820,6 +826,10 @@ The content of this structure is not mad
 </pre><p>Get the version level of the Hypervisor running. This may work only with hypervisor call, i.e. with privileged access to the hypervisor, not with a Read-Only connection.</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>hvVer</tt></i>:</span></td><td>return value for the version of the running hypervisor (OUT)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>-1 in case of error, 0 otherwise. if the version can't be extracted by lack of capacities returns 0 and @hvVer is 0, otherwise @hvVer value is major * 1,000,000 + minor * 1,000 + release</td></tr></tbody></table></div></div>
         <hr/>
+        <div class="refsect2" lang="en"><h3><a name="virConnectImportDomainXML"/>virConnectImportDomainXML ()</h3><pre class="programlisting">char *	virConnectImportDomainXML	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * format, <br/>					 const char * config, <br/>					 unsigned int flags)<br/>
+</pre><p>Reads native configuration data describing a domain, and generates libvirt domain XML. The format of the native data is hypervisor dependant.</p>
+<div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>a connection object</td></tr><tr><td><span class="term"><i><tt>format</tt></i>:</span></td><td>configuration format importing from</td></tr><tr><td><span class="term"><i><tt>config</tt></i>:</span></td><td>the configuration data to import</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>currently unused, pass 0</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. the caller must free() the returned value.</td></tr></tbody></table></div></div>
+        <hr/>
         <div class="refsect2" lang="en"><h3><a name="virConnectListDefinedDomains"/>virConnectListDefinedDomains ()</h3><pre class="programlisting">int	virConnectListDefinedDomains	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 char ** const names, <br/>					 int maxnames)<br/>
 </pre><p>list the defined but inactive domains, stores the pointers to the names in @names</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>names</tt></i>:</span></td><td>pointer to an array to store the names</td></tr><tr><td><span class="term"><i><tt>maxnames</tt></i>:</span></td><td>size of the array</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the number of names provided in the array or -1 in case of error</td></tr></tbody></table></div></div>
diff -r ba47cd6949a4 docs/html/libvirt-libvirt.html
--- a/docs/html/libvirt-libvirt.html	Thu Apr 16 12:44:17 2009 +0100
+++ b/docs/html/libvirt-libvirt.html	Fri Apr 17 10:22:22 2009 +0100
@@ -84,6 +84,7 @@ int	<a href="#virConnectDomainEventCallb
 
 int	<a href="#virConnectDomainEventDeregister">virConnectDomainEventDeregister</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb)
 int	<a href="#virConnectDomainEventRegister">virConnectDomainEventRegister</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb, <br />					 void * opaque, <br />					 <a href="libvirt-libvirt.html#virFreeCallback">virFreeCallback</a> freecb)
+char *	<a href="#virConnectExportDomainXML">virConnectExportDomainXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 const char * format, <br />					 const char * xml, <br />					 unsigned int flags)
 char *	<a href="#virConnectFindStoragePoolSources">virConnectFindStoragePoolSources</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />						 const char * type, <br />						 const char * srcSpec, <br />						 unsigned int flags)
 char *	<a href="#virConnectGetCapabilities">virConnectGetCapabilities</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)
 char *	<a href="#virConnectGetHostname">virConnectGetHostname</a>		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)
@@ -91,6 +92,7 @@ int	<a href="#virConnectGetMaxVcpus">vir
 const char *	<a href="#virConnectGetType">virConnectGetType</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)
 char *	<a href="#virConnectGetURI">virConnectGetURI</a>		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)
 int	<a href="#virConnectGetVersion">virConnectGetVersion</a>		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 unsigned long * hvVer)
+char *	<a href="#virConnectImportDomainXML">virConnectImportDomainXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 const char * format, <br />					 const char * config, <br />					 unsigned int flags)
 int	<a href="#virConnectListDefinedDomains">virConnectListDefinedDomains</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 char ** const names, <br />					 int maxnames)
 int	<a href="#virConnectListDefinedNetworks">virConnectListDefinedNetworks</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 char ** const names, <br />					 int maxnames)
 int	<a href="#virConnectListDefinedStoragePools">virConnectListDefinedStoragePools</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />						 char ** const names, <br />						 int maxnames)
@@ -359,14 +361,16 @@ int	<a href="#virStorageVolRef">virStora
 </pre><p>This function closes the connection to the Hypervisor. This should not be called if further interaction with the Hypervisor are needed especially if there is running domain which need further monitoring by the application.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 in case of success or -1 in case of error.</td></tr></tbody></table></div><h3><a name="virConnectDomainEventCallback" id="virConnectDomainEventCallback"><code>virConnectDomainEventCallback</code></a></h3><pre class="programlisting">typedef int	(*virConnectDomainEventCallback)	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> dom, <br />					 int event, <br />					 int detail, <br />					 void * opaque)
 </pre><p>A callback function to be registered, and called when a domain event occurs</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td><a href="libvirt-libvirt.html#virConnect">virConnect</a> connection</td></tr><tr><td><span class="term"><i><tt>dom</tt></i>:</span></td><td>The domain on which the event occured</td></tr><tr><td><span class="term"><i><tt>event</tt></i>:</span></td><td>The specfic <a href="libvirt-libvirt.html#virDomainEventType">virDomainEventType</a> which occured</td></tr><tr><td><span class="term"><i><tt>detail</tt></i>:</span></td><td>event specific detail information</td></tr><tr><td><span class="term"><i><tt>opaque</tt></i>:</span></td><td>opaque user data</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td></td></tr></tbody></table></div><br /><h3><a name="virConnectDomainEventDeregister" id="virConnectDomainEventDeregister"><code>virConnectDomainEventDeregister</code></a></h3><pre class="programlisting">int	virConnectDomainEventDeregister	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb)<br />
 </pre><p>Removes a Domain Event Callback. De-registering for a domain callback will disable delivery of this event type</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the connection</td></tr><tr><td><span class="term"><i><tt>cb</tt></i>:</span></td><td>callback to the function handling domain events</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 on success, -1 on failure</td></tr></tbody></table></div><h3><a name="virConnectDomainEventRegister" id="virConnectDomainEventRegister"><code>virConnectDomainEventRegister</code></a></h3><pre class="programlisting">int	virConnectDomainEventRegister	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb, <br />					 void * opaque, <br />					 <a href="libvirt-libvirt.html#virFreeCallback">virFreeCallback</a> freecb)<br />
-</pre><p>Adds a Domain Event Callback. Registering for a domain callback will enable delivery of the events The <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> object handle passed into the callback upon delivery of an event is only valid for the duration of execution of the callback. If the callback wishes to keep the domain object after the callback</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the connection</td></tr><tr><td><span class="term"><i><tt>cb</tt></i>:</span></td><td>callback to the function handling domain events</td></tr><tr><td><span class="term"><i><tt>opaque</tt></i>:</span></td><td>opaque data to pass on to the callback</td></tr><tr><td><span class="term"><i><tt>freecb</tt></i>:</span></td><td>optional function to deallocate opaque when not used anymore</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>it shall take a reference to it, by calling virDomainRef. The reference can be released once the object is no longer required by calling virDomainFree. Returns 0 on success, -1 on failure</td></tr></tbody></table></div><h3><a name="virConnectFindStoragePoolSources" id="virConnectFindStoragePoolSources"><code>virConnectFindStoragePoolSources</code></a></h3><pre class="programlisting">char *	virConnectFindStoragePoolSources	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />						 const char * type, <br />						 const char * srcSpec, <br />						 unsigned int flags)<br />
+</pre><p>Adds a Domain Event Callback. Registering for a domain callback will enable delivery of the events The <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> object handle passed into the callback upon delivery of an event is only valid for the duration of execution of the callback. If the callback wishes to keep the domain object after the callback</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the connection</td></tr><tr><td><span class="term"><i><tt>cb</tt></i>:</span></td><td>callback to the function handling domain events</td></tr><tr><td><span class="term"><i><tt>opaque</tt></i>:</span></td><td>opaque data to pass on to the callback</td></tr><tr><td><span class="term"><i><tt>freecb</tt></i>:</span></td><td>optional function to deallocate opaque when not used anymore</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>it shall take a reference to it, by calling virDomainRef. The reference can be released once the object is no longer required by calling virDomainFree. Returns 0 on success, -1 on failure</td></tr></tbody></table></div><h3><a name="virConnectExportDomainXML" id="virConnectExportDomainXML"><code>virConnectExportDomainXML</code></a></h3><pre class="programlisting">char *	virConnectExportDomainXML	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 const char * format, <br />					 const char * xml, <br />					 unsigned int flags)<br />
+</pre><p>Reads a domain XML configuration document, and generates generates a native configuration file describing the domain. The format of the native data is hypervisor dependant.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>a connection object</td></tr><tr><td><span class="term"><i><tt>format</tt></i>:</span></td><td>configuration format exporting to</td></tr><tr><td><span class="term"><i><tt>xml</tt></i>:</span></td><td>the domain configuration to export</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>currently unused, pass 0</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a 0 terminated UTF-8 encoded native config datafile, or NULL in case of error. the caller must free() the returned value.</td></tr></tbody></table></div><h3><a name="virConnectFindStoragePoolSources" id="virConnectFindStoragePoolSources"><code>virConnectFindStoragePoolSources</code></a></h3><pre class="programlisting">char *	virConnectFindStoragePoolSources	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />						 const char * type, <br />						 const char * srcSpec, <br />						 unsigned int flags)<br />
 </pre><p>Talks to a storage backend and attempts to auto-discover the set of available storage pool sources. e.g. For iSCSI this would be a set of iSCSI targets. For NFS this would be a list of exported paths. The srcSpec (optional for some storage pool types, e.g. local ones) is an instance of the storage pool's source element specifying where to look for the pools. srcSpec is not required for some types (e.g., those querying local storage resources only)</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to hypervisor connection</td></tr><tr><td><span class="term"><i><tt>type</tt></i>:</span></td><td>type of storage pool sources to discover</td></tr><tr><td><span class="term"><i><tt>srcSpec</tt></i>:</span></td><td>XML document specifying discovery source</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for discovery (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>an xml document consisting of a SourceList element containing a source document appropriate to the given pool type for each discovered source.</td></tr></tbody></table></div><h3><a name="virConnectGetCapabilities" id="virConnectGetCapabilities"><code>virConnectGetCapabilities</code></a></h3><pre class="programlisting">char *	virConnectGetCapabilities	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)<br />
 </pre><p>Provides capabilities of the hypervisor / driver.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>NULL in case of error, or an XML string defining the capabilities. The client must free the returned string after use.</td></tr></tbody></table></div><h3><a name="virConnectGetHostname" id="virConnectGetHostname"><code>virConnectGetHostname</code></a></h3><pre class="programlisting">char *	virConnectGetHostname		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)<br />
 </pre><p>This returns the system hostname on which the hypervisor is running (the result of the gethostname(2) system call). If we are connected to a remote system, then this returns the hostname of the remote system.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to a hypervisor connection</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the hostname which must be freed by the caller, or NULL if there was an error.</td></tr></tbody></table></div><h3><a name="virConnectGetMaxVcpus" id="virConnectGetMaxVcpus"><code>virConnectGetMaxVcpus</code></a></h3><pre class="programlisting">int	virConnectGetMaxVcpus		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 const char * type)<br />
 </pre><p>Provides the maximum number of virtual CPUs supported for a guest VM of a specific type. The 'type' parameter here corresponds to the 'type' attribute in the <domain> element of the XML.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>type</tt></i>:</span></td><td>value of the 'type' attribute in the <domain> element</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the maximum of virtual CPU or -1 in case of error.</td></tr></tbody></table></div><h3><a name="virConnectGetType" id="virConnectGetType"><code>virConnectGetType</code></a></h3><pre class="programlisting">const char *	virConnectGetType	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)<br />
 </pre><p>Get the name of the Hypervisor software used.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>NULL in case of error, a static zero terminated string otherwise. See also: http://www.redhat.com/archives/libvir-list/2007-February/msg00096.html</td></tr></tbody></table></div><h3><a name="virConnectGetURI" id="virConnectGetURI"><code>virConnectGetURI</code></a></h3><pre class="programlisting">char *	virConnectGetURI		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn)<br />
 </pre><p>This returns the URI (name) of the hypervisor connection. Normally this is the same as or similar to the string passed to the virConnectOpen/virConnectOpenReadOnly call, but the driver may make the URI canonical. If name == NULL was passed to virConnectOpen, then the driver will return a non-NULL URI which can be used to connect to the same hypervisor later.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to a hypervisor connection</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the URI string which must be freed by the caller, or NULL if there was an error.</td></tr></tbody></table></div><h3><a name="virConnectGetVersion" id="virConnectGetVersion"><code>virConnectGetVersion</code></a></h3><pre class="programlisting">int	virConnectGetVersion		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 unsigned long * hvVer)<br />
-</pre><p>Get the version level of the Hypervisor running. This may work only with hypervisor call, i.e. with privileged access to the hypervisor, not with a Read-Only connection.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>hvVer</tt></i>:</span></td><td>return value for the version of the running hypervisor (OUT)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>-1 in case of error, 0 otherwise. if the version can't be extracted by lack of capacities returns 0 and @hvVer is 0, otherwise @hvVer value is major * 1,000,000 + minor * 1,000 + release</td></tr></tbody></table></div><h3><a name="virConnectListDefinedDomains" id="virConnectListDefinedDomains"><code>virConnectListDefinedDomains</code></a></h3><pre class="programlisting">int	virConnectListDefinedDomains	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 char ** const names, <br />					 int maxnames)<br />
+</pre><p>Get the version level of the Hypervisor running. This may work only with hypervisor call, i.e. with privileged access to the hypervisor, not with a Read-Only connection.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>hvVer</tt></i>:</span></td><td>return value for the version of the running hypervisor (OUT)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>-1 in case of error, 0 otherwise. if the version can't be extracted by lack of capacities returns 0 and @hvVer is 0, otherwise @hvVer value is major * 1,000,000 + minor * 1,000 + release</td></tr></tbody></table></div><h3><a name="virConnectImportDomainXML" id="virConnectImportDomainXML"><code>virConnectImportDomainXML</code></a></h3><pre class="programlisting">char *	virConnectImportDomainXML	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 const char * format, <br />					 const char * config, <br />					 unsigned int flags)<br />
+</pre><p>Reads native configuration data describing a domain, and generates libvirt domain XML. The format of the native data is hypervisor dependant.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>a connection object</td></tr><tr><td><span class="term"><i><tt>format</tt></i>:</span></td><td>configuration format importing from</td></tr><tr><td><span class="term"><i><tt>config</tt></i>:</span></td><td>the configuration data to import</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>currently unused, pass 0</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. the caller must free() the returned value.</td></tr></tbody></table></div><h3><a name="virConnectListDefinedDomains" id="virConnectListDefinedDomains"><code>virConnectListDefinedDomains</code></a></h3><pre class="programlisting">int	virConnectListDefinedDomains	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 char ** const names, <br />					 int maxnames)<br />
 </pre><p>list the defined but inactive domains, stores the pointers to the names in @names</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>names</tt></i>:</span></td><td>pointer to an array to store the names</td></tr><tr><td><span class="term"><i><tt>maxnames</tt></i>:</span></td><td>size of the array</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the number of names provided in the array or -1 in case of error</td></tr></tbody></table></div><h3><a name="virConnectListDefinedNetworks" id="virConnectListDefinedNetworks"><code>virConnectListDefinedNetworks</code></a></h3><pre class="programlisting">int	virConnectListDefinedNetworks	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 char ** const names, <br />					 int maxnames)<br />
 </pre><p>list the inactive networks, stores the pointers to the names in @names</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to the hypervisor connection</td></tr><tr><td><span class="term"><i><tt>names</tt></i>:</span></td><td>pointer to an array to store the names</td></tr><tr><td><span class="term"><i><tt>maxnames</tt></i>:</span></td><td>size of the array</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the number of names provided in the array or -1 in case of error</td></tr></tbody></table></div><h3><a name="virConnectListDefinedStoragePools" id="virConnectListDefinedStoragePools"><code>virConnectListDefinedStoragePools</code></a></h3><pre class="programlisting">int	virConnectListDefinedStoragePools	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />						 char ** const names, <br />						 int maxnames)<br />
 </pre><p>Provides the list of names of inactive storage pools upto maxnames. If there are more than maxnames, the remaining names will be silently ignored.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>conn</tt></i>:</span></td><td>pointer to hypervisor connection</td></tr><tr><td><span class="term"><i><tt>names</tt></i>:</span></td><td>array of char * to fill with pool names (allocated by caller)</td></tr><tr><td><span class="term"><i><tt>maxnames</tt></i>:</span></td><td>size of the names array</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 on success, -1 on error</td></tr></tbody></table></div><h3><a name="virConnectListDomains" id="virConnectListDomains"><code>virConnectListDomains</code></a></h3><pre class="programlisting">int	virConnectListDomains		(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br />					 int * ids, <br />					 int maxids)<br />
diff -r ba47cd6949a4 docs/libvirt-api.xml
--- a/docs/libvirt-api.xml	Thu Apr 16 12:44:17 2009 +0100
+++ b/docs/libvirt-api.xml	Fri Apr 17 10:22:22 2009 +0100
@@ -176,6 +176,7 @@
      <exports symbol='virDomainGetSecurityLabel' type='function'/>
      <exports symbol='virConnectDomainEventDeregister' type='function'/>
      <exports symbol='virDomainGetSchedulerParameters' type='function'/>
+     <exports symbol='virConnectImportDomainXML' type='function'/>
      <exports symbol='virDomainLookupByUUIDString' type='function'/>
      <exports symbol='virConnectNumOfDefinedNetworks' type='function'/>
      <exports symbol='virConnectNumOfDomains' type='function'/>
@@ -268,7 +269,7 @@
      <exports symbol='virNodeListDevices' type='function'/>
      <exports symbol='virNetworkRef' type='function'/>
      <exports symbol='virStoragePoolRefresh' type='function'/>
-     <exports symbol='virConnectNumOfDefinedDomains' type='function'/>
+     <exports symbol='virConnectExportDomainXML' type='function'/>
      <exports symbol='virStorageVolLookupByKey' type='function'/>
      <exports symbol='virDomainUndefine' type='function'/>
      <exports symbol='virDomainReboot' type='function'/>
@@ -310,6 +311,7 @@
      <exports symbol='virNodeDeviceGetParent' type='function'/>
      <exports symbol='virConnectOpen' type='function'/>
      <exports symbol='virDomainCreateXML' type='function'/>
+     <exports symbol='virConnectNumOfDefinedDomains' type='function'/>
      <exports symbol='virNodeDeviceRef' type='function'/>
      <exports symbol='virDomainSetVcpus' type='function'/>
      <exports symbol='virDomainRef' type='function'/>
@@ -864,6 +866,14 @@ see note above'/>
       <arg name='opaque' type='void *' info='opaque data to pass on to the callback'/>
       <arg name='freecb' type='virFreeCallback' info='optional function to deallocate opaque when not used anymore'/>
     </function>
+    <function name='virConnectExportDomainXML' file='libvirt' module='libvirt'>
+      <info>Reads a domain XML configuration document, and generates generates a native configuration file describing the domain. The format of the native data is hypervisor dependant.</info>
+      <return type='char *' info='a 0 terminated UTF-8 encoded native config datafile, or NULL in case of error. the caller must free() the returned value.'/>
+      <arg name='conn' type='virConnectPtr' info='a connection object'/>
+      <arg name='format' type='const char *' info='configuration format exporting to'/>
+      <arg name='xml' type='const char *' info='the domain configuration to export'/>
+      <arg name='flags' type='unsigned int' info='currently unused, pass 0'/>
+    </function>
     <function name='virConnectFindStoragePoolSources' file='libvirt' module='libvirt'>
       <info>Talks to a storage backend and attempts to auto-discover the set of available storage pool sources. e.g. For iSCSI this would be a set of iSCSI targets. For NFS this would be a list of exported paths.  The srcSpec (optional for some storage pool types, e.g. local ones) is an instance of the storage pool's source element specifying where to look for the pools.  srcSpec is not required for some types (e.g., those querying local storage resources only)</info>
       <return type='char *' info='an xml document consisting of a SourceList element containing a source document appropriate to the given pool type for each discovered source.'/>
@@ -904,6 +914,14 @@ see note above'/>
       <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
       <arg name='hvVer' type='unsigned long *' info='return value for the version of the running hypervisor (OUT)'/>
     </function>
+    <function name='virConnectImportDomainXML' file='libvirt' module='libvirt'>
+      <info>Reads native configuration data  describing a domain, and generates libvirt domain XML. The format of the native data is hypervisor dependant.</info>
+      <return type='char *' info='a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. the caller must free() the returned value.'/>
+      <arg name='conn' type='virConnectPtr' info='a connection object'/>
+      <arg name='format' type='const char *' info='configuration format importing from'/>
+      <arg name='config' type='const char *' info='the configuration data to import'/>
+      <arg name='flags' type='unsigned int' info='currently unused, pass 0'/>
+    </function>
     <function name='virConnectListDefinedDomains' file='libvirt' module='libvirt'>
       <info>list the defined but inactive domains, stores the pointers to the names in @names</info>
       <return type='int' info='the number of names provided in the array or -1 in case of error'/>
diff -r ba47cd6949a4 docs/libvirt-refs.xml
--- a/docs/libvirt-refs.xml	Thu Apr 16 12:44:17 2009 +0100
+++ b/docs/libvirt-refs.xml	Fri Apr 17 10:22:22 2009 +0100
@@ -197,6 +197,7 @@
     <reference name='virConnectDomainEventCallback' href='html/libvirt-libvirt.html#virConnectDomainEventCallback'/>
     <reference name='virConnectDomainEventDeregister' href='html/libvirt-libvirt.html#virConnectDomainEventDeregister'/>
     <reference name='virConnectDomainEventRegister' href='html/libvirt-libvirt.html#virConnectDomainEventRegister'/>
+    <reference name='virConnectExportDomainXML' href='html/libvirt-libvirt.html#virConnectExportDomainXML'/>
     <reference name='virConnectFindStoragePoolSources' href='html/libvirt-libvirt.html#virConnectFindStoragePoolSources'/>
     <reference name='virConnectFlags' href='html/libvirt-libvirt.html#virConnectFlags'/>
     <reference name='virConnectGetCapabilities' href='html/libvirt-libvirt.html#virConnectGetCapabilities'/>
@@ -205,6 +206,7 @@
     <reference name='virConnectGetType' href='html/libvirt-libvirt.html#virConnectGetType'/>
     <reference name='virConnectGetURI' href='html/libvirt-libvirt.html#virConnectGetURI'/>
     <reference name='virConnectGetVersion' href='html/libvirt-libvirt.html#virConnectGetVersion'/>
+    <reference name='virConnectImportDomainXML' href='html/libvirt-libvirt.html#virConnectImportDomainXML'/>
     <reference name='virConnectListDefinedDomains' href='html/libvirt-libvirt.html#virConnectListDefinedDomains'/>
     <reference name='virConnectListDefinedNetworks' href='html/libvirt-libvirt.html#virConnectListDefinedNetworks'/>
     <reference name='virConnectListDefinedStoragePools' href='html/libvirt-libvirt.html#virConnectListDefinedStoragePools'/>
@@ -622,6 +624,7 @@
       <ref name='virConnectDomainEventCallback'/>
       <ref name='virConnectDomainEventDeregister'/>
       <ref name='virConnectDomainEventRegister'/>
+      <ref name='virConnectExportDomainXML'/>
       <ref name='virConnectFindStoragePoolSources'/>
       <ref name='virConnectFlags'/>
       <ref name='virConnectGetCapabilities'/>
@@ -630,6 +633,7 @@
       <ref name='virConnectGetType'/>
       <ref name='virConnectGetURI'/>
       <ref name='virConnectGetVersion'/>
+      <ref name='virConnectImportDomainXML'/>
       <ref name='virConnectListDefinedDomains'/>
       <ref name='virConnectListDefinedNetworks'/>
       <ref name='virConnectListDefinedStoragePools'/>
@@ -942,7 +946,9 @@
     </type>
     <type name='unsigned int'>
       <ref name='virConnectAuthCallbackPtr'/>
+      <ref name='virConnectExportDomainXML'/>
       <ref name='virConnectFindStoragePoolSources'/>
+      <ref name='virConnectImportDomainXML'/>
       <ref name='virDomainBlockPeek'/>
       <ref name='virDomainCreateLinux'/>
       <ref name='virDomainCreateXML'/>
@@ -999,6 +1005,7 @@
       <ref name='virConnectDomainEventCallback'/>
       <ref name='virConnectDomainEventDeregister'/>
       <ref name='virConnectDomainEventRegister'/>
+      <ref name='virConnectExportDomainXML'/>
       <ref name='virConnectFindStoragePoolSources'/>
       <ref name='virConnectGetCapabilities'/>
       <ref name='virConnectGetHostname'/>
@@ -1006,6 +1013,7 @@
       <ref name='virConnectGetType'/>
       <ref name='virConnectGetURI'/>
       <ref name='virConnectGetVersion'/>
+      <ref name='virConnectImportDomainXML'/>
       <ref name='virConnectListDefinedDomains'/>
       <ref name='virConnectListDefinedNetworks'/>
       <ref name='virConnectListDefinedStoragePools'/>
@@ -1349,6 +1357,7 @@
       <ref name='virConnectDomainEventCallback'/>
       <ref name='virConnectDomainEventDeregister'/>
       <ref name='virConnectDomainEventRegister'/>
+      <ref name='virConnectExportDomainXML'/>
       <ref name='virConnectFindStoragePoolSources'/>
       <ref name='virConnectFlags'/>
       <ref name='virConnectGetCapabilities'/>
@@ -1357,6 +1366,7 @@
       <ref name='virConnectGetType'/>
       <ref name='virConnectGetURI'/>
       <ref name='virConnectGetVersion'/>
+      <ref name='virConnectImportDomainXML'/>
       <ref name='virConnectListDefinedDomains'/>
       <ref name='virConnectListDefinedNetworks'/>
       <ref name='virConnectListDefinedStoragePools'/>
@@ -2162,6 +2172,10 @@
         <word name='Read-Only'>
           <ref name='virConnectGetVersion'/>
         </word>
+        <word name='Reads'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
         <word name='Reboot'>
           <ref name='virDomainReboot'/>
         </word>
@@ -2294,6 +2308,8 @@
           <ref name='VIR_USE_CPU'/>
         </word>
         <word name='UTF-8'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainDefineXML'/>
           <ref name='virDomainGetXMLDesc'/>
           <ref name='virNetworkDefineXML'/>
@@ -2381,26 +2397,6 @@
         </word>
       </letter>
       <letter name='X'>
-        <word name='XML'>
-          <ref name='virConnectFindStoragePoolSources'/>
-          <ref name='virConnectGetCapabilities'/>
-          <ref name='virConnectGetMaxVcpus'/>
-          <ref name='virDomainAttachDevice'/>
-          <ref name='virDomainCreateLinux'/>
-          <ref name='virDomainCreateXML'/>
-          <ref name='virDomainDefineXML'/>
-          <ref name='virDomainDetachDevice'/>
-          <ref name='virDomainGetXMLDesc'/>
-          <ref name='virNetworkCreateXML'/>
-          <ref name='virNetworkDefineXML'/>
-          <ref name='virNetworkGetXMLDesc'/>
-          <ref name='virNodeDeviceGetXMLDesc'/>
-          <ref name='virStoragePoolCreateXML'/>
-          <ref name='virStoragePoolDefineXML'/>
-          <ref name='virStoragePoolGetXMLDesc'/>
-          <ref name='virStorageVolCreateXML'/>
-          <ref name='virStorageVolGetXMLDesc'/>
-        </word>
         <word name='Xen'>
           <ref name='_virDomainBlockStats'/>
           <ref name='virDomainCoreDump'/>
@@ -2902,8 +2898,10 @@
         </word>
         <word name='caller'>
           <ref name='cpumap'/>
-          <ref name='virConnectGetHostname'/>
-          <ref name='virConnectGetURI'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetHostname'/>
+          <ref name='virConnectGetURI'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virConnectListDefinedStoragePools'/>
           <ref name='virConnectListStoragePools'/>
           <ref name='virConnectRef'/>
@@ -3074,9 +3072,12 @@
           <ref name='virResetLastError'/>
         </word>
         <word name='config'>
+          <ref name='virConnectExportDomainXML'/>
           <ref name='virStoragePoolDestroy'/>
         </word>
         <word name='configuration'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virStorageVolGetPath'/>
         </word>
         <word name='configured'>
@@ -3224,6 +3225,8 @@
           <ref name='virStorageVolGetInfo'/>
         </word>
         <word name='currently'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainCoreDump'/>
           <ref name='virNodeDeviceReAttach'/>
           <ref name='virNodeDeviceReset'/>
@@ -3237,16 +3240,21 @@
           <ref name='virConnSetErrorFunc'/>
           <ref name='virConnectDomainEventCallback'/>
           <ref name='virConnectDomainEventRegister'/>
-          <ref name='virDomainFree'/>
-          <ref name='virErrorFunc'/>
-          <ref name='virEventAddHandleFunc'/>
-          <ref name='virEventAddTimeoutFunc'/>
-          <ref name='virEventHandleCallback'/>
-          <ref name='virEventRemoveHandleFunc'/>
-          <ref name='virEventRemoveTimeoutFunc'/>
-          <ref name='virEventTimeoutCallback'/>
-          <ref name='virNetworkFree'/>
-          <ref name='virSetErrorFunc'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
+          <ref name='virDomainFree'/>
+          <ref name='virErrorFunc'/>
+          <ref name='virEventAddHandleFunc'/>
+          <ref name='virEventAddTimeoutFunc'/>
+          <ref name='virEventHandleCallback'/>
+          <ref name='virEventRemoveHandleFunc'/>
+          <ref name='virEventRemoveTimeoutFunc'/>
+          <ref name='virEventTimeoutCallback'/>
+          <ref name='virNetworkFree'/>
+          <ref name='virSetErrorFunc'/>
+        </word>
+        <word name='datafile'>
+          <ref name='virConnectExportDomainXML'/>
         </word>
         <word name='dconn'>
           <ref name='virDomainMigrate'/>
@@ -3297,6 +3305,10 @@
           <ref name='virConnectDomainEventDeregister'/>
           <ref name='virConnectDomainEventRegister'/>
         </word>
+        <word name='dependant'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
         <word name='depends'>
           <ref name='virNodeDeviceReset'/>
         </word>
@@ -3307,6 +3319,8 @@
           <ref name='virDomainGetVcpus'/>
         </word>
         <word name='describing'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virNodeDeviceGetXMLDesc'/>
           <ref name='virStoragePoolGetXMLDesc'/>
           <ref name='virStorageVolGetXMLDesc'/>
@@ -3406,6 +3420,7 @@
           <ref name='virDomainShutdown'/>
         </word>
         <word name='document'>
+          <ref name='virConnectExportDomainXML'/>
           <ref name='virConnectFindStoragePoolSources'/>
           <ref name='virNodeDeviceGetXMLDesc'/>
           <ref name='virStoragePoolGetXMLDesc'/>
@@ -3521,6 +3536,8 @@
           <ref name='virConnectDomainEventRegister'/>
         </word>
         <word name='encoded'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainGetXMLDesc'/>
           <ref name='virNetworkGetXMLDesc'/>
         </word>
@@ -3594,9 +3611,15 @@
           <ref name='virDomainDefineXML'/>
           <ref name='virStoragePoolDefineXML'/>
         </word>
+        <word name='export'>
+          <ref name='virConnectExportDomainXML'/>
+        </word>
         <word name='exported'>
           <ref name='virConnectFindStoragePoolSources'/>
         </word>
+        <word name='exporting'>
+          <ref name='virConnectExportDomainXML'/>
+        </word>
         <word name='extra'>
           <ref name='_virError'/>
           <ref name='virDomainCoreDump'/>
@@ -3658,6 +3681,7 @@
           <ref name='virDomainInterfaceStats'/>
         </word>
         <word name='file'>
+          <ref name='virConnectExportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainCoreDump'/>
           <ref name='virDomainSave'/>
@@ -3738,6 +3762,8 @@
           <ref name='virDomainMigrate'/>
         </word>
         <word name='format'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainGetVcpus'/>
           <ref name='virGetVersion'/>
           <ref name='virStoragePoolGetXMLDesc'/>
@@ -3773,7 +3799,9 @@
         <word name='free'>
           <ref name='_virStoragePoolInfo'/>
           <ref name='virConnCopyLastError'/>
-          <ref name='virConnectGetCapabilities'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetCapabilities'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virCopyLastError'/>
           <ref name='virDomainDestroy'/>
           <ref name='virDomainGetSchedulerType'/>
@@ -3817,6 +3845,7 @@
           <ref name='_virVcpuInfo'/>
           <ref name='virConnCopyLastError'/>
           <ref name='virConnGetLastError'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainCreate'/>
           <ref name='virDomainGetVcpus'/>
@@ -3855,6 +3884,10 @@
         <word name='general'>
           <ref name='virDomainShutdown'/>
         </word>
+        <word name='generates'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
         <word name='generation'>
           <ref name='virNodeDeviceGetXMLDesc'/>
           <ref name='virStorageVolGetXMLDesc'/>
@@ -4049,6 +4082,12 @@
         <word name='image'>
           <ref name='virDomainMemoryPeek'/>
         </word>
+        <word name='import'>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
+        <word name='importing'>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
         <word name='imposed'>
           <ref name='virDomainMigrate'/>
         </word>
@@ -4139,6 +4178,7 @@
         <word name='instance'>
           <ref name='nodeinfo'/>
           <ref name='virConnectFindStoragePoolSources'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainDestroy'/>
           <ref name='virDomainFree'/>
           <ref name='virDomainGetXMLDesc'/>
@@ -4349,6 +4389,7 @@
           <ref name='virConnectGetType'/>
         </word>
         <word name='libvirt'>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virConnectOpen'/>
           <ref name='virConnectOpenAuth'/>
           <ref name='virConnectOpenReadOnly'/>
@@ -4662,9 +4703,11 @@
         </word>
         <word name='must'>
           <ref name='cpumap'/>
-          <ref name='virConnectGetCapabilities'/>
-          <ref name='virConnectGetHostname'/>
-          <ref name='virConnectGetURI'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetCapabilities'/>
+          <ref name='virConnectGetHostname'/>
+          <ref name='virConnectGetURI'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainGetOSType'/>
           <ref name='virDomainGetSchedulerType'/>
@@ -4700,6 +4743,10 @@
           <ref name='_virDomainInfo'/>
           <ref name='_virVcpuInfo'/>
         </word>
+        <word name='native'>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectImportDomainXML'/>
+        </word>
         <word name='necessary'>
           <ref name='VIR_NODEINFO_MAXCPUS'/>
           <ref name='virConnectOpenAuth'/>
@@ -4972,7 +5019,9 @@
         <word name='pass'>
           <ref name='virConnSetErrorFunc'/>
           <ref name='virConnectDomainEventRegister'/>
-          <ref name='virConnectFindStoragePoolSources'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectFindStoragePoolSources'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainCreateLinux'/>
           <ref name='virDomainCreateXML'/>
@@ -5402,7 +5451,9 @@
           <ref name='virNodeGetCellsFreeMemory'/>
         </word>
         <word name='returned'>
-          <ref name='virConnectGetCapabilities'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetCapabilities'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainBlockStats'/>
           <ref name='virDomainCreateXML'/>
@@ -5464,6 +5515,8 @@
           <ref name='virDomainSetMemory'/>
         </word>
       </letter>
+    </chunk>
+    <chunk name='chunk9'>
       <letter name='s'>
         <word name='safe'>
           <ref name='virEventRemoveHandleFunc'/>
@@ -5844,7 +5897,7 @@
         </word>
       </letter>
     </chunk>
-    <chunk name='chunk9'>
+    <chunk name='chunk10'>
       <letter name='t'>
         <word name='take'>
           <ref name='virConnectDomainEventRegister'/>
@@ -5865,7 +5918,9 @@
           <ref name='virDomainMigrate'/>
         </word>
         <word name='terminated'>
-          <ref name='virConnectGetType'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetType'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainGetXMLDesc'/>
           <ref name='virNetworkGetBridgeName'/>
           <ref name='virNetworkGetXMLDesc'/>
@@ -6092,7 +6147,9 @@
           <ref name='virStorageVolRef'/>
         </word>
         <word name='unused'>
-          <ref name='virConnectFindStoragePoolSources'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectFindStoragePoolSources'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainBlockPeek'/>
           <ref name='virDomainCoreDump'/>
           <ref name='virNodeDeviceGetXMLDesc'/>
@@ -6228,7 +6285,7 @@
         </word>
       </letter>
     </chunk>
-    <chunk name='chunk10'>
+    <chunk name='chunk11'>
       <letter name='v'>
         <word name='valid'>
           <ref name='virConnectDomainEventRegister'/>
@@ -6237,8 +6294,10 @@
           <ref name='VIR_CPU_USABLE'/>
           <ref name='VIR_SECURITY_LABEL_BUFLEN'/>
           <ref name='_virVcpuInfo'/>
-          <ref name='virConnectGetMaxVcpus'/>
-          <ref name='virConnectGetVersion'/>
+          <ref name='virConnectExportDomainXML'/>
+          <ref name='virConnectGetMaxVcpus'/>
+          <ref name='virConnectGetVersion'/>
+          <ref name='virConnectImportDomainXML'/>
           <ref name='virDomainGetAutostart'/>
           <ref name='virDomainGetSchedulerParameters'/>
           <ref name='virDomainGetSchedulerType'/>
@@ -6633,7 +6692,7 @@
         </word>
       </letter>
     </chunk>
-    <chunk name='chunk11'>
+    <chunk name='chunk12'>
       <letter name='x'>
         <word name='xen'>
           <ref name='virConnectOpen'/>
@@ -6679,10 +6738,11 @@
       <chunk name='chunk5' start='h' end='k'/>
       <chunk name='chunk6' start='l' end='m'/>
       <chunk name='chunk7' start='n' end='p'/>
-      <chunk name='chunk8' start='q' end='s'/>
-      <chunk name='chunk9' start='t' end='u'/>
-      <chunk name='chunk10' start='v' end='w'/>
-      <chunk name='chunk11' start='x' end='z'/>
+      <chunk name='chunk8' start='q' end='r'/>
+      <chunk name='chunk9' start='s' end='s'/>
+      <chunk name='chunk10' start='t' end='u'/>
+      <chunk name='chunk11' start='v' end='w'/>
+      <chunk name='chunk12' start='x' end='z'/>
     </chunks>
   </index>
 </apirefs>
diff -r ba47cd6949a4 include/libvirt/libvirt.h
--- a/include/libvirt/libvirt.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/include/libvirt/libvirt.h	Fri Apr 17 10:22:22 2009 +0100
@@ -591,6 +591,16 @@ typedef enum {
 char *                  virDomainGetXMLDesc     (virDomainPtr domain,
                                                  int flags);
 
+
+char *                  virConnectImportDomainXML(virConnectPtr conn,
+                                                  const char *format,
+                                                  const char *config,
+                                                  unsigned int flags);
+char *                  virConnectExportDomainXML(virConnectPtr conn,
+                                                  const char *format,
+                                                  const char *xml,
+                                                  unsigned int flags);
+
 int                     virDomainBlockStats     (virDomainPtr dom,
                                                  const char *path,
                                                  virDomainBlockStatsPtr stats,
diff -r ba47cd6949a4 include/libvirt/libvirt.h.in
--- a/include/libvirt/libvirt.h.in	Thu Apr 16 12:44:17 2009 +0100
+++ b/include/libvirt/libvirt.h.in	Fri Apr 17 10:22:22 2009 +0100
@@ -591,6 +591,16 @@ typedef enum {
 char *                  virDomainGetXMLDesc     (virDomainPtr domain,
                                                  int flags);
 
+
+char *                  virConnectImportDomainXML(virConnectPtr conn,
+                                                  const char *format,
+                                                  const char *config,
+                                                  unsigned int flags);
+char *                  virConnectExportDomainXML(virConnectPtr conn,
+                                                  const char *format,
+                                                  const char *xml,
+                                                  unsigned int flags);
+
 int                     virDomainBlockStats     (virDomainPtr dom,
                                                  const char *path,
                                                  virDomainBlockStatsPtr stats,
diff -r ba47cd6949a4 qemud/remote.c
--- a/qemud/remote.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1236,6 +1236,40 @@ remoteDispatchDomainDumpXml (struct qemu
 }
 
 static int
+remoteDispatchImportDomainXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client ATTRIBUTE_UNUSED,
+                               virConnectPtr conn,
+                               remote_error *rerr,
+                               remote_import_domain_xml_args *args,
+                               remote_import_domain_xml_ret *ret)
+{
+    /* remoteDispatchClientRequest will free this. */
+    ret->xml = virConnectImportDomainXML (conn, args->format, args->config, args->flags);
+    if (!ret->xml) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    return 0;
+}
+
+static int
+remoteDispatchExportDomainXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client ATTRIBUTE_UNUSED,
+                               virConnectPtr conn,
+                               remote_error *rerr,
+                               remote_export_domain_xml_args *args,
+                               remote_export_domain_xml_ret *ret)
+{
+    /* remoteDispatchClientRequest will free this. */
+    ret->config = virConnectExportDomainXML (conn, args->format, args->xml, args->flags);
+    if (!ret->config) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    return 0;
+}
+
+static int
 remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
diff -r ba47cd6949a4 qemud/remote_dispatch_args.h
--- a/qemud/remote_dispatch_args.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_dispatch_args.h	Fri Apr 17 10:22:22 2009 +0100
@@ -103,3 +103,5 @@
     remote_node_device_re_attach_args val_remote_node_device_re_attach_args;
     remote_node_device_reset_args val_remote_node_device_reset_args;
     remote_domain_get_security_label_args val_remote_domain_get_security_label_args;
+    remote_import_domain_xml_args val_remote_import_domain_xml_args;
+    remote_export_domain_xml_args val_remote_export_domain_xml_args;
diff -r ba47cd6949a4 qemud/remote_dispatch_prototypes.h
--- a/qemud/remote_dispatch_prototypes.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_dispatch_prototypes.h	Fri Apr 17 10:22:22 2009 +0100
@@ -359,6 +359,13 @@ static int remoteDispatchDomainUndefine(
     remote_error *err,
     remote_domain_undefine_args *args,
     void *ret);
+static int remoteDispatchExportDomainXml(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_export_domain_xml_args *args,
+    remote_export_domain_xml_ret *ret);
 static int remoteDispatchFindStoragePoolSources(
     struct qemud_server *server,
     struct qemud_client *client,
@@ -408,6 +415,13 @@ static int remoteDispatchGetVersion(
     remote_error *err,
     void *args,
     remote_get_version_ret *ret);
+static int remoteDispatchImportDomainXml(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_import_domain_xml_args *args,
+    remote_import_domain_xml_ret *ret);
 static int remoteDispatchListDefinedDomains(
     struct qemud_server *server,
     struct qemud_client *client,
diff -r ba47cd6949a4 qemud/remote_dispatch_ret.h
--- a/qemud/remote_dispatch_ret.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_dispatch_ret.h	Fri Apr 17 10:22:22 2009 +0100
@@ -88,3 +88,5 @@
     remote_node_device_list_caps_ret val_remote_node_device_list_caps_ret;
     remote_domain_get_security_label_ret val_remote_domain_get_security_label_ret;
     remote_node_get_security_model_ret val_remote_node_get_security_model_ret;
+    remote_import_domain_xml_ret val_remote_import_domain_xml_ret;
+    remote_export_domain_xml_ret val_remote_export_domain_xml_ret;
diff -r ba47cd6949a4 qemud/remote_dispatch_table.h
--- a/qemud/remote_dispatch_table.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_dispatch_table.h	Fri Apr 17 10:22:22 2009 +0100
@@ -607,13 +607,23 @@
     .args_filter = (xdrproc_t) xdr_remote_node_device_reset_args,
     .ret_filter = (xdrproc_t) xdr_void,
 },
-{   /* DomainGetSecurityLabel => 118 */
+{   /* DomainGetSecurityLabel => 121 */
     .fn = (dispatch_fn) remoteDispatchDomainGetSecurityLabel,
     .args_filter = (xdrproc_t) xdr_remote_domain_get_security_label_args,
     .ret_filter = (xdrproc_t) xdr_remote_domain_get_security_label_ret,
 },
-{   /* NodeGetSecurityModel => 119 */
+{   /* NodeGetSecurityModel => 122 */
     .fn = (dispatch_fn) remoteDispatchNodeGetSecurityModel,
     .args_filter = (xdrproc_t) xdr_void,
     .ret_filter = (xdrproc_t) xdr_remote_node_get_security_model_ret,
 },
+{   /* ImportDomainXml => 123 */
+    .fn = (dispatch_fn) remoteDispatchImportDomainXml,
+    .args_filter = (xdrproc_t) xdr_remote_import_domain_xml_args,
+    .ret_filter = (xdrproc_t) xdr_remote_import_domain_xml_ret,
+},
+{   /* ExportDomainXml => 124 */
+    .fn = (dispatch_fn) remoteDispatchExportDomainXml,
+    .args_filter = (xdrproc_t) xdr_remote_export_domain_xml_args,
+    .ret_filter = (xdrproc_t) xdr_remote_export_domain_xml_ret,
+},
diff -r ba47cd6949a4 qemud/remote_protocol.c
--- a/qemud/remote_protocol.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_protocol.c	Fri Apr 17 10:22:22 2009 +0100
@@ -2261,6 +2261,50 @@ xdr_remote_domain_event_ret (XDR *xdrs, 
 }
 
 bool_t
+xdr_remote_import_domain_xml_args (XDR *xdrs, remote_import_domain_xml_args *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->format))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->config))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_import_domain_xml_ret (XDR *xdrs, remote_import_domain_xml_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_export_domain_xml_args (XDR *xdrs, remote_export_domain_xml_args *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->format))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_export_domain_xml_ret (XDR *xdrs, remote_export_domain_xml_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->config))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
 {
 
diff -r ba47cd6949a4 qemud/remote_protocol.h
--- a/qemud/remote_protocol.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_protocol.h	Fri Apr 17 10:22:22 2009 +0100
@@ -1271,6 +1271,30 @@ struct remote_domain_event_ret {
         int detail;
 };
 typedef struct remote_domain_event_ret remote_domain_event_ret;
+
+struct remote_import_domain_xml_args {
+        remote_nonnull_string format;
+        remote_nonnull_string config;
+        u_int flags;
+};
+typedef struct remote_import_domain_xml_args remote_import_domain_xml_args;
+
+struct remote_import_domain_xml_ret {
+        remote_nonnull_string xml;
+};
+typedef struct remote_import_domain_xml_ret remote_import_domain_xml_ret;
+
+struct remote_export_domain_xml_args {
+        remote_nonnull_string format;
+        remote_nonnull_string xml;
+        u_int flags;
+};
+typedef struct remote_export_domain_xml_args remote_export_domain_xml_args;
+
+struct remote_export_domain_xml_ret {
+        remote_nonnull_string config;
+};
+typedef struct remote_export_domain_xml_ret remote_export_domain_xml_ret;
 #define REMOTE_PROGRAM 0x20008086
 #define REMOTE_PROTOCOL_VERSION 1
 
@@ -1397,6 +1421,8 @@ enum remote_procedure {
         REMOTE_PROC_NODE_DEVICE_RESET = 120,
         REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
         REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+        REMOTE_PROC_IMPORT_DOMAIN_XML = 123,
+        REMOTE_PROC_EXPORT_DOMAIN_XML = 124,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -1632,6 +1658,10 @@ extern  bool_t xdr_remote_node_device_re
 extern  bool_t xdr_remote_domain_events_register_ret (XDR *, remote_domain_events_register_ret*);
 extern  bool_t xdr_remote_domain_events_deregister_ret (XDR *, remote_domain_events_deregister_ret*);
 extern  bool_t xdr_remote_domain_event_ret (XDR *, remote_domain_event_ret*);
+extern  bool_t xdr_remote_import_domain_xml_args (XDR *, remote_import_domain_xml_args*);
+extern  bool_t xdr_remote_import_domain_xml_ret (XDR *, remote_import_domain_xml_ret*);
+extern  bool_t xdr_remote_export_domain_xml_args (XDR *, remote_export_domain_xml_args*);
+extern  bool_t xdr_remote_export_domain_xml_ret (XDR *, remote_export_domain_xml_ret*);
 extern  bool_t xdr_remote_procedure (XDR *, remote_procedure*);
 extern  bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
 extern  bool_t xdr_remote_message_status (XDR *, remote_message_status*);
@@ -1843,6 +1873,10 @@ extern bool_t xdr_remote_node_device_res
 extern bool_t xdr_remote_domain_events_register_ret ();
 extern bool_t xdr_remote_domain_events_deregister_ret ();
 extern bool_t xdr_remote_domain_event_ret ();
+extern bool_t xdr_remote_import_domain_xml_args ();
+extern bool_t xdr_remote_import_domain_xml_ret ();
+extern bool_t xdr_remote_export_domain_xml_args ();
+extern bool_t xdr_remote_export_domain_xml_ret ();
 extern bool_t xdr_remote_procedure ();
 extern bool_t xdr_remote_message_direction ();
 extern bool_t xdr_remote_message_status ();
diff -r ba47cd6949a4 qemud/remote_protocol.x
--- a/qemud/remote_protocol.x	Thu Apr 16 12:44:17 2009 +0100
+++ b/qemud/remote_protocol.x	Fri Apr 17 10:22:22 2009 +0100
@@ -1130,6 +1130,29 @@ struct remote_domain_event_ret {
     int detail;
 };
 
+
+struct remote_import_domain_xml_args {
+    remote_nonnull_string format;
+    remote_nonnull_string config;
+    unsigned flags;
+};
+
+struct remote_import_domain_xml_ret {
+    remote_nonnull_string xml;
+};
+
+
+struct remote_export_domain_xml_args {
+    remote_nonnull_string format;
+    remote_nonnull_string xml;
+    unsigned flags;
+};
+
+struct remote_export_domain_xml_ret {
+    remote_nonnull_string config;
+};
+
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -1270,7 +1293,9 @@ enum remote_procedure {
     REMOTE_PROC_NODE_DEVICE_RESET = 120,
 
     REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
-    REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122
+    REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+    REMOTE_PROC_IMPORT_DOMAIN_XML = 123,
+    REMOTE_PROC_EXPORT_DOMAIN_XML = 124
 };
 
 /* Custom RPC structure. */
diff -r ba47cd6949a4 src/driver.h
--- a/src/driver.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/driver.h	Fri Apr 17 10:22:22 2009 +0100
@@ -151,6 +151,16 @@ typedef int
 typedef char *
         (*virDrvDomainDumpXML)		(virDomainPtr dom,
                                          int flags);
+typedef char *
+        (*virDrvConnectImportDomainXML) (virConnectPtr conn,
+                                         const char *configType,
+                                         const char *configData,
+                                         unsigned int flags);
+typedef char *
+        (*virDrvConnectExportDomainXML) (virConnectPtr conn,
+                                         const char *configType,
+                                         const char *xmlDesc,
+                                         unsigned int flags);
 typedef int
         (*virDrvListDefinedDomains)	(virConnectPtr conn,
                                          char **const names,
@@ -380,6 +390,8 @@ struct _virDriver {
     virDrvDomainGetSecurityLabel     domainGetSecurityLabel;
     virDrvNodeGetSecurityModel  nodeGetSecurityModel;
     virDrvDomainDumpXML		domainDumpXML;
+    virDrvConnectImportDomainXML importDomainXML;
+    virDrvConnectExportDomainXML exportDomainXML;
     virDrvListDefinedDomains	listDefinedDomains;
     virDrvNumOfDefinedDomains	numOfDefinedDomains;
     virDrvDomainCreate		domainCreate;
diff -r ba47cd6949a4 src/libvirt.c
--- a/src/libvirt.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/libvirt.c	Fri Apr 17 10:22:22 2009 +0100
@@ -2633,6 +2633,105 @@ error:
 }
 
 /**
+ * virConnectImportDomainXML:
+ * @conn: a connection object
+ * @format: configuration format importing from
+ * @config: the configuration data to import
+ * @flags: currently unused, pass 0
+ *
+ * Reads native configuration data  describing a domain, and 
+ * generates libvirt domain XML. The format of the native
+ * data is hypervisor dependant.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *virConnectImportDomainXML(virConnectPtr conn,
+                                const char *format,
+                                const char *config,
+                                unsigned int flags)
+{
+    DEBUG("conn=%p, format=%s config=%s flags=%u", conn, format, config, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (format == NULL || config == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->driver->importDomainXML) {
+        char *ret;
+        ret = conn->driver->importDomainXML (conn, format, config, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
+}
+
+/**
+ * virConnectExportDomainXML:
+ * @conn: a connection object
+ * @format: configuration format exporting to
+ * @xml: the domain configuration to export
+ * @flags: currently unused, pass 0
+ *
+ * Reads a domain XML configuration document, and generates
+ * generates a native configuration file describing the domain.
+ * The format of the native data is hypervisor dependant.
+ *
+ * Returns a 0 terminated UTF-8 encoded native config datafile, or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *virConnectExportDomainXML(virConnectPtr conn,
+                                const char *format,
+                                const char *xml,
+                                unsigned int flags)
+{
+    DEBUG("conn=%p, format=%s xml=%s flags=%u", conn, format, xml, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (format == NULL || xml == NULL) {
+        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (conn->driver->exportDomainXML) {
+        char *ret;
+        ret = conn->driver->exportDomainXML (conn, format, xml, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
+}
+
+
+/**
  * virDomainMigrate:
  * @domain: a domain object
  * @dconn: destination host (a connection object)
diff -r ba47cd6949a4 src/libvirt_public.syms
--- a/src/libvirt_public.syms	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/libvirt_public.syms	Fri Apr 17 10:22:22 2009 +0100
@@ -258,4 +258,10 @@ LIBVIRT_0.6.1 {
 	virNodeGetSecurityModel;
 } LIBVIRT_0.6.0;
 
+LIBVIRT_0.6.3 {
+    global:
+	virConnectImportDomainXML;
+	virConnectExportDomainXML;
+} LIBVIRT_0.6.1;
+
 # .... define new API here using predicted next version number ....
diff -r ba47cd6949a4 src/lxc_driver.c
--- a/src/lxc_driver.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/lxc_driver.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1443,6 +1443,8 @@ static virDriver lxcDriver = {
     NULL, /* domainGetSecurityLabel */
     NULL, /* nodeGetSecurityModel */
     lxcDomainDumpXML, /* domainDumpXML */
+    NULL, /* importDomainXML */
+    NULL, /* exportDomainXML */
     lxcListDefinedDomains, /* listDefinedDomains */
     lxcNumDefinedDomains, /* numOfDefinedDomains */
     lxcDomainStart, /* domainCreate */
diff -r ba47cd6949a4 src/openvz_driver.c
--- a/src/openvz_driver.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/openvz_driver.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1344,6 +1344,8 @@ static virDriver openvzDriver = {
     NULL, /* domainGetSecurityLabel */
     NULL, /* nodeGetSecurityModel */
     openvzDomainDumpXML, /* domainDumpXML */
+    NULL, /* importDomainXML */
+    NULL, /* exportDomainXML */
     openvzListDefinedDomains, /* listDefinedDomains */
     openvzNumDefinedDomains, /* numOfDefinedDomains */
     openvzDomainCreate, /* domainCreate */
diff -r ba47cd6949a4 src/qemu_conf.c
--- a/src/qemu_conf.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/qemu_conf.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1245,21 +1245,18 @@ int qemudBuildCommandLine(virConnectPtr 
 
             case VIR_DOMAIN_NET_TYPE_ETHERNET:
                 {
-                    char arg[PATH_MAX];
-                    if (net->ifname) {
-                        if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
-                                     net->ifname,
-                                     net->data.ethernet.script,
-                                     vlan) >= (PATH_MAX-1))
-                            goto error;
-                    } else {
-                        if (snprintf(arg, PATH_MAX-1, "tap,script=%s,vlan=%d",
-                                     net->data.ethernet.script,
-                                     vlan) >= (PATH_MAX-1))
-                            goto error;
-                    }
+                    virBuffer buf = VIR_BUFFER_INITIALIZER;
 
-                    ADD_ARG_LIT(arg);
+                    virBufferAddLit(&buf, "tap");
+                    if (net->ifname)
+                        virBufferVSprintf(&buf, ",ifname=%s", net->ifname);
+                    if (net->data.ethernet.script)
+                        virBufferVSprintf(&buf, ",script=%s", net->data.ethernet.script);
+                    virBufferVSprintf(&buf, ",vlan=%d", vlan);
+                    if (virBufferError(&buf))
+                        goto error;
+
+                    ADD_ARG(virBufferContentAndReset(&buf));
                 }
                 break;
 
diff -r ba47cd6949a4 src/qemu_conf.h
--- a/src/qemu_conf.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/qemu_conf.h	Fri Apr 17 10:22:22 2009 +0100
@@ -106,6 +106,9 @@ struct _qemudDomainStatus {
 #define QEMUD_MIGRATION_FIRST_PORT 49152
 #define QEMUD_MIGRATION_NUM_PORTS 64
 
+/* Config type for XML import/export conversions */
+#define QEMU_CONFIG_FORMAT_ARGV "qemu-argv"
+
 #define qemudReportError(conn, dom, net, code, fmt...)                       \
         virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__,          \
                                __FUNCTION__, __LINE__, fmt)
diff -r ba47cd6949a4 src/qemu_driver.c
--- a/src/qemu_driver.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/qemu_driver.c	Fri Apr 17 10:22:22 2009 +0100
@@ -3333,6 +3333,131 @@ cleanup:
     return ret;
 }
 
+#if 0
+static char *qemuImportDomainXML(virConnectPtr conn,
+                                 const char *format,
+                                 const char *config,
+                                 unsigned int flags) {
+}
+#endif
+
+
+static char *qemuExportDomainXML(virConnectPtr conn,
+                                 const char *format,
+                                 const char *xmlData,
+                                 unsigned int flags ATTRIBUTE_UNUSED) {
+    struct qemud_driver *driver = conn->privateData;
+    virDomainDefPtr def = NULL;
+    const char *emulator;
+    unsigned int qemuCmdFlags;
+    struct stat sb;
+    const char **retargv = NULL;
+    const char **retenv = NULL;
+    const char **tmp;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *ret = NULL;
+    int i;
+
+    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+                         _("unsupported config type %s"), format);
+        goto cleanup;
+    }
+
+    def = virDomainDefParseString(conn, driver->caps, xmlData, 0);
+    if (!def)
+        goto cleanup;
+
+    /* Since we're just exporting args, we can't do bridge/network
+     * setups, since libvirt will normally create TAP devices
+     * directly. We convert those configs into generic 'ethernet'
+     * config and assume the user has suitable 'ifup-qemu' scripts
+     */
+    for (i = 0 ; i < def->nnets ; i++) {
+        virDomainNetDefPtr net = def->nets[i];
+        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+            VIR_FREE(net->data.network.name);
+            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+            net->data.ethernet.dev = NULL;
+            net->data.ethernet.script = NULL;
+            net->data.ethernet.ipaddr = NULL;
+        } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+            /* Rely on fact that the 'ethernet' and 'bridge'
+             * union structs have members in same place */
+        }
+    }
+    if (def->graphics &&
+        def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+        def->graphics->data.vnc.autoport) {
+        def->graphics->data.vnc.port = 5900;
+    }
+    emulator = def->emulator;
+    if (!emulator)
+        emulator = virDomainDefDefaultEmulator(conn, def, driver->caps);
+    if (!emulator)
+        goto cleanup;
+
+    /* Make sure the binary we are about to try exec'ing exists.
+     * Technically we could catch the exec() failure, but that's
+     * in a sub-process so its hard to feed back a useful error
+     */
+    if (stat(emulator, &sb) < 0) {
+        virReportSystemError(conn, errno,
+                             _("Cannot find QEMU binary %s"),
+                             emulator);
+        goto cleanup;
+    }
+
+    if (qemudExtractVersionInfo(emulator,
+                                NULL,
+                                &qemuCmdFlags) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Cannot determine QEMU argv syntax %s"),
+                         emulator);
+        goto cleanup;
+    }
+
+
+    if (qemudBuildCommandLine(conn, driver, def,
+                              qemuCmdFlags,
+                              &retargv, &retenv,
+                              NULL, NULL, /* Don't want it to create TAP devices */
+                              NULL) < 0) {
+        goto cleanup;
+    }
+
+    tmp = retenv;
+    while (*tmp) {
+        virBufferAdd(&buf, *tmp, strlen(*tmp));
+        virBufferAddLit(&buf, " ");
+        tmp++;
+    }
+    tmp = retargv;
+    while (*tmp) {
+        virBufferAdd(&buf, *tmp, strlen(*tmp));
+        virBufferAddLit(&buf, " ");
+        tmp++;
+    }
+
+    if (virBufferError(&buf))
+        goto cleanup;
+
+    ret = virBufferContentAndReset(&buf);
+
+cleanup:
+    for (tmp = retargv ; tmp && *tmp ; tmp++)
+        VIR_FREE(*tmp);
+    VIR_FREE(retargv);
+
+    for (tmp = retenv ; tmp && *tmp ; tmp++)
+        VIR_FREE(*tmp);
+    VIR_FREE(retenv);
+
+    virDomainDefFree(def);
+    return ret;
+}
+
 
 static int qemudListDefinedDomains(virConnectPtr conn,
                             char **const names, int nnames) {
@@ -5098,6 +5223,8 @@ static virDriver qemuDriver = {
     qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
     qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
     qemudDomainDumpXML, /* domainDumpXML */
+    NULL, /* importDomainXML */
+    qemuExportDomainXML, /* exportDomainXML */
     qemudListDefinedDomains, /* listDefinedDomains */
     qemudNumDefinedDomains, /* numOfDefinedDomains */
     qemudDomainStart, /* domainCreate */
diff -r ba47cd6949a4 src/remote_internal.c
--- a/src/remote_internal.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/remote_internal.c	Fri Apr 17 10:22:22 2009 +0100
@@ -2409,6 +2409,68 @@ done:
     return rv;
 }
 
+static char *
+remoteImportDomainXML (virConnectPtr conn,
+                       const char *format,
+                       const char *config,
+                       unsigned int flags)
+{
+    char *rv = NULL;
+    remote_import_domain_xml_args args;
+    remote_import_domain_xml_ret ret;
+    struct private_data *priv = conn->privateData;
+
+    remoteDriverLock(priv);
+
+    args.format = (char *)format;
+    args.config = (char *)config;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_IMPORT_DOMAIN_XML,
+              (xdrproc_t) xdr_remote_import_domain_xml_args, (char *) &args,
+              (xdrproc_t) xdr_remote_import_domain_xml_ret, (char *) &ret) == -1)
+        goto done;
+
+    /* Caller frees. */
+    rv = ret.xml;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static char *
+remoteExportDomainXML (virConnectPtr conn,
+                       const char *format,
+                       const char *xml,
+                       unsigned int flags)
+{
+    char *rv = NULL;
+    remote_export_domain_xml_args args;
+    remote_export_domain_xml_ret ret;
+    struct private_data *priv = conn->privateData;
+
+    remoteDriverLock(priv);
+
+    args.format = (char *)format;
+    args.xml = (char *)xml;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_EXPORT_DOMAIN_XML,
+              (xdrproc_t) xdr_remote_export_domain_xml_args, (char *) &args,
+              (xdrproc_t) xdr_remote_export_domain_xml_ret, (char *) &ret) == -1)
+        goto done;
+
+    /* Caller frees. */
+    rv = ret.config;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
 static int
 remoteDomainMigratePrepare (virConnectPtr dconn,
                             char **cookie, int *cookielen,
@@ -6875,6 +6937,8 @@ static virDriver driver = {
     remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */
     remoteNodeGetSecurityModel, /* nodeGetSecurityModel */
     remoteDomainDumpXML, /* domainDumpXML */
+    remoteImportDomainXML, /* importDomainXML */
+    remoteExportDomainXML, /* exportDomainXML */
     remoteListDefinedDomains, /* listDefinedDomains */
     remoteNumOfDefinedDomains, /* numOfDefinedDomains */
     remoteDomainCreate, /* domainCreate */
diff -r ba47cd6949a4 src/test.c
--- a/src/test.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/test.c	Fri Apr 17 10:22:22 2009 +0100
@@ -3504,6 +3504,8 @@ static virDriver testDriver = {
     NULL, /* domainGetSecurityLabel */
     NULL, /* nodeGetSecurityModel */
     testDomainDumpXML, /* domainDumpXML */
+    NULL, /* importDomainXML */
+    NULL, /* exportDomainXML */
     testListDefinedDomains, /* listDefinedDomains */
     testNumOfDefinedDomains, /* numOfDefinedDomains */
     testDomainCreate, /* domainCreate */
diff -r ba47cd6949a4 src/uml_driver.c
--- a/src/uml_driver.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/uml_driver.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1859,6 +1859,8 @@ static virDriver umlDriver = {
     NULL, /* domainGetSecurityLabel */
     NULL, /* nodeGetSecurityModel */
     umlDomainDumpXML, /* domainDumpXML */
+    NULL, /* importDomainXML */
+    NULL, /* exportDomainXML */
     umlListDefinedDomains, /* listDefinedDomains */
     umlNumDefinedDomains, /* numOfDefinedDomains */
     umlDomainStart, /* domainCreate */
diff -r ba47cd6949a4 src/virsh.c
--- a/src/virsh.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/virsh.c	Fri Apr 17 10:22:22 2009 +0100
@@ -2210,6 +2210,98 @@ cmdDumpXML(vshControl *ctl, const vshCmd
 }
 
 /*
+ * "domxml-import" command
+ */
+static const vshCmdInfo info_domxmlimport[] = {
+    {"help", gettext_noop("Import native config as domain XML")},
+    {"desc", gettext_noop("Import native guest configuration format to domain XML format.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domxmlimport[] = {
+    {"format", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("source config data format")},
+    {"config", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("config data file to import from")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdImportDomXML(vshControl *ctl, const vshCmd *cmd)
+{
+    int ret = TRUE;
+    char *format;
+    char *configFile;
+    char *configData;
+    char *xmlData;
+    int flags = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    format = vshCommandOptString(cmd, "format", NULL);
+    configFile = vshCommandOptString(cmd, "config", NULL);
+
+    if (virFileReadAll(configFile, 1024*1024, &configData) < 0) {
+        return FALSE;
+    }
+
+    xmlData = virConnectImportDomainXML(ctl->conn, format, configData, flags);
+    if (xmlData != NULL) {
+        printf("%s", xmlData);
+        free(xmlData);
+    } else {
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+/*
+ * "domxml-export" command
+ */
+static const vshCmdInfo info_domxmlexport[] = {
+    {"help", gettext_noop("Export domain XML as native config")},
+    {"desc", gettext_noop("Export domain XML config to a native guest configuration format.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domxmlexport[] = {
+    {"format", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("target config data type format")},
+    {"xml", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("xml data file to export from")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdExportDomXML(vshControl *ctl, const vshCmd *cmd)
+{
+    int ret = TRUE;
+    char *format;
+    char *xmlFile;
+    char *configData;
+    char *xmlData;
+    int flags = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    format = vshCommandOptString(cmd, "format", NULL);
+    xmlFile = vshCommandOptString(cmd, "xml", NULL);
+
+    if (virFileReadAll(xmlFile, 1024*1024, &xmlData) < 0) {
+        return FALSE;
+    }
+
+    configData = virConnectExportDomainXML(ctl->conn, format, xmlData, flags);
+    if (configData != NULL) {
+        printf("%s", configData);
+        free(configData);
+    } else {
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+/*
  * "domname" command
  */
 static const vshCmdInfo info_domname[] = {
@@ -5867,12 +5959,14 @@ static const vshCmdDef commands[] = {
     {"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
     {"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
     {"edit", cmdEdit, opts_edit, info_edit},
+    {"export-domxml", cmdExportDomXML, opts_domxmlexport, info_domxmlexport},
     {"find-storage-pool-sources", cmdPoolDiscoverSources,
      opts_find_storage_pool_sources, info_find_storage_pool_sources},
     {"find-storage-pool-sources-as", cmdPoolDiscoverSourcesAs,
      opts_find_storage_pool_sources_as, info_find_storage_pool_sources_as},
     {"freecell", cmdFreecell, opts_freecell, info_freecell},
     {"hostname", cmdHostname, NULL, info_hostname},
+    {"import-domxml", cmdImportDomXML, opts_domxmlimport, info_domxmlimport},
     {"list", cmdList, opts_list, info_list},
     {"migrate", cmdMigrate, opts_migrate, info_migrate},
 
diff -r ba47cd6949a4 src/xen_unified.c
--- a/src/xen_unified.c	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/xen_unified.c	Fri Apr 17 10:22:22 2009 +0100
@@ -1043,6 +1043,97 @@ xenUnifiedDomainDumpXML (virDomainPtr do
     return NULL;
 }
 
+
+static char *
+xenUnifiedImportDomainXML(virConnectPtr conn,
+                          const char *format,
+                          const char *config,
+                          unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainDefPtr def = NULL;
+    char *ret = NULL;
+    virConfPtr conf = NULL;
+    GET_PRIVATE(conn);
+
+    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
+        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
+                        _("unsupported config type %s"), format);
+        return NULL;
+    }
+
+    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
+        conf = virConfReadMem(config, strlen(config));
+        if (!conf)
+            goto cleanup;
+
+        def = xenXMDomainConfigParse(conn, conf);
+    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
+    }
+    if (!def)
+        goto cleanup;
+
+    ret = virDomainDefFormat(conn, def, 0);
+
+cleanup:
+    virDomainDefFree(def);
+    return ret;
+}
+
+
+#define MAX_CONFIG_SIZE (1024 * 65)
+static char *
+xenUnifiedExportDomainXML(virConnectPtr conn,
+                          const char *format,
+                          const char *xmlData,
+                          unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainDefPtr def = NULL;
+    char *ret = NULL;
+    virConfPtr conf = NULL;
+    GET_PRIVATE(conn);
+
+    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
+        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
+                        _("unsupported config type %s"), format);
+        goto cleanup;
+    }
+
+    if (!(def = virDomainDefParseString(conn,
+                                        priv->caps,
+                                        xmlData,
+                                        0)))
+        goto cleanup;
+
+    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
+        int len = MAX_CONFIG_SIZE;
+        conf = xenXMDomainConfigFormat(conn, def);
+        if (!conf)
+            goto cleanup;
+
+        if (VIR_ALLOC_N(ret, len) < 0) {
+            virReportOOMError(conn);
+            goto cleanup;
+        }
+
+        if (virConfWriteMem(ret, &len, conf) < 0) {
+            VIR_FREE(ret);
+            goto cleanup;
+        }
+    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        ret = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion);
+    }
+
+cleanup:
+    virDomainDefFree(def);
+    if (conf)
+        virConfFree(conf);
+    return ret;
+}
+
+
 static int
 xenUnifiedDomainMigratePrepare (virConnectPtr dconn,
                                 char **cookie,
@@ -1580,6 +1671,8 @@ static virDriver xenUnifiedDriver = {
     NULL, /* domainGetSecurityLabel */
     NULL, /* nodeGetSecurityModel */
     xenUnifiedDomainDumpXML, /* domainDumpXML */
+    xenUnifiedImportDomainXML, /* importDomainXML */
+    xenUnifiedExportDomainXML, /* exportDomainXML */
     xenUnifiedListDefinedDomains, /* listDefinedDomains */
     xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */
     xenUnifiedDomainCreate, /* domainCreate */
diff -r ba47cd6949a4 src/xen_unified.h
--- a/src/xen_unified.h	Thu Apr 16 12:44:17 2009 +0100
+++ b/src/xen_unified.h	Fri Apr 17 10:22:22 2009 +0100
@@ -46,6 +46,9 @@ extern int xenRegister (void);
 
 #define MIN_XEN_GUEST_SIZE 64  /* 64 megabytes */
 
+#define XEN_CONFIG_FORMAT_XM    "xen-xm"
+#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr"
+
 /* _xenUnifiedDriver:
  *
  * Entry points into the underlying Xen drivers.  This structure

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list