From 3d202a04b99f0e61b6ccf8b7a5610e1a15ca58e7 Mon Sep 17 00:00:00 2001 From: Herbert Eiselt Date: Mon, 11 Feb 2019 14:54:12 +0100 Subject: Add sdnr wt odlux Add complete sdnr wireless transport app odlux core and apps Change-Id: I5dcbfb8f3b790e3bda7c8df67bd69d81958f65e5 Issue-ID: SDNC-576 Signed-off-by: Herbert Eiselt --- .../apps/connectApp/src/services/connectService.ts | 204 +++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts (limited to 'sdnr/wt/odlux/apps/connectApp/src/services') diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts new file mode 100644 index 000000000..0adcd49c6 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts @@ -0,0 +1,204 @@ +import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; +import { MountedNetworkElementType } from 'models/mountedNetworkElements'; +import { Topology, TopologyNode } from 'models/topologyNetconf'; + +import { requestRest } from '../../../../framework/src/services/restService'; +import { Result, HitEntry } from '../../../../framework/src/models/elasticSearch'; + + +/** + * Represents a web api accessor service for all Network Elements actions. + */ +class ConnectService { + /** + * Gets all known required network elements from the backend. + */ + public async getAllRequiredNetworkElements(): Promise<(RequiredNetworkElementType & { _id: string })[] | null> { + const path = 'database/mwtn/required-networkelement/_search'; + const query = { "query": { "match_all": {} } }; + + const result = await requestRest>(path, { method: "POST", body: JSON.stringify(query) }); + return result && result.hits && result.hits.hits && result.hits.hits.map(ne => ({ + _id: ne._id, + mountId: ne._source && ne._source.mountId, + host: ne._source && ne._source.host, + port: ne._source && ne._source.port, + username: ne._source && ne._source.username, + password: ne._source && ne._source.password, + })) || null; + } + + public async getRequiredNetworkElementByMountId(mountId:string): Promise<(RequiredNetworkElementType & { _id: string }) | null> { + const path = `database/mwtn/required-networkelement/${mountId}`; + + const result = await requestRest & { found: boolean }>(path, { method: "GET" }); + return result && result.found && result._source && { + _id: result._id, + mountId: result._source.mountId, + host: result._source.host, + port: result._source.port, + username: result._source.username, + password: result._source.password, + } || null; + + } + + /** + * Inserts data into the required network elements table. + */ + public async insertRequiredNetworkElement(element: RequiredNetworkElementType): Promise { + const path = `database/mwtn/required-networkelement/${ element.mountId }`; + const result = await requestRest(path, { method: "POST", body: JSON.stringify(element) }); + return result || null; + } + + /** + * Deletes data from the Required Network Elements backend. + */ + public async deleteRequiredNetworkElement(element: RequiredNetworkElementType): Promise { + const path = `database/mwtn/required-networkelement/${ element.mountId }`; + const result = await requestRest(path, { method: "DELETE", body: JSON.stringify(element) }); + return result || null; + } + + + + private static mapTopologyNode = (mountPoint: TopologyNode, required: boolean ) => { + // handle onfCapabilities + let onfCapabilities: { module: string, revision: string }[] | undefined = undefined; + let onfCoreModelRevision: string[] | undefined = undefined; + let onfAirInterfaceRevision: string[] | undefined = undefined; + + const capId = 'netconf-node-topology:available-capabilities'; + if (mountPoint[capId] && mountPoint[capId]['available-capability']) { + onfCapabilities = mountPoint[capId]['available-capability'].filter((cap) => { + return cap.capability.includes('?revision='); + }).map((cap) => { + return { + module: cap.capability.split(')')[1], + revision: cap.capability.split('?revision=')[1].substring(0, 10) + }; + }).sort((a, b) => { + if (a.module < b.module) return -1; + if (a.module > b.module) return 1; + return 0; + }); + } + + // handle clustered-connection-status + const statusId = 'netconf-node-topology:clustered-connection-status'; + let client = 'localhost'; + + if (mountPoint[statusId] && mountPoint[statusId]['netconf-master-node']) { + let node = mountPoint[statusId]['netconf-master-node']; + node = node.substring(node.indexOf('@')); + client = node.substring(1, node.indexOf(':')); + } + const mountId = mountPoint["node-id"]; + return { + mountId: mountId, + host: mountPoint["netconf-node-topology:host"], + port: mountPoint["netconf-node-topology:port"], + connectionStatus: mountPoint['netconf-node-topology:connection-status'], + capabilities: onfCapabilities || [], + required: required, + client + } + } + + /** Get all mounted network elements and fills the property required according to the database contents. */ + public async getMountedNetworkElementsList(): Promise { + const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf'; + + const topologyRequestPomise = requestRest<{ topology: Topology[] | null }>(path, { method: "GET" }, true); + const requiredNetworkElementsPromise = this.getAllRequiredNetworkElements(); + + const [netconfResponse, requiredNetworkElements] = await Promise.all([topologyRequestPomise, requiredNetworkElementsPromise]); + + // process topologyNetconf (get all known network elements) + const topologyNetconf = netconfResponse && netconfResponse.topology && netconfResponse.topology.find(topology => topology["topology-id"] === 'topology-netconf'); + let mountPoints = topologyNetconf && topologyNetconf.node && topologyNetconf.node.filter( + mountPoint => mountPoint['node-id'] !== 'controller-config').map(mountedElement => { + const required = requiredNetworkElements && requiredNetworkElements.some( + requiredElement => requiredElement.mountId === mountedElement["node-id"]); + return ConnectService.mapTopologyNode(mountedElement, !!required); + }); + + return mountPoints || []; + } + + /** Get one mounted network element. */ + public async getMountedNetworkElementByMountId(mountId: string): Promise { + const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + mountId; + const getMountedNetworkElementByMountIdPromise = requestRest<{ node: TopologyNode[] | null }>(path, { method: "GET" }, true); + const getRequiredNetworkElementByMountIdPromise = this.getRequiredNetworkElementByMountId(mountId); + + const [mountedNetworkElement, requiredNetworkElement] = await Promise.all([getMountedNetworkElementByMountIdPromise, getRequiredNetworkElementByMountIdPromise]); + return mountedNetworkElement && mountedNetworkElement.node && ConnectService.mapTopologyNode(mountedNetworkElement.node[0], requiredNetworkElement && requiredNetworkElement.mountId === mountedNetworkElement.node[0]["node-id"] || false) || null; + } + + /** Mounts an required network element. */ + public async mountNetworkElement(networkElement: RequiredNetworkElementType): Promise { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.mountId; + const mountXml = [ + '', + `${ networkElement.mountId }`, + `${ networkElement.host }`, + `${ networkElement.port }`, + `${ networkElement.username }`, + `${ networkElement.password }`, + ' false', + + ' ', + ' false', + ' 20000', + ' 100', + ' 2000', + ' 1.5', + + ' ', + ' 120', + ''].join(''); + + try { + const result = await requestRest<{}>(path, { + method: 'PUT', + headers: { + 'Content-Type': 'application/xml', + 'Accept': 'application/xml', + 'Authorization': 'Basic YWRtaW46YWRtaW4=' + }, + body: mountXml + }, true); + // expect an empty answer + return result === null; + } catch { + return false; + } + }; + + /** Unmounts a network element by its id. */ + public async unmountNetworkElement(mountId: string): Promise { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + mountId; + + try { + const result = await requestRest<{}>(path, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/xml', + 'Accept': 'application/xml', + 'Authorization': 'Basic YWRtaW46YWRtaW4=' + }, + }, true); + // expect an empty answer + return result === null; + + } catch { + return false; + } + }; + + +} +export const connectService = new ConnectService(); +export default connectService; -- cgit 1.2.3-korg