Line data Source code
1 : /*
2 : * Copyright 2012-2022 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 : #include <stdio.h>
13 : #include <string.h>
14 : #include <sys/stat.h>
15 :
16 : #include <crm/crm.h>
17 : #include <crm/services.h>
18 : #include <crm/services_internal.h>
19 :
20 : #include "services_private.h"
21 : #include "services_ocf.h"
22 :
23 : GList *
24 0 : resources_os_list_ocf_providers(void)
25 : {
26 0 : return get_directory_list(OCF_RA_PATH, FALSE, TRUE);
27 : }
28 :
29 : static GList *
30 0 : services_os_get_directory_list_provider(const char *root, const char *provider,
31 : gboolean files, gboolean executable)
32 : {
33 0 : GList *result = NULL;
34 0 : char *dirs = strdup(root);
35 0 : char *dir = NULL;
36 : char buffer[PATH_MAX];
37 :
38 0 : if (pcmk__str_empty(dirs)) {
39 0 : free(dirs);
40 0 : return result;
41 : }
42 :
43 0 : for (dir = strtok(dirs, ":"); dir != NULL; dir = strtok(NULL, ":")) {
44 0 : GList *tmp = NULL;
45 :
46 0 : sprintf(buffer, "%s/%s", dir, provider);
47 0 : tmp = services_os_get_single_directory_list(buffer, files, executable);
48 :
49 0 : if (tmp) {
50 0 : result = g_list_concat(result, tmp);
51 : }
52 : }
53 :
54 0 : free(dirs);
55 :
56 0 : return result;
57 : }
58 :
59 : GList *
60 0 : resources_os_list_ocf_agents(const char *provider)
61 : {
62 0 : GList *gIter = NULL;
63 0 : GList *result = NULL;
64 0 : GList *providers = NULL;
65 :
66 0 : if (provider) {
67 0 : return services_os_get_directory_list_provider(OCF_RA_PATH, provider,
68 : TRUE, TRUE);
69 : }
70 :
71 0 : providers = resources_os_list_ocf_providers();
72 0 : for (gIter = providers; gIter != NULL; gIter = gIter->next) {
73 0 : GList *tmp1 = result;
74 0 : GList *tmp2 = resources_os_list_ocf_agents(gIter->data);
75 :
76 0 : if (tmp2) {
77 0 : result = g_list_concat(tmp1, tmp2);
78 : }
79 : }
80 0 : g_list_free_full(providers, free);
81 0 : return result;
82 : }
83 :
84 : gboolean
85 0 : services__ocf_agent_exists(const char *provider, const char *agent)
86 : {
87 0 : gboolean rc = FALSE;
88 : struct stat st;
89 0 : char *dirs = strdup(OCF_RA_PATH);
90 0 : char *dir = NULL;
91 0 : char *buf = NULL;
92 :
93 0 : if (provider == NULL || agent == NULL || pcmk__str_empty(dirs)) {
94 0 : free(dirs);
95 0 : return rc;
96 : }
97 :
98 0 : for (dir = strtok(dirs, ":"); dir != NULL; dir = strtok(NULL, ":")) {
99 0 : buf = crm_strdup_printf("%s/%s/%s", dir, provider, agent);
100 0 : if (stat(buf, &st) == 0) {
101 0 : free(buf);
102 0 : rc = TRUE;
103 0 : break;
104 : }
105 :
106 0 : free(buf);
107 : }
108 :
109 0 : free(dirs);
110 :
111 0 : return rc;
112 : }
113 :
114 : /*!
115 : * \internal
116 : * \brief Prepare an OCF action
117 : *
118 : * \param[in,out] op Action to prepare
119 : *
120 : * \return Standard Pacemaker return code
121 : */
122 : int
123 0 : services__ocf_prepare(svc_action_t *op)
124 : {
125 0 : char *dirs = strdup(OCF_RA_PATH);
126 : struct stat st;
127 :
128 0 : if (dirs == NULL) {
129 0 : return ENOMEM;
130 : }
131 :
132 : // Look for agent on path
133 0 : for (char *dir = strtok(dirs, ":"); dir != NULL; dir = strtok(NULL, ":")) {
134 0 : char *buf = crm_strdup_printf("%s/%s/%s", dir, op->provider, op->agent);
135 :
136 0 : if (stat(buf, &st) == 0) {
137 0 : op->opaque->exec = buf;
138 0 : break;
139 : }
140 0 : free(buf);
141 : }
142 0 : free(dirs);
143 :
144 0 : if (op->opaque->exec == NULL) {
145 0 : return ENOENT;
146 : }
147 :
148 0 : op->opaque->args[0] = strdup(op->opaque->exec);
149 0 : op->opaque->args[1] = strdup(op->action);
150 0 : if ((op->opaque->args[0] == NULL) || (op->opaque->args[1] == NULL)) {
151 0 : return ENOMEM;
152 : }
153 :
154 0 : return pcmk_rc_ok;
155 : }
156 :
157 : /*!
158 : * \internal
159 : * \brief Map an actual OCF result to a standard OCF result
160 : *
161 : * \param[in] exit_status Actual OCF agent exit status
162 : *
163 : * \return Standard OCF result
164 : */
165 : enum ocf_exitcode
166 0 : services__ocf2ocf(int exit_status)
167 : {
168 0 : switch (exit_status) {
169 0 : case PCMK_OCF_DEGRADED:
170 : case PCMK_OCF_DEGRADED_PROMOTED:
171 0 : break;
172 0 : default:
173 0 : if ((exit_status < 0) || (exit_status > PCMK_OCF_FAILED_PROMOTED)) {
174 0 : exit_status = PCMK_OCF_UNKNOWN_ERROR;
175 : }
176 0 : break;
177 : }
178 0 : return (enum ocf_exitcode) exit_status;
179 : }
|