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