storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/peer-rest-server.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2019 MinIO, Inc. 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 cmd 18 19 import ( 20 "context" 21 "encoding/gob" 22 "errors" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "net/http" 27 "strconv" 28 "strings" 29 "time" 30 31 "github.com/gorilla/mux" 32 "github.com/tinylib/msgp/msgp" 33 34 "storj.io/minio/cmd/logger" 35 b "storj.io/minio/pkg/bucket/bandwidth" 36 "storj.io/minio/pkg/event" 37 "storj.io/minio/pkg/madmin" 38 trace "storj.io/minio/pkg/trace" 39 ) 40 41 // To abstract a node over network. 42 type peerRESTServer struct{} 43 44 // GetLocksHandler - returns list of older lock from the server. 45 func (s *peerRESTServer) GetLocksHandler(w http.ResponseWriter, r *http.Request) { 46 if !s.IsValid(w, r) { 47 s.WriteErrorResponse(w, errors.New("Invalid request")) 48 return 49 } 50 51 ctx := NewContext(r, w, "GetLocks") 52 logger.LogIf(ctx, gob.NewEncoder(w).Encode(globalLockServer.DupLockMap())) 53 54 w.(http.Flusher).Flush() 55 56 } 57 58 // DeletePolicyHandler - deletes a policy on the server. 59 func (s *peerRESTServer) DeletePolicyHandler(w http.ResponseWriter, r *http.Request) { 60 if !s.IsValid(w, r) { 61 s.WriteErrorResponse(w, errors.New("Invalid request")) 62 return 63 } 64 65 objAPI := newObjectLayerFn() 66 if objAPI == nil { 67 s.WriteErrorResponse(w, errServerNotInitialized) 68 return 69 } 70 71 vars := mux.Vars(r) 72 policyName := vars[peerRESTPolicy] 73 if policyName == "" { 74 s.WriteErrorResponse(w, errors.New("policyName is missing")) 75 return 76 } 77 78 if err := GlobalIAMSys.DeletePolicy(policyName); err != nil { 79 s.WriteErrorResponse(w, err) 80 return 81 } 82 83 w.(http.Flusher).Flush() 84 } 85 86 // LoadPolicyHandler - reloads a policy on the server. 87 func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Request) { 88 if !s.IsValid(w, r) { 89 s.WriteErrorResponse(w, errors.New("Invalid request")) 90 return 91 } 92 93 objAPI := newObjectLayerFn() 94 if objAPI == nil { 95 s.WriteErrorResponse(w, errServerNotInitialized) 96 return 97 } 98 99 vars := mux.Vars(r) 100 policyName := vars[peerRESTPolicy] 101 if policyName == "" { 102 s.WriteErrorResponse(w, errors.New("policyName is missing")) 103 return 104 } 105 106 if err := GlobalIAMSys.LoadPolicy(objAPI, policyName); err != nil { 107 s.WriteErrorResponse(w, err) 108 return 109 } 110 111 w.(http.Flusher).Flush() 112 } 113 114 // LoadPolicyMappingHandler - reloads a policy mapping on the server. 115 func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http.Request) { 116 if !s.IsValid(w, r) { 117 s.WriteErrorResponse(w, errors.New("Invalid request")) 118 return 119 } 120 121 objAPI := newObjectLayerFn() 122 if objAPI == nil { 123 s.WriteErrorResponse(w, errServerNotInitialized) 124 return 125 } 126 127 vars := mux.Vars(r) 128 userOrGroup := vars[peerRESTUserOrGroup] 129 if userOrGroup == "" { 130 s.WriteErrorResponse(w, errors.New("user-or-group is missing")) 131 return 132 } 133 _, isGroup := vars[peerRESTIsGroup] 134 135 if err := GlobalIAMSys.LoadPolicyMapping(objAPI, userOrGroup, isGroup); err != nil { 136 s.WriteErrorResponse(w, err) 137 return 138 } 139 140 w.(http.Flusher).Flush() 141 } 142 143 // DeleteServiceAccountHandler - deletes a service account on the server. 144 func (s *peerRESTServer) DeleteServiceAccountHandler(w http.ResponseWriter, r *http.Request) { 145 if !s.IsValid(w, r) { 146 s.WriteErrorResponse(w, errors.New("Invalid request")) 147 return 148 } 149 150 objAPI := newObjectLayerFn() 151 if objAPI == nil { 152 s.WriteErrorResponse(w, errServerNotInitialized) 153 return 154 } 155 156 vars := mux.Vars(r) 157 accessKey := vars[peerRESTUser] 158 if accessKey == "" { 159 s.WriteErrorResponse(w, errors.New("service account name is missing")) 160 return 161 } 162 163 if err := GlobalIAMSys.DeleteServiceAccount(r.Context(), accessKey); err != nil { 164 s.WriteErrorResponse(w, err) 165 return 166 } 167 168 w.(http.Flusher).Flush() 169 } 170 171 // LoadServiceAccountHandler - reloads a service account on the server. 172 func (s *peerRESTServer) LoadServiceAccountHandler(w http.ResponseWriter, r *http.Request) { 173 if !s.IsValid(w, r) { 174 s.WriteErrorResponse(w, errors.New("Invalid request")) 175 return 176 } 177 178 objAPI := newObjectLayerFn() 179 if objAPI == nil { 180 s.WriteErrorResponse(w, errServerNotInitialized) 181 return 182 } 183 184 vars := mux.Vars(r) 185 accessKey := vars[peerRESTUser] 186 if accessKey == "" { 187 s.WriteErrorResponse(w, errors.New("service account parameter is missing")) 188 return 189 } 190 191 if err := GlobalIAMSys.LoadServiceAccount(accessKey); err != nil { 192 s.WriteErrorResponse(w, err) 193 return 194 } 195 196 w.(http.Flusher).Flush() 197 } 198 199 // DeleteUserHandler - deletes a user on the server. 200 func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Request) { 201 if !s.IsValid(w, r) { 202 s.WriteErrorResponse(w, errors.New("Invalid request")) 203 return 204 } 205 206 objAPI := newObjectLayerFn() 207 if objAPI == nil { 208 s.WriteErrorResponse(w, errServerNotInitialized) 209 return 210 } 211 212 vars := mux.Vars(r) 213 accessKey := vars[peerRESTUser] 214 if accessKey == "" { 215 s.WriteErrorResponse(w, errors.New("username is missing")) 216 return 217 } 218 219 if err := GlobalIAMSys.DeleteUser(accessKey); err != nil { 220 s.WriteErrorResponse(w, err) 221 return 222 } 223 224 w.(http.Flusher).Flush() 225 } 226 227 // LoadUserHandler - reloads a user on the server. 228 func (s *peerRESTServer) LoadUserHandler(w http.ResponseWriter, r *http.Request) { 229 if !s.IsValid(w, r) { 230 s.WriteErrorResponse(w, errors.New("Invalid request")) 231 return 232 } 233 234 objAPI := newObjectLayerFn() 235 if objAPI == nil { 236 s.WriteErrorResponse(w, errServerNotInitialized) 237 return 238 } 239 240 vars := mux.Vars(r) 241 accessKey := vars[peerRESTUser] 242 if accessKey == "" { 243 s.WriteErrorResponse(w, errors.New("username is missing")) 244 return 245 } 246 247 temp, err := strconv.ParseBool(vars[peerRESTUserTemp]) 248 if err != nil { 249 s.WriteErrorResponse(w, err) 250 return 251 } 252 253 var userType = regularUser 254 if temp { 255 userType = stsUser 256 } 257 258 if err = GlobalIAMSys.LoadUser(objAPI, accessKey, userType); err != nil { 259 s.WriteErrorResponse(w, err) 260 return 261 } 262 263 w.(http.Flusher).Flush() 264 } 265 266 // LoadGroupHandler - reloads group along with members list. 267 func (s *peerRESTServer) LoadGroupHandler(w http.ResponseWriter, r *http.Request) { 268 if !s.IsValid(w, r) { 269 s.WriteErrorResponse(w, errors.New("Invalid request")) 270 return 271 } 272 273 objAPI := newObjectLayerFn() 274 if objAPI == nil { 275 s.WriteErrorResponse(w, errServerNotInitialized) 276 return 277 } 278 279 vars := mux.Vars(r) 280 group := vars[peerRESTGroup] 281 err := GlobalIAMSys.LoadGroup(objAPI, group) 282 if err != nil { 283 s.WriteErrorResponse(w, err) 284 return 285 } 286 287 w.(http.Flusher).Flush() 288 } 289 290 // StartProfilingHandler - Issues the start profiling command. 291 func (s *peerRESTServer) StartProfilingHandler(w http.ResponseWriter, r *http.Request) { 292 if !s.IsValid(w, r) { 293 s.WriteErrorResponse(w, errors.New("Invalid request")) 294 return 295 } 296 297 vars := mux.Vars(r) 298 profiles := strings.Split(vars[peerRESTProfiler], ",") 299 if len(profiles) == 0 { 300 s.WriteErrorResponse(w, errors.New("profiler name is missing")) 301 return 302 } 303 globalProfilerMu.Lock() 304 defer globalProfilerMu.Unlock() 305 if globalProfiler == nil { 306 globalProfiler = make(map[string]minioProfiler, 10) 307 } 308 309 // Stop profiler of all types if already running 310 for k, v := range globalProfiler { 311 for _, p := range profiles { 312 if p == k { 313 v.Stop() 314 delete(globalProfiler, k) 315 } 316 } 317 } 318 319 for _, profiler := range profiles { 320 prof, err := startProfiler(profiler) 321 if err != nil { 322 s.WriteErrorResponse(w, err) 323 return 324 } 325 globalProfiler[profiler] = prof 326 } 327 328 w.(http.Flusher).Flush() 329 } 330 331 // DownloadProfilingDataHandler - returns profiled data. 332 func (s *peerRESTServer) DownloadProfilingDataHandler(w http.ResponseWriter, r *http.Request) { 333 if !s.IsValid(w, r) { 334 s.WriteErrorResponse(w, errors.New("Invalid request")) 335 return 336 } 337 338 ctx := NewContext(r, w, "DownloadProfiling") 339 profileData, err := getProfileData() 340 if err != nil { 341 s.WriteErrorResponse(w, err) 342 return 343 } 344 345 defer w.(http.Flusher).Flush() 346 logger.LogIf(ctx, gob.NewEncoder(w).Encode(profileData)) 347 } 348 349 // ServerInfoHandler - returns Server Info 350 func (s *peerRESTServer) ServerInfoHandler(w http.ResponseWriter, r *http.Request) { 351 if !s.IsValid(w, r) { 352 s.WriteErrorResponse(w, errors.New("Invalid request")) 353 return 354 } 355 356 ctx := NewContext(r, w, "ServerInfo") 357 info := getLocalServerProperty(globalEndpoints, r) 358 359 defer w.(http.Flusher).Flush() 360 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 361 } 362 363 func (s *peerRESTServer) NetInfoHandler(w http.ResponseWriter, r *http.Request) { 364 ctx := NewContext(r, w, "NetInfo") 365 if !s.IsValid(w, r) { 366 s.WriteErrorResponse(w, errors.New("Invalid request")) 367 return 368 } 369 370 // Use this trailer to send additional headers after sending body 371 w.Header().Set("Trailer", "FinalStatus") 372 373 w.Header().Set("Content-Type", "application/octet-stream") 374 w.WriteHeader(http.StatusOK) 375 376 n, err := io.Copy(ioutil.Discard, r.Body) 377 if err == io.ErrUnexpectedEOF { 378 w.Header().Set("FinalStatus", err.Error()) 379 return 380 } 381 if err != nil && err != io.EOF { 382 logger.LogIf(ctx, err) 383 w.Header().Set("FinalStatus", err.Error()) 384 return 385 } 386 if n != r.ContentLength { 387 err := fmt.Errorf("Subnet health: short read: expected %d found %d", r.ContentLength, n) 388 389 logger.LogIf(ctx, err) 390 w.Header().Set("FinalStatus", err.Error()) 391 return 392 } 393 w.Header().Set("FinalStatus", "Success") 394 w.(http.Flusher).Flush() 395 } 396 397 func (s *peerRESTServer) DispatchNetInfoHandler(w http.ResponseWriter, r *http.Request) { 398 if !s.IsValid(w, r) { 399 s.WriteErrorResponse(w, errors.New("Invalid request")) 400 return 401 } 402 403 done := keepHTTPResponseAlive(w) 404 405 ctx := NewContext(r, w, "DispatchNetInfo") 406 info := GlobalNotificationSys.NetInfo(ctx) 407 408 done(nil) 409 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 410 w.(http.Flusher).Flush() 411 } 412 413 // DriveInfoHandler - returns Drive info. 414 func (s *peerRESTServer) DriveInfoHandler(w http.ResponseWriter, r *http.Request) { 415 if !s.IsValid(w, r) { 416 s.WriteErrorResponse(w, errors.New("Invalid request")) 417 return 418 } 419 420 ctx, cancel := context.WithCancel(NewContext(r, w, "DriveInfo")) 421 defer cancel() 422 infoSerial := getLocalDrives(ctx, false, globalEndpoints, r) 423 infoParallel := getLocalDrives(ctx, true, globalEndpoints, r) 424 425 errStr := "" 426 if infoSerial.Error != "" { 427 errStr = "serial: " + infoSerial.Error 428 } 429 if infoParallel.Error != "" { 430 errStr = errStr + " parallel: " + infoParallel.Error 431 } 432 info := madmin.ServerDrivesInfo{ 433 Addr: infoSerial.Addr, 434 Serial: infoSerial.Serial, 435 Parallel: infoParallel.Parallel, 436 Error: errStr, 437 } 438 defer w.(http.Flusher).Flush() 439 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 440 } 441 442 // CPUInfoHandler - returns CPU info. 443 func (s *peerRESTServer) CPUInfoHandler(w http.ResponseWriter, r *http.Request) { 444 if !s.IsValid(w, r) { 445 s.WriteErrorResponse(w, errors.New("Invalid request")) 446 return 447 } 448 449 ctx, cancel := context.WithCancel(r.Context()) 450 defer cancel() 451 452 info := getLocalCPUInfo(ctx, r) 453 454 defer w.(http.Flusher).Flush() 455 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 456 } 457 458 // DiskHwInfoHandler - returns Disk HW info. 459 func (s *peerRESTServer) DiskHwInfoHandler(w http.ResponseWriter, r *http.Request) { 460 if !s.IsValid(w, r) { 461 s.WriteErrorResponse(w, errors.New("Invalid request")) 462 return 463 } 464 465 ctx, cancel := context.WithCancel(r.Context()) 466 defer cancel() 467 468 info := getLocalDiskHwInfo(ctx, r) 469 470 defer w.(http.Flusher).Flush() 471 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 472 } 473 474 // OsInfoHandler - returns Os info. 475 func (s *peerRESTServer) OsInfoHandler(w http.ResponseWriter, r *http.Request) { 476 if !s.IsValid(w, r) { 477 s.WriteErrorResponse(w, errors.New("Invalid request")) 478 return 479 } 480 481 ctx, cancel := context.WithCancel(r.Context()) 482 defer cancel() 483 484 info := getLocalOsInfo(ctx, r) 485 486 defer w.(http.Flusher).Flush() 487 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 488 } 489 490 // ProcInfoHandler - returns Proc info. 491 func (s *peerRESTServer) ProcInfoHandler(w http.ResponseWriter, r *http.Request) { 492 if !s.IsValid(w, r) { 493 s.WriteErrorResponse(w, errors.New("Invalid request")) 494 return 495 } 496 497 ctx, cancel := context.WithCancel(r.Context()) 498 defer cancel() 499 500 info := getLocalProcInfo(ctx, r) 501 502 defer w.(http.Flusher).Flush() 503 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 504 } 505 506 // MemInfoHandler - returns Memory info. 507 func (s *peerRESTServer) MemInfoHandler(w http.ResponseWriter, r *http.Request) { 508 if !s.IsValid(w, r) { 509 s.WriteErrorResponse(w, errors.New("Invalid request")) 510 return 511 } 512 513 ctx, cancel := context.WithCancel(r.Context()) 514 defer cancel() 515 516 info := getLocalMemInfo(ctx, r) 517 518 defer w.(http.Flusher).Flush() 519 logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) 520 } 521 522 // DeleteBucketMetadataHandler - Delete in memory bucket metadata 523 func (s *peerRESTServer) DeleteBucketMetadataHandler(w http.ResponseWriter, r *http.Request) { 524 if !s.IsValid(w, r) { 525 s.WriteErrorResponse(w, errors.New("Invalid request")) 526 return 527 } 528 529 vars := mux.Vars(r) 530 bucketName := vars[peerRESTBucket] 531 if bucketName == "" { 532 s.WriteErrorResponse(w, errors.New("Bucket name is missing")) 533 return 534 } 535 536 globalReplicationStats.Delete(bucketName) 537 globalBucketMetadataSys.Remove(bucketName) 538 if localMetacacheMgr != nil { 539 localMetacacheMgr.deleteBucketCache(bucketName) 540 } 541 } 542 543 // GetBucketStatsHandler - fetches current in-memory bucket stats, currently only 544 // returns BucketReplicationStatus 545 func (s *peerRESTServer) GetBucketStatsHandler(w http.ResponseWriter, r *http.Request) { 546 if !s.IsValid(w, r) { 547 s.WriteErrorResponse(w, errors.New("Invalid request")) 548 return 549 } 550 551 vars := mux.Vars(r) 552 bucketName := vars[peerRESTBucket] 553 if bucketName == "" { 554 s.WriteErrorResponse(w, errors.New("Bucket name is missing")) 555 return 556 } 557 558 bs := BucketStats{ 559 ReplicationStats: globalReplicationStats.Get(bucketName), 560 } 561 defer w.(http.Flusher).Flush() 562 logger.LogIf(r.Context(), msgp.Encode(w, &bs)) 563 } 564 565 // LoadBucketMetadataHandler - reloads in memory bucket metadata 566 func (s *peerRESTServer) LoadBucketMetadataHandler(w http.ResponseWriter, r *http.Request) { 567 if !s.IsValid(w, r) { 568 s.WriteErrorResponse(w, errors.New("Invalid request")) 569 return 570 } 571 572 vars := mux.Vars(r) 573 bucketName := vars[peerRESTBucket] 574 if bucketName == "" { 575 s.WriteErrorResponse(w, errors.New("Bucket name is missing")) 576 return 577 } 578 579 objAPI := newObjectLayerFn() 580 if objAPI == nil { 581 s.WriteErrorResponse(w, errServerNotInitialized) 582 return 583 } 584 585 meta, err := loadBucketMetadata(r.Context(), objAPI, bucketName) 586 if err != nil { 587 s.WriteErrorResponse(w, err) 588 return 589 } 590 591 globalBucketMetadataSys.Set(bucketName, meta) 592 593 if meta.notificationConfig != nil { 594 GlobalNotificationSys.AddRulesMap(bucketName, meta.notificationConfig.ToRulesMap()) 595 } 596 597 if meta.bucketTargetConfig != nil { 598 globalBucketTargetSys.UpdateAllTargets(bucketName, meta.bucketTargetConfig) 599 } 600 } 601 602 // CycleServerBloomFilterHandler cycles bloom filter on server. 603 func (s *peerRESTServer) CycleServerBloomFilterHandler(w http.ResponseWriter, r *http.Request) { 604 if !s.IsValid(w, r) { 605 s.WriteErrorResponse(w, errors.New("Invalid request")) 606 return 607 } 608 609 ctx := NewContext(r, w, "CycleServerBloomFilter") 610 611 var req bloomFilterRequest 612 err := gob.NewDecoder(r.Body).Decode(&req) 613 if err != nil { 614 s.WriteErrorResponse(w, err) 615 return 616 } 617 bf, err := intDataUpdateTracker.cycleFilter(ctx, req) 618 if err != nil { 619 s.WriteErrorResponse(w, err) 620 return 621 } 622 623 logger.LogIf(ctx, gob.NewEncoder(w).Encode(bf)) 624 } 625 626 func (s *peerRESTServer) GetMetacacheListingHandler(w http.ResponseWriter, r *http.Request) { 627 if !s.IsValid(w, r) { 628 s.WriteErrorResponse(w, errors.New("Invalid request")) 629 return 630 } 631 ctx := NewContext(r, w, "GetMetacacheListing") 632 633 var opts listPathOptions 634 err := gob.NewDecoder(r.Body).Decode(&opts) 635 if err != nil && err != io.EOF { 636 s.WriteErrorResponse(w, err) 637 return 638 } 639 resp := localMetacacheMgr.getBucket(ctx, opts.Bucket).findCache(opts) 640 logger.LogIf(ctx, msgp.Encode(w, &resp)) 641 } 642 643 func (s *peerRESTServer) UpdateMetacacheListingHandler(w http.ResponseWriter, r *http.Request) { 644 if !s.IsValid(w, r) { 645 s.WriteErrorResponse(w, errors.New("Invalid request")) 646 return 647 } 648 ctx := NewContext(r, w, "UpdateMetacacheListing") 649 650 var req metacache 651 err := msgp.Decode(r.Body, &req) 652 if err != nil { 653 s.WriteErrorResponse(w, err) 654 return 655 } 656 cache, err := localMetacacheMgr.updateCacheEntry(req) 657 if err != nil { 658 s.WriteErrorResponse(w, err) 659 return 660 } 661 // Return updated metadata. 662 logger.LogIf(ctx, msgp.Encode(w, &cache)) 663 } 664 665 // PutBucketNotificationHandler - Set bucket policy. 666 func (s *peerRESTServer) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { 667 if !s.IsValid(w, r) { 668 s.WriteErrorResponse(w, errors.New("Invalid request")) 669 return 670 } 671 672 vars := mux.Vars(r) 673 bucketName := vars[peerRESTBucket] 674 if bucketName == "" { 675 s.WriteErrorResponse(w, errors.New("Bucket name is missing")) 676 return 677 } 678 679 var rulesMap event.RulesMap 680 if r.ContentLength < 0 { 681 s.WriteErrorResponse(w, errInvalidArgument) 682 return 683 } 684 685 err := gob.NewDecoder(r.Body).Decode(&rulesMap) 686 if err != nil { 687 s.WriteErrorResponse(w, err) 688 return 689 } 690 691 GlobalNotificationSys.AddRulesMap(bucketName, rulesMap) 692 w.(http.Flusher).Flush() 693 } 694 695 // Return disk IDs of all the local disks. 696 func getLocalDiskIDs(z *erasureServerPools) []string { 697 var ids []string 698 699 for poolIdx := range z.serverPools { 700 for _, set := range z.serverPools[poolIdx].sets { 701 disks := set.getDisks() 702 for _, disk := range disks { 703 if disk == nil { 704 continue 705 } 706 if disk.IsLocal() { 707 id, err := disk.GetDiskID() 708 if err != nil { 709 continue 710 } 711 if id == "" { 712 continue 713 } 714 ids = append(ids, id) 715 } 716 } 717 } 718 } 719 720 return ids 721 } 722 723 // HealthHandler - returns true of health 724 func (s *peerRESTServer) HealthHandler(w http.ResponseWriter, r *http.Request) { 725 s.IsValid(w, r) 726 } 727 728 // GetLocalDiskIDs - Return disk IDs of all the local disks. 729 func (s *peerRESTServer) GetLocalDiskIDs(w http.ResponseWriter, r *http.Request) { 730 if !s.IsValid(w, r) { 731 s.WriteErrorResponse(w, errors.New("Invalid request")) 732 return 733 } 734 735 ctx := NewContext(r, w, "GetLocalDiskIDs") 736 737 objLayer := newObjectLayerFn() 738 739 // Service not initialized yet 740 if objLayer == nil { 741 s.WriteErrorResponse(w, errServerNotInitialized) 742 return 743 } 744 745 z, ok := objLayer.(*erasureServerPools) 746 if !ok { 747 s.WriteErrorResponse(w, errServerNotInitialized) 748 return 749 } 750 751 ids := getLocalDiskIDs(z) 752 logger.LogIf(ctx, gob.NewEncoder(w).Encode(ids)) 753 w.(http.Flusher).Flush() 754 } 755 756 // ServerUpdateHandler - updates the current server. 757 func (s *peerRESTServer) ServerUpdateHandler(w http.ResponseWriter, r *http.Request) { 758 if !s.IsValid(w, r) { 759 s.WriteErrorResponse(w, errors.New("Invalid request")) 760 return 761 } 762 763 if r.ContentLength < 0 { 764 s.WriteErrorResponse(w, errInvalidArgument) 765 return 766 } 767 768 var info serverUpdateInfo 769 err := gob.NewDecoder(r.Body).Decode(&info) 770 if err != nil { 771 s.WriteErrorResponse(w, err) 772 return 773 } 774 775 if _, err = updateServer(info.URL, info.Sha256Sum, info.Time, info.ReleaseInfo, getMinioMode()); err != nil { 776 s.WriteErrorResponse(w, err) 777 return 778 } 779 } 780 781 var errUnsupportedSignal = fmt.Errorf("unsupported signal: only restart and stop signals are supported") 782 783 // SignalServiceHandler - signal service handler. 784 func (s *peerRESTServer) SignalServiceHandler(w http.ResponseWriter, r *http.Request) { 785 if !s.IsValid(w, r) { 786 s.WriteErrorResponse(w, errors.New("Invalid request")) 787 return 788 } 789 790 vars := mux.Vars(r) 791 signalString := vars[peerRESTSignal] 792 if signalString == "" { 793 s.WriteErrorResponse(w, errors.New("signal name is missing")) 794 return 795 } 796 si, err := strconv.Atoi(signalString) 797 if err != nil { 798 s.WriteErrorResponse(w, err) 799 return 800 } 801 signal := serviceSignal(si) 802 defer w.(http.Flusher).Flush() 803 switch signal { 804 case serviceRestart: 805 globalServiceSignalCh <- signal 806 case serviceStop: 807 globalServiceSignalCh <- signal 808 case serviceReloadDynamic: 809 objAPI := newObjectLayerFn() 810 if objAPI == nil { 811 s.WriteErrorResponse(w, errServerNotInitialized) 812 return 813 } 814 srvCfg, err := getValidConfig(objAPI) 815 if err != nil { 816 s.WriteErrorResponse(w, err) 817 return 818 } 819 if err = applyDynamicConfig(r.Context(), objAPI, srvCfg); err != nil { 820 s.WriteErrorResponse(w, err) 821 } 822 return 823 default: 824 s.WriteErrorResponse(w, errUnsupportedSignal) 825 return 826 } 827 } 828 829 // ListenHandler sends http trace messages back to peer rest client 830 func (s *peerRESTServer) ListenHandler(w http.ResponseWriter, r *http.Request) { 831 if !s.IsValid(w, r) { 832 s.WriteErrorResponse(w, errors.New("invalid request")) 833 return 834 } 835 836 values := r.URL.Query() 837 838 var prefix string 839 if len(values[peerRESTListenPrefix]) > 1 { 840 s.WriteErrorResponse(w, errors.New("invalid request")) 841 return 842 } 843 844 if len(values[peerRESTListenPrefix]) == 1 { 845 if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil { 846 s.WriteErrorResponse(w, err) 847 return 848 } 849 850 prefix = values[peerRESTListenPrefix][0] 851 } 852 853 var suffix string 854 if len(values[peerRESTListenSuffix]) > 1 { 855 s.WriteErrorResponse(w, errors.New("invalid request")) 856 return 857 } 858 859 if len(values[peerRESTListenSuffix]) == 1 { 860 if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil { 861 s.WriteErrorResponse(w, err) 862 return 863 } 864 865 suffix = values[peerRESTListenSuffix][0] 866 } 867 868 pattern := event.NewPattern(prefix, suffix) 869 870 var eventNames []event.Name 871 for _, ev := range values[peerRESTListenEvents] { 872 eventName, err := event.ParseName(ev) 873 if err != nil { 874 s.WriteErrorResponse(w, err) 875 return 876 } 877 878 eventNames = append(eventNames, eventName) 879 } 880 881 rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()}) 882 883 w.WriteHeader(http.StatusOK) 884 w.(http.Flusher).Flush() 885 886 doneCh := make(chan struct{}) 887 defer close(doneCh) 888 889 // Listen Publisher uses nonblocking publish and hence does not wait for slow subscribers. 890 // Use buffered channel to take care of burst sends or slow w.Write() 891 ch := make(chan interface{}, 2000) 892 893 globalHTTPListen.Subscribe(ch, doneCh, func(evI interface{}) bool { 894 ev, ok := evI.(event.Event) 895 if !ok { 896 return false 897 } 898 if ev.S3.Bucket.Name != "" && values.Get(peerRESTListenBucket) != "" { 899 if ev.S3.Bucket.Name != values.Get(peerRESTListenBucket) { 900 return false 901 } 902 } 903 return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key) 904 }) 905 906 keepAliveTicker := time.NewTicker(500 * time.Millisecond) 907 defer keepAliveTicker.Stop() 908 909 enc := gob.NewEncoder(w) 910 for { 911 select { 912 case ev := <-ch: 913 if err := enc.Encode(ev); err != nil { 914 return 915 } 916 w.(http.Flusher).Flush() 917 case <-keepAliveTicker.C: 918 if err := enc.Encode(&event.Event{}); err != nil { 919 return 920 } 921 w.(http.Flusher).Flush() 922 } 923 } 924 } 925 926 func extractTraceOptsFromPeerRequest(r *http.Request) (opts madmin.ServiceTraceOpts, err error) { 927 928 q := r.URL.Query() 929 opts.OnlyErrors = q.Get(peerRESTTraceErr) == "true" 930 opts.Storage = q.Get(peerRESTTraceStorage) == "true" 931 opts.Internal = q.Get(peerRESTTraceInternal) == "true" 932 opts.S3 = q.Get(peerRESTTraceS3) == "true" 933 opts.OS = q.Get(peerRESTTraceOS) == "true" 934 935 if t := q.Get(peerRESTTraceThreshold); t != "" { 936 d, err := time.ParseDuration(t) 937 if err != nil { 938 return opts, err 939 } 940 opts.Threshold = d 941 } 942 return 943 } 944 945 // TraceHandler sends http trace messages back to peer rest client 946 func (s *peerRESTServer) TraceHandler(w http.ResponseWriter, r *http.Request) { 947 if !s.IsValid(w, r) { 948 s.WriteErrorResponse(w, errors.New("Invalid request")) 949 return 950 } 951 952 traceOpts, err := extractTraceOptsFromPeerRequest(r) 953 if err != nil { 954 s.WriteErrorResponse(w, errors.New("Invalid request")) 955 return 956 } 957 958 w.WriteHeader(http.StatusOK) 959 w.(http.Flusher).Flush() 960 961 doneCh := make(chan struct{}) 962 defer close(doneCh) 963 964 // Trace Publisher uses nonblocking publish and hence does not wait for slow subscribers. 965 // Use buffered channel to take care of burst sends or slow w.Write() 966 ch := make(chan interface{}, 2000) 967 968 globalTrace.Subscribe(ch, doneCh, func(entry interface{}) bool { 969 return mustTrace(entry, traceOpts) 970 }) 971 972 keepAliveTicker := time.NewTicker(500 * time.Millisecond) 973 defer keepAliveTicker.Stop() 974 975 enc := gob.NewEncoder(w) 976 for { 977 select { 978 case entry := <-ch: 979 if err := enc.Encode(entry); err != nil { 980 return 981 } 982 w.(http.Flusher).Flush() 983 case <-keepAliveTicker.C: 984 if err := enc.Encode(&trace.Info{}); err != nil { 985 return 986 } 987 w.(http.Flusher).Flush() 988 } 989 } 990 } 991 992 func (s *peerRESTServer) BackgroundHealStatusHandler(w http.ResponseWriter, r *http.Request) { 993 if !s.IsValid(w, r) { 994 s.WriteErrorResponse(w, errors.New("invalid request")) 995 return 996 } 997 ctx := NewContext(r, w, "BackgroundHealStatus") 998 999 state, ok := getBackgroundHealStatus(ctx, newObjectLayerFn()) 1000 if !ok { 1001 s.WriteErrorResponse(w, errServerNotInitialized) 1002 return 1003 } 1004 1005 defer w.(http.Flusher).Flush() 1006 logger.LogIf(ctx, gob.NewEncoder(w).Encode(state)) 1007 } 1008 1009 // ConsoleLogHandler sends console logs of this node back to peer rest client 1010 func (s *peerRESTServer) ConsoleLogHandler(w http.ResponseWriter, r *http.Request) { 1011 if !s.IsValid(w, r) { 1012 s.WriteErrorResponse(w, errors.New("Invalid request")) 1013 return 1014 } 1015 1016 w.Header().Set("Connection", "close") 1017 w.WriteHeader(http.StatusOK) 1018 w.(http.Flusher).Flush() 1019 1020 doneCh := make(chan struct{}) 1021 defer close(doneCh) 1022 1023 ch := make(chan interface{}, 2000) 1024 globalConsoleSys.Subscribe(ch, doneCh, "", 0, string(logger.All), nil) 1025 1026 enc := gob.NewEncoder(w) 1027 for { 1028 select { 1029 case entry := <-ch: 1030 if err := enc.Encode(entry); err != nil { 1031 return 1032 } 1033 w.(http.Flusher).Flush() 1034 case <-r.Context().Done(): 1035 return 1036 } 1037 } 1038 } 1039 1040 func (s *peerRESTServer) WriteErrorResponse(w http.ResponseWriter, err error) { 1041 w.WriteHeader(http.StatusForbidden) 1042 w.Write([]byte(err.Error())) 1043 } 1044 1045 // IsValid - To authenticate and verify the time difference. 1046 func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool { 1047 if err := storageServerRequestValidate(r); err != nil { 1048 s.WriteErrorResponse(w, err) 1049 return false 1050 } 1051 return true 1052 } 1053 1054 // GetBandwidth gets the bandwidth for the buckets requested. 1055 func (s *peerRESTServer) GetBandwidth(w http.ResponseWriter, r *http.Request) { 1056 if !s.IsValid(w, r) { 1057 s.WriteErrorResponse(w, errors.New("invalid request")) 1058 return 1059 } 1060 bucketsString := r.URL.Query().Get("buckets") 1061 w.WriteHeader(http.StatusOK) 1062 w.(http.Flusher).Flush() 1063 1064 doneCh := make(chan struct{}) 1065 defer close(doneCh) 1066 1067 selectBuckets := b.SelectBuckets(strings.Split(bucketsString, ",")...) 1068 report := globalBucketMonitor.GetReport(selectBuckets) 1069 1070 enc := gob.NewEncoder(w) 1071 if err := enc.Encode(report); err != nil { 1072 s.WriteErrorResponse(w, errors.New("Encoding report failed: "+err.Error())) 1073 return 1074 } 1075 w.(http.Flusher).Flush() 1076 } 1077 1078 // GetPeerMetrics gets the metrics to be federated across peers. 1079 func (s *peerRESTServer) GetPeerMetrics(w http.ResponseWriter, r *http.Request) { 1080 if !s.IsValid(w, r) { 1081 s.WriteErrorResponse(w, errors.New("invalid request")) 1082 } 1083 w.WriteHeader(http.StatusOK) 1084 w.(http.Flusher).Flush() 1085 1086 doneCh := make(chan struct{}) 1087 defer close(doneCh) 1088 1089 enc := gob.NewEncoder(w) 1090 1091 ch := ReportMetrics(r.Context(), GetGeneratorsForPeer) 1092 for m := range ch { 1093 if err := enc.Encode(m); err != nil { 1094 s.WriteErrorResponse(w, errors.New("Encoding metric failed: "+err.Error())) 1095 return 1096 } 1097 } 1098 w.(http.Flusher).Flush() 1099 } 1100 1101 // registerPeerRESTHandlers - register peer rest router. 1102 func registerPeerRESTHandlers(router *mux.Router) { 1103 server := &peerRESTServer{} 1104 subrouter := router.PathPrefix(peerRESTPrefix).Subrouter() 1105 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHealth).HandlerFunc(HTTPTraceHdrs(server.HealthHandler)) 1106 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocks).HandlerFunc(HTTPTraceHdrs(server.GetLocksHandler)) 1107 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(HTTPTraceHdrs(server.ServerInfoHandler)) 1108 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodProcInfo).HandlerFunc(HTTPTraceHdrs(server.ProcInfoHandler)) 1109 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemInfo).HandlerFunc(HTTPTraceHdrs(server.MemInfoHandler)) 1110 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodOsInfo).HandlerFunc(HTTPTraceHdrs(server.OsInfoHandler)) 1111 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDiskHwInfo).HandlerFunc(HTTPTraceHdrs(server.DiskHwInfoHandler)) 1112 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCPUInfo).HandlerFunc(HTTPTraceHdrs(server.CPUInfoHandler)) 1113 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDriveInfo).HandlerFunc(HTTPTraceHdrs(server.DriveInfoHandler)) 1114 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodNetInfo).HandlerFunc(HTTPTraceHdrs(server.NetInfoHandler)) 1115 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDispatchNetInfo).HandlerFunc(HTTPTraceHdrs(server.DispatchNetInfoHandler)) 1116 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCycleBloom).HandlerFunc(HTTPTraceHdrs(server.CycleServerBloomFilterHandler)) 1117 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteBucketMetadata).HandlerFunc(HTTPTraceHdrs(server.DeleteBucketMetadataHandler)).Queries(restQueries(peerRESTBucket)...) 1118 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadBucketMetadata).HandlerFunc(HTTPTraceHdrs(server.LoadBucketMetadataHandler)).Queries(restQueries(peerRESTBucket)...) 1119 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetBucketStats).HandlerFunc(HTTPTraceHdrs(server.GetBucketStatsHandler)).Queries(restQueries(peerRESTBucket)...) 1120 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSignalService).HandlerFunc(HTTPTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...) 1121 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerUpdate).HandlerFunc(HTTPTraceHdrs(server.ServerUpdateHandler)) 1122 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeletePolicy).HandlerFunc(HTTPTraceAll(server.DeletePolicyHandler)).Queries(restQueries(peerRESTPolicy)...) 1123 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicy).HandlerFunc(HTTPTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) 1124 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicyMapping).HandlerFunc(HTTPTraceAll(server.LoadPolicyMappingHandler)).Queries(restQueries(peerRESTUserOrGroup)...) 1125 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteUser).HandlerFunc(HTTPTraceAll(server.DeleteUserHandler)).Queries(restQueries(peerRESTUser)...) 1126 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteServiceAccount).HandlerFunc(HTTPTraceAll(server.DeleteServiceAccountHandler)).Queries(restQueries(peerRESTUser)...) 1127 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadUser).HandlerFunc(HTTPTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...) 1128 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadServiceAccount).HandlerFunc(HTTPTraceAll(server.LoadServiceAccountHandler)).Queries(restQueries(peerRESTUser)...) 1129 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadGroup).HandlerFunc(HTTPTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...) 1130 1131 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodStartProfiling).HandlerFunc(HTTPTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...) 1132 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDownloadProfilingData).HandlerFunc(HTTPTraceHdrs(server.DownloadProfilingDataHandler)) 1133 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodTrace).HandlerFunc(server.TraceHandler) 1134 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodListen).HandlerFunc(HTTPTraceHdrs(server.ListenHandler)) 1135 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler) 1136 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLog).HandlerFunc(server.ConsoleLogHandler) 1137 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocalDiskIDs).HandlerFunc(HTTPTraceHdrs(server.GetLocalDiskIDs)) 1138 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetBandwidth).HandlerFunc(HTTPTraceHdrs(server.GetBandwidth)) 1139 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetMetacacheListing).HandlerFunc(HTTPTraceHdrs(server.GetMetacacheListingHandler)) 1140 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodUpdateMetacacheListing).HandlerFunc(HTTPTraceHdrs(server.UpdateMetacacheListingHandler)) 1141 subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetPeerMetrics).HandlerFunc(HTTPTraceHdrs(server.GetPeerMetrics)) 1142 }