package org.libvirt; import java.nio.ByteBuffer; import java.util.Collection; import java.util.Collections; import java.util.concurrent.TimeUnit; import com.sun.jna.Pointer; import com.sun.jna.ptr.PointerByReference; import org.libvirt.event.AgentLifecycleListener; import org.libvirt.event.BlockJobListener; import org.libvirt.event.IOErrorListener; import org.libvirt.event.LifecycleListener; import org.libvirt.event.PMSuspendListener; import org.libvirt.event.PMWakeupListener; import org.libvirt.event.RebootListener; import org.libvirt.jna.CString; import org.libvirt.jna.CStringByReference; import org.libvirt.jna.DomainPointer; import org.libvirt.jna.DomainSnapshotPointer; import org.libvirt.jna.Libvirt; import org.libvirt.jna.SizeT; import org.libvirt.jna.virDomainBlockInfo; import org.libvirt.jna.virDomainBlockJobInfo; import org.libvirt.jna.virDomainBlockStats; import org.libvirt.jna.virDomainInfo; import org.libvirt.jna.virDomainInterface; import org.libvirt.jna.virDomainInterfaceStats; import org.libvirt.jna.virDomainJobInfo; import org.libvirt.jna.virDomainMemoryStats; import org.libvirt.jna.virSchedParameter; import org.libvirt.jna.virTypedParameter; import org.libvirt.jna.virVcpuInfo; import static org.libvirt.Library.libvirt; import static org.libvirt.Library.libvirtQemu; import static org.libvirt.ErrorHandler.processError; import static org.libvirt.ErrorHandler.processErrorIfZero; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.ptr.IntByReference; import java.util.Arrays; import java.util.stream.Collectors; /** * A virtual machine defined within libvirt. */ public class Domain { private static int bit(final int i) { return 1 << i; } /** * TODO: get generated constants from libvirt */ public static final class BlockCommitFlags { /** NULL base means next backing file, not whole chain */ public static int SHALLOW = bit(0); /** Delete any files that are now invalid after their contents have been committed */ public static int DELETE = bit(1); /** Allow a two-phase commit when top is the active layer */ public static int ACTIVE = bit(2); /** keep the backing chain referenced using relative names */ public static int RELATIVE = bit(3); /** bandwidth in bytes/s instead of MiB/s */ public static int BANDWIDTH_BYTES = bit(4); } public static final class BlockCopyFlags { /** Limit copy to top of source backing chain */ public static int SHALLOW = bit(0); /** Reuse existing external file for a copy */ public static int REUSE_EXT = bit(1); /** Don't force usage of recoverable job for the copy operation */ public static int TRANSIENT_JOB = bit(2); /** * Force the copy job to synchronously propagate guest writes into the destination image, * so that the copy is guaranteed to converge */ public static int SYNCHRONOUS_WRITES = bit(3); } public static final class BlockCopyParameters { /** * The maximum bandwidth in bytes/s, and is used while getting the copy operation * into the mirrored phase, with a type of ullong. * * @see * Libvirt Documentation */ public static String BANDWIDTH = "bandwidth"; /** * How much data in bytes can be in flight between source and destination, * as an unsigned long long. * * @see * Libvirt Documentation */ public static String BUF_SIZE = "buf-size"; /** * The granularity in bytes at which the copy operation recognizes dirty blocks that need copying, * as an unsigned int. * * @see * Libvirt Documentation */ public static String GRANULARITY = "granularity"; } /** * Contains multiple constants that defines "virDomainMigrate* params" multiple field. * @see Libvirt domain documentation., and * libvirt-domain.h. */ public static final class DomainMigrateParameters { /** * Lists the block devices to be migrated. * At the moment this is only supported by the QEMU driver but not for the tunnelled migration. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_MIGRATE_DISKS = "migrate_disks"; /** * The new configuration to be used for the domain on the destination host as * TYPED_PARAM_STRING. The configuration must include an identical set of * virtual devices, to ensure a stable guest ABI across migration. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_DEST_XML = "destination_xml"; /** * The new persistent configuration to be used for the domain on the destination host as * TYPED_PARAM_STRING. This field cannot be used to rename the domain during migration. * Domain name in the destination XML must match the original domain name. * Omitting this parameter keeps the original domain persistent configuration. * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_PERSIST_XML = "persistent_xml"; /** * The maximum bandwidth (in MiB/s) that will be used for migration as TYPED_PARAM_ULLONG. * If set to 0 or omitted, libvirt will choose a suitable default. Some hypervisors do not * support this feature and will return an error if this field is used and is not 0. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_BANDWIDTH = "bandwidth"; /** * The maximum bandwidth (in MiB/s) that will be used for post-copy phase of a migration * as TYPED_PARAM_ULLONG. If set to 0 or omitted, post-copy migration speed will not be limited. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY = "bandwidth.postcopy"; /** * The name to be used for the domain on the destination host as TYPED_PARAM_STRING. * Omitting this parameter keeps the domain name the same. This field is only allowed to be * used with hypervisors that support domain renaming during migration. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_DEST_NAME = "destination_name"; /** * URI to use for migrating client's connection to domain's graphical console, as TYPED_PARAM_STRING. * If specified, the client will be asked to automatically reconnect using these parameters instead of * the automatically computed ones. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_GRAPHICS_URI = "graphics_uri"; /** * The listen address that hypervisor on the destination side should bind to for incoming migration. * Both IPv4 and IPv6 addresses are accepted as well as hostnames (the resolving is done on destination). * Some hypervisors do not support this feature and will return an error if this field is used. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_LISTEN_ADDRESS = "listen_address"; /** * URI to use for initiating domain migration as TYPED_PARAM_STRING. It takes a hypervisor specific format. * The uri_transports element of the hypervisor capabilities XML includes details of the * supported URI schemes. When omitted libvirt will auto-generate suitable default URI. * It is typically only necessary to specify this URI if the destination host has multiple * interfaces and a specific interface is required to transmit migration data. * This field may not be used when VIR_MIGRATE_TUNNELLED flag is set. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_URI = "migrate_uri"; /** * Port that destination server should use for incoming disks migration. * Type is TYPED_PARAM_INT. If set to 0 or omitted, libvirt will choose a suitable default. * At the moment this is only supported by the QEMU driver. * * For more details, please check Libvirt documentation:7 * @see Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_DISKS_PORT = "disks_port"; /** * URI used for incoming disks migration. Type is TYPED_PARAM_STRING. Only schemes "tcp" and * "unix" are accepted. TCP URI can currently only provide a server and port to listen on * (and connect to), UNIX URI may only provide a path component for a UNIX socket. * UNIX URI is only usable if the management application makes sure that socket created with * this name on the destination will be reachable from the source under the same exact path. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_DISKS_URI = "disks_uri"; /** * The name of the method used to compress migration traffic as TYPED_PARAM_STRING. * Supported compression methods: xbzrle, mt. * The parameter may be specified multiple times if more than one method should be used. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_COMPRESSION = "compression"; /** * The level of compression for multithread compression as TYPED_PARAM_INT. * Accepted values are in range 0-9. 0 is no compression, 1 is maximum speed * and 9 is maximum compression. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL = "compression.mt.level"; /** * The number of compression threads for multithread compression as TYPED_PARAM_INT. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS = "compression.mt.threads"; /** * The number of decompression threads for multithread compression as TYPED_PARAM_INT. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS = "compression.mt.dthreads"; /** * The size of page cache for xbzrle compression as TYPED_PARAM_ULLONG. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE = "compression.xbzrle.cache"; /** * The initial percentage guest CPUs are throttled to when auto-convergence decides migration * is not converging as TYPED_PARAM_INT. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL = "auto_converge.initial"; /** * The increment added to VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL whenever the hypervisor * decides the current rate is not enough to ensure convergence of the migration. As TYPED_PARAM_INT. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT = "auto_converge.increment"; /** * The number of connections used during parallel migration as TYPED_PARAM_INT. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS = "parallel.connections"; /** * Override the destination host name used for TLS verification as TYPED_PARAM_STRING. * Normally the TLS certificate from the destination host must match the host's name for TLS * verification to succeed. When the certificate does not match the destination hostname and * the expected certificate's hostname is known, this parameter can be used to pass this * expected hostname when starting the migration. * * @see * Libvirt Documentation */ public static final String VIR_MIGRATE_PARAM_TLS_DESTINATION = "tls.destination"; } public static final class BlockJobInfoFlags { /** bandwidth in bytes/s instead of MiB/s */ public static int BANDWIDTH_BYTES = bit(0); } public static final class BlockJobAbortFlags { public static int ASYNC = bit(0); public static int PIVOT = bit(1); } public static final class BlockResizeFlags { /** * size is in bytes instead of KiB */ public static final int BYTES = 1; } public static final class CreateFlags { /** Default behavior */ public static final int NONE = 0; /** Launch guest in paused state */ public static final int PAUSED = bit(0); /** Automatically kill guest when virConnectPtr is closed */ public static final int AUTODESTROY = bit(1); /** Avoid file system cache pollution */ public static final int BYPASS_CACHE = bit(2); /** Boot, discarding any managed save */ public static final int FORCE_BOOT = bit(3); /** Validate the XML document against schema */ public static final int VALIDATE = bit(4); } public static final class InterfaceAddressesSource { /** Parse DHCP lease file */ public static final int VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0; /** Query qemu guest agent */ public static final int VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1; /** Query ARP tables */ public static final int VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP = 2; } public static final class MetadataType { /** Operate on <description> */ public static final int DESCRIPTION = 0; /** Operate on <title> */ public static final int TITLE = 1; /** Operate on <metadata> */ public static final int ELEMENT = 2; } public static final class MigrateFlags { /** live migration */ public static final int LIVE = bit(0); /** direct source -> dest host control channel */ public static final int PEER2PEER = bit(1); /** tunnel migration data over libvirtd connection */ public static final int TUNNELED = bit(2); /** persist the VM on the destination */ public static final int PERSIST_DEST = bit(3); /** undefine the VM on the source */ public static final int UNDEFINE_SOURCE = bit(4); /** pause on remote side */ public static final int PAUSED = bit(5); /** migration with non-shared storage with full disk copy */ public static final int NON_SHARED_DISK = bit(6); /** migration with non-shared storage with incremental copy * (same base image shared between source and destination) */ public static final int NON_SHARED_INC = bit(7); /** protect for changing domain configuration through the * whole migration process; this will be used automatically * when supported */ public static final int CHANGE_PROTECTION = bit(8); /** force migration even if it is considered unsafe */ public static final int UNSAFE = bit(9); /** Migrate a domain definition without starting the domain on the * destination and without stopping it on the source host */ public static final int OFFLINE = bit(10); /** Compress migration data */ public static final int COMPRESSED = bit(11); /** Cancel migration if a soft error (such as I/O error) happens * during migration */ public static final int ABORT_ON_ERROR = bit(12); /** Enable algorithms that ensure a live migration will * eventually converge */ public static final int AUTO_CONVERGE = bit(13); /** This flag can be used with RDMA migration (i.e., when * PARAM_URI starts with "rdma://") to tell the * hypervisor to pin all domain's memory at once before migration * starts rather then letting it pin memory pages as needed */ public static final int RDMA_PIN_ALL = bit(14); /** Setting the POSTCOPY flag tells libvirt to enable * post-copy migration */ public static final int POSTCOPY = bit(15); /** Setting the TLS flag will cause the migration * to attempt to use the TLS environment configured by the * hypervisor in order to perform the migration. */ public static final int TLS = bit(16); /** Send memory pages to the destination host through several * network connections */ public static final int PARALLEL = bit(17); } public static final class XMLFlags { /** dump security sensitive information too */ public static final int SECURE = bit(0); /** dump inactive domain information*/ public static final int INACTIVE = bit(1); /** update guest CPU requirements according to host CPU */ public static final int UPDATE_CPU = bit(2); /** dump XML suitable for migration */ public static final int MIGRATABLE = bit(3); } public static final class UndefineFlags { /** Also remove any managed save */ public static final int MANAGED_SAVE = bit(0); /** If last use of domain, then also remove any snapshot metadata */ public static final int SNAPSHOTS_METADATA = bit(1); } public static final class RebootFlags { /** hypervisor choice */ public static final int DEFAULT = 0; /** Send ACPI event */ public static final int ACPI_POWER_BTN = bit(0); /** Use guest agent */ public static final int GUEST_AGENT = bit(1); /** Use initctl */ public static final int INITCTL = bit(2); /** Send a signal */ public static final int SIGNAL = bit(3); /** Use paravirt guest control */ public static final int PARAVIRT = bit(4); } public static final class SnapshotCreateFlags { /** Restore or alter metadata */ public static final int REDEFINE = bit(0); /** With redefine, make snapshot current */ public static final int CURRENT = bit(1); /** Make snapshot without remembering it */ public static final int NO_METADATA = bit(2); /** Stop running guest after snapshot */ public static final int HALT = bit(3); /** disk snapshot, not full system */ public static final int DISK_ONLY = bit(4); /** reuse any existing external files */ public static final int REUSE_EXT = bit(5); /** use guest agent to quiesce all mounted file systems within the domain */ public static final int QUIESCE = bit(6); /** atomically avoid partial changes */ public static final int ATOMIC = bit(7); /** create the snapshot while the guest is running */ public static final int LIVE = bit(8); /** validate the XML against the schema */ public static final int VALIDATE = bit(9); } public static final class SnapshotListFlags { /** List all descendants, not just children, when listing a snapshot * For historical reasons, groups do not use contiguous bits. */ public static final int DESCENDANTS = bit(0); /** Filter by snapshots with no parents, when listing a domain */ public static final int ROOTS = bit(0); /** Filter by snapshots which have metadata */ public static final int METADATA = bit(1); /** Filter by snapshots with no children */ public static final int LEAVES = bit(2); /** Filter by snapshots that have children */ public static final int NO_LEAVES = bit(3); /** Filter by snapshots with no metadata */ public static final int NO_METADATA = bit(4); /** Filter by snapshots taken while guest was shut off */ public static final int INACTIVE = bit(5); /** Filter by snapshots taken while guest was active, and with * memory state */ public static final int ACTIVE = bit(6); /** Filter by snapshots taken while guest was active, but without * memory state */ public static final int DISK_ONLY = bit(7); /** Filter by snapshots stored internal to disk images */ public static final int INTERNAL = bit(8); /** Filter by snapshots that use files external to disk images */ public static final int EXTERNAL = bit(9); /** Ensure parents occur before children in the resulting list */ public static final int TOPOLOGICAL = bit(10); } public static final class ModificationImpact { /** Affect current domain state */ public static final int CURRENT = 0; /** Affect running domain state */ public static final int LIVE = bit(0); /** Affect persistent domain state */ public static final int CONFIG = bit(1); } public static final class DeviceModifyFlags { public static final int CONFIG = ModificationImpact.CONFIG; public static final int CURRENT = ModificationImpact.CURRENT; public static final int LIVE = ModificationImpact.LIVE; public static final int FORCE = bit(2); } public static final class VcpuFlags { public static final int CONFIG = ModificationImpact.CONFIG; public static final int CURRENT = ModificationImpact.CURRENT; public static final int LIVE = ModificationImpact.LIVE; /** Max rather than current count */ public static final int MAXIMUM = bit(2); /** Modify state of the cpu in the guest */ public static final int GUEST = bit(3); /** Make vcpus added hot(un)pluggable */ public static final int HOTPLUGGABLE = bit(4); } public static final class DomainSetUserPasswordFlags { /** Password is not encrypted */ public static final int DOMAIN_PASSWORD_NOT_ENCRYPTED = 0; /** Password is already encrypted */ public static final int DOMAIN_PASSWORD_ENCRYPTED = bit(1); } /** the native virDomainPtr. */ DomainPointer vdp; /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((virConnect == null) ? 0 : virConnect.hashCode()); try { result = prime * result + ((vdp == null) ? 0 : Arrays.hashCode(this.getUUID())); } catch (LibvirtException e) { throw new RuntimeException("libvirt error testing domain equality", e); } return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Domain)) { return false; } Domain other = (Domain) obj; // return false when this domain belongs to // a different hypervisor than the other if (!this.virConnect.equals(other.virConnect)) { return false; } if (vdp == null) { return other.vdp == null; } if (vdp.equals(other.vdp)) { return true; } try { return Arrays.equals(getUUID(), other.getUUID()); } catch (LibvirtException e) { throw new RuntimeException("libvirt error testing domain equality", e); } } /** The Connect Object that represents the Hypervisor of this Domain */ private final Connect virConnect; /** * Constructs a Domain object from a known native DomainPointer, and a * Connect object. * * @param virConnect * the Domain's hypervisor * @param vdp * the native virDomainPtr */ Domain(final Connect virConnect, final DomainPointer vdp) { assert virConnect != null; this.virConnect = virConnect; this.vdp = vdp; } /** * Constructs a new Domain object increasing the reference count * on the DomainPointer. *
* This factory method is mostly useful with callback functions, * since the virDomainPtr passed is only valid for the duration of * execution of the callback. */ static Domain constructIncRef(final Connect virConnect, final DomainPointer vdp) throws LibvirtException { processError(libvirt.virDomainRef(vdp)); return new Domain(virConnect, vdp); } /** * Requests that the current background job be aborted at the soonest * opportunity. This will block until the job has either completed, or * aborted. * * @see Libvirt * Documentation * @return ignore (always 0) * @throws LibvirtException */ public int abortJob() throws LibvirtException { return processError(libvirt.virDomainAbortJob(vdp)); } /** * Creates a virtual device attachment to backend. * * @see Libvirt * Documentation * @param xmlDesc * XML description of one device * @throws LibvirtException */ public void attachDevice(final String xmlDesc) throws LibvirtException { processError(libvirt.virDomainAttachDevice(vdp, xmlDesc)); } /** * Creates a virtual device attachment to backend. * * @see Libvirt Documentation * @param xmlDesc * XML description of one device * @param flags * the an OR'ed set of {@link DeviceModifyFlags} * @throws LibvirtException */ public void attachDeviceFlags(final String xmlDesc, final int flags) throws LibvirtException { processError(libvirt.virDomainAttachDeviceFlags(vdp, xmlDesc, flags)); } /** * This function migrates domain's live block device (disk) to another * block device. * * @see * virDomainBlockCopy * @param diskPath * Path to current disk * @param xmlDesc * XML description of destination disk * @param params * Hypervisor-specific tuning parameters * @param flags * Bitwise OR'ed values of {@link BlockCopyFlags} * @throws LibvirtException */ public void blockCopy(final String diskPath, final String xmlDesc, final TypedParameter[] params, final int flags) throws LibvirtException { assert params != null : "blockCopy typed parameters cannot be null"; virTypedParameter[] input = generateNativeVirTypedParameters(params); processError(libvirt.virDomainBlockCopy(vdp, diskPath, xmlDesc, input, input.length, flags)); } /** * This function returns block device (disk) stats for block devices * attached to the domain. * * @param path * the path to the block device * @return the info * @throws LibvirtException */ public DomainBlockInfo blockInfo(final String path) throws LibvirtException { virDomainBlockInfo info = new virDomainBlockInfo(); processError(libvirt.virDomainGetBlockInfo(vdp, path, info, 0)); return new DomainBlockInfo(info); } /** * Read the contents of a domain's disk device. *
* Typical uses for this are to determine if the domain has * written a Master Boot Record (indicating that the domain has * completed installation), or to try to work out the state of the * domain's filesystems. *
* (Note that in the local case you might try to open the block * device or file directly, but that won't work in the remote * case, nor if you don't have sufficient permission. Hence the * need for this call). *
* The disk parameter can either be an unambiguous source name of
* the block device (the {@code
* Valid names can be found by calling {@link #getXMLDesc} and * inspecting elements within {@code //domain/devices/disk}. *
* This method always reads the number of bytes remaining in the
* buffer, that is, {@code buffer.remaining()} at the moment this
* method is invoked. Upon return the buffer's position will be
* equal to the limit, the limit itself will not have changed.
*
* @param disk the path to the block device, or device shorthand
* @param offset the offset within block device
* @param buffer the buffer receiving the data
*/
public void blockPeek(final String disk, final long offset,
final ByteBuffer buffer) throws LibvirtException {
SizeT size = new SizeT();
// older libvirt has a limitation on the size of data
// transferred per request in the remote driver. So, split
// larger requests into 64K blocks.
do {
final int req = Math.min(65536, buffer.remaining());
size.setValue(req);
processError(libvirt.virDomainBlockPeek(this.vdp, disk, offset, size, buffer, 0));
buffer.position(buffer.position() + req);
} while (buffer.hasRemaining());
assert buffer.position() == buffer.limit();
}
/**
* Returns block device (disk) stats for block devices attached to this
* domain. The path parameter is the name of the block device. Get this by
* calling virDomainGetXMLDesc and finding the {@code
* If mode is MemoryAddressMode.VIRTUAL the 'start' parameter is
* interpreted as virtual memory address for whichever task
* happens to be running on the domain at the moment. Although
* this sounds haphazard it is in fact what you want in order to
* read Linux kernel state, because it ensures that pointers in
* the kernel image can be interpreted coherently.
*
* This method always reads the number of bytes remaining in the
* buffer, that is, {@code buffer.remaining()} at the moment this
* method is invoked. Upon return the buffer's position will be
* equal to the limit, the limit itself will not have changed.
*
* @param start the start address of the memory to peek
* @param mode the mode which determines whether the given addresses
* are interpreted as virtual or physical addresses
*/
public void memoryPeek(final long start, final ByteBuffer buffer,
final MemoryAddressMode mode)
throws LibvirtException {
SizeT size = new SizeT();
// older libvirt has a limitation on the size of data
// transferred per request in the remote driver. So, split
// larger requests into 64K blocks.
do {
final int req = Math.min(65536, buffer.remaining());
size.setValue(req);
processError(libvirt.virDomainMemoryPeek(this.vdp, start, size, buffer, mode.getValue()));
buffer.position(buffer.position() + req);
} while (buffer.hasRemaining());
assert buffer.position() == buffer.limit();
}
/**
* This function provides memory statistics for the domain.
*
* @param number
* the number of stats to retrieve
* @return the collection of stats
* @throws LibvirtException
*/
public MemoryStatistic[] memoryStats(final int number)
throws LibvirtException {
virDomainMemoryStats[] stats = new virDomainMemoryStats[number];
MemoryStatistic[] returnStats = null;
int result = processError(libvirt.virDomainMemoryStats(vdp, stats, number, 0));
returnStats = new MemoryStatistic[result];
for (int x = 0; x < result; x++) {
returnStats[x] = new MemoryStatistic(stats[x]);
}
return returnStats;
}
/**
* Migrate this domain object from its current host to the destination host
* given by dconn (a connection to the destination host).
*
* Flags may be bitwise OR'ed values of
* {@link org.libvirt.Domain.MigrateFlags MigrateFlags}.
*
* If a hypervisor supports renaming domains during migration, then you may
* set the dname parameter to the new name (otherwise it keeps the same name).
*
* If this is not supported by the hypervisor, dname must be {@code null} or
* else you will get an exception.
*
* Since typically the two hypervisors connect directly to each other in order
* to perform the migration, you may need to specify a path from the source
* to the destination. This is the purpose of the uri parameter.
*
* If uri is {@code null}, then libvirt will try to find the best method.
*
* Uri may specify the hostname or IP address of the destination host as seen
* from the source, or uri may be a URI giving transport, hostname, user,
* port, etc. in the usual form.
*
* Uri should only be specified if you want to migrate over a specific interface
* on the remote host.
*
* For Qemu/KVM, the URI should be of the form {@code "tcp://hostname[:port]"}.
*
* This does not require TCP auth to be setup between the connections, since
* migrate uses a straight TCP connection (unless using the PEER2PEER flag,
* in which case URI should be a full fledged libvirt URI).
*
* Refer also to driver documentation for the particular URIs supported.
*
* The maximum bandwidth (in Mbps) that will be used to do
* migration can be specified with the bandwidth parameter. If
* set to 0, libvirt will choose a suitable default.
*
* Some hypervisors do not support this feature and will return an
* error if bandwidth is not 0. To see which features are
* supported by the current hypervisor, see
* Connect.getCapabilities, /capabilities/host/migration_features.
*
* There are many limitations on migration imposed by the underlying technology
* for example it may not be possible to migrate between different processors
* even with the same architecture, or between different types of hypervisor.
*
* If the hypervisor supports it, dxml can be used to alter
* host-specific portions of the domain XML that will be used on
* the destination.
*
* @param dconn
* destination host (a Connect object)
* @param dxml
* (optional) XML config for launching guest on target
* @param flags
* flags
* @param dname
* (optional) rename domain to this at destination
* @param uri
* (optional) dest hostname/URI as seen from the source host
* @param bandwidth
* (optional) specify migration bandwidth limit in Mbps
* @return the new domain object if the migration was
* successful. Note that the new domain object exists in
* the scope of the destination connection (dconn).
* @throws LibvirtException if the migration fails
*/
public Domain migrate(final Connect dconn, final long flags,
final String dxml, final String dname,
final String uri, final long bandwidth)
throws LibvirtException {
DomainPointer newPtr =
processError(libvirt.virDomainMigrate2(vdp, dconn.vcp, dxml,
new NativeLong(flags), dname, uri, new NativeLong(bandwidth)));
return new Domain(dconn, newPtr);
}
/**
* Migrate this domain object from its current host to the destination host
* given by dconn (a connection to the destination host). Flags may be one
* of more of the following: Domain.MigrateFlags.LIVE Attempt a live
* migration. If a hypervisor supports renaming domains during migration,
* then you may set the dname parameter to the new name (otherwise it keeps
* the same name). If this is not supported by the hypervisor, dname must be
* NULL or else you will get an error. Since typically the two hypervisors
* connect directly to each other in order to perform the migration, you may
* need to specify a path from the source to the destination. This is the
* purpose of the uri parameter.If uri is NULL, then libvirt will try to
* find the best method. Uri may specify the hostname or IP address of the
* destination host as seen from the source, or uri may be a URI giving
* transport, hostname, user, port, etc. in the usual form. Uri should only
* be specified if you want to migrate over a specific interface on the
* remote host. For Qemu/KVM, the uri should be of the form
* "tcp://hostname[:port]". This does not require TCP auth to be setup
* between the connections, since migrate uses a straight TCP connection
* (unless using the PEER2PEER flag, in which case URI should be a full
* fledged libvirt URI). Refer also to driver documentation for the
* particular URIs supported. If set to 0, libvirt will choose a suitable
* default. Some hypervisors do not support this feature and will return an
* error if bandwidth is not 0. To see which features are supported by the
* current hypervisor, see Connect.getCapabilities,
* /capabilities/host/migration_features. There are many limitations on
* migration imposed by the underlying technology - for example it may not
* be possible to migrate between different processors even with the same
* architecture, or between different types of hypervisor.
*
* @param dconn
* destination host (a Connect object)
* @param flags
* flags
* @param dname
* (optional) rename domain to this at destination
* @param uri
* (optional) dest hostname/URI as seen from the source host
* @param bandwidth
* optional) specify migration bandwidth limit in Mbps
* @return the new domain object if the migration was successful. Note that
* the new domain object exists in the scope of the destination
* connection (dconn).
* @throws LibvirtException
*/
public Domain migrate(final Connect dconn, final long flags,
final String dname, final String uri,
final long bandwidth)
throws LibvirtException {
DomainPointer newPtr = processError(libvirt.virDomainMigrate(vdp, dconn.vcp,
new NativeLong(flags), dname, uri, new NativeLong(bandwidth)));
return new Domain(dconn, newPtr);
}
/**
* Migrate the domain object from its current host to the destination host
* given by dconn (a connection to the destination host).
* See VIR_MIGRATE_PARAM_* and virDomainMigrateFlags for detailed
* description of accepted migration parameters and flags.
* See virDomainMigrateFlags documentation for description of individual
* flags. VIR_MIGRATE_TUNNELLED and VIR_MIGRATE_PEER2PEER are not supported
* by this API, use virDomainMigrateToURI3 instead.
*
* The destination is given either in dconnuri (if the
* {@link MigrateFlags#PEER2PEER PEER2PEER}
* is flag set), or in miguri (if neither the
* {@link MigrateFlags#PEER2PEER PEER2PEER} nor the
* {@link MigrateFlags#TUNNELED TUNNELED} migration
* flag is set in flags).
*
* @see
* virDomainMigrateToURI
*
* @param dconnuri
* (optional) URI for target libvirtd if @flags includes PEER2PEER
* @param miguri
* (optional) URI for invoking the migration, not if @flags includs TUNNELED
* @param dxml
* (optional) XML config for launching guest on target
* @param flags
* Controls the migrate
* @param dname
* The name at the destnation
* @param bandwidth
* Specify the migration bandwidth
* @return 0 if successful
* @throws LibvirtException
*/
public int migrateToURI(final String dconnuri, final String miguri,
final String dxml, final long flags,
final String dname, final long bandwidth)
throws LibvirtException {
return processError(libvirt.virDomainMigrateToURI2(vdp, dconnuri, miguri,
dxml, new NativeLong(flags),
dname, new NativeLong(bandwidth)));
}
/**
* Migrate the domain object from its current host to the destination host
* given by duri.
*
* @see
* virDomainMigrateToURI
*
* @param uri
* The destination URI
* @param flags
* Controls the migrate
* @param dname
* The name at the destnation
* @param bandwidth
* Specify the migration bandwidth
* @return 0 if successful, -1 if not
* @throws LibvirtException
*/
public int migrateToURI(final String uri, final long flags,
final String dname, final long bandwidth)
throws LibvirtException {
return processError(libvirt.virDomainMigrateToURI(vdp, uri,
new NativeLong(flags), dname, new NativeLong(bandwidth)));
}
/**
* Enter the given power management suspension target level.
*/
public void PMsuspend(final SuspendTarget target) throws LibvirtException {
PMsuspendFor(target, 0, TimeUnit.SECONDS);
}
/**
* Enter the given power management suspension target level for the given duration.
*/
public void PMsuspendFor(final SuspendTarget target, final long duration,
final TimeUnit unit)
throws LibvirtException {
processError(libvirt.virDomainPMSuspendForDuration(this.vdp,
target.ordinal(), unit.toSeconds(duration), 0));
}
/**
* Immediately wake up a guest using power management.
*
* Injects a wakeup into the guest that previously used
* {@link #PMsuspend} or {@link #PMsuspendFor}, rather than
* waiting for the previously requested duration (if any) to
* elapse.
*/
public void PMwakeup() throws LibvirtException {
processError(libvirt.virDomainPMWakeup(this.vdp, 0));
}
/**
* Dynamically changes the real CPUs which can be allocated to a virtual
* CPU. This function requires priviledged access to the hypervisor.
*
* @param vcpu
* virtual cpu number
* @param cpumap
* bit map of real CPUs represented by the the lower 8 bits of
* each int in the array. Each bit set to 1 means that
* corresponding CPU is usable. Bytes are stored in little-endian
* order: CPU0-7, 8-15... In each byte, lowest CPU number is
* least significant bit.
* @throws LibvirtException
*/
public void pinVcpu(final int vcpu, final int[] cpumap)
throws LibvirtException {
byte[] packedMap = new byte[cpumap.length];
for (int x = 0; x < cpumap.length; x++) {
packedMap[x] = (byte) cpumap[x];
}
processError(libvirt.virDomainPinVcpu(vdp, vcpu, packedMap, cpumap.length));
}
/**
* Reboot this domain, the domain object is still usable there after but the
* domain OS is being stopped for a restart. Note that the guest OS may
* ignore the request.
*
* @param flags
* extra flags for the reboot operation, see {@link RebootFlags}
* @throws LibvirtException
*/
public void reboot(final int flags) throws LibvirtException {
processError(libvirt.virDomainReboot(vdp, flags));
}
/**
* Resume this suspended domain, the process is restarted from the state
* where it was frozen by calling virSuspendDomain(). This function may
* requires privileged access
*
* @throws LibvirtException
*/
public void resume() throws LibvirtException {
processError(libvirt.virDomainResume(vdp));
}
/**
* Adds a callback to receive notifications of Block Job events
*
* @see Libvirt
* Documentation
* @param cb
* @throws LibvirtException
*/
public void addBlockJobListener(final BlockJobListener cb) throws LibvirtException {
virConnect.domainEventRegister(this, cb);
}
/**
* Removes BlockJobListener from the event framework, so it no longer receives events
* @param cb
* The BlockJobListener
* @throws LibvirtException
*/
public void removeBlockJobListener(final BlockJobListener cb) throws LibvirtException {
virConnect.removeBlockJobListener(cb);
}
/**
* Adds a callback to receive notifications of IOError domain events
* occurring on this domain.
*
* @see Libvirt
* Documentation
* @param cb
* the IOErrorCallback instance
* @throws LibvirtException on failure
*/
public void addIOErrorListener(final IOErrorListener cb) throws LibvirtException {
virConnect.domainEventRegister(this, cb);
}
/**
* Adds the specified listener to receive reboot events for this domain.
*
* @param l the reboot listener
* @throws LibvirtException on failure
*
* @see Connect#addRebootListener
* @see virConnectDomainEventRegisterAny
* @since 1.5.2
*/
public void addRebootListener(final RebootListener l)
throws LibvirtException {
virConnect.domainEventRegister(this, l);
}
/**
* Adds the specified listener to receive agent lifecycle events for this domain.
*
* @param cb the agent lifecycle listener
* @throws LibvirtException on failure
*
* @see Connect#addAgentLifecycleListener
* @see Connect#removeAgentLifecycleListener
* @see
*
virConnectDomainEventRegisterAny
*/
public void addAgentLifecycleListener(final AgentLifecycleListener cb) throws LibvirtException {
virConnect.domainEventRegister(this, cb);
}
/**
* Adds the specified listener to receive lifecycle events for this domain.
*
* @param l the lifecycle listener
* @throws LibvirtException on failure
*
* @see Connect#addLifecycleListener
* @see Connect#removeLifecycleListener
* @see virConnectDomainEventRegisterAny
*/
public void addLifecycleListener(final LifecycleListener l)
throws LibvirtException {
virConnect.domainEventRegister(this, l);
}
/**
* Adds the specified listener to receive PMWakeup events for this domain.
*
* @param l the PMWakeup listener
* @throws LibvirtException on failure
*
* @see Connect#removePMWakeupListener
* @see Connect#addPMWakeupListener
* @see virConnectDomainEventRegisterAny
*
* @since 1.5.2
*/
public void addPMWakeupListener(final PMWakeupListener l)
throws LibvirtException {
virConnect.domainEventRegister(this, l);
}
/**
* Adds the specified listener to receive PMSuspend events for this domain.
*
* @param l the PMSuspend listener
* @throws LibvirtException on failure
*
* @see Connect#removePMSuspendListener
* @see Connect#addPMSuspendListener
* @see virConnectDomainEventRegisterAny
*
* @since 1.5.2
*/
public void addPMSuspendListener(final PMSuspendListener l)
throws LibvirtException {
virConnect.domainEventRegister(this, l);
}
/**
* Reset a domain immediately without any guest OS shutdown.
*/
public void reset() throws LibvirtException {
processError(libvirt.virDomainReset(this.vdp, 0));
}
/**
* Revert the domain to a given snapshot.
*
* @see Libvirt Documentation
* @param snapshot
* the snapshot to revert to
* @return 0 if the creation is successful
* @throws LibvirtException
*/
public int revertToSnapshot(final DomainSnapshot snapshot)
throws LibvirtException {
return processError(libvirt.virDomainRevertToSnapshot(snapshot.vdsp, 0));
}
/**
* Suspends this domain and saves its memory contents to a file on disk.
* After the call, if successful, the domain is not listed as running
* anymore (this may be a problem). Use Connect.virDomainRestore() to
* restore a domain after saving.
*
* @param to
* path for the output file
* @throws LibvirtException
*/
public void save(final String to) throws LibvirtException {
processError(libvirt.virDomainSave(vdp, to));
}
public String screenshot(final Stream stream, final int screen)
throws LibvirtException {
CString mimeType = libvirt.virDomainScreenshot(this.vdp, stream.getVsp(), screen, 0);
processError(mimeType);
stream.markReadable();
return mimeType.toString();
}
/**
* Configures the network to be automatically started when the host machine
* boots.
*
* @param autostart
* @throws LibvirtException
*/
public void setAutostart(final boolean autostart) throws LibvirtException {
int autoValue = autostart ? 1 : 0;
processError(libvirt.virDomainSetAutostart(vdp, autoValue));
}
/**
* * Dynamically change the maximum amount of physical memory allocated to a
* domain. This function requires priviledged access to the hypervisor.
*
* @param memory
* the amount memory in kilobytes
* @throws LibvirtException
*/
public void setMaxMemory(final long memory) throws LibvirtException {
processError(libvirt.virDomainSetMaxMemory(vdp, new NativeLong(memory)));
}
/**
* Dynamically changes the target amount of physical memory allocated to
* this domain. This function may requires priviledged access to the
* hypervisor.
*
* @param memory
* in kilobytes
* @throws LibvirtException
*/
public void setMemory(final long memory) throws LibvirtException {
processError(libvirt.virDomainSetMemory(vdp, new NativeLong(memory)));
}
/**
* Sets the appropriate domain element given by type to the value of metadata.
*
* A type of MetadataType.DESCRIPTION is free-form text; MetadataType.TITLE is
* free-form, but no newlines are permitted, and should be short (although the length
* is not enforced). For these two options key and uri are irrelevant and must be set
* to null.
*
* For type MetadataType.ELEMENT metadata must be well-formed XML belonging to
* namespace defined by uri with local name key.
*
* Passing null for metadata says to remove that element from the domain XML (passing
* the empty string leaves the element present).
*
* @param type see {@link MetadataType}
* @param metadata the new metadata content
* @param key XML namespace prefix for type MetadataType.ELEMENT, null otherwise
* @param uri XML namespace URI for typeMetadataType.ELEMENT, null otherwise
* @param flags see {@link ModificationImpact}
* @throws LibvirtException
*/
public void setMetadata(int type, String metadata, String key, String uri, int flags)
throws LibvirtException {
processError(libvirt.virDomainSetMetadata(vdp, type, metadata, key, uri, flags));
}
/**
* Changes the scheduler parameters
*
* @param params
* an array of SchedParameter objects to be changed
* @throws LibvirtException
*/
public void setSchedulerParameters(final SchedParameter[] params)
throws LibvirtException {
virSchedParameter[] input = new virSchedParameter[params.length];
for (int x = 0; x < params.length; x++) {
input[x] = SchedParameter.toNative(params[x]);
}
processError(libvirt.virDomainSetSchedulerParameters(vdp, input, params.length));
}
/**
* Sets the user password to the value specified by password.
* If flags contain DomainSetUserPasswordFlags.DOMAIN_PASSWORD_ENCRYPTED, the password
* is assumed to be encrypted by the method required by the guest OS.
*
* @param user the username that will get a new password
* @param password the password to set
* @param flags see {@link DomainSetUserPasswordFlags}
* @throws LibvirtException
*/
public void setUserPassword(String user, String password, int flags) throws LibvirtException {
processError(libvirt.virDomainSetUserPassword(vdp, user, password, flags));
}
/**
* Dynamically changes the number of virtual CPUs used by this domain. Note
* that this call may fail if the underlying virtualization hypervisor does
* not support it or if growing the number is arbitrary limited. This
* function requires privileged access to the hypervisor.
*
* @param nvcpus
* the new number of virtual CPUs for this domain
* @throws LibvirtException
*/
public void setVcpus(final int nvcpus) throws LibvirtException {
processError(libvirt.virDomainSetVcpus(vdp, nvcpus));
}
/**
* Dynamically changes the number of virtual CPUs used by this domain. Note
* that this call may fail if the underlying virtualization hypervisor does
* not support it or if growing the number is arbitrary limited. This
* function requires privileged access to the hypervisor.
*
* @param nvcpus
* the new number of virtual CPUs for this domain
* @param flags
* {@link VcpuFlags}
* @throws LibvirtException
*/
public void setVcpusFlags(final int nvcpus, final int flags) throws LibvirtException {
processError(libvirt.virDomainSetVcpusFlags(vdp, nvcpus, flags));
}
/**
* Send key(s) to the guest.
*
* @param codeset the set of keycodes
* @param holdtime the duration that the keys will be held (in milliseconds)
* @param keys the key codes to be send
*/
public void sendKey(final KeycodeSet codeset, final int holdtime,
final int... keys)
throws LibvirtException {
processError(libvirt.virDomainSendKey(this.vdp, codeset.ordinal(),
holdtime, keys, keys.length, 0));
}
/**
* Shuts down this domain, the domain object is still usable there after but
* the domain OS is being stopped. Note that the guest OS may ignore the
* request. TODO: should we add an option for reboot, knowing it may not be
* doable in the general case ?
*
* @throws LibvirtException
*/
public void shutdown() throws LibvirtException {
processError(libvirt.virDomainShutdown(vdp));
}
/**
* Creates a new snapshot of a domain based on the snapshot xml contained in
* xmlDesc.
*
* @see Libvirt
* Documentation
* @param xmlDesc
* string containing an XML description of the domain
* @param flags
* flags for creating the snapshot, see the {@link SnapshotCreateFlags } for the flag options
* @return the snapshot
* @throws LibvirtException
*/
public DomainSnapshot snapshotCreateXML(final String xmlDesc, final int flags)
throws LibvirtException {
DomainSnapshotPointer ptr = processError(libvirt.virDomainSnapshotCreateXML(vdp, xmlDesc, flags));
return new DomainSnapshot(virConnect, ptr);
}
/**
* Creates a new snapshot of a domain based on the snapshot xml contained in
* xmlDesc.
*
* This is just a convenience method, it has the same effect
* as calling {@code snapshotCreateXML(xmlDesc, 0);}.
*
* @see #snapshotCreateXML(String, int)
* @see Libvirt
* Documentation
* @param xmlDesc
* string containing an XML description of the domain
* @return the snapshot, or null on Error
* @throws LibvirtException
*/
public DomainSnapshot snapshotCreateXML(final String xmlDesc)
throws LibvirtException {
return snapshotCreateXML(xmlDesc, 0);
}
/**
* Get the current snapshot for a domain, if any.
*
* @see Libvirt
* Documentation
* @return the snapshot
* @throws LibvirtException
*/
public DomainSnapshot snapshotCurrent() throws LibvirtException {
DomainSnapshotPointer ptr = processError(libvirt.virDomainSnapshotCurrent(vdp, 0));
return new DomainSnapshot(virConnect, ptr);
}
/**
* Collect the list of domain snapshots for the given domain. With the option to pass flags
*
* @see Libvirt
* Documentation
* @param flags {@link SnapshotListFlags}
* @return The list of names, or null if an error
* @throws LibvirtException
*/
public String[] snapshotListNames(final int flags) throws LibvirtException {
int num = snapshotNum();
if (num > 0) {
CString[] names = new CString[num];
int got = processError(libvirt.virDomainSnapshotListNames(vdp, names, num, flags));
return Library.toStringArray(names, got);
} else {
return Library.NO_STRINGS;
}
}
/**
* Collect the list of domain snapshots for the given domain.
*
* This is just a convenience method, it has the same effect
* as calling {@code snapshotListNames(0);}.
*
* @see #snapshotListNames(int)
* @see
* virDomainSnapshotListNames
* @return The list of names, or null if an error
* @throws LibvirtException
*/
public String[] snapshotListNames() throws LibvirtException {
return snapshotListNames(0);
}
/**
* Retrieve a snapshot by name
*
* @see Libvirt
* Documentation
* @param name
* the name
* @return The located snapshot
* @throws LibvirtException
*/
public DomainSnapshot snapshotLookupByName(final String name)
throws LibvirtException {
DomainSnapshotPointer ptr = processError(libvirt.virDomainSnapshotLookupByName(vdp, name, 0));
return new DomainSnapshot(virConnect, ptr);
}
/**
* Provides the number of domain snapshots for this domain..
*
* @see Libvirt
* Documentation
*/
public int snapshotNum() throws LibvirtException {
return processError(libvirt.virDomainSnapshotNum(vdp, 0));
}
/**
* Suspends this active domain, the process is frozen without further access
* to CPU resources and I/O but the memory used by the domain at the
* hypervisor level will stay allocated. Use Domain.resume() to reactivate
* the domain. This function requires priviledged access.
*
* @throws LibvirtException
*/
public void suspend() throws LibvirtException {
processError(libvirt.virDomainSuspend(vdp));
}
/**
* undefines this domain but does not stop it if it is running
*
* @throws LibvirtException
*/
public void undefine() throws LibvirtException {
processError(libvirt.virDomainUndefine(vdp));
}
/**
* Undefines this domain but does not stop if it it is running.
* With option for passing flags
*
* @see
Libvirt Documentation
* @param flags
* flags for undefining the domain.
* See virDomainUndefineFlagsValues for more information
* @throws LibvirtException
*/
public void undefine(final int flags) throws LibvirtException {
processError(libvirt.virDomainUndefineFlags(vdp, flags));
}
/**
* Change a virtual device on a domain
*
* @see
Libvirt Documentation
* @param xml
* the xml to update with
* @param flags
* controls the update
* @return always 0
* @throws LibvirtException
*/
public int updateDeviceFlags(final String xml, final int flags)
throws LibvirtException {
return processError(libvirt.virDomainUpdateDeviceFlags(vdp, xml, flags));
}
/**
* Commands for Qemu Guest Agent helper daemon
*
*@see Libvirt
* Documentation
* @param cmd
* the guest agent command string
* @param timeout
* timeout seconds
* @param flags
* execution flags
* @return result
* strings if success, NULL in failure.
* @throws LibvirtException
*/
public String qemuAgentCommand(String cmd, int timeout, int flags) throws LibvirtException {
CString result = libvirtQemu != null ? libvirtQemu.virDomainQemuAgentCommand(vdp, cmd, timeout, flags) : new CString(null);
processError(result);
return result.toString();
}
/**
* Qemu Monitor Command - it will only work with hypervisor connections to the QEMU driver.
*
*@see Libvirt
* Documentation
* @param cmd
* the qemu monitor command string
* @param flags
* bitwise-or of supported virDomainQemuMonitorCommandFlags
* @return result
* a string returned by @cmd
* @throws LibvirtException
*/
public String qemuMonitorCommand(String cmd, int flags) throws LibvirtException {
CStringByReference result = new CStringByReference();
int cmdResult = libvirtQemu != null ? libvirtQemu.virDomainQemuMonitorCommand(vdp, cmd, result, flags) : -1;
processError(cmdResult);
return result.getValue().toString();
}
}
* There are many limitations on migration imposed by the underlying
* technology - for example it may not be possible to migrate between
* different processors even with the same architecture, or between different
* types of hypervisor. virDomainFree should be used to free the resources
* after the returned domain object is no longer needed.
*
* For more informations, please @see virDomainMigrate3
* @param dconn
* destination host (a Connect object)
* @param params
* (optional) migration parameters
*
* @param flags
* bitwise-OR of virDomainMigrateFlags
* @return
* the new domain object if the migration was successful. Note that
* the new domain object exists in the scope of the destination
* connection (dconn).
* @throws LibvirtException
*/
public Domain migrate(final Connect dconn, final TypedParameter[] params, long flags) throws LibvirtException {
assert params != null : "migrate Typed parameters cannot be null";
virTypedParameter[] virTypedParameters = generateNativeVirTypedParameters(params);
DomainPointer newPtr = processError(libvirt.virDomainMigrate3(vdp, dconn.vcp, virTypedParameters, params.length, new NativeLong(flags)));
return new Domain(dconn, newPtr);
}
/**
* This methods creates an array of virTypedParameter objects based on the
* given array of TypedParameter objects. The way it has been designed ensures
* that the output will be in contiguous memory, regardless of the memory
* allocated for each of the provided "TypedParameter[]", avoiding
* "non contiguous memory due to bad backing address at Structure array".
*
* @param params
* Array of TypedParameter objects which can be:
* TypedBooleanParameter, TypedBooleanParameter, TypedDoubleParameter,
* TypedIntParameter, TypedLongParameter, TypedStringParameter,
* TypedUintParameter, or TypedUlongParameter
* @return
* An array of "virTypedParameter" objects in contiguous memory.
*/
private virTypedParameter[] generateNativeVirTypedParameters(TypedParameter[] params) {
virTypedParameter param = new virTypedParameter();
virTypedParameter[] virTypedParameters = (virTypedParameter[]) param.toArray(params.length);
for (int x = 0; x < params.length; x++) {
virTypedParameter temporaryTypedParameter = TypedParameter.toNative(params[x]);
virTypedParameters[x].field = temporaryTypedParameter.field;
virTypedParameters[x].type = temporaryTypedParameter.type;
virTypedParameters[x].value = temporaryTypedParameter.value;
}
return virTypedParameters;
}
/**
* Sets maximum tolerable time for which the domain is allowed to be paused
* at the end of live migration.
*
* @see LIbvirt
* Documentation
* @param downtime
* the time to be down
* @return always 0
* @throws LibvirtException
*/
public int migrateSetMaxDowntime(final long downtime)
throws LibvirtException {
return processError(libvirt.virDomainMigrateSetMaxDowntime(vdp, downtime, 0));
}
/**
* Migrate the domain object from its current host to the destination
* denoted by a given URI.
*