implemented Trial licenses

Original commit: elastic/x-pack-elasticsearch@64b987a991
This commit is contained in:
Areek Zillur 2014-10-10 18:56:29 -04:00
parent f05ccaa3f9
commit 6b208bce8f
10 changed files with 333 additions and 77 deletions

View File

@ -252,7 +252,15 @@ public class ESLicenseManager {
return convertToESLicense(license); return convertToESLicense(license);
} }
ESLicense decryptAndVerifyESLicense(SignedLicense signedLicense, String signature) {
return convertToESLicense(this.licenseManager.decryptAndVerifyLicense(signedLicense), signature);
}
static ESLicense convertToESLicense(License license) { static ESLicense convertToESLicense(License license) {
return convertToESLicense(license, null);
}
static ESLicense convertToESLicense(License license, String signature) {
final LicenseBuilders.LicenseBuilder licenseBuilder = LicenseBuilders.licenseBuilder(false); final LicenseBuilders.LicenseBuilder licenseBuilder = LicenseBuilders.licenseBuilder(false);
licenseBuilder licenseBuilder
.expiryDate(license.getGoodBeforeDate()) .expiryDate(license.getGoodBeforeDate())
@ -261,6 +269,10 @@ public class ESLicenseManager {
.issuedTo(license.getHolder()) .issuedTo(license.getHolder())
.issuer(license.getIssuer()); .issuer(license.getIssuer());
if (signature != null) {
licenseBuilder.signature(signature);
}
assert license.getFeatures().size() == 4 : "one license should have only four feature"; assert license.getFeatures().size() == 4 : "one license should have only four feature";
String maxNodesPrefix = "maxNodes:"; String maxNodesPrefix = "maxNodes:";
String typePrefix = "type:"; String typePrefix = "type:";

View File

@ -5,7 +5,6 @@
*/ */
package org.elasticsearch.license.manager; package org.elasticsearch.license.manager;
import net.nicholaswilliams.java.licensing.LicenseManager;
import net.nicholaswilliams.java.licensing.ObjectSerializer; import net.nicholaswilliams.java.licensing.ObjectSerializer;
import net.nicholaswilliams.java.licensing.SignedLicense; import net.nicholaswilliams.java.licensing.SignedLicense;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
@ -20,22 +19,22 @@ import static org.elasticsearch.license.core.ESLicenses.ESLicense;
public class Utils { public class Utils {
public static ESLicenses getESLicensesFromSignatures(final LicenseManager licenseManager, Set<String> signatures) { public static ESLicenses getESLicensesFromSignatures(final Set<String> signatures) {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder(); final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
for (String signature : signatures) { for (String signature : signatures) {
licensesBuilder.license(getESLicenseFromSignature(licenseManager, signature)); licensesBuilder.license(getESLicenseFromSignature(signature));
} }
return licensesBuilder.build(); return licensesBuilder.build();
} }
private static ESLicense getESLicenseFromSignature(LicenseManager licenseManager, String signature) { private static ESLicense getESLicenseFromSignature(String signature) {
byte[] signatureBytes = Base64.decodeBase64(signature); byte[] signatureBytes = Base64.decodeBase64(signature);
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
byteBuffer = (ByteBuffer) byteBuffer.position(13); byteBuffer = (ByteBuffer) byteBuffer.position(13);
int start = byteBuffer.getInt(); int start = byteBuffer.getInt();
SignedLicense signedLicense = new ObjectSerializer() SignedLicense signedLicense = new ObjectSerializer()
.readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length)); .readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
return ESLicenseManager.convertToESLicense(licenseManager.decryptAndVerifyLicense(signedLicense)); return ESLicenseManager.getInstance().decryptAndVerifyESLicense(signedLicense, signature);
} }
public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) { public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {

View File

@ -10,16 +10,19 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.license.core.ESLicenses; import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders; import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.license.plugin.core.TrialLicenses;
import org.elasticsearch.license.plugin.core.TrialLicensesBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.license.core.ESLicenses.*; import static org.elasticsearch.license.core.ESLicenses.*;
import static org.elasticsearch.license.plugin.core.TrialLicenses.TrialLicense;
public class Utils { public class Utils {
public static ESLicenses readLicensesFrom(StreamInput in) throws IOException { public static ESLicenses readGeneratedLicensesFrom(StreamInput in) throws IOException {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder(); final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
boolean exists = in.readBoolean(); boolean exists = in.readBoolean();
if (exists) { if (exists) {
@ -32,7 +35,7 @@ public class Utils {
return null; return null;
} }
public static void writeLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException { public static void writeGeneratedLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException {
if (esLicenses == null) { if (esLicenses == null) {
out.writeBoolean(false); out.writeBoolean(false);
return; return;
@ -44,6 +47,52 @@ public class Utils {
} }
} }
public static TrialLicenses readTrialLicensesFrom(StreamInput in) throws IOException {
final TrialLicensesBuilder licensesBuilder = TrialLicensesBuilder.trialLicensesBuilder();
boolean exists = in.readBoolean();
if (exists) {
int size = in.readVInt();
for (int i = 0; i < size; i++) {
licensesBuilder.license(trialLicenseFromMap(in.readMap()));
}
return licensesBuilder.build();
}
return null;
}
public static void writeTrialLicensesTo(TrialLicenses trialLicenses, StreamOutput out) throws IOException {
if (trialLicenses == null) {
out.writeBoolean(false);
return;
}
out.writeBoolean(true);
out.writeVInt(trialLicenses.trialLicenses().size());
for (TrialLicense trialLicense : trialLicenses) {
out.writeMap(trialLicenseAsMap(trialLicense));
}
}
public static Map<String, Object> trialLicenseAsMap(TrialLicense trialLicense) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put(TrialLicenseFields.UID, trialLicense.uid());
builder.put(TrialLicenseFields.ISSUE_DATE, trialLicense.issueDate());
builder.put(TrialLicenseFields.EXPIRY_DATE, trialLicense.expiryDate());
builder.put(TrialLicenseFields.MAX_NODES, trialLicense.maxNodes());
builder.put(TrialLicenseFields.FEATURE, trialLicense.feature().string());
return builder.build();
}
public static TrialLicense trialLicenseFromMap(Map<String, Object> map) {
return TrialLicensesBuilder.trialLicenseBuilder()
.uid((String) map.get(TrialLicenseFields.UID))
.maxNodes((int) map.get(TrialLicenseFields.MAX_NODES))
.feature(FeatureType.fromString((String) map.get(TrialLicenseFields.FEATURE)))
.issueDate((long) map.get(TrialLicenseFields.ISSUE_DATE))
.expiryDate((long) map.get(TrialLicenseFields.EXPIRY_DATE))
.build();
}
public static Map<String, Object> licenseAsMap(ESLicense esLicense) { public static Map<String, Object> licenseAsMap(ESLicense esLicense) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder(); ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put(LicenseFields.UID, esLicense.uid()); builder.put(LicenseFields.UID, esLicense.uid());
@ -73,6 +122,15 @@ public class Utils {
} }
final static class TrialLicenseFields {
private final static String UID = "uid";
private final static String ISSUE_DATE = "issue_date";
private final static String EXPIRY_DATE = "expiry_date";
private final static String MAX_NODES = "max_nodes";
private final static String FEATURE = "feature";
}
final static class LicenseFields { final static class LicenseFields {
private final static String UID = "uid"; private final static String UID = "uid";
private final static String TYPE = "type"; private final static String TYPE = "type";

View File

@ -13,8 +13,8 @@ import org.elasticsearch.license.core.LicenseBuilders;
import java.io.IOException; import java.io.IOException;
import static org.elasticsearch.license.plugin.action.Utils.readLicensesFrom; import static org.elasticsearch.license.plugin.action.Utils.readGeneratedLicensesFrom;
import static org.elasticsearch.license.plugin.action.Utils.writeLicensesTo; import static org.elasticsearch.license.plugin.action.Utils.writeGeneratedLicensesTo;
public class GetLicenseResponse extends ActionResponse { public class GetLicenseResponse extends ActionResponse {
@ -34,13 +34,13 @@ public class GetLicenseResponse extends ActionResponse {
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in); super.readFrom(in);
licenses = readLicensesFrom(in); licenses = readGeneratedLicensesFrom(in);
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
writeLicensesTo(licenses, out); writeGeneratedLicensesTo(licenses, out);
} }
} }

View File

@ -53,6 +53,10 @@ public class TransportGetLicenseAction extends TransportMasterNodeReadOperationA
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse> listener) throws ElasticsearchException { protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse> listener) throws ElasticsearchException {
MetaData metaData = state.metaData(); MetaData metaData = state.metaData();
LicensesMetaData licenses = metaData.custom(LicensesMetaData.TYPE); LicensesMetaData licenses = metaData.custom(LicensesMetaData.TYPE);
listener.onResponse(new GetLicenseResponse(licenses)); if (licenses != null) {
listener.onResponse(new GetLicenseResponse(licenses.getLicenses()));
} else {
listener.onResponse(new GetLicenseResponse());
}
} }
} }

View File

@ -15,8 +15,8 @@ import org.elasticsearch.license.core.LicenseUtils;
import java.io.IOException; import java.io.IOException;
import static org.elasticsearch.license.plugin.action.Utils.readLicensesFrom; import static org.elasticsearch.license.plugin.action.Utils.readGeneratedLicensesFrom;
import static org.elasticsearch.license.plugin.action.Utils.writeLicensesTo; import static org.elasticsearch.license.plugin.action.Utils.writeGeneratedLicensesTo;
public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> { public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
@ -54,14 +54,14 @@ public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in); super.readFrom(in);
license = readLicensesFrom(in); license = readGeneratedLicensesFrom(in);
readTimeout(in); readTimeout(in);
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
writeLicensesTo(license, out); writeGeneratedLicensesTo(license, out);
writeTimeout(out); writeTimeout(out);
} }
} }

View File

@ -5,7 +5,7 @@
*/ */
package org.elasticsearch.license.plugin.core; package org.elasticsearch.license.plugin.core;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
@ -14,39 +14,87 @@ import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.core.ESLicenses; import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import static org.elasticsearch.license.core.ESLicenses.ESLicense;
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
import static org.elasticsearch.license.plugin.action.Utils.*; import static org.elasticsearch.license.plugin.action.Utils.*;
import static org.elasticsearch.license.plugin.core.TrialLicenses.TrialLicense;
/** /**
* Contains metadata about registered licenses * Contains metadata about registered licenses
* *
* TODO: add trial licenses to MetaData * TODO: store only signatures rather than the whole licenses json in cluster state
*/ */
public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicenses { public class LicensesMetaData implements MetaData.Custom {
public static final String TYPE = "licenses"; public static final String TYPE = "licenses";
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
private final ImmutableMap<FeatureType, ESLicense> licenses; private final ImmutableMap<FeatureType, ESLicense> licensesMap;
private final ImmutableMap<FeatureType, TrialLicense> trialLicensesMap;
/** /**
* Constructs new licenses metadata * Constructs new licenses metadata
* *
* @param esLicenses list of esLicense * @param esLicenses list of esLicense
*/ */
public LicensesMetaData(List<ESLicense> esLicenses) { public LicensesMetaData(ESLicenses esLicenses, TrialLicenses trialLicenses) {
this.licenses = map(esLicenses); this.licensesMap = map(esLicenses);
this.trialLicensesMap = map(trialLicenses);
} }
public LicensesMetaData(ESLicenses esLicenses) {
this.licenses = map(esLicenses); public ESLicenses getLicenses() {
return new ESLicenses() {
@Override
public Collection<ESLicense> licenses() {
return licensesMap.values();
} }
private static ImmutableMap<FeatureType, ESLicense> map(Iterable<ESLicense> esLicenses) { @Override
public Set<FeatureType> features() {
return licensesMap.keySet();
}
@Override
public ESLicense get(FeatureType featureType) {
return licensesMap.get(featureType);
}
@Override
public Iterator<ESLicense> iterator() {
return licensesMap.values().iterator();
}
};
}
public TrialLicenses getTrialLicenses() {
return new TrialLicenses() {
@Override
public Collection<TrialLicense> trialLicenses() {
return trialLicensesMap.values();
}
@Override
public TrialLicense getTrialLicense(FeatureType featureType) {
return trialLicensesMap.get(featureType);
}
@Override
public Iterator<TrialLicense> iterator() {
return trialLicensesMap.values().iterator();
}
};
}
private static ImmutableMap<FeatureType, ESLicense> map(ESLicenses esLicenses) {
final ImmutableMap.Builder<FeatureType, ESLicense> builder = ImmutableMap.builder(); final ImmutableMap.Builder<FeatureType, ESLicense> builder = ImmutableMap.builder();
if (esLicenses != null) { if (esLicenses != null) {
for (ESLicense esLicense : esLicenses) { for (ESLicense esLicense : esLicenses) {
@ -56,37 +104,14 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
return builder.build(); return builder.build();
} }
@Override private static ImmutableMap<FeatureType, TrialLicense> map(TrialLicenses trialLicenses) {
public Collection<ESLicense> licenses() { final ImmutableMap.Builder<FeatureType, TrialLicense> builder = ImmutableMap.builder();
return licenses.values(); if (trialLicenses != null) {
for (TrialLicense esLicense : trialLicenses) {
builder.put(esLicense.feature(), esLicense);
} }
@Override
public Set<FeatureType> features() {
return licenses.keySet();
} }
return builder.build();
@Override
public ESLicense get(FeatureType featureType) {
return licenses.get(featureType);
}
@Override
public Iterator<ESLicense> iterator() {
return licenses.values().iterator();
}
@Override
public Collection<TrialLicense> trialLicenses() {
//todo trial license functionality
return null;
}
@Override
public TrialLicense getTrialLicense(FeatureType featureType) {
//todo trial license functionality
return null;
} }
/** /**
@ -107,7 +132,13 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
*/ */
@Override @Override
public LicensesMetaData readFrom(StreamInput in) throws IOException { public LicensesMetaData readFrom(StreamInput in) throws IOException {
return new LicensesMetaData(readLicensesFrom(in)); ESLicenses esLicenses = null;
TrialLicenses trialLicenses = null;
if (in.readBoolean()) {
esLicenses = readGeneratedLicensesFrom(in);
trialLicenses = readTrialLicensesFrom(in);
}
return new LicensesMetaData(esLicenses, trialLicenses);
} }
/** /**
@ -115,7 +146,13 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
*/ */
@Override @Override
public void writeTo(LicensesMetaData licensesMetaData, StreamOutput out) throws IOException { public void writeTo(LicensesMetaData licensesMetaData, StreamOutput out) throws IOException {
writeLicensesTo(licensesMetaData, out); if (licensesMetaData == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
writeGeneratedLicensesTo(licensesMetaData.getLicenses(), out);
writeTrialLicensesTo(licensesMetaData.getTrialLicenses(), out);
}
} }
/** /**
@ -125,25 +162,27 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
public LicensesMetaData fromXContent(XContentParser parser) throws IOException { public LicensesMetaData fromXContent(XContentParser parser) throws IOException {
XContentParser.Token token; XContentParser.Token token;
List<ESLicense> licenses = null; final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
final TrialLicensesBuilder trialLicensesBuilder = TrialLicensesBuilder.trialLicensesBuilder();
String fieldName = null; String fieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) { if (token == XContentParser.Token.FIELD_NAME) {
fieldName = parser.currentName(); fieldName = parser.currentName();
} }
if (fieldName != null && fieldName.equals(Fields.LICENSES)) { if (fieldName != null) {
if (licenses == null) { if (fieldName.equals(Fields.LICENSES)) {
licenses = new ArrayList<>();
}
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
licenses.add(licenseFromMap(parser.map())); licensesBuilder.license(licenseFromMap(parser.map()));
}
}
if (fieldName.equals(Fields.TRIAL_LICENSES)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
trialLicensesBuilder.license(trialLicenseFromMap(parser.map()));
} }
} }
} }
if (licenses == null) {
throw new ElasticsearchParseException("failed to parse licenses: expected ['" + Fields.LICENSES + "']");
} }
return new LicensesMetaData(licenses); return new LicensesMetaData(licensesBuilder.build(), trialLicensesBuilder.build());
} }
/** /**
@ -153,10 +192,16 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
public void toXContent(LicensesMetaData licensesMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException { public void toXContent(LicensesMetaData licensesMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
builder.startObject(); builder.startObject();
builder.startArray(Fields.LICENSES); builder.startArray(Fields.LICENSES);
for (ESLicense license : licensesMetaData.licenses()) { for (ESLicense license : licensesMetaData.getLicenses()) {
builder.map(licenseAsMap(license)); builder.map(licenseAsMap(license));
} }
builder.endArray(); builder.endArray();
builder.startArray(Fields.TRIAL_LICENSES);
for (TrialLicense license : licensesMetaData.getTrialLicenses()) {
builder.map(trialLicenseAsMap(license));
}
builder.endArray();
builder.endObject(); builder.endObject();
} }
@ -168,6 +213,7 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
private final static class Fields { private final static class Fields {
private static final String LICENSES = "licenses"; private static final String LICENSES = "licenses";
private static final String TRIAL_LICENSES = "trial_licenses";
} }

View File

@ -7,12 +7,17 @@ package org.elasticsearch.license.plugin.core;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.cluster.*; import org.elasticsearch.cluster.*;
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.ESLicenses; import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders; import org.elasticsearch.license.core.LicenseBuilders;
@ -23,6 +28,7 @@ import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.node.Node; import org.elasticsearch.node.Node;
import org.elasticsearch.node.internal.InternalNode; import org.elasticsearch.node.internal.InternalNode;
import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -60,7 +66,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
@Override @Override
public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener) { public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener) {
final PutLicenseRequest request = requestHolder.request; final PutLicenseRequest request = requestHolder.request;
final LicensesMetaData newLicenseMetaData = new LicensesMetaData(request.license()); final ESLicenses newLicenses = request.license();
clusterService.submitStateUpdateTask(requestHolder.source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) { clusterService.submitStateUpdateTask(requestHolder.source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) {
@Override @Override
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) { protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
@ -73,15 +79,15 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE); LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
esLicenseManager.verifyLicenses(newLicenseMetaData); esLicenseManager.verifyLicenses(newLicenses);
if (currentLicenses == null) { if (currentLicenses == null) {
// no licenses were registered // no licenses were registered
currentLicenses = newLicenseMetaData; currentLicenses = new LicensesMetaData(newLicenses, null);
} else { } else {
// merge previous license with new one // merge previous license with new one
//TODO: proper merge for trial licenses ESLicenses mergedLicenses = LicenseBuilders.merge(currentLicenses.getLicenses(), newLicenses);
currentLicenses = new LicensesMetaData(LicenseBuilders.merge(currentLicenses, newLicenseMetaData)); currentLicenses = new LicensesMetaData(mergedLicenses, currentLicenses.getTrialLicenses());
} }
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses); mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
@ -109,7 +115,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
if (currentLicenses != null) { if (currentLicenses != null) {
//TODO: proper delete for trial licenses //TODO: proper delete for trial licenses
currentLicenses = new LicensesMetaData(LicenseBuilders.removeFeatures(currentLicenses, featuresToDelete)); final ESLicenses newLicenses = LicenseBuilders.removeFeatures(currentLicenses.getLicenses(), featuresToDelete);
currentLicenses = new LicensesMetaData(newLicenses, currentLicenses.getTrialLicenses());
} }
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses); mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
return ClusterState.builder(currentState).metaData(mdBuilder).build(); return ClusterState.builder(currentState).metaData(mdBuilder).build();
@ -117,6 +124,44 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
}); });
} }
//TODO: hook this up
private void registerTrialLicense(final TrialLicenses.TrialLicense trialLicense) {
clusterService.submitStateUpdateTask("register trial license []", new ProcessedClusterStateUpdateTask() {
@Override
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
}
@Override
public ClusterState execute(ClusterState currentState) throws Exception {
MetaData metaData = currentState.metaData();
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
TrialLicensesBuilder newTrialLicenses = TrialLicensesBuilder.trialLicensesBuilder().license(trialLicense);
if (currentLicenses != null) {
if (currentLicenses.getTrialLicenses() != null) {
// had previous trial licenses
newTrialLicenses = newTrialLicenses.licenses(currentLicenses.getTrialLicenses());
currentLicenses = new LicensesMetaData(currentLicenses.getLicenses(), newTrialLicenses.build());
} else {
// had no previous trial license
currentLicenses = new LicensesMetaData(currentLicenses.getLicenses(), newTrialLicenses.build());
}
} else {
// had no license meta data
currentLicenses = new LicensesMetaData(null, newTrialLicenses.build());
}
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
return ClusterState.builder(currentState).metaData(mdBuilder).build();
}
@Override
public void onFailure(String source, @Nullable Throwable t) {
}
});
}
@Override @Override
protected void doStart() throws ElasticsearchException { protected void doStart() throws ElasticsearchException {
clusterService = node.injector().getInstance(ClusterService.class); clusterService = node.injector().getInstance(ClusterService.class);
@ -188,4 +233,36 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
this.source = source; this.source = source;
} }
} }
private TrialLicenses.TrialLicense generateTrialLicense(String feature, int durationInDays, int maxNodes) {
return TrialLicensesBuilder.trialLicenseBuilder()
.issueDate(System.currentTimeMillis())
.durationInDays(durationInDays)
.feature(ESLicenses.FeatureType.fromString(feature))
.maxNodes(maxNodes)
.build();
}
private class PutTrialLicenseRequest extends AcknowledgedRequest<PutTrialLicenseRequest> {
private PutTrialLicenseRequest() {
}
@Override
public ActionRequestValidationException validate() {
return null;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
readTimeout(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
writeTimeout(out);
}
}
} }

View File

@ -9,7 +9,7 @@ import java.util.Collection;
import static org.elasticsearch.license.core.ESLicenses.FeatureType; import static org.elasticsearch.license.core.ESLicenses.FeatureType;
public interface TrialLicenses { public interface TrialLicenses extends Iterable<TrialLicenses.TrialLicense> {
public Collection<TrialLicense> trialLicenses(); public Collection<TrialLicense> trialLicenses();
@ -22,5 +22,10 @@ public interface TrialLicenses {
public long issueDate(); public long issueDate();
public long expiryDate(); public long expiryDate();
public int maxNodes();
public String uid();
} }
} }

View File

@ -21,9 +21,29 @@ public class TrialLicensesBuilder {
return new TrialLicensesBuilder(); return new TrialLicensesBuilder();
} }
private final ImmutableMap.Builder<ESLicenses.FeatureType, TrialLicense> licenseBuilder = ImmutableMap.builder(); public static TrialLicenseBuilder trialLicenseBuilder() {
return new TrialLicenseBuilder();
}
public static TrialLicenses merge(TrialLicenses trialLicenses, TrialLicenses mergeTrialLicenses) {
if (trialLicenses == null && mergeTrialLicenses == null) {
throw new IllegalArgumentException("both licenses can not be null");
} else if (trialLicenses == null) {
return mergeTrialLicenses;
} else if (mergeTrialLicenses == null) {
return trialLicenses;
} else {
return trialLicensesBuilder()
.licenses(trialLicenses.trialLicenses())
.licenses(mergeTrialLicenses.trialLicenses())
.build();
}
}
private final ImmutableMap.Builder<ESLicenses.FeatureType, TrialLicense> licenseBuilder;
public TrialLicensesBuilder() { public TrialLicensesBuilder() {
licenseBuilder = ImmutableMap.builder();
} }
public TrialLicensesBuilder license(TrialLicense trialLicense) { public TrialLicensesBuilder license(TrialLicense trialLicense) {
@ -31,6 +51,10 @@ public class TrialLicensesBuilder {
return this; return this;
} }
public TrialLicensesBuilder licenses(TrialLicenses trialLicenses) {
return licenses(trialLicenses.trialLicenses());
}
public TrialLicensesBuilder licenses(Collection<TrialLicense> trialLicenses) { public TrialLicensesBuilder licenses(Collection<TrialLicense> trialLicenses) {
for (TrialLicense trialLicense : trialLicenses) { for (TrialLicense trialLicense : trialLicenses) {
license(trialLicense); license(trialLicense);
@ -52,6 +76,10 @@ public class TrialLicensesBuilder {
return licenseMap.get(featureType); return licenseMap.get(featureType);
} }
@Override
public Iterator<TrialLicense> iterator() {
return licenseMap.values().iterator();
}
}; };
} }
@ -60,10 +88,22 @@ public class TrialLicensesBuilder {
private long expiryDate = -1; private long expiryDate = -1;
private long issueDate = -1; private long issueDate = -1;
private int durationInDays = -1; private int durationInDays = -1;
private int maxNodes = -1;
private String uid = null;
public TrialLicenseBuilder() { public TrialLicenseBuilder() {
} }
public TrialLicenseBuilder uid(String uid) {
this.uid = uid;
return this;
}
public TrialLicenseBuilder maxNodes(int maxNodes) {
this.maxNodes = maxNodes;
return this;
}
public TrialLicenseBuilder feature(ESLicenses.FeatureType featureType) { public TrialLicenseBuilder feature(ESLicenses.FeatureType featureType) {
this.featureType = featureType; this.featureType = featureType;
return this; return this;
@ -90,6 +130,9 @@ public class TrialLicensesBuilder {
assert durationInDays != -1; assert durationInDays != -1;
expiryDate = DateUtils.expiryDateAfterDays(issueDate, durationInDays); expiryDate = DateUtils.expiryDateAfterDays(issueDate, durationInDays);
} }
if (uid == null) {
uid = UUID.randomUUID().toString();
}
return new TrialLicense() { return new TrialLicense() {
@Override @Override
public ESLicenses.FeatureType feature() { public ESLicenses.FeatureType feature() {
@ -105,6 +148,16 @@ public class TrialLicensesBuilder {
public long expiryDate() { public long expiryDate() {
return expiryDate; return expiryDate;
} }
@Override
public int maxNodes() {
return maxNodes;
}
@Override
public String uid() {
return uid;
}
}; };
} }
@ -116,6 +169,8 @@ public class TrialLicensesBuilder {
msg = "issueDate has to be set"; msg = "issueDate has to be set";
} else if (durationInDays == -1 && expiryDate == -1) { } else if (durationInDays == -1 && expiryDate == -1) {
msg = "durationInDays or expiryDate has to be set"; msg = "durationInDays or expiryDate has to be set";
} else if (maxNodes == -1) {
msg = "maxNodes has to be set";
} }
if (msg != null) { if (msg != null) {
throw new IllegalArgumentException(msg); throw new IllegalArgumentException(msg);