Skip to content

Commit 04f1e1f

Browse files
committed
*: use archiveRecoverySetting also with standby cluster.
Rename cluster spec `StandbySettings` to `StandbyConfig`. `StandbyConfig` has two fields: `StandbySettings` and `ArchiveRecoverySettings`. In this way when defining a standby cluster user can also provide a recover command inside the StandybConfig.ArchiveRecoverySettings option. Resolves sorintlab#538
1 parent d95d53c commit 04f1e1f

File tree

8 files changed

+224
-72
lines changed

8 files changed

+224
-72
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
### v0.13.0
2+
3+
#### Upgrades notes.
4+
5+
* The clusterspec `standbySettings` option as been replaced by the `standbyConfig` option. Internally it can contain two fields `standbySettings` and `archiveRecoverySettings` (see the clusterspec doc with the descriptors of this new option). If you're updating a standby cluster, BEFORE starting it you should update, using `stolonctl`, the clusterspec with the new `standbyConfig` option.
6+
7+
18
### v0.12.0
29

310
#### New features

cmd/keeper/cmd/keeper.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,14 @@ func (p *PostgresKeeper) createPGParameters(db *cluster.DB) common.Parameters {
358358
return parameters
359359
}
360360

361-
func (p *PostgresKeeper) createRecoveryParameters(standbySettings *cluster.StandbySettings, archiveRecoverySettings *cluster.ArchiveRecoverySettings, recoveryTargetSettings *cluster.RecoveryTargetSettings) common.Parameters {
361+
func (p *PostgresKeeper) createRecoveryParameters(standbyMode bool, standbySettings *cluster.StandbySettings, archiveRecoverySettings *cluster.ArchiveRecoverySettings, recoveryTargetSettings *cluster.RecoveryTargetSettings) common.Parameters {
362362
parameters := common.Parameters{}
363363

364-
if standbySettings != nil {
364+
if standbyMode {
365365
parameters["standby_mode"] = "on"
366+
}
367+
368+
if standbySettings != nil {
366369
if standbySettings.PrimaryConninfo != "" {
367370
parameters["primary_conninfo"] = standbySettings.PrimaryConninfo
368371
}
@@ -812,7 +815,7 @@ func (p *PostgresKeeper) resync(db, followedDB *cluster.DB, tryPgrewind bool) er
812815
// log pg_rewind error and fallback to pg_basebackup
813816
log.Errorw("error syncing with pg_rewind", zap.Error(err))
814817
} else {
815-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
818+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
816819
return nil
817820
}
818821
}
@@ -841,7 +844,7 @@ func (p *PostgresKeeper) resync(db, followedDB *cluster.DB, tryPgrewind bool) er
841844
}
842845
log.Infow("sync succeeded")
843846

844-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
847+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
845848

846849
return nil
847850
}
@@ -1149,18 +1152,23 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
11491152
log.Errorw("failed to restore postgres database cluster", zap.Error(err))
11501153
return
11511154
}
1155+
1156+
standbyMode := false
11521157
var standbySettings *cluster.StandbySettings
11531158
if db.Spec.FollowConfig != nil && db.Spec.FollowConfig.Type == cluster.FollowTypeExternal {
1159+
standbyMode = true
11541160
standbySettings = db.Spec.FollowConfig.StandbySettings
11551161
}
1156-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, db.Spec.PITRConfig.ArchiveRecoverySettings, db.Spec.PITRConfig.RecoveryTargetSettings))
1162+
1163+
// if we are initializing a standby cluster then enable standby_mode to not stop recovery
1164+
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbyMode, standbySettings, db.Spec.PITRConfig.ArchiveRecoverySettings, db.Spec.PITRConfig.RecoveryTargetSettings))
11571165

11581166
if err = pgm.StartTmpMerged(); err != nil {
11591167
log.Errorw("failed to start instance", zap.Error(err))
11601168
return
11611169
}
11621170

