summaryrefslogtreecommitdiffstats
path: root/daemons/controld/controld_attrd.c
blob: f728bef9fb8277779978408e4ab8dfe830e500db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright 2006-2024 the Pacemaker project contributors
 *
 * The version control history for this file may have further details.
 *
 * This source code is licensed under the GNU General Public License version 2
 * or later (GPLv2+) WITHOUT ANY WARRANTY.
 */

#include <crm_internal.h>

#include <crm/crm.h>
#include <crm/common/attrs_internal.h>
#include <crm/common/ipc.h>
#include <crm/common/ipc_attrd_internal.h>
#include <crm/common/xml.h>

#include <pacemaker-controld.h>

static pcmk_ipc_api_t *attrd_api = NULL;

void
controld_close_attrd_ipc(void)
{
    if (attrd_api != NULL) {
        crm_trace("Closing connection to pacemaker-attrd");
        pcmk_disconnect_ipc(attrd_api);
        pcmk_free_ipc_api(attrd_api);
        attrd_api = NULL;
    }
}

static inline const char *
node_type(bool is_remote)
{
    return is_remote? "Pacemaker Remote" : "cluster";
}

static inline const char *
when(void)
{
    return pcmk_is_set(controld_globals.fsa_input_register,
                       R_SHUTDOWN)? " at shutdown" : "";
}

static void
handle_attr_error(void)
{
    if (AM_I_DC) {
        /* We are unable to provide accurate information to the
         * scheduler, so allow another node to take over DC.
         * @TODO Should we do this unconditionally on any failure?
         */
        crmd_exit(CRM_EX_FATAL);

    } else if (pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
        // Fast-track shutdown since unable to request via attribute
        register_fsa_input(C_FSA_INTERNAL, I_FAIL, NULL);
    }
}

void
update_attrd(const char *host, const char *name, const char *value,
             const char *user_name, gboolean is_remote_node)
{
    int rc = pcmk_rc_ok;

    if (attrd_api == NULL) {
        rc = pcmk_new_ipc_api(&attrd_api, pcmk_ipc_attrd);
    }
    if (rc == pcmk_rc_ok) {
        uint32_t attrd_opts = pcmk__node_attr_value;

        if (is_remote_node) {
            pcmk__set_node_attr_flags(attrd_opts, pcmk__node_attr_remote);
        }
        rc = pcmk__attrd_api_update(attrd_api, host, name, value,
                                    NULL, NULL, user_name, attrd_opts);
    }
    if (rc != pcmk_rc_ok) {
        do_crm_log(AM_I_DC? LOG_CRIT : LOG_ERR,
                   "Could not update attribute %s=%s for %s node %s%s: %s "
                   CRM_XS " rc=%d", name, value, node_type(is_remote_node),
                   host, when(), pcmk_rc_str(rc), rc);
        handle_attr_error();
    }
}

void
update_attrd_list(GList *attrs, uint32_t opts)
{
    int rc = pcmk_rc_ok;

    if (attrd_api == NULL) {
        rc = pcmk_new_ipc_api(&attrd_api, pcmk_ipc_attrd);
    }
    if (rc == pcmk_rc_ok) {
        rc = pcmk__attrd_api_update_list(attrd_api, attrs, NULL, NULL, NULL,
                                         opts | pcmk__node_attr_value);
    }
    if (rc != pcmk_rc_ok) {
        do_crm_log(AM_I_DC? LOG_CRIT : LOG_ERR,
                   "Could not update multiple node attributes: %s "
                   CRM_XS " rc=%d", pcmk_rc_str(rc), rc);
        handle_attr_error();
    }
}

void
update_attrd_remote_node_removed(const char *host, const char *user_name)
{
    int rc = pcmk_rc_ok;

    if (attrd_api == NULL) {
        rc = pcmk_new_ipc_api(&attrd_api, pcmk_ipc_attrd);
    }
    if (rc == pcmk_rc_ok) {
        crm_trace("Asking attribute manager to purge Pacemaker Remote node %s",
                  host);
        rc = pcmk__attrd_api_purge(attrd_api, host, true);
    }
    if (rc != pcmk_rc_ok) {
        crm_err("Could not purge Pacemaker Remote node %s "
                "in attribute manager%s: %s " CRM_XS " rc=%d",
                host, when(), pcmk_rc_str(rc), rc);
    }
}

void
update_attrd_clear_failures(const char *host, const char *rsc, const char *op,
                            const char *interval_spec, gboolean is_remote_node)
{
    int rc = pcmk_rc_ok;

    if (attrd_api == NULL) {
        rc = pcmk_new_ipc_api(&attrd_api, pcmk_ipc_attrd);
    }
    if (rc == pcmk_rc_ok) {
        uint32_t attrd_opts = pcmk__node_attr_none;

        if (is_remote_node) {
            pcmk__set_node_attr_flags(attrd_opts, pcmk__node_attr_remote);
        }
        rc = pcmk__attrd_api_clear_failures(attrd_api, host, rsc, op,
                                            interval_spec, NULL, attrd_opts);
    }
    if (rc != pcmk_rc_ok) {
        const char *interval_desc = "all";

        if (op != NULL) {
            interval_desc = pcmk__s(interval_spec, "nonrecurring");
        }
        crm_err("Could not clear failure of %s %s for %s on %s node %s%s: %s "
                CRM_XS " rc=%d", interval_desc, pcmk__s(op, "operations"),
                pcmk__s(rsc, "all resources"), node_type(is_remote_node), host,
                when(), pcmk_rc_str(rc), rc);
    }
}