Modifies directory walker to use a regex

Now a regex is used to determine active volume properties from
their directory paths.
This commit is contained in:
Danny Jones 2014-07-29 10:20:50 -07:00
parent 47bca30edc
commit 6191ffc0de
3 changed files with 64 additions and 28 deletions

View File

@ -22,7 +22,9 @@ import (
"fmt"
"net/http"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
@ -456,7 +458,7 @@ func determineValidVolumes(pods []Pod) map[string]api.Volume {
validVolumes := make(map[string]api.Volume)
for _, pod := range pods {
for _, volume := range pod.Manifest.Volumes {
identifier := pod.Manifest.ID + "/" + volume.Name
identifier := path.Join(pod.Manifest.ID, volume.Name)
validVolumes[identifier] = volume
}
}
@ -467,32 +469,31 @@ func determineValidVolumes(pods []Pod) map[string]api.Volume {
// active and mounted. Builds their respective Cleaner type in case they need to be deleted.
func (kl *Kubelet) determineActiveVolumes() map[string]volume.Cleaner {
activeVolumes := make(map[string]volume.Cleaner)
filepath.Walk(kl.rootDirectory, func(path string, info os.FileInfo, err error) error {
// Search for volume dir structure : $ROOTDIR/$PODID/volumes/$VOLUMETYPE/$VOLUMENAME
var name string
var podID string
// Extract volume type for dir structure
dir := getDir(path)
glog.Infof("Traversing filepath %s", path)
// Handle emptyDirectory types.
if dir == "empty" {
name = info.Name()
// Retrieve podID from dir structure
podID = getDir(filepath.Dir(filepath.Dir(path)))
glog.Infof("Found active volume %s of pod %s", name, podID)
identifier := podID + "/" + name
activeVolumes[identifier] = &volume.EmptyDirectoryCleaner{path}
filepath.Walk(kl.rootDirectory, func(fullPath string, info os.FileInfo, err error) error {
// Search for volume dir structure : (ROOT_DIR)/(POD_ID)/volumes/(VOLUME_KIND)/(VOLUME_NAME)
podIDRegex := "(?P<podID>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)"
volumeNameRegex := "(?P<volumeName>[a-z0-9]([-a-z0-9]*[a-z0-9])?)"
kindRegex := "(?P<volumeKind>(empty))"
regex := path.Join(kl.rootDirectory, podIDRegex, "volumes", kindRegex, volumeNameRegex)
regexMatcher, _ := regexp.Compile(regex)
if regexMatcher.MatchString(fullPath) {
// Extract info from the directory structure.
result := make(map[string]string)
substrings := regexMatcher.FindStringSubmatch(fullPath)
for i, label := range regexMatcher.SubexpNames() {
result[label] = substrings[i]
}
kind := result["volumeKind"]
name := result["volumeName"]
podID := result["podID"]
identifier := path.Join(podID, name)
activeVolumes[identifier], err = volume.CreateVolumeCleaner(kind, fullPath)
}
return nil
})
return activeVolumes
}
// Utility function to extract only the directory name.
func getDir(path string) string {
return filepath.Base(filepath.Dir(path))
}
// Compares the map of active volumes to the map of valid volumes.
// If an active volume does not have a respective valid volume, clean it up.
func (kl *Kubelet) reconcileVolumes(pods []Pod) error {
@ -503,7 +504,10 @@ func (kl *Kubelet) reconcileVolumes(pods []Pod) error {
for name, volume := range activeVolumes {
if _, ok := validVolumes[name]; !ok {
glog.Infof("Orphaned volume %s found, tearing down volume", name)
volume.TearDown()
err := volume.TearDown()
if err != nil {
glog.Errorf("Could not tear down volume %s", name)
}
}
}
return nil

View File

@ -44,7 +44,6 @@ type Builder interface {
// The Cleaner interface provides the method to cleanup/unmount the volumes.
type Cleaner interface {
Interface
// TearDown unmounts the volume and removes traces of the SetUp procedure.
TearDown() error
}
@ -98,11 +97,7 @@ type EmptyDirectoryCleaner struct {
// Simply delete everything in the directory.
func (emptyDir *EmptyDirectoryCleaner) TearDown() error {
return os.RemoveAll(emptyDir.GetPath())
}
func (emptyDir *EmptyDirectoryCleaner) GetPath() string {
return emptyDir.Path
return os.RemoveAll(emptyDir.Path)
}
// Interprets API volume as a HostDirectory
@ -115,6 +110,10 @@ func CreateEmptyDirectoryBuilder(volume *api.Volume, podID string, rootDir strin
return &EmptyDirectoryBuilder{volume.Name, podID, rootDir}
}
func CreateEmptyDirectoryCleaner(path string) *EmptyDirectoryCleaner {
return &EmptyDirectoryCleaner{path}
}
// CreateVolumeBuilder returns a Builder capable of mounting a volume described by an
// *api.Volume, or an error.
func CreateVolumeBuilder(volume *api.Volume, podID string, rootDir string) (Builder, error) {
@ -136,3 +135,12 @@ func CreateVolumeBuilder(volume *api.Volume, podID string, rootDir string) (Buil
}
return vol, nil
}
func CreateVolumeCleaner(kind string, path string) (Cleaner, error) {
switch kind {
case "empty":
return CreateEmptyDirectoryCleaner(path), nil
default:
return nil, ErrUnsupportedVolumeType
}
}

View File

@ -108,3 +108,27 @@ func TestCreateVolumeBuilders(t *testing.T) {
}
}
}
func TestEmptySetUpAndTearDown(t *testing.T) {
volumes := []api.Volume{
{
Name: "empty-dir",
Source: &api.VolumeSource{
EmptyDirectory: &api.EmptyDirectory{},
},
},
}
expectedPath := "/tmp/kubelet/fakeID/volumes/empty/empty-dir"
for _, volume := range volumes {
volumeBuilder, _ := CreateVolumeBuilder(&volume, "fakeID", "/tmp/kubelet")
volumeBuilder.SetUp()
if _, err := os.Stat(expectedPath); os.IsNotExist(err) {
t.Errorf("Mount directory %v does not exist after SetUp", expectedPath)
}
volumeCleaner, _ := CreateVolumeCleaner("empty", expectedPath)
volumeCleaner.TearDown()
if _, err := os.Stat(expectedPath); !os.IsNotExist(err) {
t.Errorf("Mount directory %v still exists after TearDown", expectedPath)
}
}
os.RemoveAll("/tmp/kubelet")
}