Merge "Fix for namespace ordering, path of cfg files, links"
diff --git a/odtn-phase1-demo/src/App.js b/odtn-phase1-demo/src/App.js
index 0bd12cd..32a19fc 100644
--- a/odtn-phase1-demo/src/App.js
+++ b/odtn-phase1-demo/src/App.js
@@ -25,7 +25,8 @@
 import onos from './onos.png'
 import './App.css';
 import {
-  createConnectivityService,
+  createClientSideConnectivityService,
+  createLineSideConnectivityService,
   deleteConnectivityServices,
 } from './resources/dcs'
 import { getResources } from './resources/getResources'
@@ -100,7 +101,8 @@
 
   updateResource = () => {
     getResources().then( ( [ devices, connectivityServices ] ) => {
-      console.log( connectivityServices )
+      console.log( 'devices', devices )
+      console.log( 'connectivity services', connectivityServices )
       const portMap = this.getPortMap( devices )
       const network = Object.values( portMap ).map( this.setupGraph )
       this.setState( {
@@ -117,8 +119,7 @@
 
     devices.forEach( ( device, deviceIdx ) => {
       device.ports.forEach( port => {
-        const re = /\[\d*\]\((\d*)\)/
-        const portNum = re.exec( port.port )[ 1 ]
+        const portNum = parseInt(port.port)
         const lineNum = Math.floor( ( portNum - 1 ) % 100 / 2 )
 
         port.id = `${port.element}/${portNum}`
@@ -231,8 +232,6 @@
       }
       const oppositePort = ports.filter( port => port.sipId === oppositePortUuid )[ 0 ]
 
-      console.log( ports.filter( _port => !_port.isClient && _port.element === port.element ) )
-      console.log( ports.filter( _port => !_port.isClient && _port.element === oppositePort.element ) )
       internalEdges.push( {
         from: port.id,
         to: ports.filter( _port => !_port.isClient && _port.element === port.element )[ 0 ].id,
@@ -253,6 +252,27 @@
     return new Network( this.appRefList[ idx ].current, data, GRAPH_OPTION )
   }
 
+  deleteConnectivityServicePromise = (leftSipId, rightSipId) => {
+    const [ connectivitySrv, oppositePortUuid ] = this.getAssociatedConnectivity( leftSipId )
+    if ( oppositePortUuid !== rightSipId ) {
+      const message = 'Connectivity Service not found.'
+      this.setState( {
+        message,
+      } )
+      return Promise.reject(message)
+    }
+    if ( oppositePortUuid !== rightSipId ) {
+      const message = 'Connectivity Service and associated SIP are inconsistent.'
+      this.setState( {
+        message,
+      } )
+      return Promise.reject(message)
+    }
+    return deleteConnectivityServices( connectivitySrv.uuid )
+  }
+
+
+
   handleChange = ( ev ) => {
     if ( ev.target.name === 'left' ) {
       const request = Object.assign( {}, this.state.request, {
@@ -274,7 +294,7 @@
   handleCreate = () => {
     const { left, right } = this.state.request
     try {
-      this.checkRequest( left, right )
+      this.checkRequest( left.sipId, right.sipId )
     }catch(err){
       this.setState( {
         message: err.message,
@@ -283,7 +303,11 @@
       return
     }
 
-    createConnectivityService( left, right )
+    createClientSideConnectivityService( left.sipId, right.sipId )
+      .then( createLineSideConnectivityService.bind( null,
+        left.associatedLinePort.mediaSipId,
+        right.associatedLinePort.mediaSipId )
+      )
       .then( json => {
         const message = DEBUG ? JSON.stringify( json ) : 'Create ConnectivityService completed.'
         this.setState( {
@@ -304,7 +328,7 @@
   handleDelete = () => {
     const { left, right } = this.state.request
     try {
-      this.checkRequest( left, right )
+      this.checkRequest( left.sipId, right.sipId )
     }catch(err){
       this.setState( {
         message: err.message,
@@ -313,15 +337,8 @@
       return
     }
 
-    const [ connectivitySrv, clientPortUuid ] = this.getAssociatedConnectivity( left )
-    if ( clientPortUuid !== right ) {
-      const message = 'Connectivity Service not found.'
-      this.setState( {
-        message,
-      } )
-      return
-    }
-    deleteConnectivityServices( connectivitySrv.uuid )
+    this.deleteConnectivityServicePromise(left.sipId, right.sipId)
+      .then(this.deleteConnectivityServicePromise(left.associatedLinePort.mediaSipId, right.associatedLinePort.mediaSipId))
       .then( json => {
         const message = 'Delete ConnectivityService completed.'
         this.setState( {
@@ -378,7 +395,7 @@
                           } }>
                     {
                       leftSipPorts.map( port => (
-                        <MenuItem key={ port.id } value={ port.sipId }>{ port.id }</MenuItem>
+                        <MenuItem key={ port.id } value={ port }>{ port.id }</MenuItem>
                       ) )
                     }
                   </Select>
@@ -397,7 +414,7 @@
                           } }>
                     {
                       rightSipPorts.map( port => (
-                        <MenuItem key={ port.id } value={ port.sipId }>{ port.id }</MenuItem>
+                        <MenuItem key={ port.id } value={ port }>{ port.id }</MenuItem>
                       ) )
                     }
                   </Select>
diff --git a/odtn-phase1-demo/src/resources/dcs.js b/odtn-phase1-demo/src/resources/dcs.js
index c3dd27c..1e17c40 100644
--- a/odtn-phase1-demo/src/resources/dcs.js
+++ b/odtn-phase1-demo/src/resources/dcs.js
@@ -66,7 +66,7 @@
 }
 
 
-export function createConnectivityService(sip1, sip2) {
+export function createClientSideConnectivityService( sip1, sip2) {
 
   return new Promise((resolve, reject) => {
     fetch(`/dcs/operations/tapi-connectivity:create-connectivity-service`, {
@@ -74,7 +74,7 @@
       headers: {
         "Content-Type": "application/json",
       },
-      body: getCreateRequestBody(sip1, sip2)
+      body: getCreateClientSideRequestBody(sip1, sip2)
     })
       .then(res => {
         console.log(res)
@@ -90,6 +90,29 @@
   })
 }
 
+export function createLineSideConnectivityService( sip1, sip2) {
+
+  return new Promise((resolve, reject) => {
+    fetch(`/dcs/operations/tapi-connectivity:create-connectivity-service`, {
+      method: 'POST',
+      headers: {
+        "Content-Type": "application/json",
+      },
+      body: getCreateLineSideRequestBody(sip1, sip2)
+    })
+      .then(res => {
+        console.log(res)
+        if (res.ok) {
+          res.json().then(data => resolve(data["tapi-connectivity:output"]["service"]))
+        } else {
+          reject(res.text())
+        }
+      })
+      .catch(err => {
+        console.error(err)
+      })
+  })
+}
 
 export function deleteConnectivityServices(uuid) {
 
@@ -116,7 +139,7 @@
 }
 
 
-function getCreateRequestBody(sip1, sip2){
+function getCreateLineSideRequestBody(sip1, sip2){
   return `{
     "tapi-connectivity:input":
     {
@@ -125,14 +148,47 @@
                 "local-id": "id1",
                 "service-interface-point": {
                     "service-interface-point-uuid" : "${sip1}"
-                }
+                },
+                "layer-protocol-qualifier" : "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
+                "direction": "BIDIRECTIONAL",
+                "protection-role": "WORK",
+                "layer-protocol-name": "PHOTONIC_MEDIA"
             }
             ,
             {
                 "local-id": "id2",
                 "service-interface-point": {
                     "service-interface-point-uuid" : "${sip2}"
-                }
+                },
+                "layer-protocol-qualifier" : "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
+                "direction": "BIDIRECTIONAL",
+                "protection-role": "WORK",
+                "layer-protocol-name": "PHOTONIC_MEDIA"
+            }
+        ]
+    }
+}`
+}
+
+function getCreateClientSideRequestBody(sip1, sip2){
+  return `{
+    "tapi-connectivity:input":
+    {
+        "end-point" : [
+            {
+                "local-id": "id1",
+                "service-interface-point": {
+                    "service-interface-point-uuid" : "${sip1}"
+                },
+                "layer-protocol-name": "DSR"
+            }
+            ,
+            {
+                "local-id": "id2",
+                "service-interface-point": {
+                    "service-interface-point-uuid" : "${sip2}"
+                },
+                "layer-protocol-name": "DSR"
             }
         ]
     }
diff --git a/odtn-phase1-demo/src/resources/getResources.js b/odtn-phase1-demo/src/resources/getResources.js
index d92b3f2..aa35f0e 100644
--- a/odtn-phase1-demo/src/resources/getResources.js
+++ b/odtn-phase1-demo/src/resources/getResources.js
@@ -30,18 +30,40 @@
     })
     .then(([deviceDetails, sipDetails, connectivityService]) => {
 
-      const sipIdMap = sipDetails.reduce((_sipIdMap, sipDetail) => {
-        _sipIdMap[sipDetail.name.filter(kv => kv["value-name"] === "onos-cp")[0].value] = sipDetail.uuid
-        return _sipIdMap
-      }, {})
-      console.log(sipIdMap)
+      const dsrSipIdMap = sipDetails
+        .filter(filterSipsByLayer.bind(null, "DSR"))
+        .reduce((_sipIdMap, sipDetail) => {
+          _sipIdMap[sipDetail.name.filter(kv => kv["value-name"] === "onos-cp")[0].value] = sipDetail.uuid
+          return _sipIdMap
+        }, {})
+      const mediaSipIdMap = sipDetails
+        .filter(filterSipsByLayer.bind(null, "PHOTONIC_MEDIA"))
+        .reduce((_sipIdMap, sipDetail) => {
+          _sipIdMap[sipDetail.name.filter(kv => kv["value-name"] === "onos-cp")[0].value] = sipDetail.uuid
+          return _sipIdMap
+        }, {})
+      const portMap = {}
+
+      console.log('DSR SIP ID Map', dsrSipIdMap)
+      console.log('PhotinicMedia SIP ID Map', mediaSipIdMap)
 
       deviceDetails.forEach(deviceDetail => {
         deviceDetail.ports.forEach(port => {
           const key = `${port.element}/${port.port}`
-          if(sipIdMap[key]) {
-            port.sipId = sipIdMap[key]
+          if(dsrSipIdMap[key]) {
+            port.sipId = dsrSipIdMap[key]
           }
+          if(mediaSipIdMap[key]) {
+            port.mediaSipId = mediaSipIdMap[key]
+          }
+          portMap[key] = port
+        })
+      })
+
+      deviceDetails.forEach(deviceDetail => {
+        deviceDetail.ports.filter(filterClientSidePort).forEach(cliPort => {
+          const linePortKey = `${cliPort.element}/${parseInt(cliPort.port) + 100}`
+          cliPort.associatedLinePort = portMap[linePortKey]
         })
       })
 
@@ -51,4 +73,12 @@
       console.error(err)
     })
 
+}
+
+function filterClientSidePort(port) {
+  return Math.floor( parseInt(port.port) / 100 ) === 1
+}
+
+function filterSipsByLayer(layerProtocolName, sipDetail) {
+  return sipDetail["layer-protocol-name"] === layerProtocolName
 }
\ No newline at end of file
diff --git a/odtn-phase1-demo/src/setupProxy.js b/odtn-phase1-demo/src/setupProxy.js
index b7975b5..4233cfd 100644
--- a/odtn-phase1-demo/src/setupProxy.js
+++ b/odtn-phase1-demo/src/setupProxy.js
@@ -1,7 +1,10 @@
 const proxy = require('http-proxy-middleware');
+
+const onosHost = 'localhost'
+
 module.exports = function(app) {
   app.use(proxy('/onos', {
-    "target": "http://localhost:8181/onos/v1",
+    "target": `http://${onosHost}:8181/onos/v1`,
     "pathRewrite": {
       "^/onos": "",
     },
@@ -13,7 +16,7 @@
   }))
 
   app.use(proxy('/dcs', {
-    "target": "http://localhost:8181/onos/restconf",
+    "target": `http://${onosHost}:8181/onos/restconf`,
     "pathRewrite": {
       "^/dcs": "",
     },