mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
server: Startup sequence should be more idempotent. (#2974)
Fixes #2971 - honors ignore-disks option properly. Fixes #2969 - change the net.Dial to have a timeout of 3secs.
This commit is contained in:
parent
686a610fc3
commit
f8e13fb00e
@ -339,7 +339,7 @@ func TestLockRpcServerForceUnlock(t *testing.T) {
|
|||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
Node: "node",
|
Node: "node",
|
||||||
RPCPath: "rpc-path",
|
RPCPath: "rpc-path",
|
||||||
UID: "1234-5678",
|
UID: "1234-5678",
|
||||||
}
|
}
|
||||||
|
|
||||||
// First test that UID should be empty
|
// First test that UID should be empty
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RPCClient is a wrapper type for rpc.Client which provides reconnect on first failure.
|
// RPCClient is a wrapper type for rpc.Client which provides reconnect on first failure.
|
||||||
@ -78,7 +79,8 @@ func (rpcClient *RPCClient) dialRPCClient() (*rpc.Client, error) {
|
|||||||
if rpcClient.secureConn {
|
if rpcClient.secureConn {
|
||||||
conn, err = tls.Dial("tcp", rpcClient.node, &tls.Config{})
|
conn, err = tls.Dial("tcp", rpcClient.node, &tls.Config{})
|
||||||
} else {
|
} else {
|
||||||
conn, err = net.Dial("tcp", rpcClient.node)
|
// Have a dial timeout with 3 secs.
|
||||||
|
conn, err = net.DialTimeout("tcp", rpcClient.node, 3*time.Second)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -194,7 +194,7 @@ func xlHouseKeeping(storageDisks []StorageAPI) error {
|
|||||||
err := cleanupDir(disk, minioMetaBucket, tmpMetaPrefix)
|
err := cleanupDir(disk, minioMetaBucket, tmpMetaPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch errorCause(err) {
|
switch errorCause(err) {
|
||||||
case errDiskNotFound, errVolumeNotFound:
|
case errDiskNotFound, errVolumeNotFound, errFileNotFound:
|
||||||
default:
|
default:
|
||||||
errs[index] = err
|
errs[index] = err
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,9 @@ func getHealMsg(firstEndpoint string, storageDisks []StorageAPI) string {
|
|||||||
msg = fmt.Sprintf(msg, creds.AccessKeyID, creds.SecretAccessKey, firstEndpoint)
|
msg = fmt.Sprintf(msg, creds.AccessKeyID, creds.SecretAccessKey, firstEndpoint)
|
||||||
disksInfo, _, _ := getDisksInfo(storageDisks)
|
disksInfo, _, _ := getDisksInfo(storageDisks)
|
||||||
for i, info := range disksInfo {
|
for i, info := range disksInfo {
|
||||||
|
if storageDisks[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg += fmt.Sprintf(
|
msg += fmt.Sprintf(
|
||||||
"\n[%s] %s - %s %s",
|
"\n[%s] %s - %s %s",
|
||||||
int2Str(i+1, len(storageDisks)),
|
int2Str(i+1, len(storageDisks)),
|
||||||
@ -92,6 +95,9 @@ func getRegularMsg(storageDisks []StorageAPI) string {
|
|||||||
msg := colorBlue("\nInitializing data volume.")
|
msg := colorBlue("\nInitializing data volume.")
|
||||||
disksInfo, _, _ := getDisksInfo(storageDisks)
|
disksInfo, _, _ := getDisksInfo(storageDisks)
|
||||||
for i, info := range disksInfo {
|
for i, info := range disksInfo {
|
||||||
|
if storageDisks[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg += fmt.Sprintf(
|
msg += fmt.Sprintf(
|
||||||
"\n[%s] %s - %s %s",
|
"\n[%s] %s - %s %s",
|
||||||
int2Str(i+1, len(storageDisks)),
|
int2Str(i+1, len(storageDisks)),
|
||||||
@ -119,6 +125,9 @@ func getFormatMsg(storageDisks []StorageAPI) string {
|
|||||||
msg := colorBlue("\nInitializing data volume for the first time.")
|
msg := colorBlue("\nInitializing data volume for the first time.")
|
||||||
disksInfo, _, _ := getDisksInfo(storageDisks)
|
disksInfo, _, _ := getDisksInfo(storageDisks)
|
||||||
for i, info := range disksInfo {
|
for i, info := range disksInfo {
|
||||||
|
if storageDisks[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg += fmt.Sprintf(
|
msg += fmt.Sprintf(
|
||||||
"\n[%s] %s - %s %s",
|
"\n[%s] %s - %s %s",
|
||||||
int2Str(i+1, len(storageDisks)),
|
int2Str(i+1, len(storageDisks)),
|
||||||
|
34
cmd/xl-v1.go
34
cmd/xl-v1.go
@ -170,7 +170,8 @@ func (d byDiskTotal) Less(i, j int) bool {
|
|||||||
|
|
||||||
// getDisksInfo - fetch disks info across all other storage API.
|
// getDisksInfo - fetch disks info across all other storage API.
|
||||||
func getDisksInfo(disks []StorageAPI) (disksInfo []disk.Info, onlineDisks int, offlineDisks int) {
|
func getDisksInfo(disks []StorageAPI) (disksInfo []disk.Info, onlineDisks int, offlineDisks int) {
|
||||||
for _, storageDisk := range disks {
|
disksInfo = make([]disk.Info, len(disks))
|
||||||
|
for i, storageDisk := range disks {
|
||||||
if storageDisk == nil {
|
if storageDisk == nil {
|
||||||
// Storage disk is empty, perhaps ignored disk or not available.
|
// Storage disk is empty, perhaps ignored disk or not available.
|
||||||
offlineDisks++
|
offlineDisks++
|
||||||
@ -185,32 +186,49 @@ func getDisksInfo(disks []StorageAPI) (disksInfo []disk.Info, onlineDisks int, o
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
onlineDisks++
|
onlineDisks++
|
||||||
disksInfo = append(disksInfo, info)
|
disksInfo[i] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort so that the first element is the smallest.
|
|
||||||
sort.Sort(byDiskTotal(disksInfo))
|
|
||||||
|
|
||||||
// Success.
|
// Success.
|
||||||
return disksInfo, onlineDisks, offlineDisks
|
return disksInfo, onlineDisks, offlineDisks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns sorted disksInfo slice which has only valid entries.
|
||||||
|
// i.e the entries where the total size of the disk is not stated
|
||||||
|
// as 0Bytes, this means that the disk is not online or ignored.
|
||||||
|
func sortValidDisksInfo(disksInfo []disk.Info) []disk.Info {
|
||||||
|
var validDisksInfo []disk.Info
|
||||||
|
for _, diskInfo := range disksInfo {
|
||||||
|
if diskInfo.Total == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
validDisksInfo = append(validDisksInfo, diskInfo)
|
||||||
|
}
|
||||||
|
sort.Sort(byDiskTotal(validDisksInfo))
|
||||||
|
return validDisksInfo
|
||||||
|
}
|
||||||
|
|
||||||
// Get an aggregated storage info across all disks.
|
// Get an aggregated storage info across all disks.
|
||||||
func getStorageInfo(disks []StorageAPI) StorageInfo {
|
func getStorageInfo(disks []StorageAPI) StorageInfo {
|
||||||
disksInfo, onlineDisks, offlineDisks := getDisksInfo(disks)
|
disksInfo, onlineDisks, offlineDisks := getDisksInfo(disks)
|
||||||
if len(disksInfo) == 0 {
|
|
||||||
|
// Sort so that the first element is the smallest.
|
||||||
|
validDisksInfo := sortValidDisksInfo(disksInfo)
|
||||||
|
if len(validDisksInfo) == 0 {
|
||||||
return StorageInfo{
|
return StorageInfo{
|
||||||
Total: -1,
|
Total: -1,
|
||||||
Free: -1,
|
Free: -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return calculated storage info, choose the lowest Total and
|
// Return calculated storage info, choose the lowest Total and
|
||||||
// Free as the total aggregated values. Total capacity is always
|
// Free as the total aggregated values. Total capacity is always
|
||||||
// the multiple of smallest disk among the disk list.
|
// the multiple of smallest disk among the disk list.
|
||||||
storageInfo := StorageInfo{
|
storageInfo := StorageInfo{
|
||||||
Total: disksInfo[0].Total * int64(onlineDisks) / 2,
|
Total: validDisksInfo[0].Total * int64(onlineDisks) / 2,
|
||||||
Free: disksInfo[0].Free * int64(onlineDisks) / 2,
|
Free: validDisksInfo[0].Free * int64(onlineDisks) / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
storageInfo.Backend.Type = XL
|
storageInfo.Backend.Type = XL
|
||||||
storageInfo.Backend.OnlineDisks = onlineDisks
|
storageInfo.Backend.OnlineDisks = onlineDisks
|
||||||
storageInfo.Backend.OfflineDisks = offlineDisks
|
storageInfo.Backend.OfflineDisks = offlineDisks
|
||||||
|
@ -19,7 +19,10 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/minio/minio/pkg/disk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestStorageInfo - tests storage info.
|
// TestStorageInfo - tests storage info.
|
||||||
@ -73,6 +76,51 @@ func TestStorageInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort valid disks info.
|
||||||
|
func TestSortingValidDisks(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
disksInfo []disk.Info
|
||||||
|
validDisksInfo []disk.Info
|
||||||
|
}{
|
||||||
|
// One of the disks is offline.
|
||||||
|
{
|
||||||
|
disksInfo: []disk.Info{
|
||||||
|
{Total: 150, Free: 10},
|
||||||
|
{Total: 0, Free: 0},
|
||||||
|
{Total: 200, Free: 10},
|
||||||
|
{Total: 100, Free: 10},
|
||||||
|
},
|
||||||
|
validDisksInfo: []disk.Info{
|
||||||
|
{Total: 100, Free: 10},
|
||||||
|
{Total: 150, Free: 10},
|
||||||
|
{Total: 200, Free: 10},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// All disks are online.
|
||||||
|
{
|
||||||
|
disksInfo: []disk.Info{
|
||||||
|
{Total: 150, Free: 10},
|
||||||
|
{Total: 200, Free: 10},
|
||||||
|
{Total: 100, Free: 10},
|
||||||
|
{Total: 115, Free: 10},
|
||||||
|
},
|
||||||
|
validDisksInfo: []disk.Info{
|
||||||
|
{Total: 100, Free: 10},
|
||||||
|
{Total: 115, Free: 10},
|
||||||
|
{Total: 150, Free: 10},
|
||||||
|
{Total: 200, Free: 10},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
validDisksInfo := sortValidDisksInfo(testCase.disksInfo)
|
||||||
|
if !reflect.DeepEqual(validDisksInfo, testCase.validDisksInfo) {
|
||||||
|
t.Errorf("Test %d: Expected %#v, Got %#v", i+1, testCase.validDisksInfo, validDisksInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestNewXL - tests initialization of all input disks
|
// TestNewXL - tests initialization of all input disks
|
||||||
// and constructs a valid `XL` object
|
// and constructs a valid `XL` object
|
||||||
func TestNewXL(t *testing.T) {
|
func TestNewXL(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user