2023-12-27 00:03:45 +00:00
|
|
|
package lifecycle
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-08-01 21:52:15 +00:00
|
|
|
"errors"
|
2023-12-27 00:03:45 +00:00
|
|
|
"fmt"
|
|
|
|
"log/slog"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
|
|
|
)
|
|
|
|
|
|
|
|
func DoUpgrade(cancel context.CancelFunc, done chan int) error {
|
|
|
|
files, err := filepath.Glob(filepath.Join(UpdateStageDir, "*", "*.exe")) // TODO generalize for multiplatform
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to lookup downloads: %s", err)
|
|
|
|
}
|
|
|
|
if len(files) == 0 {
|
2024-08-01 21:52:15 +00:00
|
|
|
return errors.New("no update downloads found")
|
2023-12-27 00:03:45 +00:00
|
|
|
} else if len(files) > 1 {
|
|
|
|
// Shouldn't happen
|
|
|
|
slog.Warn(fmt.Sprintf("multiple downloads found, using first one %v", files))
|
|
|
|
}
|
|
|
|
installerExe := files[0]
|
|
|
|
|
|
|
|
slog.Info("starting upgrade with " + installerExe)
|
|
|
|
slog.Info("upgrade log file " + UpgradeLogFile)
|
|
|
|
|
2024-10-30 16:24:31 +00:00
|
|
|
// make the upgrade show progress, but non interactive
|
2023-12-27 00:03:45 +00:00
|
|
|
installArgs := []string{
|
|
|
|
"/CLOSEAPPLICATIONS", // Quit the tray app if it's still running
|
|
|
|
"/LOG=" + filepath.Base(UpgradeLogFile), // Only relative seems reliable, so set pwd
|
|
|
|
"/FORCECLOSEAPPLICATIONS", // Force close the tray app - might be needed
|
2024-10-30 16:24:31 +00:00
|
|
|
"/SP", // Skip the "This will install... Do you wish to continue" prompt
|
|
|
|
"/NOCANCEL", // Disable the ability to cancel upgrade mid-flight to avoid partially installed upgrades
|
2023-12-27 00:03:45 +00:00
|
|
|
"/SILENT",
|
2024-10-30 16:24:31 +00:00
|
|
|
}
|
2023-12-27 00:03:45 +00:00
|
|
|
|
|
|
|
// Safeguard in case we have requests in flight that need to drain...
|
|
|
|
slog.Info("Waiting for server to shutdown")
|
|
|
|
cancel()
|
|
|
|
if done != nil {
|
|
|
|
<-done
|
|
|
|
} else {
|
2024-02-15 17:56:49 +00:00
|
|
|
// Shouldn't happen
|
|
|
|
slog.Warn("done chan was nil, not actually waiting")
|
2023-12-27 00:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
slog.Debug(fmt.Sprintf("starting installer: %s %v", installerExe, installArgs))
|
|
|
|
os.Chdir(filepath.Dir(UpgradeLogFile)) //nolint:errcheck
|
|
|
|
cmd := exec.Command(installerExe, installArgs...)
|
|
|
|
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
|
|
return fmt.Errorf("unable to start ollama app %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if cmd.Process != nil {
|
|
|
|
err = cmd.Process.Release()
|
|
|
|
if err != nil {
|
|
|
|
slog.Error(fmt.Sprintf("failed to release server process: %s", err))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// TODO - some details about why it didn't start, or is this a pedantic error case?
|
2024-08-01 21:52:15 +00:00
|
|
|
return errors.New("installer process did not start")
|
2023-12-27 00:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO should we linger for a moment and check to make sure it's actually running by checking the pid?
|
|
|
|
|
|
|
|
slog.Info("Installer started in background, exiting")
|
|
|
|
|
|
|
|
os.Exit(0)
|
|
|
|
// Not reached
|
|
|
|
return nil
|
|
|
|
}
|