[PATCH 15/17] docs: Convert 'migration' doc to RST

Peter Krempa pkrempa at redhat.com
Fri Dec 3 15:01:54 UTC 2021


After conversion the table doesn't have to custom colors, but otherwise
seems to hold well.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 docs/meson.build       |   2 +-
 docs/migration.html.in | 688 -----------------------------------------
 docs/migration.rst     | 458 +++++++++++++++++++++++++++
 3 files changed, 459 insertions(+), 689 deletions(-)
 delete mode 100644 docs/migration.html.in
 create mode 100644 docs/migration.rst

diff --git a/docs/meson.build b/docs/meson.build
index fb6e0029d0..3aabb52950 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -77,7 +77,6 @@ docs_html_in_files = [
   'internals',
   'java',
   'logging',
-  'migration',
   'nss',
   'pci-hotplug',
   'php',
@@ -121,6 +120,7 @@ docs_rst_files = [
   'hacking',
   'libvirt-go',
   'libvirt-go-xml',
+  'migration',
   'newreposetup',
   'pci-addresses',
   'platforms',
diff --git a/docs/migration.html.in b/docs/migration.html.in
deleted file mode 100644
index 627200f96a..0000000000
--- a/docs/migration.html.in
+++ /dev/null
@@ -1,688 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <body>
-    <h1>Guest migration</h1>
-
-    <ul id="toc"></ul>
-
-    <p>
-      Migration of guests between hosts is a complicated problem with many possible
-      solutions, each with their own positive and negative points. For maximum
-      flexibility of both hypervisor integration, and administrator deployment,
-      libvirt implements several options for migration.
-    </p>
-
-    <h2><a id="transport">Network data transports</a></h2>
-
-    <p>
-      There are two options for the data transport used during migration, either
-      the hypervisor's own <strong>native</strong> transport, or <strong>tunnelled</strong>
-      over a libvirtd connection.
-    </p>
-
-    <h3><a id="transportnative">Hypervisor native transport</a></h3>
-    <p>
-      <em>Native</em> data transports may or may not support encryption, depending
-      on the hypervisor in question, but will typically have the lowest computational costs
-      by minimising the number of data copies involved. The native data transports will also
-      require extra hypervisor-specific network configuration steps by the administrator when
-      deploying a host. For some hypervisors, it might be necessary to open up a large range
-      of ports on the firewall to allow multiple concurrent migration operations.
-    </p>
-
-    <p>
-      Modern hypervisors support TLS for encryption and authentication of the
-      migration connections which can be enabled using the
-      <code>VIR_MIGRATE_TLS</code> flag. The <em>qemu</em> hypervisor driver
-      allows users to force use of TLS via the <code>migrate_tls_force</code>
-      knob configured in <code>/etc/libvirt/qemu.conf</code>.
-    </p>
-
-    <p>
-      <img class="diagram" src="migration-native.png" alt="Migration native path"/>
-    </p>
-
-    <h3><a id="transporttunnel">libvirt tunnelled transport</a></h3>
-    <p>
-      <em>Tunnelled</em> data transports will always be capable of strong encryption
-      since they are able to leverage the capabilities built in to the libvirt RPC protocol.
-      The downside of a tunnelled transport, however, is that there will be extra data copies
-      involved on both the source and destinations hosts as the data is moved between libvirtd
-      and the hypervisor. This is likely to be a more significant problem for guests with
-      very large RAM sizes, which dirty memory pages quickly. On the deployment side, tunnelled
-      transports do not require any extra network configuration over and above what's already
-      required for general libvirtd <a href="remote.html">remote access</a>, and there is only
-      need for a single port to be open on the firewall to support multiple concurrent
-      migration operations.
-    </p>
-
-    <p>
-      <em>Note:</em> Certain features such as migration of non-shared storage
-      (<code>VIR_MIGRATE_NON_SHARED_DISK</code>), the multi-connection migration
-      (<code>VIR_MIGRATE_PARALLEL</code>), or post-copy migration
-      (<code>VIR_MIGRATE_POSTCOPY</code>) may not be available when using
-      libvirt's tunnelling.
-    </p>
-
-    <p>
-      <img class="diagram" src="migration-tunnel.png" alt="Migration tunnel path"/>
-    </p>
-
-    <h2><a id="flow">Communication control paths/flows</a></h2>
-
-    <p>
-      Migration of virtual machines requires close co-ordination of the two
-      hosts involved, as well as the application invoking the migration,
-      which may be on the source, the destination, or a third host.
-    </p>
-
-    <h3><a id="flowmanageddirect">Managed direct migration</a></h3>
-
-    <p>
-      With <em>managed direct</em> migration, the libvirt client process
-      controls the various phases of migration. The client application must
-      be able to connect and authenticate with the libvirtd daemons on both
-      the source and destination hosts. There is no need for the two libvirtd
-      daemons to communicate with each other. If the client application
-      crashes, or otherwise loses its connection to libvirtd during the
-      migration process, an attempt will be made to abort the migration and
-      restart the guest CPUs on the source host. There may be scenarios
-      where this cannot be safely done, in which cases the guest will be
-      left paused on one or both of the hosts.
-    </p>
-
-    <p>
-      <img class="diagram" src="migration-managed-direct.png" alt="Migration direct, managed"/>
-    </p>
-
-
-    <h3><a id="flowpeer2peer">Managed peer to peer migration</a></h3>
-
-    <p>
-      With <em>peer to peer</em> migration, the libvirt client process only
-      talks to the libvirtd daemon on the source host. The source libvirtd
-      daemon controls the entire migration process itself, by directly
-      connecting the destination host libvirtd. If the client application crashes,
-      or otherwise loses its connection to libvirtd, the migration process
-      will continue uninterrupted until completion.  Note that the
-      source libvirtd uses its own credentials (typically root) to
-      connect to the destination, rather than the credentials used
-      by the client to connect to the source; if these differ, it is
-      common to run into a situation where a client can connect to the
-      destination directly but the source cannot make the connection to
-      set up the peer-to-peer migration.
-    </p>
-
-    <p>
-      <img class="diagram" src="migration-managed-p2p.png" alt="Migration peer-to-peer"/>
-    </p>
-
-
-    <h3><a id="flowunmanageddirect">Unmanaged direct migration</a></h3>
-
-    <p>
-      With <em>unmanaged direct</em> migration, neither the libvirt client
-      or libvirtd daemon control the migration process. Control is instead
-      delegated to the hypervisor's over management services (if any). The
-      libvirt client merely initiates the migration via the hypervisor's
-      management layer. If the libvirt client or libvirtd crash, the
-      migration process will continue uninterrupted until completion.
-    </p>
-
-    <p>
-      <img class="diagram" src="migration-unmanaged-direct.png" alt="Migration direct, unmanaged"/>
-    </p>
-
-
-    <h2><a id="security">Data security</a></h2>
-
-    <p>
-      Since the migration data stream includes a complete copy of the guest
-      OS RAM, snooping of the migration data stream may allow compromise
-      of sensitive guest information. If the virtualization hosts have
-      multiple network interfaces, or if the network switches support
-      tagged VLANs, then it is very desirable to separate guest network
-      traffic from migration or management traffic.
-    </p>
-
-    <p>
-      In some scenarios, even a separate network for migration data may
-      not offer sufficient security. In this case it is possible to apply
-      encryption to the migration data stream. If the hypervisor does not
-      itself offer encryption, then the libvirt tunnelled migration
-      facility should be used.
-    </p>
-
-    <h2><a id="offline">Offline migration</a></h2>
-
-    <p>
-      Offline migration transfers the inactive definition of a domain
-      (which may or may not be active). After successful completion, the
-      domain remains in its current state on the source host and is defined
-      but inactive on the destination host. It's a bit more clever than
-      <code>virsh dumpxml</code> on source host followed by
-      <code>virsh define</code> on destination host, as offline migration
-      will run the pre-migration hook to update the domain XML on
-      destination host. Currently, copying non-shared storage or other file
-      based storages (e.g. UEFI variable storage) is not supported during
-      offline migration.
-    </p>
-
-    <h2><a id="uris">Migration URIs</a></h2>
-
-    <p>
-      Initiating a guest migration requires the client application to
-      specify up to three URIs, depending on the choice of control
-      flow and/or APIs used. The first URI is that of the libvirt
-      connection to the source host, where the virtual guest is
-      currently running. The second URI is that of the libvirt
-      connection to the destination host, where the virtual guest
-      will be moved to (and in peer-to-peer migrations, this is from
-      the perspective of the source, not the client). The third URI is
-      a hypervisor specific
-      URI used to control how the guest will be migrated. With
-      any managed migration flow, the first and second URIs are
-      compulsory, while the third URI is optional. With the
-      unmanaged direct migration mode, the first and third URIs are
-      compulsory and the second URI is not used.
-    </p>
-
-    <p>
-      Ordinarily management applications only need to care about the
-      first and second URIs, which are both in the normal libvirt
-      connection URI format. Libvirt will then automatically determine
-      the hypervisor specific URI, by looking up the target host's
-      configured hostname. There are a few scenarios where the management
-      application may wish to have direct control over the third URI.
-    </p>
-
-    <ol>
-      <li>The configured hostname is incorrect, or DNS is broken. If a
-        host has a hostname which will not resolve to match one of its
-        public IP addresses, then libvirt will generate an incorrect
-        URI. In this case the management application should specify the
-        hypervisor specific URI explicitly, using an IP address, or a
-        correct hostname.</li>
-      <li>The host has multiple network interfaces. If a host has multiple
-        network interfaces, it might be desirable for the migration data
-        stream to be sent over a specific interface for either security
-        or performance reasons. In this case the management application
-        should specify the hypervisor specific URI, using an IP address
-        associated with the network to be used.</li>
-      <li>The firewall restricts what ports are available. When libvirt
-        generates a migration URI it will pick a port number using hypervisor
-        specific rules. Some hypervisors only require a single port to be
-        open in the firewalls, while others require a whole range of port
-        numbers. In the latter case the management application may wish
-        to choose a specific port number outside the default range in order
-        to comply with local firewall policies.</li>
-      <li>The second URI uses UNIX transport method.  In this advanced case
-        libvirt should not guess a *migrateuri* and it should be specified using
-        UNIX socket path URI: <code>unix:///path/to/socket</code>.</li>
-    </ol>
-
-    <h2><a id="config">Configuration file handling</a></h2>
-
-    <p>
-      There are two types of virtual machines known to libvirt. A <em>transient</em>
-      guest only exists while it is running, and has no configuration file stored
-      on disk. A <em>persistent</em> guest maintains a configuration file on disk
-      even when it is not running.
-    </p>
-
-    <p>
-      By default, a migration operation will not attempt to modify any configuration
-      files that may be stored on either the source or destination host. It is the
-      administrator, or management application's, responsibility to manage distribution
-      of configuration files (if desired). It is important to note that the <code>/etc/libvirt</code>
-      directory <strong>MUST NEVER BE SHARED BETWEEN HOSTS</strong>. There are some
-      typical scenarios that might be applicable:
-    </p>
-
-    <ul>
-      <li>Centralized configuration files outside libvirt, in shared storage. A cluster
-        aware  management application may maintain all the master guest configuration
-        files in a cluster filesystem. When attempting to start a guest, the config
-        will be read from the cluster FS and used to deploy a persistent guest.
-        For migration the configuration will need to be copied to the destination
-        host and removed on the original.
-      </li>
-      <li>Centralized configuration files outside libvirt, in a database. A data center
-        management application may not store configuration files at all. Instead it
-        may generate libvirt XML on the fly when a guest is booted. It will typically
-        use transient guests, and thus not have to consider configuration files during
-        migration.
-      </li>
-      <li>Distributed configuration inside libvirt. The configuration file for each
-        guest is copied to every host where the guest is able to run. Upon migration
-        the existing config merely needs to be updated with any changes.
-      </li>
-      <li>Ad-hoc configuration management inside libvirt. Each guest is tied to a
-        specific host and rarely migrated. When migration is required, the config
-        is moved from one host to the other.
-      </li>
-    </ul>
-
-    <p>
-      As mentioned above, libvirt will not modify configuration files during
-      migration by default. The <code>virsh</code> command has two flags to
-      influence this behaviour. The  <code>--undefinesource</code> flag
-      will cause the configuration file to be removed on the source host
-      after a successful migration. The <code>--persistent</code> flag will
-      cause a configuration file to be created on the destination host
-      after a successful migration. The following table summarizes the
-      configuration file handling in all possible state and flag
-      combinations.
-    </p>
-
-    <table>
-      <thead>
-        <tr class="head">
-          <th colspan="3">Before migration</th>
-          <th colspan="2">Flags</th>
-          <th colspan="3">After migration</th>
-        </tr>
-        <tr class="subhead">
-          <th>Source type</th>
-          <th>Source config</th>
-          <th>Dest config</th>
-          <th>--undefinesource</th>
-          <th>--persistent</th>
-          <th>Dest type</th>
-          <th>Source config</th>
-          <th>Dest config</th>
-        </tr>
-      </thead>
-      <tbody>
-        <!-- src:N, dst:N -->
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-        </tr>
-
-        <!-- src:N, dst:Y -->
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(unchanged dest config)</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(unchanged dest config)</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(replaced with source)</td>
-        </tr>
-        <tr>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(replaced with source)</td>
-        </tr>
-
-        <!-- src:Y dst:N -->
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td>Transient</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td>Transient</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-        </tr>
-
-        <!-- src:Y dst:Y -->
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="n">N</td>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y<br/>(unchanged dest config)</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(unchanged dest config)</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="n">N</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y<br/>(replaced with source)</td>
-        </tr>
-        <tr>
-          <td>Persistent</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td class="y">Y</td>
-          <td>Persistent</td>
-          <td class="n">N</td>
-          <td class="y">Y<br/>(replaced with source)</td>
-        </tr>
-      </tbody>
-    </table>
-
-    <h2><a id="scenarios">Migration scenarios</a></h2>
-
-
-    <h3><a id="scenarionativedirect">Native migration, client to two libvirtd servers</a></h3>
-
-    <p>
-      At an API level this requires use of virDomainMigrate, without the
-      VIR_MIGRATE_PEER2PEER flag set. The destination libvirtd server
-      will automatically determine the native hypervisor URI for migration
-      based off the primary hostname. To force migration over an alternate
-      network interface the optional hypervisor specific URI must be provided
-    </p>
-
-    <pre>
-syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [HV-URI]
-
-
-eg using default network interface
-
-virsh migrate web1 qemu+ssh://desthost/system
-virsh migrate web1 xen+tls://desthost/system
-
-
-eg using secondary network interface
-
-virsh migrate web1 qemu://desthost/system tcp://10.0.0.1/
-    </pre>
-
-    <p>
-      Supported by Xen, QEMU, VMware and VirtualBox drivers
-    </p>
-
-    <h3><a id="scenarionativepeer2peer">Native migration, client to and peer2peer between, two libvirtd servers</a></h3>
-
-    <p>
-      virDomainMigrate, with the VIR_MIGRATE_PEER2PEER flag set,
-      using the libvirt URI format for the 'uri' parameter. The
-      destination libvirtd server will automatically determine
-      the native hypervisor URI for migration, based off the
-      primary hostname. The optional uri parameter controls how
-      the source libvirtd connects to the destination libvirtd,
-      in case it is not accessible using the same address that
-      the client uses to connect to the destination, or a different
-      encryption/auth scheme is required. There is no
-      scope for forcing an alternative network interface for the
-      native migration data with this method.
-    </p>
-
-    <p>
-      This mode cannot be invoked from virsh
-    </p>
-
-    <p>
-      Supported by QEMU driver
-    </p>
-
-    <h3><a id="scenariotunnelpeer2peer1">Tunnelled migration, client and peer2peer between two libvirtd servers</a></h3>
-
-    <p>
-      virDomainMigrate, with the VIR_MIGRATE_PEER2PEER & VIR_MIGRATE_TUNNELLED
-      flags set, using the libvirt URI format for the 'uri' parameter. The
-      destination libvirtd server will automatically determine
-      the native hypervisor URI for migration, based off the
-      primary hostname. The optional uri parameter controls how
-      the source libvirtd connects to the destination libvirtd,
-      in case it is not accessible using the same address that
-      the client uses to connect to the destination, or a different
-      encryption/auth scheme is required. The native hypervisor URI
-      format is not used at all.
-    </p>
-
-    <p>
-      This mode cannot be invoked from virsh
-    </p>
-
-    <p>
-      Supported by QEMU driver
-    </p>
-
-    <h3><a id="nativedirectunmanaged">Native migration, client to one libvirtd server</a></h3>
-
-    <p>
-      virDomainMigrateToURI, without the VIR_MIGRATE_PEER2PEER flag set,
-      using a hypervisor specific URI format for the 'uri' parameter.
-      There is no use or requirement for a destination libvirtd instance
-      at all. This is typically used when the hypervisor has its own
-      native management daemon available to handle incoming migration
-      attempts on the destination.
-    </p>
-
-    <pre>
-syntax: virsh migrate GUESTNAME HV-URI
-
-
-eg using same libvirt URI for all connections
-
-    </pre>
-
-    <h3><a id="nativepeer2peer">Native migration, peer2peer between two libvirtd servers</a></h3>
-
-    <p>
-      virDomainMigrateToURI, with the VIR_MIGRATE_PEER2PEER flag set,
-      using the libvirt URI format for the 'uri' parameter. The
-      destination libvirtd server will automatically determine
-      the native hypervisor URI for migration, based off the
-      primary hostname. There is no scope for forcing an alternative
-      network interface for the native migration data with this
-      method.  The destination URI must be reachable using the source
-      libvirtd credentials (which are not necessarily the same as the
-      credentials of the client in connecting to the source).
-    </p>
-
-    <pre>
-syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [ALT-DEST-LIBVIRT-URI]
-
-
-eg using same libvirt URI for all connections
-
-virsh migrate --p2p web1 qemu+ssh://desthost/system
-
-
-eg using different libvirt URI auth scheme for peer2peer connections
-
-virsh migrate --p2p web1 qemu+ssh://desthost/system qemu+tls:/desthost/system
-
-
-eg using different libvirt URI hostname for peer2peer connections
-
-virsh migrate --p2p web1 qemu+ssh://desthost/system qemu+ssh://10.0.0.1/system
-    </pre>
-
-    <p>
-      Supported by the QEMU driver
-    </p>
-
-    <h3><a id="scenariotunnelpeer2peer2">Tunnelled migration, peer2peer between two libvirtd servers</a></h3>
-
-    <p>
-      virDomainMigrateToURI, with the VIR_MIGRATE_PEER2PEER & VIR_MIGRATE_TUNNELLED
-      flags set, using the libvirt URI format for the 'uri' parameter. The
-      destination libvirtd server will automatically determine
-      the native hypervisor URI for migration, based off the
-      primary hostname. The optional uri parameter controls how
-      the source libvirtd connects to the destination libvirtd,
-      in case it is not accessible using the same address that
-      the client uses to connect to the destination, or a different
-      encryption/auth scheme is required. The native hypervisor URI
-      format is not used at all.  The destination URI must be
-      reachable using the source libvirtd credentials (which are not
-      necessarily the same as the credentials of the client in
-      connecting to the source).
-    </p>
-
-    <pre>
-syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [ALT-DEST-LIBVIRT-URI]
-
-
-eg using same libvirt URI for all connections
-
-virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system
-
-
-eg using different libvirt URI auth scheme for peer2peer connections
-
-virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system qemu+tls:/desthost/system
-
-
-eg using different libvirt URI hostname for peer2peer connections
-
-virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system qemu+ssh://10.0.0.1/system
-    </pre>
-
-    <p>
-      Supported by QEMU driver
-    </p>
-
-
-    <h3><a id="scenariounixsocket">Migration using only UNIX sockets</a></h3>
-
-    <p>
-      In niche scenarios where libvirt daemon does not have access to the
-      network (e.g. running in a restricted container on a host that has
-      accessible network), when a management application wants to have complete
-      control over the transfer or when migrating between two containers on the
-      same host all the communication can be done using UNIX sockets.  This
-      includes connecting to non-standard socket path for the destination
-      daemon, using UNIX sockets for hypervisor's communication or for the NBD
-      data transfer.  All of that can be used with both peer2peer and direct
-      migration options.
-    </p>
-
-    <p>
-      Example using <code>/tmp/migdir</code> as a directory representing the
-      same path visible from both libvirt daemons.  That can be achieved by
-      bind-mounting the same directory to different containers running separate
-      daemons or forwarding connections to these sockets manually
-      (using <code>socat</code>, <code>netcat</code> or a custom piece of
-      software):
-    </p>
-    <pre>
-virsh migrate --domain web1 [--p2p] --copy-storage-all
-  --desturi 'qemu+unix:///system?socket=/tmp/migdir/test-sock-driver'
-  --migrateuri 'unix:///tmp/migdir/test-sock-qemu'
-  --disks-uri unix:///tmp/migdir/test-sock-nbd
-    </pre>
-
-    <p>
-      One caveat is that on SELinux-enabled systems all the sockets that the
-      hypervisor is going to connect to needs to have the proper context and
-      that is chosen before its creation by the process that creates it.  That
-      is usually done by using <code>setsockcreatecon{,raw}()</code> functions.
-      Generally *system_r:system_u:svirt_socket_t:s0* should do the trick, but
-      check the SELinux rules and settings of your system.
-    </p>
-
-    <p>
-      Supported by QEMU driver
-    </p>
-
-  </body>
-</html>
diff --git a/docs/migration.rst b/docs/migration.rst
new file mode 100644
index 0000000000..0a40600462
--- /dev/null
+++ b/docs/migration.rst
@@ -0,0 +1,458 @@
+===============
+Guest migration
+===============
+
+.. contents::
+
+Migration of guests between hosts is a complicated problem with many possible
+solutions, each with their own positive and negative points. For maximum
+flexibility of both hypervisor integration, and administrator deployment,
+libvirt implements several options for migration.
+
+Network data transports
+-----------------------
+
+There are two options for the data transport used during migration, either the
+hypervisor's own **native** transport, or **tunnelled** over a libvirtd
+connection.
+
+Hypervisor native transport
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*Native* data transports may or may not support encryption, depending on the
+hypervisor in question, but will typically have the lowest computational costs
+by minimising the number of data copies involved. The native data transports
+will also require extra hypervisor-specific network configuration steps by the
+administrator when deploying a host. For some hypervisors, it might be necessary
+to open up a large range of ports on the firewall to allow multiple concurrent
+migration operations.
+
+Modern hypervisors support TLS for encryption and authentication of the
+migration connections which can be enabled using the ``VIR_MIGRATE_TLS`` flag.
+The *qemu* hypervisor driver allows users to force use of TLS via the
+``migrate_tls_force`` knob configured in ``/etc/libvirt/qemu.conf``.
+
+|Migration native path|
+
+libvirt tunnelled transport
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*Tunnelled* data transports will always be capable of strong encryption since
+they are able to leverage the capabilities built in to the libvirt RPC protocol.
+The downside of a tunnelled transport, however, is that there will be extra data
+copies involved on both the source and destinations hosts as the data is moved
+between libvirtd and the hypervisor. This is likely to be a more significant
+problem for guests with very large RAM sizes, which dirty memory pages quickly.
+On the deployment side, tunnelled transports do not require any extra network
+configuration over and above what's already required for general libvirtd
+`remote access <remote.html>`__, and there is only need for a single port to be
+open on the firewall to support multiple concurrent migration operations.
+
+*Note:* Certain features such as migration of non-shared storage
+(``VIR_MIGRATE_NON_SHARED_DISK``), the multi-connection migration
+(``VIR_MIGRATE_PARALLEL``), or post-copy migration (``VIR_MIGRATE_POSTCOPY``)
+may not be available when using libvirt's tunnelling.
+
+|Migration tunnel path|
+
+Communication control paths/flows
+---------------------------------
+
+Migration of virtual machines requires close co-ordination of the two hosts
+involved, as well as the application invoking the migration, which may be on the
+source, the destination, or a third host.
+
+Managed direct migration
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+With *managed direct* migration, the libvirt client process controls the various
+phases of migration. The client application must be able to connect and
+authenticate with the libvirtd daemons on both the source and destination hosts.
+There is no need for the two libvirtd daemons to communicate with each other. If
+the client application crashes, or otherwise loses its connection to libvirtd
+during the migration process, an attempt will be made to abort the migration and
+restart the guest CPUs on the source host. There may be scenarios where this
+cannot be safely done, in which cases the guest will be left paused on one or
+both of the hosts.
+
+|Migration direct, managed|
+
+Managed peer to peer migration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With *peer to peer* migration, the libvirt client process only talks to the
+libvirtd daemon on the source host. The source libvirtd daemon controls the
+entire migration process itself, by directly connecting the destination host
+libvirtd. If the client application crashes, or otherwise loses its connection
+to libvirtd, the migration process will continue uninterrupted until completion.
+Note that the source libvirtd uses its own credentials (typically root) to
+connect to the destination, rather than the credentials used by the client to
+connect to the source; if these differ, it is common to run into a situation
+where a client can connect to the destination directly but the source cannot
+make the connection to set up the peer-to-peer migration.
+
+|Migration peer-to-peer|
+
+Unmanaged direct migration
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With *unmanaged direct* migration, neither the libvirt client or libvirtd daemon
+control the migration process. Control is instead delegated to the hypervisor's
+over management services (if any). The libvirt client merely initiates the
+migration via the hypervisor's management layer. If the libvirt client or
+libvirtd crash, the migration process will continue uninterrupted until
+completion.
+
+|Migration direct, unmanaged|
+
+Data security
+-------------
+
+Since the migration data stream includes a complete copy of the guest OS RAM,
+snooping of the migration data stream may allow compromise of sensitive guest
+information. If the virtualization hosts have multiple network interfaces, or if
+the network switches support tagged VLANs, then it is very desirable to separate
+guest network traffic from migration or management traffic.
+
+In some scenarios, even a separate network for migration data may not offer
+sufficient security. In this case it is possible to apply encryption to the
+migration data stream. If the hypervisor does not itself offer encryption, then
+the libvirt tunnelled migration facility should be used.
+
+Offline migration
+-----------------
+
+Offline migration transfers the inactive definition of a domain (which may or
+may not be active). After successful completion, the domain remains in its
+current state on the source host and is defined but inactive on the destination
+host. It's a bit more clever than ``virsh dumpxml`` on source host followed by
+``virsh define`` on destination host, as offline migration will run the
+pre-migration hook to update the domain XML on destination host. Currently,
+copying non-shared storage or other file based storages (e.g. UEFI variable
+storage) is not supported during offline migration.
+
+Migration URIs
+--------------
+
+Initiating a guest migration requires the client application to specify up to
+three URIs, depending on the choice of control flow and/or APIs used. The first
+URI is that of the libvirt connection to the source host, where the virtual
+guest is currently running. The second URI is that of the libvirt connection to
+the destination host, where the virtual guest will be moved to (and in
+peer-to-peer migrations, this is from the perspective of the source, not the
+client). The third URI is a hypervisor specific URI used to control how the
+guest will be migrated. With any managed migration flow, the first and second
+URIs are compulsory, while the third URI is optional. With the unmanaged direct
+migration mode, the first and third URIs are compulsory and the second URI is
+not used.
+
+Ordinarily management applications only need to care about the first and second
+URIs, which are both in the normal libvirt connection URI format. Libvirt will
+then automatically determine the hypervisor specific URI, by looking up the
+target host's configured hostname. There are a few scenarios where the
+management application may wish to have direct control over the third URI.
+
+#. The configured hostname is incorrect, or DNS is broken. If a host has a
+   hostname which will not resolve to match one of its public IP addresses, then
+   libvirt will generate an incorrect URI. In this case the management
+   application should specify the hypervisor specific URI explicitly, using an
+   IP address, or a correct hostname.
+#. The host has multiple network interfaces. If a host has multiple network
+   interfaces, it might be desirable for the migration data stream to be sent
+   over a specific interface for either security or performance reasons. In this
+   case the management application should specify the hypervisor specific URI,
+   using an IP address associated with the network to be used.
+#. The firewall restricts what ports are available. When libvirt generates a
+   migration URI it will pick a port number using hypervisor specific rules.
+   Some hypervisors only require a single port to be open in the firewalls,
+   while others require a whole range of port numbers. In the latter case the
+   management application may wish to choose a specific port number outside the
+   default range in order to comply with local firewall policies.
+#. The second URI uses UNIX transport method. In this advanced case libvirt
+   should not guess a \*migrateuri\* and it should be specified using UNIX
+   socket path URI: ``unix:///path/to/socket``.
+
+Configuration file handling
+---------------------------
+
+There are two types of virtual machines known to libvirt. A *transient* guest
+only exists while it is running, and has no configuration file stored on disk. A
+*persistent* guest maintains a configuration file on disk even when it is not
+running.
+
+By default, a migration operation will not attempt to modify any configuration
+files that may be stored on either the source or destination host. It is the
+administrator, or management application's, responsibility to manage
+distribution of configuration files (if desired). It is important to note that
+the ``/etc/libvirt`` directory **MUST NEVER BE SHARED BETWEEN HOSTS**. There are
+some typical scenarios that might be applicable:
+
+-  Centralized configuration files outside libvirt, in shared storage. A cluster
+   aware management application may maintain all the master guest configuration
+   files in a cluster filesystem. When attempting to start a guest, the config
+   will be read from the cluster FS and used to deploy a persistent guest. For
+   migration the configuration will need to be copied to the destination host
+   and removed on the original.
+-  Centralized configuration files outside libvirt, in a database. A data center
+   management application may not store configuration files at all. Instead it
+   may generate libvirt XML on the fly when a guest is booted. It will typically
+   use transient guests, and thus not have to consider configuration files
+   during migration.
+-  Distributed configuration inside libvirt. The configuration file for each
+   guest is copied to every host where the guest is able to run. Upon migration
+   the existing config merely needs to be updated with any changes.
+-  Ad-hoc configuration management inside libvirt. Each guest is tied to a
+   specific host and rarely migrated. When migration is required, the config is
+   moved from one host to the other.
+
+As mentioned above, libvirt will not modify configuration files during migration
+by default. The ``virsh`` command has two flags to influence this behaviour. The
+``--undefinesource`` flag will cause the configuration file to be removed on the
+source host after a successful migration. The ``--persistent`` flag will cause a
+configuration file to be created on the destination host after a successful
+migration. The following table summarizes the configuration file handling in all
+possible state and flag combinations.
+
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Before migration                                          | Flags                                 | After migration                                           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Source type       | Source config     | Dest config       | --undefinesource  | --persistent      | Dest type         | Source config     | Dest config       |
++===================+===================+===================+===================+===================+===================+===================+===================+
+| Transient         | N                 | N                 | N                 | N                 | Transient         | N                 | N                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | N                 | Y                 | N                 | Transient         | N                 | N                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | N                 | N                 | Y                 | Persistent        | N                 | Y                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | N                 | Y                 | Y                 | Persistent        | N                 | Y                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | Y                 | N                 | N                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (unchanged dest   |
+|                   |                   |                   |                   |                   |                   |                   | config)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | Y                 | Y                 | N                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (unchanged dest   |
+|                   |                   |                   |                   |                   |                   |                   | config)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | Y                 | N                 | Y                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (replaced with    |
+|                   |                   |                   |                   |                   |                   |                   | source)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Transient         | N                 | Y                 | Y                 | Y                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (replaced with    |
+|                   |                   |                   |                   |                   |                   |                   | source)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | N                 | N                 | N                 | Transient         | Y                 | N                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | N                 | Y                 | N                 | Transient         | N                 | N                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | N                 | N                 | Y                 | Persistent        | Y                 | Y                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | N                 | Y                 | Y                 | Persistent        | N                 | Y                 |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | Y                 | N                 | N                 | Persistent        | Y                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (unchanged dest   |
+|                   |                   |                   |                   |                   |                   |                   | config)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | Y                 | Y                 | N                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (unchanged dest   |
+|                   |                   |                   |                   |                   |                   |                   | config)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | Y                 | N                 | Y                 | Persistent        | Y                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (replaced with    |
+|                   |                   |                   |                   |                   |                   |                   | source)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+| Persistent        | Y                 | Y                 | Y                 | Y                 | Persistent        | N                 | Y                 |
+|                   |                   |                   |                   |                   |                   |                   | (replaced with    |
+|                   |                   |                   |                   |                   |                   |                   | source)           |
++-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+-------------------+
+
+Migration scenarios
+-------------------
+
+Native migration, client to two libvirtd servers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+At an API level this requires use of virDomainMigrate, without the
+VIR_MIGRATE_PEER2PEER flag set. The destination libvirtd server will
+automatically determine the native hypervisor URI for migration based off the
+primary hostname. To force migration over an alternate network interface the
+optional hypervisor specific URI must be provided
+
+::
+
+   syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [HV-URI]
+
+
+   eg using default network interface
+
+   virsh migrate web1 qemu+ssh://desthost/system
+   virsh migrate web1 xen+tls://desthost/system
+
+
+   eg using secondary network interface
+
+   virsh migrate web1 qemu://desthost/system tcp://10.0.0.1/
+
+Supported by Xen, QEMU, VMware and VirtualBox drivers
+
+Native migration, client to and peer2peer between, two libvirtd servers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+virDomainMigrate, with the VIR_MIGRATE_PEER2PEER flag set, using the libvirt URI
+format for the 'uri' parameter. The destination libvirtd server will
+automatically determine the native hypervisor URI for migration, based off the
+primary hostname. The optional uri parameter controls how the source libvirtd
+connects to the destination libvirtd, in case it is not accessible using the
+same address that the client uses to connect to the destination, or a different
+encryption/auth scheme is required. There is no scope for forcing an alternative
+network interface for the native migration data with this method.
+
+This mode cannot be invoked from virsh
+
+Supported by QEMU driver
+
+Tunnelled migration, client and peer2peer between two libvirtd servers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+virDomainMigrate, with the VIR_MIGRATE_PEER2PEER & VIR_MIGRATE_TUNNELLED flags
+set, using the libvirt URI format for the 'uri' parameter. The destination
+libvirtd server will automatically determine the native hypervisor URI for
+migration, based off the primary hostname. The optional uri parameter controls
+how the source libvirtd connects to the destination libvirtd, in case it is not
+accessible using the same address that the client uses to connect to the
+destination, or a different encryption/auth scheme is required. The native
+hypervisor URI format is not used at all.
+
+This mode cannot be invoked from virsh
+
+Supported by QEMU driver
+
+Native migration, client to one libvirtd server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+virDomainMigrateToURI, without the VIR_MIGRATE_PEER2PEER flag set, using a
+hypervisor specific URI format for the 'uri' parameter. There is no use or
+requirement for a destination libvirtd instance at all. This is typically used
+when the hypervisor has its own native management daemon available to handle
+incoming migration attempts on the destination.
+
+::
+
+   syntax: virsh migrate GUESTNAME HV-URI
+
+
+   eg using same libvirt URI for all connections
+
+
+Native migration, peer2peer between two libvirtd servers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+virDomainMigrateToURI, with the VIR_MIGRATE_PEER2PEER flag set, using the
+libvirt URI format for the 'uri' parameter. The destination libvirtd server will
+automatically determine the native hypervisor URI for migration, based off the
+primary hostname. There is no scope for forcing an alternative network interface
+for the native migration data with this method. The destination URI must be
+reachable using the source libvirtd credentials (which are not necessarily the
+same as the credentials of the client in connecting to the source).
+
+::
+
+   syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [ALT-DEST-LIBVIRT-URI]
+
+
+   eg using same libvirt URI for all connections
+
+   virsh migrate --p2p web1 qemu+ssh://desthost/system
+
+
+   eg using different libvirt URI auth scheme for peer2peer connections
+
+   virsh migrate --p2p web1 qemu+ssh://desthost/system qemu+tls:/desthost/system
+
+
+   eg using different libvirt URI hostname for peer2peer connections
+
+   virsh migrate --p2p web1 qemu+ssh://desthost/system qemu+ssh://10.0.0.1/system
+
+Supported by the QEMU driver
+
+Tunnelled migration, peer2peer between two libvirtd servers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+virDomainMigrateToURI, with the VIR_MIGRATE_PEER2PEER & VIR_MIGRATE_TUNNELLED
+flags set, using the libvirt URI format for the 'uri' parameter. The destination
+libvirtd server will automatically determine the native hypervisor URI for
+migration, based off the primary hostname. The optional uri parameter controls
+how the source libvirtd connects to the destination libvirtd, in case it is not
+accessible using the same address that the client uses to connect to the
+destination, or a different encryption/auth scheme is required. The native
+hypervisor URI format is not used at all. The destination URI must be reachable
+using the source libvirtd credentials (which are not necessarily the same as the
+credentials of the client in connecting to the source).
+
+::
+
+   syntax: virsh migrate GUESTNAME DEST-LIBVIRT-URI [ALT-DEST-LIBVIRT-URI]
+
+
+   eg using same libvirt URI for all connections
+
+   virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system
+
+
+   eg using different libvirt URI auth scheme for peer2peer connections
+
+   virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system qemu+tls:/desthost/system
+
+
+   eg using different libvirt URI hostname for peer2peer connections
+
+   virsh migrate --p2p --tunnelled web1 qemu+ssh://desthost/system qemu+ssh://10.0.0.1/system
+
+Supported by QEMU driver
+
+Migration using only UNIX sockets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In niche scenarios where libvirt daemon does not have access to the network
+(e.g. running in a restricted container on a host that has accessible network),
+when a management application wants to have complete control over the transfer
+or when migrating between two containers on the same host all the communication
+can be done using UNIX sockets. This includes connecting to non-standard socket
+path for the destination daemon, using UNIX sockets for hypervisor's
+communication or for the NBD data transfer. All of that can be used with both
+peer2peer and direct migration options.
+
+Example using ``/tmp/migdir`` as a directory representing the same path visible
+from both libvirt daemons. That can be achieved by bind-mounting the same
+directory to different containers running separate daemons or forwarding
+connections to these sockets manually (using ``socat``, ``netcat`` or a custom
+piece of software):
+
+::
+
+   virsh migrate --domain web1 [--p2p] --copy-storage-all
+     --desturi 'qemu+unix:///system?socket=/tmp/migdir/test-sock-driver'
+     --migrateuri 'unix:///tmp/migdir/test-sock-qemu'
+     --disks-uri unix:///tmp/migdir/test-sock-nbd
+
+One caveat is that on SELinux-enabled systems all the sockets that the
+hypervisor is going to connect to needs to have the proper context and that is
+chosen before its creation by the process that creates it. That is usually done
+by using ``setsockcreatecon{,raw}()`` functions. Generally
+\*system_r:system_u:svirt_socket_t:s0\* should do the trick, but check the
+SELinux rules and settings of your system.
+
+Supported by QEMU driver
+
+.. |Migration native path| image:: migration-native.png
+   :class: diagram
+.. |Migration tunnel path| image:: migration-tunnel.png
+   :class: diagram
+.. |Migration direct, managed| image:: migration-managed-direct.png
+   :class: diagram
+.. |Migration peer-to-peer| image:: migration-managed-p2p.png
+   :class: diagram
+.. |Migration direct, unmanaged| image:: migration-unmanaged-direct.png
+   :class: diagram
-- 
2.31.1




More information about the libvir-list mailing list