github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/functional/agent/handler.go (about) 1 // Copyright 2018 The etcd 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 package agent 16 17 import ( 18 "errors" 19 "fmt" 20 "net/url" 21 "os" 22 "os/exec" 23 "path/filepath" 24 "syscall" 25 "time" 26 27 "github.com/lfch/etcd-io/client/pkg/v3/fileutil" 28 "github.com/lfch/etcd-io/pkg/v3/proxy" 29 "github.com/lfch/etcd-io/tests/v3/functional/rpcpb" 30 31 "go.uber.org/zap" 32 ) 33 34 // return error for system errors (e.g. fail to create files) 35 // return status error in response for wrong configuration/operation (e.g. start etcd twice) 36 func (srv *Server) handleTesterRequest(req *rpcpb.Request) (resp *rpcpb.Response, err error) { 37 defer func() { 38 if err == nil && req != nil { 39 srv.last = req.Operation 40 srv.lg.Info("handler success", zap.String("operation", req.Operation.String())) 41 } 42 }() 43 if req != nil { 44 srv.Member = req.Member 45 srv.Tester = req.Tester 46 } 47 48 switch req.Operation { 49 case rpcpb.Operation_INITIAL_START_ETCD: 50 return srv.handle_INITIAL_START_ETCD(req) 51 case rpcpb.Operation_RESTART_ETCD: 52 return srv.handle_RESTART_ETCD(req) 53 54 case rpcpb.Operation_SIGTERM_ETCD: 55 return srv.handle_SIGTERM_ETCD() 56 case rpcpb.Operation_SIGQUIT_ETCD_AND_REMOVE_DATA: 57 return srv.handle_SIGQUIT_ETCD_AND_REMOVE_DATA() 58 59 case rpcpb.Operation_SAVE_SNAPSHOT: 60 return srv.handle_SAVE_SNAPSHOT() 61 case rpcpb.Operation_RESTORE_RESTART_FROM_SNAPSHOT: 62 return srv.handle_RESTORE_RESTART_FROM_SNAPSHOT(req) 63 case rpcpb.Operation_RESTART_FROM_SNAPSHOT: 64 return srv.handle_RESTART_FROM_SNAPSHOT(req) 65 66 case rpcpb.Operation_SIGQUIT_ETCD_AND_ARCHIVE_DATA: 67 return srv.handle_SIGQUIT_ETCD_AND_ARCHIVE_DATA() 68 case rpcpb.Operation_SIGQUIT_ETCD_AND_REMOVE_DATA_AND_STOP_AGENT: 69 return srv.handle_SIGQUIT_ETCD_AND_REMOVE_DATA_AND_STOP_AGENT() 70 71 case rpcpb.Operation_BLACKHOLE_PEER_PORT_TX_RX: 72 return srv.handle_BLACKHOLE_PEER_PORT_TX_RX(), nil 73 case rpcpb.Operation_UNBLACKHOLE_PEER_PORT_TX_RX: 74 return srv.handle_UNBLACKHOLE_PEER_PORT_TX_RX(), nil 75 case rpcpb.Operation_DELAY_PEER_PORT_TX_RX: 76 return srv.handle_DELAY_PEER_PORT_TX_RX(), nil 77 case rpcpb.Operation_UNDELAY_PEER_PORT_TX_RX: 78 return srv.handle_UNDELAY_PEER_PORT_TX_RX(), nil 79 80 default: 81 msg := fmt.Sprintf("operation not found (%v)", req.Operation) 82 return &rpcpb.Response{Success: false, Status: msg}, errors.New(msg) 83 } 84 } 85 86 // just archive the first file 87 func (srv *Server) createEtcdLogFile() error { 88 var err error 89 if srv.etcdLogFile, err = os.Create(srv.Member.Etcd.LogOutputs[0]); err != nil { 90 return err 91 } 92 srv.lg.Info("created etcd log file", zap.String("path", srv.Member.Etcd.LogOutputs[0])) 93 return nil 94 } 95 96 func (srv *Server) createEtcd(fromSnapshot bool, failpoints string) error { 97 if !fileutil.Exist(srv.Member.EtcdExec) { 98 return fmt.Errorf("unknown etcd exec path %q does not exist", srv.Member.EtcdExec) 99 } 100 101 etcdPath, etcdFlags := srv.Member.EtcdExec, srv.Member.Etcd.Flags() 102 if fromSnapshot { 103 etcdFlags = srv.Member.EtcdOnSnapshotRestore.Flags() 104 } 105 u, _ := url.Parse(srv.Member.FailpointHTTPAddr) 106 srv.lg.Info( 107 "creating etcd command", 108 zap.String("etcd-exec", etcdPath), 109 zap.Strings("etcd-flags", etcdFlags), 110 zap.String("GOFAIL_FAILPOINTS", failpoints), 111 zap.String("failpoint-http-addr", srv.Member.FailpointHTTPAddr), 112 zap.String("failpoint-addr", u.Host), 113 ) 114 srv.etcdCmd = exec.Command(etcdPath, etcdFlags...) 115 srv.etcdCmd.Env = []string{"GOFAIL_HTTP=" + u.Host} 116 if failpoints != "" { 117 srv.etcdCmd.Env = append(srv.etcdCmd.Env, "GOFAIL_FAILPOINTS="+failpoints) 118 } 119 srv.etcdCmd.Stdout = srv.etcdLogFile 120 srv.etcdCmd.Stderr = srv.etcdLogFile 121 return nil 122 } 123 124 // start but do not wait for it to complete 125 func (srv *Server) runEtcd() error { 126 errc := make(chan error) 127 go func() { 128 time.Sleep(1 * time.Second) 129 // server advertise client/peer listener had to start first 130 // before setting up proxy listener 131 errc <- srv.startProxy() 132 }() 133 134 if srv.etcdCmd != nil { 135 srv.lg.Info( 136 "starting etcd command", 137 zap.String("command-path", srv.etcdCmd.Path), 138 ) 139 err := srv.etcdCmd.Start() 140 141 srv.lg.Info( 142 "started etcd command", 143 zap.String("command-path", srv.etcdCmd.Path), 144 zap.Strings("command-args", srv.etcdCmd.Args), 145 zap.Strings("envs", srv.etcdCmd.Env), 146 zap.Error(err), 147 ) 148 if err != nil { 149 return err 150 } 151 152 return <-errc 153 } 154 155 select { 156 case <-srv.etcdServer.Server.ReadyNotify(): 157 srv.lg.Info("embedded etcd is ready") 158 case <-time.After(time.Minute): 159 srv.etcdServer.Close() 160 return fmt.Errorf("took too long to start %v", <-srv.etcdServer.Err()) 161 } 162 return <-errc 163 } 164 165 // SIGQUIT to exit with stackstrace 166 func (srv *Server) stopEtcd(sig os.Signal) error { 167 srv.stopProxy() 168 169 if srv.etcdCmd != nil { 170 srv.lg.Info( 171 "stopping etcd command", 172 zap.String("command-path", srv.etcdCmd.Path), 173 zap.String("signal", sig.String()), 174 ) 175 176 if err := srv.etcdCmd.Process.Signal(sig); err != nil { 177 return err 178 } 179 180 errc := make(chan error) 181 go func() { 182 _, ew := srv.etcdCmd.Process.Wait() 183 errc <- ew 184 close(errc) 185 }() 186 187 select { 188 case <-time.After(5 * time.Second): 189 srv.etcdCmd.Process.Kill() 190 case e := <-errc: 191 return e 192 } 193 194 err := <-errc 195 196 srv.lg.Info( 197 "stopped etcd command", 198 zap.String("command-path", srv.etcdCmd.Path), 199 zap.String("signal", sig.String()), 200 zap.Error(err), 201 ) 202 return err 203 } 204 205 srv.lg.Info("stopping embedded etcd") 206 srv.etcdServer.Server.HardStop() 207 srv.etcdServer.Close() 208 srv.lg.Info("stopped embedded etcd") 209 return nil 210 } 211 212 func (srv *Server) startProxy() error { 213 if srv.Member.EtcdClientProxy { 214 advertiseClientURL, advertiseClientURLPort, err := getURLAndPort(srv.Member.Etcd.AdvertiseClientURLs[0]) 215 if err != nil { 216 return err 217 } 218 listenClientURL, _, err := getURLAndPort(srv.Member.Etcd.ListenClientURLs[0]) 219 if err != nil { 220 return err 221 } 222 223 srv.lg.Info("Checking client target's connectivity", zap.String("target", listenClientURL.Host)) 224 if err := checkTCPConnect(srv.lg, listenClientURL.Host); err != nil { 225 return fmt.Errorf("check client target failed, %w", err) 226 } 227 228 srv.lg.Info("starting proxy on client traffic", zap.String("url", advertiseClientURL.String())) 229 srv.advertiseClientPortToProxy[advertiseClientURLPort] = proxy.NewServer(proxy.ServerConfig{ 230 Logger: srv.lg, 231 From: *advertiseClientURL, 232 To: *listenClientURL, 233 }) 234 select { 235 case err = <-srv.advertiseClientPortToProxy[advertiseClientURLPort].Error(): 236 srv.lg.Info("starting client proxy failed", zap.Error(err)) 237 return err 238 case <-time.After(2 * time.Second): 239 srv.lg.Info("started proxy on client traffic", zap.String("url", advertiseClientURL.String())) 240 } 241 } 242 243 if srv.Member.EtcdPeerProxy { 244 advertisePeerURL, advertisePeerURLPort, err := getURLAndPort(srv.Member.Etcd.AdvertisePeerURLs[0]) 245 if err != nil { 246 return err 247 } 248 listenPeerURL, _, err := getURLAndPort(srv.Member.Etcd.ListenPeerURLs[0]) 249 if err != nil { 250 return err 251 } 252 253 srv.lg.Info("Checking peer target's connectivity", zap.String("target", listenPeerURL.Host)) 254 if err := checkTCPConnect(srv.lg, listenPeerURL.Host); err != nil { 255 return fmt.Errorf("check peer target failed, %w", err) 256 } 257 258 srv.lg.Info("starting proxy on peer traffic", zap.String("url", advertisePeerURL.String())) 259 srv.advertisePeerPortToProxy[advertisePeerURLPort] = proxy.NewServer(proxy.ServerConfig{ 260 Logger: srv.lg, 261 From: *advertisePeerURL, 262 To: *listenPeerURL, 263 }) 264 select { 265 case err = <-srv.advertisePeerPortToProxy[advertisePeerURLPort].Error(): 266 srv.lg.Info("starting peer proxy failed", zap.Error(err)) 267 return err 268 case <-time.After(2 * time.Second): 269 srv.lg.Info("started proxy on peer traffic", zap.String("url", advertisePeerURL.String())) 270 } 271 } 272 return nil 273 } 274 275 func (srv *Server) stopProxy() { 276 if srv.Member.EtcdClientProxy && len(srv.advertiseClientPortToProxy) > 0 { 277 for port, px := range srv.advertiseClientPortToProxy { 278 if err := px.Close(); err != nil { 279 srv.lg.Warn("failed to close proxy", zap.Int("port", port)) 280 continue 281 } 282 select { 283 case <-px.Done(): 284 // enough time to release port 285 time.Sleep(time.Second) 286 case <-time.After(time.Second): 287 } 288 srv.lg.Info("closed proxy", 289 zap.Int("port", port), 290 zap.String("from", px.From()), 291 zap.String("to", px.To()), 292 ) 293 } 294 srv.advertiseClientPortToProxy = make(map[int]proxy.Server) 295 } 296 if srv.Member.EtcdPeerProxy && len(srv.advertisePeerPortToProxy) > 0 { 297 for port, px := range srv.advertisePeerPortToProxy { 298 if err := px.Close(); err != nil { 299 srv.lg.Warn("failed to close proxy", zap.Int("port", port)) 300 continue 301 } 302 select { 303 case <-px.Done(): 304 // enough time to release port 305 time.Sleep(time.Second) 306 case <-time.After(time.Second): 307 } 308 srv.lg.Info("closed proxy", 309 zap.Int("port", port), 310 zap.String("from", px.From()), 311 zap.String("to", px.To()), 312 ) 313 } 314 srv.advertisePeerPortToProxy = make(map[int]proxy.Server) 315 } 316 } 317 318 // if started with manual TLS, stores TLS assets 319 // from tester/client to disk before starting etcd process 320 func (srv *Server) saveTLSAssets() error { 321 const defaultFileMode os.FileMode = 0644 322 323 if err := safeDataToFile(srv.Member.PeerCertPath, []byte(srv.Member.PeerCertData), defaultFileMode); err != nil { 324 return err 325 } 326 if err := safeDataToFile(srv.Member.PeerKeyPath, []byte(srv.Member.PeerKeyData), defaultFileMode); err != nil { 327 return err 328 } 329 if err := safeDataToFile(srv.Member.PeerTrustedCAPath, []byte(srv.Member.PeerTrustedCAData), defaultFileMode); err != nil { 330 return err 331 } 332 if srv.Member.PeerCertPath != "" && 333 srv.Member.PeerKeyPath != "" && 334 srv.Member.PeerTrustedCAPath != "" { 335 srv.lg.Info( 336 "wrote", 337 zap.String("peer-cert", srv.Member.PeerCertPath), 338 zap.String("peer-key", srv.Member.PeerKeyPath), 339 zap.String("peer-trusted-ca", srv.Member.PeerTrustedCAPath), 340 ) 341 } 342 343 if err := safeDataToFile(srv.Member.ClientCertPath, []byte(srv.Member.ClientCertData), defaultFileMode); err != nil { 344 return err 345 } 346 if err := safeDataToFile(srv.Member.ClientKeyPath, []byte(srv.Member.ClientKeyData), defaultFileMode); err != nil { 347 return err 348 } 349 if err := safeDataToFile(srv.Member.ClientTrustedCAPath, []byte(srv.Member.ClientTrustedCAData), defaultFileMode); err != nil { 350 return err 351 } 352 if srv.Member.ClientCertPath != "" && 353 srv.Member.ClientKeyPath != "" && 354 srv.Member.ClientTrustedCAPath != "" { 355 srv.lg.Info( 356 "wrote", 357 zap.String("client-cert", srv.Member.ClientCertPath), 358 zap.String("client-key", srv.Member.ClientKeyPath), 359 zap.String("client-trusted-ca", srv.Member.ClientTrustedCAPath), 360 ) 361 } 362 return nil 363 } 364 365 func (srv *Server) loadAutoTLSAssets() error { 366 if srv.Member.Etcd.PeerAutoTLS { 367 // in case of slow disk 368 time.Sleep(time.Second) 369 370 fdir := filepath.Join(srv.Member.Etcd.DataDir, "fixtures", "peer") 371 372 srv.lg.Info( 373 "loading peer auto TLS assets", 374 zap.String("dir", fdir), 375 zap.String("endpoint", srv.EtcdClientEndpoint), 376 ) 377 // load peer cert.pem 378 certPath := filepath.Join(fdir, "cert.pem") 379 certData, err := loadFileData(certPath) 380 if err != nil { 381 return err 382 } 383 srv.Member.PeerCertData = string(certData) 384 // load peer key.pem 385 keyPath := filepath.Join(fdir, "key.pem") 386 keyData, err := loadFileData(keyPath) 387 if err != nil { 388 return err 389 } 390 srv.Member.PeerKeyData = string(keyData) 391 392 srv.lg.Info( 393 "loaded peer auto TLS assets", 394 zap.String("peer-cert-path", certPath), 395 zap.Int("peer-cert-length", len(certData)), 396 zap.String("peer-key-path", keyPath), 397 zap.Int("peer-key-length", len(keyData)), 398 ) 399 } 400 401 if srv.Member.Etcd.ClientAutoTLS { 402 // in case of slow disk 403 time.Sleep(time.Second) 404 405 fdir := filepath.Join(srv.Member.Etcd.DataDir, "fixtures", "client") 406 407 srv.lg.Info( 408 "loading client TLS assets", 409 zap.String("dir", fdir), 410 zap.String("endpoint", srv.EtcdClientEndpoint), 411 ) 412 // load client cert.pem 413 certPath := filepath.Join(fdir, "cert.pem") 414 certData, err := loadFileData(certPath) 415 if err != nil { 416 return err 417 } 418 srv.Member.ClientCertData = string(certData) 419 // load client key.pem 420 keyPath := filepath.Join(fdir, "key.pem") 421 keyData, err := loadFileData(keyPath) 422 if err != nil { 423 return err 424 } 425 srv.Member.ClientKeyData = string(keyData) 426 427 srv.lg.Info( 428 "loaded client TLS assets", 429 zap.String("client-cert-path", certPath), 430 zap.Int("client-cert-length", len(certData)), 431 zap.String("client-key-path", keyPath), 432 zap.Int("client-key-length", len(keyData)), 433 ) 434 } 435 436 return nil 437 } 438 439 func (srv *Server) handle_INITIAL_START_ETCD(req *rpcpb.Request) (*rpcpb.Response, error) { 440 if srv.last != rpcpb.Operation_NOT_STARTED { 441 return &rpcpb.Response{ 442 Success: false, 443 Status: fmt.Sprintf("%q is not valid; last server operation was %q", rpcpb.Operation_INITIAL_START_ETCD.String(), srv.last.String()), 444 Member: req.Member, 445 }, nil 446 } 447 448 if err := fileutil.TouchDirAll(srv.lg, srv.Member.BaseDir); err != nil { 449 return nil, err 450 } 451 srv.lg.Info("created base directory", zap.String("path", srv.Member.BaseDir)) 452 453 if srv.etcdServer == nil { 454 if err := srv.createEtcdLogFile(); err != nil { 455 return nil, err 456 } 457 } 458 459 if err := srv.saveTLSAssets(); err != nil { 460 return nil, err 461 } 462 if err := srv.createEtcd(false, req.Member.Failpoints); err != nil { 463 return nil, err 464 } 465 if err := srv.runEtcd(); err != nil { 466 return nil, err 467 } 468 if err := srv.loadAutoTLSAssets(); err != nil { 469 return nil, err 470 } 471 472 return &rpcpb.Response{ 473 Success: true, 474 Status: "start etcd PASS", 475 Member: srv.Member, 476 }, nil 477 } 478 479 func (srv *Server) handle_RESTART_ETCD(req *rpcpb.Request) (*rpcpb.Response, error) { 480 var err error 481 if !fileutil.Exist(srv.Member.BaseDir) { 482 if err = fileutil.TouchDirAll(srv.lg, srv.Member.BaseDir); err != nil { 483 return nil, err 484 } 485 } 486 487 if err = srv.saveTLSAssets(); err != nil { 488 return nil, err 489 } 490 if err = srv.createEtcd(false, req.Member.Failpoints); err != nil { 491 return nil, err 492 } 493 if err = srv.runEtcd(); err != nil { 494 return nil, err 495 } 496 if err = srv.loadAutoTLSAssets(); err != nil { 497 return nil, err 498 } 499 500 return &rpcpb.Response{ 501 Success: true, 502 Status: "restart etcd PASS", 503 Member: srv.Member, 504 }, nil 505 } 506 507 func (srv *Server) handle_SIGTERM_ETCD() (*rpcpb.Response, error) { 508 if err := srv.stopEtcd(syscall.SIGTERM); err != nil { 509 return nil, err 510 } 511 512 if srv.etcdServer != nil { 513 srv.etcdServer.GetLogger().Sync() 514 } else { 515 srv.etcdLogFile.Sync() 516 } 517 518 return &rpcpb.Response{ 519 Success: true, 520 Status: "killed etcd", 521 }, nil 522 } 523 524 func (srv *Server) handle_SIGQUIT_ETCD_AND_REMOVE_DATA() (*rpcpb.Response, error) { 525 if err := srv.stopEtcd(syscall.SIGQUIT); err != nil { 526 return nil, err 527 } 528 529 if srv.etcdServer != nil { 530 srv.etcdServer.GetLogger().Sync() 531 } else { 532 srv.etcdLogFile.Sync() 533 srv.etcdLogFile.Close() 534 } 535 536 // for debugging purposes, rename instead of removing 537 if err := os.RemoveAll(srv.Member.BaseDir + ".backup"); err != nil { 538 return nil, err 539 } 540 if err := os.Rename(srv.Member.BaseDir, srv.Member.BaseDir+".backup"); err != nil { 541 return nil, err 542 } 543 srv.lg.Info( 544 "renamed", 545 zap.String("base-dir", srv.Member.BaseDir), 546 zap.String("new-dir", srv.Member.BaseDir+".backup"), 547 ) 548 549 // create a new log file for next new member restart 550 if !fileutil.Exist(srv.Member.BaseDir) { 551 if err := fileutil.TouchDirAll(srv.lg, srv.Member.BaseDir); err != nil { 552 return nil, err 553 } 554 } 555 556 return &rpcpb.Response{ 557 Success: true, 558 Status: "killed etcd and removed base directory", 559 }, nil 560 } 561 562 func (srv *Server) handle_SAVE_SNAPSHOT() (*rpcpb.Response, error) { 563 if err := srv.Member.SaveSnapshot(srv.lg); err != nil { 564 return nil, err 565 } 566 return &rpcpb.Response{ 567 Success: true, 568 Status: "saved snapshot", 569 SnapshotInfo: srv.Member.SnapshotInfo, 570 }, nil 571 } 572 573 func (srv *Server) handle_RESTORE_RESTART_FROM_SNAPSHOT(req *rpcpb.Request) (resp *rpcpb.Response, err error) { 574 if err = srv.Member.RestoreSnapshot(srv.lg); err != nil { 575 return nil, err 576 } 577 resp, err = srv.handle_RESTART_FROM_SNAPSHOT(req) 578 if resp != nil && err == nil { 579 resp.Status = "restored snapshot and " + resp.Status 580 } 581 return resp, err 582 } 583 584 func (srv *Server) handle_RESTART_FROM_SNAPSHOT(req *rpcpb.Request) (resp *rpcpb.Response, err error) { 585 if err = srv.saveTLSAssets(); err != nil { 586 return nil, err 587 } 588 if err = srv.createEtcd(true, req.Member.Failpoints); err != nil { 589 return nil, err 590 } 591 if err = srv.runEtcd(); err != nil { 592 return nil, err 593 } 594 if err = srv.loadAutoTLSAssets(); err != nil { 595 return nil, err 596 } 597 598 return &rpcpb.Response{ 599 Success: true, 600 Status: "restarted etcd from snapshot", 601 SnapshotInfo: srv.Member.SnapshotInfo, 602 }, nil 603 } 604 605 func (srv *Server) handle_SIGQUIT_ETCD_AND_ARCHIVE_DATA() (*rpcpb.Response, error) { 606 if err := srv.stopEtcd(syscall.SIGQUIT); err != nil { 607 return nil, err 608 } 609 610 if srv.etcdServer != nil { 611 srv.etcdServer.GetLogger().Sync() 612 } else { 613 srv.etcdLogFile.Sync() 614 srv.etcdLogFile.Close() 615 } 616 617 // TODO: support separate WAL directory 618 if err := archive(srv.lg, srv.Member.BaseDir, srv.Member.Etcd.LogOutputs[0], srv.Member.Etcd.DataDir); err != nil { 619 return nil, err 620 } 621 srv.lg.Info("archived data", zap.String("base-dir", srv.Member.BaseDir)) 622 623 if srv.etcdServer == nil { 624 if err := srv.createEtcdLogFile(); err != nil { 625 return nil, err 626 } 627 } 628 629 // TODO: Verify whether this cleaning of 'cache pages' is needed. 630 srv.lg.Info("cleaning up page cache") 631 if err := cleanPageCache(); err != nil { 632 srv.lg.Warn("failed to clean up page cache", zap.String("error", err.Error())) 633 } 634 srv.lg.Info("cleaned up page cache") 635 636 return &rpcpb.Response{ 637 Success: true, 638 Status: "cleaned up etcd", 639 }, nil 640 } 641 642 // stop proxy, etcd, delete data directory 643 func (srv *Server) handle_SIGQUIT_ETCD_AND_REMOVE_DATA_AND_STOP_AGENT() (*rpcpb.Response, error) { 644 if err := srv.stopEtcd(syscall.SIGQUIT); err != nil { 645 return nil, err 646 } 647 648 if srv.etcdServer != nil { 649 srv.etcdServer.GetLogger().Sync() 650 } else { 651 srv.etcdLogFile.Sync() 652 srv.etcdLogFile.Close() 653 } 654 655 if err := os.RemoveAll(srv.Member.BaseDir); err != nil { 656 return nil, err 657 } 658 srv.lg.Info("removed base directory", zap.String("dir", srv.Member.BaseDir)) 659 660 // stop agent server 661 srv.Stop() 662 663 return &rpcpb.Response{ 664 Success: true, 665 Status: "destroyed etcd and agent", 666 }, nil 667 } 668 669 func (srv *Server) handle_BLACKHOLE_PEER_PORT_TX_RX() *rpcpb.Response { 670 for port, px := range srv.advertisePeerPortToProxy { 671 srv.lg.Info("blackholing", zap.Int("peer-port", port)) 672 px.BlackholeTx() 673 px.BlackholeRx() 674 srv.lg.Info("blackholed", zap.Int("peer-port", port)) 675 } 676 return &rpcpb.Response{ 677 Success: true, 678 Status: "blackholed peer port tx/rx", 679 } 680 } 681 682 func (srv *Server) handle_UNBLACKHOLE_PEER_PORT_TX_RX() *rpcpb.Response { 683 for port, px := range srv.advertisePeerPortToProxy { 684 srv.lg.Info("unblackholing", zap.Int("peer-port", port)) 685 px.UnblackholeTx() 686 px.UnblackholeRx() 687 srv.lg.Info("unblackholed", zap.Int("peer-port", port)) 688 } 689 return &rpcpb.Response{ 690 Success: true, 691 Status: "unblackholed peer port tx/rx", 692 } 693 } 694 695 func (srv *Server) handle_DELAY_PEER_PORT_TX_RX() *rpcpb.Response { 696 lat := time.Duration(srv.Tester.UpdatedDelayLatencyMs) * time.Millisecond 697 rv := time.Duration(srv.Tester.DelayLatencyMsRv) * time.Millisecond 698 699 for port, px := range srv.advertisePeerPortToProxy { 700 srv.lg.Info("delaying", 701 zap.Int("peer-port", port), 702 zap.Duration("latency", lat), 703 zap.Duration("random-variable", rv), 704 ) 705 px.DelayTx(lat, rv) 706 px.DelayRx(lat, rv) 707 srv.lg.Info("delayed", 708 zap.Int("peer-port", port), 709 zap.Duration("latency", lat), 710 zap.Duration("random-variable", rv), 711 ) 712 } 713 714 return &rpcpb.Response{ 715 Success: true, 716 Status: "delayed peer port tx/rx", 717 } 718 } 719 720 func (srv *Server) handle_UNDELAY_PEER_PORT_TX_RX() *rpcpb.Response { 721 for port, px := range srv.advertisePeerPortToProxy { 722 srv.lg.Info("undelaying", zap.Int("peer-port", port)) 723 px.UndelayTx() 724 px.UndelayRx() 725 srv.lg.Info("undelayed", zap.Int("peer-port", port)) 726 } 727 return &rpcpb.Response{ 728 Success: true, 729 Status: "undelayed peer port tx/rx", 730 } 731 }