summaryrefslogtreecommitdiff
path: root/libpod/in_memory_state.go
diff options
context:
space:
mode:
authorumohnani8 <umohnani@redhat.com>2018-08-08 09:50:15 -0400
committerUrvashi Mohnani <umohnani@redhat.com>2018-12-06 10:17:16 +0000
commit4c70b8a94b22b31e2c39ee710dcc21cc2f3fb337 (patch)
treed6d054bd40f9f0b02c4078b38d2839dc2dd77fc5 /libpod/in_memory_state.go
parent75b19ca8abe1957f3c48035767960a6b20c10519 (diff)
downloadpodman-4c70b8a94b22b31e2c39ee710dcc21cc2f3fb337.tar.gz
podman-4c70b8a94b22b31e2c39ee710dcc21cc2f3fb337.tar.bz2
podman-4c70b8a94b22b31e2c39ee710dcc21cc2f3fb337.zip
Add "podman volume" command
Add support for podman volume and its subcommands. The commands supported are: podman volume create podman volume inspect podman volume ls podman volume rm podman volume prune This is a tool to manage volumes used by podman. For now it only handle named volumes, but eventually it will handle all volumes used by podman. Signed-off-by: umohnani8 <umohnani@redhat.com>
Diffstat (limited to 'libpod/in_memory_state.go')
-rw-r--r--libpod/in_memory_state.go168
1 files changed, 167 insertions, 1 deletions
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 77eba0cc6..314799309 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -18,8 +18,10 @@ type InMemoryState struct {
pods map[string]*Pod
// Maps container ID to container struct.
containers map[string]*Container
+ volumes map[string]*Volume
// Maps container ID to a list of IDs of dependencies.
- ctrDepends map[string][]string
+ ctrDepends map[string][]string
+ volumeDepends map[string][]string
// Maps pod ID to a map of container ID to container struct.
podContainers map[string]map[string]*Container
// Global name registry - ensures name uniqueness and performs lookups.
@@ -46,8 +48,10 @@ func NewInMemoryState() (State, error) {
state.pods = make(map[string]*Pod)
state.containers = make(map[string]*Container)
+ state.volumes = make(map[string]*Volume)
state.ctrDepends = make(map[string][]string)
+ state.volumeDepends = make(map[string][]string)
state.podContainers = make(map[string]map[string]*Container)
@@ -244,6 +248,14 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
s.addCtrToDependsMap(ctr.ID(), depCtr)
}
+ // Add container to volume dependencies
+ for _, vol := range ctr.config.Spec.Mounts {
+ if strings.Contains(vol.Source, ctr.runtime.config.VolumePath) {
+ volName := strings.Split(vol.Source[len(ctr.runtime.config.VolumePath)+1:], "/")[0]
+ s.addCtrToVolDependsMap(ctr.ID(), volName)
+ }
+ }
+
return nil
}
@@ -294,6 +306,14 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error {
s.removeCtrFromDependsMap(ctr.ID(), depCtr)
}
+ // Remove container from volume dependencies
+ for _, vol := range ctr.config.Spec.Mounts {
+ if strings.Contains(vol.Source, ctr.runtime.config.VolumePath) {
+ volName := strings.Split(vol.Source[len(ctr.runtime.config.VolumePath)+1:], "/")[0]
+ s.removeCtrFromVolDependsMap(ctr.ID(), volName)
+ }
+ }
+
return nil
}
@@ -358,6 +378,114 @@ func (s *InMemoryState) ContainerInUse(ctr *Container) ([]string, error) {
return arr, nil
}
+// Volume retrieves a volume from its full name
+func (s *InMemoryState) Volume(name string) (*Volume, error) {
+ if name == "" {
+ return nil, ErrEmptyID
+ }
+
+ vol, ok := s.volumes[name]
+ if !ok {
+ return nil, errors.Wrapf(ErrNoSuchCtr, "no volume with name %s found", name)
+ }
+
+ return vol, nil
+}
+
+// HasVolume checks if a volume with the given name is present in the state
+func (s *InMemoryState) HasVolume(name string) (bool, error) {
+ if name == "" {
+ return false, ErrEmptyID
+ }
+
+ _, ok := s.volumes[name]
+ if !ok {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+// AddVolume adds a volume to the state
+func (s *InMemoryState) AddVolume(volume *Volume) error {
+ if !volume.valid {
+ return errors.Wrapf(ErrVolumeRemoved, "volume with name %s is not valid", volume.Name())
+ }
+
+ if _, ok := s.volumes[volume.Name()]; ok {
+ return errors.Wrapf(ErrVolumeExists, "volume with name %s already exists in state", volume.Name())
+ }
+
+ s.volumes[volume.Name()] = volume
+
+ return nil
+}
+
+// RemoveVolume removes a volume from the state
+func (s *InMemoryState) RemoveVolume(volume *Volume) error {
+ // Ensure we don't remove a volume which containers depend on
+ deps, ok := s.volumeDepends[volume.Name()]
+ if ok && len(deps) != 0 {
+ depsStr := strings.Join(deps, ", ")
+ return errors.Wrapf(ErrVolumeExists, "the following containers depend on volume %s: %s", volume.Name(), depsStr)
+ }
+
+ if _, ok := s.volumes[volume.Name()]; !ok {
+ volume.valid = false
+ return errors.Wrapf(ErrVolumeRemoved, "no volume exists in state with name %s", volume.Name())
+ }
+
+ delete(s.volumes, volume.Name())
+
+ return nil
+}
+
+// RemoveVolCtrDep updates the container dependencies of the volume
+func (s *InMemoryState) RemoveVolCtrDep(volume *Volume, ctrID string) error {
+ if !volume.valid {
+ return errors.Wrapf(ErrVolumeRemoved, "volume with name %s is not valid", volume.Name())
+ }
+
+ if _, ok := s.volumes[volume.Name()]; !ok {
+ return errors.Wrapf(ErrNoSuchVolume, "volume with name %s doesn't exists in state", volume.Name())
+ }
+
+ // Remove container that is using this volume
+ s.removeCtrFromVolDependsMap(ctrID, volume.Name())
+
+ return nil
+}
+
+// VolumeInUse checks if the given volume is being used by at least one container
+func (s *InMemoryState) VolumeInUse(volume *Volume) ([]string, error) {
+ if !volume.valid {
+ return nil, ErrVolumeRemoved
+ }
+
+ // If the volume does not exist, return error
+ if _, ok := s.volumes[volume.Name()]; !ok {
+ volume.valid = false
+ return nil, errors.Wrapf(ErrNoSuchVolume, "volume with name %s not found in state", volume.Name())
+ }
+
+ arr, ok := s.volumeDepends[volume.Name()]
+ if !ok {
+ return []string{}, nil
+ }
+
+ return arr, nil
+}
+
+// AllVolumes returns all volumes that exist in the state
+func (s *InMemoryState) AllVolumes() ([]*Volume, error) {
+ allVols := make([]*Volume, 0, len(s.volumes))
+ for _, v := range s.volumes {
+ allVols = append(allVols, v)
+ }
+
+ return allVols, nil
+}
+
// AllContainers retrieves all containers from the state
func (s *InMemoryState) AllContainers() ([]*Container, error) {
ctrs := make([]*Container, 0, len(s.containers))
@@ -945,6 +1073,44 @@ func (s *InMemoryState) removeCtrFromDependsMap(ctrID, dependsID string) {
}
}
+// Add a container to the dependency mappings for the volume
+func (s *InMemoryState) addCtrToVolDependsMap(depCtrID, volName string) {
+ if volName != "" {
+ arr, ok := s.volumeDepends[volName]
+ if !ok {
+ // Do not have a mapping for that volume yet
+ s.volumeDepends[volName] = []string{depCtrID}
+ } else {
+ // Have a mapping for the volume
+ arr = append(arr, depCtrID)
+ s.volumeDepends[volName] = arr
+ }
+ }
+}
+
+// Remove a container from the dependency mappings for the volume
+func (s *InMemoryState) removeCtrFromVolDependsMap(depCtrID, volName string) {
+ if volName != "" {
+ arr, ok := s.volumeDepends[volName]
+ if !ok {
+ // Internal state seems inconsistent
+ // But the dependency is definitely gone
+ // So just return
+ return
+ }
+
+ newArr := make([]string, 0, len(arr))
+
+ for _, id := range arr {
+ if id != depCtrID {
+ newArr = append(newArr, id)
+ }
+ }
+
+ s.volumeDepends[volName] = newArr
+ }
+}
+
// Check if we can access a pod or container, or if that is blocked by
// namespaces.
func (s *InMemoryState) checkNSMatch(id, ns string) error {