1163-
if standbySettings == nil {
1171+
if !standbyMode {
11641172
// wait for the db having replyed all the wals
11651173
if err = pgm.WaitRecoveryDone(cd.Cluster.DefSpec().SyncTimeout.Duration); err != nil {
11661174
log.Errorw("recovery not finished", zap.Error(err))
@@ -1458,7 +1466,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14581466
return
14591467
}
14601468
if !started {
1461-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
1469+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
14621470
if err = pgm.Start(); err != nil {
14631471
log.Errorw("failed to start postgres", zap.Error(err))
14641472
return
@@ -1480,7 +1488,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14801488
standbySettings := &cluster.StandbySettings{PrimaryConninfo: newReplConnParams.ConnString(), PrimarySlotName: common.StolonName(db.UID)}
14811489

14821490
curRecoveryParameters := pgm.CurRecoveryParameters()
1483-
newRecoveryParameters := p.createRecoveryParameters(standbySettings, nil, nil)
1491+
newRecoveryParameters := p.createRecoveryParameters(true, standbySettings, nil, nil)
14841492

14851493
// Update recovery conf if parameters has changed
14861494
if !curRecoveryParameters.Equals(newRecoveryParameters) {
@@ -1499,7 +1507,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14991507

15001508
case cluster.FollowTypeExternal:
15011509
curRecoveryParameters := pgm.CurRecoveryParameters()
1502-
newRecoveryParameters := p.createRecoveryParameters(db.Spec.FollowConfig.StandbySettings, nil, nil)
1510+
newRecoveryParameters := p.createRecoveryParameters(true, db.Spec.FollowConfig.StandbySettings, db.Spec.FollowConfig.ArchiveRecoverySettings, nil)
15031511

15041512
// Update recovery conf if parameters has changed
15051513
if !curRecoveryParameters.Equals(newRecoveryParameters) {

cmd/sentinel/cmd/sentinel.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ func (s *Sentinel) setDBSpecFromClusterSpec(cd *cluster.ClusterData) {
388388
db.Spec.PGParameters = clusterSpec.PGParameters
389389
db.Spec.PGHBA = clusterSpec.PGHBA
390390
if db.Spec.FollowConfig != nil && db.Spec.FollowConfig.Type == cluster.FollowTypeExternal {
391-
db.Spec.FollowConfig.StandbySettings = clusterSpec.StandbySettings
391+
db.Spec.FollowConfig.StandbySettings = clusterSpec.StandbyConfig.StandbySettings
392+
db.Spec.FollowConfig.ArchiveRecoverySettings = clusterSpec.StandbyConfig.ArchiveRecoverySettings
392393
}
393394
db.Spec.AdditionalWalSenders = *clusterSpec.AdditionalWalSenders
394395
switch s.dbType(cd, db.UID) {
@@ -881,8 +882,9 @@ func (s *Sentinel) updateCluster(cd *cluster.ClusterData, pis cluster.ProxiesInf
881882
if *clusterSpec.Role == cluster.ClusterRoleStandby {
882883
role = common.RoleStandby
883884
followConfig = &cluster.FollowConfig{
884-
Type: cluster.FollowTypeExternal,
885-
StandbySettings: clusterSpec.StandbySettings,
885+
Type: cluster.FollowTypeExternal,
886+
StandbySettings: clusterSpec.StandbyConfig.StandbySettings,
887+
ArchiveRecoverySettings: clusterSpec.StandbyConfig.ArchiveRecoverySettings,
886888
}
887889
}
888890
db := &cluster.DB{
@@ -1033,8 +1035,9 @@ func (s *Sentinel) updateCluster(cd *cluster.ClusterData, pis cluster.ProxiesInf
10331035
if *clusterSpec.Role == cluster.ClusterRoleStandby {
10341036
masterDBRole = common.RoleStandby
10351037
followConfig = &cluster.FollowConfig{
1036-
Type: cluster.FollowTypeExternal,
1037-
StandbySettings: clusterSpec.StandbySettings,
1038+
Type: cluster.FollowTypeExternal,
1039+
StandbySettings: clusterSpec.StandbyConfig.StandbySettings,
1040+
ArchiveRecoverySettings: clusterSpec.StandbyConfig.ArchiveRecoverySettings,
10381041
}
10391042
}
10401043

doc/cluster_spec.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Some options in a running cluster specification can be changed to update the des
3434
| defaultSUReplAccessMode | mode for the default hba rules used for replication by standby keepers (the su and repl auth methods will be the one provided in the keeper command line options). Values can be *all* or *strict*. *all* allow access from all ips, *strict* restrict master access to standby servers ips. | no | string | all |
3535
| newConfig | configuration for initMode of type "new" | if initMode is "new" | NewConfig | |
3636
| pitrConfig | configuration for initMode of type "pitr" | if initMode is "pitr" | PITRConfig | |
37-
| standbySettings | standby settings when the cluster is a standby cluster | if role is "standby" | StandbySettings | |
37+
| standbyConfig | standby config when the cluster is a standby cluster | if role is "standby" | StandbyConfig | |
3838
| pgParameters | a map containing the postgres server parameters and their values. The parameters value don't have to be quoted and single quotes don't have to be doubled since this is already done by the keeper when writing the postgresql.conf file | no | map[string]string | |
3939
| pgHBA | a list containing additional pg_hba.conf entries. They will be added to the pg_hba.conf generated by stolon. **NOTE**: these lines aren't validated so if some of them are wrong postgres will refuse to start or, on reload, will log a warning and ignore the updated pg_hba.conf file | no | []string | null. Will use the default behiavior of accepting connections from all hosts for all dbs and users with md5 password authentication |
4040

@@ -62,6 +62,13 @@ Some options in a running cluster specification can be changed to update the des
6262
| archiveRecoverySettings | archive recovery configuration | yes | ArchiveRecoverySettings | |
6363
| recoveryTargetSettings | recovery target configuration | no | RecoveryTargetSettings | |
6464

65+
#### StandbyConfig
66+
67+
| Name | Description | Required | Type | Default |
68+
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-------------------------|---------|
69+
| standbySettings | standby configuration | no | StandbySettings | |
70+
| archiveRecoverySettings | archive recovery configuration | no | ArchiveRecoverySettings | |
71+
6572
#### ArchiveRecoverySettings
6673

6774
| Name | Description | Required | Type | Default |

internal/cluster/cluster.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ type FollowConfig struct {
9292
// Keeper ID to follow when Type is "internal"
9393
DBUID string `json:"dbuid,omitempty"`
9494
// Standby settings when Type is "external"
95-
StandbySettings *StandbySettings `json:"standbySettings,omitempty"`
95+
StandbySettings *StandbySettings `json:"standbySettings,omitempty"`
96+
ArchiveRecoverySettings *ArchiveRecoverySettings `json:"archiveRecoverySettings,omitempty"`
9697
}
9798

9899
type PostgresBinaryVersion struct {
@@ -166,6 +167,12 @@ type ExistingConfig struct {
166167
KeeperUID string `json:"keeperUID,omitempty"`
167168
}
168169

170+
// Standby config when role is standby
171+
type StandbyConfig struct {
172+
StandbySettings *StandbySettings `json:"standbySettings,omitempty"`
173+
ArchiveRecoverySettings *ArchiveRecoverySettings `json:"archiveRecoverySettings,omitempty"`
174+
}
175+
169176
// ArchiveRecoverySettings defines the archive recovery settings in the recovery.conf file (https://www.postgresql.org/docs/9.6/static/archive-recovery-settings.html )
170177
type ArchiveRecoverySettings struct {
171178
// value for restore_command
@@ -265,8 +272,8 @@ type ClusterSpec struct {
265272
PITRConfig *PITRConfig `json:"pitrConfig,omitempty"`
266273
// Existing init configuration used when InitMode is "existing"
267274
ExistingConfig *ExistingConfig `json:"existingConfig,omitempty"`
268-
// Standby setting when role is standby
269-
StandbySettings *StandbySettings `json:"standbySettings,omitempty"`
275+
// Standby config when role is standby
276+
StandbyConfig *StandbyConfig `json:"standbyConfig,omitempty"`
270277
// Define the mode of the default hba rules needed for replication by standby keepers (the su and repl auth methods will be the one provided in the keeper command line options)
271278
// Values can be "all" or "strict", "all" allow access from all ips, "strict" restrict master access to standby servers ips.
272279
// Default is "all"
@@ -479,11 +486,8 @@ func (os *ClusterSpec) Validate() error {
479486
switch *s.Role {
480487
case ClusterRoleMaster:
481488
case ClusterRoleStandby:
482-
if s.StandbySettings == nil {
483-
return fmt.Errorf("standbySettings undefined. Required when cluster role is \"standby\"")
484-
}
485-
if s.StandbySettings.PrimaryConninfo == "" {
486-
return fmt.Errorf("standbySettings primaryConnInfo undefined. Required when cluster role is \"standby\"")
489+
if s.StandbyConfig == nil {
490+
return fmt.Errorf("standbyConfig undefined. Required when cluster role is \"standby\"")
487491
}
488492
default:
489493
return fmt.Errorf("unknown role: %q", *s.InitMode)

internal/postgresql/postgresql.go

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"os"
2525
"os/exec"
2626
"path/filepath"
27-
"regexp"
2827
"sort"
2928
"strconv"
3029
"strings"
@@ -684,48 +683,6 @@ func (p *Manager) GetRole() (common.Role, error) {
684683
return common.RoleStandby, nil
685684
}
686685

687-
func (p *Manager) GetPrimaryConninfo() (ConnParams, error) {
688-
regex := regexp.MustCompile(`\s*primary_conninfo\s*=\s*'(.*)'$`)
689-
690-
fh, err := os.Open(filepath.Join(p.dataDir, postgresRecoveryConf))
691-
if os.IsNotExist(err) {
692-
return nil, nil
693-
}
694-
defer fh.Close()
695-
696-
scanner := bufio.NewScanner(fh)
697-
scanner.Split(bufio.ScanLines)
698-
699-
for scanner.Scan() {
700-
m := regex.FindStringSubmatch(scanner.Text())
701-
if len(m) == 2 {
702-
return ParseConnString(m[1])
703-
}
704-
}
705-
return nil, nil
706-
}
707-
708-
func (p *Manager) GetPrimarySlotName() (string, error) {
709-
regex := regexp.MustCompile(`\s*primary_slot_name\s*=\s*'(.*)'$`)
710-
711-
fh, err := os.Open(filepath.Join(p.dataDir, postgresRecoveryConf))
712-
if os.IsNotExist(err) {
713-
return "", nil
714-
}
715-
defer fh.Close()
716-
717-
scanner := bufio.NewScanner(fh)
718-
scanner.Split(bufio.ScanLines)
719-
720-
for scanner.Scan() {
721-
m := regex.FindStringSubmatch(scanner.Text())
722-
if len(m) == 2 {
723-
return m[1], nil
724-
}
725-
}
726-
return "", nil
727-
}
728-
729686
func (p *Manager) writeConfs() error {
730687
if err := p.writeConf(); err != nil {
731688
return fmt.Errorf("error writing %s file: %v", postgresConf, err)

tests/integration/ha_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ func setupServers(t *testing.T, clusterName, dir string, numKeepers, numSentinel
156156
PITRConfig: &cluster.PITRConfig{
157157
DataRestoreCommand: fmt.Sprintf("PGPASSFILE=%s pg_basebackup -D %%d -h %s -p %s -U %s", pgpass.Name(), primaryKeeper.pgListenAddress, primaryKeeper.pgPort, primaryKeeper.pgReplUsername),
158158
},
159-
StandbySettings: &cluster.StandbySettings{
160-
PrimaryConninfo: fmt.Sprintf("sslmode=disable host=%s port=%s user=%s password=%s", primaryKeeper.pgListenAddress, primaryKeeper.pgPort, primaryKeeper.pgReplUsername, primaryKeeper.pgReplPassword),
159+
StandbyConfig: &cluster.StandbyConfig{
160+
StandbySettings: &cluster.StandbySettings{
161+
PrimaryConninfo: fmt.Sprintf("sslmode=disable host=%s port=%s user=%s password=%s", primaryKeeper.pgListenAddress, primaryKeeper.pgPort, primaryKeeper.pgReplUsername, primaryKeeper.pgReplPassword),
162+
},
161163
},
162164
}
163165
}

0 commit comments

Comments
 (0)