From f21492c649f39a5d1adadd1dd5855c22a2b9efff Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 16 Jun 2015 21:12:27 -0400 Subject: [PATCH] devicemapper: Compare uuid of base device on startup It is easy for one to use docker for a while, shut it down and restart docker with different set of storage options for device mapper driver which will effectively change the thin pool. That means any of the metadata stored in /var/lib/docker/devicemapper/metadata/ is not valid for the new pool and user will run into various kind of issues like container not found in the pool etc. Users think that their images or containers are lost but it might just be the case of configuration issue. People might use wrong metadata with wrong pool. To detect such situations, save UUID of base image and once docker starts later, query and compare the UUID of base image with the stored one. If they don't match, fail the initialization with the error that UUID failed to match. That way user will be forced to cleanup /var/lib/docker/ directory and start docker again. Signed-off-by: Vivek Goyal Upstream-commit: c06b05b11e6bbe48ae3ca140096d7862e5e312f8 Component: engine --- .../daemon/graphdriver/devmapper/deviceset.go | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go index 24805179f8..1844532c0b 100644 --- a/components/engine/daemon/graphdriver/devmapper/deviceset.go +++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go @@ -105,7 +105,8 @@ type DeviceSet struct { thinPoolDevice string Transaction `json:"-"` overrideUdevSyncCheck bool - deferredRemove bool // use deferred removal + deferredRemove bool // use deferred removal + BaseDeviceUUID string //save UUID of base device } type DiskUsage struct { @@ -669,9 +670,70 @@ func (devices *DeviceSet) loadMetadata(hash string) *DevInfo { return info } +func getDeviceUUID(device string) (string, error) { + out, err := exec.Command("blkid", "-s", "UUID", "-o", "value", device).Output() + if err != nil { + logrus.Debugf("Failed to find uuid for device %s:%v", device, err) + return "", err + } + + uuid := strings.TrimSuffix(string(out), "\n") + uuid = strings.TrimSpace(uuid) + logrus.Debugf("UUID for device: %s is:%s", device, uuid) + return uuid, nil +} + +func (devices *DeviceSet) verifyBaseDeviceUUID(baseInfo *DevInfo) error { + if err := devices.activateDeviceIfNeeded(baseInfo); err != nil { + return err + } + + defer devices.deactivateDevice(baseInfo) + + uuid, err := getDeviceUUID(baseInfo.DevName()) + if err != nil { + return err + } + + if devices.BaseDeviceUUID != uuid { + return fmt.Errorf("Current Base Device UUID:%s does not match with stored UUID:%s", uuid, devices.BaseDeviceUUID) + } + + return nil +} + +func (devices *DeviceSet) saveBaseDeviceUUID(baseInfo *DevInfo) error { + if err := devices.activateDeviceIfNeeded(baseInfo); err != nil { + return err + } + + defer devices.deactivateDevice(baseInfo) + + uuid, err := getDeviceUUID(baseInfo.DevName()) + if err != nil { + return err + } + + devices.BaseDeviceUUID = uuid + devices.saveDeviceSetMetaData() + return nil +} + func (devices *DeviceSet) setupBaseImage() error { oldInfo, _ := devices.lookupDevice("") if oldInfo != nil && oldInfo.Initialized { + // If BaseDeviceUUID is nil (upgrade case), save it and + // return success. + if devices.BaseDeviceUUID == "" { + if err := devices.saveBaseDeviceUUID(oldInfo); err != nil { + return fmt.Errorf("Could not query and save base device UUID:%v", err) + } + return nil + } + + if err := devices.verifyBaseDeviceUUID(oldInfo); err != nil { + return fmt.Errorf("Base Device UUID verification failed. Possibly using a different thin pool then last invocation:%v", err) + } return nil } @@ -721,6 +783,10 @@ func (devices *DeviceSet) setupBaseImage() error { return err } + if err := devices.saveBaseDeviceUUID(info); err != nil { + return fmt.Errorf("Could not query and save base device UUID:%v", err) + } + return nil }