-
Notifications
You must be signed in to change notification settings - Fork 29
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
Implement DHCP for machine network #53
base: main
Are you sure you want to change the base?
Conversation
* add provider manifests and docs * Update local-providers docs --------- Co-authored-by: Ludwig Bedacht <[email protected]> Co-authored-by: lubedacht <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First batch of comments. Didn't look at vmservice yet
d6ecf9e
to
2ca1686
Compare
Rebased and updated copyright headers. |
This PR should also update the docs as appropriate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of reviews.
func machineHasIPAddress(machine *infrav1alpha1.ProxmoxMachine) bool { | ||
return machine.Status.IPAddresses[infrav1alpha1.DefaultNetworkDevice] != (infrav1alpha1.IPAddress{}) | ||
func machineHasIPAddress(machine *infrav1.ProxmoxMachine) bool { | ||
return machine.Status.IPAddresses[infrav1.DefaultNetworkDevice] != (infrav1.IPAddress{}) | ||
} | ||
|
||
func handleIPAddressForDevice(ctx context.Context, machineScope *scope.MachineScope, device, format string, ipamRef *corev1.TypedLocalObjectReference) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this function be refactored so that it always returns an error when it also returns an empty string? To avoid all the if err != nil || ip == "" {
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's very confusing to return an error when creating a new IP claim:
cluster-api-provider-proxmox/internal/service/vmservice/ip.go
Lines 94 to 98 in 0cd195b
err = machineScope.IPAMHelper.CreateIPAddressClaim(ctx, machineScope.ProxmoxMachine, device, format, machineScope.InfraCluster.Cluster.GetName(), ipamRef) | |
if err != nil { | |
return "", errors.Wrapf(err, "unable to create Ip address claim for machine %s", machineScope.Name()) | |
} | |
return "", nil |
also when trying to add a tag:
cluster-api-provider-proxmox/internal/service/vmservice/ip.go
Lines 112 to 117 in 0cd195b
t, err := machineScope.InfraCluster.ProxmoxClient.TagVM(ctx, vm, ipTag) | |
if err != nil { | |
return "", errors.Wrapf(err, "unable to add Ip tag to VirtualMachine %s", machineScope.Name()) | |
} | |
machineScope.ProxmoxMachine.Status.TaskRef = ptr.To(string(t.UPID)) | |
return "", nil |
Another choice is to add a third return as bool, but it's actually the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there should be an error for the ""
case that handleIPAddressForDevice
would return. Then, the usages where this is an error (i.e. if err != nil || ip == "" {
s) could be reduced to the usual if err != nil {
. Of course, usages that can handle ""
would then need to handle this new error but at least they would have the right context instead of relying on a magic return value.
Quality Gate passedThe SonarCloud Quality Gate passed, but some issues were introduced. 4 New issues |
I'm ready |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, for the long wait.
| calico | templates/cluster-template-calico.yaml | templates/crs/cni/calico.yaml | | ||
| multiple-vlans | templates/cluster-template-multiple-vlans.yaml | - | | ||
| default | templates/cluster-template.yaml | - | | ||
| Flavor | Tepmlate File | CRS File | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: Template
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure that DHCP test cases don't set IPAM fields
// DHCPEnabled returns whether DHCP is enabled. | ||
func (c ClusterNetworkConfig) DHCPEnabled() bool { | ||
switch { | ||
case (c.IPv6Config != nil && ptr.Deref(c.IPv6Config.DHCP, false)) && (c.IPv4Config != nil && ptr.Deref(c.IPv4Config.DHCP, false)): | ||
return true | ||
case (c.IPv6Config != nil && ptr.Deref(c.IPv6Config.DHCP, false)) && c.IPv4Config == nil: | ||
return true | ||
case (c.IPv4Config != nil && ptr.Deref(c.IPv4Config.DHCP, false)) && c.IPv6Config == nil: | ||
return true | ||
default: | ||
return false | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this just supposed to do this?
// DHCPEnabled returns whether DHCP is enabled. | |
func (c ClusterNetworkConfig) DHCPEnabled() bool { | |
switch { | |
case (c.IPv6Config != nil && ptr.Deref(c.IPv6Config.DHCP, false)) && (c.IPv4Config != nil && ptr.Deref(c.IPv4Config.DHCP, false)): | |
return true | |
case (c.IPv6Config != nil && ptr.Deref(c.IPv6Config.DHCP, false)) && c.IPv4Config == nil: | |
return true | |
case (c.IPv4Config != nil && ptr.Deref(c.IPv4Config.DHCP, false)) && c.IPv6Config == nil: | |
return true | |
default: | |
return false | |
} | |
} | |
// DHCPEnabled returns true when DHCP is enabled. | |
func (c ClusterNetworkConfig) DHCPEnabled() bool { | |
return c.IPv4Config.DHCPEnabled() || c.IPv6Config.DHCPEnabled() | |
} | |
// DHCPEnabled returns true when DHCP is enabled. | |
func (c *IPConfig) DHCPEnabled() bool { | |
return c != nil && ptr.Deref(c.DHCP, false) | |
} |
I think this way it's easier to understand and you can also use the IPConfig.DHCPEnabled
in the controller and vmservice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem here is we need to check if the cluster has dhcp so we can skip the IPAM pool.
Then, in the machine, we also need to check if the machine has DHCP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't contradict my proposition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test case for DHCP
if len(nic.DNSServers) != 0 { | ||
config.DNSServers = nic.DNSServers | ||
if len(nics[i].DNSServers) != 0 { | ||
config.DNSServers = nics[i].DNSServers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either do this:
config.DNSServers = nics[i].DNSServers | |
conf.DNSServers = nics[i].DNSServers |
or pass in the whole AdditionalNetworkDevice
into getNetworkConfigDataForDevice
to do the override there. Same goes for ipv6 a few lines down.
if hasDHCPEnabled(scope.InfraCluster.ProxmoxCluster.Spec.IPv4Config, | ||
networkSpec.Default, | ||
infrav1alpha1.DefaultNetworkDevice, | ||
infrav1alpha1.IPV4Format) || | ||
hasDHCPEnabled(scope.InfraCluster.ProxmoxCluster.Spec.IPv6Config, | ||
networkSpec.Default, | ||
infrav1alpha1.DefaultNetworkDevice, | ||
infrav1alpha1.IPV6Format) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would actually be less code if you move the default interface handling out of hasDHCPEnabled
and use a few intermediate variables, e.g.
if dev := networkSpec.Default; scope.InfraCluster.ProxmoxCluster.Spec.DHCPEnabled() || (dev != nil && dev.DHCP4 || dev.DHCP6) {
But more importantly, why is the default device DHCP setting even considered when DHCP is enabled on the cluster?
for _, ip := range net.IPAddresses { | ||
if ip.IPAddressType == "ipv4" && ip.IPAddress != scope.InfraCluster.ProxmoxCluster.Spec.ControlPlaneEndpoint.Host { | ||
ipv4 = ip.IPAddress | ||
} else if ip.IPAddressType == "ipv6" && !strings.Contains(ip.IPAddress, "fe80:") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use netip.Addr.IsLinkLocalUnicast
. Substring match for IPv6 is always less accurate than comparing the bits.
// DHCP4 indicates that if DHCP should be used to assign IPv4 addresses. | ||
// DHCP4 enforce device to use DHCP despite the config set in cluster.spec.ipv4Config. | ||
// +optional | ||
DHCP4 bool `json:"dhcp4,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is in the base network device? All permuations of DHCP and IPAM on the default device should be configured in the cluster network config.
This also has the same pointer issue as the cluster dhcp setting.
// DHCP indicates that DHCP should be used to assign IP addresses. | ||
// mutually exclusive with Addresses. | ||
// +optional | ||
// +kubebuilder:default=false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This default isn't needed. The behavior stays the same whether it's set to false
or null
. My pointer request was about making the user-facing API explicit.
@@ -245,3 +245,13 @@ func (c *APIClient) StartVM(ctx context.Context, vm *proxmox.VirtualMachine) (*p | |||
func (c *APIClient) TagVM(ctx context.Context, vm *proxmox.VirtualMachine, tag string) (*proxmox.Task, error) { | |||
return vm.AddTag(ctx, tag) | |||
} | |||
|
|||
// GetVMNetwork returns a VM network interfaces based on nodeName and vmID. | |||
func (c *APIClient) GetVMNetwork(ctx context.Context, vm *proxmox.VirtualMachine) (iFaces []*proxmox.AgentNetworkIface, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: named return values are not used and don't provide any additional context
THis PR adds: