Skip to content

Commit 849e28b

Browse files
committed
Merge pull request sorintlab#543 from sgotti/standbysettings_recovery_command
*: use archiveRecoverySetting also with standby cluster.
2 parents cfa6f95 + 04f1e1f commit 849e28b

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
@@ -343,11 +343,14 @@ func (p *PostgresKeeper) createPGParameters(db *cluster.DB) common.Parameters {
343343
return parameters
344344
}
345345

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

349-
if standbySettings != nil {
349+
if standbyMode {
350350
parameters["standby_mode"] = "on"
351+
}
352+
353+
if standbySettings != nil {
351354
if standbySettings.PrimaryConninfo != "" {
352355
parameters["primary_conninfo"] = standbySettings.PrimaryConninfo
353356
}
@@ -797,7 +800,7 @@ func (p *PostgresKeeper) resync(db, followedDB *cluster.DB, tryPgrewind bool) er
797800
// log pg_rewind error and fallback to pg_basebackup
798801
log.Errorw("error syncing with pg_rewind", zap.Error(err))
799802
} else {
800-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
803+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
801804
return nil
802805
}
803806
}
@@ -826,7 +829,7 @@ func (p *PostgresKeeper) resync(db, followedDB *cluster.DB, tryPgrewind bool) er
826829
}
827830
log.Infow("sync succeeded")
828831

829-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
832+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
830833

831834
return nil
832835
}
@@ -1134,18 +1137,23 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
11341137
log.Errorw("failed to restore postgres database cluster", zap.Error(err))
11351138
return
11361139
}
1140+
1141+
standbyMode := false
11371142
var standbySettings *cluster.StandbySettings
11381143
if db.Spec.FollowConfig != nil && db.Spec.FollowConfig.Type == cluster.FollowTypeExternal {
1144+
standbyMode = true
11391145
standbySettings = db.Spec.FollowConfig.StandbySettings
11401146
}
1141-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, db.Spec.PITRConfig.ArchiveRecoverySettings, db.Spec.PITRConfig.RecoveryTargetSettings))
1147+
1148+
// if we are initializing a standby cluster then enable standby_mode to not stop recovery
1149+
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbyMode, standbySettings, db.Spec.PITRConfig.ArchiveRecoverySettings, db.Spec.PITRConfig.RecoveryTargetSettings))
11421150

11431151
if err = pgm.StartTmpMerged(); err != nil {
11441152
log.Errorw("failed to start instance", zap.Error(err))
11451153
return
11461154
}
11471155

1148-
if standbySettings == nil {
1156+
if !standbyMode {
11491157
// wait for the db having replyed all the wals
11501158
if err = pgm.WaitRecoveryDone(cd.Cluster.DefSpec().SyncTimeout.Duration); err != nil {
11511159
log.Errorw("recovery not finished", zap.Error(err))
@@ -1443,7 +1451,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14431451
return
14441452
}
14451453
if !started {
1446-
pgm.SetRecoveryParameters(p.createRecoveryParameters(standbySettings, nil, nil))
1454+
pgm.SetRecoveryParameters(p.createRecoveryParameters(true, standbySettings, nil, nil))
14471455
if err = pgm.Start(); err != nil {
14481456
log.Errorw("failed to start postgres", zap.Error(err))
14491457
return
@@ -1465,7 +1473,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14651473
standbySettings := &cluster.StandbySettings{PrimaryConninfo: newReplConnParams.ConnString(), PrimarySlotName: common.StolonName(db.UID)}
14661474

14671475
curRecoveryParameters := pgm.CurRecoveryParameters()
1468-
newRecoveryParameters := p.createRecoveryParameters(standbySettings, nil, nil)
1476+
newRecoveryParameters := p.createRecoveryParameters(true, standbySettings, nil, nil)
14691477

14701478
// Update recovery conf if parameters has changed
14711479
if !curRecoveryParameters.Equals(newRecoveryParameters) {
@@ -1484,7 +1492,7 @@ func (p *PostgresKeeper) postgresKeeperSM(pctx context.Context) {
14841492

14851493
case cluster.FollowTypeExternal:
14861494
curRecoveryParameters := pgm.CurRecoveryParameters()
1487-
newRecoveryParameters := p.createRecoveryParameters(db.Spec.FollowConfig.StandbySettings, nil, nil)
1495+
newRecoveryParameters := p.createRecoveryParameters(true, db.Spec.FollowConfig.StandbySettings, db.Spec.FollowConfig.ArchiveRecoverySettings, nil)
14881496

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

cmd/sentinel/cmd/sentinel.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,8 @@ func (s *Sentinel) setDBSpecFromClusterSpec(cd *cluster.ClusterData) {
372372
db.Spec.PGParameters = clusterSpec.PGParameters
373373
db.Spec.PGHBA = clusterSpec.PGHBA
374374
if db.Spec.FollowConfig != nil && db.Spec.FollowConfig.Type == cluster.FollowTypeExternal {
375-
db.Spec.FollowConfig.StandbySettings = clusterSpec.StandbySettings
375+
db.Spec.FollowConfig.StandbySettings = clusterSpec.StandbyConfig.StandbySettings
376+
db.Spec.FollowConfig.ArchiveRecoverySettings = clusterSpec.StandbyConfig.ArchiveRecoverySettings
376377
}
377378
db.Spec.AdditionalWalSenders = *clusterSpec.AdditionalWalSenders
378379
switch s.dbType(cd, db.UID) {
@@ -865,8 +866,9 @@ func (s *Sentinel) updateCluster(cd *cluster.ClusterData, pis cluster.ProxiesInf
865866
if *clusterSpec.Role == cluster.ClusterRoleStandby {
866867
role = common.RoleStandby
867868
followConfig = &cluster.FollowConfig{
868-
Type: cluster.FollowTypeExternal,
869-
StandbySettings: clusterSpec.StandbySettings,
869+
Type: cluster.FollowTypeExternal,
870+
StandbySettings: clusterSpec.StandbyConfig.StandbySettings,
871+
ArchiveRecoverySettings: clusterSpec.StandbyConfig.ArchiveRecoverySettings,
870872
}
871873
}
872874
db := &cluster.DB{
@@ -1017,8 +1019,9 @@ func (s *Sentinel) updateCluster(cd *cluster.ClusterData, pis cluster.ProxiesInf
10171019
if *clusterSpec.Role == cluster.ClusterRoleStandby {
10181020
masterDBRole = common.RoleStandby
10191021
followConfig = &cluster.FollowConfig{
1020-
Type: cluster.FollowTypeExternal,
1021-
StandbySettings: clusterSpec.StandbySettings,
1022+
Type: cluster.FollowTypeExternal,
1023+
StandbySettings: clusterSpec.StandbyConfig.StandbySettings,
1024+
ArchiveRecoverySettings: clusterSpec.StandbyConfig.ArchiveRecoverySettings,
10221025
}
10231026
}
10241027

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)