pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
services_lsb.c
Go to the documentation of this file.
1 /*
2  * Copyright 2010-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #ifndef _GNU_SOURCE
11 # define _GNU_SOURCE
12 #endif
13 
14 #include <stdio.h>
15 #include <errno.h>
16 #include <sys/stat.h>
17 
18 #include <crm/crm.h>
19 #include <crm/services.h>
20 #include "services_private.h"
21 #include "services_lsb.h"
22 
23 #define lsb_metadata_template \
24  "<?xml version='1.0'?>\n" \
25  "<!DOCTYPE resource-agent SYSTEM 'ra-api-1.dtd'>\n" \
26  "<resource-agent name='%s' version='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
27  " <version>1.0</version>\n" \
28  " <longdesc lang='en'>\n" \
29  "%s" \
30  " </longdesc>\n" \
31  " <shortdesc lang='en'>%s</shortdesc>\n" \
32  " <parameters>\n" \
33  " </parameters>\n" \
34  " <actions>\n" \
35  " <action name='meta-data' timeout='5' />\n" \
36  " <action name='start' timeout='15' />\n" \
37  " <action name='stop' timeout='15' />\n" \
38  " <action name='status' timeout='15' />\n" \
39  " <action name='restart' timeout='15' />\n" \
40  " <action name='force-reload' timeout='15' />\n" \
41  " <action name='monitor' timeout='15' interval='15' />\n" \
42  " </actions>\n" \
43  " <special tag='LSB'>\n" \
44  " <Provides>%s</Provides>\n" \
45  " <Required-Start>%s</Required-Start>\n" \
46  " <Required-Stop>%s</Required-Stop>\n" \
47  " <Should-Start>%s</Should-Start>\n" \
48  " <Should-Stop>%s</Should-Stop>\n" \
49  " <Default-Start>%s</Default-Start>\n" \
50  " <Default-Stop>%s</Default-Stop>\n" \
51  " </special>\n" \
52  "</resource-agent>\n"
53 
54 /* See "Comment Conventions for Init Scripts" in the LSB core specification at:
55  * http://refspecs.linuxfoundation.org/lsb.shtml
56  */
57 #define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
58 #define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
59 #define PROVIDES "# Provides:"
60 #define REQ_START "# Required-Start:"
61 #define REQ_STOP "# Required-Stop:"
62 #define SHLD_START "# Should-Start:"
63 #define SHLD_STOP "# Should-Stop:"
64 #define DFLT_START "# Default-Start:"
65 #define DFLT_STOP "# Default-Stop:"
66 #define SHORT_DSCR "# Short-Description:"
67 #define DESCRIPTION "# Description:"
68 
69 #define lsb_meta_helper_free_value(m) \
70  do { \
71  if ((m) != NULL) { \
72  xmlFree(m); \
73  (m) = NULL; \
74  } \
75  } while(0)
76 
87 static inline gboolean
88 lsb_meta_helper_get_value(const char *line, char **value, const char *prefix)
89 {
90  if (!*value && crm_starts_with(line, prefix)) {
91  *value = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST line+strlen(prefix));
92  return TRUE;
93  }
94  return FALSE;
95 }
96 
97 #define DESC_MAX 2048
98 
99 int
100 services__get_lsb_metadata(const char *type, char **output)
101 {
102  char ra_pathname[PATH_MAX] = { 0, };
103  FILE *fp = NULL;
104  char buffer[1024] = { 0, };
105  char *provides = NULL;
106  char *req_start = NULL;
107  char *req_stop = NULL;
108  char *shld_start = NULL;
109  char *shld_stop = NULL;
110  char *dflt_start = NULL;
111  char *dflt_stop = NULL;
112  char *s_dscrpt = NULL;
113  char *xml_l_dscrpt = NULL;
114  int offset = 0;
115  bool in_header = FALSE;
116  char description[DESC_MAX] = { 0, };
117 
118  if (type[0] == '/') {
119  snprintf(ra_pathname, sizeof(ra_pathname), "%s", type);
120  } else {
121  snprintf(ra_pathname, sizeof(ra_pathname), "%s/%s",
122  LSB_ROOT_DIR, type);
123  }
124 
125  crm_trace("Looking into %s", ra_pathname);
126  fp = fopen(ra_pathname, "r");
127  if (fp == NULL) {
128  return -errno;
129  }
130 
131  /* Enter into the LSB-compliant comment block */
132  while (fgets(buffer, sizeof(buffer), fp)) {
133 
134  // Ignore lines up to and including the block delimiter
136  in_header = TRUE;
137  continue;
138  }
139  if (!in_header) {
140  continue;
141  }
142 
143  /* Assume each of the following eight arguments contain one line */
144  if (lsb_meta_helper_get_value(buffer, &provides, PROVIDES)) {
145  continue;
146  }
147  if (lsb_meta_helper_get_value(buffer, &req_start, REQ_START)) {
148  continue;
149  }
150  if (lsb_meta_helper_get_value(buffer, &req_stop, REQ_STOP)) {
151  continue;
152  }
153  if (lsb_meta_helper_get_value(buffer, &shld_start, SHLD_START)) {
154  continue;
155  }
156  if (lsb_meta_helper_get_value(buffer, &shld_stop, SHLD_STOP)) {
157  continue;
158  }
159  if (lsb_meta_helper_get_value(buffer, &dflt_start, DFLT_START)) {
160  continue;
161  }
162  if (lsb_meta_helper_get_value(buffer, &dflt_stop, DFLT_STOP)) {
163  continue;
164  }
165  if (lsb_meta_helper_get_value(buffer, &s_dscrpt, SHORT_DSCR)) {
166  continue;
167  }
168 
169  /* Long description may cross multiple lines */
170  if ((offset == 0) // haven't already found long description
171  && crm_starts_with(buffer, DESCRIPTION)) {
172  bool processed_line = TRUE;
173 
174  // Get remainder of description line itself
175  offset += snprintf(description, DESC_MAX, "%s",
176  buffer + strlen(DESCRIPTION));
177 
178  // Read any continuation lines of the description
179  buffer[0] = '\0';
180  while (fgets(buffer, sizeof(buffer), fp)) {
181  if (crm_starts_with(buffer, "# ")
182  || crm_starts_with(buffer, "#\t")) {
183  /* '#' followed by a tab or more than one space indicates a
184  * continuation of the long description.
185  */
186  offset += snprintf(description + offset, DESC_MAX - offset,
187  "%s", buffer + 1);
188  } else {
189  /* This line is not part of the long description,
190  * so continue with normal processing.
191  */
192  processed_line = FALSE;
193  break;
194  }
195  }
196 
197  // Make long description safe to use in XML
198  xml_l_dscrpt = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST(description));
199 
200  if (processed_line) {
201  // We grabbed the line into the long description
202  continue;
203  }
204  }
205 
206  // Stop if we leave the header block
208  break;
209  }
210  if (buffer[0] != '#') {
211  break;
212  }
213  }
214  fclose(fp);
215 
217  (xml_l_dscrpt? xml_l_dscrpt : type),
218  (s_dscrpt? s_dscrpt : type),
219  (provides? provides : ""),
220  (req_start? req_start : ""),
221  (req_stop? req_stop : ""),
222  (shld_start? shld_start : ""),
223  (shld_stop? shld_stop : ""),
224  (dflt_start? dflt_start : ""),
225  (dflt_stop? dflt_stop : ""));
226 
227  lsb_meta_helper_free_value(xml_l_dscrpt);
228  lsb_meta_helper_free_value(s_dscrpt);
229  lsb_meta_helper_free_value(provides);
230  lsb_meta_helper_free_value(req_start);
231  lsb_meta_helper_free_value(req_stop);
232  lsb_meta_helper_free_value(shld_start);
233  lsb_meta_helper_free_value(shld_stop);
234  lsb_meta_helper_free_value(dflt_start);
235  lsb_meta_helper_free_value(dflt_stop);
236 
237  crm_trace("Created fake metadata: %llu",
238  (unsigned long long) strlen(*output));
239  return pcmk_ok;
240 }
241 
242 GList *
244 {
245  return services_os_get_directory_list(LSB_ROOT_DIR, TRUE, TRUE);
246 }
247 
248 char *
249 services__lsb_agent_path(const char *agent)
250 {
251  return (*agent == '/')? strdup(agent)
252  : crm_strdup_printf("%s/%s", LSB_ROOT_DIR, agent);
253 }
254 
255 bool
256 services__lsb_agent_exists(const char *agent)
257 {
258  bool rc = FALSE;
259  struct stat st;
260  char *path = services__lsb_agent_path(agent);
261 
262  rc = (stat(path, &st) == 0);
263  free(path);
264  return rc;
265 }
266 
267 /* The remaining functions below are not used by the Pacemaker code base, and
268  * are provided for API compatibility only.
269  *
270  * @TODO They should be removed or renamed.
271  */
272 
273 svc_action_t *
274 services_action_create(const char *name, const char *action,
275  guint interval_ms, int timeout)
276 {
277  return resources_action_create(name, PCMK_RESOURCE_CLASS_LSB, NULL, name,
278  action, interval_ms, timeout, NULL, 0);
279 }
280 
281 GList *
283 {
285 }
286 
Services API.
#define DFLT_STOP
Definition: services_lsb.c:65
A dumping ground.
#define LSB_INITSCRIPT_INFOEND_TAG
Definition: services_lsb.c:58
svc_action_t * services_action_create(const char *name, const char *action, guint interval_ms, int timeout)
Definition: services_lsb.c:274
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, guint interval_ms, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
Definition: services.c:159
#define DESCRIPTION
Definition: services_lsb.c:67
#define SHORT_DSCR
Definition: services_lsb.c:66
bool crm_starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:259
char * services__lsb_agent_path(const char *agent)
Definition: services_lsb.c:249
#define REQ_STOP
Definition: services_lsb.c:61
#define lsb_meta_helper_free_value(m)
Definition: services_lsb.c:69
int services__get_lsb_metadata(const char *type, char **output)
Definition: services_lsb.c:100
GList * services__list_lsb_agents(void)
Definition: services_lsb.c:243
#define DESC_MAX
Definition: services_lsb.c:97
#define crm_trace(fmt, args...)
Definition: logging.h:246
#define LSB_INITSCRIPT_INFOBEGIN_TAG
Definition: services_lsb.c:57
#define DFLT_START
Definition: services_lsb.c:64
#define LSB_ROOT_DIR
Definition: services.h:34
#define SHLD_START
Definition: services_lsb.c:62
#define REQ_START
Definition: services_lsb.c:60
#define PCMK_RESOURCE_CLASS_LSB
Definition: services.h:45
#define PROVIDES
Definition: services_lsb.c:59
#define lsb_metadata_template
Definition: services_lsb.c:23
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
Definition: services.c:1009
#define pcmk_ok
Definition: results.h:57
GList * services_list(void)
Definition: services_lsb.c:282
#define SHLD_STOP
Definition: services_lsb.c:63
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
bool services__lsb_agent_exists(const char *agent)
Definition: services_lsb.c:256
enum crm_ais_msg_types type
Definition: internal.h:85