This source file includes following definitions.
- lsb_meta_helper_get_value
- services__get_lsb_metadata
- services__list_lsb_agents
- services__lsb_agent_exists
- services__lsb_prepare
- services__lsb2ocf
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include <sys/stat.h>
15
16 #include <crm/crm.h>
17 #include <crm/common/xml.h>
18 #include <crm/services.h>
19 #include "services_private.h"
20 #include "services_lsb.h"
21
22
23 #define lsb_metadata_template \
24 "<?xml " PCMK_XA_VERSION "='1.0'?>\n" \
25 "<" PCMK_XE_RESOURCE_AGENT " " \
26 PCMK_XA_NAME "='%s' " \
27 PCMK_XA_VERSION "='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
28 " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
29 " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>\n" \
30 "%s" \
31 " </" PCMK_XE_LONGDESC ">\n" \
32 " <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>" \
33 "%s" \
34 "</" PCMK_XE_SHORTDESC ">\n" \
35 " <" PCMK_XE_PARAMETERS "/>\n" \
36 " <" PCMK_XE_ACTIONS ">\n" \
37 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_META_DATA "'" \
38 " " PCMK_META_TIMEOUT "='5s' />\n" \
39 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_START "'" \
40 " " PCMK_META_TIMEOUT "='15s' />\n" \
41 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STOP "'" \
42 " " PCMK_META_TIMEOUT "='15s' />\n" \
43 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STATUS "'" \
44 " " PCMK_META_TIMEOUT "='15s' />\n" \
45 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='restart'" \
46 " " PCMK_META_TIMEOUT "='15s' />\n" \
47 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='force-reload'" \
48 " " PCMK_META_TIMEOUT "='15s' />\n" \
49 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "'" \
50 " " PCMK_META_TIMEOUT "='15s'" \
51 " " PCMK_META_INTERVAL "='15s' />\n" \
52 " </" PCMK_XE_ACTIONS ">\n" \
53 " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "='LSB'>\n" \
54 " <Provides>%s</Provides>\n" \
55 " <Required-Start>%s</Required-Start>\n" \
56 " <Required-Stop>%s</Required-Stop>\n" \
57 " <Should-Start>%s</Should-Start>\n" \
58 " <Should-Stop>%s</Should-Stop>\n" \
59 " <Default-Start>%s</Default-Start>\n" \
60 " <Default-Stop>%s</Default-Stop>\n" \
61 " </" PCMK_XE_SPECIAL ">\n" \
62 "</" PCMK_XE_RESOURCE_AGENT ">\n"
63
64
65
66
67 #define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
68 #define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
69 #define PROVIDES "# Provides:"
70 #define REQUIRED_START "# Required-Start:"
71 #define REQUIRED_STOP "# Required-Stop:"
72 #define SHOULD_START "# Should-Start:"
73 #define SHOULD_STOP "# Should-Stop:"
74 #define DEFAULT_START "# Default-Start:"
75 #define DEFAULT_STOP "# Default-Stop:"
76 #define SHORT_DESC "# Short-Description:"
77 #define DESCRIPTION "# Description:"
78
79
80
81
82
83
84
85
86
87
88
89 static inline gboolean
90 lsb_meta_helper_get_value(const char *line, gchar **value, const char *prefix)
91 {
92
93
94
95 if ((*value == NULL) && pcmk__starts_with(line, prefix)) {
96 *value = pcmk__xml_escape(line + strlen(prefix), pcmk__xml_escape_text);
97 return TRUE;
98 }
99 return FALSE;
100 }
101
102 int
103 services__get_lsb_metadata(const char *type, char **output)
104 {
105 char ra_pathname[PATH_MAX] = { 0, };
106 FILE *fp = NULL;
107 char buffer[1024] = { 0, };
108 gchar *provides = NULL;
109 gchar *required_start = NULL;
110 gchar *required_stop = NULL;
111 gchar *should_start = NULL;
112 gchar *should_stop = NULL;
113 gchar *default_start = NULL;
114 gchar *default_stop = NULL;
115 gchar *short_desc = NULL;
116 gchar *long_desc = NULL;
117 bool in_header = FALSE;
118
119 if (type[0] == '/') {
120 snprintf(ra_pathname, sizeof(ra_pathname), "%s", type);
121 } else {
122 snprintf(ra_pathname, sizeof(ra_pathname), "%s/%s",
123 PCMK__LSB_INIT_DIR, type);
124 }
125
126 crm_trace("Looking into %s", ra_pathname);
127 fp = fopen(ra_pathname, "r");
128 if (fp == NULL) {
129 return -errno;
130 }
131
132
133 while (fgets(buffer, sizeof(buffer), fp)) {
134
135
136 if (pcmk__starts_with(buffer, LSB_INITSCRIPT_INFOBEGIN_TAG)) {
137 in_header = TRUE;
138 continue;
139 }
140 if (!in_header) {
141 continue;
142 }
143
144
145 if (lsb_meta_helper_get_value(buffer, &provides, PROVIDES)) {
146 continue;
147 }
148 if (lsb_meta_helper_get_value(buffer, &required_start,
149 REQUIRED_START)) {
150 continue;
151 }
152 if (lsb_meta_helper_get_value(buffer, &required_stop, REQUIRED_STOP)) {
153 continue;
154 }
155 if (lsb_meta_helper_get_value(buffer, &should_start, SHOULD_START)) {
156 continue;
157 }
158 if (lsb_meta_helper_get_value(buffer, &should_stop, SHOULD_STOP)) {
159 continue;
160 }
161 if (lsb_meta_helper_get_value(buffer, &default_start, DEFAULT_START)) {
162 continue;
163 }
164 if (lsb_meta_helper_get_value(buffer, &default_stop, DEFAULT_STOP)) {
165 continue;
166 }
167 if (lsb_meta_helper_get_value(buffer, &short_desc, SHORT_DESC)) {
168 continue;
169 }
170
171
172 if ((long_desc == NULL)
173 && pcmk__starts_with(buffer, DESCRIPTION)) {
174 bool processed_line = TRUE;
175 GString *desc = g_string_sized_new(2048);
176
177
178 g_string_append(desc, buffer + sizeof(DESCRIPTION) - 1);
179
180
181 buffer[0] = '\0';
182 while (fgets(buffer, sizeof(buffer), fp)) {
183 if (pcmk__starts_with(buffer, "# ")
184 || pcmk__starts_with(buffer, "#\t")) {
185
186
187
188 g_string_append(desc, buffer + 1);
189 } else {
190
191
192
193 processed_line = FALSE;
194 break;
195 }
196 }
197
198
199 long_desc = pcmk__xml_escape(desc->str, pcmk__xml_escape_text);
200 g_string_free(desc, TRUE);
201
202 if (processed_line) {
203
204 continue;
205 }
206 }
207
208
209 if (pcmk__starts_with(buffer, LSB_INITSCRIPT_INFOEND_TAG)) {
210 break;
211 }
212 if (buffer[0] != '#') {
213 break;
214 }
215 }
216 fclose(fp);
217
218 *output = crm_strdup_printf(lsb_metadata_template, type,
219 pcmk__s(long_desc, type),
220 pcmk__s(short_desc, type),
221 pcmk__s(provides, ""),
222 pcmk__s(required_start, ""),
223 pcmk__s(required_stop, ""),
224 pcmk__s(should_start, ""),
225 pcmk__s(should_stop, ""),
226 pcmk__s(default_start, ""),
227 pcmk__s(default_stop, ""));
228
229 g_free(long_desc);
230 g_free(short_desc);
231 g_free(provides);
232 g_free(required_start);
233 g_free(required_stop);
234 g_free(should_start);
235 g_free(should_stop);
236 g_free(default_start);
237 g_free(default_stop);
238 return pcmk_ok;
239 }
240
241 GList *
242 services__list_lsb_agents(void)
243 {
244 return services_os_get_directory_list(PCMK__LSB_INIT_DIR, TRUE, TRUE);
245 }
246
247 bool
248 services__lsb_agent_exists(const char *agent)
249 {
250 bool rc = FALSE;
251 struct stat st;
252 char *path = pcmk__full_path(agent, PCMK__LSB_INIT_DIR);
253
254 rc = (stat(path, &st) == 0);
255 free(path);
256 return rc;
257 }
258
259
260
261
262
263
264
265
266
267 int
268 services__lsb_prepare(svc_action_t *op)
269 {
270 op->opaque->exec = pcmk__full_path(op->agent, PCMK__LSB_INIT_DIR);
271 op->opaque->args[0] = strdup(op->opaque->exec);
272 op->opaque->args[1] = strdup(op->action);
273 if ((op->opaque->args[0] == NULL) || (op->opaque->args[1] == NULL)) {
274 return ENOMEM;
275 }
276 return pcmk_rc_ok;
277 }
278
279
280
281
282
283
284
285
286
287
288 enum ocf_exitcode
289 services__lsb2ocf(const char *action, int exit_status)
290 {
291
292 if (!pcmk__str_any_of(action, PCMK_ACTION_STATUS, PCMK_ACTION_MONITOR,
293 NULL)) {
294 if ((exit_status < 0) || (exit_status > PCMK_LSB_NOT_RUNNING)) {
295 return PCMK_OCF_UNKNOWN_ERROR;
296 }
297 return (enum ocf_exitcode) exit_status;
298 }
299
300
301 switch (exit_status) {
302 case PCMK_LSB_STATUS_OK:
303 return PCMK_OCF_OK;
304
305 case PCMK_LSB_STATUS_NOT_INSTALLED:
306 return PCMK_OCF_NOT_INSTALLED;
307
308 case PCMK_LSB_STATUS_INSUFFICIENT_PRIV:
309 return PCMK_OCF_INSUFFICIENT_PRIV;
310
311 case PCMK_LSB_STATUS_VAR_PID:
312 case PCMK_LSB_STATUS_VAR_LOCK:
313 case PCMK_LSB_STATUS_NOT_RUNNING:
314 return PCMK_OCF_NOT_RUNNING;
315
316 default:
317 return PCMK_OCF_UNKNOWN_ERROR;
318 }
319 }