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

View File

@ -44,7 +44,6 @@ type Builder interface {
// The Cleaner interface provides the method to cleanup/unmount the volumes. // The Cleaner interface provides the method to cleanup/unmount the volumes.
type Cleaner interface { type Cleaner interface {
Interface
// TearDown unmounts the volume and removes traces of the SetUp procedure. // TearDown unmounts the volume and removes traces of the SetUp procedure.
TearDown() error TearDown() error
} }
@ -98,11 +97,7 @@ type EmptyDirectoryCleaner struct {
// Simply delete everything in the directory. // Simply delete everything in the directory.
func (emptyDir *EmptyDirectoryCleaner) TearDown() error { func (emptyDir *EmptyDirectoryCleaner) TearDown() error {
return os.RemoveAll(emptyDir.GetPath()) return os.RemoveAll(emptyDir.Path)
}
func (emptyDir *EmptyDirectoryCleaner) GetPath() string {
return emptyDir.Path
} }
// Interprets API volume as a HostDirectory // 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} 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 // CreateVolumeBuilder returns a Builder capable of mounting a volume described by an
// *api.Volume, or an error. // *api.Volume, or an error.
func CreateVolumeBuilder(volume *api.Volume, podID string, rootDir string) (Builder, 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 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")
}