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

refactor: refactor container update diskquota type #1572

Merged
merged 1 commit into from Jun 22, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion apis/plugins/ContainerPlugin.go
Expand Up @@ -4,7 +4,7 @@ import "io"

// ContainerPlugin defines places where a plugin will be triggered in container lifecycle
type ContainerPlugin interface {
// PreCreate defines plugin point where receives an container create request, in this plugin point user
// PreCreate defines plugin point where receives a container create request, in this plugin point user
// could change the container create body passed-in by http request body
PreCreate(io.ReadCloser) (io.ReadCloser, error)

Expand All @@ -16,4 +16,8 @@ type ContainerPlugin interface {
// and if this endpoint should enable resolver and a map which will be used as generic params to create endpoints of
// this container
PreCreateEndpoint(string, []string) (priority int, disableResolver bool, genericParam map[string]interface{})

// PreUpdate defines plugin point where receives a container update request, in this plugin point user
// could change the container update body passed-in by http request body
PreUpdate(io.ReadCloser) (io.ReadCloser, error)
}
13 changes: 12 additions & 1 deletion apis/server/container_bridge.go
Expand Up @@ -266,8 +266,19 @@ func (s *Server) attachContainer(ctx context.Context, rw http.ResponseWriter, re

func (s *Server) updateContainer(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
config := &types.UpdateConfig{}

// set pre update hook plugin
reader := req.Body
if s.ContainerPlugin != nil {
var err error
logrus.Infof("invoke container pre-update hook in plugin")
if reader, err = s.ContainerPlugin.PreUpdate(req.Body); err != nil {
return errors.Wrapf(err, "failed to execute pre-create plugin point")
}
}

// decode request body
if err := json.NewDecoder(req.Body).Decode(config); err != nil {
if err := json.NewDecoder(reader).Decode(config); err != nil {
return httputils.NewHTTPError(err, http.StatusBadRequest)
}
// validate request body
Expand Down
5 changes: 4 additions & 1 deletion apis/swagger.yml
Expand Up @@ -2201,8 +2201,11 @@ definitions:
items:
type: "string"
DiskQuota:
type: "string"
type: "object"
description: "update disk quota for container"
x-nullable: true
additionalProperties:
type: "string"

ContainerUpgradeConfig:
description: |
Expand Down
6 changes: 3 additions & 3 deletions apis/types/update_config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions cli/update.go
Expand Up @@ -18,7 +18,6 @@ type UpdateCommand struct {
baseCommand
container
image string
quota string
}

// Init initialize update command.
Expand Down Expand Up @@ -52,7 +51,7 @@ func (uc *UpdateCommand) addFlags() {
flagSet.StringSliceVarP(&uc.env, "env", "e", nil, "Set environment variables for container")
flagSet.StringSliceVarP(&uc.labels, "label", "l", nil, "Set label for container")
flagSet.StringVar(&uc.restartPolicy, "restart", "", "Restart policy to apply when container exits")
flagSet.StringVar(&uc.quota, "quota", "", "Update disk quota for container")
flagSet.StringSliceVar(&uc.diskQuota, "disk-quota", nil, "Update disk quota for container(/=10g)")
}

// updateRun is the entry of update command.
Expand Down Expand Up @@ -86,12 +85,17 @@ func (uc *UpdateCommand) updateRun(args []string) error {
return err
}

diskQuota, err := opts.ParseDiskQuota(uc.diskQuota)
if err != nil {
return err
}

updateConfig := &types.UpdateConfig{
Env: uc.env,
Label: uc.labels,
RestartPolicy: restartPolicy,
Resources: resource,
DiskQuota: uc.quota,
DiskQuota: diskQuota,
}

apiClient := uc.cli.Client()
Expand Down
33 changes: 17 additions & 16 deletions daemon/mgr/container.go
Expand Up @@ -878,6 +878,11 @@ func (mgr *ContainerManager) Update(ctx context.Context, name string, config *ty
return fmt.Errorf("failed to update container %s: can not update kernel memory to a running container, please stop it first", c.ID)
}

// update container disk quota
if err := mgr.updateContainerDiskQuota(ctx, c, config.DiskQuota); err != nil {
return errors.Wrapf(err, "failed to update diskquota of container %s", c.ID)
}

c.Lock()

// init Container Labels
Expand Down Expand Up @@ -906,19 +911,18 @@ func (mgr *ContainerManager) Update(ctx context.Context, name string, config *ty
// TODO(ziren): we should use meta.Config.DiskQuota to record container diskquota
// compatibility with alidocker, when set DiskQuota for container
// add a DiskQuota label
if config.DiskQuota != "" {
if config.DiskQuota != nil {
if _, ok := c.Config.Labels["DiskQuota"]; ok {
c.Config.Labels["DiskQuota"] = config.DiskQuota
labels := []string{}
for dir, quota := range c.Config.DiskQuota {
labels = append(labels, fmt.Sprintf("%s=%s", dir, quota))
}
c.Config.Labels["DiskQuota"] = strings.Join(labels, ";")
}
}

c.Unlock()

// update container disk quota
if err := mgr.updateContainerDiskQuota(ctx, c, config.DiskQuota); err != nil {
return errors.Wrapf(err, "failed to update diskquota of container %s", c.ID)
}

// update Resources of a container.
if err := mgr.updateContainerResources(c, config.Resources); err != nil {
restore = true
Expand Down Expand Up @@ -1052,18 +1056,15 @@ func (mgr *ContainerManager) Remove(ctx context.Context, name string, options *t
return nil
}

func (mgr *ContainerManager) updateContainerDiskQuota(ctx context.Context, c *Container, diskQuota string) error {
if diskQuota == "" {
func (mgr *ContainerManager) updateContainerDiskQuota(ctx context.Context, c *Container, diskQuota map[string]string) error {
if diskQuota == nil {
return nil
}

quotaMap, err := opts.ParseDiskQuota([]string{diskQuota})
if err != nil {
return errors.Wrapf(err, "failed to parse disk quota")
}

c.Lock()
c.Config.DiskQuota = quotaMap
for dir, quota := range diskQuota {
c.Config.DiskQuota[dir] = quota
}
c.Unlock()

// set mount point disk quota
Expand Down Expand Up @@ -1094,7 +1095,7 @@ func (mgr *ContainerManager) updateContainerDiskQuota(ctx context.Context, c *Co
c.Unlock()

// get rootfs quota
defaultQuota := quota.GetDefaultQuota(quotaMap)
defaultQuota := quota.GetDefaultQuota(c.Config.DiskQuota)
if qid > 0 && defaultQuota == "" {
return fmt.Errorf("set quota id but have no set default quota size")
}
Expand Down
43 changes: 43 additions & 0 deletions test/cli_update_test.go
Expand Up @@ -392,3 +392,46 @@ func (suite *PouchUpdateSuite) TestUpdateContainerDeleteEnv(c *check.C) {
c.Errorf("foo=bar env should be deleted from container's env")
}
}

// TestUpdateContainerDiskQuota is to verify the correctness of delete env by update interface
func (suite *PouchUpdateSuite) TestUpdateContainerDiskQuota(c *check.C) {
if !environment.IsDiskQuota() {
c.Skip("Host does not support disk quota")
}

// create container with disk quota
name := "update-container-diskquota"
command.PouchRun("run", "-d", "--disk-quota", "/=2000m", "--name", name, busyboxImage, "top").Assert(c, icmd.Success)
defer DelContainerForceMultyTime(c, name)

ret := command.PouchRun("exec", name, "df")
//ret.Assert(c, icmd.Success)
out := ret.Combined()

found := false
for _, line := range strings.Split(out, "\n") {
if strings.Contains(line, "/") &&
strings.Contains(line, "2048000") {
found = true
break
}
}
c.Assert(found, check.Equals, true)

// update diskquota
command.PouchRun("update", "--disk-quota", "/=1000m", name).Assert(c, icmd.Success)

ret = command.PouchRun("exec", name, "df")
//ret.Assert(c, icmd.Success)
out = ret.Combined()

found = false
for _, line := range strings.Split(out, "\n") {
if strings.Contains(line, "/") &&
strings.Contains(line, "1024000") {
found = true
break
}
}
c.Assert(found, check.Equals, true)
}