| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"encoding/gob" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2019-08-19 10:56:32 +08:00
										 |  |  | 	"io" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 22:36:34 +08:00
										 |  |  | 	"github.com/dustin/go-humanize" | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	"github.com/google/uuid" | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	"github.com/gorilla/mux" | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	"github.com/minio/madmin-go" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	b "github.com/minio/minio/internal/bucket/bandwidth" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/event" | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	"github.com/minio/minio/internal/hash" | 
					
						
							| 
									
										
										
										
											2021-11-30 01:05:46 +08:00
										 |  |  | 	xhttp "github.com/minio/minio/internal/http" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2021-11-20 02:41:37 +08:00
										 |  |  | 	"github.com/minio/pkg/randreader" | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	"github.com/tinylib/msgp/msgp" | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // To abstract a node over network.
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | type peerRESTServer struct{} | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetLocksHandler - returns list of older lock from the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetLocksHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetLocks") | 
					
						
							| 
									
										
										
										
											2020-12-10 23:28:37 +08:00
										 |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(globalLockServer.DupLockMap())) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // DeletePolicyHandler - deletes a policy on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) DeletePolicyHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars[peerRESTPolicy] | 
					
						
							|  |  |  | 	if policyName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("policyName is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-30 06:38:57 +08:00
										 |  |  | 	if err := globalIAMSys.DeletePolicy(r.Context(), policyName, false); err != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadPolicyHandler - reloads a policy on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars[peerRESTPolicy] | 
					
						
							|  |  |  | 	if policyName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("policyName is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.LoadPolicy(r.Context(), objAPI, policyName); err != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | // LoadPolicyMappingHandler - reloads a policy mapping on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	userOrGroup := vars[peerRESTUserOrGroup] | 
					
						
							|  |  |  | 	if userOrGroup == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("user-or-group is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	_, isGroup := r.Form[peerRESTIsGroup] | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.LoadPolicyMapping(r.Context(), objAPI, userOrGroup, isGroup); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | // DeleteServiceAccountHandler - deletes a service account on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) DeleteServiceAccountHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars[peerRESTUser] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("service account name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-21 18:16:50 +08:00
										 |  |  | 	if err := globalIAMSys.DeleteServiceAccount(r.Context(), accessKey, false); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadServiceAccountHandler - reloads a service account on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadServiceAccountHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars[peerRESTUser] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("service account parameter is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.LoadServiceAccount(r.Context(), accessKey); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // DeleteUserHandler - deletes a user on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars[peerRESTUser] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("username is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-21 18:16:50 +08:00
										 |  |  | 	if err := globalIAMSys.DeleteUser(r.Context(), accessKey, false); err != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadUserHandler - reloads a user on the server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadUserHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars[peerRESTUser] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("username is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	temp, err := strconv.ParseBool(vars[peerRESTUserTemp]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	userType := regUser | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if temp { | 
					
						
							|  |  |  | 		userType = stsUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err = globalIAMSys.LoadUser(r.Context(), objAPI, accessKey, userType); err != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // LoadGroupHandler - reloads group along with members list.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadGroupHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	group := vars[peerRESTGroup] | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	err := globalIAMSys.LoadGroup(r.Context(), objAPI, group) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | // StartProfilingHandler - Issues the start profiling command.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) StartProfilingHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	profiles := strings.Split(vars[peerRESTProfiler], ",") | 
					
						
							|  |  |  | 	if len(profiles) == 0 { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		s.writeErrorResponse(w, errors.New("profiler name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	globalProfilerMu.Lock() | 
					
						
							|  |  |  | 	defer globalProfilerMu.Unlock() | 
					
						
							|  |  |  | 	if globalProfiler == nil { | 
					
						
							|  |  |  | 		globalProfiler = make(map[string]minioProfiler, 10) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	// Stop profiler of all types if already running
 | 
					
						
							|  |  |  | 	for k, v := range globalProfiler { | 
					
						
							|  |  |  | 		for _, p := range profiles { | 
					
						
							|  |  |  | 			if p == k { | 
					
						
							|  |  |  | 				v.Stop() | 
					
						
							|  |  |  | 				delete(globalProfiler, k) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	for _, profiler := range profiles { | 
					
						
							|  |  |  | 		prof, err := startProfiler(profiler) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		globalProfiler[profiler] = prof | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | // DownloadProfilingDataHandler - returns profiled data.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) DownloadProfilingDataHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "DownloadProfiling") | 
					
						
							|  |  |  | 	profileData, err := getProfileData() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(profileData)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-12 06:27:03 +08:00
										 |  |  | // ServerInfoHandler - returns Server Info
 | 
					
						
							|  |  |  | func (s *peerRESTServer) ServerInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ServerInfo") | 
					
						
							|  |  |  | 	info := getLocalServerProperty(globalEndpoints, r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | func (s *peerRESTServer) NetInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "NetInfo") | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Use this trailer to send additional headers after sending body
 | 
					
						
							|  |  |  | 	w.Header().Set("Trailer", "FinalStatus") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w.Header().Set("Content-Type", "application/octet-stream") | 
					
						
							|  |  |  | 	w.WriteHeader(http.StatusOK) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n, err := io.Copy(ioutil.Discard, r.Body) | 
					
						
							|  |  |  | 	if err == io.ErrUnexpectedEOF { | 
					
						
							|  |  |  | 		w.Header().Set("FinalStatus", err.Error()) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil && err != io.EOF { | 
					
						
							|  |  |  | 		logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		w.Header().Set("FinalStatus", err.Error()) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if n != r.ContentLength { | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | 		err := fmt.Errorf("Subnet health: short read: expected %d found %d", r.ContentLength, n) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 		logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		w.Header().Set("FinalStatus", err.Error()) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	w.Header().Set("FinalStatus", "Success") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | func (s *peerRESTServer) DispatchNetInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-19 02:06:11 +08:00
										 |  |  | 	done := keepHTTPResponseAlive(w) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | 	ctx := newContext(r, w, "DispatchNetInfo") | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := globalNotificationSys.GetNetPerfInfo(ctx) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 11:41:38 +08:00
										 |  |  | 	done(nil) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetDrivePerfInfosHandler - returns all disk's serial/parallal performance information.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetDrivePerfInfosHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(newContext(r, w, "DriveInfo")) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := getDrivePerfInfos(ctx, r.Host) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetCPUsHandler - returns CPU info.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetCPUsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := madmin.GetCPUs(ctx, r.Host) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetPartitionsHandler - returns disk partition information.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetPartitionsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := madmin.GetPartitions(ctx, r.Host) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetOSInfoHandler - returns operating system's information.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetOSInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := madmin.GetOSInfo(ctx, r.Host) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetProcInfoHandler - returns this MinIO process information.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetProcInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := madmin.GetProcInfo(ctx, r.Host) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | // GetMemInfoHandler - returns memory information.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetMemInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2020-05-19 00:59:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	info := madmin.GetMemInfo(ctx, r.Host) | 
					
						
							| 
									
										
										
										
											2020-03-27 12:07:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 08:09:37 +08:00
										 |  |  | // GetSysConfigHandler - returns system config information.
 | 
					
						
							|  |  |  | // (only the config that are of concern to minio)
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetSysConfigHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	info := madmin.GetSysConfig(ctx, r.Host) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | // GetSysServicesHandler - returns system services information.
 | 
					
						
							|  |  |  | // (only the services that are of concern to minio)
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetSysServicesHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	info := madmin.GetSysServices(ctx, r.Host) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetSysErrorsHandler - returns system level errors
 | 
					
						
							| 
									
										
										
										
											2021-07-30 14:05:34 +08:00
										 |  |  | func (s *peerRESTServer) GetSysErrorsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx, cancel := context.WithCancel(r.Context()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	info := madmin.GetSysErrors(ctx, r.Host) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // DeleteBucketMetadataHandler - Delete in memory bucket metadata
 | 
					
						
							|  |  |  | func (s *peerRESTServer) DeleteBucketMetadataHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucketName := vars[peerRESTBucket] | 
					
						
							|  |  |  | 	if bucketName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Bucket name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	globalReplicationStats.Delete(bucketName) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	globalBucketMetadataSys.Remove(bucketName) | 
					
						
							| 
									
										
										
										
											2021-06-24 23:39:58 +08:00
										 |  |  | 	globalBucketTargetSys.Delete(bucketName) | 
					
						
							| 
									
										
										
										
											2020-11-01 00:46:18 +08:00
										 |  |  | 	if localMetacacheMgr != nil { | 
					
						
							|  |  |  | 		localMetacacheMgr.deleteBucketCache(bucketName) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | // ReloadSiteReplicationConfigHandler - reloads site replication configuration from the disks
 | 
					
						
							|  |  |  | func (s *peerRESTServer) ReloadSiteReplicationConfigHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "LoadSiteReplication") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(r.Context(), globalSiteReplicationSys.Init(ctx, objAPI)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | // GetBucketStatsHandler - fetches current in-memory bucket stats, currently only
 | 
					
						
							|  |  |  | // returns BucketReplicationStatus
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetBucketStatsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucketName := vars[peerRESTBucket] | 
					
						
							|  |  |  | 	if bucketName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Bucket name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bs := BucketStats{ | 
					
						
							|  |  |  | 		ReplicationStats: globalReplicationStats.Get(bucketName), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	logger.LogIf(r.Context(), msgp.Encode(w, &bs)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // LoadBucketMetadataHandler - reloads in memory bucket metadata
 | 
					
						
							|  |  |  | func (s *peerRESTServer) LoadBucketMetadataHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	bucketName := vars[peerRESTBucket] | 
					
						
							|  |  |  | 	if bucketName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Bucket name is missing")) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	meta, err := loadBucketMetadata(r.Context(), objAPI, bucketName) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	globalBucketMetadataSys.Set(bucketName, meta) | 
					
						
							| 
									
										
										
										
											2020-06-27 04:17:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if meta.notificationConfig != nil { | 
					
						
							|  |  |  | 		globalNotificationSys.AddRulesMap(bucketName, meta.notificationConfig.ToRulesMap()) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-07 08:10:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if meta.bucketTargetConfig != nil { | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | 		globalBucketTargetSys.UpdateAllTargets(bucketName, meta.bucketTargetConfig) | 
					
						
							| 
									
										
										
										
											2020-08-07 08:10:21 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | // CycleServerBloomFilterHandler cycles bloom filter on server.
 | 
					
						
							| 
									
										
										
										
											2020-04-28 01:06:21 +08:00
										 |  |  | func (s *peerRESTServer) CycleServerBloomFilterHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "CycleServerBloomFilter") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var req bloomFilterRequest | 
					
						
							|  |  |  | 	err := gob.NewDecoder(r.Body).Decode(&req) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	bf, err := intDataUpdateTracker.cycleFilter(ctx, req) | 
					
						
							| 
									
										
										
										
											2020-04-28 01:06:21 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-28 01:06:21 +08:00
										 |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(bf)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | func (s *peerRESTServer) GetMetacacheListingHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetMetacacheListing") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var opts listPathOptions | 
					
						
							|  |  |  | 	err := gob.NewDecoder(r.Body).Decode(&opts) | 
					
						
							|  |  |  | 	if err != nil && err != io.EOF { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	resp := localMetacacheMgr.getBucket(ctx, opts.Bucket).findCache(opts) | 
					
						
							|  |  |  | 	logger.LogIf(ctx, msgp.Encode(w, &resp)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *peerRESTServer) UpdateMetacacheListingHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "UpdateMetacacheListing") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var req metacache | 
					
						
							|  |  |  | 	err := msgp.Decode(r.Body, &req) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-04 04:47:52 +08:00
										 |  |  | 	cache, err := localMetacacheMgr.updateCacheEntry(req) | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Return updated metadata.
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, msgp.Encode(w, &cache)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | // PutBucketNotificationHandler - Set bucket policy.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucketName := vars[peerRESTBucket] | 
					
						
							|  |  |  | 	if bucketName == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Bucket name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var rulesMap event.RulesMap | 
					
						
							|  |  |  | 	if r.ContentLength < 0 { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errInvalidArgument) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := gob.NewDecoder(r.Body).Decode(&rulesMap) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	globalNotificationSys.AddRulesMap(bucketName, rulesMap) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | // Return disk IDs of all the local disks.
 | 
					
						
							| 
									
										
										
										
											2020-12-02 05:50:33 +08:00
										 |  |  | func getLocalDiskIDs(z *erasureServerPools) []string { | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | 	var ids []string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-07 01:35:47 +08:00
										 |  |  | 	for poolIdx := range z.serverPools { | 
					
						
							|  |  |  | 		for _, set := range z.serverPools[poolIdx].sets { | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | 			disks := set.getDisks() | 
					
						
							|  |  |  | 			for _, disk := range disks { | 
					
						
							|  |  |  | 				if disk == nil { | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if disk.IsLocal() { | 
					
						
							|  |  |  | 					id, err := disk.GetDiskID() | 
					
						
							|  |  |  | 					if err != nil { | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if id == "" { | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					ids = append(ids, id) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ids | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-18 05:49:26 +08:00
										 |  |  | // HealthHandler - returns true of health
 | 
					
						
							|  |  |  | func (s *peerRESTServer) HealthHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	s.IsValid(w, r) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | // GetLocalDiskIDs - Return disk IDs of all the local disks.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetLocalDiskIDs(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetLocalDiskIDs") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objLayer := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Service not initialized yet
 | 
					
						
							|  |  |  | 	if objLayer == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 05:50:33 +08:00
										 |  |  | 	z, ok := objLayer.(*erasureServerPools) | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | 	if !ok { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ids := getLocalDiskIDs(z) | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(ids)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | // ServerUpdateHandler - updates the current server.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) ServerUpdateHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 	if r.ContentLength < 0 { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errInvalidArgument) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var info serverUpdateInfo | 
					
						
							|  |  |  | 	err := gob.NewDecoder(r.Body).Decode(&info) | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-09 00:51:11 +08:00
										 |  |  | 	if _, err = updateServer(info.URL, info.Sha256Sum, info.Time, info.ReleaseInfo, getMinioMode()); err != nil { | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | var errUnsupportedSignal = fmt.Errorf("unsupported signal") | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // SignalServiceHandler - signal service handler.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) SignalServiceHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	signalString := vars[peerRESTSignal] | 
					
						
							|  |  |  | 	if signalString == "" { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("signal name is missing")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-28 02:37:47 +08:00
										 |  |  | 	si, err := strconv.Atoi(signalString) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	signal := serviceSignal(si) | 
					
						
							| 
									
										
										
										
											2019-08-29 06:04:43 +08:00
										 |  |  | 	switch signal { | 
					
						
							|  |  |  | 	case serviceRestart: | 
					
						
							|  |  |  | 		globalServiceSignalCh <- signal | 
					
						
							|  |  |  | 	case serviceStop: | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 		globalServiceSignalCh <- signal | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | 	case serviceFreeze: | 
					
						
							|  |  |  | 		freezeServices() | 
					
						
							|  |  |  | 	case serviceUnFreeze: | 
					
						
							|  |  |  | 		unfreezeServices() | 
					
						
							| 
									
										
										
										
											2020-12-05 01:32:35 +08:00
										 |  |  | 	case serviceReloadDynamic: | 
					
						
							| 
									
										
										
										
											2021-01-23 04:09:24 +08:00
										 |  |  | 		objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 		if objAPI == nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		srvCfg, err := getValidConfig(objAPI) | 
					
						
							| 
									
										
										
										
											2020-12-05 01:32:35 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-23 04:09:24 +08:00
										 |  |  | 		if err = applyDynamicConfig(r.Context(), objAPI, srvCfg); err != nil { | 
					
						
							| 
									
										
										
										
											2020-12-05 01:32:35 +08:00
										 |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errUnsupportedSignal) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 02:01:23 +08:00
										 |  |  | // ListenHandler sends http trace messages back to peer rest client
 | 
					
						
							|  |  |  | func (s *peerRESTServer) ListenHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							| 
									
										
										
										
											2019-12-13 02:01:23 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	values := r.Form | 
					
						
							| 
									
										
										
										
											2019-12-17 12:30:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var prefix string | 
					
						
							|  |  |  | 	if len(values[peerRESTListenPrefix]) > 1 { | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							| 
									
										
										
										
											2019-12-17 12:30:57 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(values[peerRESTListenPrefix]) == 1 { | 
					
						
							|  |  |  | 		if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		prefix = values[peerRESTListenPrefix][0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var suffix string | 
					
						
							|  |  |  | 	if len(values[peerRESTListenSuffix]) > 1 { | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							| 
									
										
										
										
											2019-12-17 12:30:57 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(values[peerRESTListenSuffix]) == 1 { | 
					
						
							|  |  |  | 		if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		suffix = values[peerRESTListenSuffix][0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pattern := event.NewPattern(prefix, suffix) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var eventNames []event.Name | 
					
						
							|  |  |  | 	for _, ev := range values[peerRESTListenEvents] { | 
					
						
							|  |  |  | 		eventName, err := event.ParseName(ev) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eventNames = append(eventNames, eventName) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 02:01:23 +08:00
										 |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Listen Publisher uses nonblocking publish and hence does not wait for slow subscribers.
 | 
					
						
							|  |  |  | 	// Use buffered channel to take care of burst sends or slow w.Write()
 | 
					
						
							|  |  |  | 	ch := make(chan interface{}, 2000) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 12:30:57 +08:00
										 |  |  | 	globalHTTPListen.Subscribe(ch, doneCh, func(evI interface{}) bool { | 
					
						
							|  |  |  | 		ev, ok := evI.(event.Event) | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-21 03:52:49 +08:00
										 |  |  | 		if ev.S3.Bucket.Name != "" && values.Get(peerRESTListenBucket) != "" { | 
					
						
							|  |  |  | 			if ev.S3.Bucket.Name != values.Get(peerRESTListenBucket) { | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-21 03:45:03 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-27 21:25:05 +08:00
										 |  |  | 		return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key) | 
					
						
							| 
									
										
										
										
											2019-12-13 02:01:23 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	keepAliveTicker := time.NewTicker(500 * time.Millisecond) | 
					
						
							|  |  |  | 	defer keepAliveTicker.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	enc := gob.NewEncoder(w) | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case ev := <-ch: | 
					
						
							|  |  |  | 			if err := enc.Encode(ev); err != nil { | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			w.(http.Flusher).Flush() | 
					
						
							|  |  |  | 		case <-keepAliveTicker.C: | 
					
						
							|  |  |  | 			if err := enc.Encode(&event.Event{}); err != nil { | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			w.(http.Flusher).Flush() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | func extractTraceOptsFromPeerRequest(r *http.Request) (opts madmin.ServiceTraceOpts, err error) { | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	opts.S3 = r.Form.Get(peerRESTTraceS3) == "true" | 
					
						
							|  |  |  | 	opts.OS = r.Form.Get(peerRESTTraceOS) == "true" | 
					
						
							|  |  |  | 	opts.Storage = r.Form.Get(peerRESTTraceStorage) == "true" | 
					
						
							|  |  |  | 	opts.Internal = r.Form.Get(peerRESTTraceInternal) == "true" | 
					
						
							|  |  |  | 	opts.OnlyErrors = r.Form.Get(peerRESTTraceErr) == "true" | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	if t := r.Form.Get(peerRESTTraceThreshold); t != "" { | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 		d, err := time.ParseDuration(t) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return opts, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		opts.Threshold = d | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 06:54:41 +08:00
										 |  |  | // TraceHandler sends http trace messages back to peer rest client
 | 
					
						
							|  |  |  | func (s *peerRESTServer) TraceHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	traceOpts, err := extractTraceOptsFromPeerRequest(r) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-09 06:54:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 13:41:12 +08:00
										 |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Trace Publisher uses nonblocking publish and hence does not wait for slow subscribers.
 | 
					
						
							|  |  |  | 	// Use buffered channel to take care of burst sends or slow w.Write()
 | 
					
						
							|  |  |  | 	ch := make(chan interface{}, 2000) | 
					
						
							| 
									
										
										
										
											2019-08-01 02:08:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 14:24:07 +08:00
										 |  |  | 	globalTrace.Subscribe(ch, doneCh, func(entry interface{}) bool { | 
					
						
							|  |  |  | 		return mustTrace(entry, traceOpts) | 
					
						
							| 
									
										
										
										
											2019-08-01 02:08:39 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	keepAliveTicker := time.NewTicker(500 * time.Millisecond) | 
					
						
							|  |  |  | 	defer keepAliveTicker.Stop() | 
					
						
							| 
									
										
										
										
											2019-06-27 13:41:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	enc := gob.NewEncoder(w) | 
					
						
							| 
									
										
										
										
											2019-06-09 06:54:41 +08:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case entry := <-ch: | 
					
						
							| 
									
										
										
										
											2019-06-27 13:41:12 +08:00
										 |  |  | 			if err := enc.Encode(entry); err != nil { | 
					
						
							| 
									
										
										
										
											2019-06-09 06:54:41 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			w.(http.Flusher).Flush() | 
					
						
							| 
									
										
										
										
											2019-08-01 02:08:39 +08:00
										 |  |  | 		case <-keepAliveTicker.C: | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 			if err := enc.Encode(&madmin.TraceInfo{}); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-01 02:08:39 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			w.(http.Flusher).Flush() | 
					
						
							| 
									
										
										
										
											2019-06-09 06:54:41 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | func (s *peerRESTServer) BackgroundHealStatusHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "BackgroundHealStatus") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-05 06:36:23 +08:00
										 |  |  | 	state, ok := getBackgroundHealStatus(ctx, newObjectLayerFn()) | 
					
						
							| 
									
										
										
										
											2020-08-08 10:43:06 +08:00
										 |  |  | 	if !ok { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-26 07:42:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(state)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | func (s *peerRESTServer) ReloadPoolMetaHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pools, ok := objAPI.(*erasureServerPools) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := pools.ReloadPoolMeta(r.Context()); err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | func (s *peerRESTServer) LoadTransitionTierConfigHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		err := globalTierConfigMgr.Reload(context.Background(), newObjectLayerFn()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.LogIf(context.Background(), fmt.Errorf("Failed to reload remote tier config %s", err)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 02:10:48 +08:00
										 |  |  | // ConsoleLogHandler sends console logs of this node back to peer rest client
 | 
					
						
							|  |  |  | func (s *peerRESTServer) ConsoleLogHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w.Header().Set("Connection", "close") | 
					
						
							|  |  |  | 	w.WriteHeader(http.StatusOK) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ch := make(chan interface{}, 2000) | 
					
						
							| 
									
										
										
										
											2019-10-12 09:50:54 +08:00
										 |  |  | 	globalConsoleSys.Subscribe(ch, doneCh, "", 0, string(logger.All), nil) | 
					
						
							| 
									
										
										
										
											2019-09-04 02:10:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	enc := gob.NewEncoder(w) | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case entry := <-ch: | 
					
						
							| 
									
										
										
										
											2019-09-22 16:24:32 +08:00
										 |  |  | 			if err := enc.Encode(entry); err != nil { | 
					
						
							| 
									
										
										
										
											2019-09-04 02:10:48 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			w.(http.Flusher).Flush() | 
					
						
							|  |  |  | 		case <-r.Context().Done(): | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | func (s *peerRESTServer) writeErrorResponse(w http.ResponseWriter, err error) { | 
					
						
							|  |  |  | 	w.WriteHeader(http.StatusForbidden) | 
					
						
							|  |  |  | 	w.Write([]byte(err.Error())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsValid - To authenticate and verify the time difference.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool { | 
					
						
							|  |  |  | 	if err := storageServerRequestValidate(r); err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, err) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | // GetBandwidth gets the bandwidth for the buckets requested.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetBandwidth(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bucketsString := r.Form.Get("buckets") | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 00:04:55 +08:00
										 |  |  | 	selectBuckets := b.SelectBuckets(strings.Split(bucketsString, ",")...) | 
					
						
							|  |  |  | 	report := globalBucketMonitor.GetReport(selectBuckets) | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	enc := gob.NewEncoder(w) | 
					
						
							|  |  |  | 	if err := enc.Encode(report); err != nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("Encoding report failed: "+err.Error())) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | // GetPeerMetrics gets the metrics to be federated across peers.
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetPeerMetrics(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	enc := gob.NewEncoder(w) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-18 02:11:04 +08:00
										 |  |  | 	ch := ReportMetrics(r.Context(), peerMetricsGroups) | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 	for m := range ch { | 
					
						
							|  |  |  | 		if err := enc.Encode(m); err != nil { | 
					
						
							|  |  |  | 			s.writeErrorResponse(w, errors.New("Encoding metric failed: "+err.Error())) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | // SpeedtestResult return value of the speedtest function
 | 
					
						
							|  |  |  | type SpeedtestResult struct { | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 	Endpoint  string | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	Uploads   uint64 | 
					
						
							|  |  |  | 	Downloads uint64 | 
					
						
							| 
									
										
										
										
											2021-09-01 05:08:23 +08:00
										 |  |  | 	Error     string | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 02:41:37 +08:00
										 |  |  | func newRandomReader(size int) io.Reader { | 
					
						
							|  |  |  | 	return io.LimitReader(randreader.New(), int64(size)) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Runs the speedtest on local MinIO process.
 | 
					
						
							| 
									
										
										
										
											2021-11-30 01:05:46 +08:00
										 |  |  | func selfSpeedtest(ctx context.Context, size, concurrent int, duration time.Duration, storageClass string) (SpeedtestResult, error) { | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 		return SpeedtestResult{}, errServerNotInitialized | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 	var errOnce sync.Once | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 	var retError string | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							|  |  |  | 	var totalBytesWritten uint64 | 
					
						
							|  |  |  | 	var totalBytesRead uint64 | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	objCountPerThread := make([]uint64, concurrent) | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 	uploadsCtx, uploadsCancel := context.WithCancel(context.Background()) | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 	defer uploadsCancel() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		time.Sleep(duration) | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 		uploadsCancel() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 00:13:03 +08:00
										 |  |  | 	objNamePrefix := "speedtest/objects/" + uuid.New().String() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	wg.Add(concurrent) | 
					
						
							|  |  |  | 	for i := 0; i < concurrent; i++ { | 
					
						
							|  |  |  | 		go func(i int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			for { | 
					
						
							| 
									
										
										
										
											2021-11-20 02:41:37 +08:00
										 |  |  | 				hashReader, err := hash.NewReader(newRandomReader(size), | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 					int64(size), "", "", int64(size)) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 					if !contextCanceled(uploadsCtx) { | 
					
						
							|  |  |  | 						errOnce.Do(func() { | 
					
						
							|  |  |  | 							retError = err.Error() | 
					
						
							|  |  |  | 							logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					uploadsCancel() | 
					
						
							|  |  |  | 					return | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				reader := NewPutObjReader(hashReader) | 
					
						
							| 
									
										
										
										
											2022-01-28 00:13:03 +08:00
										 |  |  | 				objInfo, err := objAPI.PutObject(uploadsCtx, minioMetaBucket, fmt.Sprintf("%s.%d.%d", | 
					
						
							| 
									
										
										
										
											2021-11-30 01:05:46 +08:00
										 |  |  | 					objNamePrefix, i, objCountPerThread[i]), reader, ObjectOptions{ | 
					
						
							|  |  |  | 					UserDefined: map[string]string{ | 
					
						
							|  |  |  | 						xhttp.AmzStorageClass: storageClass, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 					if !contextCanceled(uploadsCtx) { | 
					
						
							|  |  |  | 						errOnce.Do(func() { | 
					
						
							|  |  |  | 							retError = err.Error() | 
					
						
							|  |  |  | 							logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					uploadsCancel() | 
					
						
							|  |  |  | 					return | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-11-20 02:41:37 +08:00
										 |  |  | 				atomic.AddUint64(&totalBytesWritten, uint64(objInfo.Size)) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				objCountPerThread[i]++ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}(i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 	// We already saw write failures, no need to proceed into read's
 | 
					
						
							|  |  |  | 	if retError != "" { | 
					
						
							|  |  |  | 		return SpeedtestResult{Uploads: totalBytesWritten, Downloads: totalBytesRead, Error: retError}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 	downloadsCtx, downloadsCancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 	defer downloadsCancel() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	go func() { | 
					
						
							|  |  |  | 		time.Sleep(duration) | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 		downloadsCancel() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wg.Add(concurrent) | 
					
						
							|  |  |  | 	for i := 0; i < concurrent; i++ { | 
					
						
							|  |  |  | 		go func(i int) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							|  |  |  | 			var j uint64 | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 			if objCountPerThread[i] == 0 { | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 			for { | 
					
						
							|  |  |  | 				if objCountPerThread[i] == j { | 
					
						
							|  |  |  | 					j = 0 | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-01-28 00:13:03 +08:00
										 |  |  | 				r, err := objAPI.GetObjectNInfo(downloadsCtx, minioMetaBucket, fmt.Sprintf("%s.%d.%d", | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 					objNamePrefix, i, j), nil, nil, noLock, ObjectOptions{}) | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 					if !contextCanceled(downloadsCtx) { | 
					
						
							|  |  |  | 						errOnce.Do(func() { | 
					
						
							|  |  |  | 							retError = err.Error() | 
					
						
							|  |  |  | 							logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					downloadsCancel() | 
					
						
							|  |  |  | 					return | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 				n, err := io.Copy(ioutil.Discard, r) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				r.Close() | 
					
						
							| 
									
										
										
										
											2021-11-20 02:41:37 +08:00
										 |  |  | 				if err == nil { | 
					
						
							|  |  |  | 					// Only capture success criteria - do not
 | 
					
						
							|  |  |  | 					// have to capture failed reads, truncated
 | 
					
						
							|  |  |  | 					// reads etc.
 | 
					
						
							|  |  |  | 					atomic.AddUint64(&totalBytesRead, uint64(n)) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 					if !contextCanceled(downloadsCtx) { | 
					
						
							|  |  |  | 						errOnce.Do(func() { | 
					
						
							|  |  |  | 							retError = err.Error() | 
					
						
							|  |  |  | 							logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					downloadsCancel() | 
					
						
							|  |  |  | 					return | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				j++ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}(i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							| 
									
										
										
										
											2021-12-07 08:36:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-11 08:43:34 +08:00
										 |  |  | 	return SpeedtestResult{Uploads: totalBytesWritten, Downloads: totalBytesRead, Error: retError}, nil | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *peerRESTServer) SpeedtestHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							| 
									
										
										
										
											2021-11-24 04:02:16 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	sizeStr := r.Form.Get(peerRESTSize) | 
					
						
							|  |  |  | 	durationStr := r.Form.Get(peerRESTDuration) | 
					
						
							|  |  |  | 	concurrentStr := r.Form.Get(peerRESTConcurrent) | 
					
						
							| 
									
										
										
										
											2021-11-30 01:05:46 +08:00
										 |  |  | 	storageClass := r.Form.Get(peerRESTStorageClass) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	size, err := strconv.Atoi(sizeStr) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		size = 64 * humanize.MiByte | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	concurrent, err := strconv.Atoi(concurrentStr) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		concurrent = 32 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	duration, err := time.ParseDuration(durationStr) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		duration = time.Second * 10 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 05:08:23 +08:00
										 |  |  | 	done := keepHTTPResponseAlive(w) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-30 01:05:46 +08:00
										 |  |  | 	result, err := selfSpeedtest(r.Context(), size, concurrent, duration, storageClass) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-09-01 05:08:23 +08:00
										 |  |  | 		result.Error = err.Error() | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 05:08:23 +08:00
										 |  |  | 	done(nil) | 
					
						
							|  |  |  | 	logger.LogIf(r.Context(), gob.NewEncoder(w).Encode(result)) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | // GetLastDayTierStatsHandler - returns per-tier stats in the last 24hrs for this server
 | 
					
						
							|  |  |  | func (s *peerRESTServer) GetLastDayTierStatsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	if !s.IsValid(w, r) { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errors.New("invalid request")) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetLastDayTierStats") | 
					
						
							|  |  |  | 	if objAPI := newObjectLayerFn(); objAPI == nil || globalTransitionState == nil { | 
					
						
							|  |  |  | 		s.writeErrorResponse(w, errServerNotInitialized) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result := globalTransitionState.getDailyAllTierStats() | 
					
						
							|  |  |  | 	logger.LogIf(ctx, gob.NewEncoder(w).Encode(result)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | // registerPeerRESTHandlers - register peer rest router.
 | 
					
						
							|  |  |  | func registerPeerRESTHandlers(router *mux.Router) { | 
					
						
							|  |  |  | 	server := &peerRESTServer{} | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter := router.PathPrefix(peerRESTPrefix).Subrouter() | 
					
						
							| 
									
										
										
										
											2020-06-18 05:49:26 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHealth).HandlerFunc(httpTraceHdrs(server.HealthHandler)) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodProcInfo).HandlerFunc(httpTraceHdrs(server.GetProcInfoHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemInfo).HandlerFunc(httpTraceHdrs(server.GetMemInfoHandler)) | 
					
						
							| 
									
										
										
										
											2021-07-30 14:05:34 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysErrors).HandlerFunc(httpTraceHdrs(server.GetSysErrorsHandler)) | 
					
						
							| 
									
										
										
										
											2021-08-13 09:58:40 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysServices).HandlerFunc(httpTraceHdrs(server.GetSysServicesHandler)) | 
					
						
							| 
									
										
										
										
											2021-08-25 08:09:37 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysConfig).HandlerFunc(httpTraceHdrs(server.GetSysConfigHandler)) | 
					
						
							| 
									
										
										
										
											2021-06-01 23:55:49 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodOsInfo).HandlerFunc(httpTraceHdrs(server.GetOSInfoHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDiskHwInfo).HandlerFunc(httpTraceHdrs(server.GetPartitionsHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCPUInfo).HandlerFunc(httpTraceHdrs(server.GetCPUsHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDriveInfo).HandlerFunc(httpTraceHdrs(server.GetDrivePerfInfosHandler)) | 
					
						
							| 
									
										
										
										
											2020-11-21 04:52:53 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodNetInfo).HandlerFunc(httpTraceHdrs(server.NetInfoHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDispatchNetInfo).HandlerFunc(httpTraceHdrs(server.DispatchNetInfoHandler)) | 
					
						
							| 
									
										
										
										
											2020-04-28 01:06:21 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCycleBloom).HandlerFunc(httpTraceHdrs(server.CycleServerBloomFilterHandler)) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteBucketMetadata).HandlerFunc(httpTraceHdrs(server.DeleteBucketMetadataHandler)).Queries(restQueries(peerRESTBucket)...) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadBucketMetadata).HandlerFunc(httpTraceHdrs(server.LoadBucketMetadataHandler)).Queries(restQueries(peerRESTBucket)...) | 
					
						
							| 
									
										
										
										
											2021-04-05 06:34:33 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetBucketStats).HandlerFunc(httpTraceHdrs(server.GetBucketStatsHandler)).Queries(restQueries(peerRESTBucket)...) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...) | 
					
						
							| 
									
										
										
										
											2020-07-23 23:03:31 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerUpdate).HandlerFunc(httpTraceHdrs(server.ServerUpdateHandler)) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.DeletePolicyHandler)).Queries(restQueries(peerRESTPolicy)...) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicyMapping).HandlerFunc(httpTraceAll(server.LoadPolicyMappingHandler)).Queries(restQueries(peerRESTUserOrGroup)...) | 
					
						
							| 
									
										
										
										
											2020-04-21 23:35:19 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.DeleteUserHandler)).Queries(restQueries(peerRESTUser)...) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteServiceAccount).HandlerFunc(httpTraceAll(server.DeleteServiceAccountHandler)).Queries(restQueries(peerRESTUser)...) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadServiceAccount).HandlerFunc(httpTraceAll(server.LoadServiceAccountHandler)).Queries(restQueries(peerRESTUser)...) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadGroup).HandlerFunc(httpTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...) | 
					
						
							| 
									
										
										
										
											2020-01-11 09:19:58 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDownloadProfilingData).HandlerFunc(httpTraceHdrs(server.DownloadProfilingDataHandler)) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodTrace).HandlerFunc(server.TraceHandler) | 
					
						
							| 
									
										
										
										
											2019-12-17 12:30:57 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodListen).HandlerFunc(httpTraceHdrs(server.ListenHandler)) | 
					
						
							| 
									
										
										
										
											2019-11-05 01:30:59 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLog).HandlerFunc(server.ConsoleLogHandler) | 
					
						
							| 
									
										
										
										
											2020-05-24 08:38:39 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocalDiskIDs).HandlerFunc(httpTraceHdrs(server.GetLocalDiskIDs)) | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetBandwidth).HandlerFunc(httpTraceHdrs(server.GetBandwidth)) | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetMetacacheListing).HandlerFunc(httpTraceHdrs(server.GetMetacacheListingHandler)) | 
					
						
							|  |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodUpdateMetacacheListing).HandlerFunc(httpTraceHdrs(server.UpdateMetacacheListingHandler)) | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetPeerMetrics).HandlerFunc(httpTraceHdrs(server.GetPeerMetrics)) | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadTransitionTierConfig).HandlerFunc(httpTraceHdrs(server.LoadTransitionTierConfigHandler)) | 
					
						
							| 
									
										
										
										
											2021-07-28 03:55:56 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSpeedtest).HandlerFunc(httpTraceHdrs(server.SpeedtestHandler)) | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodReloadSiteReplicationConfig).HandlerFunc(httpTraceHdrs(server.ReloadSiteReplicationConfigHandler)) | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodReloadPoolMeta).HandlerFunc(httpTraceHdrs(server.ReloadPoolMetaHandler)) | 
					
						
							| 
									
										
										
										
											2022-01-27 06:33:10 +08:00
										 |  |  | 	subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLastDayTierStats).HandlerFunc(httpTraceHdrs(server.GetLastDayTierStatsHandler)) | 
					
						
							| 
									
										
										
										
											2019-03-15 07:27:31 +08:00
										 |  |  | } |