From 77c5329eb507bdb1afc80467ca4cd7cb122176a1 Mon Sep 17 00:00:00 2001 From: Rudy Zhang Date: Mon, 18 Mar 2019 17:36:52 +0800 Subject: [PATCH] feature: add disable-bridge switch add disable-bridge switch Signed-off-by: Rudy Zhang --- cli/update_daemon.go | 6 ++ network/config.go | 17 ++-- network/mode/init.go | 9 ++- test/daemon/daemon.go | 1 + test/daemonv2/daemon.go | 159 ++++++++++++++++++++++++++++++++++++++ test/daemonv2/types.go | 38 +++++++++ test/z_cli_daemon_test.go | 32 +++++++- 7 files changed, 252 insertions(+), 10 deletions(-) create mode 100644 test/daemonv2/daemon.go create mode 100644 test/daemonv2/types.go diff --git a/cli/update_daemon.go b/cli/update_daemon.go index bf0403a86..332e73206 100644 --- a/cli/update_daemon.go +++ b/cli/update_daemon.go @@ -33,6 +33,7 @@ type DaemonUpdateCommand struct { label []string managerWhiteList string execRoot string + disableBridge bool bridgeName string bridgeIP string fixedCIDRv4 string @@ -73,6 +74,7 @@ func (udc *DaemonUpdateCommand) addFlags() { flagSet.StringVar(&udc.managerWhiteList, "manager-white-list", "", "update daemon manager white list") flagSet.StringSliceVar(&udc.label, "label", nil, "update daemon labels") flagSet.StringVar(&udc.execRoot, "exec-root-dir", "", "update exec root directory for network") + flagSet.BoolVar(&udc.disableBridge, "disable-bridge", false, "disable bridge network") flagSet.StringVar(&udc.bridgeName, "bridge-name", "", "update daemon bridge device") flagSet.StringVar(&udc.bridgeIP, "bip", "", "update daemon bridge IP") flagSet.StringVar(&udc.fixedCIDRv4, "fixed-cidr", "", "update daemon bridge fixed CIDR") @@ -143,6 +145,10 @@ func (udc *DaemonUpdateCommand) updateDaemonConfigFile() error { daemonConfig.NetworkConfig.ExecRoot = udc.execRoot } + if flagSet.Changed("disable-bridge") { + daemonConfig.NetworkConfig.BridgeConfig.DisableBridge = udc.disableBridge + } + if flagSet.Changed("bridge-name") { daemonConfig.NetworkConfig.BridgeConfig.Name = udc.bridgeName } diff --git a/network/config.go b/network/config.go index d65fc6c27..e7c08ec3c 100644 --- a/network/config.go +++ b/network/config.go @@ -25,14 +25,15 @@ type Config struct { // BridgeConfig defines the bridge network configuration. type BridgeConfig struct { - Name string `json:"bridge-name,omitempty"` - IPv4 string `json:"bip,omitempty"` - FixedCIDRv4 string `json:"fixed-cidr,omitempty"` - GatewayIPv4 string `json:"default-gateway,omitempty"` - EnableIPv6 bool `json:"enable-ipv6,omitempty"` - FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` - GatewayIPv6 string `json:"default-gateway-v6,omitempty"` - PreferredIP string `json:"preferred-ip,omitempty"` + DisableBridge bool `json:"disable-bridge,omitempty"` + Name string `json:"bridge-name,omitempty"` + IPv4 string `json:"bip,omitempty"` + FixedCIDRv4 string `json:"fixed-cidr,omitempty"` + GatewayIPv4 string `json:"default-gateway,omitempty"` + EnableIPv6 bool `json:"enable-ipv6,omitempty"` + FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` + GatewayIPv6 string `json:"default-gateway-v6,omitempty"` + PreferredIP string `json:"preferred-ip,omitempty"` Mtu int `json:"mtu,omitempty"` ICC bool `json:"icc,omitempty"` diff --git a/network/mode/init.go b/network/mode/init.go index 800522757..3901a51cb 100644 --- a/network/mode/init.go +++ b/network/mode/init.go @@ -7,6 +7,8 @@ import ( "github.com/alibaba/pouch/daemon/mgr" "github.com/alibaba/pouch/network" "github.com/alibaba/pouch/network/mode/bridge" + + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -59,5 +61,10 @@ func NetworkModeInit(ctx context.Context, config network.Config, manager mgr.Net } // init bridge network - return bridge.New(ctx, config.BridgeConfig, manager) + if !config.BridgeConfig.DisableBridge { + if err := bridge.New(ctx, config.BridgeConfig, manager); err != nil { + return errors.Wrapf(err, "failed to init bridge network") + } + } + return nil } diff --git a/test/daemon/daemon.go b/test/daemon/daemon.go index c61dbb6f7..11b3a86b4 100644 --- a/test/daemon/daemon.go +++ b/test/daemon/daemon.go @@ -12,6 +12,7 @@ import ( "github.com/alibaba/pouch/test/command" "github.com/alibaba/pouch/test/util" + "github.com/gotestyourself/gotestyourself/icmd" ) diff --git a/test/daemonv2/daemon.go b/test/daemonv2/daemon.go new file mode 100644 index 000000000..dddad23b9 --- /dev/null +++ b/test/daemonv2/daemon.go @@ -0,0 +1,159 @@ +package daemonv2 + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "syscall" + "time" + + daemon "github.com/alibaba/pouch/daemon/config" + "github.com/alibaba/pouch/test/command" + "github.com/alibaba/pouch/test/util" + + "github.com/gotestyourself/gotestyourself/icmd" + "github.com/pkg/errors" +) + +// New returns the daemon struct. +func New() *Daemon { + return &Daemon{ + Config: daemon.Config{ + Listen: []string{Listen}, + HomeDir: HomeDir, + ContainerdAddr: ContainerdAdd, + Pidfile: Pidfile, + Debug: true, + }, + Bin: PouchdBin, + LogPath: DaemonLog, + ConfigJSON: ConfigJSON, + + timeout: 15, + } +} + +// IsUp checks the up or not +func (d *Daemon) IsUp() bool { + return command.PouchRun("--host", d.Config.Listen[0], "version").ExitCode == 0 +} + +// Clean kills pouch daemon and clean config file +func (d *Daemon) Clean() { + d.Stop() + + if d.ConfigJSON != "" { + os.Remove(d.ConfigJSON) + } + + if d.LogPath != "" { + os.Remove(d.LogPath) + } +} + +// DumpLog prints the daemon log +func (d *Daemon) DumpLog() { + d.LogFile.Sync() + + content, err := ioutil.ReadFile(d.LogPath) + if err != nil { + fmt.Printf("failed to read log, err: %s\n", err) + } + fmt.Printf("pouch daemon log contents:\n %s\n", content) +} + +// Restart restarts pouch daemon +func (d *Daemon) Restart() error { + if err := d.Stop(); err != nil { + return err + } + + return d.Start() +} + +// Stop stops pouch daemon +func (d *Daemon) Stop() error { + if !d.IsUp() { + return nil + } + + if d.Pid != 0 { + // kill pouchd and all other process in its group + err := syscall.Kill(-d.Pid, syscall.SIGKILL) + if err != nil { + return errors.Wrap(err, "failed to kill pouchd") + } + } + + return d.LogFile.Close() +} + +// Start starts pouch daemon with config file, instead of running with arguments +func (d *Daemon) Start() error { + fd, err := os.OpenFile(d.ConfigJSON, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0755) + if err != nil { + return err + } + + if err := json.NewEncoder(fd).Encode(&d.Config); err != nil { + fd.Close() + return err + } + fd.Close() + + // start pouchd daemon + cmd := exec.Command(d.Bin, "--config-file", d.ConfigJSON) + + d.LogFile, err = os.OpenFile(d.LogPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644) + if err != nil { + return fmt.Errorf("failed to create log file %s, err %s", d.LogPath, err) + } + + mwriter := io.MultiWriter(d.LogFile) + cmd.Stderr = mwriter + cmd.Stdout = mwriter + + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + err = cmd.Start() + if err != nil { + return fmt.Errorf("failed to start cmd %v, err %s", cmd, err) + } + + // record the pid + d.Pid = cmd.Process.Pid + + wait := make(chan error) + go func() { + wait <- cmd.Wait() + fmt.Printf("[%d] exiting daemon", d.Pid) + close(wait) + }() + + if !util.WaitTimeout(time.Duration(d.timeout)*time.Second, d.IsUp) { + if d.Config.Debug { + d.DumpLog() + + fmt.Printf("\nFailed to launch pouchd\n") + + cmd := "ps aux |grep pouchd" + fmt.Printf("\nList pouchd process:\n%s\n", icmd.RunCommand("sh", "-c", cmd).Combined()) + + cmd = "ps aux |grep containerd" + fmt.Printf("\nList containerd process:\n%s\n", icmd.RunCommand("sh", "-c", cmd).Combined()) + } + + d.Clean() + return fmt.Errorf("failed to launch pouchd") + } + + return nil +} + +// RunCommand runs pouch command with specified listen +func (d *Daemon) RunCommand(args ...string) *icmd.Result { + return command.PouchRun(append([]string{"-H", d.Config.Listen[0]}, args...)...) +} diff --git a/test/daemonv2/types.go b/test/daemonv2/types.go new file mode 100644 index 000000000..ee14dc3ec --- /dev/null +++ b/test/daemonv2/types.go @@ -0,0 +1,38 @@ +package daemonv2 + +import ( + "os" + + daemon "github.com/alibaba/pouch/daemon/config" +) + +// For pouch daemon test, we launched another pouch daemon. +const ( + DaemonLog = "/tmp/pouchd.log" + PouchdBin = "pouchd" + HomeDir = "/tmp/test/pouch" + Listen = "unix:///tmp/test/pouch/pouchd.sock" + ContainerdAdd = "/tmp/test/pouch/containerd.sock" + Pidfile = "/tmp/test/pouch/pouch.pid" + ConfigJSON = "/tmp/pouchconfig.json" +) + +// Daemon defines the daemon to test +type Daemon struct { + daemon.Config + + // pouchd binary location + Bin string + + // config file + ConfigJSON string + + // pid of pouchd + Pid int + + LogPath string + LogFile *os.File + + // timeout for starting daemon + timeout int64 +} diff --git a/test/z_cli_daemon_test.go b/test/z_cli_daemon_test.go index bb43ea1bb..6e54b1cb5 100644 --- a/test/z_cli_daemon_test.go +++ b/test/z_cli_daemon_test.go @@ -16,6 +16,7 @@ import ( "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/test/command" "github.com/alibaba/pouch/test/daemon" + "github.com/alibaba/pouch/test/daemonv2" "github.com/alibaba/pouch/test/environment" "github.com/alibaba/pouch/test/util" @@ -537,7 +538,7 @@ func (suite *PouchDaemonSuite) TestUpdateDaemonWithLabels(c *check.C) { c.Assert(updated, check.Equals, true) } -// TestUpdateDaemonWithLabels tests update daemon offline +// TestUpdateDaemonOffline tests update daemon offline func (suite *PouchDaemonSuite) TestUpdateDaemonOffline(c *check.C) { path := "/tmp/pouchconfig.json" fd, err := os.Create(path) @@ -738,3 +739,32 @@ func (suite *PouchDaemonSuite) TestUpdateDaemonWithHomeDirAndSnapshotter(c *chec c.Assert(readConfig.HomeDir, check.Equals, tmpHomeDir) c.Assert(readConfig.Snapshotter, check.Equals, snapshotter) } + +// TestUpdateDaemonWithDisableBridge tests update daemon with disable bridge network +func (suite *PouchDaemonSuite) TestUpdateDaemonWithDisableBridge(c *check.C) { + d := daemonv2.New() + + // modify test config + d.Config.NetworkConfig.BridgeConfig.DisableBridge = true + + err := d.Start() + if err != nil { + c.Fatalf("failed to start daemon with json, err(%v)", err) + } + defer d.Clean() + + res := d.RunCommand("network", "ls") + res.Assert(c, icmd.Success) + + if strings.Contains(res.Stdout(), "bridge") { + d.RunCommand("network", "rm", "bridge").Assert(c, icmd.Success) + } + + d.Restart() + + res = d.RunCommand("network", "ls") + res.Assert(c, icmd.Success) + if strings.Contains(res.Stdout(), "bridge") { + c.Fatalf("failed to disable bridge network") + } +}