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 ;
32
33
import java .util .Objects ;
33
34
34
35
import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY ;
36
+ import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY ;
35
37
import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY ;
36
38
import static org .elasticsearch .xpack .core .searchablesnapshots .SearchableSnapshotsConstants .SEARCHABLE_SNAPSHOT_FEATURE ;
37
39
@@ -141,10 +143,12 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
141
143
IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
142
144
assert indexMetadata != null : "index " + index .getName () + " must exist in the cluster state" ;
143
145
String policyName = indexMetadata .getLifecyclePolicyName ();
144
- if (indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME ) != null ) {
146
+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
147
+ if (searchableSnapshotMetadata != null ) {
148
+ // TODO: allow this behavior instead of returning false, in this case the index is already a searchable a snapshot
149
+ // so the most graceful way of recovery might be to use this repo
145
150
// The index is already a searchable snapshot, let's see if the repository matches
146
- String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
147
- if (this .snapshotRepository .equals (repo ) == false ) {
151
+ if (this .snapshotRepository .equals (searchableSnapshotMetadata .repositoryName ) == false ) {
148
152
// Okay, different repo, we need to go ahead with the searchable snapshot
149
153
logger .debug (
150
154
"[{}] action is configured for index [{}] in policy [{}] which is already mounted as a searchable "
@@ -153,15 +157,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
153
157
SearchableSnapshotAction .NAME ,
154
158
index .getName (),
155
159
policyName ,
156
- repo ,
160
+ searchableSnapshotMetadata . repositoryName ,
157
161
this .snapshotRepository
158
162
);
159
163
return false ;
160
164
}
161
165
162
166
// Check to the storage type to see if we need to convert between full <-> partial
163
- final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
164
- MountSearchableSnapshotRequest .Storage existingType = partial
167
+ MountSearchableSnapshotRequest .Storage existingType = searchableSnapshotMetadata .partial
165
168
? MountSearchableSnapshotRequest .Storage .SHARED_CACHE
166
169
: MountSearchableSnapshotRequest .Storage .FULL_COPY ;
167
170
MountSearchableSnapshotRequest .Storage type = getConcreteStorageType (preActionBranchingKey );
@@ -172,7 +175,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
172
175
SearchableSnapshotAction .NAME ,
173
176
index .getName (),
174
177
policyName ,
175
- repo ,
178
+ searchableSnapshotMetadata . repositoryName ,
176
179
type
177
180
);
178
181
return true ;
@@ -215,7 +218,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
215
218
// When generating a snapshot, we either jump to the force merge step, or we skip the
216
219
// forcemerge and go straight to steps for creating the snapshot
217
220
StepKey keyForSnapshotGeneration = forceMergeIndex ? forceMergeStepKey : generateSnapshotNameKey ;
218
- // Branch, deciding whether there is an existing searchable snapshot snapshot that can be used for mounting the index
221
+ // Branch, deciding whether there is an existing searchable snapshot that can be used for mounting the index
219
222
// (in which case, skip generating a new name and the snapshot cleanup), or if we need to generate a new snapshot
220
223
BranchingStep skipGeneratingSnapshotStep = new BranchingStep (
221
224
skipGeneratingSnapshotKey ,
@@ -225,7 +228,8 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
225
228
IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
226
229
String policyName = indexMetadata .getLifecyclePolicyName ();
227
230
LifecycleExecutionState lifecycleExecutionState = indexMetadata .getLifecycleExecutionState ();
228
- if (lifecycleExecutionState .snapshotName () == null ) {
231
+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
232
+ if (lifecycleExecutionState .snapshotName () == null && searchableSnapshotMetadata == null ) {
229
233
// No name exists, so it must be generated
230
234
logger .trace (
231
235
"no snapshot name for index [{}] in policy [{}] exists, so one will be generated" ,
@@ -234,8 +238,20 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
234
238
);
235
239
return false ;
236
240
}
241
+ String snapshotIndexName ;
242
+ String snapshotName ;
243
+ String repoName ;
244
+ if (lifecycleExecutionState .snapshotName () != null ) {
245
+ snapshotIndexName = lifecycleExecutionState .snapshotIndexName ();
246
+ snapshotName = lifecycleExecutionState .snapshotName ();
247
+ repoName = lifecycleExecutionState .snapshotRepository ();
248
+ } else {
249
+ snapshotIndexName = searchableSnapshotMetadata .sourceIndex ;
250
+ snapshotName = searchableSnapshotMetadata .snapshotName ;
251
+ repoName = searchableSnapshotMetadata .repositoryName ;
252
+ }
237
253
238
- if (this .snapshotRepository .equals (lifecycleExecutionState . snapshotRepository () ) == false ) {
254
+ if (this .snapshotRepository .equals (repoName ) == false ) {
239
255
// A different repository is being used
240
256
// TODO: allow this behavior instead of throwing an exception
241
257
throw new IllegalArgumentException ("searchable snapshot indices may be converted only within the same repository" );
@@ -244,12 +260,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
244
260
// We can skip the generate, initial cleanup, and snapshot taking for this index, as we already have a generated snapshot.
245
261
// This will jump ahead directly to the "mount snapshot" step
246
262
logger .debug (
247
- "an existing snapshot [{}] in repository [{}] (index name: [{}]) "
248
- + "will be used for mounting [{}] as a searchable snapshot" ,
249
- lifecycleExecutionState .snapshotName (),
250
- lifecycleExecutionState .snapshotRepository (),
251
- lifecycleExecutionState .snapshotIndexName (),
252
- index .getName ()
263
+ "Policy [{}] will use an existing snapshot [{}] in repository [{}] (index name: [{}]) "
264
+ + "to mount [{}] as a searchable snapshot. This snapshot was found in the {}." ,
265
+ policyName ,
266
+ snapshotName ,
267
+ snapshotRepository ,
268
+ snapshotIndexName ,
269
+ index .getName (),
270
+ lifecycleExecutionState .snapshotName () != null ? "lifecycle execution state" : "metadata of " + index .getName ()
253
271
);
254
272
return true ;
255
273
}
@@ -411,4 +429,18 @@ public boolean equals(Object o) {
411
429
public int hashCode () {
412
430
return Objects .hash (snapshotRepository , forceMergeIndex );
413
431
}
432
+
433
+ @ Nullable
434
+ static SearchableSnapshotMetadata extractSearchableSnapshotFromSettings (IndexMetadata indexMetadata ) {
435
+ String indexName = indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME );
436
+ if (indexName == null ) {
437
+ return null ;
438
+ }
439
+ String snapshotName = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY );
440
+ String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
441
+ final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
442
+ return new SearchableSnapshotMetadata (indexName , repo , snapshotName , partial );
443
+ }
444
+
445
+ record SearchableSnapshotMetadata (String sourceIndex , String repositoryName , String snapshotName , boolean partial ) {};
414
446
}
0 commit comments