X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=skyquake%2Fplugins%2Flaunchpad%2Fapi%2Flaunchpad.js;fp=skyquake%2Fplugins%2Flaunchpad%2Fapi%2Flaunchpad.js;h=02c28eb4fa6eb9939f26a6bfcb8b14666d2a7ba8;hb=e29efc315df33d546237e270470916e26df391d6;hp=0000000000000000000000000000000000000000;hpb=9c5e457509ba5a1822c316635c6308874e61b4b9;p=osm%2FUI.git diff --git a/skyquake/plugins/launchpad/api/launchpad.js b/skyquake/plugins/launchpad/api/launchpad.js new file mode 100644 index 000000000..02c28eb4f --- /dev/null +++ b/skyquake/plugins/launchpad/api/launchpad.js @@ -0,0 +1,2026 @@ +/* + * + * Copyright 2016 RIFT.IO Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +var request = require('request'); +var Promise = require('bluebird'); +var rp = require('request-promise'); +var utils = require('../../../framework/core/api_utils/utils.js'); +var constants = require('../../../framework/core/api_utils/constants.js'); +var APIVersion = '/v1'; +var _ = require('underscore'); +var epa_aggregator = require('./epa_aggregator.js'); +var transforms = require('./transforms.js'); +var uuid = require('node-uuid'); + +// Revealing module pattern objects +var Catalog = {}; +var Config = {}; +var NSR = {}; +var VNFR = {}; +var VLR = {}; +var RIFT = {}; +var ComputeTopology = {}; +var NetworkTopology = {}; +var VDUR = {}; +var CloudAccount = {}; +var ConfigAgentAccount = {}; +var RPC = {}; +var SSHkey = {}; +// API Configuration Info +var APIConfig = {} +APIConfig.NfviMetrics = ['vcpu', 'memory']; + +RPC.executeNSServicePrimitive = function(req) { + var api_server = req.query['api_server']; + return new Promise(function(resolve, reject) { + var jsonData = { + "input": req.body + }; + + var headers = _.extend({}, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + } + ); + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/operations/exec-ns-service-primitive', + method: 'POST', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('RPC.executeNSServicePrimitive', error, response, body, resolve, reject)) { + return resolve({ + statusCode: response.statusCode, + data: JSON.stringify(response.body) + }); + } + }) + }); +}; + +RPC.getNSServicePrimitiveValues = function(req) { + var api_server = req.query['api_server']; + // var nsr_id = req.body['nsr_id_ref']; + // var nsConfigPrimitiveName = req.body['name']; + return new Promise(function(resolve, reject) { + var jsonData = { + "input": req.body + }; + + var headers = _.extend({}, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + } + ); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operations/get-ns-service-primitive-values', + method: 'POST', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('RPC.getNSServicePrimitiveValues', error, response, body, resolve, reject)) { + + resolve({ + statusCode: response.statusCode, + data: JSON.parse(body) + }); + } + }); + }).catch(function(error) { + console.log('error getting primitive values'); + }); +}; +RPC.refreshAccountConnectionStatus = function(req) { + var api_server = req.query['api_server']; + var Name = req.params.name; + var Type = req.params.type; + var jsonData = { + input: {} + }; + var rpcInfo = { + sdn: { + label: 'sdn-account', + rpc: 'update-sdn-status' + }, + config: { + label: 'cfg-agent-account', + rpc: 'update-cfg-agent-status' + }, + cloud: { + label: 'cloud-account', + rpc: 'update-cloud-status' + } + } + jsonData.input[rpcInfo[Type].label] = Name; + var headers = _.extend({}, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + } + ); + return new Promise(function(resolve, reject) { + + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operations/' + rpcInfo[Type].rpc, + method: 'POST', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('RPC.refreshAccountConnectionStatus', error, response, body, resolve, reject)) { + + resolve({ + statusCode: response.statusCode, + data: body + }); + } + }); + }).catch(function(error) { + console.log('Error refreshing account info'); + }); +}; + + +var DataCenters = {}; +// Catalog module methods +Catalog.get = function(req) { + var api_server = req.query['api_server']; + var results = {} + return new Promise(function(resolve, reject) { + Promise.all([ + rp({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/nsd-catalog/nsd?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + resolveWithFullResponse: true + }), + rp({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/vnfd-catalog/vnfd?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + resolveWithFullResponse: true + }), + rp({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operational/ns-instance-opdata?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + resolveWithFullResponse: true + }) + // Not enabled for now + // rp({ + // uri: utils.confdPort(api_server) + APIVersion + '/api/config/pnfd-catalog/pnfd?deep', + // method: 'GET', + // headers: _.extend({}, + // constants.HTTP_HEADERS.accept.collection, + // { + // 'Authorization': req.get('Authorization') + // }), + // forever: constants.FOREVER_ON, + // rejectUnauthorized: false, + // resolveWithFullResponse: true + // }) + ]).then(function(result) { + console.log('Resolved all request promises (NSD, VNFD) successfully'); + var response = [{ + "id": "GUID-1", + "name": "RIFT.ware™ NS Descriptors Catalog", + "short-name": "rift.ware-nsd-cat", + "description": "RIFT.ware™, an open source NFV development and deployment software platform that makes it simple to create, deploy and manage hyper-scale Virtual network functions and applications.", + "vendor": "RIFT.io", + "version": "", + "created-on": "", + "type": "nsd", + "meta": { + "icon-svg": "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%0A%3C!--%20Generator%3A%20Adobe%20Illustrator%2018.0.0%2C%20SVG%20Export%20Plug-In%20.%20SVG%20Version%3A%206.00%20Build%200)%20%20--%3E%0A%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%0A%3Csvg%20version%3D%221.1%22%20id%3D%22connection-icon-1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%2050%2050%22%20style%3D%22enable-background%3Anew%200%200%2050%2050%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%09%3Cpath%20d%3D%22M15%2030c-2.8%200-5-2.2-5-5s2.2-5%205-5%205%202.2%205%205-2.2%205-5%205zm0-8c-1.7%200-3%201.3-3%203s1.3%203%203%203%203-1.3%203-3-1.3-3-3-3z%22%2F%3E%3Cpath%20d%3D%22M35%2020c-2.8%200-5-2.2-5-5s2.2-5%205-5%205%202.2%205%205-2.2%205-5%205zm0-8c-1.7%200-3%201.3-3%203s1.3%203%203%203%203-1.3%203-3-1.3-3-3-3z%22%2F%3E%3Cpath%20d%3D%22M35%2040c-2.8%200-5-2.2-5-5s2.2-5%205-5%205%202.2%205%205-2.2%205-5%205zm0-8c-1.7%200-3%201.3-3%203s1.3%203%203%203%203-1.3%203-3-1.3-3-3-3z%22%2F%3E%3Cpath%20d%3D%22M19.007%2025.885l12.88%206.44-.895%201.788-12.88-6.44z%22%2F%3E%3Cpath%20d%3D%22M30.993%2015.885l.894%201.79-12.88%206.438-.894-1.79z%22%2F%3E%3C%2Fsvg%3E" + }, + "descriptors": [] + }, { + "id": "GUID-2", + "name": "RIFT.ware™ VNF Descriptors Catalog", + "short-name": "rift.ware-vnfd-cat", + "description": "RIFT.ware™, an open source NFV development and deployment software platform that makes it simple to create, deploy and manage hyper-scale Virtual network functions and applications.", + "vendor": "RIFT.io", + "version": "", + "created-on": "", + "type": "vnfd", + "meta": { + "icon-svg": "data:image/svg+xml, " + }, + "descriptors": [] + }, { + "id": "GUID-3", + "name": "RIFT.ware™ PNF Descriptors Catalog", + "short-name": "rift.ware-pnfd-cat", + "description": "RIFT.ware™, an open source NFV development and deployment software platform that makes it simple to create, deploy and manage hyper-scale Virtual network functions and applications.", + "vendor": "RIFT.io", + "version": "", + "created-on": "", + "type": "pnfd", + "meta": { + "icon-svg": "data:image/svg+xml, " + }, + "descriptors": [] + }]; + var vnfdCatalog = null; + var vnfdDict = {}; + if (result[1].body) { + vnfdCatalog = JSON.parse(result[1].body).collection['vnfd:vnfd'].map(function(v, i) { + vnfdDict[v.id] = v['short-name'] || v.name; + }) + } + if (result[0].body) { + response[0].descriptors = JSON.parse(result[0].body).collection['nsd:nsd']; + if (result[2].body) { + var data = JSON.parse(result[2].body); + if (data && data["nsr:ns-instance-opdata"] && data["nsr:ns-instance-opdata"]["rw-nsr:nsd-ref-count"]) { + var nsdRefCountCollection = data["nsr:ns-instance-opdata"]["rw-nsr:nsd-ref-count"]; + response[0].descriptors.map(function(nsd) { + if (!nsd["meta"]) { + nsd["meta"] = {}; + } + if (typeof nsd['meta'] == 'string') { + nsd['meta'] = JSON.parse(nsd['meta']); + } + nsd["meta"]["instance-ref-count"] = _.findWhere(nsdRefCountCollection, { + "nsd-id-ref": nsd.id + })["instance-ref-count"]; + nsd["constituent-vnfd"] && nsd["constituent-vnfd"].map(function(v) { + v.name = vnfdDict[v["vnfd-id-ref"]]; + }) + }); + } + } + }; + if (result[1].body) { + response[1].descriptors = JSON.parse(result[1].body).collection['vnfd:vnfd']; + }; + // if (result[2].body) { + // response[2].descriptors = JSON.parse(result[2].body).collection['pnfd:pnfd']; + // }; + resolve({ + statusCode: response.statusCode || 200, + data: JSON.stringify(response) + }); + }).catch(function(error) { + // Todo: Need better logic than all or nothing. + // Right now even if one of the southbound APIs fails - all fail + var res = {}; + console.log('Problem with Catalog.get', error); + res.statusCode = error.statusCode || 500; + res.errorMessage = { + error: 'Failed to get catalogs' + error + }; + reject(res); + }); + }); +}; +Catalog.delete = function(req) { + var api_server = req.query['api_server']; + var catalogType = req.params.catalogType; + var id = req.params.id; + console.log('Deleting', catalogType, id, 'from', api_server); + return new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/' + catalogType + '-catalog/' + catalogType + '/' + id, + method: 'DELETE', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('Catalog.delete', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + } + }); + }); +}; +Catalog.getVNFD = function(req) { + var api_server = req.query['api_server']; + var vnfdID = req.body.data; + var authorization = req.get('Authorization'); + var VNFDs = []; + if (typeof(vnfdID) == "object" && vnfdID.constructor.name == "Array") { + vnfdID.map(function(id) { + VNFDs.push(requestVNFD(id)); + }); + } else { + VNFDs.push(requestVNFD(vnfdID)); + } + return new Promise(function(resolve, reject) { + Promise.all(VNFDs).then(function(data) { + resolve(data) + }).catch(function(error) { + // Todo: Need better logic than all or nothing. + // Right now even if one of the southbound APIs fails - all fail + var res = {}; + console.log('Problem with Catalog.getVNFD', error); + res.statusCode = 404; + res.errorMessage = { + error: 'Failed to get VNFDs' + error + }; + reject(res); + }); + }); + + function requestVNFD(id) { + return new Promise(function(resolve, reject) { + var url = utils.confdPort(api_server) + APIVersion + '/api/config/vnfd-catalog/vnfd' + (id ? '/' + id : '') + '?deep'; + request({ + uri: url, + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': authorization + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('Catalog.getVNFD', error, response, body, resolve, reject)) { + var data; + //Is this still needed? + try { + data = JSON.parse(response.body) + } catch (e) { + reject({ + statusCode: response ? response.statusCode : 400, + errorMessage: 'Issue parsing VNFD ' + id + 'from ' + utils.confdPort(api_server) + APIVersion + '/api/config/vnfd-catalog/vnfd/' + id + '?deep' + }); + } + resolve(data); + } + }); + }); + } +}; +Catalog.create = function(req) { + var api_server = req.query['api_server']; + var catalogType = req.params.catalogType; + var data = req.body; + console.log('Creating', catalogType, 'on', api_server); + var jsonData = {}; + jsonData[catalogType] = []; + jsonData[catalogType].push(data); + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/' + catalogType + '-catalog', + method: 'POST', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('Catalog.create', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + } + }); + }); +}; +Catalog.update = function(req) { + var api_server = req.query['api_server']; + var catalogType = req.params.catalogType; + var id = req.params.id; + var data = req.body; + console.log('Updating', catalogType, 'id', id, 'on', api_server); + var jsonData = {}; + jsonData[catalogType] = {}; + jsonData[catalogType] = data; + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/' + catalogType + '-catalog' + '/' + catalogType + '/' + id, + method: 'PUT', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('Catalog.update', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + } + }); + }); +}; + +Catalog.decorateNsdCatalogWithPlacementGroups = function decorateNsdCatalogWithPlacementGroups(catalog) { + var newData = catalog; + var parsedCatalog = JSON.parse(catalog.data); + var nsds = parsedCatalog[0].descriptors; + var vnfds = parsedCatalog[1].descriptors; + var vnfdDict = (function(){ + var dict = {}; + vnfds.map(function(v, i) { + dict[v.id] = v; + }) + return dict; + })(vnfds); + + nsds.map(function(c, i) { + //Rename and decorate NSD placement groups + c['ns-placement-groups'] = c['placement-groups'] && c['placement-groups'].map(function(p, i) { + //Adds vnfd name to member-vnfd entry + p['member-vnfd'] = p['member-vnfd'].map(function(v) { + v.name = vnfdDict[v['vnfd-id-ref']].name; + return v; + }); + p['host-aggregate'] = []; + return p; + }); + + //Adds vnf placement groups to nsd object for UI + c['vnf-placement-groups'] = []; + c['constituent-vnfd'] && c['constituent-vnfd'].map(function(v) { + var vnf = vnfdDict[v['vnfd-id-ref']]; + // var vnfPg = { + // name: vnf.name, + // 'placement-groups': vnf['placement-groups'].map(function(vp){ + // vp['host-aggregate'] = [{}]; + // return vp; + // }) + // }; + v['vnf-name'] = vnf.name; + vnf['placement-groups'] && vnf['placement-groups'].map(function(vp) { + vp['host-aggregate'] = []; + vp['vnf-name'] = vnf.name; + vp['vnfd-id-ref'] = v['vnfd-id-ref']; + vp['member-vnf-index'] = v['member-vnf-index']; + c['vnf-placement-groups'].push(vp); + }) + }) + return c; + }) + // parsedCatalog[0].descriptors = nsds; + newData.data = JSON.stringify(parsedCatalog); + return newData; +} + +// NSR module methods +// Spend some time refactoring this +// refactor to accept only request object +NSR.get = function(req) { + var self = this; + var nsrPromises = []; + var api_server = req.query["api_server"]; + var id = req.params.id; + var nsdInfo = new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/nsd-catalog/nsd?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('NSR.get nsd-catalog', error, response, body, resolve, reject)) { + var data; + var isString = typeof(response.body) == "string"; + if (isString && response.body == '') return resolve('empty'); + data = isString ? JSON.parse(response.body) : response.body; + var nsdData = data.collection["nsd:nsd"]; + if (nsdData.constructor.name == "Object") { + nsdData = [nsdData]; + } + resolve(nsdData); + }; + }) + }) + var config = new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operational/ns-instance-config/nsr' + (id ? '/' + id : '') + '?deep', + method: 'GET', + headers: _.extend({}, id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('NSR.get ns-instance-config', error, response, body, resolve, reject)) { + var data; + var isString = typeof(response.body) == "string"; + if (isString && response.body == '') return resolve(); + data = isString ? JSON.parse(response.body) : response.body; + data = id ? data : data.collection; + var nsrData = data["nsr:nsr"]; + if (nsrData.constructor.name == "Object") { + nsrData = [nsrData]; + } + resolve(nsrData); + }; + }); + }); + var opData = new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operational/ns-instance-opdata/nsr' + (id ? '/' + id : '') + '?deep', + method: 'GET', + headers: _.extend({}, id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('NSR.get ns-instance-opdata', error, response, body, resolve, reject)) { + var data; + var isString = typeof(response.body) == "string"; + if (isString && response.body == '') return resolve(); + data = isString ? JSON.parse(response.body) : response.body; + data = id ? data : data.collection; + var nsrData = data["nsr:nsr"]; + if (nsrData.constructor.name == "Object") { + nsrData = [nsrData]; + } + nsrData.forEach(self.decorateWithScalingGroupDict); + nsrData.forEach(self.decorateAndTransformNFVI); + nsrData.forEach(self.decorateAndTransformWithControls); + Promise.all(self.addVnfrDataPromise(req, nsrData)).then(function() { + Promise.all(self.addVlrDataPromise(req, nsrData)).then(function() { + resolve(nsrData); + }); + }); + }; + }); + }).catch(function(error) { + console.log('error getting aggregated NS opdata', error) + //note this will actually trigger the success callback + }); + return new Promise(function(resolve, reject) { + //Need smarter error handling here + Promise.all([config, opData]).then(function(resolves) { + var aggregate = {}; + // resolves[0] ==> ns-instance-config + // resolves[1] ==> ns-instance-opdata + + var nsInstanceConfig = resolves[0] && resolves[0]; + var nsInstanceOpdata = resolves[1] && resolves[1]; + + if (!nsInstanceConfig && !nsInstanceOpdata) { + return resolve({ + nsrs: [] + }); + } + + nsInstanceConfig.forEach(function(v, k) { + v.nsd_name = v['nsd'] && v['nsd']['name']; + var scaling_group_descriptor = null; + + scaling_group_descriptor = v['nsd'] && v['nsd']['scaling-group-descriptor']; + + if (scaling_group_descriptor) { + scaling_group_descriptor.map(function(sgd, sgdi) { + sgd['vnfd-member'] && sgd['vnfd-member'].map(function(vnfd, vnfdi) { + var vnfrObj = _.findWhere(_.findWhere(nsInstanceOpdata, { + 'ns-instance-config-ref': v.id + }).vnfrs, { + 'member-vnf-index-ref': vnfd['member-vnf-index-ref'] + }); + if (vnfrObj) { + vnfd['short-name'] = vnfrObj['short-name']; + } + }) + }) + v['scaling-group-descriptor'] = scaling_group_descriptor; + } + + if (nsInstanceOpdata && nsInstanceOpdata.constructor.name == "Array") { + nsInstanceOpdata.forEach(function(w, l) { + if (v.id == w["ns-instance-config-ref"]) { + for (prop in w) { + if (prop != "ns-instance-config-ref" && !v.hasOwnProperty(prop)) { + v[prop] = w[prop]; + } + } + } + }); + } + + v['scaling-group-record'] && v['scaling-group-record'].map(function(sgr) { + var scalingGroupName = sgr['scaling-group-name-ref']; + sgr['instance'] && sgr['instance'].map(function(instance) { + var scalingGroupInstanceId = instance['instance-id']; + instance['vnfrs'] && instance['vnfrs'].map(function(vnfr) { + var vnfrObj = _.findWhere(v['vnfrs'], {id: vnfr}); + if (vnfrObj) { + vnfrObj['scaling-group-name'] = scalingGroupName; + vnfrObj['scaling-group-instance-id'] = scalingGroupInstanceId; + } + }); + }); + }) + }); + var nsrsData = nsInstanceConfig; + nsrsData.sort(function(a, b) { + return a["create-time"] - b["create-time"]; + }); + resolve({ + nsrs: nsrsData + }); + }).catch(function(error) { + reject({ + statusCode: 404, + errorMessage: error + }) + }) + }); +}; +// Static VNFR Cache bu VNFR ID +var staticVNFRCache = {}; + +/** + * [decorateWithScalingGroupDict description] + * @param {[type]} nsr [description] + * @return {[type]} +{vnfr-id} : { + "scaling-group-name-ref": "sg1", + "instance-id": 0, + "op-status": "running", + "is-default": "true", + "create-time": 1463593760, + "config-status": "configuring", + "vnfrs": [ + "432154e3-164e-4c05-83ee-3b56e4c898e7" + ] +} + */ +NSR.decorateWithScalingGroupDict = function(nsr) { + var sg = nsr["scaling-group-record"]; + var dict = {}; + if(sg) { + sg.map(function(s) { + var sgRef = s['scaling-group-name-ref']; + s.instance && s.instance.map(function(si) { + si.vnfrs && si.vnfrs.map(function(v) { + dict[v] = si; + dict[v]["scaling-group-name-ref"] = sgRef; + }) + }) + }) + } + return nsr['vnfr-scaling-groups'] = dict; +} + + +NSR.addVlrDataPromise = function(req, nsrs) { + var api_server = req.query['api_server']; + var promises = []; + nsrs.map(function(nsr) { + var vlrPromises = []; + var vlr = nsr['vlr']; + nsr['decorated-vlrs'] = []; + if (!vlr) { + console.log('No VL\'s found in NS'); + } + vlr && vlr.map(function(vlrObject) { + req.params.id = vlrObject['vlr-ref']; + var vlrPromise = VLR.get(req).then(function(vlr) { + try { + var vlrItem = vlr['data'][0]; + decorateNSRWithVLR(nsr, vlrObject, vlrItem); + } catch (e) { + console.log('Expection caught getting VLRs and adding to NSR:', e); + } + }) + vlrPromises.push(vlrPromise); + }); + var NSR_Promise = new Promise(function(resolve, reject) { + Promise.all(vlrPromises).then(function() { + resolve(); + }) + }); + promises.push(NSR_Promise); + }); + return promises; + + function decorateNSRWithVLR(nsr, nsrVLRObject, vlr) { + var vlrObject = _.extend(nsrVLRObject, vlr); + vlrObject['vnfr-connection-point-ref'] && vlrObject['vnfr-connection-point-ref'].map(function(vnfrCP) { + var vnfrName = nsr['vnfrs'] && _.find(nsr['vnfrs'], {id: vnfrCP['vnfr-id']})['name']; + vnfrName && (vnfrCP['vnfr-name'] = vnfrName); + }); + nsr['decorated-vlrs'].splice(_.sortedIndex(nsr['decorated-vlrs'], vlrObject, 'name'), 0, vlrObject); + // nsr['decorated-vlrs'].splice(_.sortedIndex(nsr['decorated-vlrs'], vlrObject, 'create-time'), 0, vlrObject); + } +} + + +NSR.addVnfrDataPromise = function(req, nsrs) { + var api_server = req.query['api_server']; + var promises = []; + nsrs.map(function(nsr) { + var epa_params = {}; + var constituent_vnfr_ref = nsr["constituent-vnfr-ref"]; + var vnfrPromises = []; + nsr["vnfrs"] = []; + nsr["dashboard-urls"] = []; + nsr['nfvi-metrics'] = []; + if (!constituent_vnfr_ref) { + console.log('Something is wrong, there are no constituent-vnfr-refs'); + constituent_vnfr_ref = []; + } + //Get VNFR Static Data + constituent_vnfr_ref && constituent_vnfr_ref.map(function(constituentVnfrObj) { + req.params.id = constituentVnfrObj['vnfr-id']; + var vnfrPromise; + vnfrPromise = VNFR.get(req).then(function(vnfr) { + try { + var vnfrItem = vnfr[0]; + decorateNSRWithVNFR(nsr, vnfrItem) + staticVNFRCache[vnfrItem.id] = vnfrItem; + } catch (e) { + console.log('Exception caught:', e); + } + }); + vnfrPromises.push(vnfrPromise); + }); + var NSR_Promise = new Promise(function(resolve, reject) { + Promise.all(vnfrPromises).then(function() { + var vnfrs = staticVNFRCache; + //Aggregate EPA Params + constituent_vnfr_ref && constituent_vnfr_ref.map(function(k) { + if (vnfrs[k['vnfr-id']]) { + epa_params = epa_aggregator(vnfrs[k['vnfr-id']].vdur, epa_params); + } + }) + //Add VNFR Name to monitoring params + try { + if (nsr["monitoring-param"]) { + nsr["monitoring-param"].map(function(m) { + var vnfr = vnfrs[m["vnfr-id"]] || {}; + m["vnfr-name"] = vnfr['name'] ? vnfr['name'] : (vnfr['short-name'] ? vnfr['short-name'] : 'VNFR'); + }); + } + } catch (e) { + console.log('Exception caught:', e); + } + resolve(); + }) + }) + nsr["epa-params"] = epa_params; + promises.push(NSR_Promise); + }) + return promises; + + function decorateNSRWithVDURConsoleUrls(nsr, vnfr) { + nsr['console-urls'] = nsr['console-urls'] ? nsr['console-urls'] : []; + + vnfr && vnfr['vdur'] && vnfr['vdur'].map(function(vdur) { + vdur['console-url'] && nsr['console-urls'].push({ + id: vdur.id, + name: vdur.name, + 'console-url': vdur['console-url'] + }); + }); + } + + function decorateNSRWithVNFR(nsr, vnfr) { + var vnfrObj = { + id: vnfr.id, + "member-vnf-index-ref": vnfr["member-vnf-index-ref"], + "short-name": vnfr["short-name"], + "vnf-configuration": vnfr["vnf-configuration"], + "nsr-id": nsr['ns-instance-config-ref'], + "name": vnfr['name'], + "vdur": vnfr["vdur"], + "cloud-account": vnfr["cloud-account"] + }; + var vnfrSg = nsr['vnfr-scaling-groups']; + var vnfrName = vnfr["name"]; + if(vnfrSg) { + if(vnfrSg[vnfr.id]) { + vnfrName = vnfrSg[vnfr.id]["scaling-group-name-ref"] + ':' + vnfrSg[vnfr.id][ "instance-id"] + ':' + vnfrName; + } + } + var vnfrNfviMetrics = buildNfviGraphs(vnfr.vdur, vnfrName); + if (vnfr['vnf-configuration'] && vnfr['vnf-configuration']['service-primitive'] && vnfr['vnf-configuration']['service-primitive'].length > 0) { + vnfrObj['service-primitives-present'] = true; + } else { + vnfrObj['service-primitives-present'] = false; + } + transforms.mergeVnfrNfviMetrics(vnfrNfviMetrics, nsr["nfvi-metrics"]); + //TODO: Should be sorted by create-time when it becomes available instead of id + // nsr["vnfrs"].splice(_.sortedIndex(nsr['vnfrs'], vnfrObj, 'create-time'), 0, vnfrObj); + nsr["vnfrs"].splice(_.sortedIndex(nsr['vnfrs'], vnfrObj, 'id'), 0, vnfrObj); + vnfrObj["dashboard-url"] = vnfr["dashboard-url"]; + nsr["dashboard-urls"].push(vnfrObj); + + decorateNSRWithVDURConsoleUrls(nsr, vnfr); + } +} +NSR.create = function(req) { + var api_server = req.query['api_server']; + var data = req.body.data; + console.log('Instantiating NSR on ', api_server); + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config', + method: 'POST', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: data + }, function(error, response, body) { + if (utils.validateResponse('NSR.create', error, response, body, resolve, reject)) { + var nsr_id = null; + try { + nsr_id = data.nsr[0].id; + } catch (e) { + console.log("NSR.create unable to get nsr_id. Error: %s", + e.toString()); + } + resolve({ + statusCode: response.statusCode, + data: { nsr_id: nsr_id } + }); + }; + }); + }); +}; +NSR.delete = function(req) { + var api_server = req.query["api_server"]; + var id = req.params.id; + if (!id || !api_server) { + return new Promise(function(resolve, reject) { + console.log('Must specifiy api_server and id to delete NSR'); + return reject({ + statusCode: 500, + errorMessage: { + error: 'Must specifiy api_server and id to delete NSR' + } + }); + }); + }; + console.log('Deleting NSR with id: ' + id + 'on server: ' + api_server); + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + id, + method: 'DELETE', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('NSR.delete', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: JSON.stringify(response.body) + }); + }; + }); + }); +}; +NSR.decorateAndTransformNFVI = function(nsr) { + var toDecorate = []; + // var metricsToUse = ["vcpu", "memory", "storage", "network"]; + var metricsToUse = ["vcpu", "memory"]; + try { + var nfviMetrics = nsr["rw-nsr:nfvi-metrics"]; + if (nfviMetrics) { + metricsToUse.map(function(name) { + toDecorate.push(nfviMetrics[name]) + }); + } + nsr["nfvi-metrics"] = toDecorate; + delete nsr["rw-nsr:nfvi-metrics"]; + } catch (e) {} + return nsr; + } + //Not a great pattern, Need a better way of handling logging; + //Refactor and move to the logging/logging.js +var logCache = { + decorateAndTransformWithControls: {} +} +NSR.decorateAndTransformWithControls = function(nsr) { + var controlTypes = ["action-param", "control-param"]; + var nsControls = []; + var Groups = {}; + controlTypes.map(function(control) { + try { + var controls = nsr["rw-nsr:" + control]; + // nsControls.push(controls); + controls.map(function(item) { + if (!Groups[item["group-tag"]]) { + Groups[item["group-tag"]] = {}; + Groups[item["group-tag"]]["action-param"] = [] + Groups[item["group-tag"]]["control-param"] = [] + } + Groups[item["group-tag"]][control].push(item); + }); + delete nsr["rw-nsr:" + control]; + } catch (e) { + var id = nsr["ns-instance-config-ref"]; + if (!logCache.decorateAndTransformWithControls[id]) { + logCache.decorateAndTransformWithControls[id] = {}; + } + var log = logCache.decorateAndTransformWithControls[id]; + if (!log[control]) { + log[control] = true; + console.log('No controls exist for ' + control + ' at ' + nsr["ns-instance-config-ref"]); + } + } + }); + for (k in Groups) { + var obj = {} + obj[k] = Groups[k]; + nsControls.push(obj) + } + nsr.nsControls = nsControls; + return nsr; +}; +NSR.setStatus = function(req) { + var api_server = req.query['api_server']; + var id = req.params.id; + var status = req.body.status; + console.log('Setting NSR (id: ' + id + ') status, on ' + api_server + ', to be: ' + status); + return new Promise(function(resolve, reject) { + var command; + if (typeof(status) != "string") { + reject({ + 'ERROR': 'NSR.setStatus Error: status is not a string type' + }); + } + command = status.toUpperCase(); + if (command != "ENABLED" && command != "DISABLED") { + reject({ + 'ERROR': 'NSR.setStatus Error: status is: ' + command + '. It should be ENABLED or DISABLED' + }); + } + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + id + '/admin-status/', + method: 'PUT', + headers: requestHeaders, + json: { + "nsr:admin-status": command + }, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('NSR.setStatus', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + }; + }); + }); +}; + +NSR.createScalingGroupInstance = function(req) { + var api_server = req.query['api_server']; + var id = req.params.id; + var scaling_group_id = req.params.scaling_group_id; + if (!api_server || !id || !scaling_group_id) { + return new Promise(function(resolve, reject) { + return reject({ + statusCode: 500, + errorMessage: { + error: 'API server/NSR id/Scaling group not provided' + } + }); + }); + } + + var instance_id = Math.floor(Math.random() * 65535); + + var jsonData = { + instance: [{ + // id: uuid.v1() + id: instance_id + }] + }; + + console.log('Creating scaling group instance for NSR ', id, ', scaling group ', scaling_group_id, ' with instance id ', instance_id); + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, + { + 'Authorization': req.get('Authorization') + } + ); + + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + id + '/scaling-group/' + scaling_group_id + '/instance', + method: 'POST', + headers: requestHeaders, + json: jsonData, + forever: constants.FOREVER_ON, + rejectUnauthorized: false + }, function (error, response, body) { + if (utils.validateResponse('NSR.createScalingGroupInstance', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: typeof response.body == 'string' ? JSON.parse(response.body):response.body + }) + } + }); + }); +}; + +NSR.deleteScalingGroupInstance = function(req) { + var api_server=req.query['api_server']; + var id = req.params.id; + var scaling_group_id = req.params.scaling_group_id; + var scaling_instance_id = req.params.scaling_instance_id; + + if (!api_server || !id || !scaling_group_id || !scaling_instance_id) { + return new Promise(function(resolve, reject) { + return reject({ + statusCode: 500, + errorMessage: { + error: 'API server/NSR id/Scaling group/Scaling instance id not provided' + } + }); + }); + } + + console.log('Deleting scaling group instance id ', scaling_instance_id, + ' for scaling group ', scaling_group_id, + ', under NSR ', id); + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, + { + 'Authorization': req.get('Authorization') + } + ); + + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + id + '/scaling-group/' + scaling_group_id + '/instance/' + scaling_instance_id, + method: 'DELETE', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false + }, function (error, response, body) { + if (utils.validateResponse('NSR.deleteScalingGroupInstance', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: typeof response.body == 'string' ? JSON.parse(response.body):response.body + }) + } + }); + }); +}; + +NSR.nsd = {}; +NSR.nsd.vld = {}; + +NSR.nsd.vld.get = function(req) { + var api_server = req.query['api_server']; + var nsr_id = req.params.nsr_id; + var vld_id = req.params.vld_id; + + if (!api_server || !nsr_id) { + return new Promise(function(resolve, reject) { + return reject({ + statusCode: constants.HTTPS_RESPONSE_CODES.ERROR.INTERNAL_SERVER_ERROR, + errorMessage: 'API server/NSR id not provided' + }); + }) + } + console.log('Getting VLD', vld_id ? (' ' + vld_id) : ('\'s'), ' for NSR id', nsr_id); + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + vld_id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, + { + 'Authorization': req.get('Authorization') + } + ); + + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + nsr_id + '/nsd/vld' + (vld_id ? '/' + vld_id : '') +'?deep', + method: 'GET', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false + }, function (error, response, body) { + if (utils.validateResponse('NSR.nsd.vld.get', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: typeof response.body == 'string' ? JSON.parse(response.body):response.body + }); + } + }); + }); +}; + +NSR.nsd.vld.create = function(req) { + var api_server = req.query['api_server']; + var nsr_id = req.params.nsr_id; + var vld_id = req.params.vld_id; + var data = req.body; + + if (!api_server || !nsr_id) { + return new Promise(function(resolve, reject) { + return reject({ + statusCode: constants.HTTPS_RESPONSE_CODES.ERROR.INTERNAL_SERVER_ERROR, + errorMessage: 'API server/NSR id not provided' + }); + }); + } + + console.log((vld_id ? 'Updating VLD ' + vld_id : 'Creating VLD') + ' under NSR', nsr_id); + + var jsonData = { + vld: typeof(data) == 'string' ? JSON.parse(data) : data + }; + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + request({ + uri: utils.confdPort(api_server) + '/api/config/ns-instance-config/nsr/' + nsr_id + '/nsd/vld' + (vld_id ? '/' + vld_id : ''), + method: vld_id ? 'PUT' : 'POST', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData + }, function(error, response, body) { + if (utils.validateResponse('NSR.nsd.vld.create/update', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: (typeof(response.body) == 'string') ? JSON.parse(response.body) : response.body + }); + } + }); + }); +}; + +NSR.nsd.vld.update = NSR.nsd.vld.create; + +NSR.nsd.vld.delete = function(req) { + var api_server = req.query['api_server']; + var nsr_id = req.params.nsr_id; + var vld_id = req.params.vld_id; + + if (!api_server || !nsr_id || !vld_id) { + return new Promise(function(resolve, reject) { + return reject({ + statusCode: constants.HTTPS_RESPONSE_CODES.ERROR.INTERNAL_SERVER_ERROR, + errorMessage: 'API server/NSR id/VLD id not provided' + }); + }) + } + console.log('Deleting VLD', vld_id, 'for NSR id', nsr_id); + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, + { + 'Authorization': req.get('Authorization') + } + ); + + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/ns-instance-config/nsr/' + nsr_id + '/nsd/vld/' + vld_id, + method: 'DELETE', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false + }, function (error, response, body) { + if (utils.validateResponse('NSR.nsd.vld.delete', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode, + data: typeof response.body == 'string' ? JSON.parse(response.body):response.body + }); + } + }); + }); +} + +VNFR.get = function(req) { + var api_server = req.query["api_server"]; + var id = req.params.id; + var uri = utils.confdPort(api_server); + uri += APIVersion + '/api/operational/vnfr-catalog/vnfr' + (id ? '/' + id : '') + '?deep'; + var headers = _.extend({}, id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('VNFR.get', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + var returnData = id ? [data["vnfr:vnfr"]] : data.collection["vnfr:vnfr"]; + returnData.forEach(function(vnfr) { + vnfr['nfvi-metrics'] = buildNfviGraphs(vnfr.vdur); + vnfr['epa-params'] = epa_aggregator(vnfr.vdur); + vnfr['service-primitives-present'] = (vnfr['vnf-configuration'] && vnfr['vnf-configuration']['service-primitive'] && vnfr['vnf-configuration']['service-primitive'].length > 0) ? true : false; + }) + return resolve(returnData); + }; + }); + }); +} + +function buildNfviGraphs(VDURs, vnfrName){ + var temp = {}; + var toReturn = []; + APIConfig.NfviMetrics.map(function(k) { + + VDURs && VDURs.map(function(v,i) { + //Check for RIFT-12699: VDUR NFVI Metrics not fully populated + if (v["rw-vnfr:nfvi-metrics"] && v["rw-vnfr:nfvi-metrics"][k] && v["rw-vnfr:nfvi-metrics"][k].hasOwnProperty('utilization')) { + if(!temp[k]) { + temp[k] = { + title: '', + data: [] + }; + }; + try { + var data = v["rw-vnfr:nfvi-metrics"][k]; + var newData = {}; + newData.name = v.name ? v.name : v.id.substring(0,6); + newData.name = vnfrName ? vnfrName + ': ' + newData.name : newData.name; + newData.id = v.id; + //converts to perentage + newData.utilization = data.utilization * 0.01; + temp[k].data.push(newData); + temp[k].title = v["rw-vnfr:nfvi-metrics"][k].label; + } catch (e) { + console.log('Something went wrong with the VNFR NFVI Metrics. Check that the data is being properly returned. ERROR: ', e); + } + } + }); + if(temp[k]) { + toReturn.push(temp[k]); + } + }); + return toReturn; + } + + +//Cache NSR reference for VNFR +VNFR.cachedNSR = {}; +VNFR.getByNSR = function(req) { + var api_server = req.query["api_server"]; + var id = req.params.nsr_id; + var uri = utils.confdPort(api_server); + var reqClone = _.clone(req); + delete reqClone.params.id; + uri += APIVersion + '/api/operational/ns-instance-opdata/nsr/' + id + '?deep'; + var headers = _.extend({}, id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + if (VNFR.cachedNSR[id]) { + var data = VNFR.cachedNSR[id]; + var vnfrList = _.pluck(data["constituent-vnfr-ref"], 'vnfr-id'); + VNFR.get(reqClone).then(function(vnfrData) { + resolve(filterVnfrByList(vnfrList, vnfrData)); + }); + } else { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('VNFR.getByNSR', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + data = data["nsr:nsr"]; + //Cache NSR data with NSR-ID as + VNFR.cachedNSR[id] = data; + var vnfrList = _.pluck(data["constituent-vnfr-ref"], 'vnfr-id'); + var returnData = []; + VNFR.get(reqClone).then(function(vnfrData) { + resolve(filterVnfrByList(vnfrList, vnfrData)); + }); + }; + }); + } + }); +}; + +function filterVnfrByList(vnfrList, vnfrData) { + return vnfrData.map(function(vnfr) { + if (vnfrList.indexOf(vnfr.id) > -1) { + return vnfr; + } + }) +}; + +VLR.get = function(req) { + var api_server = req.query["api_server"]; + var id = req.params.id; + var uri = utils.confdPort(api_server); + uri += APIVersion + '/api/operational/vlr-catalog/vlr' + (id ? '/' + id : '') + '?deep'; + var headers = _.extend({}, id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('VLR.get', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + var returnData = id ? [data["vlr:vlr"]] : data.collection["vlr:vlr"]; + return resolve({ + data: returnData, + statusCode: response.statusCode + }); + }; + }); + }); +} + +RIFT.api = function(req) { + var api_server = req.query["api_server"]; + var uri = utils.confdPort(api_server); + var url = req.path; + return new Promise(function(resolve, reject) { + request({ + url: uri + url + '?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('RIFT.api', error, response, body, resolve, reject)) { + resolve(JSON.parse(response.body)) + }; + }) + }) +}; + +ComputeTopology.get = function(req) { + var api_server = req.query['api_server']; + var nsr_id = req.params.id; + var result = { + id: nsr_id, // node id + name: nsr_id, // node name to display + parameters: {}, // the parameters that can be used to determine size/color, etc. for the node + type: 'nsr', + children: [] // children for the node + }; + return new Promise(function(resolve, reject) { + var nsrPromise = new Promise(function(success, failure) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operational/ns-instance-opdata/nsr/' + nsr_id + '?deep', + method: 'GET', + headers: _.extend({}, + constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('ComputeTopology.get ns-instance-opdata/nsr/:id', error, response, body, success, failure)) { + var data; + var isString = typeof(response.body) == "string"; + if (isString && response.body == '') { + return success({}); + } + try { + data = isString ? JSON.parse(response.body) : response.body; + + var nsrNFVIMetricData = data["nsr:nsr"]["rw-nsr:nfvi-metrics"]; + result.parameters = nsrNFVIMetricData; + + result.name = data["nsr:nsr"]["name-ref"]; + + var nsrData = data["nsr:nsr"]["constituent-vnfr-ref"]; + success(nsrData); + } catch (e) { + console.log('Error parsing ns-instance-opdata for NSR ID', nsr_id, 'Exception:', e); + return failure() + } + }; + }); + }).then(function(data) { + + try { + // got NSR data + // now get VNFR data and populate the structure + var vnfrPromises = []; + + // Run separately to confirm that primary structure is populated before promise resolution takes over + // and starts modifying the data + data.forEach(function(vnfrObj) { + + var vnfrId = vnfrObj['vnfr-id']; + + // If anything needs to be added to result for each vnfrId, do it here + + vnfrPromises.push( + new Promise(function(success, failure) { + rp({ + uri: utils.confdPort(api_server) + APIVersion + '/api/operational/vnfr-catalog/vnfr/' + vnfrId + '?deep', + method: 'GET', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + resolveWithFullResponse: true + }, function(error, response, body) { + if (utils.validateResponse('ComputeTopology.get vnfr-catalaog/vnfr/:id', error, response, body, success, failure)) { + try { + var data = JSON.parse(response.body); + var returnData = data["vnfr:vnfr"]; + + // Push VNFRs in result + result.children.push({ + id: vnfrId, + name: returnData.name, + parameters: {}, // nfvi metrics here + children: [], + type: 'vnfr' + }); + + // Push VDURs in result + returnData.vdur.forEach(function(vdur) { + result.children[result.children.length - 1].children.push({ + id: vdur.id, + name: vdur.id, + parameters: {}, + type: 'vdur' + // children: [] + }); + }); + + return success(returnData.vdur); + } catch (e) { + console.log('Error parsing vnfr-catalog for VNFR ID', vnfrId, 'Exception:', e); + return failure(); + } + }; + }); + }) + ); + }); + + Promise.all(vnfrPromises).then(function(output) { + console.log('Resolved all VNFR requests successfully'); + // By now result must be completely populated. output is moot + + // Sort the results as there's no order to them from RIFT-REST + result.children.sort(sortByName); + + result.children.forEach(function(vnfr) { + vnfr.children.sort(sortByName); + }); + + resolve({ + statusCode: 200, + data: result + }); + }).catch(function(error) { + // Todo: Can this be made better? + // Right now if one of the southbound APIs fails - we just return what's populated so far in result + console.log('Problem with ComputeTopology.get vnfr-catalog/vnfr/:id', error, 'Resolving with partial data', result); + resolve({ + statusCode: 200, + data: result + }); + }); + } catch (e) { + // API came back with empty ns-instance-opdata response for NSR ID + // bail + console.log('Error iterating through ns-instance-opdata response for NSR ID', nsr_id, 'Exception:', e); + resolve({ + statusCode: 200, + data: result + }) + } + }, function(error) { + // failed to get NSR data. + // bail + resolve({ + statusCode: 200, + data: result + }); + }); + }); +}; + +NetworkTopology.get = function(req) { + var api_server = req.query["api_server"]; + var uri = utils.confdPort(api_server); + uri += APIVersion + '/api/operational/network?deep'; + var headers = _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false + }, function(error, response, body) { + if (utils.validateResponse('NetworkTopology.get', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + var returnData = transforms.transformNetworkTopology( + data["ietf-network:network"] + ); + resolve({ + statusCode: 200, + data: returnData + }); + }; + }); + }) +} + +VDUR.get = function(req) { + var api_server = req.query["api_server"]; + var vnfrID = req.params.vnfr_id; + var vdurID = req.params.vdur_id; + var uri = utils.confdPort(api_server); + uri += APIVersion + '/api/operational/vnfr-catalog/vnfr/' + vnfrID + '/vdur/' + vdurID + '?deep'; + var headers = _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('VDUR.get', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + var returnData = data["vdur:vdur"]; + return resolve(returnData); + }; + }); + }) +} + +CloudAccount.get = function(req) { + var api_server = req.query["api_server"]; + var uri = utils.confdPort(api_server); + uri += APIVersion + '/api/config/cloud/account?deep'; + var headers = _.extend({}, constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }); + return new Promise(function(resolve, reject) { + request({ + url: uri, + method: 'GET', + headers: headers, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('CloudAccount.get', error, response, body, resolve, reject)) { + var data = JSON.parse(response.body); + var returnData = data["collection"]["rw-cloud:account"]; + resolve({ + statusCode: 200, + data: returnData + }); + }; + }); + }); +} + + +// Config-Agent Account APIs +ConfigAgentAccount.get = function(req) { + var self = this; + + var api_server = req.query["api_server"]; + var id = req.params.id; + + if (!id) { + // Get all config accounts + return new Promise(function(resolve, reject) { + + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.collection, { + 'Authorization': req.get('Authorization') + }); + + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/operational/config-agent/account', + type: 'GET', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, + function(error, response, body) { + var data; + var statusCode; + if (utils.validateResponse('ConfigAgentAccount.get', error, response, body, resolve, reject)) { + try { + data = JSON.parse(response.body).collection['rw-config-agent:account']; + statusCode = response.statusCode; + } catch (e) { + console.log('Problem with "ConfigAgentAccount.get"', e); + var err = {}; + err.statusCode = 500; + err.errorMessage = { + error: 'Problem with "ConfigAgentAccount.get": ' + e.toString() + } + return reject(err); + } + + return resolve({ + statusCode: statusCode, + data: data + }); + }; + }); + }); + } else { + //Get a specific config account + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/operational/config-agent/account/' + id, + type: 'GET', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, + function(error, response, body) { + var data; + var statusCode; + if (utils.validateResponse('ConfigAgentAccount.get', error, response, body, resolve, reject)) { + try { + data = JSON.parse(response.body)['rw-config-agent:account']; + statusCode = response.statusCode; + } catch (e) { + console.log('Problem with "ConfigAgentAccount.get"', e); + var err = {}; + err.statusCode = 500; + err.errorMessage = { + error: 'Problem with "ConfigAgentAccount.get": ' + e.toString() + } + return reject(err); + } + + return resolve({ + statusCode: statusCode, + data: data + }); + } + }); + }); + } +}; + +ConfigAgentAccount.create = function(req) { + + var api_server = req.query["api_server"]; + var data = req.body; + + return new Promise(function(resolve, reject) { + var jsonData = { + "account": Array.isArray(data) ? data : [data] + }; + + console.log('Creating with', JSON.stringify(jsonData)); + + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/config/config-agent', + method: 'POST', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData, + }, function(error, response, body) { + if (utils.validateResponse('ConfigAgentAccount.create', error, response, body, resolve, reject)) { + return resolve({ + statusCode: response.statusCode, + data: JSON.stringify(response.body), + body:response.body.body + }); + }; + }); + }); +}; + +ConfigAgentAccount.update = function(req) { + + var api_server = req.query["api_server"]; + var id = req.params.id; + var data = req.body; + + return new Promise(function(resolve, reject) { + var jsonData = { + "rw-config-agent:account": data + }; + + console.log('Updating config-agent', id, ' with', JSON.stringify(jsonData)); + + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, + constants.HTTP_HEADERS.content_type.data, { + 'Authorization': req.get('Authorization') + }); + + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/config/config-agent/account/' + id, + method: 'PUT', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + json: jsonData, + }, function(error, response, body) { + if (utils.validateResponse('ConfigAgentAccount.update', error, response, body, resolve, reject)) { + return resolve({ + statusCode: response.statusCode, + data: JSON.stringify(response.body) + }); + }; + }); + }); +}; + +ConfigAgentAccount.delete = function(req) { + + var api_server = req.query["api_server"]; + var id = req.params.id; + + if (!id || !api_server) { + return new Promise(function(resolve, reject) { + console.log('Must specifiy api_server and id to delete config-agent account'); + return reject({ + statusCode: 500, + errorMessage: { + error: 'Must specifiy api_server and id to delete config agent account' + } + }); + }); + }; + + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/config/config-agent/account/' + id, + method: 'DELETE', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('ConfigAgentAccount.delete', error, response, body, resolve, reject)) { + return resolve({ + statusCode: response.statusCode, + data: JSON.stringify(response.body) + }); + }; + }); + }); +}; + + +DataCenters.get = function(req) { + var api_server = req.query["api_server"]; + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/operational/datacenters/cloud-accounts?deep', + method: 'GET', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('DataCenters.get', error, response, body, resolve, reject)) { + var returnData = {}; + try { + data = JSON.parse(response.body)['rw-launchpad:cloud-accounts']; + data.map(function(c) { + returnData[c.name] = c.datacenters; + }) + statusCode = response.statusCode; + } catch (e) { + console.log('Problem with "DataCenters.get"', e); + var err = {}; + err.statusCode = 500; + err.errorMessage = { + error: 'Problem with "DataCenters.get": ' + e.toString() + } + return reject(err); + } + return resolve({ + statusCode: response.statusCode, + data: returnData + }); + }; + }); + }); +} + +SSHkey.get = function(req) { + var api_server = req.query["api_server"]; + return new Promise(function(resolve, reject) { + var requestHeaders = {}; + _.extend(requestHeaders, + constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }); + request({ + url: utils.confdPort(api_server) + APIVersion + '/api/config/key-pair?deep', + method: 'GET', + headers: requestHeaders, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('SSHkey.get', error, response, body, resolve, reject)) { + var returnData = {}; + try { + returnData = JSON.parse(response.body)['nsr:key-pair']; + statusCode = response.statusCode; + } catch (e) { + console.log('Problem with "SSHkey.get"', e); + var err = {}; + err.statusCode = 500; + err.errorMessage = { + error: 'Problem with "SSHkey.get": ' + e.toString() + } + return reject(err); + } + return resolve({ + statusCode: response.statusCode, + data: returnData + }); + }; + }); + }); +} +SSHkey.delete = function(req) { + var api_server = req.query['api_server']; + var id = decodeURI(req.params.name); + console.log('Deleting ssk-key', id); + return new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/key-pair/' + id, + method: 'DELETE', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('SSHkey.delete', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + } + }); + }); +}; +SSHkey.post = function(req) { + var api_server = req.query['api_server']; + var data = req.body; + return new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/key-pair/', + method: 'POST', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + json: data, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('SSHkey.post', error, response, body, resolve, reject)) { + resolve({ + data: 'success', + statusCode: response.statusCode + }); + } + }); + }); +}; +SSHkey.put = function(req) { + var api_server = req.query['api_server']; + var data = req.body; + return new Promise(function(resolve, reject) { + request({ + uri: utils.confdPort(api_server) + APIVersion + '/api/config/key-pair/', + method: 'PUT', + headers: _.extend({}, constants.HTTP_HEADERS.accept.data, { + 'Authorization': req.get('Authorization') + }), + json: data, + forever: constants.FOREVER_ON, + rejectUnauthorized: false, + }, function(error, response, body) { + if (utils.validateResponse('SSHkey.put', error, response, body, resolve, reject)) { + resolve({ + statusCode: response.statusCode + }); + } + }); + }); +}; + +function sortByName(a, b) { + return a.name > b.name; +} + +module.exports.catalog = Catalog; +module.exports.nsr = NSR; +module.exports.vnfr = VNFR; +module.exports.vlr = VLR; +module.exports.rift = RIFT; +module.exports.computeTopology = ComputeTopology; +module.exports.networkTopology = NetworkTopology; +module.exports.config = Config; +module.exports.cloud_account = CloudAccount; +module.exports['config-agent-account'] = ConfigAgentAccount; +module.exports.rpc = RPC; +module.exports.data_centers = DataCenters; +module.exports.SSHkey = SSHkey;