--- /dev/null
+/*
+ *
+ * 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 _ = require('lodash');
+
+/**
+ * Merges vnfr["nfvi-metrics"] with nsr["nfvi-metrics"] into a format consumable by the UI LP and Record Cards
+ * @param {Array} vnfr vnfr nfvi metrics
+ * @param {Array} nsr nsr nfvi metrics
+ * @return {Array} Merged NSR nfvi metrics
+ */
+function mergeVnfrNfviMetrics(vnfr, nsr) {
+ for (var i = 0; i < vnfr.length; i ++) {
+ var title = vnfr[i].title;
+ var matched = false;
+ for (var j = 0; j < nsr.length; j++) {
+ if (nsr[j] && nsr[j].title == title) {
+ matched = true;
+ nsr[j].data = nsr[j].data.concat(vnfr[i].data).sort(function(a,b) {
+ return (a.name > b.name) ? 1 : -1;
+ });
+ break;
+ }
+ }
+ if (!matched) {
+ nsr.push({
+ title: title,
+ data: vnfr[i].data
+ });
+ }
+ }
+}
+
+function terminationPointValues (node) {
+ var tpids = [];
+ var attrs = { 'tp-id': [] };
+ var TERM_PT_KEY = 'ietf-network-topology:termination-point';
+ var TERM_PT_ATTR_KEY = 'ietf-l2-topology:l2-termination-point-attributes';
+
+ var node_id = node['node-id'];
+ node[TERM_PT_KEY].forEach(
+ function(elem, index, array) {
+ if ('tp-id' in elem) {
+ attrs['tp-id'].push(elem['tp-id'])
+ }
+ if (TERM_PT_ATTR_KEY in elem) {
+ for (var key in elem[TERM_PT_ATTR_KEY]) {
+ if (!(key in attrs)) {
+ attrs[key] = _.cloneDeep(elem[TERM_PT_ATTR_KEY][key]);
+ }
+ }
+ }
+ });
+ return {
+ 'node-id': node_id,
+ attrs: attrs
+ }
+}
+
+// Transforms one or more topologies into a collection of nodes, links
+// usable by D3.js
+function transformNetworkTopology(raw) {
+ var nodes = [];
+ var links = [];
+
+ var y = 0;
+ var id = 1;
+
+ var node_mapper = {};
+ var network_ids = [];
+
+ var networks = raw;
+ if ('collection' in raw) {
+ networks = raw.collection;
+ }
+ if ('ietf-network:network' in networks) {
+ networks = networks['ietf-network:network'];
+ }
+
+ // for each network in the array of networks
+ for (var net_index=0, tot_networks=networks.length; net_index < tot_networks; net_index++) {
+ var network = networks[net_index];
+ var network_id = networks[net_index]['network-id'];
+ if (network_ids.indexOf(network_id) == -1) {
+ network_ids.push(network_id);
+ }
+ var raw_nodes = network['node'] || [];
+ var x = 0;
+ for (var index=0, tot=raw_nodes.length; index < tot; index++) {
+ var termination_point = [];
+ var new_node = {
+ id: id,
+ // TODO: make short name,
+ name: raw_nodes[index]['node-id'],
+ full_name: raw_nodes[index]['node-id'],
+ network: network_id,
+ x: x,
+ y: y,
+ attr: terminationPointValues(raw_nodes[index]).attrs
+ };
+ nodes.push(new_node);
+ // What do wse do if the name is already collected
+ node_mapper[new_node.name] = nodes.length-1;
+ x += 20;
+ id++;
+ }
+
+ var raw_links = network['ietf-network-topology:link'];
+ if (raw_links) {
+ for (var index=0, tot=raw_links.length; index < tot; index++) {
+ var source_name = raw_links[index]['source']['source-node'];
+ var dest_name = raw_links[index]['destination']['dest-node'];
+ var new_link = {
+ source: node_mapper[source_name],
+ target: node_mapper[dest_name]
+ };
+ links.push(new_link);
+ }
+ }
+ // prep for next network
+ y += 20;
+ }
+
+ // D3 is expecting array indexes of the nodes for the links
+ // Now for the links to find the nodes
+
+ return {
+ nodes: nodes,
+ links: links,
+ network_ids: network_ids
+ };
+}
+
+
+module.exports = {
+ transformNetworkTopology: transformNetworkTopology,
+ mergeVnfrNfviMetrics: mergeVnfrNfviMetrics
+}