1 /* 2 * Copyright 2010-2023 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 #ifndef PCMK__CRM_SERVICES__H 11 # define PCMK__CRM_SERVICES__H 12 13 14 # include <glib.h> 15 # include <stdio.h> 16 # include <stdint.h> 17 # include <string.h> 18 # include <stdbool.h> 19 # include <sys/types.h> 20 21 # include <crm_config.h> // OCF_ROOT_DIR 22 # include <crm/common/agents.h> 23 # include <crm/common/results.h> 24 25 #ifdef __cplusplus 26 extern "C" { 27 #endif 28 29 /*! 30 * \file 31 * \brief Services API 32 * \ingroup core 33 */ 34 35 /* TODO: Autodetect these two ?*/ 36 # ifndef SYSTEMCTL 37 # define SYSTEMCTL "/bin/systemctl" 38 # endif 39 40 /* This is the string passed in the OCF_EXIT_REASON_PREFIX environment variable. 41 * The stderr output that occurs after this prefix is encountered is considered 42 * the exit reason for a completed operation. 43 */ 44 #define PCMK_OCF_REASON_PREFIX "ocf-exit-reason:" 45 46 // Agent version to use if agent doesn't specify one 47 #define PCMK_DEFAULT_AGENT_VERSION "0.1" 48 49 enum lsb_exitcode { 50 PCMK_LSB_OK = 0, 51 PCMK_LSB_UNKNOWN_ERROR = 1, 52 PCMK_LSB_INVALID_PARAM = 2, 53 PCMK_LSB_UNIMPLEMENT_FEATURE = 3, 54 PCMK_LSB_INSUFFICIENT_PRIV = 4, 55 PCMK_LSB_NOT_INSTALLED = 5, 56 PCMK_LSB_NOT_CONFIGURED = 6, 57 PCMK_LSB_NOT_RUNNING = 7, 58 }; 59 60 // LSB uses different return codes for status actions 61 enum lsb_status_exitcode { 62 PCMK_LSB_STATUS_OK = 0, 63 PCMK_LSB_STATUS_VAR_PID = 1, 64 PCMK_LSB_STATUS_VAR_LOCK = 2, 65 PCMK_LSB_STATUS_NOT_RUNNING = 3, 66 PCMK_LSB_STATUS_UNKNOWN = 4, 67 68 /* custom codes should be in the 150-199 range reserved for application use */ 69 PCMK_LSB_STATUS_NOT_INSTALLED = 150, 70 PCMK_LSB_STATUS_INSUFFICIENT_PRIV = 151, 71 }; 72 73 //!@{ 74 //! \deprecated Do not use 75 76 enum nagios_exitcode { 77 NAGIOS_STATE_OK = 0, 78 NAGIOS_STATE_WARNING = 1, 79 NAGIOS_STATE_CRITICAL = 2, 80 NAGIOS_STATE_UNKNOWN = 3, 81 82 /* This is a custom Pacemaker value (not a nagios convention), used as an 83 * intermediate value between the services library and the executor, so the 84 * executor can map it to the corresponding OCF code. 85 */ 86 NAGIOS_INSUFFICIENT_PRIV = 100, 87 88 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 89 NAGIOS_STATE_DEPENDENT = 4, 90 NAGIOS_NOT_INSTALLED = 101, 91 #endif 92 }; 93 94 //!@} 95 96 enum svc_action_flags { 97 /* On timeout, only kill pid, do not kill entire pid group */ 98 SVC_ACTION_LEAVE_GROUP = 0x01, 99 SVC_ACTION_NON_BLOCKED = 0x02, 100 }; 101 102 typedef struct svc_action_private_s svc_action_private_t; 103 104 /*! 105 * \brief Object for executing external actions 106 * 107 * \note This object should never be instantiated directly, but instead created 108 * using one of the constructor functions (resources_action_create() for 109 * resource agents, services_alert_create() for alert agents, or 110 * services_action_create_generic() for generic executables). Similarly, 111 * do not use sizeof() on this struct. 112 */ 113 /* 114 * NOTE: Internally, services__create_resource_action() is preferable to 115 * resources_action_create(). 116 */ 117 typedef struct svc_action_s { 118 /*! Operation key (<resource>_<action>_<interval>) for resource actions, 119 * XML ID for alert actions, or NULL for generic actions 120 */ 121 char *id; 122 123 //! XML ID of resource being executed for resource actions, otherwise NULL 124 char *rsc; 125 126 //! Name of action being executed for resource actions, otherwise NULL 127 char *action; 128 129 //! Action interval for recurring resource actions, otherwise 0 130 guint interval_ms; 131 132 //! Resource standard for resource actions, otherwise NULL 133 char *standard; 134 135 //! Resource provider for resource actions that require it, otherwise NULL 136 char *provider; 137 138 //! Resource agent name for resource actions, otherwise NULL 139 char *agent; 140 141 int timeout; //!< Action timeout (in milliseconds) 142 143 /*! A hash table of name/value pairs to use as parameters for resource and 144 * alert actions, otherwise NULL. These will be used to set environment 145 * variables for non-fencing resource agents and alert agents, and to send 146 * stdin to fence agents. 147 */ 148 GHashTable *params; 149 150 int rc; //!< Exit status of action (set by library upon completion) 151 152 //!@{ 153 //! This field should be treated as internal to Pacemaker 154 int pid; // Process ID of child 155 int cancel; // Whether this is a cancellation of a recurring action 156 //!@} 157 158 int status; //!< Execution status (enum pcmk_exec_status set by library) 159 160 /*! Action counter (set by library for resource actions, or by caller 161 * otherwise) 162 */ 163 int sequence; 164 165 //!@{ 166 //! This field should be treated as internal to Pacemaker 167 int expected_rc; // Unused 168 int synchronous; // Whether execution should be synchronous (blocking) 169 //!@} 170 171 enum svc_action_flags flags; //!< Flag group of enum svc_action_flags 172 char *stderr_data; //!< Action stderr (set by library) 173 char *stdout_data; //!< Action stdout (set by library) 174 void *cb_data; //!< For caller's use (not used by library) 175 176 //! This field should be treated as internal to Pacemaker 177 svc_action_private_t *opaque; 178 } svc_action_t; 179 180 /*! 181 * \brief Get a list of files or directories in a given path 182 * 183 * \param[in] root Full path to a directory to read 184 * \param[in] files Return list of files if TRUE or directories if FALSE 185 * \param[in] executable If TRUE and files is TRUE, only return executable files 186 * 187 * \return List of what was found as char * items. 188 * \note The caller is responsibile for freeing the result with 189 * g_list_free_full(list, free). 190 */ 191 GList *get_directory_list(const char *root, gboolean files, 192 gboolean executable); 193 194 /*! 195 * \brief Get a list of providers 196 * 197 * \param[in] standard List providers of this resource agent standard 198 * 199 * \return List of providers as char * list items (or NULL if standard does not 200 * support providers) 201 * \note The caller is responsible for freeing the result using 202 * g_list_free_full(list, free). 203 */ 204 GList *resources_list_providers(const char *standard); 205 206 /*! 207 * \brief Get a list of resource agents 208 * 209 * \param[in] standard List agents of this standard (or NULL for all) 210 * \param[in] provider List agents of this provider (or NULL for all) 211 * 212 * \return List of resource agents as char * items. 213 * \note The caller is responsible for freeing the result using 214 * g_list_free_full(list, free). 215 */ 216 GList *resources_list_agents(const char *standard, const char *provider); 217 218 /*! 219 * Get list of available standards 220 * 221 * \return List of resource standards as char * items. 222 * \note The caller is responsible for freeing the result using 223 * g_list_free_full(list, free). 224 */ 225 GList *resources_list_standards(void); 226 227 /*! 228 * \brief Check whether a resource agent exists on the local host 229 * 230 * \param[in] standard Resource agent standard of agent to check 231 * \param[in] provider Provider of agent to check (or NULL) 232 * \param[in] agent Name of agent to check 233 * 234 * \return TRUE if agent exists locally, otherwise FALSE 235 */ 236 gboolean resources_agent_exists(const char *standard, const char *provider, 237 const char *agent); 238 239 /*! 240 * \brief Create a new resource action 241 * 242 * \param[in] name Name of resource that action is for 243 * \param[in] standard Resource agent standard 244 * \param[in] provider Resource agent provider 245 * \param[in] agent Resource agent name 246 * \param[in] action Name of action to create 247 * \param[in] interval_ms How often to repeat action (if 0, execute once) 248 * \param[in] timeout Error if not complete within this time (ms) 249 * \param[in,out] params Action parameters 250 * \param[in] flags Group of enum svc_action_flags 251 * 252 * \return Newly allocated action 253 * \note This function assumes ownership of (and may free) \p params. 254 * \note The caller is responsible for freeing the return value using 255 * services_action_free(). 256 */ 257 svc_action_t *resources_action_create(const char *name, const char *standard, 258 const char *provider, const char *agent, 259 const char *action, guint interval_ms, 260 int timeout, GHashTable *params, 261 enum svc_action_flags flags); 262 263 /*! 264 * \brief Reschedule a recurring action for immediate execution 265 * 266 * \param[in] name Name of resource that action is for 267 * \param[in] action Action's name 268 * \param[in] interval_ms Action's interval (in milliseconds) 269 * 270 * \return TRUE on success, otherwise FALSE 271 */ 272 gboolean services_action_kick(const char *name, const char *action, 273 guint interval_ms); 274 275 const char *resources_find_service_class(const char *agent); 276 277 /*! 278 * \brief Request execution of an arbitrary command 279 * 280 * This API has useful infrastructure in place to be able to run a command 281 * in the background and get notified via a callback when the command finishes. 282 * 283 * \param[in] exec Full path to command executable 284 * \param[in] args NULL-terminated list of arguments to pass to command 285 * 286 * \return Newly allocated action object 287 */ 288 svc_action_t *services_action_create_generic(const char *exec, 289 const char *args[]); 290 291 void services_action_cleanup(svc_action_t *op); 292 void services_action_free(svc_action_t *op); 293 int services_action_user(svc_action_t *op, const char *user); 294 gboolean services_action_sync(svc_action_t *op); 295 296 /*! 297 * \brief Run an action asynchronously, with callback after process is forked 298 * 299 * \param[in,out] op Action to run 300 * \param[in] action_callback Function to call when action completes 301 * (if NULL, any previously set callback will 302 * continue to be used) 303 * \param[in] action_fork_callback Function to call after child process is 304 * forked for action (if NULL, any 305 * previously set callback will continue to 306 * be used) 307 * 308 * \retval TRUE if the caller should not free or otherwise use \p op again, 309 * because one of these conditions is true: 310 * 311 * * \p op is NULL. 312 * * The action was successfully initiated, in which case 313 * \p action_fork_callback has been called, but \p action_callback has 314 * not (it will be called when the action completes). 315 * * The action's ID matched an existing recurring action. The existing 316 * action has taken over the callback and callback data from \p op 317 * and has been re-initiated asynchronously, and \p op has been freed. 318 * * Another action for the same resource is in flight, and \p op will 319 * be blocked until it completes. 320 * * The action could not be initiated, and is either non-recurring or 321 * being cancelled. \p action_fork_callback has not been called, but 322 * \p action_callback has, and \p op has been freed. 323 * 324 * \retval FALSE if \op is still valid, because the action cannot be initiated, 325 * and is a recurring action that is not being cancelled. 326 * \p action_fork_callback has not been called, but \p action_callback 327 * has, and a timer has been set for the next invocation of \p op. 328 */ 329 gboolean services_action_async_fork_notify(svc_action_t *op, 330 void (*action_callback) (svc_action_t *), 331 void (*action_fork_callback) (svc_action_t *)); 332 333 /*! 334 * \brief Request asynchronous execution of an action 335 * 336 * \param[in,out] op Action to execute 337 * \param[in] action_callback Function to call when the action completes 338 * (if NULL, any previously set callback will 339 * continue to be used) 340 * 341 * \retval TRUE if the caller should not free or otherwise use \p op again, 342 * because one of these conditions is true: 343 * 344 * * \p op is NULL. 345 * * The action was successfully initiated, in which case 346 * \p action_callback has not been called (it will be called when the 347 * action completes). 348 * * The action's ID matched an existing recurring action. The existing 349 * action has taken over the callback and callback data from \p op 350 * and has been re-initiated asynchronously, and \p op has been freed. 351 * * Another action for the same resource is in flight, and \p op will 352 * be blocked until it completes. 353 * * The action could not be initiated, and is either non-recurring or 354 * being cancelled. \p action_callback has been called, and \p op has 355 * been freed. 356 * 357 * \retval FALSE if \op is still valid, because the action cannot be initiated, 358 * and is a recurring action that is not being cancelled. 359 * \p action_callback has been called, and a timer has been set for the 360 * next invocation of \p op. 361 */ 362 gboolean services_action_async(svc_action_t *op, 363 void (*action_callback) (svc_action_t *)); 364 365 gboolean services_action_cancel(const char *name, const char *action, 366 guint interval_ms); 367 368 /* functions for alert agents */ 369 svc_action_t *services_alert_create(const char *id, const char *exec, 370 int timeout, GHashTable *params, 371 int sequence, void *cb_data); 372 gboolean services_alert_async(svc_action_t *action, 373 void (*cb)(svc_action_t *op)); 374 375 enum ocf_exitcode services_result2ocf(const char *standard, const char *action, 376 int exit_status); 377 378 static inline const char *services_ocf_exitcode_str(enum ocf_exitcode code) { /* */ 379 switch (code) { 380 case PCMK_OCF_OK: 381 return "ok"; 382 case PCMK_OCF_UNKNOWN_ERROR: 383 return "error"; 384 case PCMK_OCF_INVALID_PARAM: 385 return "invalid parameter"; 386 case PCMK_OCF_UNIMPLEMENT_FEATURE: 387 return "unimplemented feature"; 388 case PCMK_OCF_INSUFFICIENT_PRIV: 389 return "insufficient privileges"; 390 case PCMK_OCF_NOT_INSTALLED: 391 return "not installed"; 392 case PCMK_OCF_NOT_CONFIGURED: 393 return "not configured"; 394 case PCMK_OCF_NOT_RUNNING: 395 return "not running"; 396 case PCMK_OCF_RUNNING_PROMOTED: 397 return "promoted"; 398 case PCMK_OCF_FAILED_PROMOTED: 399 return "promoted (failed)"; 400 case PCMK_OCF_DEGRADED: 401 return "OCF_DEGRADED"; 402 case PCMK_OCF_DEGRADED_PROMOTED: 403 return "promoted (degraded)"; 404 405 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 406 case PCMK_OCF_NOT_SUPPORTED: 407 return "not supported (DEPRECATED STATUS)"; 408 case PCMK_OCF_CANCELLED: 409 return "cancelled (DEPRECATED STATUS)"; 410 case PCMK_OCF_OTHER_ERROR: 411 return "other error (DEPRECATED STATUS)"; 412 case PCMK_OCF_SIGNAL: 413 return "interrupted by signal (DEPRECATED STATUS)"; 414 case PCMK_OCF_PENDING: 415 return "pending (DEPRECATED STATUS)"; 416 case PCMK_OCF_TIMEOUT: 417 return "timeout (DEPRECATED STATUS)"; 418 #endif 419 default: 420 return "unknown"; 421 } 422 } 423 424 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) 425 #include <crm/services_compat.h> 426 #endif 427 428 # ifdef __cplusplus 429 } 430 # endif 431 432 #endif /* __PCMK_SERVICES__ */