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

Implementation of CS3 Lock API for EOS storage driver #2444

Merged
merged 57 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a2ba99a
Add option in eosclient to set an attr only if it does not exist
gmgigi96 Jan 14, 2022
7ee4f9f
Add error when an attribute is already set on a resource
gmgigi96 Jan 28, 2022
ba61ccd
Add error when trying to remove an attribute that does not exist
gmgigi96 Jan 28, 2022
5490570
eosbinary: add option to set the attr only if it does not exist
gmgigi96 Jan 28, 2022
e8dc1f8
eosgrpc: update protobuf definition
gmgigi96 Jan 14, 2022
941a294
eosgrpc: GetAttr implementation
gmgigi96 Jan 14, 2022
4cae13a
eosgrpc: add option to set an xattr only if does not exist
gmgigi96 Jan 14, 2022
1277e42
Implement GetLock method for eos storage
gmgigi96 Jan 28, 2022
0086830
Implement Unlock method for eos storage
gmgigi96 Jan 13, 2022
9ae8dd5
Implement SetLock (not atomic) and RefreshLock for eos storage
gmgigi96 Jan 28, 2022
020dcbd
Filter lock key while listing attr
gmgigi96 Jan 14, 2022
5f0e299
Add changelog
gmgigi96 Jan 14, 2022
2ca669c
Update grpc to version 1.43
gmgigi96 Jan 14, 2022
c86abb1
Update go-cs3api package (TO BE REMOVED BEFORE THE MERGE)
gmgigi96 Jan 28, 2022
e7b2b86
Removed all expiration logic
gmgigi96 Jan 31, 2022
0d5b15a
Merge branch 'master' into eos-lock
gmgigi96 Jan 31, 2022
02d10eb
Move same eos logic in a common package
gmgigi96 Jan 31, 2022
faece4e
Fix AddACL linting
gmgigi96 Jan 31, 2022
0826302
CLI cmds for lock
gmgigi96 Jan 31, 2022
4154f88
Encode and decode lock struct in eos in base64
gmgigi96 Jan 31, 2022
e6fd7db
eosbinary: fix deserializeAttribute
gmgigi96 Jan 31, 2022
d74d4e3
Change signature Unlock method to accept a lock parameter
gmgigi96 Feb 1, 2022
b7281e7
Update signature Unlock in all storage driver to accept a lock parameter
gmgigi96 Feb 1, 2022
16e12a9
Check lock id when unlock
gmgigi96 Feb 1, 2022
1c5ded0
Pass lock to storage driver from the UnlockRequest
gmgigi96 Feb 1, 2022
9565fcd
Review fixes
gmgigi96 Feb 1, 2022
956a161
Check same holde in unlock and check write access when setting lock w…
gmgigi96 Feb 1, 2022
82539d0
Return right errors on set and unset attrs
gmgigi96 Feb 3, 2022
2d8e013
eosfs: pass to write and read check the path already resolved
gmgigi96 Feb 3, 2022
4eaa44c
Fixes
gmgigi96 Feb 4, 2022
1b28860
check if user in lock is not nil
gmgigi96 Feb 7, 2022
cd66d9d
Add Precondition Failed error
gmgigi96 Feb 10, 2022
fb08150
Fixed return errors
gmgigi96 Feb 10, 2022
4e2c5bc
fix error code xrdcp
gmgigi96 Feb 15, 2022
ba1521b
fix linter
gmgigi96 Feb 15, 2022
f5330e9
check before err != nil
gmgigi96 Feb 15, 2022
d95e178
go mod tidy
gmgigi96 Feb 15, 2022
d68188d
Merge branch 'master' into eos-lock
gmgigi96 Feb 15, 2022
655daf1
fix go sum
gmgigi96 Feb 15, 2022
3ca9223
add license header
gmgigi96 Feb 15, 2022
5cd7c69
Deprecate use of grpc.WithInsecure method
gmgigi96 Feb 17, 2022
6aa3b64
fix linter
gmgigi96 Feb 17, 2022
1f20035
Implemented expiration for GetLock
gmgigi96 Mar 31, 2022
ef9adac
implemented SetLock with expiration time
gmgigi96 Mar 31, 2022
0b6f1ac
implemented refresh lock and unlock
gmgigi96 Mar 31, 2022
ac0faa0
remove sys lock from stat
gmgigi96 Mar 31, 2022
81ec620
fix expiration set when not provided
gmgigi96 Apr 7, 2022
eefd271
fix GetAttr
gmgigi96 Apr 7, 2022
d57e321
fix lock keys
gmgigi96 Apr 7, 2022
0a316aa
discard attr not set when unlocking if expiration was not set
gmgigi96 Apr 7, 2022
b8dbb98
return not found when either type or payload key in the lock is not s…
gmgigi96 Apr 7, 2022
99e4678
improved setlock code
gmgigi96 Apr 7, 2022
654c717
fix check expiration time for lock
gmgigi96 Apr 7, 2022
2af96ed
check if attribute was already set only for SetLock
gmgigi96 Apr 8, 2022
f39dbd2
remove unused code
gmgigi96 Apr 13, 2022
c1abb88
fix after rebase
gmgigi96 Apr 20, 2022
45bd16a
Fix type lock type
gmgigi96 Apr 20, 2022
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
4 changes: 4 additions & 0 deletions changelog/unreleased/eos-lock-implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Enhancement: Implement the CS3 Lock API in the EOS storage driver

