42
42
import org .opensearch .Version ;
43
43
import org .opensearch .action .admin .cluster .health .ClusterHealthRequest ;
44
44
import org .opensearch .action .admin .cluster .health .ClusterHealthResponse ;
45
+ import org .opensearch .action .admin .cluster .repositories .get .GetRepositoriesRequest ;
46
+ import org .opensearch .action .admin .cluster .repositories .get .GetRepositoriesResponse ;
45
47
import org .opensearch .action .admin .indices .settings .get .GetSettingsResponse ;
46
48
import org .opensearch .action .admin .indices .shrink .ResizeType ;
47
49
import org .opensearch .action .admin .indices .stats .IndicesStatsResponse ;
48
50
import org .opensearch .client .Requests ;
51
+ import org .opensearch .cluster .metadata .RepositoryMetadata ;
49
52
import org .opensearch .cluster .routing .allocation .decider .EnableAllocationDecider ;
50
53
import org .opensearch .common .settings .Settings ;
54
+ import org .opensearch .common .unit .TimeValue ;
55
+ import org .opensearch .core .common .unit .ByteSizeValue ;
51
56
import org .opensearch .core .xcontent .MediaTypeRegistry ;
52
57
import org .opensearch .index .query .TermsQueryBuilder ;
53
58
import org .opensearch .indices .recovery .RecoverySettings ;
54
59
import org .opensearch .remotestore .RemoteStoreBaseIntegTestCase ;
60
+ import org .opensearch .repositories .RepositoriesService ;
55
61
import org .opensearch .test .OpenSearchIntegTestCase ;
56
62
import org .opensearch .test .VersionUtils ;
63
+ import org .junit .Before ;
57
64
58
65
import java .util .concurrent .ExecutionException ;
59
66
60
67
import static org .opensearch .test .hamcrest .OpenSearchAssertions .assertAcked ;
61
68
import static org .opensearch .test .hamcrest .OpenSearchAssertions .assertHitCount ;
62
69
import static org .hamcrest .Matchers .equalTo ;
70
+ import static org .hamcrest .Matchers .greaterThan ;
63
71
64
72
@ OpenSearchIntegTestCase .ClusterScope (scope = OpenSearchIntegTestCase .Scope .TEST , numDataNodes = 0 )
65
73
public class RemoteCloneIndexIT extends RemoteStoreBaseIntegTestCase {
@@ -69,6 +77,11 @@ protected boolean forbidPrivateIndexSettings() {
69
77
return false ;
70
78
}
71
79
80
+ @ Before
81
+ public void setup () {
82
+ asyncUploadMockFsRepo = true ;
83
+ }
84
+
72
85
public void testCreateCloneIndex () {
73
86
Version version = VersionUtils .randomIndexCompatibleVersion (random ());
74
87
int numPrimaryShards = randomIntBetween (1 , 5 );
@@ -140,6 +153,79 @@ public void testCreateCloneIndex() {
140
153
141
154
}
142
155
156
+ public void testCreateCloneIndexLowPriorityRateLimit () {
157
+ Version version = VersionUtils .randomIndexCompatibleVersion (random ());
158
+ int numPrimaryShards = 1 ;
159
+ prepareCreate ("source" ).setSettings (
160
+ Settings .builder ().put (indexSettings ()).put ("number_of_shards" , numPrimaryShards ).put ("index.version.created" , version )
161
+ ).get ();
162
+ final int docs = randomIntBetween (0 , 128 );
163
+ for (int i = 0 ; i < docs ; i ++) {
164
+ client ().prepareIndex ("source" ).setSource ("{\" foo\" : \" bar\" , \" i\" : " + i + "}" , MediaTypeRegistry .JSON ).get ();
165
+ }
166
+ ByteSizeValue shardSize = client ().admin ().indices ().prepareStats ("source" ).execute ().actionGet ().getShards ()[0 ].getStats ()
167
+ .getStore ()
168
+ .size ();
169
+ logger .info ("Shard size is {}" , shardSize );
170
+ internalCluster ().ensureAtLeastNumDataNodes (2 );
171
+ // ensure all shards are allocated otherwise the ensure green below might not succeed since we require the merge node
172
+ // if we change the setting too quickly we will end up with one replica unassigned which can't be assigned anymore due
173
+ // to the require._name below.
174
+ ensureGreen ();
175
+ // relocate all shards to one node such that we can merge it.
176
+ client ().admin ().indices ().prepareUpdateSettings ("source" ).setSettings (Settings .builder ().put ("index.blocks.write" , true )).get ();
177
+ ensureGreen ();
178
+
179
+ // disable rebalancing to be able to capture the right stats. balancing can move the target primary
180
+ // making it hard to pin point the source shards.
181
+ client ().admin ()
182
+ .cluster ()
183
+ .prepareUpdateSettings ()
184
+ .setTransientSettings (Settings .builder ().put (EnableAllocationDecider .CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING .getKey (), "none" ))
185
+ .get ();
186
+ try {
187
+ // apply rate limiter
188
+ setLowPriorityUploadRate (REPOSITORY_NAME , "1kb" );
189
+ assertAcked (
190
+ client ().admin ()
191
+ .indices ()
192
+ .prepareResizeIndex ("source" , "target" )
193
+ .setResizeType (ResizeType .CLONE )
194
+ .setSettings (Settings .builder ().put ("index.number_of_replicas" , 0 ).putNull ("index.blocks.write" ).build ())
195
+ .get ()
196
+ );
197
+ ensureGreen ();
198
+ long uploadPauseTime = 0L ;
199
+ for (RepositoriesService repositoriesService : internalCluster ().getDataNodeInstances (RepositoriesService .class )) {
200
+ uploadPauseTime += repositoriesService .repository (REPOSITORY_NAME ).getLowPriorityRemoteUploadThrottleTimeInNanos ();
201
+ }
202
+ assertThat (uploadPauseTime , greaterThan (TimeValue .timeValueSeconds (randomIntBetween (5 , 10 )).nanos ()));
203
+ } catch (Exception e ) {
204
+ throw new RuntimeException (e );
205
+ } finally {
206
+ // clean up
207
+ client ().admin ()
208
+ .cluster ()
209
+ .prepareUpdateSettings ()
210
+ .setTransientSettings (
211
+ Settings .builder ()
212
+ .put (EnableAllocationDecider .CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING .getKey (), (String ) null )
213
+ .put (RecoverySettings .INDICES_INTERNAL_REMOTE_UPLOAD_TIMEOUT .getKey (), (String ) null )
214
+ )
215
+ .get ();
216
+ }
217
+ }
218
+
219
+ protected void setLowPriorityUploadRate (String repoName , String value ) throws ExecutionException , InterruptedException {
220
+ GetRepositoriesRequest gr = new GetRepositoriesRequest (new String [] { repoName });
221
+ GetRepositoriesResponse res = client ().admin ().cluster ().getRepositories (gr ).get ();
222
+ RepositoryMetadata rmd = res .repositories ().get (0 );
223
+ Settings .Builder settings = Settings .builder ()
224
+ .put ("location" , rmd .settings ().get ("location" ))
225
+ .put ("max_remote_low_priority_upload_bytes_per_sec" , value );
226
+ assertAcked (client ().admin ().cluster ().preparePutRepository (repoName ).setType (rmd .type ()).setSettings (settings ).get ());
227
+ }
228
+
143
229
public void testCreateCloneIndexFailure () throws ExecutionException , InterruptedException {
144
230
asyncUploadMockFsRepo = false ;
145
231
Version version = VersionUtils .randomIndexCompatibleVersion (random ());
0 commit comments