From aa5707b8891119741baae98cf7b51a00c0f99438 Mon Sep 17 00:00:00 2001 From: Benjamin Ford Date: Mon, 13 Jul 2015 16:00:19 -0500 Subject: [PATCH] ARI: Added new functionality to load a single module. An http request can be sent to load an Asterisk module. If the module can not be loaded or is loaded already, an error response will be returned. The command curl -v -u user:pass -X POST 'http://localhost:8088/ari /asterisk/modules/{moduleName}'" (or something similar, depending on configuration) can be run in the terminal to access this new functionality. For more information, see: https://wiki.asterisk.org/wiki.display/~bford/Asterisk+ARI+Resource * Added new ARI functionality * Asterisk modules can be loaded through http requests ASTERISK-25173 Change-Id: I9e05d5b8c5c666ecfef341504f9edc1aa84fda33 --- CHANGES | 2 +- res/ari/resource_asterisk.c | 37 ++++++++++++++++++++ res/ari/resource_asterisk.h | 13 +++++++ res/res_ari_asterisk.c | 60 +++++++++++++++++++++++++++++++++ rest-api/api-docs/asterisk.json | 22 ++++++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index dcec202fbc..97190afa28 100644 --- a/CHANGES +++ b/CHANGES @@ -193,7 +193,7 @@ ARI ------------------ * A new feature has been added that enables the retrieval of modules and module information through an HTTP request. Information on a single module - can be also be retrieved. + can be also be retrieved. Individual modules can be loaded to Asterisk. res_pjsip ------------------ diff --git a/res/ari/resource_asterisk.c b/res/ari/resource_asterisk.c index ea1a073b02..768f7711de 100644 --- a/res/ari/resource_asterisk.c +++ b/res/ari/resource_asterisk.c @@ -258,6 +258,43 @@ void ast_ari_asterisk_get_module(struct ast_variable *headers, ast_ari_response_ok(response, json); } +void ast_ari_asterisk_load_module(struct ast_variable *headers, + struct ast_ari_asterisk_load_module_args *args, + struct ast_ari_response *response) +{ + enum ast_module_load_result load_result; + + ast_assert(response != NULL); + + if (ast_module_check(args->module_name)) { + ast_ari_response_error( + response, 409, "Conflict", + "Module is already loaded"); + return; + } + + load_result = ast_load_resource(args->module_name); + + if (load_result == AST_MODULE_LOAD_DECLINE) { + ast_ari_response_error( + response, 409, "Conflict", + "Module load declined"); + return; + } else if (load_result == AST_MODULE_LOAD_SKIP) { + ast_ari_response_error( + response, 409, "Conflict", + "Module was skipped"); + return; + } else if (load_result == AST_MODULE_LOAD_FAILURE) { + ast_ari_response_error( + response, 409, "Conflict", + "Module could not be loaded properly"); + return; + } + + ast_ari_response_no_content(response); +} + void ast_ari_asterisk_get_global_var(struct ast_variable *headers, struct ast_ari_asterisk_get_global_var_args *args, struct ast_ari_response *response) diff --git a/res/ari/resource_asterisk.h b/res/ari/resource_asterisk.h index 8689f3ec10..5846a7120e 100644 --- a/res/ari/resource_asterisk.h +++ b/res/ari/resource_asterisk.h @@ -91,6 +91,19 @@ struct ast_ari_asterisk_get_module_args { * \param[out] response HTTP response */ void ast_ari_asterisk_get_module(struct ast_variable *headers, struct ast_ari_asterisk_get_module_args *args, struct ast_ari_response *response); +/*! Argument struct for ast_ari_asterisk_load_module() */ +struct ast_ari_asterisk_load_module_args { + /*! Module's name */ + const char *module_name; +}; +/*! + * \brief Load an Asterisk module. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void ast_ari_asterisk_load_module(struct ast_variable *headers, struct ast_ari_asterisk_load_module_args *args, struct ast_ari_response *response); /*! Argument struct for ast_ari_asterisk_get_global_var() */ struct ast_ari_asterisk_get_global_var_args { /*! The variable to get */ diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c index 214bb2fea1..cb9018bd3a 100644 --- a/res/res_ari_asterisk.c +++ b/res/res_ari_asterisk.c @@ -317,6 +317,65 @@ static void ast_ari_asterisk_get_module_cb( } #endif /* AST_DEVMODE */ +fin: __attribute__((unused)) + return; +} +/*! + * \brief Parameter parsing callback for /asterisk/modules/{moduleName}. + * \param get_params GET parameters in the HTTP request. + * \param path_vars Path variables extracted from the request. + * \param headers HTTP headers. + * \param[out] response Response to the HTTP request. + */ +static void ast_ari_asterisk_load_module_cb( + struct ast_tcptls_session_instance *ser, + struct ast_variable *get_params, struct ast_variable *path_vars, + struct ast_variable *headers, struct ast_ari_response *response) +{ + struct ast_ari_asterisk_load_module_args args = {}; + struct ast_variable *i; + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); +#if defined(AST_DEVMODE) + int is_valid; + int code; +#endif /* AST_DEVMODE */ + + for (i = path_vars; i; i = i->next) { + if (strcmp(i->name, "moduleName") == 0) { + args.module_name = (i->value); + } else + {} + } + ast_ari_asterisk_load_module(headers, &args, response); +#if defined(AST_DEVMODE) + code = response->response_code; + + switch (code) { + case 0: /* Implementation is still a stub, or the code wasn't set */ + is_valid = response->message == NULL; + break; + case 500: /* Internal Server Error */ + case 501: /* Not Implemented */ + case 409: /* Module could not be loaded. */ + is_valid = 1; + break; + default: + if (200 <= code && code <= 299) { + is_valid = ast_ari_validate_void( + response->message); + } else { + ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code); + is_valid = 0; + } + } + + if (!is_valid) { + ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n"); + ast_ari_response_error(response, 500, + "Internal Server Error", "Response validation failed"); + } +#endif /* AST_DEVMODE */ + fin: __attribute__((unused)) return; } @@ -525,6 +584,7 @@ static struct stasis_rest_handlers asterisk_modules_moduleName = { .is_wildcard = 1, .callbacks = { [AST_HTTP_GET] = ast_ari_asterisk_get_module_cb, + [AST_HTTP_POST] = ast_ari_asterisk_load_module_cb, }, .num_children = 0, .children = { } diff --git a/rest-api/api-docs/asterisk.json b/rest-api/api-docs/asterisk.json index 76c834e45f..dcbfb2c7b5 100644 --- a/rest-api/api-docs/asterisk.json +++ b/rest-api/api-docs/asterisk.json @@ -79,6 +79,28 @@ "reason": "Module information could not be retrieved." } ] + }, + { + "httpMethod": "POST", + "summary": "Load an Asterisk module.", + "nickname": "loadModule", + "responseClass": "void", + "parameters": [ + { + "name": "moduleName", + "description": "Module's name", + "paramType": "path", + "required": true, + "allowMultiple": false, + "dataType": "string" + } + ], + "errorResponses": [ + { + "code": 409, + "reason": "Module could not be loaded." + } + ] } ] },