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

feature: add diskquota support regular expression #1057

Merged
merged 2 commits into from
Apr 16, 2018

Conversation

rudyfly
Copy link
Collaborator

@rudyfly rudyfly commented Apr 4, 2018

Ⅰ. Describe what this PR did

Add diskquota support regular expression.

Ⅱ. Does this pull request fix one issue?

NONE

Ⅲ. Describe how you did it

We can use pouch run --disk-quota="key=value" to set quota for container. This pr can make it support to use regular expression key, such as: --disk-quota=".=1g", it means all the quota of mount points are '1g', the priority of key '.' is the lowest. If it has no 'key', just have 'value', such as: --disk-quota=1g, it means the quota of rootfs is 1g. If the mountpoint is a volume, the quota of volume is base on volume's size, the disk-quota is not take effect on a volume.

Ⅳ. Describe how to verify it

The example is test case: TestRunWithDiskQuotaRegular

create a volume with size limit: 256m

# pouch volume create -n diskquota-volume -o size=256m -o mount=/data/volume
Name:         diskquota-volume
Scope:
Status:       map[mount:/data/volume sifter:Default size:256m]
CreatedAt:    2018-4-8 14:18:35
Driver:       local
Labels:       map[]
Mountpoint:   /data/volume/diskquota-volume

create a container with diskquota

# pouch run --name diskquota-test -ti --disk-quota="1024m" --disk-quota=".*=512m" --disk-quota="/mnt/mount1=768m" -v /data/mount1:/mnt/mount1 -v /data/mount2:/mnt/mount2 -v diskquota-volume:/mnt/diskquota-volume registry.docker-cn.com/library/busybox:latest df
Filesystem           1K-blocks      Used Available Use% Mounted on
overlay                1048576        40   1048536   0% /
tmpfs                    65536         0     65536   0% /dev
shm                      65536         0     65536   0% /dev/shm
tmpfs                    65536         0     65536   0% /run
/dev/sdb2               786432         4    786428   0% /mnt/mount1
/dev/sdb2               524288         4    524284   0% /mnt/mount2
/dev/sdb2               262144         4    262140   0% /mnt/diskquota-volume
tmpfs                    65536         0     65536   0% /proc/kcore
tmpfs                    65536         0     65536   0% /proc/timer_list
tmpfs                    65536         0     65536   0% /proc/sched_debug
tmpfs                  2008224         0   2008224   0% /sys/firmware
tmpfs                  2008224         0   2008224   0% /proc/scsi

Ⅴ. Special notes for reviews

Signed-off-by: Rudy Zhang rudyflyzhang@gmail.com

@codecov-io
Copy link

codecov-io commented Apr 4, 2018

Codecov Report

Merging #1057 into master will increase coverage by 0.07%.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1057      +/-   ##
==========================================
+ Coverage   15.62%   15.69%   +0.07%     
==========================================
  Files         172      172              
  Lines        9672     9673       +1     
==========================================
+ Hits         1511     1518       +7     
+ Misses       8052     8045       -7     
- Partials      109      110       +1
Impacted Files Coverage Δ
daemon/mgr/spec_blkio.go 0% <0%> (ø) ⬆️
daemon/mgr/container.go 4.7% <0%> (-0.29%) ⬇️
cli/container.go 0% <0%> (ø) ⬆️
cli/common_flags.go 0% <0%> (ø) ⬆️
cli/cli.go 0% <0%> (ø) ⬆️
ctrd/watch.go 0% <0%> (ø) ⬆️
client/client.go 28.57% <0%> (+0.57%) ⬆️
pkg/kernel/kernel.go 72.72% <0%> (+22.72%) ⬆️

@@ -1424,6 +1432,66 @@ func (mgr *ContainerManager) parseBinds(ctx context.Context, meta *ContainerMeta
return nil
}

func (mgr *ContainerManager) setMountPointDiskQuota(ctx context.Context, c *ContainerMeta) error {
type diskQuotaRegExp struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think defining a struct in function setMountPointDiskQuota is a good idea.
Maybe we could move this into diskquota package. WDYT? @rudyfly

@@ -144,7 +144,7 @@ func (quota *GrpQuota) SetDiskQuota(dir string, size string, quotaID int) error
return fmt.Errorf("mountpoint not found: %s", dir)
}

id, err := quota.SetSubtree(dir, uint32(quotaID))
id, err := quota.SetSubtree(dir, quotaID)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to judge whether err is not nil first?

@@ -114,7 +114,7 @@ func (quota *PrjQuota) SetDiskQuota(dir string, size string, quotaID int) error
return fmt.Errorf("mountpoint not found: %s", dir)
}

id, err := quota.SetSubtree(dir, uint32(quotaID))
id, err := quota.SetSubtree(dir, quotaID)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to judge whether err is not nil first?

@@ -37,13 +38,15 @@ func processSetQuotaReexec() {
}
}()

