mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00

The current code did something like this: lock() getState() unlock() if state != running lock() getState() == running -> error unlock() This of course is wrong because between the first unlock() and second lock() call another process could have modified the state. This meant that sometimes you would get a weird error on start because the internal setup errored as the container was already running. In general any state check without holding the lock is incorrect and will result in race conditions. As such refactor the code to combine both StartAndAttach and Attach() into one function that can handle both. With that we can move the running check into the locked code. Also use typed error for this specific error case then the callers can check and ignore the specific error when needed. This also allows us to fix races in the compat API that did a similar racy state check. This commit changes slightly how we output the result, previously a start on already running container would never print the id/name of the container which is confusing and sort of breaks idempotence. Now it will include the output except when --all is used. Then it only reports the ids that were actually started. Fixes #23246 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
221 lines
9.8 KiB
Go
221 lines
9.8 KiB
Go
package define
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/containers/common/libnetwork/types"
|
|
"github.com/containers/common/pkg/detach"
|
|
)
|
|
|
|
var (
|
|
// ErrNoSuchCtr indicates the requested container does not exist
|
|
ErrNoSuchCtr = errors.New("no such container")
|
|
|
|
// ErrNoSuchPod indicates the requested pod does not exist
|
|
ErrNoSuchPod = errors.New("no such pod")
|
|
|
|
// ErrNoSuchVolume indicates the requested volume does not exist
|
|
ErrNoSuchVolume = errors.New("no such volume")
|
|
|
|
// ErrNoSuchNetwork indicates the requested network does not exist
|
|
ErrNoSuchNetwork = types.ErrNoSuchNetwork
|
|
|
|
// ErrNoSuchExecSession indicates that the requested exec session does
|
|
// not exist.
|
|
ErrNoSuchExecSession = errors.New("no such exec session")
|
|
|
|
// ErrNoSuchExitCode indicates that the requested container exit code
|
|
// does not exist.
|
|
ErrNoSuchExitCode = errors.New("no such exit code")
|
|
|
|
// ErrDepExists indicates that the current object has dependencies and
|
|
// cannot be removed before them.
|
|
ErrDepExists = errors.New("dependency exists")
|
|
|
|
// ErrNoAliases indicates that the container does not have any network
|
|
// aliases.
|
|
ErrNoAliases = errors.New("no aliases for container")
|
|
|
|
// ErrMissingPlugin indicates that the requested operation requires a
|
|
// plugin that is not present on the system or in the configuration.
|
|
ErrMissingPlugin = errors.New("required plugin missing")
|
|
|
|
// ErrCtrExists indicates a container with the same name or ID already
|
|
// exists
|
|
ErrCtrExists = errors.New("container already exists")
|
|
// ErrPodExists indicates a pod with the same name or ID already exists
|
|
ErrPodExists = errors.New("pod already exists")
|
|
// ErrImageExists indicates an image with the same ID already exists
|
|
ErrImageExists = errors.New("image already exists")
|
|
// ErrVolumeExists indicates a volume with the same name already exists
|
|
ErrVolumeExists = errors.New("volume already exists")
|
|
// ErrExecSessionExists indicates an exec session with the same ID
|
|
// already exists.
|
|
ErrExecSessionExists = errors.New("exec session already exists")
|
|
// ErrNetworkExists indicates that a network with the given name already
|
|
// exists.
|
|
ErrNetworkExists = types.ErrNetworkExists
|
|
|
|
// ErrCtrStateInvalid indicates a container is in an improper state for
|
|
// the requested operation
|
|
ErrCtrStateInvalid = errors.New("container state improper")
|
|
// ErrCtrStateRunning indicates a container is running.
|
|
ErrCtrStateRunning = errors.New("container is running")
|
|
// ErrExecSessionStateInvalid indicates that an exec session is in an
|
|
// improper state for the requested operation
|
|
ErrExecSessionStateInvalid = errors.New("exec session state improper")
|
|
// ErrVolumeBeingUsed indicates that a volume is being used by at least one container
|
|
ErrVolumeBeingUsed = errors.New("volume is being used")
|
|
|
|
// ErrRuntimeFinalized indicates that the runtime has already been
|
|
// created and cannot be modified
|
|
ErrRuntimeFinalized = errors.New("runtime has been finalized")
|
|
// ErrCtrFinalized indicates that the container has already been created
|
|
// and cannot be modified
|
|
ErrCtrFinalized = errors.New("container has been finalized")
|
|
// ErrPodFinalized indicates that the pod has already been created and
|
|
// cannot be modified
|
|
ErrPodFinalized = errors.New("pod has been finalized")
|
|
// ErrVolumeFinalized indicates that the volume has already been created and
|
|
// cannot be modified
|
|
ErrVolumeFinalized = errors.New("volume has been finalized")
|
|
|
|
// ErrInvalidArg indicates that an invalid argument was passed
|
|
ErrInvalidArg = types.ErrInvalidArg
|
|
// ErrEmptyID indicates that an empty ID was passed
|
|
ErrEmptyID = errors.New("name or ID cannot be empty")
|
|
|
|
// ErrInternal indicates an internal library error
|
|
ErrInternal = errors.New("internal libpod error")
|
|
|
|
// ErrPodPartialFail indicates that a pod operation was only partially
|
|
// successful, and some containers within the pod failed.
|
|
ErrPodPartialFail = errors.New("some containers failed")
|
|
|
|
// ErrDetach indicates that an attach session was manually detached by
|
|
// the user.
|
|
ErrDetach = detach.ErrDetach
|
|
|
|
// ErrWillDeadlock indicates that the requested operation will cause a
|
|
// deadlock. This is usually caused by upgrade issues, and is resolved
|
|
// by renumbering the locks.
|
|
ErrWillDeadlock = errors.New("deadlock due to lock mismatch")
|
|
|
|
// ErrNoCgroups indicates that the container does not have its own
|
|
// Cgroup.
|
|
ErrNoCgroups = errors.New("this container does not have a cgroup")
|
|
// ErrNoLogs indicates that this container is not creating a log so log
|
|
// operations cannot be performed on it
|
|
ErrNoLogs = errors.New("this container is not logging output")
|
|
|
|
// ErrRootless indicates that the given command cannot but run without
|
|
// root.
|
|
ErrRootless = errors.New("operation requires root privileges")
|
|
|
|
// ErrRuntimeStopped indicates that the runtime has already been shut
|
|
// down and no further operations can be performed on it
|
|
ErrRuntimeStopped = errors.New("runtime has already been stopped")
|
|
// ErrCtrStopped indicates that the requested container is not running
|
|
// and the requested operation cannot be performed until it is started
|
|
ErrCtrStopped = errors.New("container is stopped")
|
|
|
|
// ErrCtrRemoved indicates that the container has already been removed
|
|
// and no further operations can be performed on it
|
|
ErrCtrRemoved = errors.New("container has already been removed")
|
|
// ErrPodRemoved indicates that the pod has already been removed and no
|
|
// further operations can be performed on it
|
|
ErrPodRemoved = errors.New("pod has already been removed")
|
|
// ErrVolumeRemoved indicates that the volume has already been removed and
|
|
// no further operations can be performed on it
|
|
ErrVolumeRemoved = errors.New("volume has already been removed")
|
|
// ErrExecSessionRemoved indicates that the exec session has already
|
|
// been removed and no further operations can be performed on it.
|
|
ErrExecSessionRemoved = errors.New("exec session has already been removed")
|
|
|
|
// ErrDBClosed indicates that the connection to the state database has
|
|
// already been closed
|
|
ErrDBClosed = errors.New("database connection already closed")
|
|
// ErrDBBadConfig indicates that the database has a different schema or
|
|
// was created by a libpod with a different config
|
|
ErrDBBadConfig = errors.New("database configuration mismatch")
|
|
|
|
// ErrNSMismatch indicates that the requested pod or container is in a
|
|
// different namespace and cannot be accessed or modified.
|
|
ErrNSMismatch = errors.New("target is in a different namespace")
|
|
|
|
// ErrNotImplemented indicates that the requested functionality is not
|
|
// yet present
|
|
ErrNotImplemented = errors.New("not yet implemented")
|
|
|
|
// ErrOSNotSupported indicates the function is not available on the particular
|
|
// OS.
|
|
ErrOSNotSupported = errors.New("no support for this OS yet")
|
|
|
|
// ErrOCIRuntime indicates a generic error from the OCI runtime
|
|
ErrOCIRuntime = errors.New("OCI runtime error")
|
|
|
|
// ErrOCIRuntimePermissionDenied indicates the OCI runtime attempted to invoke a command that returned
|
|
// a permission denied error
|
|
ErrOCIRuntimePermissionDenied = errors.New("OCI permission denied")
|
|
|
|
// ErrOCIRuntimeNotFound indicates the OCI runtime attempted to invoke a command
|
|
// that was not found
|
|
ErrOCIRuntimeNotFound = errors.New("OCI runtime attempted to invoke a command that was not found")
|
|
|
|
// ErrOCIRuntimeUnavailable indicates that the OCI runtime associated to a container
|
|
// could not be found in the configuration
|
|
ErrOCIRuntimeUnavailable = errors.New("OCI unavailable")
|
|
|
|
// ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
|
|
// is out of date for the current podman version
|
|
ErrConmonOutdated = errors.New("outdated conmon version")
|
|
// ErrConmonDead indicates that the container's conmon process has been
|
|
// killed, preventing normal operation.
|
|
ErrConmonDead = errors.New("conmon process killed")
|
|
|
|
// ErrNetworkOnPodContainer indicates the user wishes to alter network attributes on a container
|
|
// in a pod. This cannot be done as the infra container has all the network information
|
|
ErrNetworkOnPodContainer = errors.New("network cannot be configured when it is shared with a pod")
|
|
|
|
// ErrNetworkInUse indicates the requested operation failed because the network was in use
|
|
ErrNetworkInUse = errors.New("network is being used")
|
|
|
|
// ErrNetworkConnected indicates that the required operation failed because the container is already a network endpoint
|
|
ErrNetworkConnected = errors.New("network is already connected")
|
|
|
|
// ErrStoreNotInitialized indicates that the container storage was never
|
|
// initialized.
|
|
ErrStoreNotInitialized = errors.New("the container storage was never initialized")
|
|
|
|
// ErrNoNetwork indicates that a container has no net namespace, like network=none
|
|
ErrNoNetwork = errors.New("container has no network namespace")
|
|
|
|
// ErrNetworkModeInvalid indicates that a container has the wrong network mode for an operation
|
|
ErrNetworkModeInvalid = errors.New("invalid network mode")
|
|
|
|
// ErrSetSecurityAttribute indicates that a request to set a container's security attribute
|
|
// was not possible.
|
|
ErrSetSecurityAttribute = fmt.Errorf("%w: unable to assign security attribute", ErrOCIRuntime)
|
|
|
|
// ErrGetSecurityAttribute indicates that a request to get a container's security attribute
|
|
// was not possible.
|
|
ErrGetSecurityAttribute = fmt.Errorf("%w: unable to get security attribute", ErrOCIRuntime)
|
|
|
|
// ErrSecurityAttribute indicates that an error processing security attributes
|
|
// for the container
|
|
ErrSecurityAttribute = fmt.Errorf("%w: unable to process security attribute", ErrOCIRuntime)
|
|
|
|
// ErrCanceled indicates that an operation has been cancelled by a user.
|
|
// Useful for potentially long running tasks.
|
|
ErrCanceled = errors.New("cancelled by user")
|
|
|
|
// ErrConmonVersionFormat is used when the expected version format of conmon
|
|
// has changed.
|
|
ErrConmonVersionFormat = "conmon version changed format"
|
|
|
|
// ErrRemovingCtrs indicates that there was an error removing all
|
|
// containers from a pod.
|
|
ErrRemovingCtrs = errors.New("removing pod containers")
|
|
)
|