Skip to content

Commit 70b65bd

Browse files
yktakaha4Copilotmeiji163
authored
Add postpone-cut-over-flag-file interactive command (#1561)
* Add postpone-cut-over-flag-file interactive command * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix import error --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: meiji163 <meiji163@github.com>
1 parent 7c3b9a1 commit 70b65bd

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

doc/interactive-commands.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Both interfaces may serve at the same time. Both respond to simple text command,
4141
- `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.
4242
- `throttle`: force migration suspend
4343
- `no-throttle`: cancel forced suspension (though other throttling reasons may still apply)
44+
- `postpone-cut-over-flag-file=<path>`: Postpone the [cut-over](cut-over.md) phase, writing a cut over flag file to the given path
4445
- `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.
4546
- `panic`: immediately panic and abort operation
4647

go/logic/server.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ func (this *Server) runCPUProfile(args string) (io.Reader, error) {
9999
return &buf, nil
100100
}
101101

102+
func (this *Server) createPostponeCutOverFlagFile(filePath string) (err error) {
103+
if !base.FileExists(filePath) {
104+
if err := base.TouchFile(filePath); err != nil {
105+
return fmt.Errorf("Failed to create postpone cut-over flag file %s: %w", filePath, err)
106+
}
107+
this.migrationContext.Log.Infof("Created postpone-cut-over-flag-file: %s", filePath)
108+
}
109+
return nil
110+
}
111+
102112
func (this *Server) BindSocketFile() (err error) {
103113
if this.migrationContext.ServeSocketFile == "" {
104114
return nil
@@ -222,6 +232,7 @@ throttle-http=<URL> # Set a new throttle URL
222232
throttle-control-replicas=<replicas> # Set a new comma delimited list of throttle control replicas
223233
throttle # Force throttling
224234
no-throttle # End forced throttling (other throttling may still apply)
235+
postpone-cut-over-flag-file=<path> # Postpone the cut-over phase, writing a cut over flag file to the given path
225236
unpostpone # Bail out a cut-over postpone; proceed to cut-over
226237
panic # panic and quit without cleanup
227238
help # This message
@@ -395,6 +406,19 @@ help # This message
395406
atomic.StoreInt64(&this.migrationContext.ThrottleCommandedByUser, 0)
396407
return ForcePrintStatusAndHintRule, nil
397408
}
409+
case "postpone-cut-over-flag-file":
410+
{
411+
if arg == "" {
412+
err := fmt.Errorf("User commanded 'postpone-cut-over-flag-file' without specifying file path")
413+
return NoPrintStatusRule, err
414+
}
415+
if err := this.createPostponeCutOverFlagFile(arg); err != nil {
416+
return NoPrintStatusRule, err
417+
}
418+
this.migrationContext.PostponeCutOverFlagFile = arg
419+
fmt.Fprintf(writer, "Postponed\n")
420+
return ForcePrintStatusAndHintRule, nil
421+
}
398422
case "unpostpone", "no-postpone", "cut-over":
399423
{
400424
if arg == "" && this.migrationContext.ForceNamedCutOverCommand {

go/logic/server_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package logic
22

33
import (
4+
"os"
5+
"path"
46
"testing"
57
"time"
68

@@ -66,3 +68,38 @@ func TestServerRunCPUProfile(t *testing.T) {
6668
require.Equal(t, int64(0), s.isCPUProfiling)
6769
})
6870
}
71+
72+
func TestServerCreatePostponeCutOverFlagFile(t *testing.T) {
73+
t.Parallel()
74+
75+
t.Run("success", func(t *testing.T) {
76+
s := &Server{
77+
migrationContext: base.NewMigrationContext(),
78+
}
79+
dir, err := os.MkdirTemp("", "gh-ost-test-")
80+
require.NoError(t, err)
81+
defer os.RemoveAll(dir)
82+
83+
filePath := path.Join(dir, "postpone-cut-over.flag")
84+
85+
err = s.createPostponeCutOverFlagFile(filePath)
86+
require.NoError(t, err)
87+
require.FileExists(t, filePath)
88+
})
89+
90+
t.Run("file already exists", func(t *testing.T) {
91+
s := &Server{
92+
migrationContext: base.NewMigrationContext(),
93+
}
94+
dir, err := os.MkdirTemp("", "gh-ost-test-")
95+
require.NoError(t, err)
96+
97+
filePath := path.Join(dir, "postpone-cut-over.flag")
98+
err = base.TouchFile(filePath)
99+
require.NoError(t, err)
100+
101+
err = s.createPostponeCutOverFlagFile(filePath)
102+
require.NoError(t, err)
103+
require.FileExists(t, filePath)
104+
})
105+
}

0 commit comments

Comments
 (0)