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

Add podman volume create --ignore #16243

Merged

Conversation

alexlarsson
Copy link
Contributor

This ignores the create request if the named volume already exists.
It is very useful when scripting stuff.

New --ignore option in podman volume create

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

I imagined the option to be plugged into the backend (registry.ContainerEngine().VolumeCreate) and the REST API. This way, specified options will still be applied iff the volume name isn't already taken and we can prevent race conditions.

@@ -61,6 +66,17 @@ func create(cmd *cobra.Command, args []string) error {
)
if len(args) > 0 {
createOpts.Name = args[0]

if opts.Ignore {
existsResponse, err := registry.ContainerEngine().VolumeExists(context.Background(), createOpts.Name)
Copy link
Member

Choose a reason for hiding this comment

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

There's a TOCTOU race.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is always a TOCTOU race in any call to "podman create volume", no? We can make it smaller, but nothing keeps the volume alive after registry.ContainerEngine().VolumeCreate() returns.

Copy link
Member

Choose a reason for hiding this comment

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

I'd expect the name to be checked and assigned under a lock.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but we return the name with the lock released so there are no guarantees that the volume of that name exists by the time podman prints the name.

Copy link
Member

Choose a reason for hiding this comment

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

The correct way is to always create the volume and only if it fails with volume exists ignore that error.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed. And that should happen in the backend as mentioned above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am changing the code to that, which will make things better. But fundamentally, if you have some process removing volumes without cooperation, there is no race-free way to use the "podman volume create" api (the cli or the rest api).

You are worrying that the ordering is:

Task A                              Task B
check if volume exist => yes
                                    remove volume
return old volume name
use the returned volume name => ENOVOLUME

Here a lock around the check and create will solve this problem, but there is still this possible ordering:

Task A                              Task B
check if volume exist => no
create volume
return new volume name
                                    remove volume
use the returned volume name => ENOVOLUME

And no code inside podman can ever fix that.

Copy link
Member

Choose a reason for hiding this comment

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

That is true but what it will fix is two podman volume create --ignore name calls at the same time, both can pass the volume exists check before but only one will create it and thus the other one would fail since the error was not checked.

@github-actions github-actions bot added the kind/api-change Change to remote API; merits scrutiny label Oct 21, 2022
@alexlarsson
Copy link
Contributor Author

New version pushes check inside lock.

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

Thanks, @alexlarsson!

Can you also do the plumbing for the remote client?

Once the binding type is updated you can run make generate-bindings to generate the setter.

This ignores the create request if the named volume already exists.
It is very useful when scripting stuff.

Signed-off-by: Alexander Larsson <[email protected]>
This way we don't have to use the `ExecCondition=podman volume exist`,
which saves one process start.

Signed-off-by: Alexander Larsson <[email protected]>
@alexlarsson
Copy link
Contributor Author

@vrothberg I added a "schema:" to the VolumeCreateOptions struct member addtiotion. But I'm not sure we actually need anything else? At least make generate-bindings didn't produce any changes.

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

LGTM

@vrothberg
Copy link
Member

@vrothberg I added a "schema:" to the VolumeCreateOptions struct member addtiotion. But I'm not sure we actually need anything else? At least make generate-bindings didn't produce any changes.

My bad. Most endpoints use parameters but the volume's one is sending the entire struct over the wire.

@vrothberg
Copy link
Member

Restarted the flaked test

@alexlarsson
Copy link
Contributor Author

What is with this CI? In cirrus-ci it looks like all passed, but here its still waiting for one test.

@vrothberg
Copy link
Member

What is with this CI? In cirrus-ci it looks like all passed, but here its still waiting for one test.

Haven't seen this specific issue but Cirrus does not seem to realize that the tests have finished and turned green.

@vrothberg
Copy link
Member

I reran the job. Almost there 🤞

@alexlarsson
Copy link
Contributor Author

Yay! all green

@vrothberg
Copy link
Member

@containers/podman-maintainers PTAL

Copy link
Collaborator

@flouthoc flouthoc left a comment

Choose a reason for hiding this comment

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

LGTM

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 26, 2022

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alexlarsson, flouthoc

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 26, 2022
@rhatdan
Copy link
Member

rhatdan commented Oct 26, 2022

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Oct 26, 2022
@openshift-merge-robot openshift-merge-robot merged commit 47bcd10 into containers:main Oct 26, 2022
@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Sep 20, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/api-change Change to remote API; merits scrutiny lgtm Indicates that a PR is ready to be merged. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. release-note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants