[CORD-1947] vEE OAM/CFM delay and jitter stat GUI
Change-Id: I82f364ed89805e9be7936adeefc49337917b57fd
diff --git a/xos/veestat/src/app/components/stats-service.ts b/xos/veestat/src/app/components/stats-service.ts
new file mode 100644
index 0000000..ef506ca
--- /dev/null
+++ b/xos/veestat/src/app/components/stats-service.ts
@@ -0,0 +1,286 @@
+
+/*
+ * Copyright 2017-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import * as _ from 'lodash';
+import IHttpPromiseCallbackArg = angular.IHttpPromiseCallbackArg;
+
+export interface IMicrosemiStatsBinData {
+ lowerLimit: string;
+ count: number;
+}
+
+export interface IMicrosemiStatsBin {
+ bins: IMicrosemiStatsBinData[];
+}
+
+export interface IMicrosemiStatsFormat {
+ interFrameDelayVariationTwoWayAvg: string;
+ interFrameDelayVariationTwoWayMax: string;
+ interFrameDelayVariationTwoWayMin: string;
+ interFrameDelayVariationTwoWayBins: IMicrosemiStatsBin;
+ FrameDelayTwoWayAvg: string;
+ FrameDelayTwoWayMax: string;
+ FrameDelayTwoWayMin: string;
+ FrameDelayTwoWayBins: IMicrosemiStatsBin;
+ [x: string]: any;
+}
+
+export interface IMicrosemiStatsData {
+ dm: {
+ dmId: any;
+ current: IMicrosemiStatsFormat;
+ historic: IMicrosemiStatsFormat[];
+ [x: string]: any;
+ };
+ dmId?: any;
+ current?: IMicrosemiStatsFormat;
+ historic?: IMicrosemiStatsFormat[];
+ [x: string]: any;
+
+}
+
+export interface IMicrosemiChartData {
+ labels: string[];
+ data: [number[]];
+}
+
+export interface IMicrosemiStats {
+ getMds(): any;
+ getMeps(mdName: string, maName: string): any;
+ getDms(mdName: string, maName: string, mepId: string): any;
+ get(mdName: string, maName: string, mepId: string, dmId: string): ng.IPromise<any>;
+ getAllData(res: IMicrosemiStatsData): any;
+}
+
+export interface IMicrosemiMdData {
+ mds?: [IMicrosemiMdFormat[]];
+ md?: IMicrosemiMdFormat;
+}
+
+export interface IMicrosemiMdFormat {
+ mdName: string;
+ mdNameType: string;
+ mdLevel: string;
+ mdNumericId: number;
+ maList: any[];
+}
+
+export interface IMicrosemiMaData {
+ ma: IMicrosemiMaFormat[];
+}
+
+export interface IMicrosemiMaFormat {
+ maName: string;
+ maNameType: string;
+ maNumericId: number;
+ 'ccm-interval': string;
+ componentList: any[];
+ 'rmep-list': any[];
+}
+
+export interface IMicrosemiMepData {
+ meps: [IMicrosemiMepFormat[]];
+}
+
+export interface IMicrosemiMepFormat {
+ mepId: number;
+ deviceId: string;
+ port: string;
+ direction: string;
+ mdName: string;
+ maName: string;
+ 'administrative-state': boolean;
+ 'cci-enabled': boolean;
+ 'ccm-ltm-priority': number;
+ macAddress: string;
+ loopback: any;
+ remoteMeps: any[];
+ activeMacStatusDefect: boolean;
+ activeRdiCcmDefect: boolean;
+
+}
+
+export interface IMicrosemiDmList {
+ dms: [IMicrosemiStatsData[]];
+}
+
+export class MicrosemiStats implements IMicrosemiStats {
+
+ static $inject = [
+ '$q',
+ '$http',
+ '$log',
+ '$base64'
+ ];
+
+ private auth = this.$base64.encode('onos:rocks');
+ private headers = {
+ 'Authorization': `Basic ${this.auth}`
+ };
+
+ constructor (
+ private $q: ng.IQService,
+ private $http: ng.IHttpService,
+ private $log: ng.ILogService,
+ private $base64: any
+ ) {
+
+ }
+
+ public getMds() {
+ const d = this.$q.defer();
+ this.$http.get(`/vtn/onos/cfm/md/`, {'headers': this.headers})
+ .then((res: IHttpPromiseCallbackArg<IMicrosemiMdData>) => {
+ d.resolve(res.data.mds[0]);
+ })
+ .catch(err => {
+ this.$log.error(`[CFMStatService] Error in GET md: `, err);
+ });
+ return d.promise;
+ }
+
+ public getMeps(mdName: string, maName: string) {
+ const d = this.$q.defer();
+ this.$http.get(`/vtn/onos/cfm/md/${mdName}/ma/${maName}/mep/`, {'headers': this.headers})
+ .then((res: IHttpPromiseCallbackArg<IMicrosemiMepData>) => {
+ d.resolve(res.data.meps[0]);
+ })
+ .catch(err => {
+ this.$log.error(`[CFMStatService] Error in GET mep: `, err);
+ });
+ return d.promise;
+ }
+
+ public getDms(mdName : string, maName: string, mepId: string) {
+ const d = this.$q.defer();
+ this.$http.get(`/vtn/onos/cfm/md/${mdName}/ma/${maName}/mep/${mepId}/dm/`, {'headers': this.headers})
+ .then((res: IHttpPromiseCallbackArg<IMicrosemiDmList>) => {
+ d.resolve(res.data.dms[0]);
+ })
+ .catch(err => {
+ this.$log.error(`[CFMStatService] Error in GET dm list: `, err);
+ });
+ return d.promise;
+ }
+
+ public get(mdName : string, maName: string, mepId: string, dmId: string) {
+ const d = this.$q.defer();
+
+ this.$http.get(`/vtn/onos/cfm/md/${mdName}/ma/${maName}/mep/${mepId}/dm/${dmId}`, {'headers': this.headers})
+ .then((res) => {
+ d.resolve(res);
+ })
+ .catch(err => {
+ this.$log.error(`[CFMStatService] Error in GET: `, err);
+ });
+ return d.promise;
+ }
+
+ public getAllData(res: IMicrosemiStatsData) {
+ const data = res['data'];
+ const line = this.parseDataForLine(data);
+ const delay = this.parseDelayBin(data);
+ const jitter = this.parseJitterBin(data);
+ return {
+ line,
+ delay,
+ jitter
+ };
+ }
+
+ private getNumericVal(val: string): number {
+ if (!val) {
+ return 0;
+ }
+ val = val.replace('PT', '');
+ val = val.replace('S', '');
+ return parseFloat(val) * 1000;
+ }
+
+ private formatDate(string: string): string {
+ const date = new Date(string);
+ return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
+ }
+
+ private parseDelayBin(stats: IMicrosemiStatsData) {
+ const labels: number[] = [];
+ const data: number[] = [];
+ _.forEach(stats.dm.current.frameDelayTwoWayBins.bins, (bin) => {
+ labels.push(this.getNumericVal(bin.lowerLimit));
+ data.push(bin.count);
+ });
+ return {
+ labels,
+ data
+ };
+ }
+
+ private parseJitterBin(stats: IMicrosemiStatsData) {
+ const labels: number[] = [];
+ const data: number[] = [];
+ _.forEach(stats.dm.current.interFrameDelayVariationTwoWayBins.bins, (bin) => {
+ labels.push(this.getNumericVal(bin.lowerLimit));
+ data.push(bin.count);
+ });
+ return {
+ labels,
+ data
+ };
+ }
+
+ private parseDataForLine(data: IMicrosemiStatsData): IMicrosemiChartData {
+ let stats = angular.copy(data.dm.historic);
+ stats.unshift(data.dm.current);
+
+ const jitterAvg: number[] = [];
+ const jitterMax: number[] = [];
+ const jitterMin: number[] = [];
+ const delayAvg: number[] = [];
+ const delayMax: number[] = [];
+ const delayMin: number[] = [];
+ const labels: string[] = [];
+
+ _.forEach(stats, (s: IMicrosemiStatsFormat) => {
+ const j_avg = this.getNumericVal(s.interFrameDelayVariationTwoWayAvg);
+ const j_max = this.getNumericVal(s.interFrameDelayVariationTwoWayMax);
+ const j_min = this.getNumericVal(s.interFrameDelayVariationTwoWayMin);
+ const d_avg = this.getNumericVal(s.frameDelayTwoWayAvg);
+ const d_max = this.getNumericVal(s.frameDelayTwoWayMax);
+ const d_min = this.getNumericVal(s.frameDelayTwoWayMin);
+ jitterAvg.push(j_avg);
+ jitterMax.push(j_max);
+ jitterMin.push(j_min);
+ delayAvg.push(d_avg);
+ delayMax.push(d_max);
+ delayMin.push(d_min);
+ labels.push(s.endTime ? this.formatDate(s.endTime) : 'current');
+ });
+
+ return {
+ labels: labels.reverse(),
+ data: [
+ jitterAvg.reverse(),
+ jitterMax.reverse(),
+ jitterMin.reverse(),
+ delayAvg.reverse(),
+ delayMax.reverse(),
+ delayMin.reverse(),
+ ]
+ };
+ }
+
+}