Line data Source code
1 : /*
2 : * Copyright 2004-2021 the Pacemaker project contributors
3 : *
4 : * The version control history for this file may have further details.
5 : *
6 : * This source code is licensed under the GNU Lesser General Public License
7 : * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 : */
9 :
10 : #include <crm_internal.h>
11 :
12 : #ifndef _GNU_SOURCE
13 : # define _GNU_SOURCE
14 : #endif
15 :
16 : #include <stdio.h>
17 : #include <string.h>
18 : #include <strings.h>
19 :
20 : #include <crm/crm.h>
21 : #include <crm/common/util.h>
22 :
23 : /*!
24 : * \brief Get capabilities of a resource agent standard
25 : *
26 : * \param[in] standard Standard name
27 : *
28 : * \return Bitmask of enum pcmk_ra_caps values
29 : */
30 : uint32_t
31 183 : pcmk_get_ra_caps(const char *standard)
32 : {
33 : /* @COMPAT This should probably be case-sensitive, but isn't,
34 : * for backward compatibility.
35 : */
36 183 : if (standard == NULL) {
37 1 : return pcmk_ra_cap_none;
38 :
39 182 : } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_OCF)) {
40 142 : return pcmk_ra_cap_provider | pcmk_ra_cap_params
41 : | pcmk_ra_cap_unique | pcmk_ra_cap_promotable;
42 :
43 40 : } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_STONITH)) {
44 : /* @COMPAT Stonith resources can't really be unique clones, but we've
45 : * allowed it in the past and have it in some scheduler regression tests
46 : * (which were likely never used as real configurations).
47 : *
48 : * @TODO Remove pcmk_ra_cap_unique at the next major schema version
49 : * bump, with a transform to remove PCMK_META_GLOBALLY_UNIQUE from the
50 : * config.
51 : */
52 7 : return pcmk_ra_cap_params | pcmk_ra_cap_unique | pcmk_ra_cap_stdin
53 : | pcmk_ra_cap_fence_params;
54 :
55 33 : } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_SYSTEMD)
56 30 : || !strcasecmp(standard, PCMK_RESOURCE_CLASS_SERVICE)
57 28 : || !strcasecmp(standard, PCMK_RESOURCE_CLASS_LSB)
58 6 : || !strcasecmp(standard, PCMK_RESOURCE_CLASS_UPSTART)) {
59 :
60 : /* Since service can map to LSB, systemd, or upstart, these should
61 : * have identical capabilities
62 : */
63 29 : return pcmk_ra_cap_status;
64 :
65 4 : } else if (!strcasecmp(standard, PCMK_RESOURCE_CLASS_NAGIOS)) {
66 2 : return pcmk_ra_cap_params;
67 : }
68 2 : return pcmk_ra_cap_none;
69 : }
70 :
71 : int
72 116 : pcmk__effective_rc(int rc)
73 : {
74 116 : int remapped_rc = rc;
75 :
76 116 : switch (rc) {
77 1 : case PCMK_OCF_DEGRADED:
78 1 : remapped_rc = PCMK_OCF_OK;
79 1 : break;
80 :
81 1 : case PCMK_OCF_DEGRADED_PROMOTED:
82 1 : remapped_rc = PCMK_OCF_RUNNING_PROMOTED;
83 1 : break;
84 :
85 114 : default:
86 114 : break;
87 : }
88 :
89 116 : return remapped_rc;
90 : }
91 :
92 : char *
93 8 : crm_generate_ra_key(const char *standard, const char *provider,
94 : const char *type)
95 : {
96 8 : bool std_empty = pcmk__str_empty(standard);
97 8 : bool prov_empty = pcmk__str_empty(provider);
98 8 : bool ty_empty = pcmk__str_empty(type);
99 :
100 8 : if (std_empty || ty_empty) {
101 6 : return NULL;
102 : }
103 :
104 2 : return crm_strdup_printf("%s%s%s:%s",
105 : standard,
106 : (prov_empty ? "" : ":"), (prov_empty ? "" : provider),
107 : type);
108 : }
109 :
110 : /*!
111 : * \brief Parse a "standard[:provider]:type" agent specification
112 : *
113 : * \param[in] spec Agent specification
114 : * \param[out] standard Newly allocated memory containing agent standard (or NULL)
115 : * \param[out] provider Newly allocated memory containing agent provider (or NULL)
116 : * \param[put] type Newly allocated memory containing agent type (or NULL)
117 : *
118 : * \return pcmk_ok if the string could be parsed, -EINVAL otherwise
119 : *
120 : * \note It is acceptable for the type to contain a ':' if the standard supports
121 : * that. For example, systemd supports the form "systemd:UNIT@A:B".
122 : * \note It is the caller's responsibility to free the returned values.
123 : */
124 : int
125 11 : crm_parse_agent_spec(const char *spec, char **standard, char **provider,
126 : char **type)
127 : {
128 : char *colon;
129 :
130 11 : CRM_CHECK(spec && standard && provider && type, return -EINVAL);
131 7 : *standard = NULL;
132 7 : *provider = NULL;
133 7 : *type = NULL;
134 :
135 7 : colon = strchr(spec, ':');
136 7 : if ((colon == NULL) || (colon == spec)) {
137 1 : return -EINVAL;
138 : }
139 :
140 6 : *standard = strndup(spec, colon - spec);
141 6 : spec = colon + 1;
142 :
143 6 : if (pcmk_is_set(pcmk_get_ra_caps(*standard), pcmk_ra_cap_provider)) {
144 4 : colon = strchr(spec, ':');
145 4 : if ((colon == NULL) || (colon == spec)) {
146 2 : free(*standard);
147 2 : return -EINVAL;
148 : }
149 2 : *provider = strndup(spec, colon - spec);
150 2 : spec = colon + 1;
151 : }
152 :
153 4 : if (*spec == '\0') {
154 1 : free(*standard);
155 1 : free(*provider);
156 1 : return -EINVAL;
157 : }
158 :
159 3 : *type = strdup(spec);
160 3 : return pcmk_ok;
161 : }
162 :
163 : /*!
164 : * \brief Check whether a given stonith parameter is handled by Pacemaker
165 : *
166 : * Return true if a given string is the name of one of the special resource
167 : * instance attributes interpreted directly by Pacemaker for stonith-class
168 : * resources.
169 : *
170 : * \param[in] param Parameter name to check
171 : *
172 : * \return true if \p param is a special fencing parameter
173 : */
174 : bool
175 19 : pcmk_stonith_param(const char *param)
176 : {
177 19 : if (param == NULL) {
178 1 : return false;
179 : }
180 18 : if (pcmk__str_any_of(param, PCMK_STONITH_PROVIDES,
181 : PCMK_STONITH_STONITH_TIMEOUT, NULL)) {
182 2 : return true;
183 : }
184 16 : if (!pcmk__starts_with(param, "pcmk_")) { // Short-circuit common case
185 3 : return false;
186 : }
187 13 : if (pcmk__str_any_of(param,
188 : PCMK_STONITH_ACTION_LIMIT,
189 : PCMK_STONITH_DELAY_BASE,
190 : PCMK_STONITH_DELAY_MAX,
191 : PCMK_STONITH_HOST_ARGUMENT,
192 : PCMK_STONITH_HOST_CHECK,
193 : PCMK_STONITH_HOST_LIST,
194 : PCMK_STONITH_HOST_MAP,
195 : NULL)) {
196 7 : return true;
197 : }
198 6 : param = strchr(param + 5, '_'); // Skip past "pcmk_ACTION"
199 6 : return pcmk__str_any_of(param, "_action", "_timeout", "_retries", NULL);
200 : }
201 :
202 : // Deprecated functions kept only for backward API compatibility
203 : // LCOV_EXCL_START
204 :
205 : #include <crm/common/agents_compat.h>
206 :
207 : bool
208 : crm_provider_required(const char *standard)
209 : {
210 : return pcmk_is_set(pcmk_get_ra_caps(standard), pcmk_ra_cap_provider);
211 : }
212 :
213 : // LCOV_EXCL_STOP
214 : // End deprecated API
|