mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
XL: Introduce new API StorageInfo. (#1770)
This is necessary for calculating the total storage capacity from object layer. This value is also needed for browser UI. Buckets used to carry this information, this patch deprecates this feature.
This commit is contained in:
parent
b2293c2bf4
commit
34e9ad24aa
25
fs-v1.go
25
fs-v1.go
@ -25,29 +25,31 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/minio/minio/pkg/disk"
|
||||||
"github.com/minio/minio/pkg/mimedb"
|
"github.com/minio/minio/pkg/mimedb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fsObjects - Implements fs object layer.
|
// fsObjects - Implements fs object layer.
|
||||||
type fsObjects struct {
|
type fsObjects struct {
|
||||||
storage StorageAPI
|
storage StorageAPI
|
||||||
|
physicalDisk string
|
||||||
listObjectMap map[listParams][]*treeWalkerFS
|
listObjectMap map[listParams][]*treeWalkerFS
|
||||||
listObjectMapMutex *sync.Mutex
|
listObjectMapMutex *sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFSObjects - initialize new fs object layer.
|
// newFSObjects - initialize new fs object layer.
|
||||||
func newFSObjects(exportPath string) (ObjectLayer, error) {
|
func newFSObjects(disk string) (ObjectLayer, error) {
|
||||||
var storage StorageAPI
|
var storage StorageAPI
|
||||||
var err error
|
var err error
|
||||||
if !strings.ContainsRune(exportPath, ':') || filepath.VolumeName(exportPath) != "" {
|
if !strings.ContainsRune(disk, ':') || filepath.VolumeName(disk) != "" {
|
||||||
// Initialize filesystem storage API.
|
// Initialize filesystem storage API.
|
||||||
storage, err = newPosix(exportPath)
|
storage, err = newPosix(disk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Initialize rpc client storage API.
|
// Initialize rpc client storage API.
|
||||||
storage, err = newRPCClient(exportPath)
|
storage, err = newRPCClient(disk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -60,11 +62,22 @@ func newFSObjects(exportPath string) (ObjectLayer, error) {
|
|||||||
// Return successfully initialized object layer.
|
// Return successfully initialized object layer.
|
||||||
return fsObjects{
|
return fsObjects{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
|
physicalDisk: disk,
|
||||||
listObjectMap: make(map[listParams][]*treeWalkerFS),
|
listObjectMap: make(map[listParams][]*treeWalkerFS),
|
||||||
listObjectMapMutex: &sync.Mutex{},
|
listObjectMapMutex: &sync.Mutex{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StorageInfo - returns underlying storage statistics.
|
||||||
|
func (fs fsObjects) StorageInfo() StorageInfo {
|
||||||
|
info, err := disk.GetInfo(fs.physicalDisk)
|
||||||
|
fatalIf(err, "Unable to get disk info "+fs.physicalDisk)
|
||||||
|
return StorageInfo{
|
||||||
|
Total: info.Total,
|
||||||
|
Free: info.Free,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Bucket operations
|
/// Bucket operations
|
||||||
|
|
||||||
// MakeBucket - make a bucket.
|
// MakeBucket - make a bucket.
|
||||||
@ -92,8 +105,6 @@ func (fs fsObjects) GetBucketInfo(bucket string) (BucketInfo, error) {
|
|||||||
return BucketInfo{
|
return BucketInfo{
|
||||||
Name: bucket,
|
Name: bucket,
|
||||||
Created: vi.Created,
|
Created: vi.Created,
|
||||||
Total: vi.Total,
|
|
||||||
Free: vi.Free,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +124,6 @@ func (fs fsObjects) ListBuckets() ([]BucketInfo, error) {
|
|||||||
bucketInfos = append(bucketInfos, BucketInfo{
|
bucketInfos = append(bucketInfos, BucketInfo{
|
||||||
Name: vol.Name,
|
Name: vol.Name,
|
||||||
Created: vol.Created,
|
Created: vol.Created,
|
||||||
Total: vol.Total,
|
|
||||||
Free: vol.Free,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.Sort(byBucketName(bucketInfos))
|
sort.Sort(byBucketName(bucketInfos))
|
||||||
|
@ -18,12 +18,16 @@ package main
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// StorageInfo - represents total capacity of underlying storage.
|
||||||
|
type StorageInfo struct {
|
||||||
|
Total int64 // Total disk space.
|
||||||
|
Free int64 // Free total available disk space.
|
||||||
|
}
|
||||||
|
|
||||||
// BucketInfo - bucket name and create date
|
// BucketInfo - bucket name and create date
|
||||||
type BucketInfo struct {
|
type BucketInfo struct {
|
||||||
Name string
|
Name string
|
||||||
Created time.Time
|
Created time.Time
|
||||||
Total int64
|
|
||||||
Free int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectInfo - object info.
|
// ObjectInfo - object info.
|
||||||
|
@ -20,6 +20,9 @@ import "io"
|
|||||||
|
|
||||||
// ObjectLayer implements primitives for object API layer.
|
// ObjectLayer implements primitives for object API layer.
|
||||||
type ObjectLayer interface {
|
type ObjectLayer interface {
|
||||||
|
// Storage operations.
|
||||||
|
StorageInfo() StorageInfo
|
||||||
|
|
||||||
// Bucket operations.
|
// Bucket operations.
|
||||||
MakeBucket(bucket string) error
|
MakeBucket(bucket string) error
|
||||||
GetBucketInfo(bucket string) (bucketInfo BucketInfo, err error)
|
GetBucketInfo(bucket string) (bucketInfo BucketInfo, err error)
|
||||||
|
24
posix.go
24
posix.go
@ -202,15 +202,6 @@ func (s fsStorage) MakeVol(volume string) (err error) {
|
|||||||
|
|
||||||
// ListVols - list volumes.
|
// ListVols - list volumes.
|
||||||
func (s fsStorage) ListVols() (volsInfo []VolInfo, err error) {
|
func (s fsStorage) ListVols() (volsInfo []VolInfo, err error) {
|
||||||
// Get disk info to be populated for VolInfo.
|
|
||||||
var diskInfo disk.Info
|
|
||||||
diskInfo, err = disk.GetInfo(s.diskPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil, errDiskNotFound
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
volsInfo, err = listVols(s.diskPath)
|
volsInfo, err = listVols(s.diskPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -219,9 +210,6 @@ func (s fsStorage) ListVols() (volsInfo []VolInfo, err error) {
|
|||||||
volInfo := VolInfo{
|
volInfo := VolInfo{
|
||||||
Name: vol.Name,
|
Name: vol.Name,
|
||||||
Created: vol.Created,
|
Created: vol.Created,
|
||||||
Total: diskInfo.Total,
|
|
||||||
Free: diskInfo.Free,
|
|
||||||
FSType: diskInfo.FSType,
|
|
||||||
}
|
}
|
||||||
volsInfo[i] = volInfo
|
volsInfo[i] = volInfo
|
||||||
}
|
}
|
||||||
@ -244,24 +232,12 @@ func (s fsStorage) StatVol(volume string) (volInfo VolInfo, err error) {
|
|||||||
}
|
}
|
||||||
return VolInfo{}, err
|
return VolInfo{}, err
|
||||||
}
|
}
|
||||||
// Get disk info, to be returned back along with volume info.
|
|
||||||
var diskInfo disk.Info
|
|
||||||
diskInfo, err = disk.GetInfo(s.diskPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return VolInfo{}, errDiskNotFound
|
|
||||||
}
|
|
||||||
return VolInfo{}, err
|
|
||||||
}
|
|
||||||
// As os.Stat() doesn't carry other than ModTime(), use ModTime()
|
// As os.Stat() doesn't carry other than ModTime(), use ModTime()
|
||||||
// as CreatedTime.
|
// as CreatedTime.
|
||||||
createdTime := st.ModTime()
|
createdTime := st.ModTime()
|
||||||
return VolInfo{
|
return VolInfo{
|
||||||
Name: volume,
|
Name: volume,
|
||||||
Created: createdTime,
|
Created: createdTime,
|
||||||
Free: diskInfo.Free,
|
|
||||||
Total: diskInfo.Total,
|
|
||||||
FSType: diskInfo.FSType,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,6 @@ import (
|
|||||||
type VolInfo struct {
|
type VolInfo struct {
|
||||||
Name string
|
Name string
|
||||||
Created time.Time
|
Created time.Time
|
||||||
Total int64
|
|
||||||
Free int64
|
|
||||||
FSType string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileInfo - file stat information.
|
// FileInfo - file stat information.
|
||||||
|
@ -98,6 +98,22 @@ func (web *webAPIHandlers) ServerInfo(r *http.Request, args *WebGenericArgs, rep
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StorageInfoRep - contains storage usage statistics.
|
||||||
|
type StorageInfoRep struct {
|
||||||
|
StorageInfo StorageInfo `json:"storageInfo"`
|
||||||
|
UIVersion string `json:"uiVersion"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageInfo - web call to gather storage usage statistics.
|
||||||
|
func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply *StorageInfoRep) error {
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: "Unauthorized request"}
|
||||||
|
}
|
||||||
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
|
reply.StorageInfo = web.ObjectAPI.StorageInfo()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MakeBucketArgs - make bucket args.
|
// MakeBucketArgs - make bucket args.
|
||||||
type MakeBucketArgs struct {
|
type MakeBucketArgs struct {
|
||||||
BucketName string `json:"bucketName"`
|
BucketName string `json:"bucketName"`
|
||||||
@ -127,10 +143,6 @@ type WebBucketInfo struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Date the bucket was created.
|
// Date the bucket was created.
|
||||||
CreationDate time.Time `json:"creationDate"`
|
CreationDate time.Time `json:"creationDate"`
|
||||||
// Total storage space where the bucket resides.
|
|
||||||
Total int64 `json:"total"`
|
|
||||||
// Free storage space where the bucket resides.
|
|
||||||
Free int64 `json:"free"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBuckets - list buckets api.
|
// ListBuckets - list buckets api.
|
||||||
@ -148,8 +160,6 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re
|
|||||||
reply.Buckets = append(reply.Buckets, WebBucketInfo{
|
reply.Buckets = append(reply.Buckets, WebBucketInfo{
|
||||||
Name: bucket.Name,
|
Name: bucket.Name,
|
||||||
CreationDate: bucket.Created,
|
CreationDate: bucket.Created,
|
||||||
Total: bucket.Total,
|
|
||||||
Free: bucket.Free,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
xl-v1.go
38
xl-v1.go
@ -20,8 +20,11 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/minio/minio/pkg/disk"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -33,6 +36,7 @@ const (
|
|||||||
// xlObjects - Implements fs object layer.
|
// xlObjects - Implements fs object layer.
|
||||||
type xlObjects struct {
|
type xlObjects struct {
|
||||||
storageDisks []StorageAPI
|
storageDisks []StorageAPI
|
||||||
|
physicalDisks []string
|
||||||
dataBlocks int
|
dataBlocks int
|
||||||
parityBlocks int
|
parityBlocks int
|
||||||
readQuorum int
|
readQuorum int
|
||||||
@ -147,6 +151,7 @@ func newXLObjects(disks []string) (ObjectLayer, error) {
|
|||||||
|
|
||||||
xl := xlObjects{
|
xl := xlObjects{
|
||||||
storageDisks: newPosixDisks,
|
storageDisks: newPosixDisks,
|
||||||
|
physicalDisks: disks,
|
||||||
dataBlocks: dataBlocks,
|
dataBlocks: dataBlocks,
|
||||||
parityBlocks: parityBlocks,
|
parityBlocks: parityBlocks,
|
||||||
listObjectMap: make(map[listParams][]*treeWalker),
|
listObjectMap: make(map[listParams][]*treeWalker),
|
||||||
@ -168,3 +173,36 @@ func newXLObjects(disks []string) (ObjectLayer, error) {
|
|||||||
// Return successfully initialized object layer.
|
// Return successfully initialized object layer.
|
||||||
return xl, nil
|
return xl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// byDiskTotal is a collection satisfying sort.Interface.
|
||||||
|
type byDiskTotal []disk.Info
|
||||||
|
|
||||||
|
func (d byDiskTotal) Len() int { return len(d) }
|
||||||
|
func (d byDiskTotal) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||||
|
func (d byDiskTotal) Less(i, j int) bool {
|
||||||
|
return d[i].Total < d[j].Total
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageInfo - returns underlying storage statistics.
|
||||||
|
func (xl xlObjects) StorageInfo() StorageInfo {
|
||||||
|
var disksInfo []disk.Info
|
||||||
|
for _, diskPath := range xl.physicalDisks {
|
||||||
|
info, err := disk.GetInfo(diskPath)
|
||||||
|
if err != nil {
|
||||||
|
errorIf(err, "Unable to fetch disk info for "+diskPath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
disksInfo = append(disksInfo, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort so that the first element is the smallest.
|
||||||
|
sort.Sort(byDiskTotal(disksInfo))
|
||||||
|
|
||||||
|
// Return calculated storage info, choose the lowest Total and
|
||||||
|
// Free as the total aggregated values. Total capacity is always
|
||||||
|
// the multiple of smallest disk among the disk list.
|
||||||
|
return StorageInfo{
|
||||||
|
Total: disksInfo[0].Total * int64(len(xl.storageDisks)),
|
||||||
|
Free: disksInfo[0].Free * int64(len(xl.storageDisks)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user