-
-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Waiting for proxmox_virtual_environment_vm's ipv4_addresses does not really work #100
Comments
I thought about it a bit more, and it looks like it would be better to have waiting requirements on interfaces themselves, something like: resource "proxmox_virtual_environment_vm" "example_vm" {
network_device {
wait_for_ipv4 = [ ... ]
wait_for_ipv6 = [ ... ]
}
network_device {
wait_for_ipv4 = [ ... ]
wait_for_ipv6 = [ ... ]
}
} Instead of simple true or false, there should be a list of rules.
In other words, rule is satisfied by given IP address if:
Each rule is a requirement for one IP address of the interface. Once an IP address is used to satisfy a rule, Empty list of rules means "do not wait for address" on this interface: wait_for_ipv4 = [] # do not wait for ipv4 address A list of rules containing empty list the only rule means "wait for any address": wait_for_ipv4 = [
[], # rule accepts any IP address
] Accept blocks (IPv4)
Accept blocks (IPv6)
Reject blocks
Note that "any" is not that useful, it is automatically implied in rule list that contains only reject blocks. Defaults Default should be: network_device {
wait_for_ipv4 = [
[], # wait for any IPv4 address
]
wait_for_ipv6 = [ ] # do not wait for IPv6 address
} Examples Wait for both IPv4 and IPv6 addresses that imply some any connectivity network_device {
wait_for_ipv4 = [
[ "!link" ], # wait for IPv4 address except 192.254.0.0/16
]
wait_for_ipv6 = [
[ "!link" ], # wait for IPv6 address except fe80::/64
]
} Wait for private IPv6 addresses network_device {
wait_for_ipv6 = [
[ "private" ], # wait for IPv6 address from "fc00::/7"
]
} Wait for global IPv6 addresses network_device {
wait_for_ipv6 = [
[ "!link", "!private" ], # wait for IPv6 address except from "fe80::/64" or "fc00::/7"
]
} or network_device {
wait_for_ipv6 = [
[ "link" ],
[ "!private", "!*" ], # wait for IPv6 address except from "fc00::/7" and anything that would match the earlier rules
]
} Wait for two different private IPv6 addresses network_device {
wait_for_ipv6 = [
[ "private" ], # the IPv6 address that matches this rule will not be considered for the following rule...
[ "private" ],
]
} Wait for two different private IPv6 addresses out of three possible networks, and a global IPv6 network_device {
wait_for_ipv6 = [
[ "fdf2:f3bf:406c::/48", "fd8e:eb98:4b15::/48", "fd00:83ec:7b96::/48" ],
[ "fdf2:f3bf:406c::/48", "fd8e:eb98:4b15::/48", "fd00:83ec:7b96::/48" ],
[ "!link", "!*" ],
]
} Details Matching If It is possible to wait for:
It is not possible to wait for IPv4 or IPv6. I have not found a use case that would actually require it. Possible additional use It could be useful to provide outputs resource "proxmox_virtual_environment_vm" "example_vm" {
network_device {
wait_for_ipv6 = [
[ "link" ],
[ "private" ],
[ "!*" ],
]
}
}
locals {
link_ipv6_address = proxmox_virtual_environment_vm.example_vm.waited_for_ipv6[0][0]
private_ipv6_address = proxmox_virtual_environment_vm.example_vm.waited_for_ipv6[0][1]
global_ipv6_address = proxmox_virtual_environment_vm.example_vm.waited_for_ipv6[0][2]
global_ipv6_address_another_way = proxmox_virtual_environment_vm.example_vm.waited_for_ipv6[0][-1]
} Given that last wait_for rule would generally match the most non-local (either private or global) IPv6 address, using e.g. In production environment [-1] is global, [-2] is private. In dev/test [-1] is private [-2] is link-local. Note that qemu geust agent does not provide information about which IP addresses are temporary, therefore using Why the long comment ? Before attempting to write a patch, I'm looking for a feedback. |
Thanks @otopetrik, this is really informative. Let me think about this problem for a little bit. |
I'm not sure if the full-featured set of rules per interface and rule matching logic is the best way to go. It also seems waiting for either (not both) of IPv4 or IPv6 is a valid use case during VM provisioning -- the first address returned can be used to establish a control connection to the VM for further customization. Though I agree that a simple wait for any address is not enough. We may need to make sure the address is routable, as well as we may need to filter out some addresses. I was looking around how other Terraform provides approached this problem, it looks like vsphere provider might be a good example. Something like combination of VM options wait_for_guest_net_routable and ignored_guest_ips might be sufficient to cover majority of use cases. Implementation is in WaitForGuestNet But anyway, this is just my opinion, I don't have IPv6 set up in my proxmox environments, so can't really test the use cases you are describing and probably am missing some important details. |
Even assuming link-local addresses are ignored, it would work fully only in IPv4-only networks or IPv6-only networks. In mixed networks, there is no way to know, if DHCPv4 server response will be faster than DHCPv6/RA response. For provisioning, it would likely be possible to work around it using conditional expressions.
That seems to use routing table from inside the VM. Qemu guest agent provides only MAC address, interface name, and list of IP addresses. There is not a portable way to get default gateway address, and running But something like configurable
I have noticed this bug on an IPv4-only network, when VM provisioning sometimes failed. I thought that ignoring the link-local address would not fix the issue completely. But it looks like filtering It fixes the immediate bug - it should be possible to provision VM templates with IPv4 and IPv6 enabled:
|
VM can get IPv6 link-local address faster than a DHCP server response, that results in 'ipv4_addresses' output being an empty list. It is then impossible to provision the VM using 'connection.host' field derived from 'self.ipv4_addresses'. Once again change waiting for IP address to wait for better address than IPv4 link-local addresses and IPv6 link-local addresses. Should not break bpg#182, because it requires only one GlobalUnicast address per VM.
After long time updated to a newer version, the bug reappeared. Looks like the #182 reintroduced it. It completely ignores the result of The
Variable
is true , because of the right side of || operator is true .All without any dependency on whether there is any IP address, that actually satisfies IsGlobalUnicast or not. Relevant code from terraform.tfstate
At this point terraform fails again on:
as described in the original issue. |
…#345) fix: Wait for 'net.IsGlobalUnicast' IP address, again (#100) VM can get IPv6 link-local address faster than a DHCP server response, that results in 'ipv4_addresses' output being an empty list. It is then impossible to provision the VM using 'connection.host' field derived from 'self.ipv4_addresses'. Once again change waiting for IP address to wait for better address than IPv4 link-local addresses and IPv6 link-local addresses. Should not break #182, because it requires only one GlobalUnicast address per VM.
Describe the bug
Waiting for any IP address is not enough. The fastest available one (IPv6 link-local) is usually not enough.
Even in case of actual IPv4 and IPv6 addresses, (random) one of them would be acquired first, making it impossible to reliably connect/provision.
To Reproduce
Steps to reproduce the behavior:
terraform-provider-proxmox/proxmox/virtual_environment_vm.go
Line 405 in b26e737
terraform-provider-proxmox/example/resource_virtual_environment_vm.tf
Line 78 in b26e737
Expected behavior
The following line
terraform-provider-proxmox/example/resource_virtual_environment_vm.tf
Line 78 in b26e737
should work...
Screenshots
excerpt from terraform.tfstate
At this time, the machine can be connected only over IPv6, and using link-local address. Chances are even in IPv6-only scenario, there is a router between the machine running terraform and the VM.
Additional context
In
terraform-provider-proxmox/proxmox/virtual_environment_vm.go
Line 386 in b26e737
waitForIP
boolean is not enough.There should more complex condition.
Probably adding something like the following to
proxmox_virtual_environment_vm
'sagent
block:(defaulting only
ipv4
totrue
seems reasonable)The provider should wait until all condition marked
true
are met.Even better solution would be to repeat
expect_networking
block per-interface:This example would result in waiting until
eth0
has an IPv4 address andeth2
has non-link-local IPv6 address (even in ifeth1
interface already has IPv4 and IPv6 addresses).This could be useful for VMs that have static addresses on some interfaces (e.g. router VMs,...)
Omitting
interface
field should allow any interface to fulfil the condition imposed by the block.Then the first example would be a bit stricter - it would mean that there has to be one interface that has both IPv4 and IPv6 addresses.
Weaker condition, requiring IPv4 and IPv6 addresses, but optionally on different interfaces would look like this:
(VM with single network interface that has both IPv4 and IPv6 would also fulfil this condition)
The text was updated successfully, but these errors were encountered: