2 * @copyright 2017 highstreet technologies GmbH and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at {@link http://www.eclipse.org/legal/epl-v10.html}
10 if (!String.prototype.toHumanReadableTimeFormat) {
11 String.prototype.toHumanReadableTimeFormat = function () {
12 return this.replace(/T/g, ' ').replace(/Z/g, ' UTC').replace(/\+00:00/g, ' UTC');
16 if (!String.prototype.base64ToHex) {
17 String.prototype.base64ToHex = function () {
20 for ( i = 0; i < raw.length; i++ ) {
21 var _hex = raw.charCodeAt(i).toString(16)
22 result.push('0x' + ( _hex.length === 2 ? _hex:'0' + _hex));
24 return result.join(' ');
28 if (!String.prototype.contains) {
30 * An extension to String, which checks whether another string is contained.
31 * @param {string} find A string to be checked, whether it is contained in 'this'.
32 * @return {boolean} True, if 'this' contains param 'find', otherwise false.
34 String.prototype.contains = function (find) {
35 return this.indexOf(find) > -1;
39 if (!String.prototype.format) {
41 * An extension to String, which replaces certain patterns by arguments.
42 * @see {@link https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format|javascript-equivalent-to-printf-string-format}
43 * @return {string} Formated string.
45 String.prototype.format = function () {
47 return this.replace(/{(\d+)}/g, function (match, number) {
48 return typeof args[number] !== 'undefined' ? args[number] : match
54 if (!String.prototype.replaceAll) {
56 * An extension to String, which replaces certain patterns by arguments.
57 * @see {@link https://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript|how-to-replace-all-occurrences-of-a-string-in-javascript}
58 * @param {string} find - The string which should be replaced.
59 * @param {string} replace - The string which should replace 'find'.
60 * @return {string} String where 'find' is replaced by 'replace'.
62 String.prototype.replaceAll = function (find, replace) {
63 return this.replace(new RegExp(find, 'g'), replace);
67 if (!Array.prototype.contains) {
69 * An extension to Array checking whether an array of primitive types contains a given value.
70 * @param {string|number|boolean|null|undefined} find An object which should be removed from the array.
71 * @return {boolean} True, if 'this' contains param 'find', otherwise false..
73 Array.prototype.contains = function (find) {
74 return this.indexOf(find) > -1;
78 if (!Array.prototype.clean) {
80 * An extension to Array removing defined values from an array.
81 * @see {@link https://gist.github.com/waynegraham/3684627|Array.clean()}
82 * @param {Object} deleteValue An object which should be removed from the array.
83 * @return {Array} An array without 'deleteValue'.
85 Array.prototype.clean = function (deleteValue) {
86 for (var i = 0; i < this.length; i++) { // TODO swtich to .map() ?
87 if (this[i] === deleteValue) {
97 ['app/mwtnCommons/mwtnCommons.module'],
98 function (mwtnCommonsApp) {
100 mwtnCommonsApp.register.controller('mwtnFooterController', ['$scope', function ($scope) {
102 $scope.prefix = 'ONF Wireless for OpenDaylight Boron-SR3';
105 mwtnCommonsApp.register.directive('mwtnFooter', function () {
108 controller: 'mwtnFooterController',
110 templateUrl: 'src/app/mwtnCommons/templates/mwtnFooter.tpl.html'
114 mwtnCommonsApp.register.controller('openConfigViewController', ['$scope', '$uibModalInstance', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog', 'valueData',
115 function ($scope, $uibModalInstance, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog, data) {
118 var COMPONENT = 'openConfigViewController';
120 $scope.getType = $mwtnGlobal.getType;
121 $scope.spec = data.spec;
122 $mwtnCommons.getConditionalPackagePart($scope.spec).then(function (success) {
124 var getControlType = function(type) {
138 var message = 'Check control type for ' + type;
139 $mwtnLog.warning({ component: COMPONENT, message: message });
144 success.layerProtocol = $scope.spec.layerProtocolId;
145 $scope.configuredData = success;
146 $scope.newData = $scope.configuredData[$scope.spec.partId];
148 $scope.viewData = $mwtnGlobal.getViewData($scope.configuredData[$scope.spec.partId], $scope.ne);
149 $mwtnDatabase.getSchema().then(function(schema){
151 var clone = JSON.parse(JSON.stringify($scope.viewData));
152 var keys = Object.keys(clone).map(function(key){
153 if ($mwtnGlobal.getType(key) !== 'string') {
154 console.log('key', key);
157 var item = clone[key];
160 var message = 'No schema information for ' + key;
161 console.error(key, schema[key]);
162 $mwtnLog.warning({ component: COMPONENT, message: message });
163 item['order-number'] = $mwtnCommons.getOrderNumber(97, item);
164 item.description = 'No description available.';
168 if (schema[key].controlType === undefined) {
169 item.controlType = getControlType(item.type);
171 item.controlType = schema[key].controlType;
173 item.unit = schema[key].unit;
174 item.description = schema[key].description;
175 item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item);
176 if (item.description === undefined || item.description === '') {
177 item.description = 'No description available.';
179 // hide complex types for now -> TODO
180 if (item.type === 'array' || item.type === 'object') {
181 item.visible = false;
184 }).sort(function(a,b){
185 if (clone[a]['order-number'] < clone[b]['order-number']) return -1;
186 if (clone[a]['order-number'] > clone[b]['order-number']) return 1;
188 }).map(function(key){
189 ordered[key] = clone[key];
191 $scope.viewData = ordered;
196 }, function (error) {
197 $scope.configuredData = undefined;
198 $mwtnLog.error({ component: COMPONENT, message: 'Requesting conditional package of ' + JSON.stringify($scope.spec) + ' failed!' });
201 $scope.ok = function () {
202 $scope.processing = true;
203 Object.keys($scope.viewData).map(function(key){
204 $scope.newData[key] = $scope.viewData[key].value;
207 $mwtnCommons.setConditionalPackagePart($scope.spec, $scope.newData).then(function(success){
208 $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'};
209 $scope.processing = false;
211 $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'};
212 $scope.processing = false;
213 $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)});
218 $scope.cancel = function () {
219 $uibModalInstance.close($scope.newData);
224 mwtnCommonsApp.register.controller('mwtnJsonViewerController', ['$scope', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnDatabase', '$mwtnLog',
225 function ($scope, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnDatabase, $mwtnLog) {
227 var COMPONENT = 'mwtnJsonViewerController';
228 $scope.getType = $mwtnGlobal.getType;
231 $scope.replace = false;
232 if ($scope.path && $scope.path.endsWith('-configuration') ) {
233 $scope.replace = true;
235 $scope.viewData = $mwtnGlobal.getViewData($scope.data, $scope.ne);
236 var path = [undefined, undefined, undefined];
238 path = $scope.path.split($mwtnCommons.separator);
241 nodeId: $scope.networkElement,
242 revision: '2017-03-20',
245 layerProtocolId: path[1],
250 $scope.openConfigView = function(){
251 var modalInstance = $uibModal.open({
253 ariaLabelledBy: 'modal-title',
254 ariaDescribedBy: 'modal-body',
255 templateUrl: 'src/app/mwtnCommons/templates/openConfigView.html',
256 controller: 'openConfigViewController',
259 valueData: function () {
260 return {spec:$scope.spec};
264 modalInstance.result.then(function(object) {
265 // update fetch new data from ODL
266 $mwtnCommons.getPacParts($scope.spec).then(function(success){
267 // intermedite step to display something, even processing fails or takes time
268 $scope.viewData = $mwtnGlobal.getViewData(success[$scope.spec.partId], $scope.ne);
269 // now the nice way ;)
270 $scope.viewData = processData($scope.schema);
279 $scope.myClipboard = {
282 getJson: function () {
283 return JSON.stringify(this.data, null, ' ');
285 copyToClipboard: function () {
286 var message = 'Copied to clipboard! ' + this.getJson();
287 $mwtnLog.info({ component: COMPONENT, message: message });
289 error: function (err) {
290 $mwtnLog.error({ component: COMPONENT, message: err });
294 var processData = function(schema) {
296 var clone = JSON.parse(JSON.stringify($scope.viewData));
297 var keys = Object.keys(clone).map(function(key){
298 if ($mwtnGlobal.getType(key) !== 'string') {
299 console.log('key', key);
302 var item = clone[key];
304 var message = 'No schema information for ' + key;
305 $mwtnLog.warning({ component: COMPONENT, message: message });
306 item['order-number'] = $mwtnCommons.getOrderNumber(97, item);
307 item.description = 'No description available.';
311 item.unit = schema[key].unit;
312 item.description = schema[key].description;
313 item['order-number'] = $mwtnCommons.getOrderNumber(schema[key]['order-number'], item);
314 if (item.description === undefined || item.description === '') {
315 item.description = 'No description available.';
318 }).sort(function(a,b){
319 if (clone[a]['order-number'] < clone[b]['order-number']) return -1;
320 if (clone[a]['order-number'] > clone[b]['order-number']) return 1;
322 }).map(function(key){
323 ordered[key] = clone[key];
326 if (Object.keys(ordered).length === 0) {
327 $scope.info = 'An empty object is displayed. Please check if the NetConf server has send an empty object.';
332 $mwtnDatabase.getSchema().then(function(schema){
333 $scope.schema = schema;
334 $scope.viewData = processData($scope.schema);
341 mwtnCommonsApp.register.directive('mwtnJsonViewer', function () {
347 ne: '=', // flag if ne class
351 controller: 'mwtnJsonViewerController',
353 templateUrl: 'src/app/mwtnCommons/templates/mwtnJsonViewer.tpl.html'
357 mwtnCommonsApp.register.controller('showGridCellDetailController', ['$scope', '$uibModalInstance', '$mwtnGlobal', 'valueData',
358 function ($scope, $uibModalInstance, $mwtnGlobal, valueData) {
360 $scope.networkElement = valueData.networkElement;
361 $scope.path = valueData.path;
362 $scope.type = $mwtnGlobal.getType(valueData.value);
363 $scope.value = valueData.value;
364 // $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions));
365 // $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader;
367 console.log('valueData', JSON.stringify(valueData));
369 // $scope.ok = function () {
370 // $scope.processing = true;
371 // $mwtnCommons.setPacPartLists($scope.path, $scope.listData).then(function(success){
372 // $scope.applied = {text: 'Applied: ' + new Date().toISOString(), class:'mwtnSuccess'};
373 // $scope.processing = false;
374 // }, function(error){
375 // $scope.applied = {text: 'Error: ' + new Date().toISOString(), class:'mwtnError'};
376 // $scope.processing = false;
377 // $mwtnLog.error({component: COMPONENT, message: JSON.stringify(error)});
382 $scope.cancel = function () {
383 $uibModalInstance.dismiss('cancel');
388 mwtnCommonsApp.register.controller('mwtnGridController', ['$scope', '$filter', '$uibModal', '$mwtnGlobal', '$mwtnCommons', '$mwtnLog',
389 function ($scope, $filter, $uibModal, $mwtnGlobal, $mwtnCommons, $mwtnLog) {
391 var COMPONENT = 'mwtnGridController';
395 var data = JSON.parse(JSON.stringify($scope.data));
397 var message = 'No data to be displayed!";'
398 $mwtnLog.info({ component: COMPONENT, message: message });
399 data = [{'message':message}];
402 if ($mwtnGlobal.getType(data) !== 'array') {
403 var message = 'Data must be of type "array"!';
404 $mwtnLog.info({ component: COMPONENT, message: message });
405 data = [{'message':message}];
408 if (data.length === 0) {
409 var message = 'Data list must have at least one entry!';
410 $mwtnLog.info({ component: COMPONENT, message: message });
411 data = [{'message':message}];
414 if ($mwtnGlobal.getType(data[0]) !== 'object') {
415 data = data.map(function(item){
416 return {value: item};
420 $scope.gridOptions = JSON.parse(JSON.stringify($mwtnCommons.gridOptions));
421 $scope.highlightFilteredHeader = $mwtnCommons.highlightFilteredHeader;
423 $scope.getTableHeight = function() {
425 var headerHeight = 40;
427 var rowCount = $scope.gridOptions.data.length + 2;
428 var count = rowCount;
429 if (rowCount > maxCount) {
434 height: (count * rowHeight + headerHeight) + 'px'
438 var getCellTemplate = function(field) {
439 var object = ['transmission-mode-list', 'performance-data'];
440 if (object.contains(field)) {
441 console.warn(JSON.stringify(field));
442 return ['<div class="ui-grid-cell-contents">',
443 '<i class="fa fa-info-circle" aria-hidden="true"',
444 ' ng-click="grid.appScope.show(grid.getCellValue(row, col))"',
445 ' style="color: rgb(66, 139, 202); cursor: pointer;"></i> ',
446 '{{grid.getCellValue(row, col)}}</div>'].join('');
448 return '<div class="ui-grid-cell-contents">{{grid.getCellValue(row, col)}}</div>';
450 $scope.show = function(value){
451 // console.warn(JSON.stringify(value));
452 var type = $mwtnGlobal.getType(value);
453 // if (type === 'object')
454 var modalInstance = $uibModal.open({
456 ariaLabelledBy: 'modal-title',
457 ariaDescribedBy: 'modal-body',
458 templateUrl: 'src/app/mwtnCommons/templates/showGridCellDetail.html',
459 controller: 'showGridCellDetailController',
462 valueData: function () {
463 return {networkElement: $scope.networkElement, path:$scope.path, value:value};
468 var enable = data.length > 10;
469 $scope.gridOptions.columnDefs = Object.keys(data[0]).map(function (field) {
470 var type = $mwtnGlobal.getType(data[0][field]);
471 var labelId = $mwtnGlobal.getLabelId(field);
472 var displayName = $filter('translate')(labelId);
473 var visible = $mwtnGlobal.getVisibilityOf(field);
474 if (labelId.contains('$$') || labelId === 'MWTN_SPEC') {
480 displayName: displayName,
482 enableFiltering: enable,
483 headerCellClass: $scope.highlightFilteredHeader,
484 cellTemplate: getCellTemplate(field),
489 if ($scope.gridOptions.data.length < 10) {
490 $scope.gridOptions.minRowsToShow = data.length; // 10 is default
492 $scope.gridOptions.data = data;
493 // .sort(function(a, b){
494 // if (a.type === 'object') return -1;
495 // if (a.type === 'array' ) return -2;
499 $scope.myClipboard = {
502 getJson: function () {
503 return JSON.stringify(this.data, null, ' ');
505 copyToClipboard: function () {
506 var message = 'Copied to clipboard! ' + this.getJson();
507 $mwtnLog.info({ component: COMPONENT, message: message });
509 error: function (err) {
510 $mwtnLog.error({ component: COMPONENT, message: err });
515 mwtnCommonsApp.register.directive('mwtnGrid', function () {
523 controller: 'mwtnGridController',
525 templateUrl: 'src/app/mwtnCommons/templates/mwtnGrid.tpl.html'
529 mwtnCommonsApp.register.controller('mwtnSelectNetworkElementController', ['$scope', '$state','$mwtnCommons', function ($scope, $state, $mwtnCommons) {
533 * A function which scanns the mountpoints for connected network-elements and adds it to networkElements.
534 * @param {{"onfAirInterfaceRevision": string, "node-id": string, "netconf-node-topology:connection-status": string}[]} mountpoints An array of mountpoints from OpenDaylight.
536 var initNodeList = function (mountpoints) {
537 $scope.loading = true;
538 $scope.mountPoints = mountpoints;
539 $scope.networkElements = mountpoints.filter(function (mountpoint) {
540 return mountpoint['netconf-node-topology:connection-status'] === 'connected';
541 }).map(function (mountpoint) {
542 return { id: mountpoint['node-id'], revision: mountpoint.onfAirInterfaceRevision };
543 }).sort(function (a, b) {
544 if (a.id < b.id) return -1;
545 if (a.id > b.id) return 1;
550 $scope.networkElement = undefined;
551 if ($state.params.nodeId) {
555 console.error('nodeId', $state.params.nodeId);
557 // select one of the nodes
558 /* dont do it in field applications!!!!
559 var select = parseInt(Math.random() * $scope.networkElements.length);
560 if (select !== undefined && $scope.networkElements[select]) {
561 $scope.networkElement = $scope.networkElements[select].id;
562 $scope.mountpoint = $scope.mountPoints.filter(function (mountpoint) {
563 return mountpoint['node-id'] === $scope.networkElement;
567 $scope.loading = false;
570 $mwtnCommons.getMountPoints().then(function (mountpoints) {
571 initNodeList(mountpoints);
572 }, function (error) {
573 $scope.networkElements = [];
577 mwtnCommonsApp.register.directive('mwtnSelectNetworkElement', function () {
580 controller: 'mwtnSelectNetworkElementController',
582 templateUrl: 'src/app/mwtnCommons/templates/mwtnSelectNetworkElement.tpl.html'
586 // mwtnCommonsApp.register.factory('$notifying', function($rootScope) {
588 // subscribe: function(scope, callback) {
589 // var handler = $rootScope.$on('notifying-service-event', callback);
590 // scope.$on('$destroy', handler);
593 // notify: function(text) {
594 // $rootScope.$emit('notifying-service-event', text);
599 mwtnCommonsApp.register.factory('$mwtnGlobal', function () {
603 * Returns false, if parameter/attribute should be in visible
604 * @param {string} field - a json to be analyzed
605 * @return {boolean} true, if the parameter should be visible, otherwise false.
607 service.getVisibilityOf = function(field) {
608 var hide = ['name-binding', 'object-class'];
609 return !hide.contains(field);
613 * Returns the (json) type of a value
614 * @param {*} value - a json to be analyzed
615 * @return type of json
617 service.getType = function (value) {
618 var result = typeof value;
619 if (result === 'object' && JSON.stringify(value).substring(0, 1) === '[') {
621 } else if (result === 'object' && value === null) {
623 } else if (result === 'object' && value['value-name'] && value.value) {
624 result = 'name-value';
629 service.getLabelId = function (string) {
630 return ['mwtn', string].join('_').replaceAll('-', '_').toUpperCase();
633 var isIntesting = function(key) {
634 var instesting = ['name', 'local-id', 'label', 'extension', 'physical-port-reference', 'lp', 'server-ltp', 'client-ltp', 'layer-protocol-name'];
635 return instesting.contains(key);
638 * Returns a simplfies json for display
639 * @param {*} data - the json to be simplified
640 * @param {boolean} ne - control parameter for finetuning
641 * @return a simplfied json for display
643 service.getViewData = function (data, ne) {
644 var viewData = JSON.parse(JSON.stringify(data));
646 viewData.ltp = undefined;
647 viewData.fd = undefined;
649 Object.keys(viewData).map(function (key) {
650 var type = service.getType(viewData[key]);
652 value: viewData[key],
654 labelId: service.getLabelId(key),
655 visible: service.getVisibilityOf(key)
657 viewData[key] = viewValue;
658 if (type === 'array') {
659 if (key === 'extension') {
660 viewValue.value.map(function (item) {
661 viewData[item['value-name']] = { value: item.value, type: 'string', labelId:service.getLabelId(item['value-name']) };
663 viewData[key] = undefined;
664 } else if (viewValue.value.length === 1 && isIntesting(key)) {
665 // console.warn(key, JSON.stringify(viewData[key]));
666 var valueType = service.getType(viewValue.value[0]);
667 viewData[key].value = viewValue.value[0];
668 viewData[key].type = valueType;
670 if (valueType === 'object') {
671 viewData[key].value = service.getViewData(viewValue.value);
672 } else if (valueType === 'name-value') {
673 viewData[key].value = viewValue.value.value;
674 //viewData[key].type = 'string';
676 } else if (type === 'object') {
677 viewData[key].value = service.getViewData(viewValue.value);
687 * Process an array of data synchronously.
688 * Please see https://gist.github.com/KevinTCoughlin/6901825
689 * @param {Array} data An array of data.
690 * @param {function} processData A function that processes an item of data.
691 * Signature: function(item, i, callback), where {@code item} is the i'th item,
692 * {@code i} is the loop index value and {@code calback} is the
693 * parameterless function to call on completion of processing an item.
694 * @param {function} done A callback function indecating that all items are processed.
696 var doSynchronousLoop = function (data, processData, done) {
697 if (data && data.length > 0) {
698 var loop = function (data, i, processData, done) {
699 processData(data[i], i, function () {
700 if (++i < data.length) {
701 loop(data, i, processData, done);
707 loop(data, 0, processData, done);
713 mwtnCommonsApp.register.factory('$mwtnCommons', function ($http, $q, $mwtnGlobal, $mwtnLog, $mwtnDatabase, LogicalTerminationPoint, PtpClock) {
715 var COMPONENT = '$mwtnCommons';
718 base: window.location.origin + "/restconf/",
720 'sdn-controller': [],
722 layerProtocolNameOrder: {
733 service.getOrderNumber = function(proposal, item){
734 var result = proposal;
735 if (item.type === 'array') {
737 } else if (item.type === 'object') {
739 } else if (item.labelId === 'MWTN_LOCAL_ID') {
741 } else if (item.labelId === 'MWTN_LABEL') {
743 } else if (item.labelId === 'MWTN_NAME') {
745 } else if (item.labelId === 'MWTN_UUID') {
752 * A function to get the global-identifier of a condtional package subClass by a specifcation object of such subClass and a local-name.
753 * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass.
754 * @param {string} local-name (e.g. current-problems)
755 * @return {string} globel-identifier of a conditional packages subClass (e.g. 'air-interface-diversity-current-problems')
757 service.getPartGlobalId = function (spec, localName) {
758 var address = spec.pacId.split(':');
759 var module = address[0];
760 var pacName = address[1];
762 // check for unexpected issues
764 console.error('not module', module, JSON.stringify(spec));
768 console.error('not pacName', pacName, JSON.stringify(spec));
771 if (!service.modules[module]) {
772 console.error('not service.modules[module]', service.modules[module], JSON.stringify(spec));
775 if (!service.modules[module][pacName]) {
776 console.error('not service.modules[module][pacName]', service.modules[module][pacName], JSON.stringify(spec));
779 if (!service.modules[module]) {
780 console.error('not ervice.modules[module][pacName][subClass]', service.modules[module][pacName][subClass], JSON.stringify(spec));
784 return Object.keys(service.modules[module][pacName]).filter(function (subClass) {
785 return service.modules[module][pacName][subClass]['local-name'] === localName;
786 }).map(function (subClass) {
787 return service.modules[module][pacName][subClass].name;
793 * A function to get the local-name of a condtional package subClass by a specifcation object of such subClass.
794 * @param {{pacId: string, layerProtocolId: string, partId:string}} spec - Specification object of a conditional package subclass
795 * @return {string} local-name of a conditional packages subClass (e.g. 'current-problems')
797 service.getPartLocalId = function (spec) {
799 Object.keys(service.modules).map(function (module) {
800 Object.keys(service.modules[module]).filter(function (pacName) {
801 return spec.pacId === [module, pacName].join(':') && service.modules[module][pacName][spec.partId].name === spec.partId;
802 }).map(function (pacName) {
803 result = service.modules[module][pacName][spec.partId]['local-name'];
809 var init = function () {
810 var deferred = $q.defer();
811 var databaseRequest = {
812 base: $mwtnDatabase.base,
814 docType: 'sdn-controller',
820 $mwtnDatabase.genericRequest(databaseRequest).then(function (success) {
821 // console.log('sc', JSON.stringify(success.data.hits.hits));
822 service['sdn-controller'] = success.data.hits.hits;
823 $mwtnDatabase.getModules().then(function (success) {
824 service.modules = success;
825 }, function (error) {
826 service.modules = [];
827 console.error('modules', JSON.stringify(error));
828 deferred.reject(error);
831 }, function (error) {
832 service['sdn-controller'] = [];
833 console.error('sc', JSON.stringify(error));
834 deferred.reject(error);
837 return deferred.promise;
840 service.getMainConroller = function () {
841 var deferred = $q.defer();
842 if (service['sdn-controller'].length === 0) {
843 init().then(function (success) {
844 service['sdn-controller'].map(function (controller) {
847 deferred.resolve(result);
848 }, function (error) {
849 deferred.reject(error);
852 service['sdn-controller'].map(function (controller) {
855 deferred.resolve(result);
857 return deferred.promise;
860 var createStream = function (streamName, callback) {
861 service.getMainConroller().then(function (success) {
862 var src = success._source;
864 if (ip === 'localhost') {
865 ip = service.base.split('//')[1].split(':')[0];
867 var url = [src['transport-protocol'], '://', ip, ':', src.port, '/restconf/streams/stream/', streamName].join('');
872 $http(request).then(function (response) {
873 // console.log(response.headers('Location'));
874 callback(response.headers('Location'));
875 }, function errorCallback(response) {
876 console.error(JSON.stringify(response));
879 }, function (error) {
880 console.error('mainController', error);
885 service.getMwtnWebSocketUrl = function () {
886 var deferred = $q.defer();
887 service.getMainConroller().then(function (success) {
889 var protocol = window.location.protocol.replace(/http/g, 'ws');
890 var host = window.location.hostname;
891 var user = window.localStorage.odlUser;
892 if (user === undefined) user = 'admin' // ODL default user
893 var pw = window.localStorage.odlPass;
894 if (pw === undefined) pw = 'admin' // ODL default password
896 var url = [protocol, '//', user, ':',pw, '@', host, ':8085/websocket'].join('');
897 console.info('url', url);
899 deferred.resolve(url);
900 }, function (error) {
901 console.error('mainController', error);
902 deferred.reject(error);
904 return deferred.promise;
907 service.formatTimeStamp = function (t) {
908 // t: time in ONF format, e.g. 20161020081633.7Z, 20161025235946.0+0000
909 if (t.length !== '20161020081633.7Z'.length || t.length !== '20161025221822.0+0000') {
910 if (t.endsWith('Z') || t.endsWith('+0000')) {
911 if (!t.contains('-')) {
912 return [[t.slice(0, 4), t.slice(4, 6), t.slice(6, 8)].join('-'),
913 [t.slice(8, 10), t.slice(10, 12), t.slice(12, 16)].join(':')].join(' ') + ' UTC';
917 // console.info('check', t);
918 // return new Date().toISOString().toHumanReadableTimeFormat();
919 return t.toHumanReadableTimeFormat();
922 service.formatData = function (event) {
923 var deferred = $q.defer();
925 var x2js = new X2JS();
926 var jsonObj = x2js.xml_str2json(event.data);
927 // console.info('a', service.getType(jsonObj), JSON.stringify(jsonObj));
928 if (jsonObj === null || service.getType(jsonObj) !== 'object') {
929 deferred.reject('ignore');
931 notifType = Object.keys(jsonObj)[0];
932 var formated = jsonObj[notifType];
933 formated.timeStamp = service.formatTimeStamp(formated.timeStamp);
934 formated.notifType = notifType;
935 formated.myMessage = 'someMessage';
936 formated.time = new Date().toISOString();
937 deferred.resolve(formated);
940 return deferred.promise;
943 service.getData = function (callback) {
944 return callback('$mwtnCommons registered to this application.');
947 service.getType = $mwtnGlobal.getType;
948 service.getViewData = $mwtnGlobal.getViewData;
950 service.getLayer = function (pacId) {
951 console.warn('@depricated', '$mwtnCommons.getLayer()');
954 case 'air-interface':
957 case 'pureEthernetStructure':
958 case 'hybridStructure':
959 case 'pure-ethernet-structure':
960 case 'hybrid-structure':
963 case 'ethernetContainer':
964 case 'ethernet-container':
967 case 'tdm-container':
975 service.parts = ['Capability', 'Configuration', 'Status', 'CurrentProblems', 'CurrentPerformance', 'HistoricalPerformances'];
977 service.getLabelId = function (key, callback) {
978 return callback(['mwtn', key].join('_').toUpperCase());
981 service.checkModules = function (names) {
982 // accepts a list of module names and
983 // attempts to load them, in order.
984 // attempt to load the module into m
987 names.map(function (name) {
989 m = angular.module(name);
992 result[name] = false;
998 service.mount = function (mp) {
999 // mp: mounting point
1000 var url = [service.base, service.url.mount(mp.name)].join('');
1003 '<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">',
1004 '<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">prefix:sal-netconf-connector</type>',
1006 '<address xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{1}</address>',
1007 '<port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{2}</port>',
1008 '<username xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{3}</username>',
1009 '<password xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">{4}</password>',
1010 '<tcp-only xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">false</tcp-only>',
1011 '<event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1012 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>',
1013 ' <name>global-event-executor</name>',
1014 '</event-executor>',
1015 '<binding-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1016 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>',
1017 ' <name>binding-osgi-broker</name>',
1018 '</binding-registry>',
1019 '<dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1020 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>',
1021 ' <name>dom-broker</name>',
1023 '<client-dispatcher xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1024 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>',
1025 ' <name>global-netconf-dispatcher</name>',
1026 '</client-dispatcher>',
1027 '<processing-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1028 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>',
1029 ' <name>global-netconf-processing-executor</name>',
1030 '</processing-executor>',
1031 '<keepalive-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">',
1032 ' <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:scheduled-threadpool</type>',
1033 ' <name>global-netconf-ssh-scheduled-executor</name>',
1034 '</keepalive-executor>',
1035 '</module>' ].join('').format(mp.name, mp.ipaddress, mp.port, mp.username, mp.password); */
1037 '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
1038 ' <node-id>{0}</node-id>',
1039 ' <host xmlns="urn:opendaylight:netconf-node-topology">{1}</host>',
1040 ' <port xmlns="urn:opendaylight:netconf-node-topology">{2}</port>',
1041 ' <username xmlns="urn:opendaylight:netconf-node-topology">{3}</username>',
1042 ' <password xmlns="urn:opendaylight:netconf-node-topology">{4}</password>',
1043 ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
1045 ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
1046 ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
1047 ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
1048 ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
1049 ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
1050 ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
1052 ' <!-- keepalive-delay set to 0 turns off keepalives-->',
1053 ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
1054 '</node>'].join('').format(mp.name, mp.ipaddress, mp.port, mp.username, mp.password);
1060 'Content-Type': 'application/xml',
1061 'Accept': 'application/xml'
1065 var deferred = $q.defer();
1066 $http(request).then(function (success) {
1067 deferred.resolve(success.data);
1068 }, function (error) {
1069 $mwtnLog.error({ component: '$mwtnCommons.mount', message: JSON.stringify(error.data) });
1070 deferred.reject(error);
1072 return deferred.promise;
1076 * A promise to unmount netconf devices the old way from OpenDaylight Lithium.
1077 * This is needed in case Netconf devices from 3rd ONF Wireless PoC were mounted.
1078 * @param {string} nodeId - The mountpoint identifier which should be unmounted the old way.
1080 var unmountDeprecated = function (nodeId) {
1081 var url = [service.base,
1082 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/',
1088 var deferred = $q.defer();
1089 $http(request).then(function (success) {
1090 $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId });
1091 deferred.resolve(success.data);
1092 }, function (error) {
1093 $mwtnLog.info({ component: '$mwtnCommons.unmount', message: JSON.stringify(error.data) });
1094 deferred.reject(error);
1096 return deferred.promise;
1100 * A promise to unmount netconf devices from OpenDaylight Beryllium and higher.
1101 * @param {string} nodeId - The mountpoint identifier which unmounted/disconnected from OpenDaylight.
1103 service.unmount = function (nodeId) {
1104 var url = [service.base, service.url.unmount(nodeId)].join('');
1109 var deferred = $q.defer();
1110 $http(request).then(function (success) {
1111 $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId });
1112 deferred.resolve(success.data);
1113 }, function (error) {
1115 unmountDeprecated(nodeId).then(
1116 function (success) {
1117 $mwtnLog.info({ component: COMPONENT, message: 'Mounting Point deleted: ' + nodeId });
1118 deferred.resolve(success.data);
1121 $mwtnLog.info({ component: '$mwtnCommons.unmount', message: JSON.stringify(error.data) });
1122 deferred.reject(error);
1126 return deferred.promise;
1129 service.getPacParts = function (spec) {
1130 var errorMsg = { info: 'No data received' };
1131 var deferred = $q.defer();
1132 switch (spec.pacId) {
1134 service.getActualNetworkElement(spec.nodeId, spec.revision).then(function (success) {
1135 deferred.resolve(success);
1136 }, function (error) {
1137 $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!' });
1138 deferred.reject(error);
1142 service.getPtpClockData(spec.nodeId, spec.revision).then(function (success) {
1143 deferred.resolve(success);
1144 }, function (error) {
1145 $mwtnLog.error({ component: COMPONENT, message: 'Requesting clock for ' + spec.nodeId + ' failed!' });
1149 case 'forwardingDomain':
1150 console.warn('fd', JSON.stringify(spec));
1151 service.getForwardingDomain(spec.nodeId, 'eth-switch').then(function (success) {
1152 deferred.resolve(success);
1153 }, function (error) {
1154 $mwtnLog.error({ component: COMPONENT, message: 'Requesting forwarding domain for ' + spec.nodeId + ' failed!' });
1155 deferred.reject(error);
1160 switch (spec.revision) {
1168 ltpKey = '_ltpRefList';
1172 url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), ltpKey, spec.layerProtocolId].join('/')
1174 // console.info(odlRequest.url);
1175 service.genericRequest(odlRequest).then(function (success) {
1176 deferred.resolve(success);
1177 }, function (error) {
1178 $mwtnLog.error({ component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!' });
1179 deferred.reject(errorMsg);
1186 case 'airinterface':
1190 case 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac':
1191 case 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac':
1192 case 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac':
1194 case 'microwave-model:mw-air-interface-pac':
1195 case 'microwave-model:mw-air-interface-diversity-pac':
1196 case 'microwave-model:mw-pure-ethernet-structure-pac':
1197 case 'microwave-model:mw-hybrid-mw-structure-pac':
1198 case 'microwave-model:mw-tdm-container-pac':
1199 case 'microwave-model:mw-ethernet-container-pac':
1200 case 'onf-ethernet-conditional-packages:ethernet-pac':
1202 case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac':
1203 case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac':
1205 service.getConditionalPackagePart(spec).then(function (success) {
1206 success.layerProtocol = spec.layerProtocolId;
1207 deferred.resolve(success);
1208 }, function (error) {
1209 $mwtnLog.error({ component: COMPONENT, message: 'Requesting conditional package of ' + JSON.stringify(spec) + ' failed!' });
1210 deferred.reject(errorMsg);
1216 case 'neCurrentProblems':
1217 service.getNetworkElementCurrentProblemList(spec.nodeId, spec.revision).then(function (success) {
1218 deferred.resolve(success);
1219 }, function (error) {
1220 $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!' });
1221 deferred.reject(error);
1225 case 'forwardingConstructs':
1226 // not needed (currently)
1230 $mwtnLog.error({ component: COMPONENT, message: 'Requesting ' + spec.pacId + ' is not supported!' });
1231 deferred.reject(errorMsg);
1233 return deferred.promise;
1235 service.setPacParts = function (spec, data) {
1236 var errorMsg = { info: 'No data received' };
1237 var deferred = $q.defer();
1238 switch (spec.pacId) {
1240 // service.getActualNetworkElement(spec.nodeId, spec.revision).then(function(success){
1241 // deferred.resolve(success);
1242 // }, function(error){
1243 // $mwtnLog.error({component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!'});
1244 // deferred.reject(errorMsg);
1248 // var odlRequest = {
1250 // url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), '_ltpRefList', spec.layerProtocolId].join('/')
1252 // service.genericRequest(odlRequest).then(function(success){
1253 // deferred.resolve(success);
1254 // }, function(error){
1255 // $mwtnLog.error({component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!'});
1256 // deferred.reject(errorMsg);
1259 case 'airinterface':
1263 case 'microwave-model:mw-air-interface-pac':
1264 case 'microwave-model:mw-air-interface-diversity-pac':
1265 case 'microwave-model:mw-pure-ethernet-structure-pac':
1266 case 'microwave-model:mw-hybrid-mw-structure-pac':
1267 case 'microwave-model:mw-tdm-container-pac':
1268 case 'microwave-model:mw-ethernet-container-pac':
1269 case 'onf-ethernet-conditional-packages:ethernet-pac':
1271 case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac':
1272 case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac':
1273 service.setConditionalPackagePart(spec, data).then(function (success) {
1274 deferred.resolve(success);
1275 }, function (error) {
1276 $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + JSON.stringify(spec) + ' failed!' });
1277 deferred.reject(errorMsg);
1281 $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + spec.pacId + ' not supported!' });
1282 deferred.reject(errorMsg);
1284 return deferred.promise;
1286 service.setPacPartLists = function (spec, listData) {
1287 var errorMsg = { info: 'No data received' };
1288 var deferred = $q.defer();
1289 switch (spec.pacId) {
1291 // service.getActualNetworkElement(spec.nodeId, spec.revision).then(function(success){
1292 // deferred.resolve(success);
1293 // }, function(error){
1294 // $mwtnLog.error({component: COMPONENT, message: 'Requesting ' + spec.nodeId + ' failed!'});
1295 // deferred.reject(errorMsg);
1299 // var odlRequest = {
1301 // url: [service.url.actualNetworkElement(spec.nodeId, spec.revision), '_ltpRefList', spec.layerProtocolId].join('/')
1303 // service.genericRequest(odlRequest).then(function(success){
1304 // deferred.resolve(success);
1305 // }, function(error){
1306 // $mwtnLog.error({component: COMPONENT, message: 'Requesting LTPs of ' + spec.nodeId + ' failed!'});
1307 // deferred.reject(errorMsg);
1310 case 'airinterface':
1314 case 'microwave-model:mw-air-interface-pac':
1315 case 'microwave-model:mw-air-interface-diversity-pac':
1316 case 'microwave-model:mw-pure-ethernet-structure-pac':
1317 case 'microwave-model:mw-hybrid-mw-structure-pac':
1318 case 'microwave-model:mw-tdm-container-pac':
1319 case 'microwave-model:mw-ethernet-container-pac':
1320 case 'onf-ethernet-conditional-packages:ethernet-pac':
1322 case 'onf-otn-odu-conditional-packages:otn-odu-connection-pac':
1323 case 'onf-otn-odu-conditional-packages:otn-odu-termination-pac':
1324 service.setConditionalPackagePartList(spec, listData).then(function (success) {
1325 deferred.resolve(success);
1326 }, function (error) {
1327 $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + JSON.stringify(spec) + ' failed!' });
1328 deferred.reject(errorMsg);
1332 $mwtnLog.error({ component: COMPONENT, message: 'Modification of ' + spec.pacId + ' not supported!' });
1333 deferred.reject(errorMsg);
1335 return deferred.promise;
1337 var nodeIntId = 100;
1338 service.getNodeIntIdFromNodeId = function (nodeId) {
1339 nodeIntId = nodeIntId + 1;
1340 if (nodeId.contains('-')) {
1341 return nodeId.split('-')[1];
1346 service.getRequiredNetworkElements = function (complete) {
1347 var sort = [{ _id: { order: 'asc' } }];;
1353 var deferred = $q.defer();
1354 $mwtnDatabase.getFilteredSortedData('mwtn', 'required-networkelement', 0, 10000, sort, query).then(
1355 function (success) {
1357 deferred.resolve(success.data.hits.hits);
1359 var result = success.data.hits.hits.map(function (ne) {
1360 var yangifiedObj = service.yangifyObject(ne._source);
1361 var pacKey = 'microwave-model:mw-air-interface-pac';
1362 if (yangifiedObj['microwave-model-object-classes-air-interface:mw-air-interface-pac']) {
1363 pacKey = 'microwave-model-object-classes-air-interface:mw-air-interface-pac';
1365 var configKey = 'air-interface-configuration';
1366 var radioSignalIds = [];
1367 if (yangifiedObj[pacKey]) {
1368 radioSignalIds = yangifiedObj[pacKey].filter(
1370 return mwps[configKey] && mwps[configKey]['radio-signal-id'];
1374 return mwps[configKey]['radio-signal-id'];
1379 id: service.getNodeIntIdFromNodeId(yangifiedObj['node-id']),
1380 name: yangifiedObj['node-id'],
1381 ipaddress: yangifiedObj.connect.host,
1382 port: yangifiedObj.connect.port,
1383 username: yangifiedObj.connect.username,
1384 password: yangifiedObj.connect.password,
1385 radioSignalIds: JSON.stringify(radioSignalIds),
1386 connectionStatus: 'disconnected'
1389 deferred.resolve(result);
1392 $mwtnLog.error({ component: COMPONENT, message: 'Problems in retrieving required network elements.' });
1393 deferred.reject(error);
1396 return deferred.promise;
1399 service.getConnectionStatus = function (neId) {
1400 var url = service.base + service.url.connectionStatus(neId);
1405 var deferred = $q.defer();
1406 $http(request).then(function (success) {
1407 // console.log(JSON.stringify(success));
1408 deferred.resolve(success.data.node[0]['netconf-node-topology:connection-status']);
1409 }, function (error) {
1410 deferred.reject(error);
1412 return deferred.promise;
1414 service.executeClosedLoopAutomation = function () {
1415 var url = service.base + 'operations/closedLoopAutomation:start';
1420 var deferred = $q.defer();
1421 $http(request).then(function (success) {
1422 deferred.resolve(success);
1423 }, function (error) {
1424 deferred.reject(error);
1426 return deferred.promise;
1428 service.saveClosedLoopAutomation = function (enabled, option) {
1429 var url = service.base + 'operations/closedLoopAutomation:save-timer';
1440 var deferred = $q.defer();
1441 $http(request).then(function (success) {
1442 deferred.resolve(success);
1443 }, function (error) {
1444 deferred.reject(error);
1446 return deferred.promise;
1448 service.readClosedLoopAutomation = function () {
1449 var url = service.base + 'operations/closedLoopAutomation:read-timer';
1454 var deferred = $q.defer();
1455 $http(request).then(function (success) {
1456 deferred.resolve(success);
1457 }, function (error) {
1458 deferred.reject(error);
1460 return deferred.promise;
1464 * A promise inquiring the a single mountpoint from topology-netconf.
1465 * @param {string} nodeId - The mountpoint identifier.
1466 * @return {{'node-id':string, 'netconf-node-topology:tcp-only': boolean, 'netconf-node-topology:host', string, 'netconf-node-topology:keepalive-delay':number, 'netconf-node-topology:port':number, 'netconf-node-topology:username':string, 'netconf-node-topology:password': string}} - The mountpoint from topology-netconf.
1468 service.getMountPoint = function (nodeId) {
1471 url: service.url.mount(nodeId)
1473 var deferred = $q.defer();
1474 service.genericRequest(odlRequest).then(
1475 function (success) {
1476 deferred.resolve(success.data.node[0]);
1479 deferred.reject(error);
1482 return deferred.promise;
1485 service.getMountPoints = function () {
1486 var url = service.base + service.url.actualNetworkElements();
1491 var deferred = $q.defer();
1492 $http(request).then(function (success) {
1493 var requiredTopology = 'topology-netconf';
1494 var topo = success.data.topology.filter(function (topo) {
1495 return topo['topology-id'] === requiredTopology;
1497 // console.log('topo', JSON.stringify(topo));
1498 if (topo.length === 0) {
1499 var message = ['ODL', requiredTopology, 'not found!'].join(' ');
1500 $mwtnLog.error({ component: COMPONENT, message: message });
1501 deferred.reject(message);
1502 } else if (topo[0].node) {
1503 var mwMountPoints = topo[0].node.filter(function (mountpoint) {
1504 return mountpoint['node-id'] !== 'controller-config';
1505 }).map(function (mountpoint) {
1506 // console.info('mountpoint', JSON.stringify(mountpoint));
1507 var capId = 'netconf-node-topology:available-capabilities';
1508 if (mountpoint[capId] && mountpoint[capId]['available-capability']) {
1509 var caps = mountpoint[capId]['available-capability'].filter(function (cap) {
1510 // console.info(JSON.stringify(cap));
1511 return cap.capability.contains('?revision=');
1512 }).map(function (cap) {
1514 module: cap.capability.split(')')[1],
1515 revision: cap.capability.split('?revision=')[1].substring(0, 10)
1517 }).sort(function (a, b) {
1518 if (a.module < b.module) return -1;
1519 if (a.module > b.module) return 1;
1522 // console.log('mountpoint', JSON.stringify(caps));
1523 mountpoint.onfCapabilities = caps;
1524 mountpoint.onfCoreModelRevision = caps.filter(function (cap) {
1525 return cap.module === 'core-model' || cap.module === 'CoreModel-CoreNetworkModule-ObjectClasses';
1526 }).map(function (cap) {
1527 return cap.revision;
1529 if (mountpoint.onfCoreModelRevision.length === 1) {
1530 mountpoint.onfCoreModelRevision = mountpoint.onfCoreModelRevision[0];
1532 $mwtnLog.error({ component: COMPONENT, message: mountpoint.onfCoreModelRevision.length + ' CoreModels supported by ' + mountpoint['node-id'] });
1535 // console.log('caps', JSON.stringify(caps));
1536 mountpoint.onfAirInterfaceRevision = caps.filter(function (cap) {
1537 return cap.module === 'microwave-model' || cap.module === 'MicrowaveModel-ObjectClasses-AirInterface';
1538 }).map(function (cap) {
1539 return cap.revision;
1541 // console.log('onfAirInterfaceRevision', mountpoint.onfAirInterfaceRevision);
1542 if (mountpoint.onfAirInterfaceRevision.length === 1) {
1543 mountpoint.onfAirInterfaceRevision = mountpoint.onfAirInterfaceRevision[0];
1545 $mwtnLog.error({ component: COMPONENT, message: 'More than 1 or no MicrowaveModel supported by ' + mountpoint['node-id'] });
1548 var clusterConneactionStatus = 'netconf-node-topology:clustered-connection-status';
1549 if (mountpoint[clusterConneactionStatus] && mountpoint[clusterConneactionStatus]['netconf-master-node']) {
1550 var value = mountpoint[clusterConneactionStatus]['netconf-master-node'];
1551 value = value.substring(value.indexOf('@'));
1552 mountpoint.client = value.substring(1, value.indexOf(':'));
1554 mountpoint.client = window.location.hostname;
1558 // console.log('mwMountPoints', JSON.stringify(mwMountPoints));
1559 deferred.resolve(mwMountPoints);
1561 }, function (error) {
1562 $mwtnLog.error({ component: COMPONENT, message: JSON.stringify(error.data) });
1563 deferred.reject(error);
1565 return deferred.promise;
1567 service.separator = ' ';
1569 service.highlightFilteredHeader = function (row, rowRenderIndex,
1570 col, colRenderIndex) {
1571 if (col.filters[0].term) {
1572 return 'header-filtered';
1577 service.gridOptions = {
1579 enableColumnResizing: true,
1580 enableSorting: true,
1581 enableFiltering: true,
1582 enableGridMenu: true,
1583 exporterMenuPdf: false,
1584 showGridFooter: true,
1585 // showColumnFooter: true,
1587 enableRowSelection: true,
1588 enableRowHeaderSelection: true,
1591 service.gridOptions.gridMenuCustomItems = [{
1592 title: 'Rotate Grid',
1593 action: function ($event) {
1594 this.grid.element.toggleClass('rotated');
1599 actualNetworkElements: function () {
1600 return 'operational/network-topology:network-topology/topology/topology-netconf';
1602 connectionStatus: function (neId) {
1603 return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId;
1605 mount: function (neId) {
1606 return 'config/network-topology:network-topology/topology/topology-netconf/node/' + neId;
1607 // return 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules'; // depricated
1609 unmount: function (neId) {
1610 // return 'config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/' + neId; // depricated
1611 return 'config/network-topology:network-topology/topology/topology-netconf/node/' + neId;
1613 forwardingDomain: function (neId, fdUuid) {
1614 return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/core-model:network-element/fd/' +fdUuid;
1616 forwardingConstruct: function (neId, fcUuid) {
1617 return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/core-model:forwarding-construct/' +fcUuid;
1619 clock: function (neId, revision) {
1620 return 'operational/network-topology:network-topology/topology/topology-netconf/node/' + neId + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1';
1622 actualNetworkElement: function (neId, revision) {
1626 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1628 '/yang-ext:mount/CoreModel-CoreNetworkModule-ObjectClasses:NetworkElement/',
1635 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1637 '/yang-ext:mount/core-model:network-element'].join('');
1638 default: // 2016-08-11
1640 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1642 '/yang-ext:mount/CoreModel-CoreNetworkModule-ObjectClasses:NetworkElement'].join('');
1645 networkElementCurrentProblemList: function (neId, revision) {
1646 console.log(neId, revision);
1650 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1652 '/yang-ext:mount/MicrowaveModel-NetworkElement-CurrentProblemList:NetworkElementCurrentProblems'].join('');
1654 case "2017-03-20": // TODO sko equipmentAlarms check new yang file if agreed
1656 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1658 '/yang-ext:mount/onf-core-model-conditional-packages:network-element-pac/network-element-current-problems'].join('');
1661 'operational/network-topology:network-topology/topology/topology-netconf/node/',
1663 '/yang-ext:mount/onf-core-model-conditional-packages:network-element-pac/network-element-current-problems'].join('');
1668 * Changes different time formats to a common time fromat
1669 * TODO currently not implemented!
1671 service.normalizeTimeFormat = function (time, format) {
1675 * Changing a string according to yang naming conventions.
1676 * The function should be alinged with the ONF Eagle project.
1678 service.yangify = function (str) {
1680 .replace(/RefList+$/, '') // endling "List" was removed
1681 .replace(/List+$/, '') // endling "List" was removed
1682 .replace(/([a-z])([A-Z])/g, '$1-$2') // insert dashes
1683 .replace(/([0-9])([a-zA-Z])/g, '$1-$2') // insert dashes
1684 .replace(/([A-Z])([A-Z])([a-z])/g, '$1-$2$3') // insert dashes
1685 .toLowerCase() // lowercase everything
1686 .replace(/^_/, '') // remove leading underscore
1687 .replace(/:_/g, ':') // and leading underscores in path segments
1688 .replace(/_/g, '-'); // convert underscore to dashes
1690 // catch "wrong" UML labels
1692 'air-interface':'air-interface-list',
1693 'air-interface-ltp':'air-interface-ltp-list',
1694 'air-interface-capability': 'air-interface-capability-list',
1695 'air-interface-current-problem': 'air-interface-current-problem-list',
1696 'container-capability': 'container-capability-list',
1697 'current-performance-data':'current-performance-data-list',
1698 'current-problem':'current-problem-list',
1699 'historical-performance-data':'historical-performance-data-list',
1700 'problem-kind-severity':'problem-kind-severity-list',
1701 'pure-ethernet-structure-capability':'pure-ethernet-structure-capability-list',
1702 'segment-status':'segment-status-list',
1703 'segments-id':'segments-id-list',
1704 'structure-capability': 'structure-capability-list',
1705 'structure-current-problem': 'structure-current-problem-list',
1706 'supported-tdm-container-types':'supported-tdm-container-types-list',
1707 'supported-tdm-structure-types':'supported-tdm-structure-types-list',
1708 'supported-channel-plan':'supported-channel-plan-list',
1709 'supported-loop-back-kind':'transmission-mode-list',
1710 'transmission-mode':'transmission-mode-list'
1712 if (exceptions[result]) {
1713 console.warn(result, '.>', exceptions[result]);
1714 result=exceptions[result];
1717 // catch modulation value difference
1718 if (result.startsWith('time') && result.endsWith('symbols')
1719 || result.startsWith('time') && result.contains('-symbols-') && result.endsWith('-s')
1720 || result.startsWith('time') && result.contains('-symbols-') && result.endsWith('-l')) {
1721 result = result.replace('symbols', 'states');
1727 * Checking, whether a jsonObject should be yangifyed
1729 service.isCamelCase = function (jsonObject) {
1730 if (jsonObject === undefined || jsonObject === null) {
1734 var type = service.getType(jsonObject);
1738 Object.keys(jsonObject).map(function (key) {
1739 result = result || key !== [service.yangify(key)];
1752 console.error('Type1:', type, ' is not supported!');
1758 * Yangifies a names/keys of a jsonOject
1760 service.yangifyObject = function (jsonObject) {
1761 if (jsonObject === undefined || jsonObject === null) {
1765 var type = service.getType(jsonObject);
1770 Object.keys(jsonObject).map(function (key) {
1771 result[service.yangify(key)] = service.yangifyObject(jsonObject[key]);
1775 result = jsonObject.map(function (item, index) {
1776 return service.yangifyObject(item);
1785 result = jsonObject;
1788 console.error('Type:', type, ' is not supported!');
1789 result = jsonObject;
1794 * Send a restconf request to OpenDayligth.
1795 * All ODL restconf requests should pass this function.
1797 service.genericRequest = function (odlRequest) {
1798 var url = [service.base, odlRequest.url].join('');
1800 method: odlRequest.method,
1802 data: odlRequest.data
1804 var deferred = $q.defer();
1805 $http(request).then(function (success) {
1806 // yangifing the response is required until all NEs has switch to CoreModel 1.2 (ONF-TR-532)
1807 // deferred.resolve(service.yangifyObject(success));
1808 deferred.resolve(success);
1809 }, function (error) {
1810 $mwtnLog.error({ component: COMPONENT + '.genericRequest', message: JSON.stringify(error.data) });
1811 deferred.reject(error);
1813 return deferred.promise;
1815 service.getMountedNetConfServers = function (callback) {
1816 var url = service.base + service.url.actualNetworkElements();
1821 $http(request).then(function (success) {
1822 return callback(success.data);
1823 }, function (error) {
1824 console.error(JSON.stringify(error));
1829 service.getActualNetworkElement = function (neId, revision) {
1830 var url = [service.base,
1831 service.url.actualNetworkElement(neId, revision)].join('');
1836 var taskId = [neId, 'ONF:CoreModel:NetworkElement data received'].join(' ');
1838 var deferred = $q.defer();
1839 console.time(taskId);
1840 $http(request).then(function (success) {
1841 console.timeEnd(taskId);
1842 success.data.revision = revision;
1843 // deferred.resolve(service.yangifyObject(success.data));
1844 deferred.resolve(success.data);
1845 }, function (error) {
1846 console.timeEnd(taskId);
1847 $mwtnLog.info({ component: '$mwtnCommons.getActualNetworkElement', message: JSON.stringify(error.data) });
1848 deferred.reject(error);
1850 return deferred.promise;
1853 service.getForwardingDomain = function(neId, fdUuid) {
1854 var url = [service.base,
1855 service.url.forwardingDomain(neId, fdUuid)].join('');
1860 var taskId = [neId, 'ONF:ForwardingDomain received'].join(' ');
1862 var deferred = $q.defer();
1863 console.time(taskId);
1864 $http(request).then(function (success) {
1865 console.timeEnd(taskId);
1866 // deferred.resolve(service.yangifyObject(success.data));
1867 deferred.resolve(success.data);
1868 }, function (error) {
1869 console.timeEnd(taskId);
1870 $mwtnLog.info({ component: '$mwtnCommons.getForwardingDomain', message: JSON.stringify(error.data) });
1871 deferred.reject(error);
1873 return deferred.promise;
1876 service.getForwardingConstruct = function(neId, fcUuid) {
1877 var url = [service.base,
1878 service.url.forwardingConstruct(neId, fcUuid)].join('');
1883 var taskId = [neId, fcUuid, 'ONF:ForwardingConstruct received'].join(' ');
1885 var deferred = $q.defer();
1886 console.time(taskId);
1887 $http(request).then(function (success) {
1888 console.timeEnd(taskId);
1889 // deferred.resolve(service.yangifyObject(success.data));
1890 deferred.resolve(success.data);
1891 }, function (error) {
1892 console.timeEnd(taskId);
1893 $mwtnLog.info({ component: '$mwtnCommons.getForwardingConstruct', message: JSON.stringify(error.data) });
1896 return deferred.promise;
1899 service.getPtpClockData = function(neId, revision) {
1900 var url = [service.base,
1901 service.url.clock(neId, revision)].join('');
1906 var taskId = [neId, 'ONF:PTP:DataSet received'].join(' ');
1908 var deferred = $q.defer();
1909 console.time(taskId);
1910 $http(request).then(function (success) {
1911 console.timeEnd(taskId);
1912 success.data.revision = revision;
1913 // deferred.resolve(service.yangifyObject(success.data));
1914 deferred.resolve(success.data);
1915 }, function (error) {
1916 console.timeEnd(taskId);
1917 $mwtnLog.info({ component: '$mwtnCommons.getPtpClockData', message: JSON.stringify(error.data) });
1918 deferred.reject(error);
1920 return deferred.promise;
1923 service.getNetworkElementCurrentProblemList = function (neId, revision) {
1924 var url = [service.base,
1925 service.url.networkElementCurrentProblemList(neId, revision)].join('');
1930 var taskId = [neId, 'ONF:CoreModel:NetworkElement data received'].join(' ');
1932 var deferred = $q.defer();
1933 console.time(taskId);
1934 $http(request).then(function (success) {
1935 console.timeEnd(taskId);
1936 success.data.revision = revision;
1937 // deferred.resolve(service.yangifyObject(success.data)); TODO: check if correct
1938 deferred.resolve(success.data);
1939 }, function (error) {
1940 console.timeEnd(taskId);
1941 $mwtnLog.info({ component: '$mwtnCommons.getActualNetworkElement', message: JSON.stringify(error.data) });
1942 deferred.reject(error);
1944 return deferred.promise;
1947 var getIdsByRevision = function (revision, pacId, partId) {
1953 case 'AirInterface':
1954 case 'airinterface':
1955 case 'airInterface':
1956 pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_AirInterface_Pac';
1957 partId = 'airInterface' + partId;
1958 if (partId === 'airInterfaceCapability' || partId === 'airInterfaceCurrentProblems') {
1965 pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Structure_Pac';
1966 partId = 'structure' + partId;
1972 pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Container_Pac';
1973 partId = 'container' + partId;
1976 pacId = 'MicrowaveModel-ObjectClasses-MwConnection:MW_Container_Pac';
1977 partId = 'container' + partId;
1986 case 'AirInterface':
1987 case 'airinterface':
1988 case 'airInterface':
1989 case 'air-interface':
1990 pacId = 'microwave-model:mw-air-interface-pac';
1991 partId = 'air-interface-' + service.yangify(partId);
1996 var isHybrid = false; // TODO How do I know this?
1998 pacId = 'microwave-model:mw-hybrid-mw-structure-pac';
1999 partId = 'hybrid-mw-structure-' + service.yangify(partId);
2001 pacId = 'microwave-model:mw-pure-ethernet-structure-pac';
2002 partId = 'pure-ethernet-structure-' + service.yangify(partId);
2009 pacId = 'microwave-model:mw-ethernet-container-pac';
2010 partId = 'ethernet-container-' + service.yangify(partId);
2013 pacId = 'microwave-model:mw-tdm-container-pac';
2014 partId = 'tdm-container-' + service.yangify(partId);
2021 case 'AirInterface':
2022 case 'airinterface':
2023 case 'airInterface':
2024 pacId = 'MicrowaveModel-ObjectClasses-AirInterface:MW_AirInterface_Pac';
2025 partId = 'airInterface' + partId;
2030 pacId = 'MicrowaveModel-ObjectClasses-PureEthernetStructure:MW_PureEthernetStructure_Pac';
2031 partId = 'pureEthernetStructure' + partId;
2037 pacId = 'MicrowaveModel-ObjectClasses-EthernetContainer:MW_EthernetContainer_Pac';
2038 partId = 'ethernetContainer' + partId;
2041 pacId = 'microwave-model:mw-tdm-container-pac';
2042 partId = 'tdm-container-' + service.yangify(partId);
2052 service.getConditionalPackagePart = function (spec) {
2053 // console.log(JSON.stringify(spec));
2054 var deferred = $q.defer();
2056 deferred.reject('ignore');
2057 return deferred.promise;
2060 var ids = getIdsByRevision(spec.revision, spec.pacId, spec.partId);
2061 var operation = 'operational';
2062 if (spec.config === true) {
2063 operation = 'config';
2066 var url = [service.base, operation,
2067 '/network-topology:network-topology/topology/topology-netconf/node/',
2069 '/yang-ext:mount/', ids.pacId, '/',
2070 spec.layerProtocolId, '/',
2071 ids.partId].join('');
2076 // console.log(JSON.stringify(request));
2078 var taskId = [spec.nodeId, spec.layerProtocolId, spec.pacId, 'data received'].join(' ');
2079 console.time(taskId);
2080 $http(request).then(function (success) {
2081 console.timeEnd(taskId);
2082 success.data.revision = spec.revision;
2083 deferred.resolve(success.data);
2084 // console.log(JSON.stringify(service.yangifyObject(success.data)));
2085 // [sko] not now - later after all apps are updated to the new model: deferred.resolve(service.yangifyObject(success.data));
2086 }, function (error) {
2087 console.timeEnd(taskId);
2088 $mwtnLog.info({ component: '$mwtnCommons.getConditionalPackagePart', message: JSON.stringify(error.data) });
2089 deferred.reject(error);
2091 return deferred.promise;
2094 service.getPtpPort = function (spec) {
2095 var deferred = $q.defer();
2096 if (!spec.networkElement || !spec.value) {
2097 deferred.reject('ignore');
2098 return deferred.promise;
2101 var operation = 'config';
2102 var url = [service.base, operation,
2103 '/network-topology:network-topology/topology/topology-netconf/node/',
2104 spec.networkElement,
2105 '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/port-ds-list/',
2106 spec.value['port-number']].join('');
2111 console.warn(JSON.stringify(request));
2113 var taskId = [spec.networkElement, spec.value['port-number'], 'data received'].join(' ');
2114 console.time(taskId);
2115 $http(request).then(function (success) {
2116 console.timeEnd(taskId);
2117 console.warn(JSON.stringify(success.data));
2118 deferred.resolve(success.data);
2119 }, function (error) {
2120 console.timeEnd(taskId);
2121 $mwtnLog.info({ component: '$mwtnCommons.getPtpPort', message: JSON.stringify(error.data) });
2122 deferred.reject(error);
2124 return deferred.promise;
2127 service.setPtpPort = function (spec, data) {
2128 var deferred = $q.defer();
2129 if (!spec.networkElement || !spec.value) {
2130 deferred.reject('ignore');
2131 return deferred.promise;
2134 var operation = 'config';
2135 var url = [service.base, operation,
2136 '/network-topology:network-topology/topology/topology-netconf/node/',
2137 spec.networkElement,
2138 '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/port-ds-list/',
2139 spec.value['port-number']].join('');
2141 var body = {'port-ds-list': data};
2147 'Content-Type': 'application/json',
2148 'Accept': 'application/json'
2153 var taskId = [spec.networkElement, spec.value['port-number'], 'data received'].join(' ');
2154 console.time(taskId);
2155 $http(request).then(function (success) {
2156 console.timeEnd(taskId);
2157 deferred.resolve(success.data);
2158 // deferred.resolve(service.yangifyObject(success.data));
2159 }, function (error) {
2160 console.timeEnd(taskId);
2161 $mwtnLog.error({ component: '$mwtnCommons.setPtpPort', message: JSON.stringify(error.data) });
2162 deferred.reject(error);
2164 return deferred.promise;
2168 service.getPtpDefaultDs = function (spec) {
2169 var deferred = $q.defer();
2170 if (!spec.networkElement || !spec.value) {
2171 deferred.reject('ignore');
2172 return deferred.promise;
2175 var operation = 'config';
2176 var url = [service.base, operation,
2177 '/network-topology:network-topology/topology/topology-netconf/node/',
2178 spec.networkElement,
2179 '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/default-ds/'].join('');
2184 console.warn(JSON.stringify(request));
2186 var taskId = [spec.networkElement, 'default-ds', 'data received'].join(' ');
2187 console.time(taskId);
2188 $http(request).then(function (success) {
2189 console.timeEnd(taskId);
2190 console.warn(JSON.stringify(success.data));
2191 deferred.resolve(success.data);
2192 }, function (error) {
2193 console.timeEnd(taskId);
2194 $mwtnLog.info({ component: '$mwtnCommons.getPtpPort', message: JSON.stringify(error.data) });
2195 deferred.reject(error);
2197 return deferred.promise;
2200 service.setPtpDefaultDs = function (spec, data) {
2201 var deferred = $q.defer();
2202 if (!spec.networkElement || !spec.value) {
2203 deferred.reject('ignore');
2204 return deferred.promise;
2207 var operation = 'config';
2208 var url = [service.base, operation,
2209 '/network-topology:network-topology/topology/topology-netconf/node/',
2210 spec.networkElement,
2211 '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/default-ds/'].join('');
2213 var body = {'default-ds': data};
2219 'Content-Type': 'application/json',
2220 'Accept': 'application/json'
2225 var taskId = [spec.networkElement, 'default-ds', 'data received'].join(' ');
2226 console.time(taskId);
2227 $http(request).then(function (success) {
2228 console.timeEnd(taskId);
2229 deferred.resolve(success.data);
2230 // deferred.resolve(service.yangifyObject(success.data));
2231 }, function (error) {
2232 console.timeEnd(taskId);
2233 $mwtnLog.error({ component: '$mwtnCommons.setPtpPort', message: JSON.stringify(error.data) });
2234 deferred.reject(error);
2236 return deferred.promise;
2240 service.setConditionalPackagePart = function (spec, data) {
2241 var deferred = $q.defer();
2243 deferred.reject('ignore');
2244 return deferred.promise;
2247 var ids = getIdsByRevision(spec.revision, spec.pacId, spec.partId);
2249 body[ids.partId] = data;
2251 var url = [service.base,
2252 'config/network-topology:network-topology/topology/topology-netconf/node/',
2254 '/yang-ext:mount/', ids.pacId, '/',
2255 spec.layerProtocolId, '/',
2256 ids.partId].join('');
2261 'Content-Type': 'application/json',
2262 'Accept': 'application/json'
2267 var taskId = [spec.nodeId, spec.layerProtocolId, spec.pacId, 'data received'].join(' ');
2268 console.time(taskId);
2269 $http(request).then(function (success) {
2270 console.timeEnd(taskId);
2271 success.data.revision = spec.revision;
2272 deferred.resolve(success.data);
2273 // deferred.resolve(service.yangifyObject(success.data));
2274 }, function (error) {
2275 console.timeEnd(taskId);
2276 $mwtnLog.error({ component: '$mwtnCommons.setConditionalPackagePart', message: JSON.stringify(error.data) });
2277 deferred.reject(error);
2279 return deferred.promise;
2282 // pureEthernetStructureConfiguration/problemKindSeverityList/value1
2284 // "problemKindSeverityList": [
2286 // "problemKindName": "severity1",
2287 // "problemKindSeverity": "warning"
2292 var processData = function (item, i, callback) {
2293 var spec = item.spec;
2294 var ids = getIdsByRevision(spec.revision, spec.pacId,
2296 item.spec = undefined;
2298 body[spec.attribute] = [item];
2299 $mwtnDatabase.getSchema().then(function (schema) {
2302 Object.keys(item).map(function (k) {
2303 // works currently only for single key lists
2304 if (schema[k] && schema[k]['is-key']) {
2310 service.base.slice(0, -1),
2311 'config/network-topology:network-topology/topology/topology-netconf/node',
2312 spec.nodeId, 'yang-ext:mount', ids.pacId,
2313 spec.layerProtocolId, ids.partId,
2314 spec.attribute, item[key]].join('/');
2319 'Content-Type': 'application/json',
2320 'Accept': 'application/json'
2324 // console.log(JSON.stringify(request));
2325 var taskId = [spec.nodeId, spec.layerProtocolId,
2326 spec.pacId, item.problemKindName,
2327 'data received'].join(' ');
2328 console.time(taskId);
2329 $http(request).then(function (success) {
2330 console.timeEnd(taskId);
2331 success.data.revision = spec.revision;
2335 console.timeEnd(taskId);
2338 component: '$mwtnCommons.setConditionalPackagePart',
2340 .stringify(error.data)
2347 service.setConditionalPackagePartList = function (spec, data) {
2348 var deferred = $q.defer();
2350 deferred.reject('ignore');
2351 return deferred.promise;
2354 data.map(function (item) {
2358 doSynchronousLoop(data, processData, function () {
2361 return deferred.promise;
2364 var saveRequiredNetworkElement = function (requiredNode) {
2365 var url = [$mwtnDatabase.base, $mwtnDatabase.index, 'required-networkelement',
2366 requiredNode.nodeId].join('/');
2367 var bodyString = JSON.stringify(requiredNode);
2369 'Content-Type': 'application/json',
2370 'Content-Length': bodyString.length
2378 var deferred = $q.defer();
2379 console.time('database:' + url);
2380 $http(request).then(function (success) {
2381 console.timeEnd('database:' + url);
2382 // console.log(JSON.stringify(success));
2383 deferred.resolve(success);
2384 }, function (error) {
2385 console.timeEnd('database:' + url);
2386 $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) });
2387 deferred.reject(error);
2389 return deferred.promise;
2393 * A function which inquires data from a netconf server and stores it in a database.
2394 * @param {{'node-id': string, ipAddress: string, port: number, username: string, password: string, site:string, onfCoreModelRevision: string, onfAirInterfaceRevision: string}} netconfServer - A netConf server object with all connectivity parameters.
2396 service.addRequiredNetworkElement = function (netconfServer) {
2397 /** {Object} requiredNode - Data set to be stored in database */
2398 var requiredNode = {
2399 nodeId: netconfServer['node-id'],
2400 siteRef: netconfServer.site,
2401 onfCoreModelRevision: netconfServer.onfCoreModelRevision,
2402 onfAirInterfaceRevision: netconfServer.onfAirInterfaceRevision,
2405 mountId: netconfServer['node-id'],
2406 host: netconfServer['netconf-node-topology:host'],
2407 port: netconfServer['netconf-node-topology:port'],
2408 username: netconfServer.username,
2409 password: netconfServer.password
2411 'core-model:network-element': {},
2414 var deferred = $q.defer();
2415 saveRequiredNetworkElement(requiredNode).then(function (success) {
2416 deferred.resolve(success);
2417 }, function (error) {
2418 $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) });
2419 deferred.reject(error);
2422 // [sko] much simplified du to ONAP concepts, no device configuration needs to be stored in database.
2424 // // get NetworkElement object from node
2426 // nodeId: requiredNode.nodeId,
2427 // revision: requiredNode.onfCoreModelRevision,
2431 // var updatePart = function (spec, data) {
2432 // data.layerProtocol = spec.layerProtocolId;
2433 // requiredNode[spec.pacId].push(data);
2436 // var numberOfLtps = -1;
2437 // var processLTPs = function (item, i, callback) {
2438 // var ltp = new LogicalTerminationPoint(item);
2439 // ltp.getLayerProtocols().map(
2441 // * A function processing a layer-protocol object
2442 // * @param {LayerProtocol} lp A layer-protocol object
2445 // var conditionalPackage = lp.getConditionalPackage(true);
2446 // if (conditionalPackage !== '') {
2447 // if (requiredNode[conditionalPackage] === undefined) {
2448 // // create missing pac array
2449 // requiredNode[conditionalPackage] = [];
2452 // nodeId: requiredNode.nodeId,
2453 // revision: requiredNode.onfCoreModelRevision,
2454 // pacId: conditionalPackage,
2455 // layer: lp.getLayer(),
2456 // layerProtocolId: lp.getId()
2458 // spec.partId = service.getPartGlobalId(spec, 'configuration');
2459 // // console.info(JSON.stringify(spec));
2460 // service.getPacParts(spec).then(function (success) {
2461 // // console.log(JSON.stringify(success));
2462 // spec.message = ['Process LTP', i+1, 'of', numberOfLtps].join(' ');
2463 // $notifying.notify(spec);
2464 // updatePart(spec, service.yangifyObject(success));
2465 // return callback();
2466 // }, function (error) {
2467 // spec.message = ['Process LTP', i+1, 'of', numberOfLtps].join(' ');
2468 // $notifying.notify(spec);
2469 // $mwtnLog.error({ component: '$mwtnCommons.processLTPs bad data', message: JSON.stringify(error) });
2470 // return callback();
2473 // $mwtnLog.info({ component: COMPONENT, message: 'No condtional package found: ' + ltp.getId() });
2474 // return callback();
2478 // // console.log(JSON.stringify(ltp.getData()));
2481 // service.getPacParts(spec).then(function (success) {
2482 // success = service.yangifyObject(success);
2483 // requiredNode['core-model:network-element'] = success['network-element'];
2484 // var id = success['network-element']['node-id'];
2485 // numberOfLtps = success['network-element'].ltp.length;
2486 // doSynchronousLoop(success['network-element'].ltp, processLTPs, function () {
2487 // saveRequiredNetworkElement(requiredNode).then(function (success) {
2488 // $notifying.notify( { nodeId: id, message: 'finish'} );
2489 // deferred.resolve(success);
2490 // }, function (error) {
2491 // $mwtnLog.error({ component: '$mwtnCommons.saveRequiredNetworkElement', message: JSON.stringify(error.data) });
2492 // deferred.reject(error);
2496 // }, function (error) {
2497 // $mwtnLog.error({ component: '$mwtnCommons.getPacParts', message: JSON.stringify(error.data) });
2498 // deferred.reject(error);
2500 return deferred.promise;
2503 service.registerForOdlEvents = function (path, callback) {
2507 'operations/sal-remote:create-data-change-event-subscription']
2512 "sal-remote-augment:datastore": "CONFIGURATION",
2513 "sal-remote-augment:scope": "SUBTREE"
2517 $http(request).then(
2518 function successCallback(response) {
2519 // this callback will be called asynchronously
2520 // when the response is available
2521 // console.log(JSON.stringify(response));
2522 createStream(response.data.output['stream-name'],
2523 function (socketLocation) {
2524 callback(socketLocation);
2526 }, function errorCallback(response) {
2527 // called asynchronously if an error occurs
2528 // or server returns response with an error status.
2529 console.error(JSON.stringify(response));
2536 // Precision Time Protocol PTP
2537 mwtnCommonsApp.register.factory('$mwtnPtp', function ($http, $q, $mwtnCommons, PtpClock) {
2538 var key1 = 'netconf-node-topology:available-capabilities';
2539 var key2 = 'available-capability';
2540 var filterActivePtpClocks = function(mountpoints) {
2541 return mountpoints.filter(function(mountpoint) {
2542 if (!mountpoint) return false;
2543 if (!mountpoint[key1]) return false;
2544 if (!mountpoint[key1][key2]) return false;
2545 if (mountpoint['netconf-node-topology:connection-status'] !== 'connected') return false;
2546 var ptpCapability = mountpoint[key1][key2].filter(function(capability){
2547 return capability.contains('ietf-ptp-dataset');
2549 return ptpCapability.length > 0;
2550 }).map(function(mountpoint){
2551 return mountpoint['node-id'];
2555 var processData = function (nodeId, i, callback) {
2556 $mwtnCommons.getPtpClockData(nodeId).then(
2557 function (success) {
2558 ptpClocks[nodeId] = new PtpClock(success);
2562 console.error(error);
2569 service.getPtpClocks = function() {
2570 var deferred = $q.defer();
2572 $mwtnCommons.getMountPoints().then(function (mountpoints) {
2573 var ptpClockNodeIds = filterActivePtpClocks(mountpoints);
2574 doSynchronousLoop(ptpClockNodeIds, processData, function () {
2575 deferred.resolve(ptpClocks);
2577 }, function (error) {
2582 return deferred.promise;
2585 service.getParent = function(nodeId) {
2586 var deferred = $q.defer();
2589 url: 'operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId + '/yang-ext:mount/ietf-ptp-dataset:instance-list/1/parent-ds/parent-port-identity'
2592 $mwtnCommons.genericRequest(request).then(function(success){
2593 console.warn(JSON.stringify(success));
2594 deferred.resolve(success.data['parent-port-identity']);
2595 }, function(error) {
2596 console.error(JSon.stringify(error));
2599 return deferred.promise;
2606 mwtnCommonsApp.register.factory('$mwtnLog', function ($http, $q, $mwtnDatabase) {
2607 var writeLogToDB = function (data, callback) {
2608 var url = [$mwtnDatabase.base, $mwtnDatabase.index, 'log'].join('/');
2613 timestamp: data.timestamp ? data.timestamp : new Date().toISOString(),
2614 type: data.type ? data.type : 'info',
2615 component: data.component ? data.component : 'unkonwn',
2616 message: data.message
2619 $http(request).then(function successCallback(response) {
2620 return callback(true);
2621 }, function errorCallback(response) {
2622 console.error(JSON.stringify(response));
2623 return callback(false);
2627 var createIndex = function (index, callback) {
2628 var url = [$mwtnDatabase.base, index].join('/');
2633 timestamp: new Date().toISOString(),
2635 component: '$mwtnLog',
2639 $http(request).then(function (success) {
2640 return callback(true);
2641 }, function (error) {
2642 console.error(JSON.stringify(error));
2643 return callback(false);
2646 var checkIndex = function (index, callback) {
2647 var url = [$mwtnDatabase.base, index].join('/');
2652 $http(request).then(function successCallback(response) {
2653 return callback(true);
2654 }, function errorCallback(response) {
2655 console.error(JSON.stringify(response));
2656 createIndex(index, function (created) {
2657 return callback(created);
2661 var checkDatabase = function (callback) {
2662 var url = $mwtnDatabase.base;
2667 $http(request).then(function successCallback(response) {
2668 checkIndex($mwtnDatabase.index, function (exists) {
2669 return callback(exists);
2671 }, function errorCallback(response) {
2672 console.error(JSON.stringify(response));
2673 return callback(false);
2676 var getData = function (type, log) {
2678 data.timestamp = new Date().toISOString();
2679 switch (typeof log) {
2682 data.component = 'unknown';
2687 data.component = log.component;
2688 data.message = log.message;
2691 data.type = 'error';
2692 data.component = '$mwtnLog';
2693 data.message = 'pnf log service is called with wrong parameters.';
2695 // console.log(JSON.stringify(data));
2699 base: $mwtnDatabase.base
2701 service.debug = function (log) {
2702 var data = getData('debug', log);
2703 checkDatabase(function (isRunning) {
2705 writeLogToDB(data, function () {
2706 // console.log('log stored');
2709 console.error(data.timestamp, service.base,
2710 'Database (ElasticSerach) not reachable!?');
2713 console.log(data.timestamp, JSON.stringify(log));
2715 service.error = function (log) {
2716 var data = getData('error', log);
2717 checkDatabase(function (isRunning) {
2719 writeLogToDB(data, function () {
2720 // console.log('log stored');
2723 console.error(data.timestamp, service.base,
2724 'Database (ElasticSerach) not reachable!?');
2727 console.error(data.timestamp, JSON.stringify(log));
2729 service.info = function (log) {
2730 var data = getData('info', log);
2731 checkDatabase(function (isRunning) {
2733 writeLogToDB(data, function () {
2734 // console.log('log stored');
2737 console.error(data.timestamp, service.base, 'Database (ElasticSerach) not reachable!?');
2740 console.info(data.timestamp, JSON.stringify(log));
2742 service.warning = function (log) {
2743 var data = getData('warning', log);
2744 checkDatabase(function (isRunning) {
2746 writeLogToDB(data, function () {
2747 // console.log('log stored');
2750 console.error(data.timestamp, service.base, 'Database (ElasticSerach) not reachable!?');
2753 console.warn(data.timestamp, JSON.stringify(log));
2759 mwtnCommonsApp.register.factory('$mwtnEthernet', function ($http, $q) {
2762 service.base = window.location.origin + '/restconf';
2764 create: service.base + '/operations/route:create',
2765 delete: service.base + '/operations/route:delete'
2768 service.createForwardingConstruct = function(spec) {
2769 var deferred = $q.defer();
2773 url: service.url.create,
2778 nodeName: spec.nodeId,
2786 console.log(JSON.stringify(spec));
2787 console.log(JSON.stringify(request));
2789 var consoleId = 'create-forwarding-consturuct: ';
2790 console.time(consoleId);
2791 $http(request).then(function (success) {
2792 console.timeEnd(consoleId);
2793 console.log(JSON.stringify(success));
2794 deferred.resolve(success.data.output.status);
2795 }, function (error) {
2796 console.timeEnd(consoleId);
2797 // console.error(JSON.stringify(error.statusText));
2798 deferred.reject(error.statusText);
2800 return deferred.promise;
2803 service.deleteForwardingConstruct = function(spec) {
2805 var deferred = $q.defer();
2808 url: service.url.delete,
2809 data: {input:{vlanid:spec.ltp.slice(-2)}}
2811 console.log(JSON.stringify(spec));
2812 console.log(JSON.stringify(request));
2814 var consoleId = 'delete-forwarding-consturuct: ';
2815 console.time(consoleId);
2816 $http(request).then(function (success) {
2817 console.timeEnd(consoleId);
2818 console.log(JSON.stringify(success));
2819 deferred.resolve(success.data.output.status);
2820 }, function (error) {
2821 console.timeEnd(consoleId);
2822 // console.error(JSON.stringify(error.statusText));
2823 deferred.reject(error.statusText);
2825 return deferred.promise;
2831 // Service Database (ElasticSerach)
2832 mwtnCommonsApp.register.factory('$mwtnDatabase', function ($http, $q) {
2834 base: window.location.origin + '/database',
2840 // TODO getBase is not needed anymore
2841 service.getBase = function (functionId) {
2842 var deferred = $q.defer();
2849 return deferred.promise;
2852 service.genericRequest = function (databaseRequest) {
2853 var url = [databaseRequest.base, databaseRequest.index, databaseRequest.docType,
2854 databaseRequest.command].join('/');
2856 method: databaseRequest.method,
2859 from: databaseRequest.from,
2860 size: databaseRequest.size,
2861 sort: databaseRequest.sort,
2862 filter: databaseRequest.filter,
2863 query: databaseRequest.query
2866 // overwrite request data if given
2867 if (databaseRequest.data) {
2868 request.data = databaseRequest.data;
2870 var deferred = $q.defer();
2871 var consoleId = 'database: ' + url;
2872 console.time(consoleId);
2873 $http(request).then(function (success) {
2874 console.timeEnd(consoleId);
2875 // console.log(JSON.stringify(success));
2876 deferred.resolve(success);
2877 }, function (error) {
2878 console.timeEnd(consoleId);
2879 console.warn(JSON.stringify(error));
2880 deferred.reject(error);
2882 return deferred.promise;
2885 service.aggregationRequest = function (databaseRequest) {
2886 var url = [databaseRequest.base, databaseRequest.index, databaseRequest.docType,
2887 databaseRequest.command].join('/');
2889 method: databaseRequest.method,
2891 data: databaseRequest.aggregation
2893 var deferred = $q.defer();
2894 var consoleId = 'database: ' + url;
2895 console.time(consoleId);
2896 $http(request).then(function (success) {
2897 console.timeEnd(consoleId);
2898 deferred.resolve(success);
2899 }, function (error) {
2900 console.timeEnd(consoleId);
2901 console.warn(JSON.stringify(error));
2902 deferred.reject(error);
2904 return deferred.promise;
2907 service.getAllData = function (functionId, docType, from, size, sort) {
2908 var deferred = $q.defer();
2909 service.getBase(functionId).then(function (success) {
2910 var databaseRequest = {
2913 index: success.index,
2923 service.genericRequest(databaseRequest).then(function (success) {
2924 // console.log('getAllData', success);
2925 deferred.resolve(success);
2926 }, function (error) {
2927 deferred.reject(error);
2929 }, function (error) {
2930 deferred.reject(error);
2932 return deferred.promise;
2935 service.getFilteredData = function (functionId, docType, from, size, query) {
2936 var deferred = $q.defer();
2937 service.getBase(functionId).then(function (success) {
2938 var databaseRequest = {
2941 index: success.index,
2949 service.genericRequest(databaseRequest).then(function (success) {
2950 // console.log('getAllData', success);
2951 deferred.resolve(success);
2952 }, function (error) {
2953 deferred.reject(error);
2955 }, function (error) {
2956 deferred.reject(error);
2958 return deferred.promise;
2961 service.getFilteredSortedData = function (functionId, docType, from, size, sort, query) {
2962 var deferred = $q.defer();
2963 service.getBase(functionId).then(function (success) {
2964 var databaseRequest = {
2967 index: success.index,
2975 service.genericRequest(databaseRequest).then(function (success) {
2976 // console.log('getAllData', success);
2977 deferred.resolve(success);
2978 }, function (error) {
2979 deferred.reject(error);
2981 }, function (error) {
2982 deferred.reject(error);
2984 return deferred.promise;
2987 service.getAggregatedData = function (functionId, docType, aggregation) {
2988 var deferred = $q.defer();
2989 service.getBase(functionId).then(function (success) {
2990 var databaseRequest = {
2993 index: success.index,
2996 aggregation: aggregation
2998 service.aggregationRequest(databaseRequest).then(function (success) {
2999 deferred.resolve(success);
3000 }, function (error) {
3001 deferred.reject(error);
3003 }, function (error) {
3004 deferred.reject(error);
3006 return deferred.promise;
3009 service.getAggregations = function (functionId, docType, aggregations) {
3010 var deferred = $q.defer();
3011 service.getBase(functionId).then(function (success) {
3012 var databaseRequest = {
3015 index: success.index,
3018 aggregation: aggregations
3020 service.aggregationRequest(databaseRequest).then(function (success) {
3021 deferred.resolve(success);
3022 }, function (error) {
3023 deferred.reject(error);
3025 }, function (error) {
3026 deferred.reject(error);
3028 return deferred.promise;
3031 service.getData = function (docType, from, size, sort, filter, query) {
3032 var deferred = $q.defer();
3033 service.getBase('mwtn').then(function (success) {
3034 var databaseRequest = {
3037 index: success.index,
3045 service.genericRequest(databaseRequest).then(function (success) {
3046 deferred.resolve(success);
3047 }, function (error) {
3048 deferred.reject(error);
3050 }, function (error) {
3051 deferred.reject(error);
3053 return deferred.promise;
3056 service.deleteDocType = function (spec) {
3057 var deferred = $q.defer();
3058 service.getBase(spec.functionId).then(function (success) {
3059 var databaseRequest = {
3062 index: success.index,
3063 docType: spec.docType,
3068 service.genericRequest(databaseRequest).then(function (success) {
3069 deferred.resolve(status);
3070 }, function (error) {
3071 deferred.reject(error);
3073 }, function (error) {
3074 deferred.reject(error);
3076 return deferred.promise;
3080 * A promise, which inquires a single document from database.
3081 * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn').
3082 * @param {string} docType - The document type of the document to be deleted.
3083 * @param {string} id - An identifier of the document to be deleted.
3085 service.getSingleDocument = function (functionId, docType, id) {
3086 var deferred = $q.defer();
3087 service.getBase(functionId).then(function (success) {
3088 var databaseRequest = {
3091 index: success.index,
3096 service.genericRequest(databaseRequest).then(function (success) {
3097 deferred.resolve(success.data._source);
3098 }, function (error) {
3099 deferred.reject(error);
3101 }, function (error) {
3102 deferred.reject(error);
3104 return deferred.promise;
3108 * A promise, creating or updateing a single document of the database.
3109 * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn').
3110 * @param {string} docType - The document type of the document to be deleted.
3111 * @param {string} id - An identifier of the document to be deleted.
3112 * @param {Object} data - A json object to be stored in the database
3114 service.createSingleDocument = function (functionId, docType, id, data) {
3115 var deferred = $q.defer();
3116 service.getBase(functionId).then(function (success) {
3117 var databaseRequest = {
3120 index: success.index,
3126 service.genericRequest(databaseRequest).then(function (success) {
3127 deferred.resolve(success);
3128 }, function (error) {
3129 deferred.reject(error);
3131 }, function (error) {
3132 deferred.reject(error);
3134 return deferred.promise;
3138 * A promise, which deletes one document within the database.
3139 * @param {string} functionId - An identifier of an SDN function (e.g 'mwtn').
3140 * @param {string} docType - The document type of the document to be deleted.
3141 * @param {string} id - An identifier of the document to be deleted.
3143 service.deleteSingleDocument = function (functionId, docType, id) {
3144 var deferred = $q.defer();
3145 service.getBase(functionId).then(function (success) {
3146 var databaseRequest = {
3149 index: success.index,
3154 service.genericRequest(databaseRequest).then(function (success) {
3155 deferred.resolve({ status: success.status, logId: success.data._id });
3156 }, function (error) {
3157 deferred.reject(error);
3159 }, function (error) {
3160 deferred.reject(error);
3162 return deferred.promise;
3165 var moduleInformation;
3166 var inquireModuleInformation = function () {
3167 var deferred = $q.defer();
3168 service.getBase('mwtn').then(function (success) {
3169 var databaseRequest = {
3172 index: success.index,
3176 service.getAllData('mwtn', 'module', 0, 999, undefined).then(function (success) {
3177 // console.log(JSON.stringify(data.data.hits.hits));
3178 moduleInformation = {};
3179 success.data.hits.hits.map(function (hit) {
3180 moduleInformation[hit._id] = hit._source;
3182 // console.log('got moduleInformation', Object.keys(moduleInformation).length);
3183 return deferred.resolve(moduleInformation);
3184 }, function (error) {
3185 deferred.reject(error);
3187 }, function (error) {
3188 deferred.reject(error);
3190 return deferred.promise;
3194 * A promise which returns object yang class and attribute descriptions
3196 service.getModules = function () {
3197 var deferred = $q.defer();
3198 if (moduleInformation) {
3199 deferred.resolve(moduleInformation);
3201 inquireModuleInformation().then(function (success) {
3202 deferred.resolve(success);
3203 }, function (error) {
3204 deferred.reject(error);
3207 return deferred.promise;
3210 var schemaInformation;
3211 var inquireSchemaInformation = function () {
3212 var deferred = $q.defer();
3213 service.getBase('mwtn').then(function (success) {
3214 var databaseRequest = {
3217 index: success.index,
3221 service.getAllData('mwtn', 'schema-information', 0, 9999, undefined).then(function (success) {
3222 // console.log(JSON.stringify(data.data.hits.hits));
3223 schemaInformation = {};
3224 success.data.hits.hits.map(function (hit) {
3225 schemaInformation[hit._id] = hit._source;
3227 // console.log('got schemaInformation', Object.keys(schemaInformation).length);
3228 return deferred.resolve(schemaInformation);
3229 }, function (error) {
3230 deferred.reject(error);
3232 }, function (error) {
3233 deferred.reject(error);
3235 return deferred.promise;
3239 * A promise which returns object yang class and attribute descriptions
3241 service.getSchema = function () {
3242 var deferred = $q.defer();
3243 if (schemaInformation) {
3244 deferred.resolve(schemaInformation);
3246 inquireSchemaInformation().then(function (success) {
3247 deferred.resolve(success);
3248 }, function (error) {
3249 deferred.reject(error);
3252 return deferred.promise;
3257 // Class NetConfServer
3258 mwtnCommonsApp.register.factory('NetConfServer', function () {
3260 // Class NetConfServer
3261 var NetConfServer = function (data) {
3263 this.getData = function () {
3266 this.getRadioSignalId = function () {
3267 return this.data.airInterfaceConfiguration.radioSignalId;
3269 this.isLinkUp = function () {
3270 return this.data.airInterfaceStatus.linkIsUp;
3272 this.isPowerOn = function () {
3273 return this.data.airInterfaceConfiguration.powerIsOn;
3275 this.isActive = function () {
3276 return this.isPowerOn() && this.isLinkUp();
3279 return NetConfServer;
3282 mwtnCommonsApp.register.factory('ActualNetworkElement', function () {
3284 // Class ActualNetworkElement
3285 var ActualNetworkElement = function (data) {
3287 this.data.layerProtocols = {};
3288 this.setOnfNetworkElement = function (onfNe) {
3289 this.data.onfNetworkElement = onfNe;
3291 this.getLpByRadioSignalId = function (radioSignalId) {
3292 //console.log('getLP', JSON.stringify(this.data.ltp));
3294 for (var layerProtocolKey in this.data.layerProtocols) {
3295 if (this.data.layerProtocols[layerProtocolKey].getRadioSignalId &&
3296 radioSignalId === parseInt(this.data.layerProtocols[layerProtocolKey].getRadioSignalId())) {
3297 layerProtocol = this.data.layerProtocols[layerProtocolKey];
3300 return layerProtocol;
3302 this.getLpByRadioSignalIds = function (radioSignalIds) {
3303 //console.log('getLP', JSON.stringify(this.data.ltp));
3305 if (radioSignalIds !== undefined) {
3306 for (var layerProtocolKey in this.data.layerProtocols) {
3307 if (this.data.layerProtocols[layerProtocolKey].getRadioSignalIds &&
3308 radioSignalIds.toString() === this.data.layerProtocols[layerProtocolKey].getRadioSignalIds(this).toString()) {
3309 layerProtocol = this.data.layerProtocols[layerProtocolKey];
3313 return layerProtocol;
3315 this.setLP = function (onfPac) {
3316 this.data.layerProtocols[onfPac.data.layerProtocol] = onfPac;
3318 this.getLpPac = function (lpRef) {
3319 return this.data.layerProtocols[lpRef];
3321 this.getName = function () {
3322 return this.data.name;
3324 this.getConnectionStatus = function () {
3325 return this.data.connectionStatus;
3327 this.isConnected = function () {
3328 return this.data.name !== 'controller-config' && this.data.connectionStatus == 'connected';
3330 this.setConnectionStatus = function (status) {
3331 this.data.connectionStatus = status;
3334 return ActualNetworkElement;
3337 mwtnCommonsApp.register.factory('LogicalTerminationPoint', function ($mwtnGlobal, $mwtnLog) {
3338 // Sub-Class LayerProtocol
3340 * An object representing an LP.
3341 * @typedef {Object} LayerProtocol
3343 var LayerProtocol = function (data) {
3344 // take a guess, if termiation-state is not exposed
3345 if (data['termination-state'] === undefined) {
3347 data['termination-state'] = 'terminated-bidirectional';
3348 if (data['layer-protocol-name'] === "ETH") {
3349 data['termination-state'] = 'lp-can-never-terminate';
3351 $mwtnLog.warning({ component: 'LTP.getTerminationState', message: 'Check whether NE provided mandatory termination state. ' + data.uuid });
3352 } else if (data['termination-state'] === false || data['termination-state'] === 'false' ) {
3353 data['termination-state'] = 'terminated-bidirectional';
3356 // console.log('in', JSON.stringify(data));
3357 var defaultMapping = {
3359 // [FFA 1709] 'etc-ttp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-ethernet-container-pac' },
3360 'etc-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' },
3361 'tdm-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-tdm-container-pac' },
3364 'mws-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-PureEthernetStructure?module=MicrowaveModel-ObjectClasses-PureEthernetStructure', 'revision': '2016-09-02', 'conditional-package': 'MW_PureEthernetStructure_Pac' },
3365 'mwps-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-AirInterface?module=MicrowaveModel-ObjectClasses-AirInterface', 'revision': '2016-09-01', 'conditional-package': 'MW_AirInterface_Pac' },
3366 // 'mws-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:microwave-model?module=microwave-model', 'revision': '2017-03-24', 'conditional-package': 'mw-air-interface-diversity-pac' },
3368 'eth-ctp': { 'capability': 'urn:onf:params:xml:ns:yang:onf-ethernet-conditional-packages?module=onf-ethernet-conditional-packages', 'revision': '2017-04-02', 'conditional-package': 'ethernet-pac' },
3370 'mwps-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-AirInterface?module=MicrowaveModel-ObjectClasses-AirInterface', 'revision': '2016-09-01', 'conditional-package': 'MW_AirInterface_Pac' },
3371 'mws-ttp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-PureEthernetStructure?module=MicrowaveModel-ObjectClasses-PureEthernetStructure', 'revision': '2016-09-02', 'conditional-package': 'MW_PureEthernetStructure_Pac' },
3372 'eth-ctp-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' },
3373 'etc-ctp': { 'capability': 'uri:onf:MicrowaveModel-ObjectClasses-EthernetContainerl?module=MicrowaveModel-ObjectClasses-EthernetContainer', 'revision': '2016-09-02', 'conditional-package': 'MW_EthernetContainer_Pac' },
3376 // create empty extension, if not exists
3377 if (!data.extension) {
3378 data.extension = [];
3383 this.getData = function () {
3386 this.getId = function () {
3387 return this.getData().uuid;
3389 this.getLabel = function () {
3390 return ['LP(', this.getItuLabel(true).toUpperCase(), '): ', this.getId()].join('');
3392 this.getLayer = function () {
3393 var layer = this.getData()['layer-protocol-name'];
3394 if (layer === 'ETH-CTP') {
3399 this.getTerminationState = function (abstract) {
3400 // 3th PoC termination state is of type boolean
3401 if (this.getData()['termination-state'] === true) {
3403 } else if (this.getData()['termination-state'] === false) {
3406 // 4th PoC termination state is of type enum
3407 if (abstract !== true) {
3408 return this.getData()['termination-state'];
3411 'lp-can-never-terminate': 'ctp',
3412 'lt-not-terminated': 'ctp',
3413 'terminated-server-to-client-flow': 'ttp',
3414 'terminated-client-to-server-flow': 'ttp',
3415 'terminated-bidirectional': 'ttp',
3416 'lt-permenantly-terminated': 'ttp',
3417 'termination-state-unknown': 'ttp'
3419 return mapping[this.getData()['termination-state']];
3421 this.getItuLabel = function () {
3422 return [this.getLayer(), this.getTerminationState(true)].join('-').toLowerCase();
3424 this.getExtension = function (key) {
3425 var result = this.getData().extension.filter(function (ex) {
3426 return ex['value-name'] === key;
3427 }).map(function (ex) {
3430 if (result && result.length > 0) {
3433 // check hardcoded alternatives
3434 var ituLabel = this.getItuLabel();
3435 if (!defaultMapping[ituLabel]) {
3438 return defaultMapping[ituLabel][key];
3441 * A getter for the yang-capability of the LayerProtocol
3442 * @param {boolean|undefined} moduleOnly - Defines, whether the result should contain only yang-module-name.
3443 * @return {string} The conditional package name of the LayerProtocol
3445 this.getCapability = function (moduleOnly) {
3446 var cap = this.getExtension('capability');
3447 if (!cap) return '';
3449 // workaround bug in spec
3450 if (cap.contains('onf-ethernet-conditional-package') && !cap.contains('onf-ethernet-conditional-packages')) {
3451 console.warn('Inform vendor about spec error and updates');
3452 cap = cap.replaceAll('onf-ethernet-conditional-package', 'onf-ethernet-conditional-packages');
3454 if (cap !== '' && moduleOnly === true) {
3455 return cap.split('?module=')[1];
3459 this.getRevision = function () {
3460 return this.getExtension('revision');
3463 * A getter for the conditional package name of the LayerProtocol
3464 * @param {boolean|undefined} addModule - Defines, whether the result should include the yang-module-name.
3465 * @return {string} The conditional package name of the LayerProtocol
3467 this.getConditionalPackage = function (addModule) {
3468 var cp = this.getExtension('conditional-package');
3472 if (addModule === true) {
3473 return [this.getCapability(true), cp].join(':');
3479 // Sub-Class LogicalTerminationPoint
3481 * An object representing an LTP.
3482 * @typedef {Object} LogicalTerminationPoint
3484 var LogicalTerminationPoint = function (data) {
3486 this.layerProtocols = this.data.lp.map(function (layerProtocol) {
3487 return new LayerProtocol(layerProtocol);
3489 // console.log(this.layerProtocols);
3490 this.getData = function () {
3493 this.getId = function () {
3494 return this.getData().uuid;
3496 this.getName = function () {
3497 return this.getData().name[0].value;
3499 this.getDirectionality = function () {
3500 return this.getData()['ltp-direction'];
3502 this.getServerLtps = function () {
3503 return this.getData()['server-ltp'];
3505 this.getClientLtps = function () {
3506 return this.getData()['client-ltp'];
3508 this.getLayer = function () {
3509 return this.getLayerProtocols()[0].getLayer();
3511 this.getLabel = function () {
3512 return ['LTP(', this.getLayerProtocols()[0].getItuLabel(true).toUpperCase(), '): ', this.getId()].join('');
3514 this.getLayerProtocols = function () {
3515 return this.layerProtocols;
3517 this.getConditionalPackages = function () {
3518 console.error(JSON.stringifythis.getLayerProtocols()());
3519 return this.getLayerProtocols().map(function (lp) {
3520 return lp.getConditionalPackage();
3524 return LogicalTerminationPoint;
3527 mwtnCommonsApp.register.factory('PtpClock', function (PtpPort) {
3528 var PtpClock = function (data) {
3529 var COMPONENT = "PtpClock";
3531 if (data && data['instance-list'] && data['instance-list'][0]) {
3532 this.data = data['instance-list'][0];
3534 if (!this.data['port-ds-list'] || this.data['port-ds-list'].length === 0) {
3536 var message = ['The PTP clock', data['instance-number'], 'dose not support a single PTP port.'].join(' ');
3537 console.info({ component: COMPONENT, message: message });
3539 this.ptpPorts = this.data['port-ds-list'].map(function(ptpPort) {
3540 return new PtpPort(ptpPort);
3544 this.getData = function () {
3546 // return JSON.parse(JSON.stringify(this.data).replaceAll('onf-ptp-dataset:', ''));
3548 this.getIdentity = function(hex) {
3549 var defaultDs = this.getData()['default-ds'];
3550 var result = 'ERROR: no clock identity found';
3551 if (defaultDs && defaultDs['clock-identity']) {
3552 result = defaultDs['clock-identity'];
3554 result = result.base64ToHex();
3559 this.getParent = function(hex) {
3560 var parentDs = this.getData()['parent-ds'];
3561 var key = 'parent-port-identity';
3563 if (parentDs && parentDs[key] && parentDs[key]['clock-identity'] && parentDs[key]['port-number']) {
3564 result = parentDs[key]['clock-identity'];
3566 result = result.base64ToHex();
3568 result = [result, parentDs[key]['port-number']].join('#');
3572 this.getGrandMaster = function(hex) {
3573 var parentDs = this.getData()['parent-ds'];
3574 // console.warn(JSON.stringify(parentDs));
3575 var key = 'parent-port-identity';
3577 if (parentDs && parentDs['grandmaster-identity']) {
3578 result = parentDs['grandmaster-identity'];
3580 result = result.base64ToHex();
3585 this.getPtpPorts = function () {
3586 return this.ptpPorts;
3592 mwtnCommonsApp.register.factory('PtpPort', function () {
3593 var PtpPort = function (data) {
3595 this.getData = function () {
3598 this.getId = function() {
3599 return this.getData()['port-number'];
3601 this.getNumber = function() {
3602 return this.getData()['port-number'];
3604 this.getState = function() {
3605 return this.getData()['port-state'];
3607 this.isSlave = function() {
3608 return this.getData()['port-state'] === 'SLAVE';
3610 this.isMaster = function() {
3611 return this.getData()['port-state'] === 'MASTER';
3613 this.getLogicalTerminationPointReference = function() {
3614 return this.getData()['onf-ptp-dataset:logical-termination-point'];
3620 mwtnCommonsApp.register.factory('OnfNetworkElement', function ($mwtnGlobal, LogicalTerminationPoint) {
3622 // Class OnfNetworkElement
3623 var OnfNetworkElement = function (data) {
3624 var COMPONENT = "OnfNetworkElement";
3628 var message = ['No data received.'].join(' ');
3629 console.warn({ component: COMPONENT, message: message });
3633 // console.log(JSON.stringify(data));
3634 if (!this.data.ltp || this.data.ltp.length === 0) {
3635 this.logicalTerminationPoints = [];
3636 var message = ['The network-element', data.uuid, 'does not support a single LTP. No LTP -> no SDN integration via ONF core-model.'].join(' ');
3637 // TODO $mwtnLog -> Unknown provider: $mwtnlogProvider <- $mwtnlog <- OnfNetworkElement [sko] Dont get it ;(
3638 console.warn({ component: COMPONENT, message: message });
3640 this.logicalTerminationPoints = this.data.ltp.map(function (logicalTerminationPoint) {
3641 return new LogicalTerminationPoint(logicalTerminationPoint);
3645 this.getData = function () {
3648 this.getId = function () {
3649 return this.getData().uuid;
3651 this.getForwardingDomain = function () {
3652 return this.getData().fd;
3654 this.getName = function () {
3655 return this.getData().name[0].value || this.getData().uuid;
3657 this.getLogicalTerminationPoints = function () {
3658 return this.logicalTerminationPoints;
3660 this.getLtp = function (id) {
3661 var result = this.getLogicalTerminationPoints().filter(function (ltp) {
3662 return ltp.getId() === id;
3664 if (result.length === 1) {
3669 this.getLpById = function (id) {
3671 this.getLogicalTerminationPoints().map(function (ltp) {
3672 ltp.getLayerProtocols().map(function (lp) {
3673 if (lp.getData().uuid === id) {
3680 this.getNumberOfLtps = function () {
3681 return this.logicalTerminationPoints.length;
3683 this.getServerLtps = function (layerProtocolRef) {
3685 if (this.data._ltpRefList) {
3686 var ltpList = this.data._ltpRefList.map(function (ltp) {
3687 if (ltp.lp[0].uuid === layerProtocolRef) {
3688 result = ltp._serverLtpRefList;
3694 this.getClientLtpIds = function (layerProtocolRef) {
3696 if (this.data._ltpRefList) {
3697 var ltpList = this.data._ltpRefList.map(function (ltp) {
3698 if (ltp.lp[0].uuid === layerProtocolRef) {
3699 result = ltp._clientLtpRefList;
3705 this.getLpByLtpRef = function (ltpRef) {
3707 if (this.data._ltpRefList) {
3708 var ltpList = this.data._ltpRefList.map(function (ltp) {
3709 if (ltp.uuid === ltpRef) {
3716 this.getLtpsByLayer = function (layerProtocolName) {
3717 return this.getLogicalTerminationPoints().filter(function (ltp) {
3718 return ltp.getLayer() === layerProtocolName;
3721 this.getLTPMwpsList = function () {
3722 return this.getLtpsByLayer('MWPS');
3724 this.getLTPMwsList = function () {
3725 return this.getLtpsByLayer('MWS');
3727 this.getLTPEthCtpList = function () {
3728 return this.getLtpsByLayer('ETH');
3730 this.getLTPTdmCtpList = function () {
3731 return this.getLtpsByLayer('TDM');
3734 return OnfNetworkElement;
3737 mwtnCommonsApp.register.factory('MicrowavePhysicalSection', function () {
3739 // Class MicrowavePhysicalSection
3740 var MicrowavePhysicalSection = function (data) {
3742 this.getData = function () {
3745 this.getLayerProtocolId = function () {
3746 return this.getData().layerProtocol;
3748 this.getRadioSignalId = function () {
3749 return this.getData()['air-interface-configuration'] ? this.data['air-interface-configuration']['radio-signal-id'] : -1;
3751 this.isLinkUp = function () {
3752 return this.getData()['air-interface-status']['link-is-up'];
3754 this.isPowerOn = function () {
3755 return this.getData()['air-interface-configuration']['power-is-on'];
3757 this.isActive = function () {
3758 return this.isPowerOn() && this.isLinkUp();
3761 return MicrowavePhysicalSection;
3764 mwtnCommonsApp.register.factory('MicrowaveSection', function () {
3766 // Class MicrowaveSection
3767 var MicrowaveSection = function (data) {
3769 this.getData = function () {
3772 this.getId = function () {
3773 return this.data.layerProtocol;
3775 this.getRadioSignalIds = function (actualNe) {
3776 this.data.parent = actualNe;
3778 var onfNe = actualNe.data.onfNetworkElement;
3779 var lpId = this.getId();
3780 onfNe.getServerLtps(lpId).map(function (mwpsLtpRef) {
3781 var lpRef = onfNe.getLpByLtpRef(mwpsLtpRef).uuid;
3782 var mwps = actualNe.getLpPac(lpRef);
3783 result.push(mwps.getRadioSignalId());
3787 this.getTimeSlotCapacity = function () {
3788 return this.data.structureCapability.timeSlotCapacity;
3790 this.getTotalNumberOfTimeSlots = function () {
3791 return this.data.structureCapability.totalNumberOfTimeSlots;
3793 this.getNumberOfEffectiveTimeSlots = function () {
3795 this.data.structureStatus.timeSlotStatusList.map(function (ts) {
3796 if (ts.operationalStatus === 'ENABLED') {
3802 this.getConfiguredCapacity = function () {
3803 return this.getTotalNumberOfTimeSlots() * this.getTimeSlotCapacity();
3805 this.getEffectiveCapacity = function () {
3806 return this.getNumberOfEffectiveTimeSlots() * this.getTimeSlotCapacity();
3808 this.isActive = function () {
3809 if (this.data.parent === undefined) {
3812 var actualNe = this.data.parent;
3814 var onfNe = actualNe.data.onfNetworkElement;
3815 var lpId = this.getId();
3816 onfNe.getServerLtps(lpId).map(function (mwpsLtpRef) {
3817 var lpRef = onfNe.getLpByLtpRef(mwpsLtpRef).uuid;
3818 var mwps = actualNe.getLpPac(lpRef);
3819 result = result && mwps.isActive();
3824 return MicrowaveSection;