~ubuntu-branches/debian/sid/resource-agents/sid

« back to all changes in this revision

Viewing changes to heartbeat/pgsql

  • Committer: Package Import Robot
  • Author(s): Martin Loschwitz
  • Date: 2012-10-09 11:16:59 UTC
  • mfrom: (3.1.1)
  • Revision ID: package-import@ubuntu.com-20121009111659-jrcwfqskcbh0iuio
Tags: 1:3.9.3+git20121009-1
* New upstream version
* debian/patches/01_docbook_patch.patch: Refactored for new release
* debian/patches/02_spelling_fixes.patch.new: Refatored for new release
* debian/control: Bumped Standards-Version to 3.9.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#
6
6
# Authors:      Serge Dubrouski (sergeyfd@gmail.com) -- original RA
7
7
#               Florian Haas (florian@linbit.com) -- makeover
 
8
#               Takatoshi MATSUO (matsuo.tak@gmail.com) -- support replication
8
9
#
9
 
# Copyright:    2006-2010 Serge Dubrouski <sergeyfd@gmail.com>
 
10
# Copyright:    2006-2012 Serge Dubrouski <sergeyfd@gmail.com>
10
11
#                         and other Linux-HA contributors
11
12
# License:      GNU General Public License (GPL)
12
13
#
20
21
# Get PostgreSQL Configuration parameter
21
22
#
22
23
get_pgsql_param() {
23
 
    local config_file
24
24
    local param_name
25
25
 
26
26
    param_name=$1
27
 
 
28
 
    #Check that config file exists 
29
 
    if [ -n "$OCF_RESKEY_config" ]; then
30
 
        config=$OCF_RESKEY_config
31
 
    else
32
 
        config=$OCF_RESKEY_pgdata/postgresql.conf
33
 
    fi
34
 
 
35
 
    check_config "$config"
36
 
    [ $? -eq 0 ] || return
37
 
 
38
27
    perl_code="if (/^\s*$param_name[\s=]+\s*(.*)$/) {
39
28
       \$dir=\$1;
40
29
       \$dir =~ s/\s*\#.*//;
41
30
       \$dir =~ s/^'(\S*)'/\$1/;
42
31
       print \$dir;}"
43
32
 
44
 
    perl -ne "$perl_code" < $config
 
33
    perl -ne "$perl_code" < $OCF_RESKEY_config
45
34
}
46
35
 
47
36
# Defaults
51
40
OCF_RESKEY_pgdba_default=postgres
52
41
OCF_RESKEY_pghost_default=""
53
42
OCF_RESKEY_pgport_default=5432
54
 
OCF_RESKEY_config_default=""
55
43
OCF_RESKEY_start_opt_default=""
56
44
OCF_RESKEY_pgdb_default=template1
57
45
OCF_RESKEY_logfile_default=/dev/null
59
47
OCF_RESKEY_monitor_user_default=""
60
48
OCF_RESKEY_monitor_password_default=""
61
49
OCF_RESKEY_monitor_sql_default="select now();"
 
50
# Defaults for replication
 
51
OCF_RESKEY_rep_mode_default=none
 
52
OCF_RESKEY_node_list_default=""
 
53
OCF_RESKEY_restore_command_default=""
 
54
OCF_RESKEY_archive_cleanup_command_default=""
 
55
OCF_RESKEY_recovery_end_command_default=""
 
56
OCF_RESKEY_master_ip_default=""
 
57
OCF_RESKEY_repuser_default="postgres"
 
58
OCF_RESKEY_primary_conninfo_opt_default=""
 
59
OCF_RESKEY_tmpdir_default="/var/lib/pgsql/tmp"
 
60
OCF_RESKEY_xlog_check_count_default="3"
 
61
OCF_RESKEY_crm_attr_timeout_default="5"
 
62
OCF_RESKEY_stop_escalate_in_slave_default=30
62
63
 
63
64
: ${OCF_RESKEY_pgctl=${OCF_RESKEY_pgctl_default}}
64
65
: ${OCF_RESKEY_psql=${OCF_RESKEY_psql_default}}
66
67
: ${OCF_RESKEY_pgdba=${OCF_RESKEY_pgdba_default}}
67
68
: ${OCF_RESKEY_pghost=${OCF_RESKEY_pghost_default}}
68
69
: ${OCF_RESKEY_pgport=${OCF_RESKEY_pgport_default}}
69
 
: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
 
70
: ${OCF_RESKEY_config=${OCF_RESKEY_pgdata}/postgresql.conf}
70
71
: ${OCF_RESKEY_start_opt=${OCF_RESKEY_start_opt_default}}
71
72
: ${OCF_RESKEY_pgdb=${OCF_RESKEY_pgdb_default}}
72
73
: ${OCF_RESKEY_logfile=${OCF_RESKEY_logfile_default}}
75
76
: ${OCF_RESKEY_monitor_password=${OCF_RESKEY_monitor_password_default}}
76
77
: ${OCF_RESKEY_monitor_sql=${OCF_RESKEY_monitor_sql_default}}
77
78
 
 
79
# for replication
 
80
: ${OCF_RESKEY_rep_mode=${OCF_RESKEY_rep_mode_default}}
 
81
: ${OCF_RESKEY_node_list=${OCF_RESKEY_node_list_default}}
 
82
: ${OCF_RESKEY_restore_command=${OCF_RESKEY_restore_command_default}}
 
83
: ${OCF_RESKEY_archive_cleanup_command=${OCF_RESKEY_archive_cleanup_command_default}}
 
84
: ${OCF_RESKEY_recovery_end_command=${OCF_RESKEY_recovery_end_command_default}}
 
85
: ${OCF_RESKEY_master_ip=${OCF_RESKEY_master_ip_default}}
 
86
: ${OCF_RESKEY_repuser=${OCF_RESKEY_repuser_default}}
 
87
: ${OCF_RESKEY_primary_conninfo_opt=${OCF_RESKEY_primary_conninfo_opt_default}}
 
88
: ${OCF_RESKEY_tmpdir=${OCF_RESKEY_tmpdir_default}}
 
89
: ${OCF_RESKEY_xlog_check_count=${OCF_RESKEY_xlog_check_count_default}}
 
90
: ${OCF_RESKEY_crm_attr_timeout=${OCF_RESKEY_crm_attr_timeout_default}}
 
91
: ${OCF_RESKEY_stop_escalate_in_slave=${OCF_RESKEY_stop_escalate_in_slave_default}}
 
92
 
78
93
usage() {
79
94
    cat <<EOF
80
 
        usage: $0 start|stop|status|monitor|meta-data|validate-all|methods
 
95
        usage: $0 start|stop|status|monitor|promote|demote|notify|meta-data|validate-all|methods
81
96
 
82
 
        $0 manages a PostgreSQL Server as an HA resource.
 
97
        $0 manages a PostgreSQL Server as an HA resource.
83
98
 
84
99
        The 'start' operation starts the PostgreSQL server.
85
100
        The 'stop' operation stops the PostgreSQL server.
86
101
        The 'status' operation reports whether the PostgreSQL is up.
87
102
        The 'monitor' operation reports whether the PostgreSQL is running.
 
103
        The 'promote' operation promotes the PostgreSQL server.
 
104
        The 'demote' operation demotes the PostgreSQL server.
88
105
        The 'validate-all' operation reports whether the parameters are valid.
89
106
        The 'methods' operation reports on the methods $0 supports.
90
107
EOF
92
109
}
93
110
 
