[ONOS-7876] Initial STC implementation for ODTN
Change-Id: I51a22348cc73c576c5d10551e84ca8ac2f2a2040
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java
index a2a5572..15208a2 100644
--- a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java
@@ -226,7 +226,8 @@
try {
dcs.createNode(rid, node);
} catch (FailedException e) {
- log.warn("Failed to add resource", e);
+ log.warn("Failed to add resource {}", rid);
+ log.debug("Exception", e);
}
}
}
diff --git a/tools/test/scenarios/bin/execute-tapi-context-get-call.py b/tools/test/scenarios/bin/execute-tapi-context-get-call.py
new file mode 100755
index 0000000..95cff90
--- /dev/null
+++ b/tools/test/scenarios/bin/execute-tapi-context-get-call.py
@@ -0,0 +1,43 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+import tapiHelper
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) < 3:
+ print "usage: execute-tapi-context-get-call onos-node state"
+ sys.exit(1)
+
+node = sys.argv[1]
+state = sys.argv[2] #if empty tapi context must be empty, if full it needs to contain all devices and ports
+
+if state != "empty" and len(sys.argv) == 3:
+ print "usage: execute-tapi-context-get-call onos-node full devices links ports"
+ sys.exit(1)
+
+request = 'http://' + node + ':8181/onos/restconf/data/tapi-common:context'
+tapiContext = tapiHelper.get_context(request)
+
+if state == "empty":
+ uuid = tapiContext['tapi-common:context']['tapi-topology:topology-context']['topology'][0]['uuid']
+ if uuid == "":
+ print "empty uuid"
+ sys.exit(1)
+ print "@stc tapi topology uuid=" + uuid
+ sys.exit(0)
+
+if state == "full":
+ devices = sys.argv[3]
+ links = sys.argv[4]
+ ports = sys.argv[5]
+ #TODO parse reply for number of devices, links and ports
+ print "Parsing for given topology not yet implemented"
+ sys.exit(0)
+
+sys.exit(1)
+
+
+
+
diff --git a/tools/test/scenarios/bin/execute-tapi-post-call.py b/tools/test/scenarios/bin/execute-tapi-post-call.py
new file mode 100755
index 0000000..031e276
--- /dev/null
+++ b/tools/test/scenarios/bin/execute-tapi-post-call.py
@@ -0,0 +1,46 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+import tapiHelper
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) < 4:
+ print "usage: execute-tapi-post-call onos-node context empty uuid. Uuid is optional and defaults to empty"
+ sys.exit(1)
+
+node = sys.argv[1]
+context = sys.argv[2]
+empty = sys.argv[3]
+
+if len(sys.argv) == 4:
+ uuid = ""
+else:
+ uuid = sys.argv[4]
+
+if "get-connectivity-service-list" in context:
+ connectivity_request = 'http://' + node + ':8181/onos/restconf/operations/' + context
+ tapi_connection = tapiHelper.get_connection(connectivity_request, uuid)
+ tapi_connection_json = tapi_connection.json()
+ print tapi_connection_json
+ if not tapi_connection_json["tapi-connectivity:output"] and empty != "empty":
+ print "No connection was established"
+ sys.exit(1)
+ #TODO verify empty connection if uuid is empty
+ #TODO verify correct connection if uuid is not empty
+ sys.exit(0)
+
+if "create-connectivity-service" in context:
+ context_request = 'http://' + node + ':8181/onos/restconf/data/tapi-common:context'
+ connectivity_request = 'http://' + node + ':8181/onos/restconf/operations/' + context
+ tapi_connection = tapiHelper.create_connection(context_request, connectivity_request)
+ print context
+ print tapi_connection.json()
+ sys.exit(0)
+
+sys.exit(1)
+
+
+
+
diff --git a/tools/test/scenarios/bin/tapiHelper.py b/tools/test/scenarios/bin/tapiHelper.py
new file mode 100755
index 0000000..74714d0
--- /dev/null
+++ b/tools/test/scenarios/bin/tapiHelper.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python3
+
+import requests
+import json
+import itertools
+
+#
+# Creates connectivity json
+#
+def tapi_input(sip_uuids):
+ create_input = {
+ "tapi-connectivity:input": {
+ "end-point" : [
+ {
+ "local-id": sip_uuids[0],
+ "service-interface-point": {
+ "service-interface-point-uuid" : sip_uuids[0]
+ }
+ }
+ ,
+ {
+ "local-id": sip_uuids[1],
+ "service-interface-point": {
+ "service-interface-point-uuid" : sip_uuids[1]
+ }
+ }
+ ]
+ }
+ }
+ return create_input
+
+#
+# Obtains TAPI context through restconf
+#
+def get_context(url_context):
+ resp = requests.get(url_context, auth=('onos', 'rocks'))
+ if resp.status_code != 200:
+ raise Exception('GET {}'.format(resp.status_code))
+ return resp.json()
+
+#
+# Requests a connectivity service
+#
+def request_connection(url_connectivity, context):
+ # All Context SIPs
+ sips = context["tapi-common:context"]["service-interface-point"]
+
+ # Sorted Photonic Media SIPs. filter is an iterable
+ esips = list(filter(is_dsr_media, sorted(sips, key=lambda sip: sip["name"][0]["value"])))
+ endpoints = [esips[0], esips[-1]]
+ sip_uuids = []
+ for sip in endpoints:
+ sip_uuids.append(sip["uuid"])
+ for uuid in sip_uuids:
+ print(uuid)
+
+ create_input_json = json.dumps(tapi_input(sip_uuids))
+ print (create_input_json)
+ headers = {'Content-type': 'application/json'}
+ resp = requests.post(url_connectivity, data=create_input_json, headers=headers, auth=('onos', 'rocks'))
+ if resp.status_code != 200:
+ raise Exception('POST {}'.format(resp.status_code))
+ return resp
+
+#
+# Filter method used to keep only SIPs that are photonic_media
+#
+def is_photonic_media(sip):
+ return sip["layer-protocol-name"]=="PHOTONIC_MEDIA"
+
+#
+# Filter method used to keep only SIPs that are DSR
+#
+def is_dsr_media(sip):
+ return sip["layer-protocol-name"]=="DSR"
+
+#
+# Processes the topology to verify the correctness
+#
+def process_topology():
+ # TODO use method to parse topology
+ # Getting the Topology
+ # topology = context["tapi-common:context"]["tapi-topology:topology-context"]["topology"][0]
+ # nodes = topology["node"];
+ # links = topology["link"];
+ noop
+
+#
+# Creates a connection first getting the context, parsing for SIPS and then issuing the request.
+#
+def create_connection(url_context, url_connectivity):
+ context = get_context(url_context)
+ return request_connection(url_connectivity, context)
+
+#
+# Obtains existing connectivity services
+#
+def get_connection(url_connectivity, uuid):
+ if(uuid == ""):
+ json = '{}'
+ else:
+ #TODO use uuid to retrieve given topo
+ print "Not Yet implemented"
+ json = '{}'
+ headers = {'Content-type': 'application/json'}
+ resp = requests.post(url_connectivity, data=json, headers=headers, auth=('onos', 'rocks'))
+ if resp.status_code != 200:
+ raise Exception('POST {}'.format(resp.status_code))
+ return resp
+
+
+
+
+
+
diff --git a/tools/test/scenarios/net-odtn-restconf.xml b/tools/test/scenarios/net-odtn-restconf.xml
new file mode 100644
index 0000000..93d2095
--- /dev/null
+++ b/tools/test/scenarios/net-odtn-restconf.xml
@@ -0,0 +1,54 @@
+<!--
+ ~ Copyright 2015-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.
+ -->
+<scenario name="net-odtn-restconf"
+ description="ODTN RESTCONF API test">
+ <group name="Net-ODTN-Restconf">
+
+ <!-- Verify the correct topology is present -->
+
+ <step name="Net-ODTN-Restconf.Tapi-context"
+ exec="execute-tapi-context-get-call.py ${OC1} empty"/>
+
+ <!-- Verify empty connectivity service -->
+
+ <step name="Net-ODTN-Restconf.Tapi-connectivity" requires="Net-ODTN-Restconf.Tapi-context"
+ exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
+
+ <!-- Push the connectivity service request -->
+
+ <!--<step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
+ exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list true"/>
+
+ <group name="ODTN-Net-Setup.Verify-Logs-3" requires="ODTN-Net-Setup.Tapi-connectivity">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-3-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+
+ <step name="ODTN-Net-Setup.Tapi-context" requires="ODTN-Net-Setup.Verify-Logs"
+ exec="execute-tapi-context-get-call.py ${OC1} empty"/>
+ <step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
+ exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty true"/>
+
+ <group name="ODTN-Net-Setup.Verify-Logs-4" requires="ODTN-Net-Setup.Tapi-connectivity">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-4-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>-->
+
+
+ </group>
+</scenario>
diff --git a/tools/test/scenarios/net-odtn-smoke.xml b/tools/test/scenarios/net-odtn-smoke.xml
new file mode 100644
index 0000000..e49ca73
--- /dev/null
+++ b/tools/test/scenarios/net-odtn-smoke.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ Copyright 2018-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.
+ -->
+
+
+<scenario name="net-odtn-smoke"
+ description="ODTN test steps">
+
+ <import file="${ONOS_SCENARIOS}/net-setup-odtn.xml"/>
+
+ <!--TODO check proper topology-->
+ <!--<step name="Net-ODTN-Smoke.Check-Summary"
+ requires="ODTN-Net-Setup.Verify-Logs-2" delay="5"
+ exec="onos-check-summary ${OC1} [0-9]* 4 8 0 112"/>-->
+
+ <import file="${ONOS_SCENARIOS}/net-odtn-restconf.xml"/>
+ <dependency name="Net-ODTN-Restconf" requires="ODTN-Net-Setup"/>
+
+ <import file="${ONOS_SCENARIOS}/net-teardown-odtn.xml"/>
+ <dependency name="Net-Teardown-ODTN" requires="Net-ODTN-Restconf"/>
+
+ <import file="${ONOS_SCENARIOS}/shutdown.xml"/>
+ <dependency name="Shutdown-ONOS" requires="Net-Teardown-ODTN"/>
+
+</scenario>
diff --git a/tools/test/scenarios/net-setup-odtn.xml b/tools/test/scenarios/net-setup-odtn.xml
new file mode 100644
index 0000000..78987a2
--- /dev/null
+++ b/tools/test/scenarios/net-setup-odtn.xml
@@ -0,0 +1,93 @@
+<!--
+ ~ Copyright 2015-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.
+ -->
+
+<scenario name="net-setup-odtn" description="ODTN network setup steps">
+
+ <group name="ODTN-Net-Setup">
+
+ <!-- Clean -->
+ <step name="ODTN-Net-Setup.Wipe-Out-Data-Before" exec="onos-wipe-out"/>
+
+ <!-- Make sure that there is no data in the system -->
+ <step name="ODTN-Net-Setup.Initial-Summary-Check" requires="~ODTN-Net-Setup.Wipe-Out-Data-Before"
+ exec="onos-check-summary ${OC1} [0-9]* 0 0 0"/>
+
+ <!-- Deactivate unneeded apps -->
+ <group name="ODTN-Net-Setup.Deactivate-Apps" requires="ODTN-Net-Setup.Initial-Summary-Check">
+ <step name="App-Deactivate-fwd"
+ exec="onos ${OCI} app deactivate org.onosproject.fwd"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ <step name="App-Deactivate-Openflow"
+ exec="onos ${OCI} app deactivate org.onosproject.openflow"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ <step name="App-Deactivate-Drivers"
+ exec="onos ${OCI} app deactivate org.onosproject.drivers"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ <step name="App-Deactivate-Mobility"
+ exec="onos ${OCI} app deactivate org.onosproject.mobility"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ <step name="App-Deactivate-ProxyArp"
+ exec="onos ${OCI} app deactivate org.onosproject.proxyarp"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ <step name="App-Deactivate-RouteService"
+ exec="onos ${OCI} app deactivate org.onosproject.route-service"
+ requires="ODTN-Net-Setup.Initial-Summary-Check"/>
+ </group>
+
+ <!-- Active required apps and yang models-->
+ <group name="ODTN-Net-Setup.Activate-Apps" requires="ODTN-Net-Setup.Deactivate-Apps">
+ <step name="App-Activate-Odtn-Service"
+ exec="onos ${OCI} app activate org.onosproject.odtn-service"
+ requires="ODTN-Net-Setup.Deactivate-Apps"/>
+ </group>
+
+ <group name="ODTN-Net-Setup.Verify-Apps" requires="ODTN-Net-Setup.Activate-Apps" delay="40">
+ <parallel var="${OC#}">
+ <step name="Check-Apps-${#}" exec="onos-check-apps ${OC#} optical-model,yang,config,configsync,faultmanagement,
+ netconf,configsync-netconf,drivers,drivers.netconf,drivers.optical,restconf,protocols.restconfserver,
+ odtn-api,drivers.odtn-driver,odtn-service,models.tapi,models.ietf,models.openconfig,models.openconfig-infinera,
+ models.openconfig-odtn includes"
+ requires="ODTN-Net-Setup.Activate-Apps"/>
+ </parallel>
+ </group>
+
+ <group name="ODTN-Net-Setup.Verify-Logs" requires="ODTN-Net-Setup.Verify-Apps">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+
+ <step name="ODTN-Net-Setup.Tapi-context" requires="ODTN-Net-Setup.Verify-Logs"
+ exec="execute-tapi-context-get-call.py ${OC1} empty"/>
+
+ <group name="ODTN-Net-Setup.Verify-Logs-2" requires="ODTN-Net-Setup.Tapi-context">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-2-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+
+ <!-- Verify empty connectivity service -->
+
+ <step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
+ exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
+
+ <!--TODO include check for empty connectivity service-->
+ <!--TODO include 2 or more docker emulators to setup the network for phase 1.0-->
+ <!--TODO push netcfg links between emulated devices -->
+ <!--TODO push emulated links between emulated devices -->
+ <!--TODO check logs -->
+ </group>
+</scenario>
diff --git a/tools/test/scenarios/net-teardown-odtn.xml b/tools/test/scenarios/net-teardown-odtn.xml
new file mode 100644
index 0000000..be063c1
--- /dev/null
+++ b/tools/test/scenarios/net-teardown-odtn.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright 2015-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.
+ -->
+<scenario name="net-teardown-odtn" description="Network teardown steps">
+ <group name="Net-Teardown-ODTN">
+ <!-- TODO remove docker simulators docker stop $(docker ps -aq) -->
+ <group name="ODTN-Net-Teardown.Deactivate-Apps-2">
+ <step name="App-Dectivate-Odtn-Service"
+ exec="onos ${OCI} app deactivate org.onosproject.odtn-service"/>
+ </group>
+ </group>
+</scenario>
\ No newline at end of file
diff --git a/tools/test/scenarios/shutdown.xml b/tools/test/scenarios/shutdown.xml
index 8ff43c5..f493da4 100644
--- a/tools/test/scenarios/shutdown.xml
+++ b/tools/test/scenarios/shutdown.xml
@@ -19,7 +19,7 @@
<step name="Stop-Service-${#}" exec="onos-service ${OC#} stop"/>
<step name="Wait-for-Stop-${#}" exec="onos-wait-for-stop ${OC#}"
requires="~Stop-Service-${#}"/>
- <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"
+ <step name="Shutdown-ONOS.Check-Logs-${#}" exec="onos-check-logs ${OC#}"
requires="~Wait-for-Stop-${#}"/>
</parallel>
</group>