Update License GET API; minor cleanup

Original commit: elastic/x-pack-elasticsearch@4d4d84caec
This commit is contained in:
Areek Zillur 2014-10-24 12:03:11 -04:00
parent 1a5f72c28d
commit aa4720a2c8
3 changed files with 75 additions and 9 deletions

View File

@ -13,7 +13,6 @@ import org.elasticsearch.license.plugin.core.LicensesService;
public class LicenseModule extends AbstractModule { public class LicenseModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
//TODO: bind LicensesManagementService and LicensesValidationService to LicensesServices instead
bind(ESLicenseManager.class).in(Scopes.SINGLETON); bind(ESLicenseManager.class).in(Scopes.SINGLETON);
bind(LicensesService.class).in(Scopes.SINGLETON); bind(LicensesService.class).in(Scopes.SINGLETON);
} }

View File

@ -313,12 +313,17 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
if (!pendingRegistrations.isEmpty()) { if (!pendingRegistrations.isEmpty()) {
ListenerHolder pendingRegistrationLister; ListenerHolder pendingRegistrationLister;
while ((pendingRegistrationLister = pendingRegistrations.poll()) != null) { while ((pendingRegistrationLister = pendingRegistrations.poll()) != null) {
logger.info("trying to register pending listener for " + pendingRegistrationLister.feature); boolean masterAvailable = registerListener(pendingRegistrationLister);
registerListener(pendingRegistrationLister); logger.info("trying to register pending listener for " + pendingRegistrationLister.feature + " masterAvailable: " + masterAvailable);
if (!masterAvailable) {
// if the master is not available do not, break out of trying pendingRegistrations
break;
}
} }
} }
// notify all interested plugins // notify all interested plugins
logger.info("LicensesService: cluster state changed");
if (checkIfUpdatedMetaData(event)) { if (checkIfUpdatedMetaData(event)) {
final LicensesMetaData currentLicensesMetaData = event.state().getMetaData().custom(LicensesMetaData.TYPE); final LicensesMetaData currentLicensesMetaData = event.state().getMetaData().custom(LicensesMetaData.TYPE);
// Change to debug // Change to debug
@ -360,8 +365,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
* then notifies features to be disabled * then notifies features to be disabled
* *
* @param listenerHolder of the feature to register * @param listenerHolder of the feature to register
*
* @return true if registration has been completed, false otherwise (if masterNode is not available)
*/ */
private void registerListener(final ListenerHolder listenerHolder) { private boolean registerListener(final ListenerHolder listenerHolder) {
logger.info("Registering listener for " + listenerHolder.feature);
LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
if (!hasLicenseForFeature(listenerHolder.feature, currentMetaData)) { if (!hasLicenseForFeature(listenerHolder.feature, currentMetaData)) {
// does not have actual license so generate a trial license // does not have actual license so generate a trial license
@ -371,31 +380,35 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
RegisterTrialLicenseRequest request = new RegisterTrialLicenseRequest(listenerHolder.feature, RegisterTrialLicenseRequest request = new RegisterTrialLicenseRequest(listenerHolder.feature,
new TimeValue(options.durationInDays, TimeUnit.DAYS), options.maxNodes); new TimeValue(options.durationInDays, TimeUnit.DAYS), options.maxNodes);
if (clusterService.state().nodes().localNodeMaster()) { if (clusterService.state().nodes().localNodeMaster()) {
logger.info("Executing trial license request");
registerTrialLicense(request); registerTrialLicense(request);
} else { } else {
DiscoveryNode masterNode = clusterService.state().nodes().masterNode(); DiscoveryNode masterNode = clusterService.state().nodes().masterNode();
logger.info("has STATE_NOT_RECOVERED_BLOCK: " + clusterService.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)
+ " has masterNode: " + (masterNode != null));
if (masterNode != null) { if (masterNode != null) {
logger.info("Sending trial license request to master");
transportService.sendRequest(masterNode, transportService.sendRequest(masterNode,
REGISTER_TRIAL_LICENSE_ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME); REGISTER_TRIAL_LICENSE_ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME);
} else { } else {
// could not sent register trial license request to master // could not sent register trial license request to master
logger.info("Store as pendingRegistration [master not available yet]");
pendingRegistrations.add(listenerHolder); pendingRegistrations.add(listenerHolder);
return false;
} }
} }
} else { } else {
// notify feature as clusterChangedEvent may not happen // notify feature as clusterChangedEvent may not happen
// as no trial or signed license has been found for feature // as no trial or signed license has been found for feature
// Change to debug // Change to debug
logger.info("calling notifyFeatures from registerListeners"); logger.info("Calling notifyFeatures [no trial license spec provided]");
notifyFeatures(currentMetaData); notifyFeatures(currentMetaData);
} }
} else { } else {
// signed license already found for the new registered // signed license already found for the new registered
// feature, notify feature on registration // feature, notify feature on registration
logger.info("Calling notifyFeatures [signed license available]");
notifyFeatures(currentMetaData); notifyFeatures(currentMetaData);
} }
return true;
} }
private boolean hasLicenseForFeature(String feature, LicensesMetaData currentLicensesMetaData) { private boolean hasLicenseForFeature(String feature, LicensesMetaData currentLicensesMetaData) {
@ -481,7 +494,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicensesMetaData); LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicensesMetaData);
long nextScheduleFrequency = -1l; long nextScheduleFrequency = -1l;
long offset = TimeValue.timeValueMinutes(1).getMillis(); long offset = TimeValue.timeValueMinutes(1).getMillis();
StringBuilder sb = new StringBuilder("Registered listeners: [ ");
for (ListenerHolder listenerHolder : registeredListeners) { for (ListenerHolder listenerHolder : registeredListeners) {
sb.append(listenerHolder.feature);
sb.append(" ");
long expiryDate = -1l; long expiryDate = -1l;
if (hasLicenseForFeature(listenerHolder.feature, currentLicensesMetaData)) { if (hasLicenseForFeature(listenerHolder.feature, currentLicensesMetaData)) {
final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData);
@ -508,6 +526,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
listenerHolder.disableFeatureIfNeeded(); listenerHolder.disableFeatureIfNeeded();
} }
} }
sb.append("]");
logger.info(sb.toString());
if (nextScheduleFrequency == -1l) { if (nextScheduleFrequency == -1l) {
nextScheduleFrequency = TimeValue.timeValueMinutes(5).getMillis(); nextScheduleFrequency = TimeValue.timeValueMinutes(5).getMillis();

View File

@ -9,13 +9,16 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.core.ESLicenses; import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.plugin.action.get.GetLicenseAction; import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest; import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
import org.elasticsearch.rest.*; import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener; import org.elasticsearch.rest.action.support.RestBuilderListener;
import java.io.IOException;
import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK; import static org.elasticsearch.rest.RestStatus.OK;
@ -32,9 +35,53 @@ public class RestGetLicenseAction extends BaseRestHandler {
client.admin().cluster().execute(GetLicenseAction.INSTANCE, new GetLicenseRequest(), new RestBuilderListener<GetLicenseResponse>(channel) { client.admin().cluster().execute(GetLicenseAction.INSTANCE, new GetLicenseRequest(), new RestBuilderListener<GetLicenseResponse>(channel) {
@Override @Override
public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception { public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception {
ESLicenses.toXContent(response.licenses(), builder); toXContent(response, builder);
return new BytesRestResponse(OK, builder); return new BytesRestResponse(OK, builder);
} }
}); });
} }
/**
* Output Format:
* {
*   "licenses" : [
*     {
*       "uid" : ...,
*       "type" : ...,
*       "subscription_type" :...,
*       "issued_to" : ... (cluster name if one-time trial license, else value from signed license),
*       "issue_date" : YY-MM-DD (date string in UTC),
*       "expiry_date" : YY-MM-DD (date string in UTC),
*       "feature" : ...,
*       "max_nodes" : ...
*     },
* {...}
*   ]
* }
*
* There will be only one license displayed per feature, the selected license will have the latest expiry_date
* out of all other licenses for the feature.
*
* The licenses are sorted by latest issue_date
*/
private static void toXContent(GetLicenseResponse response, XContentBuilder builder) throws IOException {
builder.startObject();
builder.startArray("licenses");
for (ESLicense license : response.licenses()) {
builder.startObject();
builder.field("uid", license.uid());
builder.field("type", license.type().string());
builder.field("subscription_type", license.subscriptionType().string());
builder.field("issued_to", license.issuedTo());
builder.field("issue_date", DateUtils.dateStringFromLongDate(license.issueDate()));
builder.field("expiry_date", DateUtils.dateStringFromLongDate(license.expiryDate()));
builder.field("feature", license.feature());
builder.field("max_nodes", license.maxNodes());
builder.endObject();
}
builder.endArray();
builder.endObject();
}
} }