in controllers/manager/gatewayvmconfiguration_controller.go [543:681]
func (r *GatewayVMConfigurationReconciler) reconcileVMSSVM(
ctx context.Context,
vmConfig *egressgatewayv1alpha1.GatewayVMConfiguration,
vmssName string,
vm *compute.VirtualMachineScaleSetVM,
ipPrefixID string,
lbBackendpoolID string,
wantIPConfig bool,
) (string, error) {
log := log.FromContext(ctx).WithValues("vmssInstance", to.Val(vm.ID), "wantIPConfig", wantIPConfig, "ipPrefixID", ipPrefixID)
ipConfigName := managedSubresourceName(vmConfig)
vmssRG := getVMSSResourceGroup(vmConfig)
if vm.Properties == nil || vm.Properties.NetworkProfileConfiguration == nil {
return "", fmt.Errorf("vmss vm(%s) has empty network profile", to.Val(vm.InstanceID))
}
if vm.Properties.OSProfile == nil {
return "", fmt.Errorf("vmss vm(%s) has empty os profile", to.Val(vm.InstanceID))
}
forceUpdate := false
// check ProvisioningState
if vm.Properties.ProvisioningState != nil && !strings.EqualFold(to.Val(vm.Properties.ProvisioningState), "Succeeded") {
log.Info(fmt.Sprintf("VMSS instance ProvisioningState %q", to.Val(vm.Properties.ProvisioningState)))
if strings.EqualFold(to.Val(vm.Properties.ProvisioningState), "Failed") {
forceUpdate = true
log.Info(fmt.Sprintf("Force update for unexpected VMSS instance ProvisioningState:%q", to.Val(vm.Properties.ProvisioningState)))
}
}
// check primary IP & secondary IP
var primaryIP, secondaryIP string
if !forceUpdate && wantIPConfig {
for _, nic := range vm.Properties.NetworkProfileConfiguration.NetworkInterfaceConfigurations {
if nic.Properties != nil && to.Val(nic.Properties.Primary) {
vmNic, err := r.GetVMSSInterface(ctx, vmssRG, vmssName, to.Val(vm.InstanceID), to.Val(nic.Name))
if err != nil || vmNic.Properties == nil || vmNic.Properties.IPConfigurations == nil {
if err != nil {
log.Info("Skip IP check for forceUpdate", "error", err.Error())
} else {
log.Info("Skip IP check for forceUpdate")
}
break
}
for _, ipConfig := range vmNic.Properties.IPConfigurations {
if ipConfig != nil && ipConfig.Properties != nil && strings.EqualFold(to.Val(ipConfig.Name), ipConfigName) {
secondaryIP = to.Val(ipConfig.Properties.PrivateIPAddress)
} else if ipConfig != nil && ipConfig.Properties != nil && to.Val(ipConfig.Properties.Primary) {
primaryIP = to.Val(ipConfig.Properties.PrivateIPAddress)
}
}
}
}
if primaryIP == "" || secondaryIP == "" {
forceUpdate = true
log.Info("Force update for missing primary IP and/or secondary IP", "primaryIP", primaryIP, "secondaryIP", secondaryIP)
}
}
interfaces := vm.Properties.NetworkProfileConfiguration.NetworkInterfaceConfigurations
needUpdate, err := r.reconcileVMSSNetworkInterface(ctx, ipConfigName, ipPrefixID, lbBackendpoolID, wantIPConfig, interfaces)
if err != nil {
return "", fmt.Errorf("failed to reconcile vm interface(%s): %w", to.Val(vm.InstanceID), err)
}
vmUpdated := false
if needUpdate || forceUpdate {
log.Info("Updating vmss instance")
if !needUpdate && forceUpdate {
log.Info("Updating vmss instance triggered by forceUpdate")
}
newVM := compute.VirtualMachineScaleSetVM{
Properties: &compute.VirtualMachineScaleSetVMProperties{
NetworkProfileConfiguration: &compute.VirtualMachineScaleSetVMNetworkProfileConfiguration{
NetworkInterfaceConfigurations: interfaces,
},
},
}
if _, err := r.UpdateVMSSInstance(ctx, vmssRG, vmssName, to.Val(vm.InstanceID), newVM); err != nil {
return "", fmt.Errorf("failed to update vmss instance(%s): %w", to.Val(vm.InstanceID), err)
}
vmUpdated = true
}
// return earlier if it's deleting event
if !wantIPConfig {
return "", nil
}
if vmUpdated || primaryIP == "" || secondaryIP == "" {
primaryIP, secondaryIP = "", ""
for _, nic := range interfaces {
if nic.Properties != nil && to.Val(nic.Properties.Primary) {
vmNic, err := r.GetVMSSInterface(ctx, vmssRG, vmssName, to.Val(vm.InstanceID), to.Val(nic.Name))
if err != nil {
return "", fmt.Errorf("failed to get vmss(%s) instance(%s) nic(%s): %w", vmssName, to.Val(vm.InstanceID), to.Val(nic.Name), err)
}
if vmNic.Properties == nil || vmNic.Properties.IPConfigurations == nil {
return "", fmt.Errorf("vmss(%s) instance(%s) nic(%s) has empty ip configurations", vmssName, to.Val(vm.InstanceID), to.Val(nic.Name))
}
for _, ipConfig := range vmNic.Properties.IPConfigurations {
if ipConfig != nil && ipConfig.Properties != nil && strings.EqualFold(to.Val(ipConfig.Name), ipConfigName) {
secondaryIP = to.Val(ipConfig.Properties.PrivateIPAddress)
} else if ipConfig != nil && ipConfig.Properties != nil && to.Val(ipConfig.Properties.Primary) {
primaryIP = to.Val(ipConfig.Properties.PrivateIPAddress)
}
}
}
}
}
if primaryIP == "" || secondaryIP == "" {
return "", fmt.Errorf("failed to find private IP from vmss(%s), instance(%s), ipConfig(%s)", vmssName, to.Val(vm.InstanceID), ipConfigName)
}
vmprofile := egressgatewayv1alpha1.GatewayVMProfile{
NodeName: to.Val(vm.Properties.OSProfile.ComputerName),
PrimaryIP: primaryIP,
SecondaryIP: secondaryIP,
}
if vmConfig.Status == nil {
vmConfig.Status = &egressgatewayv1alpha1.GatewayVMConfigurationStatus{}
}
for i, profile := range vmConfig.Status.GatewayVMProfiles {
if profile.NodeName == vmprofile.NodeName {
if profile.PrimaryIP != primaryIP || profile.SecondaryIP != secondaryIP {
vmConfig.Status.GatewayVMProfiles[i].PrimaryIP = primaryIP
vmConfig.Status.GatewayVMProfiles[i].SecondaryIP = secondaryIP
log.Info("GatewayVMConfiguration status updated", "primaryIP", primaryIP, "secondaryIP", secondaryIP)
return secondaryIP, nil
}
log.Info("GatewayVMConfiguration status not changed", "primaryIP", primaryIP, "secondaryIP", secondaryIP)
return secondaryIP, nil
}
}
log.Info("GatewayVMConfiguration status updated for new nodes", "nodeName", vmprofile.NodeName, "primaryIP", primaryIP, "secondaryIP", secondaryIP)
vmConfig.Status.GatewayVMProfiles = append(vmConfig.Status.GatewayVMProfiles, vmprofile)
return secondaryIP, nil
}