MXS-1929: Allow service creation at runtime

Services can now be created at runtime. The command to create services is
exposed in the REST API.
This commit is contained in:
Markus Mäkelä 2018-07-18 10:10:10 +03:00
parent 5a40064826
commit 037cedf70e
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
4 changed files with 92 additions and 0 deletions

View File

@ -76,6 +76,7 @@ MXS_BEGIN_DECLS
#define MXS_JSON_PTR_PARAM_SSL_VERIFY_PEER_CERT MXS_JSON_PTR_PARAMETERS "/ssl_verify_peer_certificate"
/** Non-parameter JSON pointers */
#define MXS_JSON_PTR_ROUTER "/data/attributes/router"
#define MXS_JSON_PTR_MODULE "/data/attributes/module"
#define MXS_JSON_PTR_PASSWORD "/data/attributes/password"
#define MXS_JSON_PTR_ACCOUNT "/data/attributes/account"

View File

@ -1078,6 +1078,53 @@ bool runtime_create_filter(const char *name, const char *module, MXS_CONFIG_PARA
return rval;
}
static bool runtime_create_service(const char *name, const char *router, MXS_CONFIG_PARAMETER* params)
{
mxs::SpinLockGuard guard(crt_lock);
bool rval = false;
if (service_find(name) == NULL)
{
SERVICE* service = NULL;
CONFIG_CONTEXT ctx{(char*)""};
ctx.parameters = load_defaults(router, MODULE_FILTER, CN_FILTER);
if (ctx.parameters)
{
for (MXS_CONFIG_PARAMETER* p = params; p; p = p->next)
{
config_replace_param(&ctx, p->name, p->value);
}
if ((service = service_alloc(name, router, ctx.parameters)) == NULL)
{
runtime_error("Could not create service '%s' with module '%s'", name, router);
}
config_parameter_free(ctx.parameters);
}
if (service)
{
if (service_serialize(service))
{
MXS_NOTICE("Created service '%s'", name);
rval = true;
}
else
{
runtime_error("Failed to serialize service '%s'", name);
}
}
}
else
{
runtime_error("Can't create service '%s', it already exists", name);
}
return rval;
}
bool runtime_destroy_service(SERVICE* service)
{
bool rval = false;
@ -1815,6 +1862,28 @@ MXS_FILTER_DEF* runtime_create_filter_from_json(json_t* json)
return rval;
}
SERVICE* runtime_create_service_from_json(json_t* json)
{
SERVICE* rval = NULL;
if (validate_object_json(json, {MXS_JSON_PTR_ROUTER}, {service_to_filter, object_to_server}))
{
const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID));
const char* router = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ROUTER));
MXS_CONFIG_PARAMETER* params = extract_parameters_from_json(json);
if (runtime_create_service(name, router, params))
{
rval = service_find(name);
ss_dassert(rval);
}
config_parameter_free(params);
}
return rval;
}
bool object_to_server_relations(const char* target, json_t* old_json, json_t* new_json)
{
if (mxs_json_pointer(new_json, MXS_JSON_PTR_RELATIONSHIPS) == NULL)

View File

@ -275,6 +275,15 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json);
*/
MXS_FILTER_DEF* runtime_create_filter_from_json(json_t* json);
/**
* @brief Create a new service from JSON
*
* @param json JSON defining the service
*
* @return Created service or NULL on error
*/
SERVICE* runtime_create_service_from_json(json_t* json);
/**
* @brief Alter a monitor using JSON
*

View File

@ -337,6 +337,18 @@ HttpResponse cb_create_filter(const HttpRequest& request)
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
}
HttpResponse cb_create_service(const HttpRequest& request)
{
ss_dassert(request.get_json());
if (runtime_create_service_from_json(request.get_json()))
{
return HttpResponse(MHD_HTTP_NO_CONTENT);
}
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
}
HttpResponse cb_create_service_listener(const HttpRequest& request)
{
SERVICE* service = service_find(request.uri_part(1).c_str());
@ -885,6 +897,7 @@ public:
m_post.push_back(SResource(new Resource(cb_create_server, 1, "servers")));
m_post.push_back(SResource(new Resource(cb_create_monitor, 1, "monitors")));
m_post.push_back(SResource(new Resource(cb_create_filter, 1, "filters")));
m_post.push_back(SResource(new Resource(cb_create_service, 1, "services")));
m_post.push_back(SResource(new Resource(cb_create_service_listener, 3,
"services", ":service", "listeners")));
m_post.push_back(SResource(new Resource(cb_create_user, 2, "users", "inet")));