https://github.com/cs3org/cs3apis/pull/160
https://github.com/cs3org/reva/pull/2444
70 changes: 70 additions & 0 deletions cmd/reva/getlock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package main

import (
"errors"
"fmt"
"io"

rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/gdexlab/go-render/render"
)

func getlockCommand() *command {
cmd := newCommand("getlock")
cmd.Description = func() string { return "get a lock on a resource" }
cmd.Usage = func() string { return "Usage: getlock <resource_path>" }

cmd.ResetFlags = func() {}

cmd.Action = func(w ...io.Writer) error {
if cmd.NArg() < 1 {
return errors.New("Invalid arguments: " + cmd.Usage())
}

fn := cmd.Args()[0]
client, err := getClient()
if err != nil {
return err
}

ctx := getAuthContext()

ref := &provider.Reference{Path: fn}

res, err := client.GetLock(ctx, &provider.GetLockRequest{
Ref: ref,
})

if err != nil {
return err
}

if res.Status.Code != rpc.Code_CODE_OK {
return formatError(res.Status)
}

fmt.Println(render.Render(res.Lock))

return nil
}
return cmd
}
3 changes: 2 additions & 1 deletion cmd/reva/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"google.golang.org/grpc"
ins "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)

Expand All @@ -56,7 +57,7 @@ func getClient() (gateway.GatewayAPIClient, error) {

func getConn() (*grpc.ClientConn, error) {
if insecure {
return grpc.Dial(conf.Host, grpc.WithInsecure())
return grpc.Dial(conf.Host, grpc.WithTransportCredentials(ins.NewCredentials()))
}

// TODO(labkode): if in the future we want client-side certificate validation,
Expand Down
3 changes: 3 additions & 0 deletions cmd/reva/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ var (
appTokensListCommand(),
appTokensRemoveCommand(),
appTokensCreateCommand(),
setlockCommand(),
getlockCommand(),
unlockCommand(),
helpCommand(),
}
)
Expand Down
171 changes: 171 additions & 0 deletions cmd/reva/setlock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package main

import (
"context"
"errors"
"fmt"
"io"
"time"

gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
)

func setlockCommand() *command {
cmd := newCommand("setlock")
cmd.Description = func() string { return "set a lock on a resource" }
cmd.Usage = func() string { return "Usage: setlock [-flags] <resource_path>" }

typeFlag := cmd.String("type", "write", "type of lock")
idFlag := cmd.String("id", "", "id of lock")
userFlag := cmd.String("user", "", "user associated to lock")
appFlag := cmd.String("app", "", "app associated to lock")
expFlag := cmd.String("exp", "", "lock expiration time")
refreshFlag := cmd.Bool("refresh", false, "refresh the lock")

cmd.ResetFlags = func() {
*typeFlag, *idFlag, *userFlag, *appFlag, *expFlag, *refreshFlag = "", "", "", "", "", false
}

cmd.Action = func(w ...io.Writer) error {
if cmd.NArg() < 1 {
return errors.New("Invalid arguments: " + cmd.Usage())
}

fn := cmd.Args()[0]
client, err := getClient()
if err != nil {
return err
}

ctx := getAuthContext()

lock, err := createLock(ctx, client, *typeFlag, *idFlag, *userFlag, *appFlag, *expFlag)
if err != nil {
return err
}

ref := &provider.Reference{Path: fn}

if *refreshFlag {
res, err := client.RefreshLock(ctx, &provider.RefreshLockRequest{
Ref: ref,
Lock: lock,
})
if err != nil {
return err
}

if res.Status.Code != rpc.Code_CODE_OK {
return formatError(res.Status)
}
} else {
res, err := client.SetLock(ctx, &provider.SetLockRequest{
Ref: ref,
Lock: lock,
})
if err != nil {
return err
}

if res.Status.Code != rpc.Code_CODE_OK {
return formatError(res.Status)
}
}

fmt.Println("OK")

return nil
}
return cmd
}

func createLock(ctx context.Context, client gateway.GatewayAPIClient, t, id, u, app, exp string) (*provider.Lock, error) {
lockType, err := getType(t)
if err != nil {
return nil, err
}
var uID *user.UserId
if u != "" {
u, err := getUser(ctx, client, u)
if err != nil {
return nil, err
}
uID = u.GetId()
}
var expiration *types.Timestamp
if exp != "" {
expiration, err = getExpiration(exp)
if err != nil {
return nil, err
}
}

lock := provider.Lock{
LockId: id,
Type: lockType,
User: uID,
AppName: app,
Expiration: expiration,
}

return &lock, nil
}

func getType(t string) (provider.LockType, error) {
switch t {
case "shared":
return provider.LockType_LOCK_TYPE_SHARED, nil
case "write":
return provider.LockType_LOCK_TYPE_WRITE, nil
case "exclusive":
return provider.LockType_LOCK_TYPE_EXCL, nil
default:
return provider.LockType_LOCK_TYPE_INVALID, errors.New("type not recognised")
}
}

func getUser(ctx context.Context, client gateway.GatewayAPIClient, u string) (*user.User, error) {
res, err := client.GetUserByClaim(ctx, &user.GetUserByClaimRequest{
Claim: "username",
Value: u,
})
switch {
case err != nil:
return nil, err
case res.Status.Code != rpc.Code_CODE_OK:
return nil, errors.New(res.Status.Message)
}
return res.User, nil
}

func getExpiration(exp string) (*types.Timestamp, error) {
t, err := time.Parse("2006-01-02", exp)
if err != nil {
return nil, err
}
return &types.Timestamp{
Seconds: uint64(t.Unix()),
}, nil
}
93 changes: 93 additions & 0 deletions cmd/reva/unlock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package main

import (
"errors"
"fmt"
"io"

rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
)

func unlockCommand() *command {
cmd := newCommand("unlock")
cmd.Description = func() string { return "remove a lock on a resource" }
cmd.Usage = func() string { return "Usage: unlock <resource_path>" }

idFlag := cmd.String("id", "", "lock id")

cmd.ResetFlags = func() {
*idFlag = ""
}

cmd.Action = func(w ...io.Writer) error {
if cmd.NArg() < 1 {
return errors.New("Invalid arguments: " + cmd.Usage())
}

fn := cmd.Args()[0]
client, err := getClient()
if err != nil {
return err
}

ctx := getAuthContext()

ref := &provider.Reference{Path: fn}

// get lock from the id if set
var lock *provider.Lock
if *idFlag == "" {
getLockRes, err := client.GetLock(ctx, &provider.GetLockRequest{
Ref: ref,
})
if err != nil {
return err
}
if getLockRes.Status.Code != rpc.Code_CODE_OK {
return formatError(getLockRes.Status)
}
lock = getLockRes.Lock
} else {
lock = &provider.Lock{
LockId: *idFlag,
}
}

res, err := client.Unlock(ctx, &provider.UnlockRequest{
Ref: ref,
Lock: lock,
})

if err != nil {
return err
}

if res.Status.Code != rpc.Code_CODE_OK {
return formatError(res.Status)
}

fmt.Println("OK")

return nil
}
return cmd
}
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,4 @@ go 1.16
replace (
github.com/eventials/go-tus => github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a
github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1
google.golang.org/grpc => google.golang.org/grpc v1.26.0 // temporary downgrade
)
Loading