storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/peer-rest-server.go (about)

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