[Libguestfs] [PATCH v2v v2 2/2] v2v: Copy static IP address information over for Windows guests (RHBZ#1626503).
Pino Toscano
ptoscano at redhat.com
Thu Apr 25 14:30:11 UTC 2019
On Tuesday, 16 April 2019 10:55:40 CEST Richard W.M. Jones wrote:
> For Linux the guest itself remembers the IP address associated with
> each MAC address. Thus it doesn't matter if the interface type
> changes (ie. to virtio-net), because as long as we preserve the MAC
> address the guest will use the same IP address or the same DHCP
> configuration.
>
> However on Windows this association is not maintained by MAC address.
> In fact the MAC address isn't saved anywhere in the guest registry.
> (It seems instead this is likely done through PCI device type and
> address which we don't record at the moment and is almost impossible
> to preserve.) When a guest which doesn't use DHCP is migrated, the
> guest sees the brand new virtio-net devices and doesn't know what to
> do with them, and meanwhile the right static IPs are still associated
> with the old and now-defunct interfaces in the registry.
>
> We cannot collect the required information from within the guest.
> However we can collect it outside the tool by some other means
> (eg. using VMware Tools APIs) and present this information to virt-v2v
> which then writes it into the Windows guest at firstboot time.
>
> This commit adds the --mac ..:ip:.. sub-option which creates a
> Powershell script to set network adapters at firstboot. An option
> such as:
>
> --mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254
>
> approximately turns into this script:
>
> # Wait for the netkvm (virtio-net) driver to become active.
> $adapters = @()
> While (-Not $adapters) {
> Start-Sleep -Seconds 5
> $adapters = Get-NetAdapter -Physical |
> Where DriverFileName -eq "netkvm.sys"
> }
> $mac_address = '00-0c-29-e6-3d-9d'
> $ifindex = (Get-NetAdapter -Physical |
> Where MacAddress -eq $mac_address).ifIndex
> if ($ifindex) {
> New-NetIPAddress -InterfaceIndex $ifindex
> -IPAddress '192.168.0.89'
> -DefaultGateway '192.168.0.1'
> -PrefixLength 24
> Set-DnsClientServerAddress -InterfaceIndex $ifindex
> -ServerAddresses ('192.168.0.254')
> }
>
> Thanks: Brett Thurber for diagnosing the problem and suggesting paths
> towards a fix.
> ---
I have no experience on the Windows-specific parts, so I can only
comment on the v2v integration.
> diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
> index 641eed017..82f9a7da6 100644
> --- a/v2v/cmdline.ml
> +++ b/v2v/cmdline.ml
> @@ -41,11 +41,12 @@ type cmdline = {
> print_estimate : bool;
> print_source : bool;
> root_choice : root_choice;
> + static_ips : static_ip list;
> ks : Tools_utils.key_store;
> }
Instead of a separate list (which needs to be passed around, etc), most
probably this can fit as part of the Network module, adding a new
element to the vnet_type type, e.g.:
and vnet_type = Bridge | Network | Static_ip of static_ip
Most probably the static IP specification string can be parsed in a new
Network.add_static_ip method, which would also take care to check for
duplicated MAC specifications.
> + and configure_network_interfaces net_driver =
> + (* If we were asked to force network interfaces to have particular
> + * static IP addresses then it is done here by installing a
> + * Powershell script which runs at boot.
> + *)
> + if static_ips <> [] then (
> + let psh_filename = "v2vnetcf.ps1" in
> + let psh = ref [] in
> + let add = List.push_back psh in
> +
> + add "Set-PSDebug -Trace 1";
> + add "";
I suggest adding a simple helper here:
let sq = sprintf "'%s'" in
(sq = Single Quote)
> +
> + (* If virtio-net was added to the registry, we must wait for
> + * it to be installed at runtime.
> + *)
> + if net_driver = Virtio_net then (
> + add "# Wait for the netkvm (virtio-net) driver to become active.";
> + add "$adapters = @()";
> + add "While (-Not $adapters) {";
> + add " Start-Sleep -Seconds 5";
> + add " $adapters = Get-NetAdapter -Physical | Where DriverFileName -eq \"netkvm.sys\"";
> + add " Write-Host \"adapters = '$adapters'\"";
> + add "}";
> + add ""
> + );
> +
> + List.iter (
> + fun { if_mac_addr; if_ip_address; if_default_gateway;
> + if_prefix_length; if_nameservers } ->
> + add (sprintf "$mac_address = '%s'"
> + (String.replace if_mac_addr ":" "-"));
> + add "$ifindex = (Get-NetAdapter -Physical | Where MacAddress -eq $mac_address).ifIndex";
> + add "if ($ifindex) {";
> +
> + add " Write-Host \"setting IP address of adapter at $ifindex\"";
> +
> + (* New-NetIPAddress command *)
> + let args = ref [] in
> + List.push_back args "-InterfaceIndex";
> + List.push_back args "$ifindex";
> + List.push_back args "-IPAddress";
> + List.push_back args (sprintf "'%s'" if_ip_address);
'sq' can be used here.
> + (match if_default_gateway with
> + | None -> ()
> + | Some gw ->
> + List.push_back args "-DefaultGateway";
> + List.push_back args (sprintf "'%s'" gw)
'sq' can be used here.
> + );
> + (match if_prefix_length with
> + | None -> ()
> + | Some len ->
> + List.push_back args "-PrefixLength";
> + List.push_back args (string_of_int len)
> + );
> + let cmd1 = "New-NetIPAddress " ^ String.concat " " !args in
> + add (" " ^ cmd1);
Most probably this can be:
add (sprintf " New-NetIPAddress %s" (String.concat " " !args));
(just for consistency with the same pattern done few lines below this.)
> +
> + (* Set-DnsClientServerAddress command *)
> + if if_nameservers <> [] then (
> + add (sprintf " Set-DnsClientServerAddress -InterfaceIndex $ifindex -ServerAddresses (%s)"
> + (String.concat "," (List.map (sprintf "'%s'") if_nameservers)))
'sq' can be used here.
> + );
> + add "}";
> + add ""
install_firstboot_powershell already adds a newline at the end, so most
probably this empty line can be removed.
--
Pino Toscano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20190425/87786de2/attachment.sig>
More information about the Libguestfs
mailing list