...

Source file src/edge-infra.dev/pkg/sds/display/k8s/controllers/displayctl/nodedisplayconfig_upgrade.go

Documentation: edge-infra.dev/pkg/sds/display/k8s/controllers/displayctl

     1  package displayctl
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"edge-infra.dev/pkg/sds/display/displaymanager/manager"
     8  	v2 "edge-infra.dev/pkg/sds/display/k8s/apis/v2"
     9  	"edge-infra.dev/pkg/sds/lib/set"
    10  )
    11  
    12  // Upgrades the NodeDisplayConfig, if required.
    13  //
    14  // The NodeDisplayConfig requires an upgrade if either:
    15  //   - It has just been converted by the webhook.
    16  //   - It was previously upgraded, but one or more of the displays
    17  //     were disconnected and couldn't be identified.
    18  func (c *NodeDisplayConfigController) upgradeNodeDisplayConfig(ctx context.Context, nodeDisplayConfig *v2.NodeDisplayConfig) (bool, error) {
    19  	if !requiresUpgrade(nodeDisplayConfig) {
    20  		return false, nil
    21  	}
    22  
    23  	// read the current display configuration so we can find which port
    24  	// displays identified by MPID are connected to
    25  	displayConfig, err := readDisplayConfiguration(ctx, c.DisplayManager)
    26  	if err != nil {
    27  		return false, err
    28  	}
    29  
    30  	// if the NodeDisplayConfig has V1 spec, it has just been converted
    31  	// by the conversion webhook and needs upgrading
    32  	if nodeDisplayConfig.Spec.HasV1() {
    33  		upgradeV1Spec(nodeDisplayConfig, displayConfig)
    34  		return true, nil
    35  	}
    36  
    37  	// if there is no V1 spec, attempt to identify displays which were
    38  	// disconnected during the upgrade
    39  	return identifyDisconnectedDisplays(nodeDisplayConfig, displayConfig), nil
    40  }
    41  
    42  func requiresUpgrade(nodeDisplayConfig *v2.NodeDisplayConfig) bool {
    43  	if nodeDisplayConfig.Spec == nil {
    44  		return false
    45  	}
    46  
    47  	if nodeDisplayConfig.Spec.HasV1() {
    48  		return true
    49  	}
    50  
    51  	return nodeDisplayConfig.Spec.HasDisconnected()
    52  }
    53  
    54  func readDisplayConfiguration(ctx context.Context, displayManager manager.DisplayManager) (*v2.DisplayConfig, error) {
    55  	// wait for display manager to become ready before applying configuration
    56  	if err := displayManager.Wait(ctx); err != nil {
    57  		return nil, fmt.Errorf("display manager did not become ready: %w", err)
    58  	}
    59  
    60  	// read displays and input devices from node
    61  	displayConfig, _, err := displayManager.Read(ctx)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("unable to read display configuration from node: %w", err)
    64  	}
    65  
    66  	return displayConfig, nil
    67  }
    68  
    69  func upgradeV1Spec(nodeDisplayConfig *v2.NodeDisplayConfig, displayConfig *v2.DisplayConfig) {
    70  	result, disconnectedIDs := v2.DisplayConfigFromV1(nodeDisplayConfig.Spec.V1, displayConfig)
    71  	nodeDisplayConfig.Spec = result
    72  	if len(disconnectedIDs) > 0 {
    73  		nodeDisplayConfig.Status.Upgrade.DisconnectedDisplays = disconnectedIDs
    74  	}
    75  }
    76  
    77  func identifyDisconnectedDisplays(nodeDisplayConfig *v2.NodeDisplayConfig, displayConfig *v2.DisplayConfig) bool {
    78  	identified := set.Set[v2.DisplayPort]{}
    79  	disconnectedIDs := nodeDisplayConfig.DisconnectedDisplayIDs()
    80  
    81  	// identify disconnected in displays
    82  	for idx, display := range nodeDisplayConfig.Spec.Displays {
    83  		if mpid, ok := disconnectedIDs[display.DisplayPort]; ok {
    84  			if foundDisplay := displayConfig.Displays.FindByMPID(mpid); foundDisplay != nil {
    85  				identified.Add(display.DisplayPort)
    86  				display.DisplayPort = foundDisplay.DisplayPort
    87  				nodeDisplayConfig.Spec.Displays[idx] = display
    88  			}
    89  		}
    90  	}
    91  
    92  	// identify disconnected in layout
    93  	for idx, dp := range nodeDisplayConfig.Spec.Layout {
    94  		if mpid, ok := disconnectedIDs[dp]; ok {
    95  			if foundDisplay := displayConfig.Displays.FindByMPID(mpid); foundDisplay != nil {
    96  				identified.Add(dp)
    97  				nodeDisplayConfig.Spec.Layout[idx] = foundDisplay.DisplayPort
    98  			}
    99  		}
   100  	}
   101  
   102  	// updated disconnected displays
   103  	disconnectedIDs = removeIdentifiedFromDisconnectedIDs(disconnectedIDs, identified.ToSlice())
   104  	nodeDisplayConfig.Status.Upgrade.DisconnectedDisplays = disconnectedIDs
   105  
   106  	return len(identified) > 0
   107  }
   108  
   109  func removeIdentifiedFromDisconnectedIDs(disconnectedIDs map[v2.DisplayPort]v2.MPID, identified []v2.DisplayPort) map[v2.DisplayPort]v2.MPID {
   110  	for _, dp := range identified {
   111  		delete(disconnectedIDs, dp)
   112  	}
   113  
   114  	if len(disconnectedIDs) == 0 {
   115  		return nil
   116  	}
   117  
   118  	return disconnectedIDs
   119  }
   120  

View as plain text