seaweedfs/weed/filer/remote_storage.go

182 lines
5.8 KiB
Go
Raw Permalink Normal View History

2021-07-27 05:53:44 +00:00
package filer
import (
"context"
"fmt"
"github.com/seaweedfs/seaweedfs/weed/pb"
"github.com/seaweedfs/seaweedfs/weed/pb/remote_pb"
"github.com/seaweedfs/seaweedfs/weed/remote_storage"
"github.com/seaweedfs/seaweedfs/weed/util"
2021-08-04 23:25:46 +00:00
"google.golang.org/grpc"
2022-08-17 19:05:07 +00:00
"google.golang.org/protobuf/proto"
2021-07-27 05:53:44 +00:00
"math"
2021-07-27 08:16:28 +00:00
"strings"
2021-07-27 05:53:44 +00:00
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
2021-07-27 05:53:44 +00:00
"github.com/viant/ptrie"
)
2021-07-27 08:16:28 +00:00
const REMOTE_STORAGE_CONF_SUFFIX = ".conf"
const REMOTE_STORAGE_MOUNT_FILE = "mount.mapping"
2021-07-27 05:53:44 +00:00
type FilerRemoteStorage struct {
2021-07-27 08:16:28 +00:00
rules ptrie.Trie
2021-08-26 22:18:34 +00:00
storageNameToConf map[string]*remote_pb.RemoteConf
2021-07-27 05:53:44 +00:00
}
2021-07-27 08:16:28 +00:00
func NewFilerRemoteStorage() (rs *FilerRemoteStorage) {
rs = &FilerRemoteStorage{
rules: ptrie.New(),
2021-08-26 22:18:34 +00:00
storageNameToConf: make(map[string]*remote_pb.RemoteConf),
2021-07-27 05:53:44 +00:00
}
2021-07-27 08:16:28 +00:00
return rs
2021-07-27 05:53:44 +00:00
}
func (rs *FilerRemoteStorage) LoadRemoteStorageConfigurationsAndMapping(filer *Filer) (err error) {
2021-07-27 08:16:28 +00:00
// execute this on filer
limit := int64(math.MaxInt32)
entries, _, err := filer.ListDirectoryEntries(context.Background(), DirectoryEtcRemote, "", false, limit, "", "", "")
2021-07-27 05:53:44 +00:00
if err != nil {
if err == filer_pb.ErrNotFound {
return nil
}
glog.Errorf("read remote storage %s: %v", DirectoryEtcRemote, err)
return
}
for _, entry := range entries {
2021-07-27 08:16:28 +00:00
if entry.Name() == REMOTE_STORAGE_MOUNT_FILE {
2021-08-01 05:39:38 +00:00
if err := rs.loadRemoteStorageMountMapping(entry.Content); err != nil {
return err
}
continue
2021-07-27 08:16:28 +00:00
}
if !strings.HasSuffix(entry.Name(), REMOTE_STORAGE_CONF_SUFFIX) {
return nil
}
2021-08-26 22:18:34 +00:00
conf := &remote_pb.RemoteConf{}
2021-07-27 05:53:44 +00:00
if err := proto.Unmarshal(entry.Content, conf); err != nil {
2021-07-27 08:16:28 +00:00
return fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, entry.Name(), err)
2021-07-27 05:53:44 +00:00
}
2021-07-27 08:16:28 +00:00
rs.storageNameToConf[conf.Name] = conf
2021-07-27 05:53:44 +00:00
}
return nil
}
2021-07-27 08:16:28 +00:00
func (rs *FilerRemoteStorage) loadRemoteStorageMountMapping(data []byte) (err error) {
2021-08-26 22:18:34 +00:00
mappings := &remote_pb.RemoteStorageMapping{}
2021-07-27 08:16:28 +00:00
if err := proto.Unmarshal(data, mappings); err != nil {
return fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, REMOTE_STORAGE_MOUNT_FILE, err)
}
2021-07-27 10:26:35 +00:00
for dir, storageLocation := range mappings.Mappings {
rs.mapDirectoryToRemoteStorage(util.FullPath(dir), storageLocation)
2021-07-27 08:16:28 +00:00
}
return nil
}
2021-08-26 22:18:34 +00:00
func (rs *FilerRemoteStorage) mapDirectoryToRemoteStorage(dir util.FullPath, loc *remote_pb.RemoteStorageLocation) {
rs.rules.Put([]byte(dir+"/"), loc)
2021-07-27 08:16:28 +00:00
}
2021-08-26 22:18:34 +00:00
func (rs *FilerRemoteStorage) FindMountDirectory(p util.FullPath) (mountDir util.FullPath, remoteLocation *remote_pb.RemoteStorageLocation) {
rs.rules.MatchPrefix([]byte(p), func(key []byte, value interface{}) bool {
2021-08-01 05:39:38 +00:00
mountDir = util.FullPath(string(key[:len(key)-1]))
2021-08-26 22:18:34 +00:00
remoteLocation = value.(*remote_pb.RemoteStorageLocation)
return true
})
return
}
2021-08-26 22:18:34 +00:00
func (rs *FilerRemoteStorage) FindRemoteStorageClient(p util.FullPath) (client remote_storage.RemoteStorageClient, remoteConf *remote_pb.RemoteConf, found bool) {
var storageLocation *remote_pb.RemoteStorageLocation
2021-07-27 08:16:28 +00:00
rs.rules.MatchPrefix([]byte(p), func(key []byte, value interface{}) bool {
2021-08-26 22:18:34 +00:00
storageLocation = value.(*remote_pb.RemoteStorageLocation)
2021-07-27 08:16:28 +00:00
return true
})
2021-08-04 07:31:06 +00:00
if storageLocation == nil {
found = false
2021-07-27 08:16:28 +00:00
return
}
2021-08-04 07:31:06 +00:00
return rs.GetRemoteStorageClient(storageLocation.Name)
}
2021-08-26 22:18:34 +00:00
func (rs *FilerRemoteStorage) GetRemoteStorageClient(storageName string) (client remote_storage.RemoteStorageClient, remoteConf *remote_pb.RemoteConf, found bool) {
remoteConf, found = rs.storageNameToConf[storageName]
if !found {
2021-07-27 08:16:28 +00:00
return
}
var err error
if client, err = remote_storage.GetRemoteStorage(remoteConf); err == nil {
found = true
return
}
return
}
2021-07-27 10:26:35 +00:00
2021-08-26 22:18:34 +00:00
func UnmarshalRemoteStorageMappings(oldContent []byte) (mappings *remote_pb.RemoteStorageMapping, err error) {
mappings = &remote_pb.RemoteStorageMapping{
Mappings: make(map[string]*remote_pb.RemoteStorageLocation),
2021-07-27 10:26:35 +00:00
}
if len(oldContent) > 0 {
if err = proto.Unmarshal(oldContent, mappings); err != nil {
glog.Warningf("unmarshal existing mappings: %v", err)
2021-07-27 10:26:35 +00:00
}
}
2021-08-01 05:39:38 +00:00
return
}
func ReadRemoteStorageConf(grpcDialOption grpc.DialOption, filerAddress pb.ServerAddress, storageName string) (conf *remote_pb.RemoteConf, readErr error) {
2021-08-04 23:25:46 +00:00
var oldContent []byte
if readErr = pb.WithFilerClient(false, 0, filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
2021-08-04 23:25:46 +00:00
oldContent, readErr = ReadInsideFiler(client, DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX)
return readErr
}); readErr != nil {
return nil, readErr
}
// unmarshal storage configuration
2021-08-26 22:18:34 +00:00
conf = &remote_pb.RemoteConf{}
2021-08-04 23:25:46 +00:00
if unMarshalErr := proto.Unmarshal(oldContent, conf); unMarshalErr != nil {
readErr = fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX, unMarshalErr)
return
}
return
}
func DetectMountInfo(grpcDialOption grpc.DialOption, filerAddress pb.ServerAddress, dir string) (*remote_pb.RemoteStorageMapping, string, *remote_pb.RemoteStorageLocation, *remote_pb.RemoteConf, error) {
mappings, listErr := ReadMountMappings(grpcDialOption, filerAddress)
if listErr != nil {
return nil, "", nil, nil, listErr
}
if dir == "" {
return mappings, "", nil, nil, fmt.Errorf("need to specify '-dir' option")
}
var localMountedDir string
2021-08-26 22:18:34 +00:00
var remoteStorageMountedLocation *remote_pb.RemoteStorageLocation
for k, loc := range mappings.Mappings {
if strings.HasPrefix(dir, k) {
localMountedDir, remoteStorageMountedLocation = k, loc
}
}
if localMountedDir == "" {
return mappings, localMountedDir, remoteStorageMountedLocation, nil, fmt.Errorf("%s is not mounted", dir)
}
// find remote storage configuration
remoteStorageConf, err := ReadRemoteStorageConf(grpcDialOption, filerAddress, remoteStorageMountedLocation.Name)
if err != nil {
return mappings, localMountedDir, remoteStorageMountedLocation, remoteStorageConf, err
}
return mappings, localMountedDir, remoteStorageMountedLocation, remoteStorageConf, nil
}