Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement the UpdateStorageSpace method #2162

Merged
merged 1 commit into from
Oct 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/unreleased/update-storage-spaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Implement the UpdateStorageSpace method

Added the UpdateStorageSpace method to the decomposedfs.

https://github.com/cs3org/reva/pull/2162
4 changes: 1 addition & 3 deletions internal/grpc/services/storageprovider/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora
}

func (s *service) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return &provider.UpdateStorageSpaceResponse{
Status: status.NewUnimplemented(ctx, errtypes.NotSupported("UpdateStorageSpace not implemented"), "UpdateStorageSpace not implemented"),
}, nil
return s.storage.UpdateStorageSpace(ctx, req)
}

func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) (*provider.DeleteStorageSpaceResponse, error) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/storage/fs/nextcloud/nextcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -792,3 +792,19 @@ func (nc *StorageDriver) CreateStorageSpace(ctx context.Context, req *provider.C
}
return &respObj, nil
}

// UpdateStorageSpace updates a storage space
func (nc *StorageDriver) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
bodyStr, _ := json.Marshal(req)
_, respBody, err := nc.do(ctx, Action{"UpdateStorageSpace", string(bodyStr)})
if err != nil {
return nil, err
}
var respObj provider.UpdateStorageSpaceResponse
fmt.Println(string(respBody))
err = json.Unmarshal(respBody, &respObj)
if err != nil {
return nil, err
}
return &respObj, nil
}
5 changes: 5 additions & 0 deletions pkg/storage/fs/owncloud/owncloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,11 @@ func (fs *ocfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListSt
return nil, errtypes.NotSupported("list storage spaces")
}

// UpdateStorageSpace updates a storage space
func (fs *ocfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}

func (fs *ocfs) propagate(ctx context.Context, leafPath string) error {
var root string
if fs.c.EnableHome {
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/owncloudsql/owncloudsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,11 @@ func (fs *owncloudsqlfs) ListStorageSpaces(ctx context.Context, filter []*provid
return nil, errtypes.NotSupported("list storage spaces")
}

// UpdateStorageSpace updates a storage space
func (fs *owncloudsqlfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}

func readChecksumIntoResourceChecksum(ctx context.Context, checksums, algo string, ri *provider.ResourceInfo) {
re := regexp.MustCompile(strings.ToUpper(algo) + `:(.*)`)
matches := re.FindStringSubmatch(checksums)
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,3 +680,8 @@ func (fs *s3FS) RestoreRecycleItem(ctx context.Context, basePath, key, relativeP
func (fs *s3FS) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) {
return nil, errtypes.NotSupported("list storage spaces")
}

// UpdateStorageSpace updates a storage space
func (fs *s3FS) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}
1 change: 1 addition & 0 deletions pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type FS interface {
UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error
ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error)
CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error)
UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error)
}

// Registry is the interface that storage registries implement
Expand Down
230 changes: 151 additions & 79 deletions pkg/storage/utils/decomposedfs/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ import (
"github.com/pkg/xattr"
)

const (
spaceTypeAny = "*"
spaceIDAny = "*"
)

// CreateStorageSpace creates a storage space
func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) {
// spaces will be located by default in the root of the storage.
Expand Down Expand Up @@ -163,8 +168,8 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide
// we would not need /nodes/root if access always happened via spaceid+relative path

var (
spaceType = "*"
spaceID = "*"
spaceType = spaceTypeAny
spaceID = spaceIDAny
)

for i := range filter {
Expand Down Expand Up @@ -206,102 +211,84 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide
appctx.GetLogger(ctx).Error().Err(err).Str("id", filepath.Base(target)).Msg("could not read node, skipping")
continue
}

spaceType := filepath.Base(filepath.Dir(matches[i]))

owner, err := n.Owner()
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not read owner, skipping")
continue
}

// TODO apply more filters

