github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/fault/fault_io.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package fault 21 22 import ( 23 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" 24 "github.com/spf13/cobra" 25 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/cli-runtime/pkg/genericiooptions" 28 cmdutil "k8s.io/kubectl/pkg/cmd/util" 29 "k8s.io/kubectl/pkg/util/templates" 30 31 "github.com/1aal/kubeblocks/pkg/cli/create" 32 "github.com/1aal/kubeblocks/pkg/cli/util" 33 ) 34 35 var faultIOExample = templates.Examples(` 36 # Affects the first container in default namespace's all pods. Delay all IO operations under the /data path by 10s. 37 kbcli fault io latency --delay=10s --volume-path=/data 38 39 # Affects the first container in mycluster-mysql-0 pod. 40 kbcli fault io latency mycluster-mysql-0 --delay=10s --volume-path=/data 41 42 # Affects the mysql container in mycluster-mysql-0 pod. 43 kbcli fault io latency mycluster-mysql-0 --delay=10s --volume-path=/data -c=mysql 44 45 # There is a 50% probability of affecting the read IO operation of the test.txt file under the /data path. 46 kbcli fault io latency mycluster-mysql-0 --delay=10s --volume-path=/data --path=test.txt --percent=50 --method=READ -c=mysql 47 48 # Same as above.Make all IO operations under the /data path return the specified error number 22 (Invalid argument). 49 kbcli fault io errno --volume-path=/data --errno=22 50 51 # Same as above.Modify the IO operation permission attribute of the files under the /data path to 72.(110 in octal). 52 kbcli fault io attribute --volume-path=/data --perm=72 53 54 # Modify all files so that random positions of 1's with a maximum length of 10 bytes will be replaced with 0's. 55 kbcli fault io mistake --volume-path=/data --filling=zero --max-occurrences=10 --max-length=1 56 `) 57 58 type IOAttribute struct { 59 Ino uint64 `json:"ino,omitempty"` 60 Size uint64 `json:"size,omitempty"` 61 Blocks uint64 `json:"blocks,omitempty"` 62 Perm uint16 `json:"perm,omitempty"` 63 Nlink uint32 `json:"nlink,omitempty"` 64 UID uint32 `json:"uid,omitempty"` 65 GID uint32 `json:"gid,omitempty"` 66 } 67 68 type IOMistake struct { 69 Filling string `json:"filling,omitempty"` 70 MaxOccurrences int `json:"maxOccurrences,omitempty"` 71 MaxLength int `json:"maxLength,omitempty"` 72 } 73 74 type IOChaosOptions struct { 75 // Parameters required by the `latency` command. 76 Delay string `json:"delay"` 77 78 // Parameters required by the `fault` command. 79 Errno int `json:"errno"` 80 81 // Parameters required by the `attribute` command. 82 IOAttribute `json:"attr,omitempty"` 83 84 // Parameters required by the `mistake` command. 85 IOMistake `json:"mistake,omitempty"` 86 87 VolumePath string `json:"volumePath"` 88 Path string `json:"path"` 89 Percent int `json:"percent"` 90 Methods []string `json:"methods,omitempty"` 91 ContainerNames []string `json:"containerNames,omitempty"` 92 93 FaultBaseOptions 94 } 95 96 func NewIOChaosCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 97 cmd := &cobra.Command{ 98 Use: "io", 99 Short: "IO chaos.", 100 } 101 cmd.AddCommand( 102 NewIOLatencyCmd(f, streams), 103 NewIOFaultCmd(f, streams), 104 NewIOAttributeOverrideCmd(f, streams), 105 NewIOMistakeCmd(f, streams), 106 ) 107 return cmd 108 } 109 110 func NewIOChaosOptions(f cmdutil.Factory, streams genericiooptions.IOStreams, action string) *IOChaosOptions { 111 o := &IOChaosOptions{ 112 FaultBaseOptions: FaultBaseOptions{ 113 CreateOptions: create.CreateOptions{ 114 Factory: f, 115 IOStreams: streams, 116 CueTemplateName: CueTemplateIOChaos, 117 GVR: GetGVR(Group, Version, ResourceIOChaos), 118 }, 119 Action: action, 120 }, 121 } 122 o.CreateOptions.PreCreate = o.PreCreate 123 o.CreateOptions.Options = o 124 return o 125 } 126 127 func NewIOLatencyCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 128 o := NewIOChaosOptions(f, streams, string(v1alpha1.IoLatency)) 129 cmd := o.NewCobraCommand(Latency, LatencyShort) 130 131 o.AddCommonFlag(cmd, f) 132 cmd.Flags().StringVar(&o.Delay, "delay", "", `Specific delay time.`) 133 134 util.CheckErr(cmd.MarkFlagRequired("delay")) 135 return cmd 136 } 137 138 func NewIOFaultCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 139 o := NewIOChaosOptions(f, streams, string(v1alpha1.IoFaults)) 140 cmd := o.NewCobraCommand(Errno, ErrnoShort) 141 142 o.AddCommonFlag(cmd, f) 143 cmd.Flags().IntVar(&o.Errno, "errno", 0, `The returned error number.`) 144 145 util.CheckErr(cmd.MarkFlagRequired("errno")) 146 return cmd 147 } 148 149 func NewIOAttributeOverrideCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 150 o := NewIOChaosOptions(f, streams, string(v1alpha1.IoAttrOverride)) 151 cmd := o.NewCobraCommand(Attribute, AttributeShort) 152 153 o.AddCommonFlag(cmd, f) 154 cmd.Flags().Uint64Var(&o.Ino, "ino", 0, `ino number.`) 155 cmd.Flags().Uint64Var(&o.Size, "size", 0, `File size.`) 156 cmd.Flags().Uint64Var(&o.Blocks, "blocks", 0, `The number of blocks the file occupies.`) 157 cmd.Flags().Uint16Var(&o.Perm, "perm", 0, `Decimal representation of file permissions.`) 158 cmd.Flags().Uint32Var(&o.Nlink, "nlink", 0, `The number of hard links.`) 159 cmd.Flags().Uint32Var(&o.UID, "uid", 0, `Owner's user ID.`) 160 cmd.Flags().Uint32Var(&o.GID, "gid", 0, `The owner's group ID.`) 161 162 return cmd 163 } 164 165 func NewIOMistakeCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 166 o := NewIOChaosOptions(f, streams, string(v1alpha1.IoMistake)) 167 cmd := o.NewCobraCommand(Mistake, MistakeShort) 168 169 o.AddCommonFlag(cmd, f) 170 cmd.Flags().StringVar(&o.Filling, "filling", "", `The filling content of the error data can only be zero (filling with 0) or random (filling with random bytes).`) 171 cmd.Flags().IntVar(&o.MaxOccurrences, "max-occurrences", 1, `The maximum number of times an error can occur per operation.`) 172 cmd.Flags().IntVar(&o.MaxLength, "max-length", 1, `The maximum length (in bytes) of each error.`) 173 174 util.CheckErr(cmd.MarkFlagRequired("filling")) 175 util.CheckErr(cmd.MarkFlagRequired("max-occurrences")) 176 util.CheckErr(cmd.MarkFlagRequired("max-length")) 177 178 return cmd 179 } 180 181 func (o *IOChaosOptions) NewCobraCommand(use, short string) *cobra.Command { 182 return &cobra.Command{ 183 Use: use, 184 Short: short, 185 Example: faultIOExample, 186 Run: func(cmd *cobra.Command, args []string) { 187 o.Args = args 188 cmdutil.CheckErr(o.CreateOptions.Complete()) 189 cmdutil.CheckErr(o.Validate()) 190 cmdutil.CheckErr(o.Complete()) 191 cmdutil.CheckErr(o.Run()) 192 }, 193 } 194 } 195 196 func (o *IOChaosOptions) AddCommonFlag(cmd *cobra.Command, f cmdutil.Factory) { 197 o.FaultBaseOptions.AddCommonFlag(cmd) 198 199 cmd.Flags().StringVar(&o.VolumePath, "volume-path", "", `The mount point of the volume in the target container must be the root directory of the mount.`) 200 cmd.Flags().StringVar(&o.Path, "path", "", `The effective scope of the injection error can be a wildcard or a single file.`) 201 cmd.Flags().IntVar(&o.Percent, "percent", 100, `Probability of failure per operation, in %.`) 202 cmd.Flags().StringArrayVar(&o.Methods, "method", nil, "The file system calls that need to inject faults. For example: WRITE READ") 203 cmd.Flags().StringArrayVarP(&o.ContainerNames, "container", "c", nil, "The name of the container, such as mysql, prometheus.If it's empty, the first container will be injected.") 204 205 util.CheckErr(cmd.MarkFlagRequired("volume-path")) 206 207 // register flag completion func 208 registerFlagCompletionFunc(cmd, f) 209 } 210 211 func (o *IOChaosOptions) Validate() error { 212 return o.BaseValidate() 213 } 214 215 func (o *IOChaosOptions) Complete() error { 216 return o.BaseComplete() 217 } 218 219 func (o *IOChaosOptions) PreCreate(obj *unstructured.Unstructured) error { 220 c := &v1alpha1.IOChaos{} 221 if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, c); err != nil { 222 return err 223 } 224 225 data, e := runtime.DefaultUnstructuredConverter.ToUnstructured(c) 226 if e != nil { 227 return e 228 } 229 obj.SetUnstructuredContent(data) 230 return nil 231 }