UNPKG

9.89 kBJavaScriptView Raw
1/**
2 * Copyright 2018 F5 Networks, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17'use strict';
18
19const q = require('q');
20const util = require('./util');
21const Logger = require('./logger');
22const BigIq53LicenseProvider = require('./bigIq53LicenseProvider');
23
24const LICENSE_PATH = '/cm/device/tasks/licensing/pool/member-management/';
25const LICENSE_TIMEOUT = { maxRetries: 40, retryIntervalMs: 5000 };
26
27/**
28 * BigIq 5.3 license provider constructor
29 *
30 * @class
31 * @classdesc
32 * Provides ability to get licenses from BIG-IQ 5.3 (and compatible versions).
33 *
34 * @param {Object} bigIp - Base {@link BigIp} object.
35 * @param {Object} [options] - Optional parameters.
36 * @param {Object} [options.logger] - Logger to use. Or, pass loggerOptions to get your own logger.
37 * @param {Object} [options.loggerOptions] - Options for the logger.
38 * See {@link module:logger.getLogger} for details.
39*/
40function BigIq54LicenseProvider(bigIp, options) {
41 const injectedLogger = options ? options.logger : undefined;
42 let loggerOptions = options ? options.loggerOptions : undefined;
43
44 this.constructorOptions = {};
45 if (options) {
46 Object.keys(options).forEach((option) => {
47 this.constructorOptions[option] = options[option];
48 });
49 }
50
51 if (injectedLogger) {
52 this.logger = injectedLogger;
53 util.setLogger(injectedLogger);
54 } else {
55 loggerOptions = loggerOptions || { logLevel: 'none' };
56 loggerOptions.module = module;
57 this.logger = Logger.getLogger(loggerOptions);
58 util.setLoggerOptions(loggerOptions);
59 }
60
61 this.bigIp = bigIp;
62}
63
64/**
65 * Gets a license from BIG-IQ for an unmanaged BIG-IP
66 *
67 * @param {Object} bigIqControl - iControl object for BIG-IQ
68 * @param {String} poolName - Name of the BIG-IQ license pool to use
69 * @param {String} bigIpMgmtAddress - IP address of BIG-IP management port.
70 * Unused only for display in this API. Default 192.0.2.1.
71 * @param {String} bigIpMgmtPort - IP port of BIG-IP management port.
72 * Unused in this API, but here for consistency.
73 * @param {Object} options - Optional parameters
74 * @param {String} options.cloud - Cloud environment. Accepted values are:
75 * aws, azure, gce, vmware, hyperv, kvm, xen
76 * @param {String} [options.skuKeyword1] - skuKeyword1 parameter for CLPv2 licensing. Default none.
77 * @param {String} [options.skuKeyword2] - skuKeyword2 parameter for CLPv2 licensing. Default none.
78 * @param {String} [options.unitOfMeasure] - unitOfMeasure parameter for CLPv2 licensing. Default none.
79 * @param {String} [options.tenant] - tenant parameter for CLPv2 licensing. Default none.
80 * @param {Boolean} [options.noUnreachable] - Do not use the unreachable API even on BIG-IQs that support it.
81 *
82 *
83 * @returns {Promise} A promise which is resolved when the BIG-IP has been licensed
84 * or rejected if an error occurs.
85 */
86BigIq54LicenseProvider.prototype.getUnmanagedDeviceLicense = function getUnmanagedDeviceLicense(
87 bigIqControl,
88 poolName,
89 bigIpMgmtAddress,
90 bigIpMgmtPort,
91 options
92) {
93 if (options && options.noUnreachable) {
94 this.logger.silly('noUnreachable specified, passing off to 5.3 license API');
95 const licenseProvider = new BigIq53LicenseProvider(
96 this.bigIp,
97 this.constructorOptions
98 );
99 return licenseProvider.getUnmanagedDeviceLicense(
100 bigIqControl,
101 poolName,
102 bigIpMgmtAddress,
103 bigIpMgmtPort,
104 options
105 );
106 }
107
108 if (!options || !options.cloud) {
109 const message = 'Cloud name is required when licensing from BIG-IQ 5.4';
110 this.logger.info(message);
111 return q.reject(new Error(message));
112 }
113
114 this.logger.debug('Licensing from pool', poolName);
115 return licenseFromPool.call(this, bigIqControl, poolName, bigIpMgmtAddress, options);
116};
117
118/**
119 * Revokes a license from a BIG-IP
120 *
121 * @param {Object} bigIqControl - iControl object for BIG-IQ
122 * @param {String} poolName - Name of the BIG-IQ license pool to use
123 * @param {String} instance - {@link AutoscaleInstance} to revoke license for
124 * @param {Object} options - Optional parameters
125 * @param {Boolean} [options.noUnreachable] - Do not use the unreachable API even on BIG-IQs that support it.
126 *
127 * @returns {Promise} A promise which is resolved when the BIG-IP license has
128 * been revoked, or rejected if an error occurs.
129 */
130BigIq54LicenseProvider.prototype.revoke = function revoke(bigIqControl, poolName, instance, options) {
131 if (options && options.noUnreachable) {
132 this.logger.silly('noUnreachable specified, passing off to 5.3 revoke API');
133 const licenseProvider = new BigIq53LicenseProvider(
134 this.bigIp,
135 this.constructorOptions
136 );
137 return licenseProvider.revoke(bigIqControl, poolName, instance, options);
138 }
139
140 return bigIqControl.create(
141 LICENSE_PATH,
142 {
143 command: 'revoke',
144 licensePoolName: poolName,
145 address: instance.mgmtIp || '192.0.2.1',
146 assignmentType: 'UNREACHABLE',
147 macAddress: instance.macAddress
148 }
149 );
150};
151
152/**
153 * Gets the license timeout to use
154 *
155 * This is here so that it can be overridden by test code
156 *
157 * @returns the license timeout
158 */
159BigIq54LicenseProvider.prototype.getLicenseTimeout = function getLicenseTimeout() {
160 return LICENSE_TIMEOUT;
161};
162
163function licenseFromPool(bigIqControl, poolName, bigIpMgmtAddress, options) {
164 const hypervisor = options ? options.cloud : undefined;
165 const skuKeyword1 = options ? options.skuKeyword1 : undefined;
166 const skuKeyword2 = options ? options.skuKeyword2 : undefined;
167 const unitOfMeasure = options ? options.unitOfMeasure : undefined;
168 const tenant = options ? options.tenant : undefined;
169 // get our mac address
170 return this.bigIp.deviceInfo()
171 .then((deviceInfo) => {
172 let tenantValue = '';
173 if (tenant) {
174 tenantValue = `${tenant},
175 mgmtAddress=${deviceInfo.managementAddress},hostname=${deviceInfo.hostname}`;
176 } else {
177 tenantValue = `mgmtAddress=${deviceInfo.managementAddress},hostname=${deviceInfo.hostname}`;
178 }
179 const createLicenseTask = function () {
180 return bigIqControl.create(
181 LICENSE_PATH,
182 {
183 hypervisor,
184 skuKeyword1,
185 skuKeyword2,
186 unitOfMeasure,
187 command: 'assign',
188 licensePoolName: poolName,
189 address: bigIpMgmtAddress || '192.0.2.1',
190 assignmentType: 'UNREACHABLE',
191 tenant: tenantValue,
192 macAddress: deviceInfo.baseMac
193 }
194 );
195 };
196
197 return util.tryUntil(this, util.MEDIUM_RETRY, createLicenseTask);
198 })
199 .then((response) => {
200 this.logger.debug(response);
201
202 const taskId = response.id;
203
204 const getLicenseText = function () {
205 return bigIqControl.list(LICENSE_PATH + taskId)
206 .then((taskResponse) => {
207 const status = taskResponse.status;
208 this.logger.verbose('Current licensing task status:', status);
209 if (status === 'FINISHED') {
210 return q(
211 {
212 success: true,
213 licenseText: taskResponse.licenseText
214 }
215 );
216 } else if (status === 'FAILED') {
217 return q(
218 {
219 success: false,
220 errorMessage: taskResponse.errorMessage
221 }
222 );
223 }
224 return q.reject();
225 });
226 };
227
228 return util.tryUntil(this, this.getLicenseTimeout(), getLicenseText)
229 .then((licenseTextResponse) => {
230 if (licenseTextResponse.success && licenseTextResponse.licenseText) {
231 this.logger.silly('License text', licenseTextResponse.licenseText);
232 return this.bigIp.onboard.installLicense(licenseTextResponse.licenseText);
233 }
234
235 return q.reject(new Error(licenseTextResponse.errorMessage));
236 })
237 .catch((err) => {
238 this.logger.info('Failed to license:', err && err.message ? err.message : err);
239 return q.reject(err);
240 });
241 });
242}
243
244module.exports = BigIq54LicenseProvider;