Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Worker process doesn't let parallel API package stage updates to complete when terminated #9267

Merged

Conversation

yhabteab
Copy link
Member

@yhabteab yhabteab commented Feb 28, 2022

When the second request isn't finished processing till the new worker process is started and its configs are validated, the old worker is terminated immediately after the new worker becomes ready. When the worker process is terminated, all the worker threads of the Process class that are responsible for processing such requests are also destroyed. Thus, the second API request remains incomplete and produces a package stage without startup logs and status file.

Changes:

Concurrent package updates are strictly prohibited.

To Reproduce

  • First create two different config packages
    • curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/packages/cmdb?pretty=1'
    • curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/packages/test?pretty=1'
  • Next just update these packages asynchronously. You need also to specify different configuration each time so that the reload signal can be triggered internally. You also need to post the requests in a bit order (not strictly simultaneous) so that you can reproduce the issue.
curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/stages/cmdb'  -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { check_command = \"dummy\" }" }, "pretty": true }'
curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/stages/test'  -d '{ "files": { "conf.d/test.conf": "object Host \"test-host\" { check_command = \"dummy\" }" }, "pretty": true }'

fixes #7898

@cla-bot cla-bot bot added the cla/signed label Feb 28, 2022
@icinga-probot icinga-probot bot added area/api REST API bug Something isn't working labels Feb 28, 2022
@yhabteab yhabteab marked this pull request as draft February 28, 2022 16:41
@yhabteab yhabteab changed the title Parallel API package stage updates doesn’t let to finish before terminating worker process Worker process doesn't let parallel API package stage updates to complete when terminated Feb 28, 2022
lib/cli/daemoncommand.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@julianbrost julianbrost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be possible to solve this within ApiListener? Adding this to Process feels somewhat random for me. Possible options:

  • Wait for pending actions in ApiListener::Stop(). You'd have to be careful that you actually reload with a new configuration that's consistent with all the requests answered.
  • Fail concurrent requests for modification altogether, i.e. just return some kind of "conflicting operation already in progress, please try again later" error. Clients then would have to handle this, but they have to handle failures already anyways since the API is gone during the reload, but the error would look a bit different.

@yhabteab
Copy link
Member Author

yhabteab commented Mar 2, 2022

Fail concurrent requests for modification altogether

You want me to forbid concurrent stage updates that are completely independent from each other?

@Al2Klimov
Copy link
Member

Tom and I also do. (Icinga/icingaweb2-module-director#2412)

@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch 2 times, most recently from e909865 to 62e0c34 Compare March 2, 2022 18:52
@yhabteab
Copy link
Member Author

yhabteab commented Mar 2, 2022

Before:
See in the referenced issue.

After:

Package cmdb:

curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/stages/cmdb'  -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { check_command = \"dummy\" }" }, "pretty": true }'

HTTP/1.1 200 OK
Server: Icinga/v2.13.0-209-g62e0c349b
Content-Type: application/json
Content-Length: 221

{
    "results": [
        {
            "code": 200,
            "package": "cmdb",
            "stage": "9a218b57-8b04-4f66-80ff-3c9c8763fe24",
            "status": "Created stage. Reload triggered."
        }
    ]
}

Package icinga:

curl -k -s -S -i -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/config/stage
s/icinga'  -d '{ "files": { "conf.d/test.conf": "object Host \"test-host\" { check_command = \"dummy\" }" }, "pretty": true }'
HTTP/1.1 409 Conflict
Server: Icinga/v2.13.0-209-g62e0c349b
Content-Type: application/json
Content-Length: 142

{
    "error": 409,
    "status": "Conflicting request, there is already an ongoing package update in progress. Please try it again later."
}

lib/remote/configstageshandler.hpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.cpp Show resolved Hide resolved
lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch 2 times, most recently from 1e5cc5e to cecfca5 Compare March 7, 2022 08:15
lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.cpp Show resolved Hide resolved
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from cecfca5 to 0c5c0ab Compare March 7, 2022 12:12
@yhabteab yhabteab requested a review from Al2Klimov March 7, 2022 12:52
Copy link
Contributor

@julianbrost julianbrost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the inline comments, please also make sure to test #9267 (comment) (second paragraph).

lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.hpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from 0c5c0ab to cb85adc Compare March 7, 2022 17:00
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from cb85adc to c82b397 Compare March 7, 2022 17:08
Copy link
Contributor

@julianbrost julianbrost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where you add that new Defer parameter, lines are getting quite long, so I'd say it's time to add some line breaks.

lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from c82b397 to 129b1dd Compare March 8, 2022 09:34
lib/remote/configstageshandler.hpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configstageshandler.cpp Outdated Show resolved Hide resolved
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from 129b1dd to c67bd66 Compare March 8, 2022 10:29
Copy link
Contributor

@julianbrost julianbrost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yhabteab Is this intentionally still in draft state? I don't have anything more code-wise so far. I'll still do some testing but preferably after you say you don't plan any other changes to the code.

lib/remote/configpackageutility.cpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.hpp Outdated Show resolved Hide resolved
lib/remote/configpackageutility.hpp Outdated Show resolved Hide resolved
} catch (const std::exception& ex) {
return HttpUtility::SendJsonError(response, params, 500,
"Stage creation failed.",
DiagnosticInformation(ex));
}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just caught my eye and fixed it right away. Is this a reason for a change request?

@@ -212,4 +221,3 @@ void ConfigStagesHandler::HandleDelete(
response.result(http::status::ok);
HttpUtility::SendJsonBody(response, params, result);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same 👆

@yhabteab
Copy link
Member Author

@yhabteab Is this intentionally still in draft state?

Sorry, forgot to press the ready!

@yhabteab yhabteab marked this pull request as ready for review March 28, 2022 07:53
@Al2Klimov
Copy link
Member

Let's hear a second opinion on my requested changes...

m_Func();
} catch (...) {
// https://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor
if (m_Func != nullptr) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw. wondering whether != nullptr is actually necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…alidation success and process is going to be reloaded
To prevent Icinga2 from being restarted while
one or more requests are still in progress and end up
as corrupted stages without status file and startup logs.
@yhabteab yhabteab force-pushed the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch from c67bd66 to 6193a91 Compare March 30, 2022 07:42
@Al2Klimov Al2Klimov merged commit b29b95e into master Apr 6, 2022
@icinga-probot icinga-probot bot deleted the bugfix/parallel-api-package-calls-do-not-finish-while-reload branch April 6, 2022 11:28
@Al2Klimov
Copy link
Member

@yhabteab Backport this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api REST API bug Something isn't working cla/signed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API package calls do not complete while reload being called
3 participants