in functions/source/fgt-asg-handler/lib/aws/index.js [2731:2830]
async findRecyclableLicense(stockRecords, usageRecords, limit = -1) {
if (stockRecords instanceof Map && usageRecords instanceof Map) {
let gracePeriod = (parseInt(this._settings['get-license-grace-period']) || 600) * 1000;
// do health check on each item
let queries = [],
healthCheckResults,
recyclableRecords = [],
count = 0,
maxCount,
platform = this.platform;
if (limit === 'all' || isNaN(limit) || parseInt(limit) <= 0) {
maxCount = -1; // set a negative max count to indicate no limit
} else {
maxCount = parseInt(limit); // set a positive maxcount
}
usageRecords.forEach(item => {
if (item.instanceId && item.scalingGroupName) {
queries.push(
(async function(rec) {
// get instance health check and instance info
let tasks = [];
tasks.push(
platform
.getInstanceHealthCheck({
instanceId: rec.instanceId,
scalingGroupName: rec.scalingGroupName
})
.catch(() => null)
);
tasks.push(
platform
.describeInstance({
instanceId: item.instanceId,
scalingGroupName: item.scalingGroupName,
readCache: false
})
.catch(() => null)
);
let [healthCheck, instance] = await Promise.all(tasks);
return {
checksum: rec.checksum,
usageRecord: rec,
healthCheck: healthCheck,
instance: instance
};
})(item)
);
}
}, this);
healthCheckResults = await Promise.all(queries);
for (let result of healthCheckResults) {
// recycle this stock record if checksum (of a license file) exists and the
// corresponding instance which used this license doesn't exist or state isn't
// in-sync
// there's a situation when one fgt was assigned one license, the fgt need time
// to get config, boot up, become available, and start to send hb.
// until then the health check of that fgt won't be available. therefore, here
// the script sets a grace period to allow for the fgt to become fully available.
// if the fgt instance cannot come up and runniing by the grace period. it's
// license will be recycled.
// the health check here only verifies the in-sync state of any fgt instance but
// it doesn't trigger failover.
if (result.checksum && stockRecords.has(result.checksum)) {
let recyclable = false;
// if instance is gone? recycle the license
if (!result.instance) {
recyclable = true;
} else if (
result.instance &&
result.healthCheck &&
(!result.healthCheck.inSync ||
result.healthCheck.inevitableFailToSyncTime <
result.healthCheck.healthCheckTime)
) {
// if instance exists but instance state isn't in-sync? recycle the license
recyclable = true;
} else if (
result.instance &&
!result.healthCheck &&
result.usageRecord &&
Date.now() > result.usageRecord.assignedTime + gracePeriod
) {
// if instance exists but no healthcheck and grace period has passed?
recyclable = true;
}
// recycle the recyclable license
if (recyclable) {
count++;
if (maxCount < 0 || count <= maxCount) {
recyclableRecords.push(stockRecords.get(result.checksum));
if (count === maxCount) {
break;
}
}
}
}
}
return recyclableRecords;
}
}