github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/erasure-server-pool-decom_test.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"context"
    22  	"testing"
    23  )
    24  
    25  func prepareErasurePools() (ObjectLayer, []string, error) {
    26  	nDisks := 32
    27  	fsDirs, err := getRandomDisks(nDisks)
    28  	if err != nil {
    29  		return nil, nil, err
    30  	}
    31  
    32  	pools := mustGetPoolEndpoints(0, fsDirs[:16]...)
    33  	pools = append(pools, mustGetPoolEndpoints(1, fsDirs[16:]...)...)
    34  
    35  	// Everything is fine, should return nil
    36  	objLayer, err := newErasureServerPools(context.Background(), pools)
    37  	if err != nil {
    38  		return nil, nil, err
    39  	}
    40  	return objLayer, fsDirs, nil
    41  }
    42  
    43  func TestPoolMetaValidate(t *testing.T) {
    44  	objLayer1, fsDirs, err := prepareErasurePools()
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	defer removeRoots(fsDirs)
    49  
    50  	meta := objLayer1.(*erasureServerPools).poolMeta
    51  	pools := objLayer1.(*erasureServerPools).serverPools
    52  
    53  	objLayer2, fsDirs, err := prepareErasurePools()
    54  	if err != nil {
    55  		t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err)
    56  	}
    57  	defer removeRoots(fsDirs)
    58  
    59  	newPools := objLayer2.(*erasureServerPools).serverPools
    60  	reducedPools := pools[1:]
    61  	orderChangePools := []*erasureSets{
    62  		pools[1],
    63  		pools[0],
    64  	}
    65  
    66  	var nmeta1 poolMeta
    67  	nmeta1.Version = poolMetaVersion
    68  	nmeta1.Pools = append(nmeta1.Pools, meta.Pools...)
    69  	for i, pool := range nmeta1.Pools {
    70  		if i == 0 {
    71  			nmeta1.Pools[i] = PoolStatus{
    72  				CmdLine:    pool.CmdLine,
    73  				ID:         i,
    74  				LastUpdate: UTCNow(),
    75  				Decommission: &PoolDecommissionInfo{
    76  					Complete: true,
    77  				},
    78  			}
    79  		}
    80  	}
    81  
    82  	var nmeta2 poolMeta
    83  	nmeta2.Version = poolMetaVersion
    84  	nmeta2.Pools = append(nmeta2.Pools, meta.Pools...)
    85  	for i, pool := range nmeta2.Pools {
    86  		if i == 0 {
    87  			nmeta2.Pools[i] = PoolStatus{
    88  				CmdLine:    pool.CmdLine,
    89  				ID:         i,
    90  				LastUpdate: UTCNow(),
    91  				Decommission: &PoolDecommissionInfo{
    92  					Complete: false,
    93  				},
    94  			}
    95  		}
    96  	}
    97  
    98  	testCases := []struct {
    99  		meta           poolMeta
   100  		pools          []*erasureSets
   101  		expectedUpdate bool
   102  		expectedErr    bool
   103  		name           string
   104  	}{
   105  		{
   106  			meta:           meta,
   107  			pools:          pools,
   108  			name:           "Correct",
   109  			expectedErr:    false,
   110  			expectedUpdate: false,
   111  		},
   112  		{
   113  			meta:           meta,
   114  			pools:          newPools,
   115  			name:           "Correct-Update",
   116  			expectedErr:    false,
   117  			expectedUpdate: true,
   118  		},
   119  		{
   120  			meta:           meta,
   121  			pools:          reducedPools,
   122  			name:           "Correct-Update",
   123  			expectedErr:    false,
   124  			expectedUpdate: true,
   125  		},
   126  		{
   127  			meta:           meta,
   128  			pools:          orderChangePools,
   129  			name:           "Invalid-Orderchange",
   130  			expectedErr:    false,
   131  			expectedUpdate: true,
   132  		},
   133  		{
   134  			meta:           nmeta1,
   135  			pools:          pools,
   136  			name:           "Invalid-Completed-Pool-Not-Removed",
   137  			expectedErr:    true,
   138  			expectedUpdate: false,
   139  		},
   140  		{
   141  			meta:           nmeta2,
   142  			pools:          pools,
   143  			name:           "Correct-Decom-Pending",
   144  			expectedErr:    false,
   145  			expectedUpdate: false,
   146  		},
   147  		{
   148  			meta:           nmeta2,
   149  			pools:          reducedPools,
   150  			name:           "Invalid-Decom-Pending-Pool-Removal",
   151  			expectedErr:    false,
   152  			expectedUpdate: true,
   153  		},
   154  		{
   155  			meta:           nmeta1,
   156  			pools:          reducedPools,
   157  			name:           "Correct-Decom-Pool-Removed",
   158  			expectedErr:    false,
   159  			expectedUpdate: true,
   160  		},
   161  		{
   162  			meta:           poolMeta{}, // no-pool info available fresh setup.
   163  			pools:          pools,
   164  			name:           "Correct-Fresh-Setup",
   165  			expectedErr:    false,
   166  			expectedUpdate: true,
   167  		},
   168  		{
   169  			meta:           nmeta2,
   170  			pools:          orderChangePools,
   171  			name:           "Invalid-Orderchange-Decom",
   172  			expectedErr:    false,
   173  			expectedUpdate: true,
   174  		},
   175  	}
   176  
   177  	t.Parallel()
   178  	for _, testCase := range testCases {
   179  		testCase := testCase
   180  		t.Run(testCase.name, func(t *testing.T) {
   181  			update, err := testCase.meta.validate(testCase.pools)
   182  			if testCase.expectedErr {
   183  				t.Log(err)
   184  			}
   185  			if err != nil && !testCase.expectedErr {
   186  				t.Errorf("Expected success, but found %s", err)
   187  			}
   188  			if err == nil && testCase.expectedErr {
   189  				t.Error("Expected error, but got `nil`")
   190  			}
   191  			if update != testCase.expectedUpdate {
   192  				t.Errorf("Expected %t, got %t", testCase.expectedUpdate, update)
   193  			}
   194  		})
   195  	}
   196  }