fs: evaluate labels from all mount points

This commit is contained in:
Aaron Levy 2016-03-01 09:20:57 +00:00
parent 8b2e8bd9ad
commit b1e4bc7d11
2 changed files with 101 additions and 63 deletions

View File

@ -76,6 +76,10 @@ func NewFsInfo(context Context) (FsInfo, error) {
labels: make(map[string]string, 0), labels: make(map[string]string, 0),
dmsetup: &defaultDmsetupClient{}, dmsetup: &defaultDmsetupClient{},
} }
fsInfo.addSystemRootLabel(mounts)
fsInfo.addDockerImagesLabel(context, mounts)
supportedFsType := map[string]bool{ supportedFsType := map[string]bool{
// all ext systems are checked through prefix. // all ext systems are checked through prefix.
"btrfs": true, "btrfs": true,
@ -102,12 +106,7 @@ func NewFsInfo(context Context) (FsInfo, error) {
} }
} }
// need to call this before the log line below printing out the partitions, as this function may
// add a "partition" for devicemapper to fsInfo.partitions
fsInfo.addDockerImagesLabel(context)
glog.Infof("Filesystem partitions: %+v", fsInfo.partitions) glog.Infof("Filesystem partitions: %+v", fsInfo.partitions)
fsInfo.addSystemRootLabel()
return fsInfo, nil return fsInfo, nil
} }
@ -144,18 +143,23 @@ func (self *RealFsInfo) getDockerDeviceMapperInfo(dockerInfo map[string]string)
} }
// addSystemRootLabel attempts to determine which device contains the mount for /. // addSystemRootLabel attempts to determine which device contains the mount for /.
func (self *RealFsInfo) addSystemRootLabel() { func (self *RealFsInfo) addSystemRootLabel(mounts []*mount.Info) {
for src, p := range self.partitions { for _, m := range mounts {
if p.mountpoint == "/" { if m.Mountpoint == "/" {
if _, ok := self.labels[LabelSystemRoot]; !ok { self.partitions[m.Source] = partition{
self.labels[LabelSystemRoot] = src fsType: m.Fstype,
mountpoint: m.Mountpoint,
major: uint(m.Major),
minor: uint(m.Minor),
} }
self.labels[LabelSystemRoot] = m.Source
return
} }
} }
} }
// addDockerImagesLabel attempts to determine which device contains the mount for docker images. // addDockerImagesLabel attempts to determine which device contains the mount for docker images.
func (self *RealFsInfo) addDockerImagesLabel(context Context) { func (self *RealFsInfo) addDockerImagesLabel(context Context, mounts []*mount.Info) {
dockerDev, dockerPartition, err := self.getDockerDeviceMapperInfo(context.DockerInfo) dockerDev, dockerPartition, err := self.getDockerDeviceMapperInfo(context.DockerInfo)
if err != nil { if err != nil {
glog.Warningf("Could not get Docker devicemapper device: %v", err) glog.Warningf("Could not get Docker devicemapper device: %v", err)
@ -164,11 +168,7 @@ func (self *RealFsInfo) addDockerImagesLabel(context Context) {
self.partitions[dockerDev] = *dockerPartition self.partitions[dockerDev] = *dockerPartition
self.labels[LabelDockerImages] = dockerDev self.labels[LabelDockerImages] = dockerDev
} else { } else {
dockerPaths := getDockerImagePaths(context) self.updateDockerImagesPath(mounts, getDockerImagePaths(context))
for src, p := range self.partitions {
self.updateDockerImagesPath(src, p.mountpoint, dockerPaths)
}
} }
} }
@ -190,22 +190,30 @@ func getDockerImagePaths(context Context) []string {
return dockerImagePaths return dockerImagePaths
} }
// This method compares the mountpoint with possible docker image mount points. If a match is found, // This method compares the mountpoints with possible docker image mount points. If a match is found,
// docker images label is added to the partition. // docker images label is added to the partition.
func (self *RealFsInfo) updateDockerImagesPath(source string, mountpoint string, dockerImagePaths []string) { func (self *RealFsInfo) updateDockerImagesPath(mounts []*mount.Info, dockerImagePaths []string) {
for _, v := range dockerImagePaths { var useMount *mount.Info
if v == mountpoint { for _, m := range mounts {
if i, ok := self.labels[LabelDockerImages]; ok { for _, p := range dockerImagePaths {
// pick the innermost mountpoint. if p != m.Mountpoint {
mnt := self.partitions[i].mountpoint continue
if len(mnt) < len(mountpoint) { }
self.labels[LabelDockerImages] = source // pick the innermost mountpoint
} if useMount == nil || (len(useMount.Mountpoint) < len(m.Mountpoint)) {
} else { useMount = m
self.labels[LabelDockerImages] = source
} }
} }
} }
if useMount != nil {
self.partitions[useMount.Source] = partition{
fsType: useMount.Fstype,
mountpoint: useMount.Mountpoint,
major: uint(useMount.Major),
minor: uint(useMount.Minor),
}
self.labels[LabelDockerImages] = useMount.Source
}
} }
func (self *RealFsInfo) GetDeviceForLabel(label string) (string, error) { func (self *RealFsInfo) GetDeviceForLabel(label string) (string, error) {

View File

@ -22,6 +22,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/docker/pkg/mount"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -161,22 +162,29 @@ func TestParseDMTable(t *testing.T) {
} }
func TestAddSystemRootLabel(t *testing.T) { func TestAddSystemRootLabel(t *testing.T) {
fsInfo := &RealFsInfo{ tests := []struct {
labels: map[string]string{}, mounts []*mount.Info
partitions: map[string]partition{ expected string
"/dev/mapper/vg_vagrant-lv_root": { }{
mountpoint: "/", {
}, mounts: []*mount.Info{
"vg_vagrant-docker--pool": { {Source: "/dev/sda1", Mountpoint: "/foo"},
mountpoint: "", {Source: "/dev/sdb1", Mountpoint: "/"},
fsType: "devicemapper",
}, },
expected: "/dev/sdb1",
}, },
} }
fsInfo.addSystemRootLabel() for i, tt := range tests {
if e, a := "/dev/mapper/vg_vagrant-lv_root", fsInfo.labels[LabelSystemRoot]; e != a { fsInfo := &RealFsInfo{
t.Errorf("expected %q, got %q", e, a) labels: map[string]string{},
partitions: map[string]partition{},
}
fsInfo.addSystemRootLabel(tt.mounts)
if source, ok := fsInfo.labels[LabelSystemRoot]; !ok || source != tt.expected {
t.Errorf("case %d: expected mount source '%s', got '%s'", i, tt.expected, source)
}
} }
} }
@ -305,7 +313,7 @@ func TestAddDockerImagesLabel(t *testing.T) {
driverStatus string driverStatus string
dmsetupTable string dmsetupTable string
getDockerDeviceMapperInfoError error getDockerDeviceMapperInfoError error
partitions map[string]partition mounts []*mount.Info
expectedDockerDevice string expectedDockerDevice string
expectedPartition *partition expectedPartition *partition
}{ }{
@ -314,10 +322,11 @@ func TestAddDockerImagesLabel(t *testing.T) {
driver: "devicemapper", driver: "devicemapper",
driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`, driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`,
dmsetupTable: "0 53870592 thin-pool 253:2 253:3 1024 0 1 skip_block_zeroing", dmsetupTable: "0 53870592 thin-pool 253:2 253:3 1024 0 1 skip_block_zeroing",
partitions: map[string]partition{ mounts: []*mount.Info{
"/dev/mapper/vg_vagrant-lv_root": { {
mountpoint: "/", Source: "/dev/mapper/vg_vagrant-lv_root",
fsType: "devicemapper", Mountpoint: "/",
Fstype: "devicemapper",
}, },
}, },
expectedDockerDevice: "vg_vagrant-docker--pool", expectedDockerDevice: "vg_vagrant-docker--pool",
@ -332,41 +341,62 @@ func TestAddDockerImagesLabel(t *testing.T) {
name: "devicemapper, loopback on non-root partition", name: "devicemapper, loopback on non-root partition",
driver: "devicemapper", driver: "devicemapper",
driverStatus: `[["Data loop file","/var/lib/docker/devicemapper/devicemapper/data"]]`, driverStatus: `[["Data loop file","/var/lib/docker/devicemapper/devicemapper/data"]]`,
partitions: map[string]partition{ mounts: []*mount.Info{
"/dev/mapper/vg_vagrant-lv_root": { {
mountpoint: "/", Source: "/dev/mapper/vg_vagrant-lv_root",
fsType: "devicemapper", Mountpoint: "/",
Fstype: "devicemapper",
}, },
"/dev/sdb1": { {
mountpoint: "/var/lib/docker/devicemapper", Source: "/dev/sdb1",
Mountpoint: "/var/lib/docker/devicemapper",
}, },
}, },
expectedDockerDevice: "/dev/sdb1", expectedDockerDevice: "/dev/sdb1",
}, },
{ {
name: "multiple mounts - innermost check", name: "multiple mounts - innermost check",
partitions: map[string]partition{ mounts: []*mount.Info{
"/dev/sda1": { {
mountpoint: "/", Source: "/dev/sda1",
fsType: "ext4", Mountpoint: "/",
Fstype: "ext4",
}, },
"/dev/sdb1": { {
mountpoint: "/var/lib/docker", Source: "/dev/sdb1",
fsType: "ext4", Mountpoint: "/var/lib/docker",
Fstype: "ext4",
}, },
"/dev/sdb2": { {
mountpoint: "/var/lib/docker/btrfs", Source: "/dev/sdb2",
fsType: "btrfs", Mountpoint: "/var/lib/docker/btrfs",
Fstype: "btrfs",
}, },
}, },
expectedDockerDevice: "/dev/sdb2", expectedDockerDevice: "/dev/sdb2",
}, },
{
name: "root fs inside container, docker-images bindmount",
mounts: []*mount.Info{
{
Source: "overlay",
Mountpoint: "/",
Fstype: "overlay",
},
{
Source: "/dev/sda1",
Mountpoint: "/var/lib/docker",
Fstype: "ext4",
},
},
expectedDockerDevice: "/dev/sda1",
},
} }
for _, tt := range tests { for _, tt := range tests {
fsInfo := &RealFsInfo{ fsInfo := &RealFsInfo{
labels: map[string]string{}, labels: map[string]string{},
partitions: tt.partitions, partitions: map[string]partition{},
dmsetup: &testDmsetup{ dmsetup: &testDmsetup{
data: []byte(tt.dmsetupTable), data: []byte(tt.dmsetupTable),
}, },
@ -380,7 +410,7 @@ func TestAddDockerImagesLabel(t *testing.T) {
}, },
} }
fsInfo.addDockerImagesLabel(context) fsInfo.addDockerImagesLabel(context, tt.mounts)
if e, a := tt.expectedDockerDevice, fsInfo.labels[LabelDockerImages]; e != a { if e, a := tt.expectedDockerDevice, fsInfo.labels[LabelDockerImages]; e != a {
t.Errorf("%s: docker device: expected %q, got %q", tt.name, e, a) t.Errorf("%s: docker device: expected %q, got %q", tt.name, e, a)