space := &provider.StorageSpace{
// FIXME the driver should know its id move setting the spaceid from the storage provider to the drivers
//Id: &provider.StorageSpaceId{OpaqueId: "1284d238-aa92-42ce-bdc4-0b0000009157!" + n.ID},
Root: &provider.ResourceId{
// FIXME the driver should know its id move setting the spaceid from the storage provider to the drivers
//StorageId: "1284d238-aa92-42ce-bdc4-0b0000009157",
OpaqueId: n.ID,
},
Name: n.Name,
SpaceType: filepath.Base(filepath.Dir(matches[i])),
// Mtime is set either as node.tmtime or as fi.mtime below
}

switch space.SpaceType {
case "share":
if utils.UserEqual(u.Id, owner) {
// do not list shares as spaces for the owner
continue
}
default:
sname, err := xattr.Get(n.InternalPath(), xattrs.SpaceNameAttr)
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not read space name, attribute not found")
continue
}
space.Name = string(sname)
if spaceType == "share" && utils.UserEqual(u.Id, owner) {
// do not list shares as spaces for the owner
continue
}

// filter out spaces user cannot access (currently based on stat permission)
p, err := n.ReadUserPermissions(ctx, u)
// TODO apply more filters
space, err := fs.storageSpaceFromNode(ctx, n, matches[i], spaceType)
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not read permissions, skipping")
continue
}
if !p.Stat {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not convert to storage space")
continue
}
spaces = append(spaces, space)
}
}

// fill in user object if the current user is the owner
if utils.UserEqual(u.Id, owner) {
space.Owner = u
} else {
space.Owner = &userv1beta1.User{ // FIXME only return a UserID, not a full blown user object
Id: owner,
}
}
return spaces, nil

// we set the space mtime to the root item mtime
// override the stat mtime with a tmtime if it is present
if tmt, err := n.GetTMTime(); err == nil {
un := tmt.UnixNano()
space.Mtime = &types.Timestamp{
Seconds: uint64(un / 1000000000),
Nanos: uint32(un % 1000000000),
}
} else if fi, err := os.Stat(matches[i]); err == nil {
// fall back to stat mtime
un := fi.ModTime().UnixNano()
space.Mtime = &types.Timestamp{
Seconds: uint64(un / 1000000000),
Nanos: uint32(un % 1000000000),
}
}
}

// quota
v, err := xattr.Get(matches[i], xattrs.QuotaAttr)
if err == nil {
// make sure we have a proper signed int
// we use the same magic numbers to indicate:
// -1 = uncalculated
// -2 = unknown
// -3 = unlimited
if quota, err := strconv.ParseUint(string(v), 10, 64); err == nil {
space.Quota = &provider.Quota{
QuotaMaxBytes: quota,
QuotaMaxFiles: math.MaxUint64, // TODO MaxUInt64? = unlimited? why even max files? 0 = unlimited?
}
} else {
appctx.GetLogger(ctx).Debug().Err(err).Str("nodepath", matches[i]).Msg("could not read quota")
}
}
// UpdateStorageSpace updates a storage space
func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
space := req.StorageSpace

spaces = append(spaces, space)
_, spaceID, err := utils.SplitStorageSpaceID(space.Id.OpaqueId)
if err != nil {
return nil, err
}

matches, err := filepath.Glob(filepath.Join(fs.o.Root, "spaces", spaceTypeAny, spaceID))
if err != nil {
return nil, err
}

if len(matches) != 1 {
return nil, errors.New("multiple spaces found")
}

target, err := os.Readlink(matches[0])
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Str("match", matches[0]).Msg("could not read link, skipping")
}

node, err := node.ReadNode(ctx, fs.lu, filepath.Base(target))
if err != nil {
return nil, err
}

if space.Name != "" {
if err := node.SetMetadata(xattrs.SpaceNameAttr, space.Name); err != nil {
return nil, err
}
}

return spaces, nil
if space.Quota != nil {
if err := node.SetMetadata(xattrs.QuotaAttr, strconv.FormatUint(space.Quota.QuotaMaxBytes, 10)); err != nil {
return nil, err
}
}