94
111
meta_data() {
95
 
        cat <<EOF
 
112
    cat <<EOF
96
113
<?xml version="1.0"?>
97
114
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
98
115
<resource-agent name="pgsql">
193
210
<content type="string" default="${OCF_RESKEY_monitor_sql_default}" />
194
211
</parameter>
195
212
 
196
 
 
197
213
<parameter name="config" unique="0" required="0">
198
214
<longdesc lang="en">
199
 
Path to the PostgreSQL configuration file for the instance
 
215
Path to the PostgreSQL configuration file for the instance.
200
216
</longdesc>
201
217
<shortdesc lang="en">Configuration file</shortdesc>
202
 
<content type="integer" default="${OCF_RESKEY_config_default}" />
 
218
<content type="string" default="${OCF_RESKEY_pgdata}/postgresql.conf" />
203
219
</parameter>
204
220
 
205
221
<parameter name="pgdb" unique="0" required="0">
231
247
Number of shutdown retries (using -m fast) before resorting to -m immediate
232
248
</longdesc>
233
249
<shortdesc lang="en">stop escalation</shortdesc>
234
 
<content type="integer" default="${OCF_RESKEY_stop_escalation}" />
 
250
<content type="integer" default="${OCF_RESKEY_stop_escalate_default}" />
 
251
</parameter>
 
252
 
 
253
<parameter name="rep_mode" unique="0" required="0">
 
254
<longdesc lang="en">
 
255
Replication mode(none(default)/async/sync).
 
256
"async" and "sync" require PostgreSQL 9.1 or later.
 
257
If you use async or sync, it requires node_list, master_ip, restore_command
 
258
parameters, and needs setting postgresql.conf, pg_hba.conf up for
 
259
replication.
 
260
Please delete "include /../../rep_mode.conf" line in postgresql.conf
 
261
when you switch from sync to async.
 
262
</longdesc>
 
263
<shortdesc lang="en">rep_mode</shortdesc>
 
264
<content type="string" default="${OCF_RESKEY_rep_mode_default}" />
 
265
</parameter>
 
266
 
 
267
<parameter name="node_list" unique="0" required="0">
 
268
<longdesc lang="en">
 
269
All node names. Please separate each node name with a space.
 
270
This is required for replication.
 
271
</longdesc>
 
272
<shortdesc lang="en">node list</shortdesc>
 
273
<content type="string" default="${OCF_RESKEY_node_list_default}" />
 
274
</parameter>
 
275
 
 
276
<parameter name="restore_command" unique="0" required="0">
 
277
<longdesc lang="en">
 
278
restore_command for recovery.conf.
 
279
This is required for replication.
 
280
</longdesc>
 
281
<shortdesc lang="en">restore_command</shortdesc>
 
282
<content type="string" default="${OCF_RESKEY_restore_command_default}" />
 
283
</parameter>
 
284
 
 
285
<parameter name="archive_cleanup_command" unique="0" required="0">
 
286
<longdesc lang="en">
 
287
archive_cleanup_command for recovery.conf.
 
288
This is used for replication and is optional.
 
289
</longdesc>
 
290
<shortdesc lang="en">archive_cleanup_command</shortdesc>
 
291
<content type="string" default="${OCF_RESKEY_archive_cleanup_command_default}" />
 
292
</parameter>
 
293
 
 
294
<parameter name="recovery_end_command" unique="0" required="0">
 
295
<longdesc lang="en">
 
296
recovery_end_command for recovery.conf.
 
297
This is used for replication and is optional.
 
298
</longdesc>
 
299
<shortdesc lang="en">recovery_end_command</shortdesc>
 
300
<content type="string" default="${OCF_RESKEY_recovery_end_command_default}" />
 
301
</parameter>
 
302
 
 
303
<parameter name="master_ip" unique="0" required="0">
 
304
<longdesc lang="en">
 
305
Master's floating IP address to be connected from hot standby.
 
306
This parameter is used for "primary_conninfo" in recovery.conf.
 
307
This is required for replication.
 
308
</longdesc>
 
309
<shortdesc lang="en">master ip</shortdesc>
 
310
<content type="string" default="${OCF_RESKEY_master_ip_default}" />
 
311
</parameter>
 
312
 
 
313
<parameter name="repuser" unique="0" required="0">
 
314
<longdesc lang="en">
 
315
User used to connect to the master server.
 
316
This parameter is used for "primary_conninfo" in recovery.conf.
 
317
This is required for replication.
 
318
</longdesc>
 
319
<shortdesc lang="en">repuser</shortdesc>
 
320
<content type="string" default="${OCF_RESKEY_repuser_default}" />
 
321
</parameter>
 
322
 
 
323
<parameter name="primary_conninfo_opt" unique="0" required="0">
 
324
<longdesc lang="en">
 
325
primary_conninfo options of recovery.conf except host, port, user and application_name.
 
326
This is optional for replication.
 
327
</longdesc>
 
328
<shortdesc lang="en">primary_conninfo_opt</shortdesc>
 
329
<content type="string" default="${OCF_RESKEY_primary_conninfo_opt_default}" />
 
330
</parameter>
 
331
 
 
332
<parameter name="tmpdir" unique="0" required="0">
 
333
<longdesc lang="en">
 
334
Path to temporary directory.
 
335
This is optional for replication.
 
336
</longdesc>
 
337
<shortdesc lang="en">tmpdir</shortdesc>
 
338
<content type="string" default="${OCF_RESKEY_tmpdir_default}" />
 
339
</parameter>
 
340
 
 
341
<parameter name="xlog_check_count" unique="0" required="0">
 
342
<longdesc lang="en">
 
343
Number of checking xlog on monitor before promote.
 
344
This is optional for replication.
 
345
</longdesc>
 
346
<shortdesc lang="en">xlog check count</shortdesc>
 
347
<content type="integer" default="${OCF_RESKEY_check_count_default}" />
 
348
</parameter>
 
349
 
 
350
<parameter name="crm_attr_timeout" unique="0" required="0">
 
351
<longdesc lang="en">
 
352
The timeout of crm_attribute forever update command.
 
353
Default value is 5 seconds.
 
354
This is optional for replication.
 
355
</longdesc>
 
356
<shortdesc lang="en">The timeout of crm_attribute forever update command.</shortdesc>
 
357
<content type="integer" default="${OCF_RESKEY_crm_attr_timeout_default}" />
 
358
</parameter>
 
359
 
 
360
<parameter name="stop_escalate_in_slave" unique="0" required="0">
 
361
<longdesc lang="en">
 
362
Number of shutdown retries (using -m fast) before resorting to -m immediate
 
363
in Slave state.
 
364
This is optional for replication.
 
365
</longdesc>
 
366
<shortdesc lang="en">stop escalation_in_slave</shortdesc>
 
367
<content type="integer" default="${OCF_RESKEY_stop_escalate_in_slave_default}" />
235
368
</parameter>
236
369
</parameters>
237
370
 
240
373
<action name="stop" timeout="120" />
241
374
<action name="status" timeout="60" />
242
375
<action name="monitor" depth="0" timeout="30" interval="30"/>
 
376
<action name="monitor" depth="0" timeout="30" interval="29" role="Master" />
 
377
<action name="promote" timeout="120" />
 
378
<action name="demote" timeout="120" />
 
379
<action name="notify"   timeout="90" />
243
380
<action name="meta-data" timeout="5" />
244
381
<action name="validate-all" timeout="5" />
245
382
<action name="methods" timeout="5" />
250
387
 
251
388
 
252
389
#
253
 
#       Run the given command in the Resource owner environment...
 
390
#   Run the given command in the Resource owner environment...
254
391
#
255
392
runasowner() {
256
393
    local quietrun=""
287
424
#
288
425
 
289
426
pgsql_methods() {
290
 
  cat <<EOF
291
 
        start
292
 
        stop
293
 
        status
294
 
        monitor
295
 
        methods
296
 
        meta-data
297
 
        validate-all
 
427
    cat <<EOF
 
428
    start
 
429
    stop
 
430
    status
 
431
    monitor
 
432
    promote
 
433
    demote
 
434
    notify
 
435
    methods
 
436
    meta-data
 
437
    validate-all
298
438
EOF
299
439
}
300
440
 
301
441
 
302
 
#pgsql_start: Starts PostgreSQL
303
 
pgsql_start() {
 
442
#pgsql_real_start: Starts PostgreSQL
 
443
pgsql_real_start() {
304
444
    local pgctl_options
305
445
    local postgres_options
306
446
    local rc
307
447
 
308
448
    if pgsql_status; then
309
449
        ocf_log info "PostgreSQL is already running. PID=`cat $PIDFILE`"
310
 
        return $OCF_SUCCESS
 
450
        if is_replication; then
 
451
            return $OCF_ERR_GENERIC
 
452
        else
 
453
            return $OCF_SUCCESS
 
454
        fi
311
455
    fi
312
456
 
313
457
    # Remove postmaster.pid if it exists
314
458
    rm -f $PIDFILE
315
459
 
316
460
    # Remove backup_label if it exists
317
 
    if [ -f $BACKUPLABEL ]; then
318
 
        ocf_log info "Removing $BACKUPLABEL. The previous backup might have failed."
319
 
        rm -f $BACKUPLABEL
 
461
    if [ -f $BACKUPLABEL ] && ! is_replication; then
 
462
        ocf_log info "Removing $BACKUPLABEL. The previous backup might have failed."
 
463
        rm -f $BACKUPLABEL
320
464
    fi
321
465
 
322
466
    # Check if we need to create a log file
323
467
    if ! check_log_file $OCF_RESKEY_logfile
324
468
    then
325
469
        ocf_log err "PostgreSQL can't write to the log file: $OCF_RESKEY_logfile"
326
 
        return $OCF_ERR_PERM
 
470
        return $OCF_ERR_PERM
327
471
    fi
328
472
 
329
473
    # Check socket directory
336
480
    pgctl_options="$OCF_RESKEY_ctl_opt -D $OCF_RESKEY_pgdata -l $OCF_RESKEY_logfile"
337
481
 
338
482
    # Set options passed to the PostgreSQL server process
339
 
    postgres_options=""
340
 
    if [ -n "$OCF_RESKEY_config" ]; then
341
 
        postgres_options="$postgres_options -c config_file=${OCF_RESKEY_config}"
342
 
    fi
 
483
    postgres_options="-c config_file=${OCF_RESKEY_config}"
 
484
 
343
485
    if [ -n "$OCF_RESKEY_pghost" ]; then
344
 
        postgres_options="$postgres_options -h $OCF_RESKEY_pghost"
 
486
        postgres_options="$postgres_options -h $OCF_RESKEY_pghost"
345
487
    fi
346
488
    if [ -n "$OCF_RESKEY_start_opt" ]; then
347
 
        postgres_options="$postgres_options $OCF_RESKEY_start_opt"
 
489
        postgres_options="$postgres_options $OCF_RESKEY_start_opt"
348
490
    fi
349
491
 
350
492
    # Tack pass-through options onto pg_ctl options
351
 
    if [ -n "$postgres_options" ]; then
352
 
        pgctl_options="$pgctl_options -o '$postgres_options'"
353
 
    fi
 
493
    pgctl_options="$pgctl_options -o '$postgres_options'"
354
494
 
355
495
    # Invoke pg_ctl
356
 
    runasowner "$OCF_RESKEY_pgctl $pgctl_options start"
 
496
    runasowner "unset PGUSER; unset PGPASSWORD; $OCF_RESKEY_pgctl $pgctl_options start"
357
497
 
358
498
    if [ $? -eq 0 ]; then
359
 
        # Probably started.....
 
499
        # Probably started.....
360
500
        ocf_log info "PostgreSQL start command sent."
361
501
    else
362
 
        ocf_log err "Can't start PostgreSQL."
 
502
        ocf_log err "Can't start PostgreSQL."
363
503
        return $OCF_ERR_GENERIC
364
504
    fi
365
505
 
366
506
    while :
367
507
    do
368
 
        pgsql_monitor warn
 
508
        pgsql_real_monitor warn
369
509
        rc=$?
370
 
        if [ $rc -eq 0 ]; then
 
510
        if [ $rc -eq $OCF_SUCCESS -o $rc -eq $OCF_RUNNING_MASTER ]; then
371
511
            break;
372
512
        fi
373
513
        sleep 1
374
 
        ocf_log debug "PostgreSQL still hasn't started yet. Waiting..."
 
514
        ocf_log debug "PostgreSQL still hasn't started yet. Waiting..."
375
515
    done
 
516
 
376
517
    ocf_log info "PostgreSQL is started."
377
 
 
378
 
    return $OCF_SUCCESS
379
 
}
380
 
 
381
 
#pgsql_stop: Stop PostgreSQL
382
 
pgsql_stop() {
383
 
    local rc
 
518
    return $rc
 
519
}
 
520
 
 
521
pgsql_replication_start() {
 
522
    local rc
 
523
 
 
524
    # initializing for replication
 
525
    change_pgsql_status "$NODENAME" "STOP"
 
526
    delete_master_baseline
 
527
    $CRM_MASTER -v $CAN_NOT_PROMOTE
 
528
    rm -f ${XLOG_NOTE_FILE}.* $REP_MODE_CONF $RECOVERY_CONF
 
529
    if ! make_recovery_conf || ! delete_xlog_location || ! set_async_mode_all; then
 
530
        return $OCF_ERR_GENERIC
 
531
    fi
 
532
 
 
533
    if [ -f $PGSQL_LOCK ]; then
 
534
        ocf_log err "My data may be inconsistent. You have to remove $PGSQL_LOCK file to force start."
 
535
        return $OCF_ERR_GENERIC
 
536
    fi
 
537
 
 
538
    # start
 
539
    pgsql_real_start
 
540
    if [ $? -ne $OCF_SUCCESS ]; then
 
541
        return $OCF_ERR_GENERIC
 
542
    fi
 
543
    change_pgsql_status "$NODENAME" "HS:alone"
 
544
    return $OCF_SUCCESS
 
545
}
 
546
 
 
547
#pgsql_start: pgsql_real_start() wrapper for replication
 
548
pgsql_start() {
 
549
    if ! is_replication; then
 
550
        pgsql_real_start
 
551
        return $?
 
552
    else
 
553
        pgsql_replication_start
 
554
        return $?
 
555
    fi
 
556
}
 
557
 
 
558
#pgsql_promote: Promote PostgreSQL
 
559
pgsql_promote() {
 
560
    local target
 
561
    local rc
 
562
 
 
563
    if ! is_replication; then
 
564
        ocf_log err "Not in a replication mode."
 
565
        return $OCF_ERR_CONFIGURED
 
566
    fi
 
567
    rm -f ${XLOG_NOTE_FILE}.*
 
568
 
 
569
    for target in $NODE_LIST; do
 
570
        [ "$target" = "$NODENAME" ] && continue
 
571
        change_data_status "$target" "DISCONNECT"
 
572
        change_master_score "$target" "$CAN_NOT_PROMOTE"
 
573
    done
 
574
 
 
575
    ocf_log info "Creating $PGSQL_LOCK."
 
576
    touch $PGSQL_LOCK
 
577
    show_master_baseline
 
578
 
 
579
    runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata promote"
 
580
    if [ $? -eq 0 ]; then
 
581
        ocf_log info "PostgreSQL promote command sent."
 
582
    else
 
583
        ocf_log err "Can't promote PostgreSQL."
 
584
        return $OCF_ERR_GENERIC
 
585
    fi
 
586
 
 
587
    while :
 
588
    do
 
589
        pgsql_real_monitor warn
 
590
        rc=$?
 
591
        if [ $rc -eq $OCF_RUNNING_MASTER ]; then
 
592
            break;
 
593
        elif [ $rc -eq $OCF_ERR_GENERIC ]; then
 
594
            ocf_log err "Can't promote PostgreSQL."
 
595
            return $rc
 
596
        fi
 
597
        sleep 1
 
598
        ocf_log debug "PostgreSQL still hasn't promoted yet. Waiting..."
 
599
    done
 
600
    ocf_log info "PostgreSQL is promoted."
 
601
 
 
602
    change_data_status "$NODENAME" "LATEST"
 
603
    $CRM_MASTER -v $PROMOTE_ME
 
604
    change_pgsql_status "$NODENAME" "PRI"
 
605
    return $OCF_SUCCESS
 
606
}
 
607
 
 
608
#pgsql_demote: Demote PostgreSQL
 
609
pgsql_demote() {
 
610
    local rc
 
611
 
 
612
    if ! is_replication; then
 
613
        ocf_log err "Not in a replication mode."
 
614
        return $OCF_ERR_CONFIGURED
 
615
    fi
 
616
 
 
617
    $CRM_MASTER -v $CAN_NOT_PROMOTE
 
618
    delete_master_baseline
 
619
 
 
620
    if ! pgsql_status; then
 
621
        ocf_log info "PostgreSQL is already stopped on demote."
 
622
    else
 
623
        ocf_log info "Stopping PostgreSQL on demote."
 
624
        pgsql_real_stop master
 
625
        rc=$?
 
626
        if [ "$rc" -ne "$OCF_SUCCESS" ]; then
 
627
            change_pgsql_status "$NODENAME" "UNKNOWN"
 
628
            return $rc
 
629
        fi
 
630
    fi
 
631
    change_pgsql_status "$NODENAME" "STOP"
 
632
    return $OCF_SUCCESS
 
633
}
 
634
 
 
635
#pgsql_real_stop: Stop PostgreSQL
 
636
pgsql_real_stop() {
 
637
    local rc
 
638
    local count
 
639
    local stop_escalate
384
640
 
385
641
    if ! pgsql_status
386
642
    then
388
644
        return $OCF_SUCCESS
389
645
    fi
390
646
 
 
647
    stop_escalate=$OCF_RESKEY_stop_escalate
 
648
    if [ "$1" = "slave" ]; then
 
649
        stop_escalate="$OCF_RESKEY_stop_escalate_in_slave"
 
650
    fi
 
651
 
391
652
    # Stop PostgreSQL, do not wait for clients to disconnect
392
 
    runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m fast"
 
653
    if [ $stop_escalate -gt 0 ]; then
 
654
            runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m fast"
 
655
    fi
393
656
 
394
657
    # stop waiting
395
658
    count=0
396
 
    while [ $count -lt $OCF_RESKEY_stop_escalate ]
 
659
    while [ $count -lt $stop_escalate ]
397
660
    do
398
661
        if ! pgsql_status
399
662
        then
406
669
 
407
670
    if pgsql_status
408
671
    then
409
 
       #PostgreSQL is still up. Use another shutdown mode.
410
 
       ocf_log info "PostgreSQL failed to stop after ${OCF_RESKEY_stop_escalate}s using -m fast. Trying -m immediate..."
411
 
       runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m immediate"
 
672
        #PostgreSQL is still up. Use another shutdown mode.
 
673
        ocf_log info "PostgreSQL failed to stop after ${OCF_RESKEY_stop_escalate}s using -m fast. Trying -m immediate..."
 
674
        runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m immediate"
412
675
    fi
413
676
 
414
677
    while :
415
678
    do
416
 
        pgsql_monitor
 
679
        pgsql_real_monitor
417
680
        rc=$?
418
681
        if [ $rc -eq $OCF_NOT_RUNNING ]; then
419
682
            # An unnecessary debug log is prevented.
420
683
            break;
421
684
        fi
422
 
        sleep 1
423
 
        ocf_log debug "PostgreSQL still hasn't stopped yet. Waiting..."
 
685
        sleep 1
 
686
        ocf_log debug "PostgreSQL still hasn't stopped yet. Waiting..."
424
687
    done
425
688
 
426
689
    # Remove postmaster.pid if it exists
427
690
    rm -f $PIDFILE
428
691
 
429
 
    return $OCF_SUCCESS
 
692
    if  [ "$1" = "master" -a "$OCF_RESKEY_CRM_meta_notify_slave_uname" = " " ]; then
 
693
        ocf_log info "Removing $PGSQL_LOCK."
 
694
        rm -f $PGSQL_LOCK
 
695
    fi
 
696
    return $OCF_SUCCESS
 
697
}
 
698
 
 
699
pgsql_replication_stop() {
 
700
    local rc
 
701
 
 
702
    $CRM_MASTER -v $CAN_NOT_PROMOTE
 
703
    delete_xlog_location
 
704
 
 
705
    if ! pgsql_status
 
706
    then
 
707
        ocf_log info "PostgreSQL is already stopped."
 
708
        change_pgsql_status "$NODENAME" "STOP"
 
709
        return $OCF_SUCCESS
 
710
    fi
 
711
 
 
712
    pgsql_real_stop slave
 
713
    rc=$?
 
714
    if [ $rc -ne $OCF_SUCCESS ]; then
 
715
        change_pgsql_status "$NODENAME" "UNKNOWN"
 
716
        return $rc
 
717
    fi
 
718
 
 
719
    change_pgsql_status "$NODENAME" "STOP"
 
720
    set_async_mode_all
 
721
    delete_master_baseline
 
722
    return $OCF_SUCCESS
 
723
}
 
724
 
 
725
#pgsql_stop: pgsql_real_stop() wrapper for replication
 
726
pgsql_stop() {
 
727
    if ! is_replication; then
 
728
        pgsql_real_stop
 
729
        return $?
 
730
    else
 
731
        pgsql_replication_stop
 
732
        return $?
 
733
    fi
430
734
}
431
735
 
432
736
#
446
750
}
447
751
 
448
752
#
449
 
# pgsql_monitor
 
753
# pgsql_real_monitor
450
754
#
451
755
 
452
 
pgsql_monitor() {
 
756
pgsql_real_monitor() {
453
757
    local loglevel
454
 
    local psql_options
455
758
    local rc
 
759
    local output
456
760
 
457
761
    # Set the log level of the error message
458
762
    loglevel=${1:-err}
459
763
 
460
764
    if ! pgsql_status
461
765
    then
462
 
        ocf_log info "PostgreSQL is down"
463
 
        return $OCF_NOT_RUNNING
464
 
    fi
465
 
 
466
 
    if [ -n "$OCF_RESKEY_monitor_user" ]; then
467
 
        PGUSER=$OCF_RESKEY_monitor_user; export PGUSER
468
 
        PGPASSWORD=$OCF_RESKEY_monitor_password; export PGPASSWORD
469
 
        psql_options="-p $OCF_RESKEY_pgport $OCF_RESKEY_pgdb"
470
 
    else
471
 
        psql_options="-p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb"
472
 
    fi
473
 
 
474
 
    if [ -n "$OCF_RESKEY_pghost" ]; then
475
 
        psql_options="$psql_options -h $OCF_RESKEY_pghost"
476
 
    else
477
 
       if [ -n "$OCF_RESKEY_socketdir" ]; then
478
 
           psql_options="$psql_options -h $OCF_RESKEY_socketdir"
479
 
       fi
 
766
        ocf_log info "PostgreSQL is down"
 
767
        return $OCF_NOT_RUNNING
 
768
    fi
 
769
 
 
770
    if is_replication; then
 
771
        #Check replication state
 
772
        output=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
 
773
                $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
 
774
                -Atc \"${CHECK_MS_SQL}\""`
 
775
        rc=$?
 
776
        if [ $rc -ne  0 ]; then
 
777
            report_psql_error $rc $loglevel
 
778
            return $OCF_ERR_GENERIC
 
779
        fi
 
780
 
 
781
        case "$output" in
 
782
            f)  ocf_log debug "PostgreSQL is running as a primary."
 
783
                if [ "$OCF_RESKEY_monitor_sql" = "$OCF_RESKEY_monitor_sql_default" ]; then
 
784
                    return $OCF_RUNNING_MASTER
 
785
                fi
 
786
                ;;
 
787
 
 
788
            t)  ocf_log debug "PostgreSQL is running as a hot standby."
 
789
                return $OCF_SUCCESS;;
 
790
 
 
791
            *)  ocf_log err "$CHECK_MS_SQL output is $output"
 
792
                return $OCF_ERR_GENERIC;;
 
793
        esac
480
794
    fi
481
795
 
482
796
    OCF_RESKEY_monitor_sql=`escape_string "$OCF_RESKEY_monitor_sql"`
483
 
    runasowner -q $loglevel "$OCF_RESKEY_psql $psql_options -c '$OCF_RESKEY_monitor_sql'"
484
 
 
 
797
    runasowner -q $loglevel "$OCF_RESKEY_psql $psql_options \
 
798
                  -c '$OCF_RESKEY_monitor_sql'"
485
799
    rc=$?
486
800
    if [ $rc -ne  0 ]; then
487
 
        ocf_log $loglevel "PostgreSQL $OCF_RESKEY_pgdb isn't running"
488
 
        if [ $rc -eq 1 ]; then
489
 
            ocf_log err "Fatal error (out of memory, file not found, etc.) occurred while executing the psql command."
490
 
        elif [ $rc -eq 2 ]; then
491
 
            ocf_log $loglevel "Connection error (connection to the server went bad and the session was not interactive) occurred while executing the psql command."
492
 
        elif [ $rc -eq 3 ]; then
493
 
            ocf_log err "Script error (the variable ON_ERROR_STOP was set) occurred while executing the psql command."
494
 
        fi
495
 
        return $OCF_ERR_GENERIC
496
 
    fi
497
 
 
498
 
    return $OCF_SUCCESS
 
801
        report_psql_error $rc $loglevel
 
802
        return $OCF_ERR_GENERIC
 
803
    fi
 
804
 
 
805
    if is_replication; then
 
806
        return $OCF_RUNNING_MASTER
 
807
    fi
 
808
    return $OCF_SUCCESS
 
809
}
 
810
 
 
811
pgsql_replication_monitor() {
 
812
    local rc
 
813
 
 
814
    rc=$1
 
815
    if [ $rc -ne $OCF_SUCCESS -a $rc -ne "$OCF_RUNNING_MASTER" ]; then
 
816
        return $rc
 
817
    fi
 
818
    # If I am Master
 
819
    if [ $rc -eq $OCF_RUNNING_MASTER ]; then
 
820
        change_data_status "$NODENAME" "LATEST"
 
821
        change_pgsql_status "$NODENAME" "PRI"
 
822
        control_slave_status || return $OCF_ERR_GENERIC
 
823
        return $rc
 
824
    fi
 
825
 
 
826
    # I can't get master node name from $OCF_RESKEY_CRM_meta_notify_master_uname on monitor,
 
827
    # so I will get master node name using crm_mon -n
 
828
    crm_mon -n1 | tr -d "\t" | grep -q "^${RESOURCE_NAME}:.* Master"
 
829
    if [ $? -ne 0 ] ; then
 
830
        # If I am Slave and Master is not exist
 
831
        ocf_log info "Master does not exist."
 
832
        change_pgsql_status "$NODENAME" "HS:alone"
 
833
        have_master_right
 
834
        if [ $? -eq 0 ]; then
 
835
            rm -f ${XLOG_NOTE_FILE}.*
 
836
        fi
 
837
    else
 
838
        output=`$CRM_ATTR_FOREVER -N "$NODENAME" \
 
839
                -n "$PGSQL_DATA_STATUS_ATTR" -G -q`
 
840
        if [ "$output" = "DISCONNECT" ]; then
 
841
            change_pgsql_status "$NODENAME" "HS:alone"
 
842
        fi
 
843
    fi
 
844
    return $rc
 
845
}
 
846
 
 
847
#pgsql_monitor: pgsql_real_monitor() wrapper for replication
 
848
pgsql_monitor() {
 
849
    local rc
 
850
 
 
851
    pgsql_real_monitor
 
852
    rc=$?
 
853
    if ! is_replication; then
 
854
        return $rc
 
855
    else
 
856
        pgsql_replication_monitor $rc
 
857
        return $?
 
858
    fi
 
859
}
 
860
 
 
861
# pgsql_post_demote
 
862
pgsql_post_demote() {
 
863
    DEMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_demote_uname | sed "s/ /\n/g" | head -1`
 
864
    ocf_log debug "post-demote called. Demote uname is $DEMOTE_NODE"
 
865
    if [ "$DEMOTE_NODE" != "$NODENAME" ]; then
 
866
        if ! echo $OCF_RESKEY_CRM_meta_notify_master_uname | grep $NODENAME; then
 
867
            show_master_baseline
 
868
            change_pgsql_status "$NODENAME" "HS:alone"
 
869
        fi
 
870
    fi
 
871
    return $OCF_SUCCESS
 
872
}
 
873
 
 
874
pgsql_pre_promote() {
 
875
    local master_baseline
 
876
    local my_master_baseline
 
877
    local cmp_location
 
878
    local number_of_nodes
 
879
 
 
880
    # If my data is newer than new master's one, I fail my resource.
 
881
    PROMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_promote_uname | \
 
882
                  sed "s/ /\n/g" | head -1`
 
883
    number_of_nodes=`echo $NODE_LIST | wc -w`
 
884
    if [ $number_of_nodes -ge 3 -a \
 
885
         "$OCF_RESKEY_rep_mode" = "sync" -a \
 
886
         "$PROMOTE_NODE" != "$NODENAME" ]; then
 
887
        master_baseline=`$CRM_ATTR_REBOOT -N "$PROMOTE_NODE" -n \
 
888
                         "$PGSQL_MASTER_BASELINE" -G -q 2>/dev/null`
 
889
        if [ $? -eq 0 ]; then
 
890
            my_master_baseline=`$CRM_ATTR_REBOOT -N "$NODENAME" -n \
 
891
                                "$PGSQL_MASTER_BASELINE" -G -q 2>/dev/null`
 
892
            # get older location
 
893
            cmp_location=`printf "$master_baseline\n$my_master_baseline\n" |\
 
894
                          sort | head -1`
 
895
            if [ "$cmp_location" != "$my_master_baseline" ]; then
 
896
                ocf_log err "My data is newer than new master's one. New master's location : $master_baseline"
 
897
                $CRM_FAILCOUNT -r $OCF_RESOURCE_INSTANCE -U $NODENAME -v INFINITY
 
898
                return $OCF_ERR_GENERIC
 
899
            fi
 
900
        fi
 
901
    fi
 
902
    return $OCF_SUCCESS
 
903
}
 
904
 
 
905
pgsql_notify() {
 
906
    local type="${OCF_RESKEY_CRM_meta_notify_type}"
 
907
    local op="${OCF_RESKEY_CRM_meta_notify_operation}"
 
908
    local rc
 
909
 
 
910
    if ! is_replication; then
 
911
        return $OCF_SUCCESS
 
912
    fi
 
913
 
 
914
    ocf_log debug "notify: ${type} for ${op}"
 
915
    case $type in
 
916
        pre)
 
917
            case $op in
 
918
                promote)
 
919
                    pgsql_pre_promote
 
920
                    return $?
 
921
                    ;;
 
922
            esac
 
923
            ;;
 
924
        post)
 
925
            case $op in
 
926
                promote)
 
927
                    delete_xlog_location
 
928
                    PROMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_promote_uname | \
 
929
                                  sed "s/ /\n/g" | head -1`
 
930
                    if [ "$PROMOTE_NODE" != "$NODENAME" ]; then
 
931
                        delete_master_baseline
 
932
                    fi
 
933
                    return $OCF_SUCCESS
 
934
                    ;;
 
935
                demote)
 
936
                    pgsql_post_demote
 
937
                    return $?
 
938
                    ;;
 
939
                start|stop)
 
940
                    if [ "$NODENAME " = "$OCF_RESKEY_CRM_meta_notify_master_uname" ]; then
 
941
                        control_slave_status
 
942
                    fi
 
943
                    return $OCF_SUCCESS
 
944
                    ;;
 
945
            esac
 
946
            ;;
 
947
    esac
 
948
    return $OCF_SUCCESS
 
949
}
 
950
 
 
951
control_slave_status() {
 
952
    local rc
 
953
    local data_status
 
954
    local target
 
955
    local all_data_status
 
956
    local tmp_data_status
 
957
    local node_name
 
958
    local number_of_nodes
 
959
 
 
960
    all_data_status=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
 
961
                     $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
 
962
                     -Atc \"${CHECK_REPLICATION_STATE_SQL}\""`
 
963
    rc=$?
 
964
    if [ $rc -eq 0 ]; then
 
965
        if [ -n "$all_data_status" ]; then
 
966
            all_data_status=`echo $all_data_status | sed "s/\n/ /g"`
 
967
        fi
 
968
    else
 
969
        report_psql_error $rc warn
 
970
        return 1
 
971
    fi
 
972
 
 
973
    number_of_nodes=`echo $NODE_LIST | wc -w`
 
974
    for target in $NODE_LIST; do
 
975
        if [ "$target" = "$NODENAME" ]; then
 
976
            continue
 
977
        fi
 
978
 
 
979
        data_status="DISCONNECT"
 
980
        if [ -n "$all_data_status" ]; then
 
981
            for tmp_data_status in $all_data_status; do
 
982
                node_name=`echo $tmp_data_status | cut -d "|" -f 1`
 
983
                state=`echo $tmp_data_status | cut -d "|" -f 2`
 
984
                sync_state=`echo $tmp_data_status | cut -d "|" -f 3`
 
985
                ocf_log debug "node=$node_name, state=$state, sync_state=$sync_state"
 
986
                if [ "$node_name" = "$target" ];then
 
987
                    data_status="$state|$sync_state"
 
988
                    break
 
989
                fi
 
990
            done
 
991
        fi
 
992
 
 
993
        case "$data_status" in
 
994
            "STREAMING|SYNC")
 
995
                change_data_status "$target" "$data_status"
 
996
                change_master_score "$target" "$CAN_PROMOTE"
 
997
                change_pgsql_status "$target" "HS:sync"
 
998
                ;;
 
999
            "STREAMING|ASYNC")
 
1000
                change_data_status "$target" "$data_status"
 
1001
                if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
 
1002
                    change_master_score "$target" "$CAN_NOT_PROMOTE"
 
1003
                    if ! is_sync_mode "$target"; then
 
1004
                        set_sync_mode "$target"
 
1005
                    fi
 
1006
                else
 
1007
                    if [ $number_of_nodes -le 2 ]; then
 
1008
                        change_master_score "$target" "$CAN_PROMOTE"
 
1009
                    else
 
1010
                        # I can't determine which slave's data is newest in async mode.
 
1011
                        change_master_score "$target" "$CAN_NOT_PROMOTE"
 
1012
                    fi
 
1013
                fi
 
1014
                change_pgsql_status "$target" "HS:async"
 
1015
                ;;
 
1016
            "STREAMING|POTENTIAL")
 
1017
                change_data_status "$target" "$data_status"
 
1018
                change_master_score "$target" "$CAN_NOT_PROMOTE"
 
1019
                change_pgsql_status "$target" "HS:potential"
 
1020
                ;;
 
1021
            "DISCONNECT")
 
1022
                change_data_status "$target" "$data_status"
 
1023
                change_master_score "$target" "$CAN_NOT_PROMOTE"
 
1024
                if [ "$OCF_RESKEY_rep_mode" = "sync" ] && \
 
1025
                   is_sync_mode "$target"; then
 
1026
                    set_async_mode "$target"
 
1027
                fi
 
1028
                ;;
 
1029
            *)
 
1030
                change_data_status "$target" "$data_status"
 
1031
                change_master_score "$target" "$CAN_NOT_PROMOTE"
 
1032
                if [ "$OCF_RESKEY_rep_mode" = "sync" ] && \
 
1033
                    is_sync_mode "$target"; then
 
1034
                    set_async_mode "$target"
 
1035
                fi
 
1036
                change_pgsql_status "$target" "HS:connected"
 
1037
                ;;
 
1038
        esac
 
1039
    done
 
1040
    return 0
 
1041
}
 
1042
 
 
1043
have_master_right() {
 
1044
    local old
 
1045
    local new
 
1046
    local output
 
1047
    local data_status
 
1048
    local node
 
1049
    local mylocation
 
1050
    local count
 
1051
    local newestXlog
 
1052
    local oldfile
 
1053
    local newfile
 
1054
 
 
1055
    ocf_log debug "Checking if I have a master right."
 
1056
 
 
1057
    data_status=`$CRM_ATTR_FOREVER -N "$NODENAME" -n \
 
1058
                 "$PGSQL_DATA_STATUS_ATTR" -G -q`
 
1059
    if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
 
1060
        if [ -n "$data_status" -a "$data_status" != "STREAMING|SYNC" -a \
 
1061
             "$data_status" != "LATEST" ]; then
 
1062
            ocf_log warn "My data is out-of-date. status=$data_status"
 
1063
            return 1
 
1064
        fi
 
1065
    else
 
1066
        if [ -n "$data_status" -a "$data_status" != "STREAMING|SYNC" -a \
 
1067
             "$data_status" != "STREAMING|ASYNC" -a \
 
1068
             "$data_status" != "LATEST" ]; then
 
1069
            ocf_log warn "My data is out-of-date. status=$data_status"
 
1070
            return 1
 
1071
        fi
 
1072
    fi
 
1073
    ocf_log info "My data status=$data_status."
 
1074
 
 
1075
    show_xlog_location
 
1076
    if [ $? -ne 0 ]; then
 
1077
        ocf_log err "Failed to show my xlog location."
 
1078
        exit $OCF_ERR_GENERIC
 
1079
    fi
 
1080
 
 
1081
    old=0
 
1082
    for count in `seq $OCF_RESKEY_xlog_check_count`; do
 
1083
       if [ -f ${XLOG_NOTE_FILE}.$count ]; then
 
1084
           old=$count
 
1085
           continue
 
1086
       fi
 
1087
       break
 
1088
    done
 
1089
    new=`expr $old + 1`
 
1090
 
 
1091
    # get xlog locations of all nodes
 
1092
    for node in ${NODE_LIST}; do
 
1093
        output=`$CRM_ATTR_REBOOT -N "$node" -n \
 
1094
                "$PGSQL_XLOG_LOC_NAME" -G -q 2>/dev/null`
 
1095
        if [ $? -ne 0 ]; then
 
1096
            ocf_log warn "Can't get $node xlog location."
 
1097
            continue
 
1098
        else
 
1099
            ocf_log info "$node xlog location : $output"
 
1100
            echo "$node $output" >> ${XLOG_NOTE_FILE}.${new}
 
1101
            if [ "$node" = "$NODENAME" ]; then
 
1102
                mylocation=$output
 
1103
            fi
 
1104
        fi
 
1105
    done
 
1106
 
 
1107
    oldfile=`cat ${XLOG_NOTE_FILE}.${old} 2>/dev/null`
 
1108
    newfile=`cat ${XLOG_NOTE_FILE}.${new} 2>/dev/null`
 
1109
    if [ "$oldfile" != "$newfile" ]; then
 
1110
        # reset counter
 
1111
        rm -f ${XLOG_NOTE_FILE}.*
 
1112
        printf "$newfile\n" > ${XLOG_NOTE_FILE}.0
 
1113
        return 1
 
1114
    fi
 
1115
 
 
1116
    if [ "$new" -ge "$OCF_RESKEY_xlog_check_count" ]; then
 
1117
        newestXlog=`printf "$newfile\n" | sort -t " " -k 2,3 -r | \
 
1118
                    head -1 | cut -d " " -f 2`
 
1119
        if [ "$newestXlog" = "$mylocation" ]; then
 
1120
            ocf_log info "I have a master right."
 
1121
            $CRM_MASTER -v $PROMOTE_ME
 
1122
            return 0
 
1123
        fi
 
1124
        change_data_status "$NODENAME" "DISCONNECT"
 
1125
        ocf_log info "I don't have correct master data."
 
1126
        # reset counter
 
1127
        rm -f ${XLOG_NOTE_FILE}.*
 
1128
        printf "$newfile\n" > ${XLOG_NOTE_FILE}.0
 
1129
    fi
 
1130
 
 
1131
    return 1
 
1132
}
 
1133
 
 
1134
is_replication() {
 
1135
    if [ "$OCF_RESKEY_rep_mode" != "none" ]; then
 
1136
        return 0
 
1137
    fi
 
1138
    return 1
 
1139
}
 
1140
 
 
1141
get_my_location() {
 
1142
    local rc
 
1143
    local output
 
1144
    local replay_loc
 
1145
    local receive_loc
 
1146
    local output1
 
1147
    local output2
 
1148
    local log1
 
1149
    local log2
 
1150
    local newer_location
 
1151
 
 
1152
    output=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
 
1153
            $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
 
1154
            -Atc \"${CHECK_XLOG_LOC_SQL}\""`
 
1155
    rc=$?
 
1156
    if [ $rc -ne 0 ]; then
 
1157
        report_psql_error $rc warn
 
1158
        ocf_log err "Can't get my xlog location."
 
1159
        return 1
 
1160
    fi
 
1161
    replay_loc=`echo $output | cut -d "|" -f 1`
 
1162
    receive_loc=`echo $output | cut -d "|" -f 2`
 
1163
 
 
1164
    output1=`echo "$replay_loc" | cut -d "/" -f 1`
 
1165
    output2=`echo "$replay_loc" | cut -d "/" -f 2`
 
1166
    log1=`printf "%08s\n" $output1 | sed "s/ /0/g"`
 
1167
    log2=`printf "%08s\n" $output2 | sed "s/ /0/g"`
 
1168
    replay_loc="${log1}${log2}"
 
1169
 
 
1170
    output1=`echo "$receive_loc" | cut -d "/" -f 1`
 
1171
    output2=`echo "$receive_loc" | cut -d "/" -f 2`
 
1172
    log1=`printf "%08s\n" $output1 | sed "s/ /0/g"`
 
1173
    log2=`printf "%08s\n" $output2 | sed "s/ /0/g"`
 
1174
    receive_loc="${log1}${log2}"
 
1175
 
 
1176
    newer_location=`printf "$replay_loc\n$receive_loc" | sort -r | head -1`
 
1177
    echo "$newer_location"
 
1178
    return 0
 
1179
}
 
1180
 
 
1181
show_xlog_location() {
 
1182
    local location
 
1183
 
 
1184
    location=`get_my_location` || return 1
 
1185
    $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_XLOG_LOC_NAME" -v "$location"
 
1186
}
 
1187
 
 
1188
delete_xlog_location() {
 
1189
    $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_XLOG_LOC_NAME" -D
 
1190
}
 
1191
 
 
1192
show_master_baseline() {
 
1193
    local rc
 
1194
    local location
 
1195
 
 
1196
    runasowner -q err "$OCF_RESKEY_psql $psql_options \
 
1197
                       -U $OCF_RESKEY_pgdba -c 'CHECKPOINT'"
 
1198
    rc=$?
 
1199
    if [ $rc -ne 0 ]; then
 
1200
        report_psql_error $rc warn
 
1201
    fi
 
1202
    location=`get_my_location`
 
1203
    ocf_log info "My master baseline : $location."
 
1204
    $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_MASTER_BASELINE" -v "$location"
 
1205
}
 
1206
 
 
1207
delete_master_baseline() {
 
1208
    $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_MASTER_BASELINE" -D
 
1209
}
 
1210
 
 
1211
set_async_mode_all() {
 
1212
    [ "$OCF_RESKEY_rep_mode" = "sync" ] || return 0
 
1213
    ocf_log info "Set all nodes into async mode."
 
1214
    runasowner -q err "echo \"synchronous_standby_names = ''\" > \"$REP_MODE_CONF\""
 
1215
    if [ $? -ne 0 ]; then
 
1216
        ocf_log err "Can't set all nodes into async mode."
 
1217
        return 1
 
1218
    fi
 
1219
    return 0
 
1220
}
 
1221
 
 
1222
set_async_mode() {
 
1223
    local sync_node_in_conf
 
1224
 
 
1225
    sync_node_in_conf=`cat $REP_MODE_CONF | cut -d "'" -f 2`
 
1226
    if [ -n "$sync_node_in_conf" ]; then
 
1227
        ocf_log info "Setup $1 into async mode."
 
1228
        sync_node_in_conf=`echo $sync_node_in_conf | sed "s/$1//g" |\
 
1229
                           sed "s/^,//g" | sed "s/,,/,/g" | sed "s/,$//g"`
 
1230
        echo "synchronous_standby_names = '$sync_node_in_conf'" > "$REP_MODE_CONF"
 
1231
    else
 
1232
        ocf_log info "$1 is already in async mode."
 
1233
        return 0
 
1234
    fi
 
1235
 
 
1236
    ocf_log info "All synced nodes : \"$sync_node_in_conf\""
 
1237
    reload_conf
 
1238
}
 
1239
 
 
1240
set_sync_mode() {
 
1241
    local sync_node_in_conf
 
1242
 
 
1243
    sync_node_in_conf=`cat $REP_MODE_CONF | cut -d "'" -f 2`
 
1244
    if [ -n "$sync_node_in_conf" ]; then
 
1245
        ocf_log info "Setup $1 into sync mode."
 
1246
        echo "synchronous_standby_names = '$sync_node_in_conf,$1'" > "$REP_MODE_CONF"
 
1247
    else
 
1248
        ocf_log info "Setup $1 into sync mode."
 
1249
        echo "synchronous_standby_names = '$1'" > "$REP_MODE_CONF"
 
1250
    fi
 
1251
 
 
1252
    sync_node_in_conf=`cat $REP_MODE_CONF | cut -d "'" -f 2`
 
1253
    ocf_log info "All synced nodes : \"$sync_node_in_conf\""
 
1254
    reload_conf
 
1255
}
 
1256
 
 
1257
is_sync_mode() {
 
1258
    cat $REP_MODE_CONF |  grep -q -e "[,' ]$1[,' ]"
 
1259
}
 
1260
 
 
1261
reload_conf() {
 
1262
    # Invoke pg_ctl
 
1263
    runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata reload"
 
1264
    if [ $? -eq 0 ]; then
 
1265
        ocf_log info "Reload configuration file."
 
1266
    else
 
1267
        ocf_log err "Can't reload configuration file."
 
1268
        return 1
 
1269
    fi
 
1270
 
 
1271
    return 0
 
1272
}
 
1273
 
 
1274
user_recovery_conf() {
 
1275
    # put archive_cleanup_command and recovery_end_command only when defined by user
 
1276
    if [ -n "$OCF_RESKEY_archive_cleanup_command" ]; then
 
1277
        echo "archive_cleanup_command = '${OCF_RESKEY_archive_cleanup_command}'"
 
1278
    fi
 
1279
    if [ -n "$OCF_RESKEY_recovery_end_command" ]; then
 
1280
        echo "recovery_end_command = '${OCF_RESKEY_recovery_end_command}'"
 
1281
    fi
 
1282
}
 
1283
 
 
1284
make_recovery_conf() {
 
1285
    runasowner "touch $RECOVERY_CONF"
 
1286
    if [ $? -ne 0 ]; then
 
1287
        ocf_log err "Can't create recovery.conf."
 
1288
        return 1
 
1289
    fi
 
1290
 
 
1291
cat > $RECOVERY_CONF <<END
 
1292
standby_mode = 'on'
 
1293
primary_conninfo = 'host=${OCF_RESKEY_master_ip} port=${OCF_RESKEY_pgport} user=${OCF_RESKEY_repuser} application_name=${NODENAME} ${OCF_RESKEY_primary_conninfo_opt}'
 
1294
restore_command = '${OCF_RESKEY_restore_command}'
 
1295
recovery_target_timeline = 'latest'
 
1296
END
 
1297
 
 
1298
    user_recovery_conf >> $RECOVERY_CONF
 
1299
    ocf_log debug "Created recovery.conf. host=${OCF_RESKEY_master_ip}, user=${OCF_RESKEY_repuser}"
 
1300
    return 0
 
1301
}
 
1302
 
 
1303
# change pgsql-status.
 
1304
# arg1:node, arg2: value
 
1305
change_pgsql_status() {
 
1306
    local output
 
1307
 
 
1308
    if ! is_node_online $1; then
 
1309
        return 0
 
1310
    fi
 
1311
 
 
1312
    output=`$CRM_ATTR_REBOOT -N "$1" -n "$PGSQL_STATUS_ATTR" -G -q 2>/dev/null`
 
1313
    if [ "$output" != "$2" ]; then
 
1314
        # If slave's disk is broken, RA cannot read PID file
 
1315
        # and misjudges the PostgreSQL as down while it is running.
 
1316
        # It causes overwriting of pgsql-status by Master because replication is still connected.
 
1317
        if [ "$output" = "STOP" -o "$output" = "UNKNOWN" ]; then
 
1318
            if [ "$1" != "$NODENAME" ]; then
 
1319
                ocf_log warn "Changing $PGSQL_STATUS_ATTR on $1 : $output->$2 by $NODENAME is prohibited."
 
1320
                return 0
 
1321
            fi
 
1322
        fi
 
1323
        ocf_log info "Changing $PGSQL_STATUS_ATTR on $1 : $output->$2."
 
1324
        $CRM_ATTR_REBOOT -N "$1" -n "$PGSQL_STATUS_ATTR" -v "$2"
 
1325
        if [ $? -ne 0 ]; then
 
1326
            ocf_log err "Can't change $PGSQL_STATUS_ATTR."
 
1327
            return 1
 
1328
        fi
 
1329
    fi
 
1330
    return 0
 
1331
}
 
1332
 
 
1333
# change pgsql-data-status.
 
1334
# arg1:node, arg2: value
 
1335
change_data_status() {
 
1336
    local output
 
1337
 
 
1338
    if ! node_exist $1; then
 
1339
        return 0
 
1340
    fi
 
1341
 
 
1342
    while :
 
1343
    do
 
1344
        output=`$CRM_ATTR_FOREVER -N "$1" -n "$PGSQL_DATA_STATUS_ATTR" -G -q 2>/dev/null`
 
1345
        if [ "$output" != "$2" ]; then
 
1346
            ocf_log info "Changing $PGSQL_DATA_STATUS_ATTR on $1 : $output->$2."
 
1347
            exec_func_with_timeout "$CRM_ATTR_FOREVER" "-N $1 -n \
 
1348
                                    $PGSQL_DATA_STATUS_ATTR -v \"$2\"" \
 
1349
                                    $OCF_RESKEY_crm_attr_timeout
 
1350
            if [ $? -ne 0 ]; then
 
1351
                ocf_log err "Can't change $PGSQL_DATA_STATUS_ATTR."
 
1352
                return 1
 
1353
            fi
 
1354
        else
 
1355
            break
 
1356
        fi
 
1357
    done
 
1358
    return 0
 
1359
}
 
1360
 
 
1361
# change master-score
 
1362
# arg1:node, arg2: score
 
1363
change_master_score() {
 
1364
    local instance
 
1365
    local current_score
 
1366
 
 
1367
    if ! is_node_online $1; then
 
1368
        return 0
 
1369
    fi
 
1370
 
 
1371
    instance=0
 
1372
    while :
 
1373
    do
 
1374
        if [ "$instance" -ge "$OCF_RESKEY_CRM_meta_clone_max" ]; then
 
1375
            break
 
1376
        fi
 
1377
        if [ "${RESOURCE_NAME}:${instance}" = "$OCF_RESOURCE_INSTANCE" ]; then
 
1378
            instance=`expr $instance + 1`
 
1379
            continue
 
1380
        fi
 
1381
 
 
1382
        current_score=`$CRM_ATTR_REBOOT -N "$1" -n "master-${RESOURCE_NAME}:${instance}" -G -q 2>/dev/null`
 
1383
        if [ -n "$current_score" -a "$current_score" != "$2" ]; then
 
1384
            ocf_log info "Changing ${RESOURCE_NAME}:${instance} master score on $1 : $current_score->$2."
 
1385
            $CRM_ATTR_REBOOT -N "$target" -n "master-${RESOURCE_NAME}:${instance}" -v "$2"
 
1386
            if [ $? -ne 0 ]; then
 
1387
                ocf_log err "Can't change master score."
 
1388
                return 1
 
1389
            fi
 
1390
        fi
 
1391
        instance=`expr $instance + 1`
 
1392
    done
 
1393
    return 0
 
1394
}
 
1395
 
 
1396
report_psql_error()
 
1397
{
 
1398
    local rc
 
1399
    local loglevel
 
1400
 
 
1401
    rc=$1
 
1402
    loglevel=${2:-err}
 
1403
 
 
1404
    ocf_log $loglevel "PostgreSQL $OCF_RESKEY_pgdb isn't running"
 
1405
    if [ $rc -eq 1 ]; then
 
1406
        ocf_log err "Fatal error (out of memory, file not found, etc.) occurred while executing the psql command."
 
1407
    elif [ $rc -eq 2 ]; then
 
1408
        ocf_log $loglevel "Connection error (connection to the server went bad and the session was not interactive) occurred while executing the psql command."
 
1409
    elif [ $rc -eq 3 ]; then
 
1410
        ocf_log err "Script error (the variable ON_ERROR_STOP was set) occurred while executing the psql command."
 
1411
    fi
 
1412
}
 
1413
 
 
1414
#
 
1415
# timeout management function
 
1416
# arg1 : command
 
1417
# arg2 : command's args
 
1418
# arg3 : timeout(s)
 
1419
#
 
1420
exec_func_with_timeout() {
 
1421
    local func_pid
 
1422
    local count
 
1423
    local rc
 
1424
 
 
1425
    $1 `eval echo $2` &
 
1426
    func_pid=$!
 
1427
    count=0
 
1428
    while kill -s 0 $func_pid >/dev/null 2>&1; do
 
1429
        sleep 1
 
1430
        count=`expr $count + 1`
 
1431
        if [ $count -ge $3 ]; then
 
1432
            ocf_log debug "Execute $1 time out."
 
1433
            kill -s 9 $func_pid >/dev/null 2>&1
 
1434
            return 0
 
1435
        fi
 
1436
    done
 
1437
    wait $func_pid
 
1438
}
 
1439
 
 
1440
is_node_online() {
 
1441
    crm_mon -1 -n | grep -e "^Node $1 " -e "^Node $1:" | grep -q -v "OFFLINE"
 
1442
}
 
1443
 
 
1444
node_exist() {
 
1445
    crm_mon -1 -n | grep -q "^Node $1"
499
1446
}
500
1447
 
501
1448
check_binary2() {
511
1458
 
512
1459
    if [ ! -f "$1" ]; then
513
1460
        if ocf_is_probe; then
514
 
           ocf_log info "Configuration file $1 not readable during probe."
 
1461
           ocf_log info "Configuration file is $1 not readable during probe."
515
1462
           rc=1
516
1463
        else
517
1464
           ocf_log err "Configuration file $1 doesn't exist"
524
1471
 
525
1472
# Validate most critical parameters
526
1473
pgsql_validate_all() {
 
1474
    local version
 
1475
    local check_config_rc
 
1476
 
527
1477
    if ! check_binary2 "$OCF_RESKEY_pgctl" || 
528
1478
       ! check_binary2 "$OCF_RESKEY_psql"; then
529
1479
        return $OCF_ERR_INSTALLED
530
1480
    fi
531
1481
 
532
 
    if [ -n "$OCF_RESKEY_config" -a ! -f "$OCF_RESKEY_config" ]; then
533
 
       check_config "$OCF_RESKEY_config"
534
 
       [ $? -eq 2 ] && return $OCF_ERR_INSTALLED
535
 
    fi
 
1482
    check_config "$OCF_RESKEY_config"
 
1483
    check_config_rc=$?
 
1484
    [ $check_config_rc -eq 2 ] && return $OCF_ERR_INSTALLED
 
1485
    [ $check_config_rc -eq 0 ] && : ${OCF_RESKEY_socketdir=`get_pgsql_param unix_socket_directory`}
536
1486
 
537
1487
    getent passwd $OCF_RESKEY_pgdba >/dev/null 2>&1
538
1488
    if [ ! $? -eq 0 ]; then
561
1511
        return $OCF_ERR_CONFIGURED
562
1512
    fi
563
1513
 
 
1514
    if is_replication; then
 
1515
        version=`cat $OCF_RESKEY_pgdata/PG_VERSION`
 
1516
        if [ `printf "$version\n9.1" | sort -n | head -1` != "9.1" ]; then
 
1517
            ocf_log err "Replication mode needs PostgreSQL 9.1 or higher."
 
1518
            return $OCF_ERR_INSTALLED
 
1519
        fi
 
1520
        if ! ocf_is_ms; then
 
1521
            ocf_log err "Replication requires Master/Slave configuration."
 
1522
            return $OCF_ERR_CONFIGURED
 
1523
        fi
 
1524
        if [ ! "$OCF_RESKEY_rep_mode" = "sync" -a ! "$OCF_RESKEY_rep_mode" = "async" ]; then
 
1525
            ocf_log err "Invalid rep_mode : $OCF_RESKEY_rep_mode"
 
1526
            return $OCF_ERR_CONFIGURED
 
1527
        fi
 
1528
        if [ ! -n "$OCF_RESKEY_master_ip" ]; then
 
1529
            ocf_log err "master_ip can't be empty."
 
1530
            return $OCF_ERR_CONFIGURED
 
1531
        fi
 
1532
        if [ ! -n "$NODE_LIST" ]; then
 
1533
            ocf_log err "node_list can't be empty."
 
1534
            return $OCF_ERR_CONFIGURED
 
1535
        fi
 
1536
        if [ "$OCF_RESKEY_rep_mode" = "sync" -a $check_config_rc -eq 0 ]; then
 
1537
            if ! grep -q "include '$REP_MODE_CONF' # added by pgsql RA" $OCF_RESKEY_config; then
 
1538
                echo "include '$REP_MODE_CONF' # added by pgsql RA" >> $OCF_RESKEY_config
 
1539
            fi
 
1540
        fi
 
1541
        if ! mkdir -p $OCF_RESKEY_tmpdir || ! chown $OCF_RESKEY_pgdba $OCF_RESKEY_tmpdir || ! chmod 700 $OCF_RESKEY_tmpdir; then
 
1542
            ocf_log err "Can't create directory $OCF_RESKEY_tmpdir or it is not readable by $OCF_RESKEY_pgdba"
 
1543
            return $OCF_ERR_PERM
 
1544
        fi
 
1545
    fi
 
1546
 
564
1547
    return $OCF_SUCCESS
565
1548
}
566
1549
 
591
1574
check_socket_dir() {
592
1575
    if [ ! -d "$OCF_RESKEY_socketdir" ]; then
593
1576
        if ! mkdir "$OCF_RESKEY_socketdir"; then
594
 
            ocf_log err "Cannot create directory $OCF_RESKEY_socketdir"
 
1577
            ocf_log err "Can't create directory $OCF_RESKEY_socketdir"
595
1578
            exit $OCF_ERR_PERM
596
1579
        fi
597
1580
 
598
1581
        if ! chown $OCF_RESKEY_pgdba:`getent passwd \
599
1582
             $OCF_RESKEY_pgdba | cut -d ":" -f 4` "$OCF_RESKEY_socketdir" 
600
1583
        then
601
 
            ocf_log err "Cannot change ownership for $OCF_RESKEY_socketdir"
 
1584
            ocf_log err "Can't change ownership for $OCF_RESKEY_socketdir"
602
1585
            exit $OCF_ERR_PERM
603
1586
        fi
604
1587
 
605
1588
        if ! chmod 2775 "$OCF_RESKEY_socketdir"; then
606
 
            ocf_log err "Cannot change permissions for $OCF_RESKEY_socketdir"
 
1589
            ocf_log err "Can't change permissions for $OCF_RESKEY_socketdir"
607
1590
            exit $OCF_ERR_PERM
608
1591
        fi
609
1592
    else
610
1593
        if ! runasowner "touch $OCF_RESKEY_socketdir/test.$$"; then
611
 
            ocf_log err "$OCF_RESKEY_pgdba cannot create files in $OCF_RESKEY_socketdir"
 
1594
            ocf_log err "$OCF_RESKEY_pgdba can't create files in $OCF_RESKEY_socketdir"
612
1595
            exit $OCF_ERR_PERM
613
1596
        fi
614
1597
        rm $OCF_RESKEY_socketdir/test.$$
630
1613
PIDFILE=${OCF_RESKEY_pgdata}/postmaster.pid
631
1614
BACKUPLABEL=${OCF_RESKEY_pgdata}/backup_label
632
1615
 
 
1616
if is_replication; then
 
1617
    RECOVERY_CONF=${OCF_RESKEY_pgdata}/recovery.conf
 
1618
    REP_MODE_CONF=${OCF_RESKEY_tmpdir}/rep_mode.conf
 
1619
    PGSQL_LOCK=${OCF_RESKEY_tmpdir}/PGSQL.lock
 
1620
    XLOG_NOTE_FILE=${OCF_RESKEY_tmpdir}/xlog_note
 
1621
 
 
1622
    CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
 
1623
    CRM_ATTR_REBOOT="${HA_SBIN_DIR}/crm_attribute -l reboot"
 
1624
    CRM_ATTR_FOREVER="${HA_SBIN_DIR}/crm_attribute -l forever"
 
1625
    CRM_FAILCOUNT="${HA_SBIN_DIR}/crm_failcount"
 
1626
 
 
1627
    CAN_NOT_PROMOTE="-INFINITY"
 
1628
    CAN_PROMOTE="100"
 
1629
    PROMOTE_ME="1000"
 
1630
 
 
1631
    CHECK_MS_SQL="select pg_is_in_recovery()"
 
1632
    CHECK_XLOG_LOC_SQL="select pg_last_xlog_replay_location(),pg_last_xlog_receive_location()"
 
1633
    CHECK_REPLICATION_STATE_SQL="select application_name,upper(state),upper(sync_state) from pg_stat_replication"
 
1634
 
 
1635
    RESOURCE_NAME=`echo $OCF_RESOURCE_INSTANCE | cut -d ":" -f 1`
 
1636
    PGSQL_STATUS_ATTR="${RESOURCE_NAME}-status"
 
1637
    PGSQL_DATA_STATUS_ATTR="${RESOURCE_NAME}-data-status"
 
1638
    PGSQL_XLOG_LOC_NAME="${RESOURCE_NAME}-xlog-loc"
 
1639
    PGSQL_MASTER_BASELINE="${RESOURCE_NAME}-master-baseline"
 
1640
 
 
1641
    NODENAME=`uname -n | tr '[A-Z]' '[a-z]'`
 
1642
    NODE_LIST=`echo $OCF_RESKEY_node_list | tr '[A-Z]' '[a-z]'`
 
1643
    OPERATION=$1
 
1644
fi
 
1645
 
633
1646
case "$1" in
634
1647
    methods)    pgsql_methods
635
1648
                exit $?;;
638
1651
                exit $OCF_SUCCESS;;
639
1652
esac
640
1653
 
641
 
# $OCF_RESKEY_pgdata has to be initialized at this momemnt
642
 
: ${OCF_RESKEY_socketdir=`get_pgsql_param unix_socket_directory`}
643
 
 
644
1654
pgsql_validate_all
645
1655
rc=$?
646
1656
 
647
 
[ "$1" == "validate-all" ] && exit $rc
 
1657
[ "$1" = "validate-all" ] && exit $rc
648
1658
 
649
1659
if [ $rc -ne 0 ]
650
1660
then
664
1674
    exit $OCF_ERR_GENERIC
665
1675
fi
666
1676
 
 
1677
# make psql command options
 
1678
if [ -n "$OCF_RESKEY_monitor_user" ]; then
 
1679
    PGUSER=$OCF_RESKEY_monitor_user; export PGUSER
 
1680
    PGPASSWORD=$OCF_RESKEY_monitor_password; export PGPASSWORD
 
1681
    psql_options="-p $OCF_RESKEY_pgport $OCF_RESKEY_pgdb"
 
1682
else
 
1683
    psql_options="-p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb"
 
1684
fi
 
1685
 
 
1686
if [ -n "$OCF_RESKEY_pghost" ]; then
 
1687
   psql_options="$psql_options -h $OCF_RESKEY_pghost"
 
1688
else
 
1689
   if [ -n "$OCF_RESKEY_socketdir" ]; then
 
1690
       psql_options="$psql_options -h $OCF_RESKEY_socketdir"
 
1691
   fi
 
1692
fi
 
1693
 
667
1694
# What kind of method was invoked?
668
1695
case "$1" in
669
1696
    status)     if pgsql_status
681
1708
    start)      pgsql_start
682
1709
                exit $?;;
683
1710
 
 
1711
    promote)    pgsql_promote
 
1712
                exit $?;;
 
1713
 
 
1714
    demote)     pgsql_demote
 
1715
                exit $?;;
 
1716
 
 
1717
    notify)     pgsql_notify
 
1718
                exit $?;;
 
1719
 
684
1720
    stop)       pgsql_stop
685
1721
                exit $?;;
686
1722
    *)