mirror of https://github.com/Icinga/icinga2.git
Merge pull request #5620 from Icinga/fix/api-staging-3668
WIP: Ensure that the REST API config package/stage creation is atomic
This commit is contained in:
commit
2bbb5366fd
|
@ -102,11 +102,14 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri
|
|||
bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName,
|
||||
const String& config, const Array::Ptr& errors)
|
||||
{
|
||||
if (!ConfigPackageUtility::PackageExists("_api")) {
|
||||
ConfigPackageUtility::CreatePackage("_api");
|
||||
{
|
||||
boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex());
|
||||
if (!ConfigPackageUtility::PackageExists("_api")) {
|
||||
ConfigPackageUtility::CreatePackage("_api");
|
||||
|
||||
String stage = ConfigPackageUtility::CreateStage("_api");
|
||||
ConfigPackageUtility::ActivateStage("_api", stage);
|
||||
String stage = ConfigPackageUtility::CreateStage("_api");
|
||||
ConfigPackageUtility::ActivateStage("_api", stage);
|
||||
}
|
||||
}
|
||||
|
||||
String path = GetObjectConfigPath(type, fullName);
|
||||
|
@ -240,4 +243,3 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cas
|
|||
|
||||
return DeleteObjectHelper(object, cascade, errors);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,12 +53,15 @@ void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& req
|
|||
|
||||
Array::Ptr results = new Array();
|
||||
|
||||
for (const String& package : packages) {
|
||||
Dictionary::Ptr packageInfo = new Dictionary();
|
||||
packageInfo->Set("name", package);
|
||||
packageInfo->Set("stages", Array::FromVector(ConfigPackageUtility::GetStages(package)));
|
||||
packageInfo->Set("active-stage", ConfigPackageUtility::GetActiveStage(package));
|
||||
results->Add(packageInfo);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex());
|
||||
for (const String& package : packages) {
|
||||
Dictionary::Ptr packageInfo = new Dictionary();
|
||||
packageInfo->Set("name", package);
|
||||
packageInfo->Set("stages", Array::FromVector(ConfigPackageUtility::GetStages(package)));
|
||||
packageInfo->Set("active-stage", ConfigPackageUtility::GetActiveStage(package));
|
||||
results->Add(packageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary::Ptr result = new Dictionary();
|
||||
|
@ -85,6 +88,7 @@ void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& re
|
|||
Dictionary::Ptr result1 = new Dictionary();
|
||||
|
||||
try {
|
||||
boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex());
|
||||
ConfigPackageUtility::CreatePackage(packageName);
|
||||
} catch (const std::exception& ex) {
|
||||
HttpUtility::SendJsonError(response, 500, "Could not create package.",
|
||||
|
|
|
@ -190,7 +190,10 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con
|
|||
|
||||
/* validation went fine, activate stage and reload */
|
||||
if (pr.ExitStatus == 0) {
|
||||
ActivateStage(packageName, stageName);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(GetStaticMutex());
|
||||
ActivateStage(packageName, stageName);
|
||||
}
|
||||
|
||||
if (reload)
|
||||
Application::RequestRestart();
|
||||
|
@ -317,3 +320,8 @@ bool ConfigPackageUtility::ValidateName(const String& name)
|
|||
return (!boost::regex_search(name.GetData(), what, expr));
|
||||
}
|
||||
|
||||
boost::mutex& ConfigPackageUtility::GetStaticMutex(void)
|
||||
{
|
||||
static boost::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
static bool ContainsDotDot(const String& path);
|
||||
static bool ValidateName(const String& name);
|
||||
|
||||
static boost::mutex& GetStaticMutex(void);
|
||||
|
||||
private:
|
||||
static void CollectDirNames(const String& path, std::vector<String>& dirs);
|
||||
static void CollectPaths(const String& path, std::vector<std::pair<String, bool> >& paths);
|
||||
|
|
|
@ -110,6 +110,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ
|
|||
if (!files)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter 'files' must be specified."));
|
||||
|
||||
boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex());
|
||||
stageName = ConfigPackageUtility::CreateStage(packageName, files);
|
||||
|
||||
/* validate the config. on success, activate stage and reload */
|
||||
|
|
Loading…
Reference in New Issue