...

Source file src/edge-infra.dev/pkg/sds/patching/patchmanager/patchmanager.go

Documentation: edge-infra.dev/pkg/sds/patching/patchmanager

     1  package patchmanager
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/go-logr/logr"
    10  	"github.com/spf13/afero"
    11  
    12  	file "edge-infra.dev/pkg/sds/lib/os/file"
    13  	"edge-infra.dev/pkg/sds/patching/common"
    14  	v1patch "edge-infra.dev/pkg/sds/patching/k8s/apis/ienpatch/v1"
    15  
    16  	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
    17  )
    18  
    19  type PatchManager struct {
    20  	Ctx        context.Context
    21  	K8sClient  k8sclient.Client
    22  	Log        logr.Logger
    23  	HostName   string
    24  	Ienpatch   *v1patch.IENPatch
    25  	CurrentVer string
    26  	TargetVer  string
    27  	Fs         afero.OsFs
    28  	Cfg        common.Config
    29  }
    30  
    31  func (p *PatchManager) PatchIEN() (v1patch.PatchStatus, error) {
    32  	// Remount boot to RW
    33  	if err := remount(p.Cfg.MountPath); err != nil {
    34  		return v1patch.Retry, err
    35  	}
    36  
    37  	if err := p.installPatchset(); err != nil {
    38  		return v1patch.Retry, fmt.Errorf("Failed to unpack and install patchset: %w", err)
    39  	}
    40  
    41  	if p.Ienpatch.Spec.DownloadOnly {
    42  		p.Log.Info("Download and extraction complete. Set downloadOnly to false to continue patching")
    43  		return v1patch.DownloadComplete, nil
    44  	}
    45  
    46  	if !p.isNodeTargetted() {
    47  		return v1patch.Pending, nil
    48  	}
    49  
    50  	if err := p.WaitForRebootAllowed(); err != nil {
    51  		return v1patch.Retry, fmt.Errorf("Error occurred while waiting to see if reboot is possible: %w", err)
    52  	}
    53  
    54  	if err := generatePatchingEnv(p.CurrentVer, p.TargetVer, p.Cfg.EnvFilePath); err != nil {
    55  		return v1patch.Retry, fmt.Errorf("Failed to generate patching.env file: %w", err)
    56  	}
    57  	// Write to two paths for BWC. Clean up when all OS ver is at 1.14
    58  	if err := generatePatchingEnv(p.CurrentVer, p.TargetVer, common.EnvFilePath); err != nil {
    59  		return v1patch.Retry, fmt.Errorf("Failed to generate patching.env file: %w", err)
    60  	}
    61  
    62  	if err := requestReboot(p.Ienpatch.Spec.AutoReboot, p.Log, p.Cfg); err != nil {
    63  		return v1patch.Failed, fmt.Errorf("Failed to schedule reboot: %w", err)
    64  	}
    65  	return v1patch.Reboot, nil
    66  }
    67  
    68  func Contains(nodeList []string, nodeName string) bool {
    69  	for _, v := range nodeList {
    70  		if v == nodeName {
    71  			return true
    72  		}
    73  	}
    74  	return false
    75  }
    76  
    77  func generatePatchingEnv(currentVer, targetVer string, path string) error {
    78  	data := []byte(fmt.Sprintf("CURRENT='%s'\nTARGET='%s'\n", currentVer, targetVer))
    79  	return os.WriteFile(path, data, 0600)
    80  }
    81  
    82  func requestReboot(autoreboot bool, log logr.Logger, cfg common.Config) error {
    83  	if !autoreboot {
    84  		log.Info("Auto reboot is disabled. Please manually reboot the system")
    85  		return nil
    86  	}
    87  
    88  	perms := os.FileMode(0755)
    89  
    90  	if err := os.MkdirAll(filepath.Dir(cfg.RebootPath), perms); err != nil {
    91  		return err
    92  	}
    93  
    94  	if _, err := os.Create(cfg.RebootPath); err != nil {
    95  		return err
    96  	}
    97  
    98  	if err := os.Chmod(cfg.RebootPath, perms); err != nil {
    99  		return err
   100  	}
   101  
   102  	log.Info("Auto reboot scheduled, waiting for reboot daemon")
   103  	return nil
   104  }
   105  
   106  // Remount path with read write mode
   107  func remount(mountPath string) error {
   108  	fileHandler := file.New()
   109  	// Remount boot to RW
   110  	mountInfo, err := fileHandler.GetMountInfo(mountPath)
   111  	if err != nil {
   112  		return fmt.Errorf("Failed to get mount info for mountPath %s: %w", mountPath, err)
   113  	}
   114  
   115  	if remountErr := fileHandler.RemountFsReadWrite(mountPath, mountInfo.Source); remountErr != nil {
   116  		return fmt.Errorf("Failed to remount %s: %w", mountPath, err)
   117  	}
   118  	return nil
   119  }
   120  

View as plain text