1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
(* helper-v2v-input
* Copyright (C) 2009-2021 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
open Printf
open Unix
open Std_utils
open Tools_utils
open Common_gettext.Gettext
open Types
open Utils
open Parse_domain_from_vmx
open Input
module VMX = struct
let to_string options args = String.concat " " ("-i vmx" :: args)
let query_input_options () =
printf (f_"No input options can be used in this mode.\n")
let rec setup dir options args =
if options.input_options <> [] then
error (f_"no -io (input options) are allowed here");
if not options.read_only then
error (f_"in-place mode does not work with VMX source");
let vmx_source =
match args with
| [arg] ->
let input_password =
match options.input_password with
| None -> None
| Some ip -> Some (Nbdkit_ssh.PasswordFile ip) in
let input_transport =
match options.input_transport with
| None -> None
| Some `SSH -> Some `SSH
| Some `VDDK ->
error (f_"-i vmx: cannot use -it vddk in this input mode") in
vmx_source_of_arg input_password input_transport arg
| _ ->
error (f_"-i vmx: expecting a VMX file or ssh:// URI") in
let source, filenames = parse_domain_from_vmx vmx_source in
(match vmx_source with
| File vmx_filename ->
(* Local file in VMDK format, use qemu-nbd. *)
List.iteri (
fun i filename ->
let socket = sprintf "%s/in%d" dir i in
On_exit.unlink socket;
let cmd = QemuNBD.create
(absolute_path_from_other_file vmx_filename filename) in
QemuNBD.set_snapshot cmd true; (* protective overlay *)
QemuNBD.set_format cmd (Some "vmdk");
let _, pid = QemuNBD.run_unix socket cmd in
On_exit.kill pid
) filenames
| SSH (password, uri) ->
List.iteri (
fun i filename ->
let socket = sprintf "%s/in%d" dir i in
On_exit.unlink socket;
let vmx_path =
match uri.uri_path with
| None -> assert false (* checked by vmx_source_of_arg *)
| Some path -> path in
let abs_path = absolute_path_from_other_file vmx_path filename in
let flat_vmdk = PCRE.replace (PCRE.compile "\\.vmdk$")
"-flat.vmdk" abs_path in
let server =
match uri.uri_server with
| None -> assert false (* checked by vmx_source_of_arg *)
| Some server -> server in
let port =
match uri.uri_port with
| i when i <= 0 -> None
| i -> Some (string_of_int i) in
let user = uri.Xml.uri_user in
(* RHBZ#1774386 *)
if not (Ssh.remote_file_exists ?password ?port ~server ?user
flat_vmdk) then
error (f_"This transport does not support guests with snapshots. \
Either collapse the snapshots for this guest and try \
the conversion again, or use one of the alternate \
conversion methods described in \
virt-v2v-input-vmware(1) section \"NOTES\".");
let cor = dir // "convert" in
let bandwidth = options.bandwidth in
let nbdkit = Nbdkit_ssh.create_ssh ?bandwidth ~cor ?password
~server ?port ?user flat_vmdk in
let _, pid = Nbdkit.run_unix socket nbdkit in
On_exit.kill pid
) filenames
);
source
(* The filename can be an absolute path, but is more often a
* path relative to the location of the vmx file (which might
* be remote over SSH).
*)
and absolute_path_from_other_file other_filename filename =
if not (Filename.is_relative filename) then filename
else (Filename.dirname (absolute_path other_filename)) // filename
end
|