spaceType := filepath.Base(filepath.Dir(matches[0]))
updated, err := fs.storageSpaceFromNode(ctx, node, matches[0], spaceType)
if err != nil {
return nil, err
}

return &provider.UpdateStorageSpaceResponse{
Status: &v1beta11.Status{Code: v1beta11.Code_CODE_OK},
StorageSpace: updated,
}, nil
}

// createHiddenSpaceFolder bootstraps a storage space root with a hidden ".space" folder used to store space related
Expand Down Expand Up @@ -336,3 +323,88 @@ func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, nodeI

return nil
}

func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, node *node.Node, nodePath, spaceType string) (*provider.StorageSpace, error) {
owner, err := node.Owner()
if err != nil {
return nil, err
}

// TODO apply more filters

space := &provider.StorageSpace{
// FIXME the driver should know its id move setting the spaceid from the storage provider to the drivers
//Id: &provider.StorageSpaceId{OpaqueId: "1284d238-aa92-42ce-bdc4-0b0000009157!" + n.ID},
Root: &provider.ResourceId{
// FIXME the driver should know its id move setting the spaceid from the storage provider to the drivers
//StorageId: "1284d238-aa92-42ce-bdc4-0b0000009157",
OpaqueId: node.ID,
},
Name: node.Name,
SpaceType: spaceType,
// Mtime is set either as node.tmtime or as fi.mtime below
}

switch space.SpaceType {
case "project":
sname, err := xattr.Get(node.InternalPath(), xattrs.SpaceNameAttr)
if err != nil {
return nil, err
}
space.Name = string(sname)
default:
space.Name = "root"
}

user := ctxpkg.ContextMustGetUser(ctx)

// filter out spaces user cannot access (currently based on stat permission)
p, err := node.ReadUserPermissions(ctx, user)
if err != nil {
return nil, err
}
if !p.Stat {
return nil, errors.New("user is not allowed to Stat the space")
}

space.Owner = &userv1beta1.User{ // FIXME only return a UserID, not a full blown user object
Id: owner,
}

// we set the space mtime to the root item mtime
// override the stat mtime with a tmtime if it is present
if tmt, err := node.GetTMTime(); err == nil {
un := tmt.UnixNano()
space.Mtime = &types.Timestamp{
Seconds: uint64(un / 1000000000),
Nanos: uint32(un % 1000000000),
}
} else if fi, err := os.Stat(nodePath); err == nil {
// fall back to stat mtime
un := fi.ModTime().UnixNano()
space.Mtime = &types.Timestamp{
Seconds: uint64(un / 1000000000),
Nanos: uint32(un % 1000000000),
}
}

// quota
v, err := xattr.Get(nodePath, xattrs.QuotaAttr)
if err == nil {
// make sure we have a proper signed int
// we use the same magic numbers to indicate:
// -1 = uncalculated
// -2 = unknown
// -3 = unlimited
if quota, err := strconv.ParseUint(string(v), 10, 64); err == nil {
space.Quota = &provider.Quota{
QuotaMaxBytes: quota,
QuotaMaxFiles: math.MaxUint64, // TODO MaxUInt64? = unlimited? why even max files? 0 = unlimited?
}
} else {
return nil, err
}
}

return space, nil
}
5 changes: 5 additions & 0 deletions pkg/storage/utils/eosfs/eosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,11 @@ func (fs *eosfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListS
return nil, errtypes.NotSupported("list storage spaces")
}

// UpdateStorageSpace updates a storage space
func (fs *eosfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}

func (fs *eosfs) convertToRecycleItem(ctx context.Context, eosDeletedItem *eosclient.DeletedEntry) (*provider.RecycleItem, error) {
path, err := fs.unwrap(ctx, eosDeletedItem.RestorePath)
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/utils/localfs/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,11 @@ func (fs *localfs) ListStorageSpaces(ctx context.Context, filter []*provider.Lis
return nil, errtypes.NotSupported("list storage spaces")
}

// UpdateStorageSpace updates a storage space
func (fs *localfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}

func (fs *localfs) propagate(ctx context.Context, leafPath string) error {

var root string
Expand Down