mirror of https://github.com/chaos-mesh/chaosd.git
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:
parent
4e99e3cc8e
commit
81dc95afc2
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue