...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/debug/stresschaos.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/debug

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package debug
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"strconv"
    22  
    23  	"code.cloudfoundry.org/bytefmt"
    24  	"github.com/hasura/go-graphql-client"
    25  
    26  	"github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/common"
    27  	ctrlclient "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/client"
    28  )
    29  
    30  type stressDebugger struct {
    31  	client *ctrlclient.CtrlClient
    32  }
    33  
    34  func StressDebug(client *ctrlclient.CtrlClient) Debugger {
    35  	return &stressDebugger{
    36  		client: client,
    37  	}
    38  }
    39  
    40  func (d *stressDebugger) Collect(ctx context.Context, namespace, chaosName string) ([]*common.ChaosResult, error) {
    41  	var results []*common.ChaosResult
    42  
    43  	var name *graphql.String
    44  	if chaosName != "" {
    45  		n := graphql.String(chaosName)
    46  		name = &n
    47  	}
    48  
    49  	var query struct {
    50  		Namespace []struct {
    51  			StressChaos []struct {
    52  				Name      string
    53  				Podstress []struct {
    54  					Pod struct {
    55  						Namespace string
    56  						Name      string
    57  					}
    58  					Cgroups struct {
    59  						Raw string
    60  						Cpu *struct {
    61  							Quota  int
    62  							Period int
    63  						}
    64  						Memory *struct {
    65  							Limit uint64
    66  						}
    67  					}
    68  					ProcessStress []struct {
    69  						Process struct {
    70  							Pid     string
    71  							Command string
    72  						}
    73  						Cgroup string
    74  					}
    75  				}
    76  			} `graphql:"stresschaos(name: $name)"`
    77  		} `graphql:"namespace(ns: $namespace)"`
    78  	}
    79  
    80  	variables := map[string]interface{}{
    81  		"namespace": graphql.String(namespace),
    82  		"name":      name,
    83  	}
    84  
    85  	err := d.client.QueryClient.Query(ctx, &query, variables)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	if len(query.Namespace) == 0 {
    91  		return results, nil
    92  	}
    93  
    94  	for _, stressChaos := range query.Namespace[0].StressChaos {
    95  		result := &common.ChaosResult{
    96  			Name: stressChaos.Name,
    97  		}
    98  
    99  		for _, podStressChaos := range stressChaos.Podstress {
   100  			podResult := common.PodResult{
   101  				Name: podStressChaos.Pod.Name,
   102  			}
   103  
   104  			podResult.Items = append(podResult.Items, common.ItemResult{Name: "cat /proc/cgroups", Value: podStressChaos.Cgroups.Raw})
   105  			for _, process := range podStressChaos.ProcessStress {
   106  				podResult.Items = append(podResult.Items, common.ItemResult{
   107  					Name:  fmt.Sprintf("/proc/%s/cgroup of %s", process.Process.Pid, process.Process.Command),
   108  					Value: process.Cgroup,
   109  				})
   110  			}
   111  			if podStressChaos.Cgroups.Cpu != nil {
   112  				podResult.Items = append(podResult.Items, common.ItemResult{Name: "cpu.cfs_quota_us", Value: strconv.Itoa(podStressChaos.Cgroups.Cpu.Quota)})
   113  				periodItem := common.ItemResult{Name: "cpu.cfs_period_us", Value: strconv.Itoa(podStressChaos.Cgroups.Cpu.Period)}
   114  				if podStressChaos.Cgroups.Cpu.Quota == -1 {
   115  					periodItem.Status = common.ItemFailure
   116  					periodItem.ErrInfo = "no cpu limit is set for now"
   117  				} else {
   118  					periodItem.Status = common.ItemSuccess
   119  					periodItem.SucInfo = fmt.Sprintf("cpu limit is equals to %.2f", float64(podStressChaos.Cgroups.Cpu.Quota)/float64(podStressChaos.Cgroups.Cpu.Period))
   120  				}
   121  				podResult.Items = append(podResult.Items, periodItem)
   122  			}
   123  
   124  			if podStressChaos.Cgroups.Memory != nil {
   125  				podResult.Items = append(podResult.Items, common.ItemResult{Name: "memory.limit_in_bytes", Value: bytefmt.ByteSize(podStressChaos.Cgroups.Memory.Limit) + "B"})
   126  			}
   127  			result.Pods = append(result.Pods, podResult)
   128  		}
   129  		results = append(results, result)
   130  	}
   131  	return results, nil
   132  }
   133  
   134  func (d *stressDebugger) List(ctx context.Context, namespace string) ([]string, error) {
   135  	var query struct {
   136  		Namespace []struct {
   137  			StressChaos []struct {
   138  				Name string
   139  			} `graphql:"stresschaos"`
   140  		} `graphql:"namespace(ns: $namespace)"`
   141  	}
   142  
   143  	variables := map[string]interface{}{
   144  		"namespace": graphql.String(namespace),
   145  	}
   146  
   147  	err := d.client.QueryClient.Query(ctx, &query, variables)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	if len(query.Namespace) == 0 {
   153  		return nil, nil
   154  	}
   155  
   156  	var names []string
   157  	for _, stressChaos := range query.Namespace[0].StressChaos {
   158  		names = append(names, string(stressChaos.Name))
   159  	}
   160  	return names, nil
   161  }
   162