mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
devmapper: Update device-mapper-tool
This makes the device mapper tool work again and adds new features to get pool status, device status and to list all devices.
This commit is contained in:
parent
427649eee1
commit
80aecc7014
3 changed files with 176 additions and 38 deletions
|
@ -57,6 +57,16 @@ type Status struct {
|
||||||
MetadataLoopback string
|
MetadataLoopback string
|
||||||
Data DiskUsage
|
Data DiskUsage
|
||||||
Metadata DiskUsage
|
Metadata DiskUsage
|
||||||
|
SectorSize uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type DevStatus struct {
|
||||||
|
DeviceId int
|
||||||
|
Size uint64
|
||||||
|
TransactionId uint64
|
||||||
|
SizeInSectors uint64
|
||||||
|
MappedSectors uint64
|
||||||
|
HighestMappedSector uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevName(name string) string {
|
func getDevName(name string) string {
|
||||||
|
@ -357,13 +367,24 @@ func minor(device uint64) uint64 {
|
||||||
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) initDevmapper() error {
|
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
logInit(devices)
|
logInit(devices)
|
||||||
|
|
||||||
// Make sure the sparse images exist in <root>/devicemapper/data and
|
// Make sure the sparse images exist in <root>/devicemapper/data and
|
||||||
// <root>/devicemapper/metadata
|
// <root>/devicemapper/metadata
|
||||||
|
|
||||||
createdLoopback := !devices.hasImage("data") || !devices.hasImage("metadata")
|
hasData := devices.hasImage("data")
|
||||||
|
hasMetadata := devices.hasImage("metadata")
|
||||||
|
|
||||||
|
if !doInit && !hasData {
|
||||||
|
return fmt.Errorf("Looback data file not found %s")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doInit && !hasMetadata {
|
||||||
|
return fmt.Errorf("Looback metadata file not found %s")
|
||||||
|
}
|
||||||
|
|
||||||
|
createdLoopback := !hasData || !hasMetadata
|
||||||
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
|
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
||||||
|
@ -438,9 +459,11 @@ func (devices *DeviceSet) initDevmapper() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the base image
|
// Setup the base image
|
||||||
if err := devices.setupBaseImage(); err != nil {
|
if doInit {
|
||||||
utils.Debugf("Error device setupBaseImage: %s\n", err)
|
if err := devices.setupBaseImage(); err != nil {
|
||||||
return err
|
utils.Debugf("Error device setupBaseImage: %s\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -757,6 +780,69 @@ func (devices *DeviceSet) setInitialized(hash string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) List() []string {
|
||||||
|
devices.Lock()
|
||||||
|
defer devices.Unlock()
|
||||||
|
|
||||||
|
ids := make([]string, len(devices.Devices))
|
||||||
|
i := 0
|
||||||
|
for k := range devices.Devices {
|
||||||
|
ids[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) {
|
||||||
|
var params string
|
||||||
|
_, sizeInSectors, _, params, err = getStatus(devName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) {
|
||||||
|
devices.Lock()
|
||||||
|
defer devices.Unlock()
|
||||||
|
|
||||||
|
info := devices.Devices[hash]
|
||||||
|
if info == nil {
|
||||||
|
return nil, fmt.Errorf("No device %s", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
status := &DevStatus{
|
||||||
|
DeviceId: info.DeviceId,
|
||||||
|
Size: info.Size,
|
||||||
|
TransactionId: info.TransactionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := devices.activateDeviceIfNeeded(hash); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
status.SizeInSectors = sizeInSectors
|
||||||
|
status.MappedSectors = mappedSectors
|
||||||
|
status.HighestMappedSector = highestMappedSector
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) {
|
||||||
|
var params string
|
||||||
|
if _, totalSizeInSectors, _, params, err = getStatus(devices.getPoolName()); err == nil {
|
||||||
|
_, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) Status() *Status {
|
func (devices *DeviceSet) Status() *Status {
|
||||||
devices.Lock()
|
devices.Lock()
|
||||||
defer devices.Unlock()
|
defer devices.Unlock()
|
||||||
|
@ -767,26 +853,25 @@ func (devices *DeviceSet) Status() *Status {
|
||||||
status.DataLoopback = path.Join(devices.loopbackDir(), "data")
|
status.DataLoopback = path.Join(devices.loopbackDir(), "data")
|
||||||
status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
|
status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
|
||||||
|
|
||||||
_, totalSizeInSectors, _, params, err := getStatus(devices.getPoolName())
|
totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64
|
// Convert from blocks to bytes
|
||||||
if _, err := fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal); err == nil {
|
blockSizeInSectors := totalSizeInSectors / dataTotal
|
||||||
// Convert from blocks to bytes
|
|
||||||
blockSizeInSectors := totalSizeInSectors / dataTotal
|
|
||||||
|
|
||||||
status.Data.Used = dataUsed * blockSizeInSectors * 512
|
status.Data.Used = dataUsed * blockSizeInSectors * 512
|
||||||
status.Data.Total = dataTotal * blockSizeInSectors * 512
|
status.Data.Total = dataTotal * blockSizeInSectors * 512
|
||||||
|
|
||||||
// metadata blocks are always 4k
|
// metadata blocks are always 4k
|
||||||
status.Metadata.Used = metadataUsed * 4096
|
status.Metadata.Used = metadataUsed * 4096
|
||||||
status.Metadata.Total = metadataTotal * 4096
|
status.Metadata.Total = metadataTotal * 4096
|
||||||
}
|
|
||||||
|
status.SectorSize = blockSizeInSectors * 512
|
||||||
}
|
}
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeviceSet(root string) (*DeviceSet, error) {
|
func NewDeviceSet(root string, doInit bool) (*DeviceSet, error) {
|
||||||
SetDevDir("/dev")
|
SetDevDir("/dev")
|
||||||
|
|
||||||
devices := &DeviceSet{
|
devices := &DeviceSet{
|
||||||
|
@ -795,7 +880,7 @@ func NewDeviceSet(root string) (*DeviceSet, error) {
|
||||||
activeMounts: make(map[string]int),
|
activeMounts: make(map[string]int),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := devices.initDevmapper(); err != nil {
|
if err := devices.initDevmapper(doInit); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,59 +1,112 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/devmapper"
|
"github.com/dotcloud/docker/graphdriver/devmapper"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
fmt.Printf("Usage: %s [snap new-id base-id] | [remove id] | [mount id mountpoint]\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage: %s <flags> [status] | [list] | [device id] | [snap new-id base-id] | [remove id] | [mount id mountpoint]\n", os.Args[0])
|
||||||
|
flag.PrintDefaults()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
devices := devmapper.NewDeviceSet("/var/lib/docker")
|
root := flag.String("r", "/var/lib/docker", "Docker root dir")
|
||||||
|
flDebug := flag.Bool("D", false, "Debug mode")
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
flag.Parse()
|
||||||
|
|
||||||
|
if *flDebug {
|
||||||
|
os.Setenv("DEBUG", "1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NArg() < 1 {
|
||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := os.Args[1]
|
args := flag.Args()
|
||||||
if cmd == "snap" {
|
|
||||||
if len(os.Args) < 4 {
|
home := path.Join(*root, "devicemapper")
|
||||||
|
devices, err := devmapper.NewDeviceSet(home, false)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Can't initialize device mapper: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch args[0] {
|
||||||
|
case "status":
|
||||||
|
status := devices.Status()
|
||||||
|
fmt.Printf("Pool name: %s\n", status.PoolName)
|
||||||
|
fmt.Printf("Data Loopback file: %s\n", status.DataLoopback)
|
||||||
|
fmt.Printf("Metadata Loopback file: %s\n", status.MetadataLoopback)
|
||||||
|
fmt.Printf("Sector size: %d\n", status.SectorSize)
|
||||||
|
fmt.Printf("Data use: %d of %d (%.1f %%)\n", status.Data.Used, status.Data.Total, 100.0*float64(status.Data.Used)/float64(status.Data.Total))
|
||||||
|
fmt.Printf("Metadata use: %d of %d (%.1f %%)\n", status.Metadata.Used, status.Metadata.Total, 100.0*float64(status.Metadata.Used)/float64(status.Metadata.Total))
|
||||||
|
break
|
||||||
|
case "list":
|
||||||
|
ids := devices.List()
|
||||||
|
sort.Strings(ids)
|
||||||
|
for _, id := range ids {
|
||||||
|
fmt.Println(id)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "device":
|
||||||
|
if flag.NArg() < 2 {
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
status, err := devices.GetDeviceStatus(args[1])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Can't get device info: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("Id: %d\n", status.DeviceId)
|
||||||
|
fmt.Printf("Size: %d\n", status.Size)
|
||||||
|
fmt.Printf("Transaction Id: %d\n", status.TransactionId)
|
||||||
|
fmt.Printf("Size in Sectors: %d\n", status.SizeInSectors)
|
||||||
|
fmt.Printf("Mapped Sectors: %d\n", status.MappedSectors)
|
||||||
|
fmt.Printf("Highest Mapped Sector: %d\n", status.HighestMappedSector)
|
||||||
|
break
|
||||||
|
case "snap":
|
||||||
|
if flag.NArg() < 3 {
|
||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := devices.AddDevice(os.Args[2], os.Args[3])
|
err := devices.AddDevice(args[1], args[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Can't create snap device: ", err)
|
fmt.Println("Can't create snap device: ", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else if cmd == "remove" {
|
break
|
||||||
if len(os.Args) < 3 {
|
case "remove":
|
||||||
|
if flag.NArg() < 2 {
|
||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := devices.RemoveDevice(os.Args[2])
|
err := devices.RemoveDevice(args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Can't remove device: ", err)
|
fmt.Println("Can't remove device: ", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else if cmd == "mount" {
|
break
|
||||||
if len(os.Args) < 4 {
|
case "mount":
|
||||||
|
if flag.NArg() < 3 {
|
||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := devices.MountDevice(os.Args[2], os.Args[3])
|
err := devices.MountDevice(args[1], args[2], false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Can't create snap device: ", err)
|
fmt.Println("Can't create snap device: ", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
break
|
||||||
fmt.Printf("Unknown command %s\n", cmd)
|
default:
|
||||||
if len(os.Args) < 4 {
|
fmt.Printf("Unknown command %s\n", args[0])
|
||||||
usage()
|
usage()
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Driver struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(home string) (graphdriver.Driver, error) {
|
func Init(home string) (graphdriver.Driver, error) {
|
||||||
deviceSet, err := NewDeviceSet(home)
|
deviceSet, err := NewDeviceSet(home, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue