File: input_vmx.ml

package info (click to toggle)
virt-v2v 2.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 25,256 kB
  • sloc: ml: 19,861; sh: 8,454; ansic: 6,880; makefile: 2,797; python: 1,114; perl: 854; xml: 117
file content (138 lines) | stat: -rw-r--r-- 4,953 bytes parent folder | download | duplicates (3)
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
133
134
135
136
137
138
(* helper-v2v-input
 * Copyright (C) 2009-2025 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

    let uris =
      match vmx_source with
      | VMXSourceFile vmx_filename ->
         (* Local file in VMDK format, use qemu-nbd. *)
         List.mapi (
           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;

             NBD_URI.Unix (socket, None)
         ) filenames

      | VMXSourceSSH (password, uri) ->
         List.mapi (
           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;

             NBD_URI.Unix (socket, None)
         ) filenames in

    source, uris

  (* 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