Network: support down NIC (#130)

* add new feature nic down

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add nic down

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add nic down validate

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* use SchedulerConfig

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add support fot sub-interface

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add test for nic down

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add test for nic down

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* use bash to implement nic down

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* edit some details

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* replace cmd.Start with cmd.CombinedOutput

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* remove nohup

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* remove useless log.Error

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add some comments

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add some comments

Signed-off-by: FingerLeader <wanxfinger@gmail.com>

* add some comments

Signed-off-by: FingerLeader <wanxfinger@gmail.com>
This commit is contained in:
FingerLeader 2022-03-02 18:41:46 +08:00 committed by GitHub
parent 4e99e3cc8e
commit 81dc95afc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 157 additions and 0 deletions

View File

@ -49,6 +49,7 @@ func NewNetworkAttackCommand(uid *string) *cobra.Command {
NetworkDNSCommand(dep, options),
NewNetworkPortOccupiedCommand(dep, options),
NewNetworkBandwidthCommand(dep, options),
NewNICDownCommand(dep, options),
)
return cmd
@ -268,3 +269,20 @@ func NewNetworkPortOccupiedCommand(dep fx.Option, options *core.NetworkCommand)
cmd.Flags().StringVarP(&options.Port, "port", "p", "", "this specified port is to occupied")
return cmd
}
func NewNICDownCommand(dep fx.Option, options *core.NetworkCommand) *cobra.Command {
cmd := &cobra.Command{
Use: "down",
Short: "down network interface card",
Run: func(cmd *cobra.Command, args []string) {
options.Action = core.NetworkNICDownAction
options.CompleteDefaults()
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonNetworkAttackFunc)).Run()
},
}
cmd.Flags().StringVarP(&options.Device, "device", "d", "", "the network interface to impact")
SetScheduleFlags(cmd, &options.SchedulerConfig)
return cmd
}

View File

@ -70,6 +70,7 @@ const (
NetworkPartitionAction = "partition"
NetworkBandwidthAction = "bandwidth"
NetworkPortOccupiedAction = "occupied"
NetworkNICDownAction = "down"
)
func (n *NetworkCommand) Validate() error {
@ -89,6 +90,8 @@ func (n *NetworkCommand) Validate() error {
return n.validNetworkOccupied()
case NetworkBandwidthAction:
return n.validNetworkBandwidth()
case NetworkNICDownAction:
return n.validNetworkNICDown()
default:
return errors.Errorf("network action %s not supported", n.Action)
}
@ -203,6 +206,18 @@ func (n *NetworkCommand) validNetworkOccupied() error {
return nil
}
func (n *NetworkCommand) validNetworkNICDown() error {
if len(n.Duration) == 0 {
return errors.New("duration is required")
}
if len(n.Device) == 0 {
return errors.New("device is required")
}
return nil
}
func (n *NetworkCommand) CompleteDefaults() {
switch n.Action {
case NetworkDelayAction:

View File

@ -85,6 +85,24 @@ func (networkAttack) Attack(options core.AttackConfig, env Environment) (err err
return errors.WithStack(err)
}
}
case core.NetworkNICDownAction:
if err := env.Chaos.getNICIP(attack); err != nil {
return errors.WithStack(err)
}
NICDownCommand := fmt.Sprintf("ifconfig %s down", attack.Device)
cmd := exec.Command("bash", "-c", NICDownCommand)
_, err := cmd.CombinedOutput()
if err != nil {
return errors.WithStack(err)
}
if attack.Duration != "-1" {
err := env.Chaos.recoverNICDownScheduled(attack)
return errors.WithStack(err)
}
}
return nil
@ -348,6 +366,8 @@ func (networkAttack) Recover(exp core.Experiment, env Environment) error {
return errors.WithStack(err)
}
}
case core.NetworkNICDownAction:
return env.Chaos.recoverNICDown(attack)
}
return nil
}
@ -511,3 +531,54 @@ func (s *Server) recoverEtcHosts(attack *core.NetworkCommand, uid string) error
}
return nil
}
func (s *Server) recoverNICDown(attack *core.NetworkCommand) error {
NICUpCommand := fmt.Sprintf("ifconfig %s %s up", attack.Device, attack.IPAddress)
recoverCmd := exec.Command("bash", "-c", NICUpCommand)
_, err := recoverCmd.CombinedOutput()
if err != nil {
return errors.WithStack(err)
}
return nil
}
func (s *Server) recoverNICDownScheduled(attack *core.NetworkCommand) error {
NICUpCommand := fmt.Sprintf("sleep %s && ifconfig %s %s up", attack.Duration, attack.Device, attack.IPAddress)
recoverCmd := exec.Command("bash", "-c", NICUpCommand)
_, err := recoverCmd.CombinedOutput()
if err != nil {
return errors.WithStack(err)
}
return nil
}
// getNICIP() uses `ifconfig` to get interfaces' IP. The reason for
// not using net.Interfaces() is that net.Interfaces() can't get
// sub interfaces.
func (s *Server) getNICIP(attack *core.NetworkCommand) error {
getIPCommand := fmt.Sprintf("ifconfig %s | awk '/inet\\>/ {print $2}'", attack.Device)
cmd := exec.Command("bash", "-c", getIPCommand)
stdout, err := cmd.StdoutPipe()
if err != nil {
return errors.WithStack(err)
}
if err = cmd.Start(); err != nil {
return errors.WithStack(err)
}
stdoutBytes := make([]byte, 1024)
_, err = stdout.Read(stdoutBytes)
if err != nil {
return errors.WithStack(err)
}
// When stdoutBytes is converted to string, the string will be IPAddress with a few unnecessary
// zeros, which makes IPAddress' format wrong, so the trailing zeros needs to be trimmed.
attack.IPAddress = strings.TrimRight(string(stdoutBytes), "\n\x00")
return nil
}

View File

@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Copyright 2022 Chaos Mesh Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
set -u
cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
cd $cur
bin_path=../../../bin
# test nic down
nic=$(cat /proc/net/dev | awk '{i++; if(i>2){print $1}}' | sed 's/^[\t]*//g' | sed 's/[:]*$//g' | head -n 1)
ifconfig ${nic}:0 192.168.10.28 up
test_nic=$(ifconfig | grep ${nic}:0 | sed 's/:0:.*/:0/g')
if [[ test_nic == "" ]]; then
echo "create test nic failed"
exit 1
fi
${bin_path}/chaosd attack network down -d ${test_nic} --duration 1s
stat=$(ifconfig | grep ${test_nic} | sed 's/:0:.*/:0/g')
if [[ -n ${stat} ]]; then
echo "fail to disable the test nic"
ifconfig ${test_nic} down
exit 1
fi
sleep 1s
stat=$(ifconfig | grep ${test_nic} | sed 's/:0:.*/:0/g')
if [[ ${stat} != ${test_nic} ]]; then
echo "fail to enable the test nic"
exit 1
fi
ifconfig ${test_nic} down
exit 0