1
0
mirror of https://github.com/gluster/glusterd2.git synced 2026-02-06 06:45:35 +01:00
Files
glusterd2/plugins/device/deviceutils/store-utils.go
Aravinda VK bebbc65052 Support for loopback bricks
Register the Bricks hosting directory using,

```
glustercli device add <peerid> <path> --provisioner loop
```

Example:

```
glustercli device add 70d79c3f-e7af-43f6-8b65-05dff2423da1 \
	   /exports --provisioner loop
```

Now create the volume using,

```
glustercli volume create gv1 --size 1G \
	   --provisioner loop \
	   --replica 3
```

Fixes: #1418
Signed-off-by: Aravinda VK <avishwan@redhat.com>
2019-02-14 10:49:17 +05:30

235 lines
6.2 KiB
Go

package deviceutils
import (
"context"
"encoding/json"
"github.com/gluster/glusterd2/glusterd2/brick"
"github.com/gluster/glusterd2/glusterd2/gdctx"
"github.com/gluster/glusterd2/glusterd2/store"
"github.com/gluster/glusterd2/glusterd2/transaction"
gderrors "github.com/gluster/glusterd2/pkg/errors"
"github.com/gluster/glusterd2/pkg/lvmutils"
deviceapi "github.com/gluster/glusterd2/plugins/device/api"
"github.com/coreos/etcd/clientv3"
)
const (
devicePrefix string = "devices/"
)
// GetDevices returns devices of specified peer/peers from the store
// if no peers are specified, it returns devices of all peers
func GetDevices(peerIds ...string) ([]deviceapi.Info, error) {
var devices []deviceapi.Info
var err error
var resp *clientv3.GetResponse
if len(peerIds) > 0 {
for _, peerID := range peerIds {
resp, err = store.Get(context.TODO(), devicePrefix+peerID+"/", clientv3.WithPrefix())
if err != nil {
return nil, err
}
}
} else {
resp, err = store.Get(context.TODO(), devicePrefix, clientv3.WithPrefix())
if err != nil {
return nil, err
}
}
for _, kv := range resp.Kvs {
var dev deviceapi.Info
if err = json.Unmarshal(kv.Value, &dev); err != nil {
return nil, err
}
devices = append(devices, dev)
}
return devices, nil
}
// GetDevice returns device of specified peer and device name
func GetDevice(peerID, deviceName string) (*deviceapi.Info, error) {
var device deviceapi.Info
var err error
resp, err := store.Get(context.TODO(), devicePrefix+peerID+"/"+deviceName)
if err != nil {
return nil, err
}
if resp.Count != 1 {
return nil, gderrors.ErrDeviceNotFound
}
if err = json.Unmarshal(resp.Kvs[0].Value, &device); err != nil {
return nil, err
}
return &device, nil
}
// SetDeviceState sets device state and updates device state in etcd
func SetDeviceState(peerID, deviceName, deviceState string) error {
dev, err := GetDevice(peerID, deviceName)
if err != nil {
return err
}
dev.State = deviceState
return AddOrUpdateDevice(*dev)
}
// AddOrUpdateDevice adds device to peerinfo
func AddOrUpdateDevice(device deviceapi.Info) error {
json, err := json.Marshal(device)
if err != nil {
return err
}
storeKey := device.PeerID.String() + "/" + device.Device
if _, err := store.Put(context.TODO(), devicePrefix+storeKey, string(json)); err != nil {
return err
}
return nil
}
// UpdateDeviceFreeSize updates the actual available size of VG
func UpdateDeviceFreeSize(peerID, device string) error {
dev, err := GetDevice(peerID, device)
if err != nil {
return err
}
availableSize, extentSize, err := lvmutils.GetVgAvailableSize(dev.VgName())
if err != nil {
return err
}
dev.AvailableSize = availableSize
dev.UsedSize = dev.TotalSize - availableSize
dev.ExtentSize = extentSize
return AddOrUpdateDevice(*dev)
}
// AddDeviceFreeSize updates device available size
func AddDeviceFreeSize(peerID, device string, size uint64) error {
clusterLocks := transaction.Locks{}
if err := clusterLocks.Lock(peerID + device); err != nil {
return err
}
defer clusterLocks.UnLock(context.Background())
dev, err := GetDevice(peerID, device)
if err != nil {
return err
}
dev.AvailableSize = dev.AvailableSize + size
dev.UsedSize = dev.TotalSize - dev.AvailableSize
return AddOrUpdateDevice(*dev)
}
// ReduceDeviceFreeSize updates device available size
func ReduceDeviceFreeSize(peerID, device string, size uint64) error {
clusterLocks := transaction.Locks{}
if err := clusterLocks.Lock(peerID + device); err != nil {
return err
}
defer clusterLocks.UnLock(context.Background())
dev, err := GetDevice(peerID, device)
if err != nil {
return err
}
dev.AvailableSize = dev.AvailableSize - size
dev.UsedSize = dev.TotalSize - dev.AvailableSize
return AddOrUpdateDevice(*dev)
}
// UpdateDeviceFreeSizeByVg updates the actual available size of VG
func UpdateDeviceFreeSizeByVg(peerID, vgname string) error {
devs, err := GetDevices(peerID)
if err != nil {
return err
}
for _, dev := range devs {
if dev.VgName() == vgname {
availableSize, extentSize, err := lvmutils.GetVgAvailableSize(vgname)
if err != nil {
return err
}
dev.AvailableSize = availableSize
dev.UsedSize = dev.TotalSize - availableSize
dev.ExtentSize = extentSize
return AddOrUpdateDevice(dev)
}
}
return gderrors.ErrDeviceNotFound
}
//IsVgExist checks whether the given vg exist in the device list for the local peer
func IsVgExist(vgname string) bool {
peerID := gdctx.MyUUID.String()
deviceDetails, err := GetDevices(peerID)
if err != nil {
return false
}
for _, dev := range deviceDetails {
if dev.VgName() == vgname {
return true
}
}
return false
}
// GetDeviceAvailableSize gets the device size and vgName using device Path
func GetDeviceAvailableSize(peerID, device string) (uint64, error) {
dev, err := GetDevice(peerID, device)
if err != nil {
return 0, err
}
return dev.AvailableSize, nil
}
// CheckForAvailableVgSize prepares a brickName to vgName mapping in order to use while expanding lvm.
// Also it checks for sufficient space available on devices of current node.
func CheckForAvailableVgSize(expansionSize uint64, bricksInfo []brick.Brickinfo) (map[string]string, bool, error) {
// map of brickName to vgName. Used while extending lv
brickVgMapping := make(map[string]string)
// map of deviceName to required free size in that device
requiredDeviceSizeMap := make(map[string]uint64)
// Map deviceName to required free space on the device
for _, b := range bricksInfo {
if _, ok := requiredDeviceSizeMap[b.MountInfo.DevicePath]; !ok {
requiredDeviceSizeMap[b.MountInfo.DevicePath] = expansionSize
} else {
requiredDeviceSizeMap[b.MountInfo.DevicePath] += expansionSize
}
}
// Check in the map prepared in last step by looking through devices names and device available size of bricks from current node.
for _, b := range bricksInfo {
// retrieve device available size by device Name and return the vgName and available device Size.
deviceSize, err := GetDeviceAvailableSize(b.PeerID.String(), b.RootDevice)
if err != nil {
return map[string]string{}, false, err
}
if requiredDeviceSizeMap[b.MountInfo.DevicePath] > deviceSize {
return map[string]string{}, false, nil
}
brickVgMapping[b.Path] = b.DeviceInfo.VgName
}
return brickVgMapping, true, nil
}