]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
ARI: Added new functionality to reload a single module. 59/859/3
authorBenjamin Ford <bford@digium.com>
Tue, 14 Jul 2015 18:12:32 +0000 (13:12 -0500)
committerBenjamin Keith Ford <bford@digium.com>
Tue, 14 Jul 2015 18:17:30 +0000 (13:17 -0500)
An http request can be sent to reload an Asterisk module. If the
module can not be reloaded or is not already loaded, an error
response will be returned.

The command "curl -v -u user:pass -X PUT 'http://localhost:8088
/ari/asterisk/modules/{moduleName}'" (or something similar, based
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 reloaded through http requests

ASTERISK-25173

Change-Id: I289188bcae182b2083bdbd9ebfffd50b62f58ae1

CHANGES
include/asterisk/ari.h
res/ari/resource_asterisk.c
res/ari/resource_asterisk.h
res/res_ari.c
res/res_ari_asterisk.c
rest-api/api-docs/asterisk.json

diff --git a/CHANGES b/CHANGES
index 349c2e3eff9180de0b1dc09f271338908459b842..a72c970f6dae4aaada1bb78abc780ac1a3409956 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -194,7 +194,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. Individual modules can be loaded to Asterisk, as
-   well as unloaded.
+   well as unloaded and reloaded.
 
 res_pjsip
 ------------------
index 00769eea56f641cb4a4e63599728c1b8c06c7477..c3df46a2b421cedab0adf1fc01f0432712ec2fde 100644 (file)
@@ -224,6 +224,11 @@ void ast_ari_response_ok(struct ast_ari_response *response,
  */
 void ast_ari_response_no_content(struct ast_ari_response *response);
 
+/*!
+ * \brief Fill in a <tt>Accepted</tt> (202) \a ast_ari_response.
+ */
+void ast_ari_response_accepted(struct ast_ari_response *response);
+
 /*!
  * \brief Fill in a <tt>Created</tt> (201) \a ast_ari_response.
  * \param response Response to fill in.
index 13f459eec3f64d83b644753a4f1946e9aea605eb..e7617913168e998e9c922caed6ce8c73f12ebb2a 100644 (file)
@@ -323,6 +323,56 @@ void ast_ari_asterisk_unload_module(struct ast_variable *headers,
        ast_ari_response_no_content(response);
 }
 
+void ast_ari_asterisk_reload_module(struct ast_variable *headers,
+       struct ast_ari_asterisk_reload_module_args *args,
+       struct ast_ari_response *response)
+{
+       enum ast_module_reload_result reload_result;
+
+       ast_assert(response != NULL);
+
+       if (!ast_module_check(args->module_name)) {
+               ast_ari_response_error(
+                       response, 404, "Not Found",
+                       "Module not found in running modules");
+               return;
+       }
+
+       reload_result = ast_module_reload(args->module_name);
+
+       if (reload_result == AST_MODULE_RELOAD_NOT_FOUND) {
+               ast_ari_response_error(
+                       response, 404, "Not Found",
+                       "Module could not be found");
+               return;
+       } else if (reload_result == AST_MODULE_RELOAD_ERROR) {
+               ast_ari_response_error(
+                       response, 409, "Conflict",
+                       "An unknown error occurred while reloading the module");
+               return;
+       } else if (reload_result == AST_MODULE_RELOAD_IN_PROGRESS) {
+               ast_ari_response_error(
+                       response, 409, "Conflict",
+                       "Another reload is currently in progress");
+               return;
+       } else if (reload_result == AST_MODULE_RELOAD_UNINITIALIZED) {
+               ast_ari_response_error(
+                       response, 409, "Conflict",
+                       "Module has not been initialized");
+               return;
+       } else if (reload_result == AST_MODULE_RELOAD_NOT_IMPLEMENTED) {
+               ast_ari_response_error(
+                       response, 409, "Conflict",
+                       "Module does not support reloading");
+               return;
+       } else if (reload_result == AST_MODULE_RELOAD_QUEUED) {
+               ast_ari_response_accepted(response);
+               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)
index 5e3ff9b158e0545958b56ec5062a197d5e05410e..574d947e4e55736634de329d9fa91d3819dd8319 100644 (file)
@@ -117,6 +117,19 @@ struct ast_ari_asterisk_unload_module_args {
  * \param[out] response HTTP response
  */
 void ast_ari_asterisk_unload_module(struct ast_variable *headers, struct ast_ari_asterisk_unload_module_args *args, struct ast_ari_response *response);
+/*! Argument struct for ast_ari_asterisk_reload_module() */
+struct ast_ari_asterisk_reload_module_args {
+       /*! Module's name */
+       const char *module_name;
+};
+/*!
+ * \brief Reload an Asterisk module.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_asterisk_reload_module(struct ast_variable *headers, struct ast_ari_asterisk_reload_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 */
index bdc4379b2d4bd2bc16a947486d120e8d16281e8e..0575fdecd44c67a231b8019602b4b34bda1b522f 100644 (file)
@@ -284,6 +284,13 @@ void ast_ari_response_no_content(struct ast_ari_response *response)
        response->response_text = "No Content";
 }
 
+void ast_ari_response_accepted(struct ast_ari_response *response)
+{
+       response->message = ast_json_null();
+       response->response_code = 202;
+       response->response_text = "Accepted";
+}
+
 void ast_ari_response_alloc_failed(struct ast_ari_response *response)
 {
        response->message = ast_json_ref(oom_json);
index 41580cbf661113216d7f002239c9e396acf98029..7d938a0a464a42433f1a21b9b405f417b8e5dc8a 100644 (file)
@@ -436,6 +436,66 @@ static void ast_ari_asterisk_unload_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_reload_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_reload_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_reload_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 404: /* Module not found in running modules. */
+       case 409: /* Module could not be reloaded. */
+               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;
 }
@@ -646,6 +706,7 @@ static struct stasis_rest_handlers asterisk_modules_moduleName = {
                [AST_HTTP_GET] = ast_ari_asterisk_get_module_cb,
                [AST_HTTP_POST] = ast_ari_asterisk_load_module_cb,
                [AST_HTTP_DELETE] = ast_ari_asterisk_unload_module_cb,
+               [AST_HTTP_PUT] = ast_ari_asterisk_reload_module_cb,
        },
        .num_children = 0,
        .children = {  }
index 28badce8062cc2b5907ba864ee4794e89e2dced3..c6968a5ba3a47d596064e034e1340e0428b3707d 100644 (file)
                                                        "reason": "Module could not be unloaded."
                                                }
                                        ]
+                               },
+                               {
+                                       "httpMethod": "PUT",
+                                       "summary": "Reload an Asterisk module.",
+                                       "nickname": "reloadModule",
+                                       "responseClass": "void",
+                                       "parameters": [
+                                               {
+                                                       "name": "moduleName",
+                                                       "description": "Module's name",
+                                                       "paramType": "path",
+                                                       "required": true,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
+                                               }
+                                       ],
+                                       "errorResponses": [
+                                               {
+                                                       "code": 404,
+                                                       "reason": "Module not found in running modules."
+                                               },
+                                               {
+                                                       "code": 409,
+                                                       "reason": "Module could not be reloaded."
+                                               }
+                                       ]
                                }
                        ]
                },