if len(os.Args) != 3 {
if len(os.Args) != 4 {
err = fmt.Errorf("invalid arguments: %v, it should be: %s: <path> <size>", os.Args, os.Args[0])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the next statement is return, I am wondering what is the usage of err = fmt.Errorf("invalid arguments: %v, it should be: %s: <path> <size>", os.Args, os.Args[0]).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh,I forgot to modify this error.

@allencloud
Copy link
Collaborator

Actually I could not quite follow you via the title.
Could you help to provide more information about the context?

@rudyfly
Copy link
Collaborator Author

rudyfly commented Apr 11, 2018

PTAL @allencloud @yyb196

if len(os.Args) != 3 {
err = fmt.Errorf("invalid arguments: %v, it should be: %s: <path> <size>", os.Args, os.Args[0])
if len(os.Args) != 4 {
err = fmt.Errorf("invalid arguments: %v, it should be: %s: <path> <size> <quota id>", os.Args, os.Args[0])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This err assignment is useless. I think we need to add a log to record this.

logrus.Errorf("invalid arguments: %v, it should be: %s: <path> <size> <quota id>", os.Args, os.Args[0])

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will return the error to runc and then print it. All the hooks do it like this.

if err != nil {
logrus.Errorf("failed to set subtree: %v", err)
return
}

err = SetDiskQuota(dir, size, int(qid))
err = SetDiskQuota(dir, size, qid)
if err != nil {
logrus.Errorf("failed to set disk quota: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to return at the err point?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reminder.

@@ -326,7 +326,7 @@ func (suite *PouchNetworkSuite) TestNetworkPortMapping(c *check.C) {
"-p", "9999:80",
image).Assert(c, icmd.Success)

time.Sleep(1 * time.Second)
time.Sleep(10 * time.Second)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why to change this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The network test is always fail, so I increase the delay time.

)

if c.Config.QuotaID != "" {
id, err := strconv.Atoi(c.Config.QuotaID)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, we will move this kind of validation out of package mgr. And it should be in the scope of bridge layer.

apis/swagger.yml Outdated
@@ -1784,6 +1784,9 @@ definitions:
type: "object"
additionalProperties:
type: "string"
QuotaID:
type: "string"
description: "set disk quota by specified quota id"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add more description that how many kinds of quota is there and what do they mean?

@@ -120,3 +120,22 @@ func SetFileAttrNoOutput(dir string, id uint32) {
func GetNextQuatoID() (uint32, error) {
return Gquota.GetNextQuatoID()
}

//GetDefaultQuota returns the default quota.
func GetDefaultQuota(quotas map[string]string) string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change this into GetDefaultQuotaSize ?

quotas := c.Config.DiskQuota
defaultQuota := quota.GetDefaultQuota(quotas)
if setQuotaID && defaultQuota == "" {
return fmt.Errorf("set quota id but have no set quota size")
Copy link
Collaborator

@allencloud allencloud Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid we need to emphasize the default, since default will take / and *. into consideration.

set quota id but have no set default quota size?

Copy link
Collaborator Author

@rudyfly rudyfly Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set quota id but have no set default quota size?

It will be failed when create container.

for _, re := range res {
findStr := re.Pattern.FindString(mp.Destination)
if findStr == mp.Destination {
quotas[mp.Destination] = re.Size
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If quotas is nil, maybe here we will run into a panic.

return
}

basefs := os.Args[1]
size := os.Args[2]
id, _ := strconv.Atoi(os.Args[3])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if we should not ignore the error. Maybe we can just record it.

rudyfly added 2 commits April 16, 2018 15:05
Add diskquota support regular expression.

We can use pouch run --disk-quota="key=value" to set quota for
container. This pr can make it support to use regular expression key,
such as: --disk-quota=".=1g", it means all the quota of mount points
are'1g', the priority of key'.'is the lowest. If it has no'key', just
have'value', such as: --disk-quota=1g, it means the quota of rootfs is
1g. If the mountpoint is a volume, the quota of volume is base on
volume's size, the disk-quota is not take effect on a volume.

Signed-off-by: Rudy Zhang <rudyflyzhang@gmail.com>
Specified quota id for a container, if id < 0, it means pouchd
alloc a unique quota id. If specified quota id, it will ignore the
quota's regular expression, but the volume will keep its size as before.

Signed-off-by: Rudy Zhang <rudyflyzhang@gmail.com>

// if QuotaID is < 0, it means pouchd alloc a unique quota id.
if id < 0 {
qid, err = quota.GetNextQuatoID()
Copy link
Collaborator

@allencloud allencloud Apr 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/GetNextQuatoID/GetNextQuotaID

@@ -120,3 +120,22 @@ func SetFileAttrNoOutput(dir string, id uint32) {
func GetNextQuatoID() (uint32, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/GetNextQuatoID/GetNextQuotaID

@allencloud
Copy link
Collaborator

LGTM

@pouchrobot pouchrobot added the LGTM one maintainer or community participant agrees to merge the pull reuqest. label Apr 16, 2018
@allencloud allencloud merged commit 95302f6 into AliyunContainerService:master Apr 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature LGTM one maintainer or community participant agrees to merge the pull reuqest. size/XL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants