diff --git a/v2v/TODO b/v2v/TODO index 3d30dcb3b..cf78969ca 100644 --- a/v2v/TODO +++ b/v2v/TODO @@ -9,6 +9,7 @@ Missing features compared to Perl version: p2v: - network dialog and network configuration + - network mapping - control where the image is sent (ie. RHEV ESD, libvirt, etc) p2v/conversion.c: "/tmp/virt-p2v-%04d%02d%02d-XXXXXXXX", @@ -26,11 +27,6 @@ v2v/source_libvirt.ml: * XXX Quoting, although it's not needed for v v2v/target_RHEV.ml: (* Old virt-v2v ignored removable media. XXX *) v2v/types.mli: (* Only used by RHEV. XXX Should be parameterized type. *) -Perform network mapping on command line, eg: - --network net1 # Means map "default" to "net1" - --network net:net2 # Means map "net" to "net2" -How did old virt-v2v do this? - For OVA support we need to have the source write to the final target directory (where possible as it might not always be possible to do that). One way to do this is to have an early target hook, called diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml index c99eaef1d..70b12091e 100644 --- a/v2v/cmdline.ml +++ b/v2v/cmdline.ml @@ -57,6 +57,19 @@ let parse_cmdline () = error (f_"unknown -i option: %s") s in + let network_map = ref [] in + let add_network, add_bridge = + let add t str = + match string_split ":" str with + | "", "" -> error (f_"invalid --bridge or --network parameter") + | out, "" | "", out -> network_map := ((t, ""), out) :: !network_map + | in_, out -> network_map := ((t, in_), out) :: !network_map + in + let add_network str = add Network str + and add_bridge str = add Bridge str in + add_network, add_bridge + in + let output_mode = ref `Libvirt in let set_output_mode = function | "libvirt" -> output_mode := `Libvirt @@ -89,6 +102,7 @@ let parse_cmdline () = let ditto = " -\"-" in let argspec = Arg.align [ + "--bridge", Arg.String add_bridge, "in:out " ^ s_"Map bridge 'in' to 'out'"; "--debug-gc",Arg.Set debug_gc, " " ^ s_"Debug GC and memory allocations"; "-i", Arg.String set_input_mode, "disk|libvirt|libvirtxml " ^ s_"Set input mode (default: libvirt)"; "-ic", Arg.Set_string input_conn, "uri " ^ s_"Libvirt URI"; @@ -96,6 +110,7 @@ let parse_cmdline () = "format " ^ s_"Input format (for -i disk)"; "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; "--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable"; + "--network", Arg.String add_network, "in:out " ^ s_"Map network 'in' to 'out'"; "--no-copy", Arg.Clear do_copy, " " ^ s_"Just write the metadata"; "-o", Arg.String set_output_mode, "libvirt|local|rhev " ^ s_"Set output mode (default: libvirt)"; "-oa", Arg.String set_output_alloc, "sparse|preallocated " ^ s_"Set output allocation mode"; @@ -152,6 +167,7 @@ read the man page virt-v2v(1). let input_format = match !input_format with "" -> None | s -> Some s in let input_mode = !input_mode in let machine_readable = !machine_readable in + let network_map = !network_map in let output_alloc = !output_alloc in let output_conn = match !output_conn with "" -> None | s -> Some s in let output_format = match !output_format with "" -> None | s -> Some s in @@ -248,5 +264,6 @@ read the man page virt-v2v(1). OutputRHEV (output_storage, rhev_params) in input, output, - debug_gc, do_copy, output_alloc, output_format, output_name, + debug_gc, do_copy, network_map, + output_alloc, output_format, output_name, quiet, root_choice, trace, verbose diff --git a/v2v/source_disk.ml b/v2v/source_disk.ml index 4f29f97f4..9bcffbe90 100644 --- a/v2v/source_disk.ml +++ b/v2v/source_disk.ml @@ -60,7 +60,7 @@ let create input_format disk = let network = { s_mac = None; s_vnet = "default"; - s_vnet_type = `Network + s_vnet_type = Network } in let source = { @@ -73,7 +73,7 @@ let create input_format disk = s_display = None; s_disks = [disk]; s_removables = []; - s_nics = [ network ]; + s_nics = [network]; } in source diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml index 9e3333255..6c2e665ce 100644 --- a/v2v/source_libvirt.ml +++ b/v2v/source_libvirt.ml @@ -209,8 +209,8 @@ let create_xml ?(map_source_file = identity) ?(map_source_dev = identity) xml = let vnet_type = match xpath_to_string "@type" "" with - | "network" -> Some `Network - | "bridge" -> Some `Bridge + | "network" -> Some Network + | "bridge" -> Some Bridge | _ -> None in match vnet_type with | None -> () diff --git a/v2v/target_libvirt.ml b/v2v/target_libvirt.ml index c8409c6bc..a2240d54c 100644 --- a/v2v/target_libvirt.ml +++ b/v2v/target_libvirt.ml @@ -114,7 +114,7 @@ let create_libvirt_xml ?pool source overlays guestcaps = fun { s_mac = mac; s_vnet_type = vnet_type; s_vnet = vnet } -> let vnet_type_str = match vnet_type with - | `Bridge -> "bridge" | `Network -> "network" in + | Bridge -> "bridge" | Network -> "network" in let nic = e "interface" [ "type", vnet_type_str ] [ diff --git a/v2v/types.ml b/v2v/types.ml index bd8db1159..582fb2fad 100644 --- a/v2v/types.ml +++ b/v2v/types.ml @@ -82,8 +82,9 @@ and source_removable = { and source_nic = { s_mac : string option; s_vnet : string; - s_vnet_type : [`Bridge|`Network]; + s_vnet_type : vnet_type; } +and vnet_type = Bridge | Network and source_display = { s_display_type : [`VNC|`Spice]; s_keymap : string option; @@ -137,7 +138,7 @@ and string_of_source_removable { s_removable_type = typ; and string_of_source_nic { s_mac = mac; s_vnet = vnet; s_vnet_type = typ } = sprintf "%s%s%s" - (match typ with `Bridge -> "bridge" | `Network -> "network") + (match typ with Bridge -> "bridge" | Network -> "network") vnet (match mac with | None -> "" diff --git a/v2v/types.mli b/v2v/types.mli index 565156a62..09af68e7a 100644 --- a/v2v/types.mli +++ b/v2v/types.mli @@ -74,9 +74,10 @@ and source_removable = { and source_nic = { s_mac : string option; (** MAC address. *) s_vnet : string; (** Source network name. *) - s_vnet_type : [`Bridge|`Network]; (** Source network type. *) + s_vnet_type : vnet_type; (** Source network type. *) } (** Network interfaces. *) +and vnet_type = Bridge | Network and source_display = { s_display_type : [`VNC|`Spice]; (** Display type. *) diff --git a/v2v/v2v.ml b/v2v/v2v.ml index 36dcd7a29..3339c7b8d 100644 --- a/v2v/v2v.ml +++ b/v2v/v2v.ml @@ -32,7 +32,8 @@ let () = Random.self_init () let rec main () = (* Handle the command line. *) let input, output, - debug_gc, do_copy, output_alloc, output_format, output_name, + debug_gc, do_copy, network_map, + output_alloc, output_format, output_name, quiet, root_choice, trace, verbose = Cmdline.parse_cmdline () in @@ -58,6 +59,28 @@ let rec main () = *) | Some name -> { source with s_name = name } in + (* Map networks and bridges. *) + let source = + let { s_nics = nics } = source in + let nics = List.map ( + fun ({ s_vnet_type = t; s_vnet = vnet } as nic) -> + try + (* Look for a --network or --bridge parameter which names this + * network/bridge (eg. --network in:out). + *) + let new_name = List.assoc (t, vnet) network_map in + { nic with s_vnet = new_name } + with Not_found -> + try + (* Not found, so look for a default mapping (eg. --network out). *) + let new_name = List.assoc (t, "") network_map in + { nic with s_vnet = new_name } + with Not_found -> + (* Not found, so return the original NIC unchanged. *) + nic + ) nics in + { source with s_nics = nics } in + (* Create a qcow2 v3 overlay to protect the source image(s). There * is a specific reason to use the newer qcow2 variant: Because the * L2 table can store zero clusters efficiently, and because diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod index 9c4a0a5ae..2a261138f 100644 --- a/v2v/virt-v2v.pod +++ b/v2v/virt-v2v.pod @@ -7,7 +7,7 @@ virt-v2v - Convert a guest to use KVM virt-v2v -ic esx://esx.example.com/ esx_guest virt-v2v -ic esx://esx.example.com/ \ - -o rhev -os rhev.nfs:/export_domain esx_guest + -o rhev -os rhev.nfs:/export_domain --network rhevm esx_guest virt-v2v -i libvirtxml -o local -os /tmp guest-domain.xml @@ -80,10 +80,11 @@ This is the same as the previous example, except you want to send the guest to a RHEV-M Export Storage Domain which is located remotely (over NFS) at C. If you are unclear about the location of the Export Storage Domain you should check the -settings on your RHEV-M management console. +settings on your RHEV-M management console. Guest network +interface(s) are connected to the target network called C. virt-v2v -ic esx://esx.example.com/ \ - -o rhev -os rhev.nfs:/export_domain esx_guest + -o rhev -os rhev.nfs:/export_domain --network rhevm esx_guest In this case the host running virt-v2v acts as a B. @@ -120,6 +121,10 @@ command line. Display help. +=item B<--bridge> ... + +See I<--network> below. + =item B<--debug-gc> Debug garbage collection and memory allocation. This is only useful @@ -176,6 +181,18 @@ This option is used to make the output more machine friendly when being parsed by other programs. See L below. +=item B<--network> in:out + +=item B<--network> out + +=item B<--bridge> in:out + +=item B<--bridge> out + +Map network (or bridge) called C to network (or bridge) called +C. If no C prefix is given, all other networks (or bridges) +are mapped to C. + =item B<--no-copy> Don't copy the disks. Instead, conversion is performed (and thrown