diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md index 89ec60e7e..7133ba4f6 100644 --- a/doc/12-icinga2-api.md +++ b/doc/12-icinga2-api.md @@ -1381,7 +1381,8 @@ Stages provide a way to maintain multiple configuration versions for a package. Send a `POST` request to the URL endpoint `/v1/config/stages` and add the name of an existing configuration package to the URL path (e.g. `example-cmdb`). The request body must contain the `files` attribute with the value being -a dictionary of file targets and their content. +a dictionary of file targets and their content. You can also specify an optional `reload` attribute +that will tell icinga2 to reload after stage config validation. By default this is set to `true`. The file path requires one of these two directories inside its path: @@ -1412,7 +1413,7 @@ intentional. "code": 200.0, "package": "example-cmdb", "stage": "example.localdomain-1441625839-0", - "status": "Created stage." + "status": "Created stage. Icinga2 will reload." } ] } @@ -1420,9 +1421,10 @@ intentional. The Icinga 2 API returns the `package` name this stage was created for, and also generates a unique name for the `stage` attribute you'll need for later requests. -Icinga 2 automatically restarts the daemon in order to activate the new config stage. -If the validation for the new config stage failed, the old stage and its configuration objects -will remain active. +Icinga 2 automatically restarts the daemon in order to activate the new config stage. This +can be disabled by setting `reload` to `false` in the request. +If the validation for the new config stage failed, the old stage +and its configuration objects will remain active. > **Note** > diff --git a/lib/remote/configpackageutility.cpp b/lib/remote/configpackageutility.cpp index 9c0d1bbf3..024b01a2c 100644 --- a/lib/remote/configpackageutility.cpp +++ b/lib/remote/configpackageutility.cpp @@ -176,7 +176,7 @@ void ConfigPackageUtility::ActivateStage(const String& packageName, const String WritePackageConfig(packageName); } -void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName) +void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload) { String logFile = GetPackageDir() + "/" + packageName + "/" + stageName + "/startup.log"; std::ofstream fpLog(logFile.CStr(), std::ofstream::out | std::ostream::binary | std::ostream::trunc); @@ -191,7 +191,9 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con /* validation went fine, activate stage and reload */ if (pr.ExitStatus == 0) { ActivateStage(packageName, stageName); - Application::RequestRestart(); + + if (reload) + Application::RequestRestart(); } else { Log(LogCritical, "ConfigPackageUtility") << "Config validation failed for package '" @@ -199,7 +201,7 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con } } -void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName) +void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload) { VERIFY(Application::GetArgC() >= 1); @@ -213,7 +215,7 @@ void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, cons Process::Ptr process = new Process(Process::PrepareCommand(args)); process->SetTimeout(300); - process->Run(boost::bind(&TryActivateStageCallback, _1, packageName, stageName)); + process->Run(boost::bind(&TryActivateStageCallback, _1, packageName, stageName, reload)); } void ConfigPackageUtility::DeleteStage(const String& packageName, const String& stageName) diff --git a/lib/remote/configpackageutility.hpp b/lib/remote/configpackageutility.hpp index f6f8c4cb2..80813879d 100644 --- a/lib/remote/configpackageutility.hpp +++ b/lib/remote/configpackageutility.hpp @@ -51,7 +51,7 @@ public: static std::vector GetStages(const String& packageName); static String GetActiveStage(const String& packageName); static void ActivateStage(const String& packageName, const String& stageName); - static void AsyncTryActivateStage(const String& packageName, const String& stageName); + static void AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload); static std::vector > GetFiles(const String& packageName, const String& stageName); @@ -65,7 +65,7 @@ private: static void WritePackageConfig(const String& packageName); static void WriteStageConfig(const String& packageName, const String& stageName); - static void TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName); + static void TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload); }; } diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index ee2fc2374..fa1e3309f 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -98,6 +98,10 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ if (!ConfigPackageUtility::ValidateName(packageName)) return HttpUtility::SendJsonError(response, 400, "Invalid package name."); + bool reload = true; + if (params->Contains("reload")) + reload = HttpUtility::GetLastParameter(params, "reload"); + Dictionary::Ptr files = params->Get("files"); String stageName; @@ -109,7 +113,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ stageName = ConfigPackageUtility::CreateStage(packageName, files); /* validate the config. on success, activate stage and reload */ - ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName); + ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, reload); } catch (const std::exception& ex) { return HttpUtility::SendJsonError(response, 500, "Stage creation failed.", @@ -118,10 +122,13 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ Dictionary::Ptr result1 = new Dictionary(); + String responseStatus = "Created stage. "; + responseStatus += (reload ? " Icinga2 will reload." : " Icinga2 reload skipped."); + result1->Set("package", packageName); result1->Set("stage", stageName); result1->Set("code", 200); - result1->Set("status", "Created stage."); + result1->Set("status", responseStatus); Array::Ptr results = new Array(); results->Add(result1);