github.com/midokura/kubeedge@v1.2.0-mido.0/tests/performance/common/common.go (about) 1 /* 2 Copyright 2019 The KubeEdge Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package common 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "io" 23 "io/ioutil" 24 "math" 25 "net/http" 26 "os/exec" 27 "sort" 28 "strconv" 29 "strings" 30 "time" 31 32 . "github.com/onsi/gomega" 33 v1 "k8s.io/api/core/v1" 34 35 "github.com/kubeedge/kubeedge/tests/e2e/utils" 36 "github.com/kubeedge/kubeedge/tests/stubs/common/constants" 37 "github.com/kubeedge/kubeedge/tests/stubs/common/types" 38 ) 39 40 //K8s resource handlers 41 const ( 42 AppHandler = "/api/v1/namespaces/default/pods" 43 NodeHandler = "/api/v1/nodes" 44 DeploymentHandler = "/apis/apps/v1/namespaces/default/deployments" 45 ConfigmapHandler = "/api/v1/namespaces/default/configmaps" 46 ServiceHandler = "/api/v1/namespaces/default/services" 47 NodelabelKey = "k8snode" 48 NodelabelVal = "kb-perf-node" 49 ) 50 51 var ( 52 chconfigmapRet = make(chan error) 53 Deployments []string 54 NodeInfo = make(map[string][]string) 55 CloudConfigMap string 56 CloudCoreDeployment string 57 ToTaint bool 58 IsQuicProtocol bool 59 ) 60 61 func HandleCloudDeployment(cloudConfigMap, cloudCoreDeployment, apiserver2, confighdl, deploymenthdl, imgURL string, nodelimit int) error { 62 nodes := strconv.FormatInt(int64(nodelimit), 10) 63 cmd := exec.Command("bash", "-x", "scripts/update_configmap.sh", "create_cloud_config", "", apiserver2, cloudConfigMap, nodes) 64 err := utils.PrintCombinedOutput(cmd) 65 Expect(err).Should(BeNil()) 66 go utils.HandleConfigmap(chconfigmapRet, http.MethodPost, confighdl, false) 67 ret := <-chconfigmapRet 68 Expect(ret).To(BeNil()) 69 utils.ProtocolQuic = IsQuicProtocol 70 //Handle cloudCore deployment 71 go utils.HandleDeployment(true, false, http.MethodPost, deploymenthdl, cloudCoreDeployment, imgURL, "", cloudConfigMap, 1) 72 73 return nil 74 } 75 76 func CreateConfigMapforEdgeCore(cloudhub, cmHandler, nodeHandler string, numOfNodes int) { 77 //Create edgecore configMaps based on the users choice of edgecore deployment. 78 for i := 0; i < numOfNodes; i++ { 79 nodeName := "perf-node-" + utils.GetRandomString(10) 80 nodeSelector := "node-" + utils.GetRandomString(5) 81 configmap := "edgecore-configmap-" + utils.GetRandomString(5) 82 //Register EdgeNodes to K8s Master 83 go utils.RegisterNodeToMaster(nodeName, nodeHandler, nodeSelector) 84 cmd := exec.Command("bash", "-x", "scripts/update_configmap.sh", "create_edge_config", nodeName, cloudhub, configmap) 85 err := utils.PrintCombinedOutput(cmd) 86 Expect(err).Should(BeNil()) 87 //Create ConfigMaps for Each EdgeNode created 88 go utils.HandleConfigmap(chconfigmapRet, http.MethodPost, cmHandler, true) 89 ret := <-chconfigmapRet 90 Expect(ret).To(BeNil()) 91 //Store the ConfigMap against each edgenode 92 NodeInfo[nodeName] = append(NodeInfo[nodeName], configmap, nodeSelector) 93 } 94 } 95 96 func HandleEdgeCorePodDeployment(depHandler, imgURL, podHandler, nodeHandler string, numOfNodes int) v1.PodList { 97 replica := 1 98 //Create edgeCore deployments as per users configuration 99 for _, configmap := range NodeInfo { 100 UID := "edgecore-deployment-" + utils.GetRandomString(5) 101 go utils.HandleDeployment(false, true, http.MethodPost, depHandler, UID, imgURL, "", configmap[0], replica) 102 Deployments = append(Deployments, UID) 103 } 104 time.Sleep(2 * time.Second) 105 podlist, err := utils.GetPods(podHandler, "") 106 Expect(err).To(BeNil()) 107 utils.CheckPodRunningState(podHandler, podlist) 108 109 //Check All EdgeNode are in Running state 110 Eventually(func() int { 111 count := 0 112 for edgenodeName := range NodeInfo { 113 status := utils.CheckNodeReadyStatus(nodeHandler, edgenodeName) 114 utils.Infof("Node Name: %v, Node Status: %v", edgenodeName, status) 115 if status == "Running" { 116 count++ 117 } 118 } 119 return count 120 }, "1200s", "2s").Should(Equal(numOfNodes), "Nodes register to the k8s master is unsuccessfull !!") 121 122 return podlist 123 } 124 125 func HandleEdgeDeployment(cloudhub, depHandler, nodeHandler, cmHandler, imgURL, podHandler string, numOfNodes int) v1.PodList { 126 CreateConfigMapforEdgeCore(cloudhub, cmHandler, nodeHandler, numOfNodes) 127 podlist := HandleEdgeCorePodDeployment(depHandler, imgURL, podHandler, nodeHandler, numOfNodes) 128 return podlist 129 } 130 131 func DeleteEdgeDeployments(apiServerForRegisterNode, apiServerForDeployments string, nodes int) { 132 //delete confogMap 133 for _, configmap := range NodeInfo { 134 go utils.HandleConfigmap(chconfigmapRet, http.MethodDelete, apiServerForDeployments+ConfigmapHandler+"/"+configmap[0], false) 135 ret := <-chconfigmapRet 136 Expect(ret).To(BeNil()) 137 138 } 139 //delete edgenode deployment 140 for _, depName := range Deployments { 141 go utils.HandleDeployment(true, true, http.MethodDelete, apiServerForDeployments+DeploymentHandler+"/"+depName, "", "", "", "", 0) 142 } 143 //delete edgenodes 144 for edgenodeName := range NodeInfo { 145 err := utils.DeRegisterNodeFromMaster(apiServerForRegisterNode+NodeHandler, edgenodeName) 146 if err != nil { 147 utils.Fatalf("DeRegisterNodeFromMaster failed: %v", err) 148 } 149 } 150 //Verify deployments, configmaps, nodes are deleted successfully 151 Eventually(func() int { 152 count := 0 153 for _, depName := range Deployments { 154 statusCode := utils.VerifyDeleteDeployment(apiServerForDeployments + DeploymentHandler + "/" + depName) 155 if statusCode == 404 { 156 count++ 157 } 158 } 159 return count 160 }, "60s", "4s").Should(Equal(len(Deployments)), "EdgeNode deployments delete unsuccessfull !!") 161 162 Eventually(func() int { 163 count := 0 164 for _, configmap := range NodeInfo { 165 statusCode, _ := utils.GetConfigmap(apiServerForDeployments + ConfigmapHandler + "/" + configmap[0]) 166 if statusCode == 404 { 167 count++ 168 } 169 } 170 return count 171 }, "60s", "4s").Should(Equal(len(Deployments)), "EdgeNode configMaps delete unsuccessfull !!") 172 173 Eventually(func() int { 174 count := 0 175 for edgenodeName := range NodeInfo { 176 status := utils.CheckNodeDeleteStatus(apiServerForRegisterNode+NodeHandler, edgenodeName) 177 utils.Infof("Node Name: %v, Node Status: %v", edgenodeName, status) 178 if status == 404 { 179 count++ 180 } 181 } 182 return count 183 }, "60s", "4s").Should(Equal(nodes), "EdgeNode deleton is unsuccessfull !!") 184 //Cleanup globals 185 NodeInfo = map[string][]string{} 186 Deployments = nil 187 } 188 189 func DeleteCloudDeployment(apiserver string) { 190 //delete cloud deployment 191 go utils.HandleDeployment(true, true, http.MethodDelete, apiserver+DeploymentHandler+"/"+CloudCoreDeployment, "", "", "", "", 0) 192 //delete cloud configMap 193 go utils.HandleConfigmap(chconfigmapRet, http.MethodDelete, apiserver+ConfigmapHandler+"/"+CloudConfigMap, false) 194 ret := <-chconfigmapRet 195 Expect(ret).To(BeNil()) 196 //delete cloud svc 197 StatusCode := utils.DeleteSvc(apiserver + ServiceHandler + "/" + CloudCoreDeployment) 198 Expect(StatusCode).Should(Equal(http.StatusOK)) 199 } 200 201 func ApplyLabel(nodeHandler string) error { 202 var isMasterNode bool 203 nodes := utils.GetNodes(nodeHandler) 204 for _, node := range nodes.Items { 205 isMasterNode = false 206 for key := range node.Labels { 207 if strings.Contains(key, "node-role.kubernetes.io/master") { 208 isMasterNode = true 209 break 210 } 211 } 212 if isMasterNode == false { 213 utils.ApplyLabelToNode(nodeHandler+"/"+node.Name, NodelabelKey, NodelabelVal) 214 } 215 } 216 return nil 217 } 218 219 // AddFakePod adds a fake pod 220 func AddFakePod(ControllerHubURL string, pod types.FakePod) { 221 reqBody, err := json.Marshal(pod) 222 if err != nil { 223 utils.Fatalf("Unmarshal HTTP Response has failed: %v", err) 224 } 225 226 err, resp := SendHttpRequest(http.MethodPost, 227 ControllerHubURL+constants.PodResource, 228 bytes.NewBuffer(reqBody)) 229 if err != nil { 230 utils.Fatalf("Frame HTTP request failed: %v", err) 231 } 232 233 if resp != nil { 234 defer resp.Body.Close() 235 236 contents, err := ioutil.ReadAll(resp.Body) 237 if err != nil { 238 utils.Fatalf("HTTP Response reading has failed: %v", err) 239 } 240 241 if contents != nil { 242 utils.Infof("AddPod response: %v", contents) 243 } else { 244 utils.Infof("AddPod response: nil") 245 } 246 } 247 } 248 249 // DeleteFakePod deletes a fake pod 250 func DeleteFakePod(ControllerHubURL string, pod types.FakePod) { 251 err, resp := SendHttpRequest(http.MethodDelete, 252 ControllerHubURL+constants.PodResource+ 253 "?name="+pod.Name+"&namespace="+pod.Namespace+"&nodename="+pod.NodeName, 254 nil) 255 if err != nil { 256 utils.Fatalf("Frame HTTP request failed: %v", err) 257 } 258 259 if resp != nil { 260 defer resp.Body.Close() 261 262 contents, err := ioutil.ReadAll(resp.Body) 263 if err != nil { 264 utils.Fatalf("HTTP Response reading has failed: %v", err) 265 } 266 267 if contents != nil { 268 utils.Infof("DeletePod response: %v", contents) 269 } else { 270 utils.Infof("DeletePod response: nil") 271 } 272 } 273 } 274 275 // ListFakePods lists all fake pods 276 func ListFakePods(ControllerHubURL string) []types.FakePod { 277 pods := []types.FakePod{} 278 err, resp := SendHttpRequest(http.MethodGet, ControllerHubURL+constants.PodResource, nil) 279 if err != nil { 280 utils.Fatalf("Frame HTTP request failed: %v", err) 281 } 282 283 if resp != nil { 284 defer resp.Body.Close() 285 286 contents, err := ioutil.ReadAll(resp.Body) 287 if err != nil { 288 utils.Fatalf("HTTP Response reading has failed: %v", err) 289 } 290 291 err = json.Unmarshal(contents, &pods) 292 if err != nil { 293 utils.Fatalf("Unmarshal message content with error: %s", err) 294 } 295 } 296 297 utils.Infof("ListPods result: %d", len(pods)) 298 return pods 299 } 300 301 // SendHttpRequest launches a http request 302 func SendHttpRequest(method, reqApi string, body io.Reader) (error, *http.Response) { 303 var resp *http.Response 304 client := &http.Client{} 305 req, err := http.NewRequest(method, reqApi, body) 306 if err != nil { 307 utils.Fatalf("Frame HTTP request failed: %v", err) 308 return err, resp 309 } 310 req.Header.Set("Content-Type", "application/json") 311 t := time.Now() 312 resp, err = client.Do(req) 313 if err != nil { 314 utils.Fatalf("HTTP request is failed :%v", err) 315 return err, resp 316 } 317 if resp != nil { 318 utils.Infof("%s %s %v in %v", req.Method, req.URL, resp.Status, time.Now().Sub(t)) 319 } 320 return nil, resp 321 } 322 323 // GetLatency calculates latency based on different percent 324 func GetLatency(pods []types.FakePod) types.Latency { 325 latency := types.Latency{} 326 if len(pods) > 0 { 327 // Sort fake pods 328 sort.Stable(types.FakePodSort(pods)) 329 330 // Get 50% throughputs latency 331 index50 := int(math.Ceil(float64(len(pods)) * 0.50)) 332 latency.Percent50 = time.Duration(pods[index50-1].RunningTime - pods[index50-1].CreateTime) 333 334 // Get 90% throughputs latency 335 index90 := int(math.Ceil(float64(len(pods)) * 0.90)) 336 latency.Percent90 = time.Duration(pods[index90-1].RunningTime - pods[index90-1].CreateTime) 337 338 // Get 99% throughputs latency 339 index99 := int(math.Ceil(float64(len(pods)) * 0.99)) 340 latency.Percent99 = time.Duration(pods[index99-1].RunningTime - pods[index99-1].CreateTime) 341 342 // Get 100% throughputs latency 343 index100 := int(math.Ceil(float64(len(pods)) * 1.00)) 344 latency.Percent100 = time.Duration(pods[index100-1].RunningTime - pods[index100-1].CreateTime) 345 } 346 return latency 347 }