For input methods which use nbdkit, we can cheaply add
nbdkit-rate-filter to control input-side network bandwidth. These
options control that filter. We can choose to set the bandwidth
statically and optionally change it dynamically:
--bandwidth 10M
# static bandwidth of 10 Mbps, no dynamic adjustment possible
--bandwidth 5M --bandwidth-file /tmp/bw
# initial static bandwidth of 5 Mbps, adjustable by writing to /tmp/bw
--bandwidth-file /tmp/bw
# no initial bandwidth cap, can be added later by writing to /tmp/bw
It only makes sense to control the input side since virt-v2v writes a
lot less data than it reads.
---
v2v/Makefile.am | 1 +
v2v/cmdline.ml | 17 ++++++++++--
v2v/cmdline.mli | 1 +
v2v/input_disk.ml | 2 +-
v2v/input_libvirt_other.ml | 4 +--
v2v/input_libvirt_other.mli | 2 +-
v2v/input_libvirt_vcenter_https.ml | 6 ++--
v2v/input_libvirt_vddk.ml | 6 ++--
v2v/input_libvirt_xen_ssh.ml | 6 ++--
v2v/input_libvirtxml.ml | 2 +-
v2v/input_ova.ml | 2 +-
v2v/input_vmx.ml | 26 ++++++++++--------
v2v/nbdkit.ml | 34 +++++++++++++++++------
v2v/nbdkit.mli | 9 ++++--
v2v/parse_libvirt_xml.ml | 9 +++---
v2v/parse_libvirt_xml.mli | 4 +--
v2v/types.ml | 6 +++-
v2v/types.mli | 7 ++++-
v2v/v2v.ml | 3 +-
v2v/vCenter.ml | 4 +--
v2v/vCenter.mli | 3 +-
v2v/virt-v2v.pod | 44 ++++++++++++++++++++++++++++++
22 files changed, 146 insertions(+), 52 deletions(-)
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 66a684348..cd000da7c 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -268,6 +268,7 @@ virt_v2v_copy_to_local_CFLAGS = \
$(LIBVIRT_CFLAGS)
COPY_TO_LOCAL_BOBJECTS = \
+ types.cmo \
uefi.cmo \
utils.cmo \
libvirt_utils.cmo \
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
index 4d390f249..641eed017 100644
--- a/v2v/cmdline.ml
+++ b/v2v/cmdline.ml
@@ -29,6 +29,7 @@ open Types
open Utils
type cmdline = {
+ bandwidth : bandwidth option;
compressed : bool;
debug_overlays : bool;
do_copy : bool;
@@ -47,6 +48,8 @@ type cmdline = {
let mac_re = PCRE.compile ~anchored:true
"([[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}):(network|bridge):(.*)"
let parse_cmdline () =
+ let bandwidth = ref None in
+ let bandwidth_file = ref None in
let compressed = ref false in
let debug_overlays = ref false in
let do_copy = ref true in
@@ -191,6 +194,10 @@ let parse_cmdline () =
and ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours in
let argspec = [
+ [ L"bandwidth" ], Getopt.String ("bps", set_string_option_once
"--bandwidth" bandwidth),
+ s_"Set bandwidth to bits per sec";
+ [ L"bandwidth-file" ], Getopt.String ("filename",
set_string_option_once "--bandwidth-file" bandwidth_file),
+ s_"Set bandwidth dynamically from file";
[ S 'b'; L"bridge" ], Getopt.String ("in:out",
add_bridge),
s_"Map bridge ‘in’ to ‘out’";
[ L"compressed" ], Getopt.Set compressed,
@@ -304,6 +311,11 @@ read the man page virt-v2v(1).
(* Dereference the arguments. *)
let args = List.rev !args in
+ let bandwidth =
+ match !bandwidth, !bandwidth_file with
+ | None, None -> None
+ | Some rate, None -> Some (StaticBandwidth rate)
+ | rate, Some filename -> Some (DynamicBandwidth (rate, filename)) in
let compressed = !compressed in
let debug_overlays = !debug_overlays in
let do_copy = !do_copy in
@@ -351,6 +363,7 @@ read the man page virt-v2v(1).
pr "in-place\n";
pr "io/oo\n";
pr "mac-option\n";
+ pr "bandwidth-option\n";
List.iter (pr "input:%s\n") (Modules_list.input_modules ());
List.iter (pr "output:%s\n") (Modules_list.output_modules ());
List.iter (pr "convert:%s\n") (Modules_list.convert_modules ());
@@ -683,8 +696,8 @@ read the man page virt-v2v(1).
output_format, output_alloc in
{
- compressed; debug_overlays; do_copy; in_place; network_map;
- output_alloc; output_format; output_name;
+ bandwidth; compressed; debug_overlays; do_copy; in_place;
+ network_map; output_alloc; output_format; output_name;
print_estimate; print_source; root_choice;
ks = opthandle.ks;
},
diff --git a/v2v/cmdline.mli b/v2v/cmdline.mli
index 78601e191..1c9e6c258 100644
--- a/v2v/cmdline.mli
+++ b/v2v/cmdline.mli
@@ -19,6 +19,7 @@
(** Command line argument parsing. *)
type cmdline = {
+ bandwidth : Types.bandwidth option;
compressed : bool;
debug_overlays : bool;
do_copy : bool;
diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml
index 8321a2a8c..52f40a31b 100644
--- a/v2v/input_disk.ml
+++ b/v2v/input_disk.ml
@@ -36,7 +36,7 @@ class input_disk input_format disk = object
| Some fmt -> " -if " ^ fmt)
disk
- method source () =
+ method source ?bandwidth () =
(* Check the input file exists and is readable. *)
Unix.access disk [Unix.R_OK];
diff --git a/v2v/input_libvirt_other.ml b/v2v/input_libvirt_other.ml
index 010244f1d..e1aae38ec 100644
--- a/v2v/input_libvirt_other.ml
+++ b/v2v/input_libvirt_other.ml
@@ -58,10 +58,10 @@ class input_libvirt_other libvirt_conn input_password guest =
object (self)
inherit input_libvirt libvirt_conn input_password guest
- method source () =
+ method source ?bandwidth () =
debug "input_libvirt_other: source ()";
- let source, disks, _ = parse_libvirt_domain self#conn guest in
+ let source, disks, _ = parse_libvirt_domain ?bandwidth self#conn guest in
let disks = List.map (fun { p_source_disk = disk } -> disk) disks in
{ source with s_disks = disks }
end
diff --git a/v2v/input_libvirt_other.mli b/v2v/input_libvirt_other.mli
index f47a6fe3c..7eee9bda3 100644
--- a/v2v/input_libvirt_other.mli
+++ b/v2v/input_libvirt_other.mli
@@ -23,7 +23,7 @@ val error_if_libvirt_does_not_support_json_backingfile : unit ->
unit
class virtual input_libvirt : Libvirt.rw Libvirt.Connect.t Lazy.t -> string option
-> string -> object
method precheck : unit -> unit
method as_options : string
- method virtual source : unit -> Types.source
+ method virtual source : ?bandwidth:Types.bandwidth -> unit -> Types.source
method private conn : Libvirt.rw Libvirt.Connect.t
end
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
index c0de34ded..84ab15ca9 100644
--- a/v2v/input_libvirt_vcenter_https.ml
+++ b/v2v/input_libvirt_vcenter_https.ml
@@ -41,7 +41,7 @@ object (self)
method precheck () =
error_if_libvirt_does_not_support_json_backingfile ()
- method source () =
+ method source ?bandwidth () =
debug "input_libvirt_vcenter_https: source: server %s" server;
(* Remove proxy environment variables so curl doesn't try to use
@@ -56,7 +56,7 @@ object (self)
unsetenv "ALL_PROXY";
unsetenv "NO_PROXY";
- let source, disks, xml = parse_libvirt_domain self#conn guest in
+ let source, disks, xml = parse_libvirt_domain ?bandwidth self#conn guest in
(* Find the <vmware:datacenterpath> element from the XML. This
* was added in libvirt >= 1.2.20.
@@ -78,7 +78,7 @@ object (self)
| { p_source_disk = disk; p_source = P_dont_rewrite } -> disk
| { p_source_disk = disk; p_source = P_source_file path } ->
let { VCenter.qemu_uri } =
- VCenter.map_source ?password_file:input_password
+ VCenter.map_source ?bandwidth ?password_file:input_password
dcPath parsed_uri server path in
(* The libvirt ESX driver doesn't normally specify a format, but
diff --git a/v2v/input_libvirt_vddk.ml b/v2v/input_libvirt_vddk.ml
index aea3e0cde..60609d323 100644
--- a/v2v/input_libvirt_vddk.ml
+++ b/v2v/input_libvirt_vddk.ml
@@ -113,8 +113,8 @@ object (self)
super#as_options (* superclass prints "-i libvirt etc" *)
pt_options
- method source () =
- let source, disks, xml = parse_libvirt_domain self#conn guest in
+ method source ?bandwidth () =
+ let source, disks, xml = parse_libvirt_domain ?bandwidth self#conn guest in
(* Find the <vmware:moref> element from the XML. This was added
* in libvirt >= 3.7 and is required.
@@ -183,7 +183,7 @@ object (self)
* directly in this form to VDDK.
*)
let nbdkit =
- Nbdkit.create_vddk ?config ?cookie ?libdir ~moref
+ Nbdkit.create_vddk ?bandwidth ?config ?cookie ?libdir ~moref
?nfchostport ?password_file:input_password ?port
~server ?snapshot ~thumbprint ?transports ?user
path in
diff --git a/v2v/input_libvirt_xen_ssh.ml b/v2v/input_libvirt_xen_ssh.ml
index 975253e44..cf067f018 100644
--- a/v2v/input_libvirt_xen_ssh.ml
+++ b/v2v/input_libvirt_xen_ssh.ml
@@ -40,10 +40,10 @@ object (self)
error_if_libvirt_does_not_support_json_backingfile ();
error_if_no_ssh_agent ()
- method source () =
+ method source ?bandwidth () =
debug "input_libvirt_xen_ssh: source: server %s" server;
- let source, disks, _ = parse_libvirt_domain self#conn guest in
+ let source, disks, _ = parse_libvirt_domain ?bandwidth self#conn guest in
let port =
match parsed_uri.uri_port with
@@ -61,7 +61,7 @@ object (self)
disk
| { p_source_disk = disk; p_source = P_source_dev path }
| { p_source_disk = disk; p_source = P_source_file path } ->
- let nbdkit = Nbdkit.create_ssh ~password:NoPassword
+ let nbdkit = Nbdkit.create_ssh ?bandwidth ~password:NoPassword
?port ~server ?user path in
let qemu_uri = Nbdkit.run nbdkit in
{ disk with s_qemu_uri = qemu_uri }
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
index a44b41fce..efffb28b0 100644
--- a/v2v/input_libvirtxml.ml
+++ b/v2v/input_libvirtxml.ml
@@ -31,7 +31,7 @@ object
method as_options = "-i libvirtxml " ^ file
- method source () =
+ method source ?bandwidth () =
let xml = read_whole_file file in
let source, disks = parse_libvirt_xml xml in
diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
index 6309ff9a5..872796137 100644
--- a/v2v/input_ova.ml
+++ b/v2v/input_ova.ml
@@ -75,7 +75,7 @@ class input_ova ova = object
method as_options = "-i ova " ^ ova
- method source () =
+ method source ?bandwidth () =
(* Extract ova file. *)
let ova_t = parse_ova ova in
diff --git a/v2v/input_vmx.ml b/v2v/input_vmx.ml
index f521346e5..925d80ba8 100644
--- a/v2v/input_vmx.ml
+++ b/v2v/input_vmx.ml
@@ -106,8 +106,9 @@ let remote_file_exists uri path =
eprintf "%s\n%!" cmd;
Sys.command cmd = 0
-let rec find_disks vmx vmx_source =
- find_scsi_disks vmx vmx_source @ find_ide_disks vmx vmx_source
+let rec find_disks ?bandwidth vmx vmx_source =
+ find_scsi_disks ?bandwidth vmx vmx_source
+ @ find_ide_disks ?bandwidth vmx vmx_source
(* Find all SCSI hard disks.
*
@@ -117,7 +118,7 @@ let rec find_disks vmx vmx_source =
* | omitted
* scsi0:0.fileName = "guest.vmdk"
*)
-and find_scsi_disks vmx vmx_source =
+and find_scsi_disks ?bandwidth vmx vmx_source =
let get_scsi_controller_target ns =
sscanf ns "scsi%d:%d" (fun c t -> c, t)
in
@@ -129,7 +130,7 @@ and find_scsi_disks vmx vmx_source =
Some "scsi-harddisk"; None ] in
let scsi_controller = Source_SCSI in
- find_hdds vmx vmx_source
+ find_hdds ?bandwidth vmx vmx_source
get_scsi_controller_target is_scsi_controller_target
scsi_device_types scsi_controller
@@ -139,7 +140,7 @@ and find_scsi_disks vmx vmx_source =
* ide0:0.deviceType = "ata-hardDisk"
* ide0:0.fileName = "guest.vmdk"
*)
-and find_ide_disks vmx vmx_source =
+and find_ide_disks ?bandwidth vmx vmx_source =
let get_ide_controller_target ns =
sscanf ns "ide%d:%d" (fun c t -> c, t)
in
@@ -150,11 +151,11 @@ and find_ide_disks vmx vmx_source =
let ide_device_types = [ Some "ata-harddisk" ] in
let ide_controller = Source_IDE in
- find_hdds vmx vmx_source
+ find_hdds ?bandwidth vmx vmx_source
get_ide_controller_target is_ide_controller_target
ide_device_types ide_controller
-and find_hdds vmx vmx_source
+and find_hdds ?bandwidth vmx vmx_source
get_controller_target is_controller_target
device_types controller =
(* Find namespaces matching '(ide|scsi)X:Y' with suitable deviceType. *)
@@ -180,7 +181,8 @@ and find_hdds vmx vmx_source
match path, v with
| [ns; "filename"], Some filename ->
let c, t = get_controller_target ns in
- let uri, format = qemu_uri_of_filename vmx_source filename in
+ let uri, format = qemu_uri_of_filename ?bandwidth
+ vmx_source filename in
let s = { s_disk_id = (-1);
s_qemu_uri = uri; s_format = Some format;
s_controller = Some controller } in
@@ -207,7 +209,7 @@ and find_hdds vmx vmx_source
* This constructs a QEMU URI of the filename relative to the
* vmx file (which might be remote over SSH).
*)
-and qemu_uri_of_filename vmx_source filename =
+and qemu_uri_of_filename ?bandwidth vmx_source filename =
match vmx_source with
| File vmx_filename ->
(* Always ensure this returns an absolute path to avoid
@@ -234,7 +236,7 @@ and qemu_uri_of_filename vmx_source filename =
let port = Option.map string_of_int (port_of_uri uri) in
let user = uri.Xml.uri_user in
- let nbdkit = Nbdkit.create_ssh ~password:NoPassword ~server
+ let nbdkit = Nbdkit.create_ssh ?bandwidth ~password:NoPassword ~server
?port ?user abs_path in
let qemu_uri = Nbdkit.run nbdkit in
qemu_uri, format
@@ -386,7 +388,7 @@ object
method as_options = "-i vmx " ^ arg
- method source () =
+ method source ?bandwidth () =
let vmx_source = vmx_source_of_arg input_transport arg in
(* If the transport is SSH, fetch the file from remote, else
@@ -480,7 +482,7 @@ object
None
| None -> None in
- let disks = find_disks vmx vmx_source in
+ let disks = find_disks ?bandwidth vmx vmx_source in
let removables = find_removables vmx in
let nics = find_nics vmx in
diff --git a/v2v/nbdkit.ml b/v2v/nbdkit.ml
index 8cb711b27..166eb1334 100644
--- a/v2v/nbdkit.ml
+++ b/v2v/nbdkit.ml
@@ -24,6 +24,7 @@ open Std_utils
open Tools_utils
open Unix_utils
+open Types
open Utils
let nbdkit_min_version = (1, 12)
@@ -88,7 +89,7 @@ let error_unless_nbdkit_compiled_with_selinux dump_config =
error (f_"nbdkit was compiled without SELinux support. You will have to
recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode
while doing the conversion.")
)
-let common_create plugin_name plugin_args plugin_env =
+let common_create ?bandwidth plugin_name plugin_args plugin_env =
error_unless_nbdkit_working ();
(* Environment. We always add LANG=C. *)
@@ -150,7 +151,24 @@ let common_create plugin_name plugin_args plugin_env =
add_arg "--filter"; add_arg "readahead"
);
- let args = get_args () @ [ plugin_name ] @ plugin_args in
+ (* Add the rate filter. *)
+ let rate_args =
+ if Sys.file_exists (filterdir // "nbdkit-rate-filter.so") then (
+ match bandwidth with
+ | None -> []
+ | Some bandwidth ->
+ add_arg "--filter"; add_arg "rate";
+ match bandwidth with
+ | StaticBandwidth rate ->
+ [ "rate=" ^ rate ]
+ | DynamicBandwidth (None, filename) ->
+ [ "rate-file=" ^ filename ]
+ | DynamicBandwidth (Some rate, filename) ->
+ [ "rate=" ^ rate; "rate-file=" ^ filename ]
+ )
+ else [] in
+
+ let args = get_args () @ [ plugin_name ] @ plugin_args @ rate_args in
{ plugin_name; args; env; dump_config; dump_plugin; filterdir }
@@ -160,7 +178,7 @@ let common_create plugin_name plugin_args plugin_env =
let libNN = sprintf "lib%d" Sys.word_size
(* Create an nbdkit module specialized for reading from VDDK sources. *)
-let create_vddk ?config ?cookie ?libdir ~moref
+let create_vddk ?bandwidth ?config ?cookie ?libdir ~moref
?nfchostport ?password_file ?port
~server ?snapshot ~thumbprint ?transports ?user path =
(* Compute the LD_LIBRARY_PATH that we may have to pass to nbdkit. *)
@@ -255,10 +273,10 @@ See also the virt-v2v-input-vmware(1) manual.") libNN
add_arg (sprintf "thumbprint=%s" thumbprint);
Option.may (fun s -> add_arg (sprintf "transports=%s" s)) transports;
- common_create "vddk" (get_args ()) env
+ common_create ?bandwidth "vddk" (get_args ()) env
(* Create an nbdkit module specialized for reading from SSH sources. *)
-let create_ssh ~password ?port ~server ?user path =
+let create_ssh ?bandwidth ~password ?port ~server ?user path =
let add_arg, get_args =
let args = ref [] in
let add_arg a = List.push_front a args in
@@ -276,10 +294,10 @@ let create_ssh ~password ?port ~server ?user path =
);
add_arg (sprintf "path=%s" path);
- common_create "ssh" (get_args ()) []
+ common_create ?bandwidth "ssh" (get_args ()) []
(* Create an nbdkit module specialized for reading from Curl sources. *)
-let create_curl ?cookie ~password ?(sslverify=true) ?user url =
+let create_curl ?bandwidth ?cookie ~password ?(sslverify=true) ?user url =
let add_arg, get_args =
let args = ref [] in
let add_arg a = List.push_front a args in
@@ -299,7 +317,7 @@ let create_curl ?cookie ~password ?(sslverify=true) ?user url =
if not sslverify then add_arg "sslverify=false";
add_arg (sprintf "url=%s" url);
- common_create "curl" (get_args ()) []
+ common_create ?bandwidth "curl" (get_args ()) []
let run { args; env } =
(* Create a temporary directory where we place the sockets. *)
diff --git a/v2v/nbdkit.mli b/v2v/nbdkit.mli
index efbb62f98..627c78c11 100644
--- a/v2v/nbdkit.mli
+++ b/v2v/nbdkit.mli
@@ -20,7 +20,8 @@
type t
-val create_vddk : ?config:string ->
+val create_vddk : ?bandwidth:Types.bandwidth ->
+ ?config:string ->
?cookie:string ->
?libdir:string ->
moref:string ->
@@ -46,7 +47,8 @@ type password =
| AskForPassword
| PasswordFile of string
-val create_ssh : password:password ->
+val create_ssh : ?bandwidth:Types.bandwidth ->
+ password:password ->
?port:string ->
server:string ->
?user:string ->
@@ -59,7 +61,8 @@ val create_ssh : password:password ->
Note this doesn't run nbdkit yet, it just creates the object. *)
-val create_curl : ?cookie:string ->
+val create_curl : ?bandwidth:Types.bandwidth ->
+ ?cookie:string ->
password:password ->
?sslverify:bool ->
?user:string ->
diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml
index 97d8a5cd8..86990aeb3 100644
--- a/v2v/parse_libvirt_xml.ml
+++ b/v2v/parse_libvirt_xml.ml
@@ -46,7 +46,7 @@ let get_drive_slot str offset =
warning (f_"could not parse device name ‘%s’ from the source libvirt
XML") str;
None
-let parse_libvirt_xml ?conn xml =
+let parse_libvirt_xml ?bandwidth ?conn xml =
debug "libvirt xml is:\n%s" xml;
(* Create a default libvirt connection on request, to not open one
@@ -319,7 +319,8 @@ let parse_libvirt_xml ?conn xml =
| _, Some port ->
invalid_arg "invalid port number in libvirt XML" in
sprintf "%s://%s%s%s" driver host port (uri_quote path) in
- let nbdkit = Nbdkit.create_curl ~password:NoPassword url in
+ let nbdkit = Nbdkit.create_curl ?bandwidth ~password:NoPassword
+ url in
let qemu_uri = Nbdkit.run nbdkit in
add_disk qemu_uri format controller P_dont_rewrite
| Some protocol, _, _ ->
@@ -537,9 +538,9 @@ let parse_libvirt_xml ?conn xml =
},
disks)
-let parse_libvirt_domain conn guest =
+let parse_libvirt_domain ?bandwidth conn guest =
let dom = Libvirt_utils.get_domain conn guest in
(* Use XmlSecure to get passwords (RHBZ#1174123). *)
let xml = Libvirt.Domain.get_xml_desc_flags dom [Libvirt.Domain.XmlSecure] in
- let source, disks = parse_libvirt_xml ~conn xml in
+ let source, disks = parse_libvirt_xml ?bandwidth ~conn xml in
source, disks, xml
diff --git a/v2v/parse_libvirt_xml.mli b/v2v/parse_libvirt_xml.mli
index 2d81e0d99..658ebc5eb 100644
--- a/v2v/parse_libvirt_xml.mli
+++ b/v2v/parse_libvirt_xml.mli
@@ -27,7 +27,7 @@ and parsed_source =
| P_source_file of string (** <source file> *)
| P_dont_rewrite (** s_qemu_uri is already set. *)
-val parse_libvirt_domain : Libvirt.rw Libvirt.Connect.t -> string -> Types.source *
parsed_disk list * string
+val parse_libvirt_domain : ?bandwidth:Types.bandwidth -> Libvirt.rw Libvirt.Connect.t
-> string -> Types.source * parsed_disk list * string
(** [parse_libvirt_domain conn dom] loads the XML of the domain [dom]
from the libvirt connection [conn].
The result is a tuple with a {!Types.source} structure, a list of
@@ -36,7 +36,7 @@ val parse_libvirt_domain : Libvirt.rw Libvirt.Connect.t -> string
-> Types.sourc
{b Note} the [source.s_disks] field is an empty list. The caller
must map over the parsed disks and update the [source.s_disks] field. *)
-val parse_libvirt_xml : ?conn:Libvirt.rw Libvirt.Connect.t -> string ->
Types.source * parsed_disk list
+val parse_libvirt_xml : ?bandwidth:Types.bandwidth -> ?conn:Libvirt.rw
Libvirt.Connect.t -> string -> Types.source * parsed_disk list
(** Take libvirt XML and parse it into a {!Types.source} structure and a
list of source disks.
diff --git a/v2v/types.ml b/v2v/types.ml
index 581f5466f..0dac7cc65 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -506,10 +506,14 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of
string
type output_allocation = Sparse | Preallocated
+type bandwidth =
+| StaticBandwidth of string
+| DynamicBandwidth of string option * string
+
class virtual input = object
method precheck () = ()
method virtual as_options : string
- method virtual source : unit -> source
+ method virtual source : ?bandwidth:bandwidth -> unit -> source
end
class virtual output = object
diff --git a/v2v/types.mli b/v2v/types.mli
index 1441c0109..1425fe3cf 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -361,6 +361,11 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of
string
type output_allocation = Sparse | Preallocated
(** Type of [-oa] (output allocation) option. *)
+type bandwidth =
+| StaticBandwidth of string
+| DynamicBandwidth of string option * string
+(** [--bandwidth] and [--bandwidth-file] options. *)
+
(** {2 Input object}
This is subclassed for the various input [-i] options.
@@ -398,7 +403,7 @@ class virtual input : object
method virtual as_options : string
(** Converts the input object back to the equivalent command line options.
This is just used for pretty-printing log messages. *)
- method virtual source : unit -> source
+ method virtual source : ?bandwidth:bandwidth -> unit -> source
(** Examine the source hypervisor and create a source struct. *)
end
(** Encapsulates all [-i], etc input arguments as an object. *)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index e2e6269f5..cd64a7c27 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -198,7 +198,8 @@ let rec main () =
and open_source cmdline input =
message (f_"Opening the source %s") input#as_options;
- let source = input#source () in
+ let bandwidth = cmdline.bandwidth in
+ let source = input#source ?bandwidth () in
(* Print source and stop. *)
if cmdline.print_source then (
diff --git a/v2v/vCenter.ml b/v2v/vCenter.ml
index 2563ad0ed..89c5579b9 100644
--- a/v2v/vCenter.ml
+++ b/v2v/vCenter.ml
@@ -35,7 +35,7 @@ type remote_resource = {
let source_re = PCRE.compile "^\\[(.*)\\] (.*)\\.vmdk$"
let snapshot_re = PCRE.compile "^(.*)-\\d{6}(\\.vmdk)$"
-let rec map_source ?password_file dcPath uri server path =
+let rec map_source ?bandwidth ?password_file dcPath uri server path =
(* If no_verify=1 was passed in the libvirt URI, then we have to
* turn off certificate verification here too.
*)
@@ -78,7 +78,7 @@ let rec map_source ?password_file dcPath uri server path =
| Some password_file -> Nbdkit.PasswordFile password_file in
let nbdkit =
- Nbdkit.create_curl ?cookie:session_cookie ~password ~sslverify
+ Nbdkit.create_curl ?bandwidth ?cookie:session_cookie ~password ~sslverify
https_url in
let qemu_uri = Nbdkit.run nbdkit in
diff --git a/v2v/vCenter.mli b/v2v/vCenter.mli
index d72d5686e..5620cad45 100644
--- a/v2v/vCenter.mli
+++ b/v2v/vCenter.mli
@@ -54,7 +54,8 @@ type remote_resource = {
(** The "remote resource" is the structure returned by the {!map_source}
function. *)
-val map_source : ?password_file:string -> string -> Xml.uri -> string ->
string -> remote_resource
+val map_source : ?bandwidth:Types.bandwidth -> ?password_file:string ->
+ string -> Xml.uri -> string -> string -> remote_resource
(** [map_source ?password_file dcPath uri server path]
maps the [<source path=...>] string to a {!remote_resource}
structure containing both an [https://] URL and a qemu URI,
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index 9a555c3be..8ba141be9 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -155,6 +155,50 @@ qemu, do:
Display help.
+=item B<--bandwidth> bps
+
+=item B<--bandwidth-file> filename
+
+Some input methods are able to limit the network bandwidth they will
+use statically or dynamically. In the first variant this sets the
+bandwidth limit statically in bits per second. Formats like C<10M>
+may be used (meaning 10 megabits per second).
+
+In the second variant the bandwidth is limited dynamically from the
+content of the file (also in bits per second, in the same formats
+supported by the first variant). You may use both parameters
+together, meaning: first limit to a static rate, then you can create
+the file while virt-v2v is running to adjust the rate dynamically.
+
+This is only supported for:
+
+=over 4
+
+=item *
+
+L<input from Xen|virt-v2v-input-xen(1)>
+
+=item *
+
+L<input from VMware VMX|virt-v2v-input-vmware(1)/INPUT FROM VMWARE VMX>
+when using the SSH transport method
+
+=item *
+
+L<input from VDDK|virt-v2v-input-vmware(1)/INPUT FROM VDDK>
+
+=item *
+
+I<-i libvirtxml> when using HTTP or HTTPS disks
+
+=item *
+
+L<input from VMware vCenter server|virt-v2v-input-vmware(1)/INPUT FROM VMWARE VCENTER
SERVER>
+
+=back
+
+The options are silently ignored for other input methods.
+
=item B<-b> ...
=item B<--bridge> ...
--
2.22.0