Merge pull request #126 from safing/feature/hub-upgrading

Add automatic upgrades for spn-hub
This commit is contained in:
Daniel
2020-08-11 16:57:58 +02:00
committed by GitHub
3 changed files with 132 additions and 24 deletions

View File

@@ -5,12 +5,12 @@ import (
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portmaster/updates"
)
const (
eventShutdown = "shutdown"
eventRestart = "restart"
restartCode = 23
)
func registerEvents() {
@@ -43,8 +43,6 @@ func shutdown(ctx context.Context, _ interface{}) error {
// restart restarts the Portmaster.
func restart(ctx context.Context, data interface{}) error {
log.Info("core: user requested restart")
modules.SetExitStatusCode(restartCode)
// Do not use a worker, as this would block itself here.
go modules.Shutdown() //nolint:errcheck
updates.RestartNow()
return nil
}

65
updates/restart.go Normal file
View File

@@ -0,0 +1,65 @@
package updates
import (
"context"
"time"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/tevino/abool"
)
const (
// RestartExitCode will instruct portmaster-start to restart the process immediately, potentially with a new version.
RestartExitCode = 23
)
var (
restartTask *modules.Task
restartPending *abool.AtomicBool
restartTriggered *abool.AtomicBool
)
func init() {
restartTask = module.NewTask("automatic restart", automaticRestart).MaxDelay(10 * time.Minute)
}
// DelayedRestart triggers a restart of the application by shutting down the
// module system gracefully and returning with RestartExitCode. The restart
// may be further delayed by up to 10 minutes by the internal task scheduling
// system. This only works if the process is managed by portmaster-start.
func DelayedRestart(delay time.Duration) {
log.Warningf("updates: restart triggered, will execute in %s", delay)
// This enables TriggerRestartIfPending.
// Subsequent calls to TriggerRestart should be able to set a new delay.
restartPending.Set()
// Schedule the restart task.
restartTask.Schedule(time.Now().Add(delay))
}
// TriggerRestartIfPending triggers an automatic restart, if one is pending.
// This can be used to prepone a scheduled restart if the conditions are preferable.
func TriggerRestartIfPending() {
if restartPending.IsSet() {
_ = automaticRestart(module.Ctx, nil)
}
}
// RestartNow immediately executes a restart.
// This only works if the process is managed by portmaster-start.
func RestartNow() {
_ = automaticRestart(module.Ctx, nil)
}
func automaticRestart(_ context.Context, _ *modules.Task) error {
if restartTriggered.SetToIf(false, true) {
log.Info("updates: initiating automatic restart")
modules.SetExitStatusCode(RestartExitCode)
// Do not use a worker, as this would block itself here.
go modules.Shutdown() //nolint:errcheck
}
return nil
}

View File

@@ -11,16 +11,15 @@ import (
"strings"
"time"
"github.com/tevino/abool"
"github.com/google/renameio"
processInfo "github.com/shirou/gopsutil/process"
"github.com/tevino/abool"
"github.com/safing/portbase/info"
"github.com/safing/portbase/log"
"github.com/safing/portbase/notifications"
"github.com/safing/portbase/rng"
"github.com/safing/portbase/updater"
processInfo "github.com/shirou/gopsutil/process"
)
const (
@@ -29,12 +28,13 @@ const (
)
var (
// UpgradeCore specifies if portmaster-core should be upgraded.
UpgradeCore = true
upgraderActive = abool.NewBool(false)
pmCtrlUpdate *updater.File
pmCoreUpdate *updater.File
pmCtrlUpdate *updater.File
pmCoreUpdate *updater.File
spnHubUpdate *updater.File
hubUpgradeStarted bool
rawVersionRegex = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+b?\*?$`)
)
@@ -61,34 +61,43 @@ func upgrader(_ context.Context, _ interface{}) error {
log.Warningf("updates: failed to upgrade portmaster-start: %s", err)
}
if UpgradeCore {
binBaseName := strings.Split(filepath.Base(os.Args[0]), "_")[0]
switch binBaseName {
case "portmaster-core":
err = upgradeCoreNotify()
if err != nil {
log.Warningf("updates: failed to notify about core upgrade: %s", err)
}
case "spn-hub":
err = upgradeHub()
if err != nil {
log.Warningf("updates: failed to initiate hub upgrade: %s", err)
}
}
return nil
}
func upgradeCoreNotify() error {
if pmCoreUpdate != nil && !pmCoreUpdate.UpgradeAvailable() {
return nil
}
// make identifier
identifier := "core/portmaster-core" // identifier, use forward slash!
if onWindows {
identifier += exeExt
}
// check if we can upgrade
if pmCoreUpdate == nil || pmCoreUpdate.UpgradeAvailable() {
// get newest portmaster-core
new, err := GetPlatformFile(identifier)
if err != nil {
return err
}
pmCoreUpdate = new
} else {
return nil
// get newest portmaster-core
new, err := GetPlatformFile(identifier)
if err != nil {
return err
}
pmCoreUpdate = new
// check for new version
if info.GetInfo().Version != pmCoreUpdate.Version() {
n := notifications.NotifyInfo(
"updates:core-update-available",
@@ -128,6 +137,42 @@ func upgradeCoreNotifyActionHandler(n *notifications.Notification) {
}
}
func upgradeHub() error {
if hubUpgradeStarted {
return nil
}
if spnHubUpdate != nil && !spnHubUpdate.UpgradeAvailable() {
return nil
}
// make identifier
identifier := "hub/spn-hub" // identifier, use forward slash!
if onWindows {
identifier += exeExt
}
// get newest spn-hub
new, err := GetPlatformFile(identifier)
if err != nil {
return err
}
spnHubUpdate = new
// check for new version
if info.GetInfo().Version != spnHubUpdate.Version() {
// get random delay with up to three hours
delayMinutes, err := rng.Number(3 * 60)
if err != nil {
return err
}
DelayedRestart(time.Duration(delayMinutes) * time.Minute)
hubUpgradeStarted = true
}
return nil
}
func upgradePortmasterStart() error {
filename := "portmaster-start"
if onWindows {