Revert "cmd/syncthing: Do auto-upgrade before startup (fixes #6384) (#6385)"

This reverts commit c101a04179.
This commit is contained in:
Jakob Borg 2020-04-07 12:55:25 +02:00
parent 670a9809fa
commit 0275cbd66a

View File

@ -139,12 +139,10 @@ The following are valid values for the STTRACE variable:
%s` %s`
) )
var (
// Environment options // Environment options
var (
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != "" innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != "" noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != ""
errConcurrentUpgrade = errors.New("upgrade prevented by other running Syncthing instance")
) )
type RuntimeOptions struct { type RuntimeOptions struct {
@ -361,24 +359,14 @@ func main() {
} }
if options.doUpgradeCheck { if options.doUpgradeCheck {
if _, err := checkUpgrade(); err != nil { checkUpgrade()
l.Warnln("Checking for upgrade:", err)
os.Exit(exitCodeForUpgrade(err))
}
return return
} }
if options.doUpgrade { if options.doUpgrade {
release, err := checkUpgrade() release := checkUpgrade()
if err == nil { performUpgrade(release)
err = performUpgrade(release) return
}
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(exitCodeForUpgrade(err))
}
l.Infof("Upgraded to %q", release.Tag)
os.Exit(syncthing.ExitUpgrade.AsInt())
} }
if options.resetDatabase { if options.resetDatabase {
@ -474,47 +462,45 @@ func debugFacilities() string {
return b.String() return b.String()
} }
type errNoUpgrade struct { func checkUpgrade() upgrade.Release {
current, latest string
}
func (e errNoUpgrade) Error() string {
return fmt.Sprintf("no upgrade available (current %q >= latest %q).", e.current, e.latest)
}
func checkUpgrade() (upgrade.Release, error) {
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger) cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
opts := cfg.Options() opts := cfg.Options()
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases) release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
if err != nil { if err != nil {
return upgrade.Release{}, err l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
} }
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 { if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
return upgrade.Release{}, errNoUpgrade{build.Version, release.Tag} noUpgradeMessage := "No upgrade available (current %q >= latest %q)."
l.Infof(noUpgradeMessage, build.Version, release.Tag)
os.Exit(syncthing.ExitNoUpgradeAvailable.AsInt())
} }
l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag) l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag)
return release, nil return release
} }
func performUpgradeDirect(release upgrade.Release) error { func performUpgrade(release upgrade.Release) {
// Use leveldb database locks to protect against concurrent upgrades // Use leveldb database locks to protect against concurrent upgrades
if _, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto); err != nil { _, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto)
return errConcurrentUpgrade if err == nil {
} err = upgrade.To(release)
return upgrade.To(release) if err != nil {
} l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
func performUpgrade(release upgrade.Release) error {
if err := performUpgradeDirect(release); err != nil {
if err != errConcurrentUpgrade {
return err
} }
l.Infof("Upgraded to %q", release.Tag)
} else {
l.Infoln("Attempting upgrade through running Syncthing...") l.Infoln("Attempting upgrade through running Syncthing...")
return upgradeViaRest() err = upgradeViaRest()
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
}
l.Infoln("Syncthing upgrading")
os.Exit(syncthing.ExitUpgrade.AsInt())
} }
return nil
} }
func upgradeViaRest() error { func upgradeViaRest() error {
@ -582,45 +568,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
os.Exit(syncthing.ExitError.AsInt()) os.Exit(syncthing.ExitError.AsInt())
} }
// Candidate builds should auto upgrade. Make sure the option is set,
// unless we are in a build where it's disabled or the STNOUPGRADE
// environment variable is set.
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
opts.AutoUpgradeIntervalH = 12
// Set the option into the config as well, as the auto upgrade
// loop expects to read a valid interval from there.
cfg.SetOptions(opts)
cfg.Save()
}
// We don't tweak the user's choice of upgrading to pre-releases or
// not, as otherwise they cannot step off the candidate channel.
}
// Check if auto-upgrades should be done and if yes, do an initial
// upgrade immedately. The auto-upgrade routine can only be started
// later after App is initialised.
shouldAutoUpgrade := shouldUpgrade(cfg, runtimeOptions)
if shouldAutoUpgrade {
// Try to do upgrade directly
release, err := checkUpgrade()
if err == nil {
if err = performUpgradeDirect(release); err == nil {
l.Infof("Upgraded to %q, exiting now.", release.Tag)
os.Exit(syncthing.ExitUpgrade.AsInt())
}
}
// Log the error if relevant.
if err != nil {
if _, ok := err.(errNoUpgrade); !ok {
l.Infoln("Initial automatic upgrade:", err)
}
}
}
if runtimeOptions.unpaused { if runtimeOptions.unpaused {
setPauseState(cfg, false) setPauseState(cfg, false)
} else if runtimeOptions.paused { } else if runtimeOptions.paused {
@ -645,10 +592,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts) app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
if shouldAutoUpgrade {
go autoUpgrade(cfg, app, evLogger)
}
setupSignalHandling(app) setupSignalHandling(app)
if len(os.Getenv("GOMAXPROCS")) == 0 { if len(os.Getenv("GOMAXPROCS")) == 0 {
@ -671,6 +614,31 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
go standbyMonitor(app) go standbyMonitor(app)
} }
// Candidate builds should auto upgrade. Make sure the option is set,
// unless we are in a build where it's disabled or the STNOUPGRADE
// environment variable is set.
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
opts.AutoUpgradeIntervalH = 12
// Set the option into the config as well, as the auto upgrade
// loop expects to read a valid interval from there.
cfg.SetOptions(opts)
cfg.Save()
}
// We don't tweak the user's choice of upgrading to pre-releases or
// not, as otherwise they cannot step off the candidate channel.
}
if opts := cfg.Options(); opts.AutoUpgradeIntervalH > 0 {
if runtimeOptions.NoUpgrade {
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
} else {
go autoUpgrade(cfg, app, evLogger)
}
}
if err := app.Start(); err != nil { if err := app.Start(); err != nil {
os.Exit(syncthing.ExitError.AsInt()) os.Exit(syncthing.ExitError.AsInt())
} }
@ -803,20 +771,6 @@ func standbyMonitor(app *syncthing.App) {
} }
} }
func shouldUpgrade(cfg config.Wrapper, runtimeOptions RuntimeOptions) bool {
if upgrade.DisabledByCompilation {
return false
}
if opts := cfg.Options(); opts.AutoUpgradeIntervalH < 0 {
return false
}
if runtimeOptions.NoUpgrade {
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
return false
}
return true
}
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) { func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
timer := time.NewTimer(0) timer := time.NewTimer(0)
sub := evLogger.Subscribe(events.DeviceConnected) sub := evLogger.Subscribe(events.DeviceConnected)
@ -939,10 +893,3 @@ func setPauseState(cfg config.Wrapper, paused bool) {
os.Exit(syncthing.ExitError.AsInt()) os.Exit(syncthing.ExitError.AsInt())
} }
} }
func exitCodeForUpgrade(err error) int {
if _, ok := err.(errNoUpgrade); ok {
return syncthing.ExitNoUpgradeAvailable.AsInt()
}
return syncthing.ExitError.AsInt()
}