16
16
import org .elasticsearch .common .Strings ;
17
17
import org .elasticsearch .common .io .stream .StreamInput ;
18
18
import org .elasticsearch .common .io .stream .StreamOutput ;
19
+ import org .elasticsearch .core .Nullable ;
19
20
import org .elasticsearch .license .LicenseUtils ;
20
21
import org .elasticsearch .license .XPackLicenseState ;
21
22
import org .elasticsearch .xcontent .ConstructingObjectParser ;
31
32
import java .util .Objects ;
32
33
33
34
import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY ;
35
+ import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY ;
34
36
import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY ;
35
37
import static org .elasticsearch .xpack .core .searchablesnapshots .SearchableSnapshotsConstants .SEARCHABLE_SNAPSHOT_FEATURE ;
36
38
@@ -143,10 +145,12 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
143
145
IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
144
146
assert indexMetadata != null : "index " + index .getName () + " must exist in the cluster state" ;
145
147
String policyName = LifecycleSettings .LIFECYCLE_NAME_SETTING .get (indexMetadata .getSettings ());
146
- if (indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME ) != null ) {
148
+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
149
+ if (searchableSnapshotMetadata != null ) {
150
+ // TODO: allow this behavior instead of returning false, in this case the index is already a searchable a snapshot
151
+ // so the most graceful way of recovery might be to use this repo
147
152
// The index is already a searchable snapshot, let's see if the repository matches
148
- String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
149
- if (this .snapshotRepository .equals (repo ) == false ) {
153
+ if (this .snapshotRepository .equals (searchableSnapshotMetadata .repositoryName ) == false ) {
150
154
// Okay, different repo, we need to go ahead with the searchable snapshot
151
155
logger .debug (
152
156
"[{}] action is configured for index [{}] in policy [{}] which is already mounted as a searchable "
@@ -155,15 +159,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
155
159
SearchableSnapshotAction .NAME ,
156
160
index .getName (),
157
161
policyName ,
158
- repo ,
162
+ searchableSnapshotMetadata . repositoryName ,
159
163
this .snapshotRepository
160
164
);
161
165
return false ;
162
166
}
163
167
164
168
// Check to the storage type to see if we need to convert between full <-> partial
165
- final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
166
- MountSearchableSnapshotRequest .Storage existingType = partial
169
+ MountSearchableSnapshotRequest .Storage existingType = searchableSnapshotMetadata .partial
167
170
? MountSearchableSnapshotRequest .Storage .SHARED_CACHE
168
171
: MountSearchableSnapshotRequest .Storage .FULL_COPY ;
169
172
MountSearchableSnapshotRequest .Storage type = getConcreteStorageType (preActionBranchingKey );
@@ -174,7 +177,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
174
177
SearchableSnapshotAction .NAME ,
175
178
index .getName (),
176
179
policyName ,
177
- repo ,
180
+ searchableSnapshotMetadata . repositoryName ,
178
181
type
179
182
);
180
183
return true ;
@@ -211,7 +214,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
211
214
// When generating a snapshot, we either jump to the force merge step, or we skip the
212
215
// forcemerge and go straight to steps for creating the snapshot
213
216
StepKey keyForSnapshotGeneration = forceMergeIndex ? forceMergeStepKey : generateSnapshotNameKey ;
214
- // Branch, deciding whether there is an existing searchable snapshot snapshot that can be used for mounting the index
217
+ // Branch, deciding whether there is an existing searchable snapshot that can be used for mounting the index
215
218
// (in which case, skip generating a new name and the snapshot cleanup), or if we need to generate a new snapshot
216
219
BranchingStep skipGeneratingSnapshotStep = new BranchingStep (
217
220
skipGeneratingSnapshotKey ,
@@ -221,7 +224,8 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
221
224
IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
222
225
String policyName = LifecycleSettings .LIFECYCLE_NAME_SETTING .get (indexMetadata .getSettings ());
223
226
LifecycleExecutionState lifecycleExecutionState = LifecycleExecutionState .fromIndexMetadata (indexMetadata );
224
- if (lifecycleExecutionState .getSnapshotName () == null ) {
227
+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
228
+ if (lifecycleExecutionState .getSnapshotName () == null && searchableSnapshotMetadata == null ) {
225
229
// No name exists, so it must be generated
226
230
logger .trace (
227
231
"no snapshot name for index [{}] in policy [{}] exists, so one will be generated" ,
@@ -230,8 +234,20 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
230
234
);
231
235
return false ;
232
236
}
237
+ String snapshotIndexName ;
238
+ String snapshotName ;
239
+ String repoName ;
240
+ if (lifecycleExecutionState .getSnapshotName () != null ) {
241
+ snapshotIndexName = lifecycleExecutionState .getSnapshotIndexName ();
242
+ snapshotName = lifecycleExecutionState .getSnapshotName ();
243
+ repoName = lifecycleExecutionState .getSnapshotRepository ();
244
+ } else {
245
+ snapshotIndexName = searchableSnapshotMetadata .sourceIndex ;
246
+ snapshotName = searchableSnapshotMetadata .snapshotName ;
247
+ repoName = searchableSnapshotMetadata .repositoryName ;
248
+ }
233
249
234
- if (this .snapshotRepository .equals (lifecycleExecutionState . getSnapshotRepository () ) == false ) {
250
+ if (this .snapshotRepository .equals (repoName ) == false ) {
235
251
// A different repository is being used
236
252
// TODO: allow this behavior instead of throwing an exception
237
253
throw new IllegalArgumentException ("searchable snapshot indices may be converted only within the same repository" );
@@ -240,12 +256,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
240
256
// We can skip the generate, initial cleanup, and snapshot taking for this index, as we already have a generated snapshot.
241
257
// This will jump ahead directly to the "mount snapshot" step
242
258
logger .debug (
243
- "an existing snapshot [{}] in repository [{}] (index name: [{}]) "
244
- + "will be used for mounting [{}] as a searchable snapshot" ,
245
- lifecycleExecutionState .getSnapshotName (),
246
- lifecycleExecutionState .getSnapshotRepository (),
247
- lifecycleExecutionState .getSnapshotIndexName (),
248
- index .getName ()
259
+ "Policy [{}] will use an existing snapshot [{}] in repository [{}] (index name: [{}]) "
260
+ + "to mount [{}] as a searchable snapshot. This snapshot was found in the {}." ,
261
+ policyName ,
262
+ snapshotName ,
263
+ snapshotRepository ,
264
+ snapshotIndexName ,
265
+ index .getName (),
266
+ lifecycleExecutionState .getSnapshotName () != null ? "lifecycle execution state" : "metadata of " + index .getName ()
249
267
);
250
268
return true ;
251
269
}
@@ -401,11 +419,53 @@ public boolean equals(Object o) {
401
419
return false ;
402
420
}
403
421
SearchableSnapshotAction that = (SearchableSnapshotAction ) o ;
404
- return Objects .equals (snapshotRepository , that .snapshotRepository );
422
+ return Objects .equals (snapshotRepository , that .snapshotRepository ) && Objects . equals ( forceMergeIndex , that . forceMergeIndex ) ;
405
423
}
406
424
407
425
@ Override
408
426
public int hashCode () {
409
- return Objects .hash (snapshotRepository );
427
+ return Objects .hash (snapshotRepository , forceMergeIndex );
428
+ }
429
+
430
+ @ Nullable
431
+ static SearchableSnapshotMetadata extractSearchableSnapshotFromSettings (IndexMetadata indexMetadata ) {
432
+ String indexName = indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME );
433
+ if (indexName == null ) {
434
+ return null ;
435
+ }
436
+ String snapshotName = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY );
437
+ String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
438
+ final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
439
+ return new SearchableSnapshotMetadata (indexName , repo , snapshotName , partial );
410
440
}
441
+
442
+ static class SearchableSnapshotMetadata {
443
+ private final String sourceIndex ;
444
+ private final String repositoryName ;
445
+ private final String snapshotName ;
446
+ private final boolean partial ;
447
+
448
+ SearchableSnapshotMetadata (String sourceIndex , String repositoryName , String snapshotName , boolean partial ) {
449
+ this .sourceIndex = sourceIndex ;
450
+ this .repositoryName = repositoryName ;
451
+ this .snapshotName = snapshotName ;
452
+ this .partial = partial ;
453
+ }
454
+
455
+ public String sourceIndex () {
456
+ return sourceIndex ;
457
+ }
458
+
459
+ public String repositoryName () {
460
+ return repositoryName ;
461
+ }
462
+
463
+ public String snapshotName () {
464
+ return snapshotName ;
465
+ }
466
+
467
+ public boolean partial () {
468
+ return partial ;
469
+ }
470
+ };
411
471
}
0 commit comments