Merge "Cluster sanity test using openflow plugin"
authorLuis Gomez <ecelgp@gmail.com>
Sat, 28 Mar 2015 16:47:56 +0000 (16:47 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 28 Mar 2015 16:47:56 +0000 (16:47 +0000)
test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/010__Flows_OF13_Cluster.txt [new file with mode: 0644]
test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/SanityLibrary.py [new file with mode: 0644]
test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/__init__.txt [new file with mode: 0644]
test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/mininetwork.py [new file with mode: 0644]

diff --git a/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/010__Flows_OF13_Cluster.txt b/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/010__Flows_OF13_Cluster.txt
new file mode 100644 (file)
index 0000000..0a32545
--- /dev/null
@@ -0,0 +1,365 @@
+*** Settings ***
+Library        OperatingSystem
+Library        Collections
+Library        XML
+Library        SSHLibrary
+Library        ../../../../csit/libraries/XmlComparator.py
+Variables      ../../../../csit/variables/Variables.py
+Library        ../../../../csit/libraries/RequestsLibrary.py
+Library        ../../../../csit/libraries/Common.py
+Library        SanityLibrary
+Suite Setup       Create Controllers Sessions
+Suite Teardown    Delete All Sessions
+
+*** Variables ***
+#${member1}=        ODLVM1
+#${member2}=        ODLVM2
+#${member3}=        ODLVM3
+${switch_idx}=     1
+${switch_name}=    s${switch_idx}
+${url_m1_shard}=   /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-inventory-config,type=DistributedConfigDatastore
+${url_m2_shard}=   /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-2-shard-inventory-config,type=DistributedConfigDatastore
+${url_m3_shard}=   /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-3-shard-inventory-config,type=DistributedConfigDatastore
+${get_pers_url}=   /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-config-datastore-provider/distributed-config-store-module
+
+*** Test Cases ***
+Logging Initial Cluster Information
+    ${resp}=   Get Controller Response   session1  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-inventory-config,type=DistributedConfigDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session1  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-inventory-operational,type=DistributedOperationalDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session1  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-config-datastore-provider/distributed-config-store-module
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session1  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-operational-datastore-provider/distributed-operational-store-module
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session2  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-2-shard-inventory-config,type=DistributedConfigDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session2  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-2-shard-inventory-operational,type=DistributedOperationalDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session2  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-config-datastore-provider/distributed-config-store-module
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session2  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-operational-datastore-provider/distributed-operational-store-module
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session3  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-3-shard-inventory-config,type=DistributedConfigDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session3  /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-3-shard-inventory-operational,type=DistributedOperationalDatastore
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session3  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-config-datastore-provider/distributed-config-store-module
+    Log   ${resp.content}
+    ${resp}=   Get Controller Response   session3  /restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/distributed-datastore-provider:distributed-operational-datastore-provider/distributed-operational-store-module
+    Log   ${resp.content}
+Add Flow 1 To Controller1
+    Init Flow Variables    1   1   1
+    Log             ${data}
+    ${resp}=        Putxml    session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}   data=${data}
+    Log             ${resp.content}
+    ${msg}=  Set Variable   Adding flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+    Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Add Flow 2 To Controller2
+    Init Flow Variables    1   2   2
+    Log             ${data}
+    ${resp}=        Putxml    session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}   data=${data}
+    Log             ${resp.content}
+    ${msg}=  Set Variable   Adding flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+    Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Add Flow 3 To Controller3
+    Init Flow Variables    1   3   3
+    Log             ${data}
+    ${resp}=        Putxml    session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}   data=${data}
+    Log             ${resp.content}
+    ${msg}=  Set Variable   Adding flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+    Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Show Switch Content After Add
+     Sleep  20s
+     Write    dpctl dump-flows -O OpenFlow13
+     Sleep  1s
+     ${switchouput}    Read
+     Log     ${switchouput}
+Check Flow 1 Configured On Controller1
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 1 Operational On Controller1
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 1 Configured On Controller2
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 1 Operational On Controller2
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 1 Configured On Controller3
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 1 Operational On Controller3
+   Init Flow Variables   1    1    1
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Configured On Controller1
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Operational On Controller1
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Configured On Controller2
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Operational On Controller2
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Configured On Controller3
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 2 Operational On Controller3
+   Init Flow Variables   1    2    2
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Configured On Controller1
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Operational On Controller1
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Configured On Controller2
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Operational On Controller2
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Configured On Controller3
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Configured  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Check Flow 3 Operational On Controller3
+   Init Flow Variables   1    3    3
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${True}  ${pres}   msg=${msg}
+Delete Flow 1 On Controller1
+      Init Flow Variables    1   1   1
+      ${resp}=  Delete   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}
+      Log             ${resp.content}
+      ${msg}=  Set Variable  Delete flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+      Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Delete Flow 2 On Controller2
+      Init Flow Variables    1   2   2
+      ${resp}=  Delete   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}
+      Log             ${resp.content}
+      ${msg}=  Set Variable  Delete flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+      Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Delete Flow 3 On Controller3
+      Init Flow Variables    1   3   3
+      ${resp}=  Delete   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id}
+      Log             ${resp.content}
+      ${msg}=  Set Variable  Delete flow for /restconf/config/opendaylight-inventory:nodes/node/openflow:${switch_idx}/table/${table_id}/flow/${flow_id} failed, http response ${resp.status_code} received.
+      Should Be Equal As Strings   ${resp.status_code}   200   msg=${msg}
+Show Switch Content After Delete
+     Sleep  20s
+     Write    dpctl dump-flows -O OpenFlow13
+     Sleep  1s
+     ${switchouput}    Read
+     Log     ${switchouput}
+Check Flow 1 Not Configured On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 1 Not Operational On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 1 Not Configured On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 1 Not Operational On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 1 Not Configured On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 1 Not Operational On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 2 Not Configured On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 2 Not Operational On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 2 Not Configured On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 2 Not Operational On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 2 Not Configured On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/2
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 2 Not Operational On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 3 Not Configured On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 3 Not Operational On Controller1
+   ${resp}=   Get Controller Response   session1   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 3 Not Configured On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 3 Not Operational On Controller2
+   ${resp}=   Get Controller Response   session2   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+Check Flow 3 Not Configured On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/1/flow/3
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  404
+Check Flow 3 Not Operational On Controller3
+   ${resp}=   Get Controller Response   session3   /restconf/operational/opendaylight-inventory:nodes/node/openflow:1/table/1
+   Log    ${resp.content}
+   Should Be Equal As Strings  ${resp.status_code}  200
+   ${pres}  ${msg}=  Is Flow Operational2  ${data}   ${resp.content}
+   Run Keyword If   '''${msg}'''!='${EMPTY}'   Log   ${msg}
+   Should Be Equal  ${False}  ${pres}   msg=${msg}
+*** Keywords ***
+Init Flow Variables   [Arguments]   ${tableid}  ${flowid}  ${priority}
+      ${data}=       Get Flow Content   ${tableid}  ${flowid}  ${priority}
+      ${xmlroot}=    Parse Xml    ${data}
+      ${table_id}=   Set Variable  ${tableid}
+      ${flow_id}=    Set Variable  ${flowid}
+      ${flow_priority}=    Set Variable  ${priority}
+      Set Suite Variable   ${table_id}
+      Set Suite Variable   ${flow_id}
+      Set Suite Variable   ${flow_priority}
+      Set Suite Variable   ${data}
+      Set Suite Variable   ${xmlroot}
+Create Controllers Sessions
+    Create Session    session1    http://${CONTROLLER1}:${RESTCONFPORT}    auth=${AUTH}    headers=${HEADERS_XML}
+    Create Session    session2    http://${CONTROLLER2}:${RESTCONFPORT}    auth=${AUTH}    headers=${HEADERS_XML}
+    Create Session    session3    http://${CONTROLLER3}:${RESTCONFPORT}    auth=${AUTH}    headers=${HEADERS_XML}
+Get Controller Response  [Arguments]  ${session}  ${url}
+    ${headers}=      Create Dictionary   Accept   application/xml
+    ${resp}=   Get  ${session}  ${url}   headers=${headers}
+    Return From Keyword   ${resp}
+
diff --git a/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/SanityLibrary.py b/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/SanityLibrary.py
new file mode 100644 (file)
index 0000000..faf0ec0
--- /dev/null
@@ -0,0 +1,61 @@
+import json
+
+
+class SanityLibrary:
+
+    def get_flow_content(self, tid=1, fid=1, priority=1):
+
+        flow_template = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<flow xmlns="urn:opendaylight:flow:inventory">
+    <strict>false</strict>
+    <instructions>
+        <instruction>
+            <order>0</order>
+            <apply-actions>
+                <action>
+                    <order>0</order>
+                    <drop-action/>
+                </action>
+            </apply-actions>
+        </instruction>
+    </instructions>
+    <table_id>%s</table_id>
+    <id>%s</id>
+    <cookie_mask>4294967295</cookie_mask>
+    <installHw>false</installHw>
+    <match>
+        <ethernet-match>
+            <ethernet-type>
+                <type>2048</type>
+            </ethernet-type>
+        </ethernet-match>
+        <ipv4-source>10.0.0.1</ipv4-source>
+    </match>
+    <cookie>%s</cookie>
+    <flow-name>%s</flow-name>
+    <priority>%s</priority>
+    <barrier>false</barrier>
+</flow>'''
+
+        flow_data = flow_template % (tid, fid, fid, 'TestFlow-{}'.format(fid), priority)
+        return flow_data
+
+    def is_cluter_set_up(self, rsp1, rsp2, rsp3):
+        try:
+            states = []
+            for r in [rsp1, rsp2, rsp3]:
+                rj = json.loads(r)
+                states.append(rj['value']['RaftState'])
+                states.sort()
+            if states == ['Follower', 'Follower', 'Leader']:
+                return True
+        except Exception:
+            return False
+        return False
+
+    def get_persistence(self, rsp):
+        try:
+            rj = json.loads(rsp)
+            return rj['module'][0]['distributed-datastore-provider:config-properties']['persistent']
+        except:
+            pass
diff --git a/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/__init__.txt b/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/__init__.txt
new file mode 100644 (file)
index 0000000..f4bec22
--- /dev/null
@@ -0,0 +1,28 @@
+*** Settings ***
+Documentation     Test suite for the OpenDaylight base edition with of13, aimed for statistics manager
+Suite Setup       Start Suite
+Suite Teardown    Stop Suite
+Library           SSHLibrary
+
+*** Variables ***
+${start}          sudo python mininetwork.py --controllers=${CONTROLLER1},${CONTROLLER2},${CONTROLLER3}
+
+*** Keywords ***
+Start Suite
+    Log    Start the test on the base edition
+    Open Connection    ${MININET}    prompt=>
+    Login With Public Key    ${MININET_USER}    ${USER_HOME}/.ssh/id_rsa    any
+    Put File    ${CURDIR}/mininetwork.py   mininetwork.py
+    Write    sudo ovs-vsctl set-manager ptcp:6644
+    Write    sudo mn -c
+    Read Until   >
+    Write    ${start}
+    Read Until   mininet>
+
+Stop Suite
+    Log    Stop the test on the base edition
+    Read
+    Write    exit
+    Sleep    2
+    Read
+    Close Connection
diff --git a/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/mininetwork.py b/test/tools/OF_Test/robot_suites/500__OF_Cluster_Sanity_OF/mininetwork.py
new file mode 100644 (file)
index 0000000..80e12c5
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+
+from mininet.net import Mininet
+from mininet.node import OVSKernelSwitch, RemoteController
+from mininet.cli import CLI
+import multiprocessing
+import time
+import argparse
+
+
+d = 11
+c = 0
+b = 0
+a = 1
+
+
+def get_next_ip():
+    global a, b, c, d
+    rip = "{}.{}.{}.{}".format(d, c, b, a)
+    a += 1
+    if a == 255:
+        a = 1
+        b += 1
+    if b == 255:
+        b = 0
+        c += 1
+    if c == 255:
+        c = 0
+        d += 1
+    return rip
+
+# switchid and hostid
+hid = 0
+sid = 0
+
+
+def get_next_hid():
+    global hid
+    hid += 1
+    return hid
+
+
+def get_next_sid():
+    global sid
+    sid += 1
+    return sid
+
+
+def get_switch(net, hosts):
+    sname = 's{}'.format(get_next_sid())
+    s = net.addSwitch(sname)
+    for i in range(hosts):
+        hname = 'h{}'.format(get_next_hid())
+        hip = get_next_ip()
+        h = net.addHost(hname, ip=hip)
+        s.linkTo(h)
+        print "switch {}: host {}-{} added".format(sname, hname, hip)
+    return s
+
+
+def get_net(switches, hostpswtich, controllers=['10.25.2.9']):
+
+    net = Mininet(controller=RemoteController, switch=OVSKernelSwitch)
+
+    cs = []
+    for i, cip in enumerate(controllers):
+        c = net.addController('c{}'.format(i), controller=RemoteController, ip=cip, port=6633)
+        cs.append(c)
+        print "contrller {} created".format(c)
+
+    ss = []
+    for i in range(switches):
+        s = get_switch(net, hostpswtich)
+
+    net.build()
+    for c in cs:
+        c.start()
+
+    for s in ss:
+        s.start(cs)
+
+    return net
+
+
+class MininetworkProcess(multiprocessing.Process):
+    """Base class.
+    Do NOT use this class directly.
+    """
+    def __init__(self, swithes, hps, controllers=['10.25.2.9']):
+        super(MininetworkProcess, self).__init__()
+        self._event = multiprocessing.Event()
+        self._net = get_net(swithes, hps, controllers=controllers)
+
+    def run(self):
+        self._net.start()
+        self._net.staticArp()
+        while self._event.is_set() is False:
+            time.sleep(1)
+        self._net.stop()
+
+
+if __name__ == '__main__':
+    # setLogLevel( 'info' )
+    parser = argparse.ArgumentParser(description='Starts switches with specified controllers')
+    parser.add_argument('--controllers', default='10.25.2.9',
+                        help='Comma separated list of cluster members (default ="10.25.2.9,10.25.2.10,10.25.2.11")')
+    args = parser.parse_args()
+
+    net = get_net(3, 1, controllers=args.controllers.split(','))
+
+    net.start()
+    net.staticArp()
+    CLI(net)
+    net.stop()