Skip to content

Commit

Permalink
OCPBUGS-27390: IPI install fails on Nutanix with DHCP network
Browse files Browse the repository at this point in the history
  • Loading branch information
yanhua121 committed Feb 9, 2024
1 parent bb24521 commit c6e7d3f
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 110 deletions.
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,3 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace k8s.io/kubectl => k8s.io/kubectl v0.28.2
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -869,8 +869,8 @@ k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM=
k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64=
k8s.io/kubectl v0.29.0 h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI=
k8s.io/kubectl v0.29.0/go.mod h1:0jMjGWIcMIQzmUaMgAzhSELv5WtHo2a8pq67DtviAJs=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
Expand Down
79 changes: 63 additions & 16 deletions pkg/actuators/machine/machine_scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ type machineScope struct {
// For Machine vm create/update use, take a copy of the providerSpec that we can mutate.
// This must never be written back to the Machine itself.
providerSpecValidated *machinev1.NutanixMachineProviderConfig

// The machine referenced Node
node *corev1.Node
}

func newMachineScope(params machineScopeParams) (*machineScope, error) {
Expand Down Expand Up @@ -288,26 +291,65 @@ func (s *machineScope) setProviderStatus(vm *nutanixClientV3.VMIntentResponse, c
s.providerStatus.VmUUID = vm.Metadata.UUID

// update machine.status.addresses
addresses := s.machine.Status.Addresses
addr := getExistingAddress(addresses, corev1.NodeInternalIP)
if addr != nil {
addr.Address = *vm.Status.Resources.NicList[0].IPEndpointList[0].IP
} else {
addresses = append(addresses, corev1.NodeAddress{
Type: corev1.NodeInternalIP,
Address: *vm.Status.Resources.NicList[0].IPEndpointList[0].IP,
})
machineAddresses := []corev1.NodeAddress{}
vmIPEndpoints := make(map[string]bool)

for _, nic := range vm.Status.Resources.NicList {
for _, ipEndpoint := range nic.IPEndpointList {
if ipEndpoint.IP != nil && *ipEndpoint.IP != "" {
vmIPEndpoints[*ipEndpoint.IP] = true
}
}
}
addr = getExistingAddress(addresses, corev1.NodeInternalDNS)
if addr != nil {
addr.Address = *vm.Spec.Name

// If the node is linked to the machine, we use the node object's status.addresses to populate that of the machine object.
// Also validate the NodeInternalIP addresses are included in the VM's IPEndpointList
if s.isNodeLinked() {
node, err := s.getNode()
if err != nil {
return fmt.Errorf("%s: failed to get node: %w", s.machine.Name, err)
}

for _, naddr := range node.Status.Addresses {
// verify that the node's InternalIP address is included in the vm's IPEndpointList
if naddr.Type == corev1.NodeInternalIP {
if _, ok := vmIPEndpoints[naddr.Address]; !ok {
return fmt.Errorf("%s: the node's InternalIP address %s is not found in the Machine VM's ip_endpoint_list.", s.machine.Name, naddr.Address)
}
}

// add the node's address to the Machine object.
machineAddresses = append(machineAddresses, corev1.NodeAddress{
Type: naddr.Type,
Address: naddr.Address,
})

}
klog.V(3).Infof("%s: use the node object's addresses to populate that of the machine object.", s.machine.Name)

} else {
addresses = append(addresses, corev1.NodeAddress{
Type: corev1.NodeInternalDNS,
// Node is not ready
klog.V(3).Infof("%s: the node is not ready yet.", s.machine.Name)
}

// if the node is not ready or not having addresses data yet,
// use the VM's data to popute the machine addresses
if len(machineAddresses) == 0 {
for ipAddr, _ := range vmIPEndpoints {
machineAddresses = append(machineAddresses, corev1.NodeAddress{
Type: corev1.NodeInternalIP,
Address: ipAddr,
})
}

machineAddresses = append(machineAddresses, corev1.NodeAddress{
Type: corev1.NodeHostName,
Address: *vm.Spec.Name,
})
}
s.machine.Status.Addresses = addresses

s.machine.Status.Addresses = machineAddresses
klog.V(3).Infof("%s: the machine status.addresses=%+v.", s.machine.Name, s.machine.Status.Addresses)

s.providerStatus.Conditions = setNutanixProviderConditions([]metav1.Condition{condition}, s.providerStatus.Conditions)

Expand All @@ -319,6 +361,10 @@ func (s *machineScope) isNodeLinked() bool {
}

func (s *machineScope) getNode() (*corev1.Node, error) {
if s.node != nil {
return s.node, nil
}

var node corev1.Node
if !s.isNodeLinked() {
return nil, fmt.Errorf("[Machine: %s] NodeRef empty, unable to get related Node", s.machine.Name)
Expand All @@ -339,7 +385,8 @@ func (s *machineScope) getNode() (*corev1.Node, error) {
return nil, err
}

return &node, nil
s.node = &node
return s.node, nil
}

// nodeHasVolumesAttached returns true if node status still have volumes attached
Expand Down
45 changes: 8 additions & 37 deletions pkg/actuators/machine/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"time"

nutanixClientV3 "github.com/nutanix-cloud-native/prism-go-client/pkg/nutanix/v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"

machinecontroller "github.com/openshift/machine-api-operator/pkg/controller/machine"
Expand Down Expand Up @@ -244,28 +242,6 @@ func (r *Reconciler) exists() (bool, error) {
return true, nil
}

// isMaster returns true if the machine is part of a cluster's control plane
func (r *Reconciler) isMaster() (bool, error) {
if r.machine.Status.NodeRef == nil {
klog.Errorf("NodeRef not found in machine %q", r.machine.Name)
return false, nil
}
node := &corev1.Node{}
nodeKey := types.NamespacedName{
Name: r.machine.Status.NodeRef.Name,
}

err := r.client.Get(r.Context, nodeKey, node)
if err != nil {
return false, fmt.Errorf("failed to get node from machine %s", r.machine.Name)
}

if _, exists := node.Labels[masterLabel]; exists {
return true, nil
}
return false, nil
}

// setProviderID adds providerID in the machine spec
func (r *Reconciler) setProviderID(vmUUID *string) error {
if vmUUID == nil {
Expand All @@ -282,34 +258,29 @@ func (r *Reconciler) setProviderID(vmUUID *string) error {
klog.Infof("%s: ProviderID set at machine.spec: %s", r.machine.Name, providerID)
}

if r.machine.Status.NodeRef == nil {
klog.Infof("%s: the Machine node is not ready yet.", r.machine.Name)
if !r.machineScope.isNodeLinked() {
// Node is not ready
klog.V(3).Infof("%s: the node is not ready yet.", r.machine.Name)
return nil
}

// update the corresponding node.Spec.ProviderID
nodeName := r.machine.Status.NodeRef.Name
if len(nodeName) == 0 {
nodeName = r.machine.Name
}
nodeKey := types.NamespacedName{Name: nodeName}
node := &corev1.Node{}
err := r.client.Get(r.Context, nodeKey, node)
node, err := r.machineScope.getNode()
if err != nil {
return fmt.Errorf("%s: failed to get node %s: %w", r.machine.Name, nodeName, err)
return fmt.Errorf("%s: failed to get node: %w", r.machine.Name, err)
}

existingNodeProviderID := node.Spec.ProviderID
if existingNodeProviderID == providerID {
klog.Infof("%s: The node %q spec.providerID is already set with value: %s", r.machine.Name, nodeName, existingNodeProviderID)
klog.Infof("%s: The node %q spec.providerID is already set with value: %s", r.machine.Name, node.Name, existingNodeProviderID)
} else {
node.Spec.ProviderID = providerID
err := r.client.Update(r.Context, node)
if err != nil {
klog.Errorf("%s: failed to update the node %q spec.providerID. error: %v", r.machine.Name, nodeName, err)
klog.Errorf("%s: failed to update the node %q spec.providerID. error: %v", r.machine.Name, node.Name, err)
return err
}
klog.Infof("%s: The node %q spec.providerID is set to: %s", r.machine.Name, nodeName, providerID)
klog.Infof("%s: The node %q spec.providerID is set to: %s", r.machine.Name, node.Name, providerID)
}

return nil
Expand Down
6 changes: 4 additions & 2 deletions vendor/k8s.io/kubectl/pkg/cmd/util/factory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions vendor/k8s.io/kubectl/pkg/cmd/util/factory_client_access.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 16 additions & 4 deletions vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 22 additions & 1 deletion vendor/k8s.io/kubectl/pkg/drain/drain.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions vendor/k8s.io/kubectl/pkg/util/openapi/openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c6e7d3f

Please sign in to comment.