Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/interactive-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Both interfaces may serve at the same time. Both respond to simple text command,
- `throttle-control-replicas='replica1,replica2'`: change list of throttle-control replicas, these are replicas `gh-ost` will check. This takes a comma separated list of replica's to check and replaces the previous list.
- `throttle`: force migration suspend
- `no-throttle`: cancel forced suspension (though other throttling reasons may still apply)
- `postpone-cut-over-flag-file=<path>`: Postpone the [cut-over](cut-over.md) phase, writing a cut over flag file to the given path
- `unpostpone`: at a time where `gh-ost` is postponing the [cut-over](cut-over.md) phase, instruct `gh-ost` to stop postponing and proceed immediately to cut-over.
- `panic`: immediately panic and abort operation

Expand Down
24 changes: 24 additions & 0 deletions go/logic/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ func (this *Server) runCPUProfile(args string) (io.Reader, error) {
return &buf, nil
}

func (this *Server) createPostponeCutOverFlagFile(filePath string) (err error) {
if !base.FileExists(filePath) {
if err := base.TouchFile(filePath); err != nil {
return fmt.Errorf("Failed to create postpone cut-over flag file %s: %w", filePath, err)
}
this.migrationContext.Log.Infof("Created postpone-cut-over-flag-file: %s", filePath)
}
return nil
}

func (this *Server) BindSocketFile() (err error) {
if this.migrationContext.ServeSocketFile == "" {
return nil
Expand Down Expand Up @@ -222,6 +232,7 @@ throttle-http=<URL> # Set a new throttle URL
throttle-control-replicas=<replicas> # Set a new comma delimited list of throttle control replicas
throttle # Force throttling
no-throttle # End forced throttling (other throttling may still apply)
postpone-cut-over-flag-file=<path> # Postpone the cut-over phase, writing a cut over flag file to the given path
unpostpone # Bail out a cut-over postpone; proceed to cut-over
panic # panic and quit without cleanup
help # This message
Expand Down Expand Up @@ -395,6 +406,19 @@ help # This message
atomic.StoreInt64(&this.migrationContext.ThrottleCommandedByUser, 0)
return ForcePrintStatusAndHintRule, nil
}
case "postpone-cut-over-flag-file":
{
if arg == "" {
err := fmt.Errorf("User commanded 'postpone-cut-over-flag-file' without specifying file path")
return NoPrintStatusRule, err
}
if err := this.createPostponeCutOverFlagFile(arg); err != nil {
return NoPrintStatusRule, err
}
this.migrationContext.PostponeCutOverFlagFile = arg
fmt.Fprintf(writer, "Postponed\n")
return ForcePrintStatusAndHintRule, nil
}
case "unpostpone", "no-postpone", "cut-over":
{
if arg == "" && this.migrationContext.ForceNamedCutOverCommand {
Expand Down
36 changes: 36 additions & 0 deletions go/logic/server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package logic

import (
"os"
"path"
"testing"
"time"

Expand Down Expand Up @@ -66,3 +68,37 @@ func TestServerRunCPUProfile(t *testing.T) {
require.Equal(t, int64(0), s.isCPUProfiling)
})
}

func TestServerCreatePostponeCutOverFlagFile(t *testing.T) {
t.Parallel()

t.Run("success", func(t *testing.T) {
s := &Server{
migrationContext: base.NewMigrationContext(),
}
dir, err := os.MkdirTemp("", "gh-ost-test-")
require.NoError(t, err)

filePath := path.Join(dir, "postpone-cut-over.flag")

err = s.createPostponeCutOverFlagFile(filePath)
require.NoError(t, err)
require.FileExists(t, filePath)
})

t.Run("file already exists", func(t *testing.T) {
s := &Server{
migrationContext: base.NewMigrationContext(),
}
dir, err := os.MkdirTemp("", "gh-ost-test-")
require.NoError(t, err)

filePath := path.Join(dir, "postpone-cut-over.flag")
err = base.TouchFile(filePath)
require.NoError(t, err)

err = s.createPostponeCutOverFlagFile(filePath)
require.NoError(t, err)
require.FileExists(t, filePath)
})
}