UNPKG

10.4 kBJavaScriptView Raw
1/**
2 * Copyright 2017-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 authn = require('./authn');
22const sharedConstants = require('./sharedConstants');
23const bigIqLicenseProviderFactory = require('./bigIqLicenseProviderFactory');
24const Logger = require('./logger');
25const PRODUCTS = require('./sharedConstants').PRODUCTS;
26
27/**
28 * BigIq constructor
29 *
30 * @class
31 * @classdesc
32 * Provides core functionality (CRUD operations, ready, etc) and maintains
33 * references to other modules in f5-cloud-libs.
34 *
35 * After creating a BigIq with this constructor, you must call the
36 * async init() method.
37 *
38 * @param {Object} [options] - Optional parameters.
39 * @param {Object} [options.logger] - Logger to use. Or, pass loggerOptions to get your own logger.
40 * @param {Object} [options.loggerOptions] - Options for the logger.
41 * See {@link module:logger.getLogger} for details.
42 */
43function BigIq(options) {
44 const logger = options ? options.logger : undefined;
45 let loggerOptions = options ? options.loggerOptions : undefined;
46
47 this.constructorOptions = {};
48 if (options) {
49 Object.keys(options).forEach((option) => {
50 this.constructorOptions[option] = options[option];
51 });
52 }
53
54 if (logger) {
55 this.logger = logger;
56 util.setLogger(logger);
57 } else {
58 loggerOptions = loggerOptions || { logLevel: 'none' };
59 loggerOptions.module = module;
60 this.logger = Logger.getLogger(loggerOptions);
61 util.setLoggerOptions(loggerOptions);
62 }
63}
64
65/**
66 * Initialize this instance w/ host user password
67 *
68 * @param {String} host - Host to connect to.
69 * @param {String} user - User (with admin rights).
70 * @param {String} passwordOrUri - Password for user or URL (file, http, https, arn) to
71 * location containing password.
72 * @param {Object} [options] - Optional parameters.
73 * @param {Boolean} [options.passwordIsUri] - Indicates that password is a URI for the password
74 * @param {Boolean} [options.passwordEncrypted] - Indicates that the password is encrypted
75 * @param {Number} [options.port] - Port of management port. Default 443.
76 * @param {Object} [options.bigIp] - {@link BigIp} object. BigIp to control.
77 *
78 * @returns {Promise} A promise which is resolved when initialization is complete
79 * or rejected if an error occurs.
80 */
81BigIq.prototype.init = function init(host, user, passwordOrUri, options) {
82 this.initOptions = {};
83 Object.assign(this.initOptions, options);
84
85 this.host = host ? host.trim() : 'localhost';
86 this.user = user ? user.trim() : null;
87
88 this.bigIp = options ? options.bigIp || {} : {};
89
90 const authnOptions = {
91 product: PRODUCTS.BIGIQ,
92 passwordIsUri: this.initOptions.passwordIsUri,
93 passwordEncrypted: this.initOptions.passwordEncrypted,
94 port: this.initOptions.port
95 };
96
97 return authn.authenticate(this.host, this.user, passwordOrUri, authnOptions)
98 .then((icontrol) => {
99 this.icontrol = icontrol;
100 this.logger.debug('Getting BIG-IQ version.');
101
102 const getVersion = function () {
103 return this.icontrol.list(
104 '/shared/resolver/device-groups/cm-shared-all-big-iqs/devices?$select=version'
105 );
106 };
107
108 return util.tryUntil(this, util.MEDIUM_RETRY, getVersion);
109 })
110 .then((response) => {
111 this.logger.debug(response);
112 this.version = response[0].version;
113 })
114 .catch((err) => {
115 this.logger.info('Unable to initialize BIG-IQ', err && err.message ? err.message : err);
116 return q.reject(err);
117 });
118};
119
120/**
121 * Licenses a BIG-IP from a license pool
122 *
123 * @param {String} poolName - Name of the BIG-IQ pool to license from.
124 * @param {String} bigIpMgmtAddress - Management address of BIG-IP
125 * @param {String} bigIpMgmtPort - Management port of BIG-IP
126 * @param {Object} [options] - Optional parameters
127 * @param {String} [options.cloud] - Name of cloud. Only BIG-IQ 5.4+ needs this.
128 * Supported values are:
129 * aws, azure, gce, vmware, hyperv, kvm, xen
130 * @param {String} [options.skuKeyword1] - skuKeyword1 parameter for CLPv2 licensing. Default none.
131 * @param {String} [options.skuKeyword2] - skuKeyword2 parameter for CLPv2 licensing. Default none.
132 * @param {String} [options.unitOfMeasure] - unitOfMeasure parameter for CLPv2 licensing. Default none.
133 * @param {Boolean} [options.noUnreachable] - Do not use the unreachable API even on BIG-IQs that support it.
134 * @param {Boolean} [options.autoApiType] - Automatically determine API type rather than basing on BIG-IQ
135 * version.
136 *
137 * @returns {Promise} A promise which is resolved when the licensing
138 * is complete or rejected if an error occurs.
139 */
140BigIq.prototype.licenseBigIp = function licenseBigIp(poolName, bigIpMgmtAddress, bigIpMgmtPort, options) {
141 const methodOptions = {};
142 Object.assign(methodOptions, options);
143
144 this.logger.debug('Getting license provider');
145 return getLicenseProvider.call(this, poolName, methodOptions)
146 .then((licenseProvider) => {
147 this.logger.debug('Getting license from provider.');
148 return licenseProvider.getUnmanagedDeviceLicense(
149 this.icontrol,
150 poolName,
151 bigIpMgmtAddress,
152 bigIpMgmtPort,
153 {
154 cloud: methodOptions.cloud,
155 skuKeyword1: methodOptions.skuKeyword1,
156 skuKeyword2: methodOptions.skuKeyword2,
157 unitOfMeasure: methodOptions.unitOfMeasure,
158 tenant: methodOptions.tenant,
159 noUnreachable: methodOptions.noUnreachable
160 }
161 );
162 });
163};
164
165/**
166 * Revokes a license for a BIG-IP
167 *
168 * @param {String} poolName - The name of the license pool to revoke from
169 * @param {String} instance - {@link AutoscaleInstance} to revoke license for
170 * @param {Object} [options] - Optional parameters
171 * @param {Boolean} [options.noUnreachable] - Do not use the unreachable API even on BIG-IQs that support it.
172 */
173BigIq.prototype.revokeLicense = function revokeLicense(poolName, instance, options) {
174 let licenseProvider;
175 this.logger.silly('Revoking license for', instance);
176 try {
177 licenseProvider = bigIqLicenseProviderFactory.getLicenseProviderByVersion(
178 this.version,
179 this.bigIp,
180 this.constructorOptions
181 );
182 this.logger.silly('Calling license provider revoke');
183 return licenseProvider.revoke(this.icontrol, poolName, instance, options);
184 } catch (err) {
185 this.logger.debug('Error revoking license', err && err.message ? err.message : err);
186 return q.reject(err);
187 }
188};
189
190/**
191 * Gets a license provider based on api type or version
192 * @param {String} poolName - The name of the license pool
193 * @param {Object} options - Options
194 * @param {Boolean} options.autoApiType - Automatically determine API type rather
195 * than basing on BIG-IQ version.
196 * @param {Boolean} [options.noUnreachable] - Do not use the unreachable API even on BIG-IQs that support it.
197 */
198function getLicenseProvider(poolName, options) {
199 const methodOptions = {};
200 Object.assign(methodOptions, options);
201 const factoryOptions = {};
202 Object.assign(factoryOptions, this.constructorOptions);
203
204 let licenseProvider;
205
206 if (methodOptions.autoApiType) {
207 return getApiType.call(this, methodOptions)
208 .then((apiType) => {
209 // Even though the main API by type is the same across BIG-IQ versions,
210 // there are some subtle differences the implementations need to know
211 // about
212 factoryOptions.version = this.version;
213 try {
214 licenseProvider = bigIqLicenseProviderFactory.getLicenseProviderByType(
215 apiType,
216 this.bigIp,
217 factoryOptions
218 );
219 return q(licenseProvider);
220 } catch (err) {
221 this.logger.info(
222 'Error getting license provider by type', err && err.message ? err.message : err
223 );
224 return q.reject(err);
225 }
226 })
227 .catch((err) => {
228 this.logger.info('Error getting api type', err && err.message ? err.message : err);
229 return q.reject(err);
230 });
231 }
232
233 try {
234 licenseProvider = bigIqLicenseProviderFactory.getLicenseProviderByVersion(
235 this.version,
236 this.bigIp,
237 factoryOptions
238 );
239
240 return q(licenseProvider);
241 } catch (err) {
242 this.logger.info(
243 'Error getting license provider by type', err && err.message ? err.message : err
244 );
245 return q.reject(err);
246 }
247}
248
249function getApiType(options) {
250 const apiType = options.noUnreachable ?
251 sharedConstants.LICENSE_API_TYPES.UTILITY :
252 sharedConstants.LICENSE_API_TYPES.UTILITY_UNREACHABLE;
253
254 this.logger.silly(`using api type ${apiType}`);
255 return q.resolve(apiType);
256}
257
258module.exports = BigIq;