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-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  cmd  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"reflect" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"runtime" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/gorilla/mux" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-15 00:38:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio-go/v7/pkg/set" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 05:59:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xhttp  "github.com/minio/minio/internal/http" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio/internal/logger" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio/internal/rest" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/pkg/env" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bootstrapRESTVersion        =  "v1" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bootstrapRESTVersionPrefix  =  SlashSeparator  +  bootstrapRESTVersion 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bootstrapRESTPrefix         =  minioReservedBucketPath  +  "/bootstrap" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bootstrapRESTPath           =  bootstrapRESTPrefix  +  bootstrapRESTVersionPrefix 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bootstrapRESTMethodHealth  =  "/health" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bootstrapRESTMethodVerify  =  "/verify" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// To abstract a node over network.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  bootstrapRESTServer  struct { }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ServerSystemConfig - captures information about server configuration.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ServerSystemConfig  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MinioPlatform   string 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									MinioEndpoints  EndpointServerPools 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									MinioEnv        map [ string ] string 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Diff - returns error on first difference found in two configs.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s1  ServerSystemConfig )  Diff ( s2  ServerSystemConfig )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s1 . MinioPlatform  !=  s2 . MinioPlatform  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Expected platform '%s', found to be running '%s'" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s1 . MinioPlatform ,  s2 . MinioPlatform ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 03:43:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s1 . MinioEndpoints . NEndpoints ( )  !=  s2 . MinioEndpoints . NEndpoints ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Expected number of endpoints %d, seen %d" ,  s1 . MinioEndpoints . NEndpoints ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s2 . MinioEndpoints . NEndpoints ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  ep  :=  range  s1 . MinioEndpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ep . SetCount  !=  s2 . MinioEndpoints [ i ] . SetCount  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "Expected set count %d, seen %d" ,  ep . SetCount , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s2 . MinioEndpoints [ i ] . SetCount ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ep . DrivesPerSet  !=  s2 . MinioEndpoints [ i ] . DrivesPerSet  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "Expected drives pet set %d, seen %d" ,  ep . DrivesPerSet , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s2 . MinioEndpoints [ i ] . DrivesPerSet ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j ,  endpoint  :=  range  ep . Endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  endpoint . String ( )  !=  s2 . MinioEndpoints [ i ] . Endpoints [ j ] . String ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  fmt . Errorf ( "Expected endpoint %s, seen %s" ,  endpoint , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													s2 . MinioEndpoints [ i ] . Endpoints [ j ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! reflect . DeepEqual ( s1 . MinioEnv ,  s2 . MinioEnv )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 03:43:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  missing  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  mismatching  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  k ,  v  :=  range  s1 . MinioEnv  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ev ,  ok  :=  s2 . MinioEnv [ k ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												missing  =  append ( missing ,  k ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  v  !=  ev  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												mismatching  =  append ( mismatching ,  k ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( mismatching )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( ` Expected same MINIO_ environment variables and values across all servers: Missing environment values: %s / Mismatch environment values: %s ` ,  missing ,  mismatching ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( ` Expected same MINIO_ environment variables and values across all servers: Missing environment values: %s ` ,  missing ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-02 02:37:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  skipEnvs  =  map [ string ] struct { } {  
						 
					
						
							
								
									
										
										
										
											2021-12-23 03:43:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"MINIO_OPTS" :          { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"MINIO_CERT_PASSWD" :   { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"MINIO_SERVER_DEBUG" :  { } , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-21 05:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"MINIO_DSYNC_TRACE" :   { } , 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-02 02:37:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  getServerSystemCfg ( )  ServerSystemConfig  {  
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									envs  :=  env . List ( "MINIO_" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									envValues  :=  make ( map [ string ] string ,  len ( envs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  envK  :=  range  envs  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-02 02:37:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// skip certain environment variables as part
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// of the whitelist and could be configured
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// differently on each nodes, update skipEnvs()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// map if there are such environment values
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  ok  :=  skipEnvs [ envK ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										envValues [ envK ]  =  env . Get ( envK ,  "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  ServerSystemConfig { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										MinioPlatform :   fmt . Sprintf ( "OS: %s | Arch: %s" ,  runtime . GOOS ,  runtime . GOARCH ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										MinioEndpoints :  globalEndpoints , 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 23:27:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										MinioEnv :        envValues , 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// HealthHandler returns success if request is valid
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( b  * bootstrapRESTServer )  HealthHandler ( w  http . ResponseWriter ,  r  * http . Request )  { }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( b  * bootstrapRESTServer )  VerifyHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "VerifyHandler" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg  :=  getServerSystemCfg ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									logger . LogIf ( ctx ,  json . NewEncoder ( w ) . Encode ( & cfg ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// registerBootstrapRESTHandlers - register bootstrap rest router.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  registerBootstrapRESTHandlers ( router  * mux . Router )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									server  :=  & bootstrapRESTServer { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									subrouter  :=  router . PathPrefix ( bootstrapRESTPrefix ) . Subrouter ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									subrouter . Methods ( http . MethodPost ) . Path ( bootstrapRESTVersionPrefix  +  bootstrapRESTMethodHealth ) . HandlerFunc ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										httpTraceHdrs ( server . HealthHandler ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									subrouter . Methods ( http . MethodPost ) . Path ( bootstrapRESTVersionPrefix  +  bootstrapRESTMethodVerify ) . HandlerFunc ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										httpTraceHdrs ( server . VerifyHandler ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 03:43:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// client to talk to bootstrap NEndpoints.
  
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								type  bootstrapRESTClient  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									endpoint    Endpoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									restClient  * rest . Client 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Wrapper to restClient.Call to handle network errors, in case of network error the connection is marked disconnected
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// permanently. The only way to restore the connection is at the xl-sets layer by xlsets.monitorAndConnectEndpoints()
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// after verifying format.json
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( client  * bootstrapRESTClient )  callWithContext ( ctx  context . Context ,  method  string ,  values  url . Values ,  body  io . Reader ,  length  int64 )  ( respBody  io . ReadCloser ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  values  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										values  =  make ( url . Values ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-09-05 00:45:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									respBody ,  err  =  client . restClient . Call ( ctx ,  method ,  values ,  body ,  length ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  respBody ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Stringer provides a canonicalized representation of node.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( client  * bootstrapRESTClient )  String ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  client . endpoint . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Verify - fetches system server config.
  
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( client  * bootstrapRESTClient )  Verify ( ctx  context . Context ,  srcCfg  ServerSystemConfig )  ( err  error )  {  
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  newObjectLayerFn ( )  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									respBody ,  err  :=  client . callWithContext ( ctx ,  bootstrapRESTMethodVerify ,  nil ,  nil ,  - 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  xhttp . DrainBody ( respBody ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									recvCfg  :=  ServerSystemConfig { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  json . NewDecoder ( respBody ) . Decode ( & recvCfg ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  srcCfg . Diff ( recvCfg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  verifyServerSystemConfig ( ctx  context . Context ,  endpointServerPools  EndpointServerPools )  error  {  
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									srcCfg  :=  getServerSystemCfg ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									clnts  :=  newBootstrapRESTClients ( endpointServerPools ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									var  onlineServers  int 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  offlineEndpoints  [ ] string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  retries  int 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  onlineServers  <  len ( clnts ) / 2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  clnt  :=  range  clnts  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  clnt . Verify ( ctx ,  srcCfg ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  isNetworkError ( err )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													offlineEndpoints  =  append ( offlineEndpoints ,  clnt . String ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  fmt . Errorf ( "%s as has incorrect configuration: %w" ,  clnt . String ( ) ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											onlineServers ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-09 00:10:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  <- ctx . Done ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ctx . Err ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Sleep for a while - so that we don't go into
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// 100% CPU when half the endpoints are offline.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											time . Sleep ( 100  *  time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retries ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// after 5 retries start logging that servers are not reachable yet
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  retries  >=  5  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-25 00:53:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												logger . Info ( fmt . Sprintf ( "Waiting for atleast %d remote servers to be online for bootstrap check" ,  len ( clnts ) / 2 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-19 09:05:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  len ( offlineEndpoints )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													logger . Info ( fmt . Sprintf ( "Following servers are currently offline or unreachable %s" ,  offlineEndpoints ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-09 00:10:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												retries  =  0  // reset to log again after 5 retries.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											offlineEndpoints  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newBootstrapRESTClients ( endpointServerPools  EndpointServerPools )  [ ] * bootstrapRESTClient  {  
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									seenHosts  :=  set . NewStringSet ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  clnts  [ ] * bootstrapRESTClient 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 05:50:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  ep  :=  range  endpointServerPools  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										for  _ ,  endpoint  :=  range  ep . Endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  seenHosts . Contains ( endpoint . Host )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											seenHosts . Add ( endpoint . Host ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Only proceed for remote endpoints.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! endpoint . IsLocal  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-12 13:19:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												clnts  =  append ( clnts ,  newBootstrapRESTClient ( endpoint ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  clnts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns a new bootstrap client.
  
						 
					
						
							
								
									
										
										
										
											2020-07-12 13:19:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newBootstrapRESTClient ( endpoint  Endpoint )  * bootstrapRESTClient  {  
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									serverURL  :=  & url . URL { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Scheme :  endpoint . Scheme , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Host :    endpoint . Host , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Path :    bootstrapRESTPath , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-24 01:51:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									restClient  :=  rest . NewClient ( serverURL ,  globalInternodeTransport ,  newCachedAuthToken ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-27 01:29:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									restClient . HealthCheckFn  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 00:26:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-12 13:19:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  & bootstrapRESTClient { endpoint :  endpoint ,  restClient :  restClient } 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-23 04:45:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}