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

eosfs: set quota #1477

Merged
merged 6 commits into from
Feb 15, 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
3 changes: 3 additions & 0 deletions changelog/unreleased/eos-set-quota.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Enhancement: Set quota when creating home directory in EOS

https://github.com/cs3org/reva/pull/1477
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ redis_address = "localhost:6379"
{{< /highlight >}}
{{% /dir %}}

{{% dir name="user_groups_cache_expiration" type="int" default=5 %}}
{{% dir name="group_members_cache_expiration" type="int" default=5 %}}
The time in minutes for which the members of a group would be cached [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/cbox/group/rest/rest.go#L75)
{{< highlight toml >}}
[cbox.group.rest]
user_groups_cache_expiration = 5
group_members_cache_expiration = 5
{{< /highlight >}}
{{% /dir %}}

Expand Down
3 changes: 3 additions & 0 deletions internal/grpc/services/gateway/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq
// TODO(labkode): if both commits are enabled they could be done concurrently.
if s.c.CommitShareToStorageGrant {
addGrantStatus, err := s.addGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, req.Grant.Permissions.Permissions)
if err != nil {
labkode marked this conversation as resolved.
Show resolved Hide resolved
return nil, errors.Wrap(err, "gateway: error adding grant to storage")
}
if addGrantStatus.Code != rpc.Code_CODE_OK {
return &collaboration.CreateShareResponse{
Status: addGrantStatus,
Expand Down
12 changes: 12 additions & 0 deletions pkg/eosclient/eosbinary/eosbinary.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,18 @@ func (c *Client) GetQuota(ctx context.Context, username, rootUID, rootGID, path
return c.parseQuota(path, stdout)
}

// SetQuota sets the quota of a user on the quota node defined by path
func (c *Client) SetQuota(ctx context.Context, rootUID, rootGID string, info *eosclient.SetQuotaInfo) error {
maxBytes := fmt.Sprintf("%d", info.MaxBytes)
maxFiles := fmt.Sprintf("%d", info.MaxFiles)
cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "quota", "set", "-u", info.Username, "-p", info.QuotaNode, "-v", maxBytes, "-i", maxFiles)
_, _, err := c.executeEOS(ctx, cmd)
if err != nil {
return err
}
return nil
}

// Touch creates a 0-size,0-replica file in the EOS namespace.
func (c *Client) Touch(ctx context.Context, uid, gid, path string) error {
cmd := exec.CommandContext(ctx, "/usr/bin/eos", "-r", uid, gid, "file", "touch", path)
Expand Down
10 changes: 10 additions & 0 deletions pkg/eosclient/eosclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type EOSClient interface {
SetAttr(ctx context.Context, uid, gid string, attr *Attribute, recursive bool, path string) error
UnsetAttr(ctx context.Context, uid, gid string, attr *Attribute, path string) error
GetQuota(ctx context.Context, username, rootUID, rootGID, path string) (*QuotaInfo, error)
SetQuota(ctx context.Context, rootUID, rootGID string, info *SetQuotaInfo) error
Touch(ctx context.Context, uid, gid, path string) error
Chown(ctx context.Context, uid, gid, chownUID, chownGID, path string) error
Chmod(ctx context.Context, uid, gid, mode, path string) error
Expand Down Expand Up @@ -99,3 +100,12 @@ type QuotaInfo struct {
AvailableBytes, UsedBytes int
AvailableInodes, UsedInodes int
}

// SetQuotaInfo encapsulates the information needed to
// create a quota space in EOS for a user
type SetQuotaInfo struct {
Username string
QuotaNode string
MaxBytes uint64
MaxFiles uint64
}
5 changes: 5 additions & 0 deletions pkg/eosclient/eosgrpc/eosgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ func (c *Client) GetQuota(ctx context.Context, username, rootUID, rootGID, path
return nil, errtypes.NotSupported("eosgrpc: GetQuota not implemented")
}

// SetQuota sets the quota of a user on the quota node defined by path
func (c *Client) SetQuota(ctx context.Context, rootUID, rootGID string, info *eosclient.SetQuotaInfo) error {
return errtypes.NotSupported("eosgrpc: SetQuota not implemented")
}

// Touch creates a 0-size,0-replica file in the EOS namespace.
func (c *Client) Touch(ctx context.Context, uid, gid, path string) error {
log := appctx.GetLogger(ctx)
Expand Down
9 changes: 9 additions & 0 deletions pkg/storage/utils/eosfs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ type Config struct {
// Namespace for metadata operations
Namespace string `mapstructure:"namespace"`

// QuotaNode for storing quota information
QuotaNode string `mapstructure:"quota_node"`

// DefaultQuotaBytes sets the default maximum bytes available for a user
DefaultQuotaBytes uint64 `mapstructure:"default_quota_bytes"`

// DefaultQuotaFiles sets the default maximum files available for a user
DefaultQuotaFiles uint64 `mapstructure:"default_quota_files"`

// ShadowNamespace for storing shadow data
ShadowNamespace string `mapstructure:"shadow_namespace"`

Expand Down
45 changes: 37 additions & 8 deletions pkg/storage/utils/eosfs/eosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ func (c *Config) init() {
c.ShadowNamespace = path.Join(c.Namespace, ".shadow")
}

// Quota node defaults to namespace if empty
if c.QuotaNode == "" {
c.QuotaNode = c.Namespace
}

if c.DefaultQuotaBytes == 0 {
c.DefaultQuotaBytes = 1000000000000 // 1 TB
}
if c.DefaultQuotaFiles == 0 {
c.DefaultQuotaFiles = 1000000 // 1 Million
}

if c.ShareFolder == "" {
c.ShareFolder = "/MyShares"
}
Expand Down Expand Up @@ -838,6 +850,25 @@ func (fs *eosfs) createNominalHome(ctx context.Context) error {
}

err = fs.createUserDir(ctx, u, home, false)
if err != nil {
err := errors.Wrap(err, "eosfs: error creating user dir")
return err
}

// set quota for user
quotaInfo := &eosclient.SetQuotaInfo{
Username: u.Username,
MaxBytes: fs.conf.DefaultQuotaBytes,
MaxFiles: fs.conf.DefaultQuotaFiles,
QuotaNode: fs.conf.QuotaNode,
}

err = fs.c.SetQuota(ctx, uid, gid, quotaInfo)
if err != nil {
err := errors.Wrap(err, "eosfs: error setting quota")
return err
}

return err
}

Expand Down Expand Up @@ -913,6 +944,7 @@ func (fs *eosfs) createUserDir(ctx context.Context, u *userpb.User, path string,
return errors.Wrap(err, "eos: error setting attribute")
}
}

return nil
}

Expand Down Expand Up @@ -941,11 +973,6 @@ func (fs *eosfs) CreateDir(ctx context.Context, p string) error {
func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.URL) error {
// TODO(labkode): for the time being we only allow to create references
// on the virtual share folder to not pollute the nominal user tree.
u, err := getUser(ctx)
if err != nil {
return errors.Wrap(err, "eos: no user in ctx")
}

if !fs.isShareFolder(ctx, p) {
return errtypes.PermissionDenied("eos: cannot create references outside the share folder: share_folder=" + fs.conf.ShareFolder + " path=" + p)
}
Expand All @@ -960,9 +987,11 @@ func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.U
if err != nil {
return nil
}
if err := fs.createUserDir(ctx, u, tmp, false); err != nil {
err = errors.Wrapf(err, "eos: error creating temporary ref file")
return err

err = fs.c.CreateDir(ctx, uid, gid, tmp)
ishank011 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
// EOS will return success on mkdir over an existing directory.
return errors.Wrap(err, "eos: error creating ref-dir")
}

// set xattr on ref
Expand Down