Skip to content

Commit

Permalink
support update hostname by nsexec
Browse files Browse the repository at this point in the history
Signed-off-by: allen.wang <allen.wq@alipay.com>
  • Loading branch information
wangforthinker committed Sep 11, 2018
1 parent ff5d11f commit f16afaa
Show file tree
Hide file tree
Showing 23 changed files with 2,054 additions and 2 deletions.
3 changes: 3 additions & 0 deletions apis/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,9 @@ definitions:
x-nullable: true
additionalProperties:
type: "string"
Hostname:
type: "string"
description: "update hostname for container"

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

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

2 changes: 2 additions & 0 deletions cli/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func (uc *UpdateCommand) addFlags() {
flagSet.StringSliceVarP(&uc.labels, "label", "l", nil, "Set label for container")
flagSet.StringVar(&uc.restartPolicy, "restart", "", "Restart policy to apply when container exits")
flagSet.StringSliceVar(&uc.diskQuota, "disk-quota", nil, "Update disk quota for container(/=10g)")
flagSet.StringVar(&uc.hostname, "hostname", "", "Update hostname")
}

// updateRun is the entry of update command.
Expand Down Expand Up @@ -96,6 +97,7 @@ func (uc *UpdateCommand) updateRun(args []string) error {
RestartPolicy: restartPolicy,
Resources: resource,
DiskQuota: diskQuota,
Hostname: uc.hostname,
}

apiClient := uc.cli.Client()
Expand Down
13 changes: 13 additions & 0 deletions daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,19 @@ func (mgr *ContainerManager) Update(ctx context.Context, name string, config *ty
}
}()

if config.Hostname != "" {
if c.HostConfig.NetworkMode == "host" {
return fmt.Errorf("host container %s cannot update hostname", c.ID)
}

c.Config.Hostname = strfmt.Hostname(config.Hostname)
if c.IsRunning() {
if err = updateHostnameForRunningContainer(config.Hostname, c); err != nil {
return err
}
}
}

if c.IsRunning() && config.Resources.KernelMemory != 0 {
return fmt.Errorf("failed to update container %s: can not update kernel memory to a running container, please stop it first", c.ID)
}
Expand Down
84 changes: 84 additions & 0 deletions daemon/mgr/container_update_hostname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package mgr

import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
"syscall"

"github.com/alibaba/pouch/pkg/nsexec"
)

func init() {
nsexec.Register("sethostname", handleUpdateHostname)
}

func handleUpdateHostname(data []byte) (res []byte, err error) {
oldHostname, err := os.Hostname()
if err != nil {
return nil, err
}

err = syscall.Sethostname(data)
if err != nil {
return nil, err
}

//update /etc/hostname and /etc/hosts
err = ioutil.WriteFile("/etc/hostname", append(data, '\n'), 0644)
if err != nil {
return nil, fmt.Errorf("update /etc/hostname failed:%s", err.Error())
}

hosts, err := ioutil.ReadFile("/etc/hosts")
if err != nil {
return nil, fmt.Errorf("update /etc/hosts failed:%s", err.Error())
}

exp1 := regexp.MustCompile(fmt.Sprintf(`\s%s\s`, oldHostname))
exp2 := regexp.MustCompile(fmt.Sprintf(`\s%s$`, oldHostname))

replaceStr1 := fmt.Sprintf(" %s ", string(data))
replaceStr2 := fmt.Sprintf(" %s", string(data))

d := string(hosts)
lines := strings.Split(d, "\n")
for i, line := range lines {
if !strings.Contains(line, oldHostname) {
continue
}

newLine := line

if exp1.FindString(newLine) != "" {
newLine = exp1.ReplaceAllString(newLine, replaceStr1)
}

if exp2.FindString(newLine) != "" {
newLine = exp2.ReplaceAllString(newLine, replaceStr2)
}

lines[i] = newLine
}

newHosts := strings.Join(lines, "\n")
err = ioutil.WriteFile("/etc/hosts", []byte(newHosts), 0644)

return nil, err
}

func updateHostnameForRunningContainer(hostname string, container *Container) error {
pid := container.State.Pid
if pid <= 0 {
return fmt.Errorf("container pid %d is not vaild", pid)
}

_, err := nsexec.NsExec(int(pid), nsexec.Op{OpCode: "sethostname", Data: []byte(hostname)})
if err != nil {
return err
}

return nil
}
5 changes: 5 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ var (
logOpts []string
)

func init() {
reexec.Register("nsexec", reexecRunNsExec)
}

var cfg = &config.Config{}

func main() {
logrus.Infof("os args:%v", os.Args)
if reexec.Init() {
return
}
Expand Down
39 changes: 39 additions & 0 deletions nsexec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// +build linux

package main

import (
"encoding/json"
"os"
"strconv"

_ "github.com/opencontainers/runc/libcontainer/nsenter"
"github.com/sirupsen/logrus"

"github.com/alibaba/pouch/pkg/nsexec"
)

//reexecRunNsExec will run nsenter in go init and join to container namespace
func reexecRunNsExec() {
logrus.Infof("run reexecRunNsExec")
initPipe := os.Getenv("_LIBCONTAINER_INITPIPE")
pipeFd, err := strconv.Atoi(initPipe)
if err != nil {
panic("init pipe get failed")
}

f := os.NewFile(uintptr(pipeFd), "init")
defer f.Close()

nsexecOp := nsexec.Op{}
err = json.NewDecoder(f).Decode(&nsexecOp)
if err != nil {
panic("op failed")
}

res := nsexec.Dispatch(nsexecOp)
err = json.NewEncoder(f).Encode(res)
if err != nil {
panic("send data failed")
}
}
26 changes: 26 additions & 0 deletions pkg/nsexec/nsexec_child_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nsexec

import "fmt"

// Dispatch should be called by pouchd nsexec to do function in container namespace
func Dispatch(op Op) *Result {
f, exist := regigsterFuncMap[op.OpCode]
if !exist {
return &Result{
Finish: true,
ErrMsg: fmt.Sprintf("not register nsexec op %s", op.OpCode),
}
}

res, err := f(op.Data)
errMsg := ""
if err != nil {
errMsg = err.Error()
}

return &Result{
Finish: true,
ErrMsg: errMsg,
Data: res,
}
}
Loading

0 comments on commit f16afaa

Please sign in to comment.