Update the payload of network-topology-pcep node 07/102407/3
authorSangwook Ha <sangwook.ha@verizon.com>
Sat, 17 Sep 2022 20:31:51 +0000 (13:31 -0700)
committerSangwook Ha <sangwook.ha@verizon.com>
Sat, 17 Sep 2022 22:50:53 +0000 (15:50 -0700)
In Chlorine network-pcep-topology-config.yang was removed (BGPCEP-990)
and 'session-config' in the network-topology-pcep node is augmented from
network-topology-pcep.yang.

Update the namespace of 'session-config' in the configuration payload to
that of network-topology-pcep.yang for Chlorine.

The soft links to the aluminium directories were replaced with chlorine
directories with files copied from aluminium. The only files changed are
the following two PUT payload:

- pcepuser/chlorine/node_speaker_entity_identifier/data.xml
- tcpmd5user/chlorine/pcep_topology_node/data.xml

Change-Id: I1e54f7a65cc31884a9c6ae2d03fa5fd51ac95638
Signed-off-by: Sangwook Ha <sangwook.ha@verizon.com>
22 files changed:
csit/variables/pcepuser/chlorine [deleted symlink]
csit/variables/pcepuser/chlorine/node_session_state/location.uri [new file with mode: 0644]
csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/data.xml [new file with mode: 0644]
csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/location.uri [new file with mode: 0644]
csit/variables/pcepuser/chlorine/pcep_topology/location.uri [new file with mode: 0644]
csit/variables/pcepuser/chlorine/variables.py [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine [deleted symlink]
csit/variables/tcpmd5user/chlorine/default_off/data.json [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_off/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_state/data.json [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_state/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_state/volatiles.list [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_updated_state/data.json [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_updated_state/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/default_on_updated_state/volatiles.list [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/pcep_topology_node/data.xml [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/pcep_topology_node/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/data.xml [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/update_delegated/location.uri [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/update_delegated/post_data.xml [new file with mode: 0644]
csit/variables/tcpmd5user/chlorine/variables.py [new file with mode: 0644]

diff --git a/csit/variables/pcepuser/chlorine b/csit/variables/pcepuser/chlorine
deleted file mode 120000 (symlink)
index 121ca56..0000000
+++ /dev/null
@@ -1 +0,0 @@
-aluminium
\ No newline at end of file
diff --git a/csit/variables/pcepuser/chlorine/node_session_state/location.uri b/csit/variables/pcepuser/chlorine/node_session_state/location.uri
new file mode 100644 (file)
index 0000000..0348c3e
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology/node=pcc%3A%2F%2F$IP/pcep-session-state?content=nonconfig
diff --git a/csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/data.xml b/csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/data.xml
new file mode 100644 (file)
index 0000000..fc7e22d
--- /dev/null
@@ -0,0 +1,8 @@
+<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+    <node-id>$IP</node-id>
+    <session-config xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+        <speaker-entity-id-value xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep:sync:optimizations:config">
+            AQIDBA==
+        </speaker-entity-id-value>
+    </session-config>
+</node>
diff --git a/csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/location.uri b/csit/variables/pcepuser/chlorine/node_speaker_entity_identifier/location.uri
new file mode 100644 (file)
index 0000000..b2a9868
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology/node=$IP
diff --git a/csit/variables/pcepuser/chlorine/pcep_topology/location.uri b/csit/variables/pcepuser/chlorine/pcep_topology/location.uri
new file mode 100644 (file)
index 0000000..8e7a122
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology?content=nonconfig
diff --git a/csit/variables/pcepuser/chlorine/variables.py b/csit/variables/pcepuser/chlorine/variables.py
new file mode 100644 (file)
index 0000000..dda6c50
--- /dev/null
@@ -0,0 +1,263 @@
+"""Variables file for pcepuser suite.
+
+Expected JSON templates are fairly long,
+therefore there are moved out of testcase file.
+Also, it is needed to generate base64 encoded tunnel name
+from Mininet IP (which is not known beforehand),
+so it is easier to employ Python here,
+than do manipulation in Robot file."""
+# Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0 which accompanies this distribution,
+# and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import base64
+from string import Template
+
+
+__author__ = "Vratko Polak"
+__copyright__ = "Copyright(c) 2015, Cisco Systems, Inc."
+__license__ = "Eclipse Public License v1.0"
+__email__ = "vrpolak@cisco.com"
+
+
+def get_variables(mininet_ip):
+    """Return dict of variables for the given IP address of Mininet VM."""
+    variables = {}
+    # 'V' style of explanation.
+    # Comments a nalyze from high level, to low level, then code builds from low level back to high level.
+    # ### Pcep-topology JSON responses.
+    # Some testcases see only the tunnel created by pcc-mock start: "delegated tunnel" (ID 1).
+    # Other testcases see also tunnel created on ODL demand: "instatntiated tunnel" (ID 2).
+    # Both tunnels can have two states. "Default" upon creation with single hop "1.1.1.1",
+    # and "updated" after update-lsp, which prepends another hop "2.2.2.2".
+    # Variable naming always specifies delegated state first, and ends with _json to distinguish from operation data.
+    # The whole list: default_json, updated_json, updated_default_json, updated_updated_json.
+    # Oh, and the state without mock-pcc connected is off_json.
+    # off_json has '{}' substring and no variable data, so here it is as a special case:
+    variables[
+        "off_json"
+    ] = """{
+ "network-topology:topology": [
+  {
+   "topology-id": "pcep-topology",
+   "topology-types": {
+    "network-topology-pcep:topology-pcep": {}
+   }
+  }
+ ]
+}"""
+    # Ok, other _json strings will have more regular structure and some variable data,
+    # so we will be using templates heavily.
+    # First off, there is segment describing PCC which conatins IP address but is otherwise constant.
+    # So the top-level template will look like this:
+    json_templ = Template(
+        """{
+ "network-topology-pcep:path-computation-client": {
+  "ip-address": "$IP",
+  "reported-lsp": [$LSPS
+  ],
+  "state-sync": "synchronized",
+  "stateful-tlv": {
+   "odl-pcep-ietf-stateful:stateful": {
+    "lsp-update-capability": true,
+    "odl-pcep-ietf-initiated:initiation": true
+   }
+  }
+ }
+}"""
+    )
+    # The _json variables will differ only in $LSPS, but $IP will be present inside.
+    # Thus, the $IP substitution will come last, and any auxiliary substitutions before this final one
+    # will have to use safe_substitute().
+    # As you see, $LSPS is in json_templ without preceding newline.
+    # As a rule, a segment will always start with endline and end without endline,
+    # so that we can add comma where needed.
+    # Discussion amout delegated and instantiated implies that $LSPS is either a single delegated LSP
+    # or a pair of delegated and instantiated (separated by comma) LSPS, in appropriate state.
+    # Of course, one LSP always follow a structure, for which here is the template:
+    lsp_templ = Template(
+        """
+   {
+    "name": "$NAME",
+    "path": [
+     {
+      "ero": {
+       "ignore": false,
+       "processing-rule": false,
+       "subobject": [$HOPS
+       ]
+      },
+      "lsp-id": $ID,
+      "odl-pcep-ietf-stateful:lsp": {
+       "administrative": true,
+       "delegate": true,
+       "ignore": false,
+       "odl-pcep-ietf-initiated:create": $CREATED,
+       "operational": "up",
+       "plsp-id": $ID,
+       "processing-rule": false,
+       "remove": false,
+       "sync": true,
+       "tlvs": {
+        "lsp-identifiers": {
+         "ipv4": {
+          "ipv4-extended-tunnel-id": "$IP",
+          "ipv4-tunnel-endpoint-address": "1.1.1.1",
+          "ipv4-tunnel-sender-address": "$IP"
+         },
+         "lsp-id": $ID,
+         "tunnel-id": $ID
+        },
+        "symbolic-path-name": {
+         "path-name": "$CODE"
+        }
+       }
+      }
+     }
+    ]
+   }"""
+    )
+    # IDs were already talked about, IP will be set last. Now, $NAME.
+    # Pcc-mock uses a fixed naming scheme for delegated tunnels, so one more template can be written,
+    # but it is so simple we can write just the one-line code instead:
+    delegated_name = "pcc_" + mininet_ip + "_tunnel_1"  # 1 == ID
+    # For the instantiated tunnel, user is free to specify anything, even charachers such as \u0000 work.
+    # But as we need to plug the name to XML, let us try something more friendly:
+    instantiated_name = "Instantiated tunnel"
+    # What is CODE? The NAME in base64 encoding (without endline):
+    delegated_name_bytes = delegated_name.encode("ascii")
+    delegated_code_encoded = base64.b64encode(delegated_name_bytes)
+    delegated_code = delegated_code_encoded.decode("ascii")
+    instantiated_name_bytes = instantiated_name.encode("ascii")
+    instantiated_code_encoded = base64.b64encode(instantiated_name_bytes)
+    instantiated_code = instantiated_code_encoded.decode("ascii")
+
+    # The remaining segment is HOPS, and that is the place where default and updated states differ.
+    # Once again, there is a template for a single hop:
+    hop_templ = Template(
+        """
+       {
+         "ip-prefix": {
+          "ip-prefix": "$HOPIP/32"
+         },
+         "loose": false
+       }"""
+    )
+    # The low-to-high part of V comes now, it is just substituting and concatenating.
+    # Hops:
+    final_hop = hop_templ.substitute({"HOPIP": "1.1.1.1"})
+    update_hop = hop_templ.substitute({"HOPIP": "2.2.2.2"})
+    both_hops = update_hop + "," + final_hop
+    # Lsps:
+    default_lsp_templ = Template(lsp_templ.safe_substitute({"HOPS": final_hop}))
+    updated_lsp_templ = Template(lsp_templ.safe_substitute({"HOPS": both_hops}))
+    repl_dict = {
+        "NAME": delegated_name,
+        "ID": "1",
+        "CODE": delegated_code,
+        "CREATED": "false",
+    }
+    delegated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
+    delegated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
+    repl_dict = {
+        "NAME": instantiated_name,
+        "ID": "2",
+        "CODE": instantiated_code,
+        "CREATED": "true",
+    }
+    instantiated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
+    instantiated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
+    # Json templates (without IP set).
+    repl_dict = {"LSPS": delegated_default_lsp}
+    default_json_templ = Template(json_templ.safe_substitute(repl_dict))
+    repl_dict = {"LSPS": delegated_updated_lsp}
+    updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
+    repl_dict = {"LSPS": delegated_updated_lsp + "," + instantiated_default_lsp}
+    updated_default_json_templ = Template(json_templ.safe_substitute(repl_dict))
+    repl_dict = {"LSPS": delegated_updated_lsp + "," + instantiated_updated_lsp}
+    updated_updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
+    # Final json variables.
+    repl_dict = {"IP": mininet_ip}
+    variables["default_json"] = default_json_templ.substitute(repl_dict)
+    variables["updated_json"] = updated_json_templ.substitute(repl_dict)
+    variables["updated_default_json"] = updated_default_json_templ.substitute(repl_dict)
+    variables["updated_updated_json"] = updated_updated_json_templ.substitute(repl_dict)
+    # ### Pcep operations XML data.
+    # There are three operations, so let us just write templates from information at
+    # https://wiki.opendaylight.org/view/BGP_LS_PCEP:Programmer_Guide#Tunnel_Management_for_draft-ietf-pce-stateful-pce-07_and_draft-ietf-pce-pce-initiated-lsp-00
+    # _xml describes content type and also distinguishes from similarly named _json strings.
+    add_xml_templ = Template(
+        '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
+        " <node>pcc://$IP</node>\n"
+        " <name>$NAME</name>\n"
+        ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
+        '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
+        "</network-topology-ref>\n"
+        " <arguments>\n"
+        '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
+        "   <delegate>true</delegate>\n"
+        "   <administrative>true</administrative>\n"
+        "  </lsp>\n"
+        "  <endpoints-obj>\n"
+        "   <ipv4>\n"
+        "    <source-ipv4-address>$IP</source-ipv4-address>\n"
+        "    <destination-ipv4-address>1.1.1.1</destination-ipv4-address>\n"
+        "   </ipv4>\n"
+        "  </endpoints-obj>\n"
+        "  <ero>\n"
+        "   <subobject>\n"
+        "    <loose>false</loose>\n"
+        "    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n"
+        "   </subobject>\n"
+        "  </ero>\n"
+        " </arguments>\n"
+        "</input>\n"
+    )
+    update_xml_templ = Template(
+        '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
+        " <node>pcc://$IP</node>\n"
+        " <name>$NAME</name>\n"
+        ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
+        '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
+        "</network-topology-ref>\n"
+        " <arguments>\n"
+        '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
+        "   <delegate>true</delegate>\n"
+        "   <administrative>true</administrative>\n"
+        "  </lsp>\n"
+        "  <ero>\n"
+        "   <subobject>\n"
+        "    <loose>false</loose>\n"
+        "    <ip-prefix><ip-prefix>2.2.2.2/32</ip-prefix></ip-prefix>\n"
+        "   </subobject>\n"
+        "   <subobject>\n"
+        "    <loose>false</loose>\n"
+        "    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n"
+        "   </subobject>\n"
+        "  </ero>\n"
+        " </arguments>\n"
+        "</input>\n"
+    )
+    remove_xml_templ = Template(
+        '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
+        " <node>pcc://$IP</node>\n"
+        " <name>$NAME</name>\n"
+        ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
+        '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
+        "</network-topology-ref>\n"
+        "</input>\n"
+    )
+    # The operations can be applied to either delegated or instantiated tunnel, NAME is the only distinguishing value.
+    # Also, the final IP substitution can be done here.
+    repl_dict = {"IP": mininet_ip}
+    repl_dict["NAME"] = delegated_name
+    variables["update_delegated_xml"] = update_xml_templ.substitute(repl_dict)
+    variables["remove_delegated_xml"] = remove_xml_templ.substitute(repl_dict)
+    repl_dict["NAME"] = instantiated_name
+    variables["add_instantiated_xml"] = add_xml_templ.substitute(repl_dict)
+    variables["update_instantiated_xml"] = update_xml_templ.substitute(repl_dict)
+    variables["remove_instantiated_xml"] = remove_xml_templ.substitute(repl_dict)
+    # All variables ready.
+    return variables
diff --git a/csit/variables/tcpmd5user/chlorine b/csit/variables/tcpmd5user/chlorine
deleted file mode 120000 (symlink)
index 121ca56..0000000
+++ /dev/null
@@ -1 +0,0 @@
-aluminium
\ No newline at end of file
diff --git a/csit/variables/tcpmd5user/chlorine/default_off/data.json b/csit/variables/tcpmd5user/chlorine/default_off/data.json
new file mode 100644 (file)
index 0000000..8d847fa
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "network-topology:topology": [
+        {
+            "topology-id": "pcep-topology",
+            "topology-types": {
+                "network-topology-pcep:topology-pcep": {}
+            }
+        }
+    ]
+}
diff --git a/csit/variables/tcpmd5user/chlorine/default_off/location.uri b/csit/variables/tcpmd5user/chlorine/default_off/location.uri
new file mode 100644 (file)
index 0000000..8e7a122
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology?content=nonconfig
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_state/data.json b/csit/variables/tcpmd5user/chlorine/default_on_state/data.json
new file mode 100644 (file)
index 0000000..01393b0
--- /dev/null
@@ -0,0 +1,113 @@
+{
+    "network-topology:topology": [
+        {
+            "node": [
+                {
+                    "network-pcep-topology-stats:pcep-session-state": {
+                        "delegated-lsps-count": 1,
+                        "local-pref": {
+                            "deadtimer": 120,
+                            "ip-address": "$IP_ODL",
+                            "keepalive": 30,
+                            "session-id": "*"
+                        },
+                        "messages": {
+                            "error-messages": {$ERRORS
+                                "received-error-msg-count": 0,
+                                "sent-error-msg-count": 0
+                            },
+                            "last-sent-msg-timestamp": 0,
+                            "odl-pcep-stateful-stats:last-received-rpt-msg-timestamp": "*",
+                            "odl-pcep-stateful-stats:received-rpt-msg-count": 2,
+                            "odl-pcep-stateful-stats:sent-init-msg-count": 0,
+                            "odl-pcep-stateful-stats:sent-upd-msg-count": 0,
+                            "received-msg-count": 2,
+                            "reply-time": {
+                                "average-time": 0,
+                                "max-time": 0,
+                                "min-time": 0
+                            },
+                            "sent-msg-count": 0,
+                            "unknown-msg-received": 0
+                        },
+                        "peer-capabilities": {
+                            "odl-pcep-stateful-stats:active": true,
+                            "odl-pcep-stateful-stats:instantiation": true,
+                            "odl-pcep-stateful-stats:stateful": true
+                        },
+                        "peer-pref": {
+                            "deadtimer": 120,
+                            "ip-address": "$IP",
+                            "keepalive": 30,
+                            "session-id": "*"
+                        },
+                        "session-duration": "*",
+                        "synchronized": true
+                    },
+                    "network-topology-pcep:path-computation-client": {
+                        "ip-address": "$IP",
+                        "reported-lsp": [
+                            {
+                                "name": "$NAME",
+                                "path": [
+                                    {
+                                        "ero": {
+                                            "ignore": false,
+                                            "processing-rule": false,
+                                            "subobject": [
+                                                {
+                                                    "ip-prefix": {
+                                                        "ip-prefix": "1.1.1.1/32"
+                                                    },
+                                                    "loose": false
+                                                }
+                                            ]
+                                        },
+                                        "lsp-id": 1,
+                                        "odl-pcep-ietf-stateful:lsp": {
+                                            "administrative": true,
+                                            "delegate": true,
+                                            "ignore": false,
+                                            "odl-pcep-ietf-initiated:create": false,
+                                            "operational": "up",
+                                            "plsp-id": 1,
+                                            "processing-rule": false,
+                                            "remove": false,
+                                            "sync": true,
+                                            "tlvs": {
+                                                "lsp-identifiers": {
+                                                    "ipv4": {
+                                                        "ipv4-extended-tunnel-id": "$IP",
+                                                        "ipv4-tunnel-endpoint-address": "1.1.1.1",
+                                                        "ipv4-tunnel-sender-address": "$IP"
+                                                    },
+                                                    "lsp-id": 1,
+                                                    "tunnel-id": 1
+                                                },
+                                                "symbolic-path-name": {
+                                                    "path-name": "$CODE"
+                                                }
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        ],
+                        "state-sync": "synchronized",
+                        "stateful-tlv": {
+                            "odl-pcep-ietf-stateful:stateful": {
+                                "lsp-update-capability": true,
+                                "odl-pcep-ietf-initiated:initiation": true
+                            }
+                        }
+                    },
+                    "node-id": "pcc://$IP"
+                }
+            ],
+            "topology-id": "pcep-topology",
+            "topology-types": {
+                "network-topology-pcep:topology-pcep": {}
+            }
+        }
+    ]
+}
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_state/location.uri b/csit/variables/tcpmd5user/chlorine/default_on_state/location.uri
new file mode 100644 (file)
index 0000000..8e7a122
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology?content=nonconfig
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_state/volatiles.list b/csit/variables/tcpmd5user/chlorine/default_on_state/volatiles.list
new file mode 100644 (file)
index 0000000..567832f
--- /dev/null
@@ -0,0 +1,3 @@
+odl-pcep-stateful-stats:last-received-rpt-msg-timestamp
+session-duration
+session-id
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_updated_state/data.json b/csit/variables/tcpmd5user/chlorine/default_on_updated_state/data.json
new file mode 100644 (file)
index 0000000..0d5e2e3
--- /dev/null
@@ -0,0 +1,119 @@
+{
+    "network-topology:topology": [
+        {
+            "node": [
+                {
+                    "network-pcep-topology-stats:pcep-session-state": {
+                        "delegated-lsps-count": 1,
+                        "local-pref": {
+                            "deadtimer": 120,
+                            "ip-address": "$IP_ODL",
+                            "keepalive": 30,
+                            "session-id": "*"
+                        },
+                        "messages": {
+                            "error-messages": {$ERRORS
+                                "received-error-msg-count": 0,
+                                "sent-error-msg-count": 0
+                            },
+                            "last-sent-msg-timestamp": "*",
+                            "odl-pcep-stateful-stats:last-received-rpt-msg-timestamp": "*",
+                            "odl-pcep-stateful-stats:received-rpt-msg-count": 3,
+                            "odl-pcep-stateful-stats:sent-init-msg-count": 0,
+                            "odl-pcep-stateful-stats:sent-upd-msg-count": 1,
+                            "received-msg-count": 3,
+                            "reply-time": {
+                                "average-time": "*",
+                                "max-time": "*",
+                                "min-time": "*"
+                            },
+                            "sent-msg-count": 1,
+                            "unknown-msg-received": 0
+                        },
+                        "peer-capabilities": {
+                            "odl-pcep-stateful-stats:active": true,
+                            "odl-pcep-stateful-stats:instantiation": true,
+                            "odl-pcep-stateful-stats:stateful": true
+                        },
+                        "peer-pref": {
+                            "deadtimer": 120,
+                            "ip-address": "$IP",
+                            "keepalive": 30,
+                            "session-id": "*"
+                        },
+                        "session-duration": "*",
+                        "synchronized": true
+                    },
+                    "network-topology-pcep:path-computation-client": {
+                        "ip-address": "$IP",
+                        "reported-lsp": [
+                            {
+                                "name": "$NAME",
+                                "path": [
+                                    {
+                                        "ero": {
+                                            "ignore": false,
+                                            "processing-rule": false,
+                                            "subobject": [
+                                                {
+                                                    "ip-prefix": {
+                                                        "ip-prefix": "1.1.1.1/32"
+                                                    },
+                                                    "loose": false
+                                                },
+                                                {
+                                                    "ip-prefix": {
+                                                        "ip-prefix": "2.2.2.2/32"
+                                                    },
+                                                    "loose": false
+                                                }
+                                            ]
+                                        },
+                                        "lsp-id": 1,
+                                        "odl-pcep-ietf-stateful:lsp": {
+                                            "administrative": true,
+                                            "delegate": true,
+                                            "ignore": false,
+                                            "odl-pcep-ietf-initiated:create": false,
+                                            "operational": "up",
+                                            "plsp-id": 1,
+                                            "processing-rule": false,
+                                            "remove": false,
+                                            "sync": true,
+                                            "tlvs": {
+                                                "lsp-identifiers": {
+                                                    "ipv4": {
+                                                        "ipv4-extended-tunnel-id": "$IP",
+                                                        "ipv4-tunnel-endpoint-address": "1.1.1.1",
+                                                        "ipv4-tunnel-sender-address": "$IP"
+                                                    },
+                                                    "lsp-id": 1,
+                                                    "tunnel-id": 1
+                                                },
+                                                "symbolic-path-name": {
+                                                    "path-name": "$CODE"
+                                                }
+                                            }
+                                        }
+                                    }
+                                ]
+                            }
+                        ],
+                        "state-sync": "synchronized",
+                        "stateful-tlv": {
+                            "odl-pcep-ietf-stateful:stateful": {
+                                "lsp-update-capability": true,
+                                "odl-pcep-ietf-initiated:initiation": true
+                            }
+                        }
+                    },
+                    "node-id": "pcc://$IP"
+                }
+            ],
+            "topology-id": "pcep-topology",
+            "topology-types": {
+                "network-topology-pcep:topology-pcep": {}
+            }
+        }
+    ]
+}
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_updated_state/location.uri b/csit/variables/tcpmd5user/chlorine/default_on_updated_state/location.uri
new file mode 100644 (file)
index 0000000..8e7a122
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology?content=nonconfig
diff --git a/csit/variables/tcpmd5user/chlorine/default_on_updated_state/volatiles.list b/csit/variables/tcpmd5user/chlorine/default_on_updated_state/volatiles.list
new file mode 100644 (file)
index 0000000..21a0739
--- /dev/null
@@ -0,0 +1,7 @@
+odl-pcep-stateful-stats:last-received-rpt-msg-timestamp
+session-duration
+session-id
+last-sent-msg-timestamp
+average-time
+max-time
+min-time
diff --git a/csit/variables/tcpmd5user/chlorine/pcep_topology_node/data.xml b/csit/variables/tcpmd5user/chlorine/pcep_topology_node/data.xml
new file mode 100644 (file)
index 0000000..fd32725
--- /dev/null
@@ -0,0 +1,6 @@
+<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+    <node-id>$IP</node-id>
+    <session-config xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+        <password>$PASSWD</password>
+    </session-config>
+</node>
diff --git a/csit/variables/tcpmd5user/chlorine/pcep_topology_node/location.uri b/csit/variables/tcpmd5user/chlorine/pcep_topology_node/location.uri
new file mode 100644 (file)
index 0000000..b2a9868
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology/node=$IP
diff --git a/csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/data.xml b/csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/data.xml
new file mode 100644 (file)
index 0000000..fd203a7
--- /dev/null
@@ -0,0 +1,3 @@
+<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+    <node-id>$IP</node-id>
+</node>
diff --git a/csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/location.uri b/csit/variables/tcpmd5user/chlorine/pcep_topology_node_empty/location.uri
new file mode 100644 (file)
index 0000000..b2a9868
--- /dev/null
@@ -0,0 +1 @@
+rests/data/network-topology:network-topology/topology=pcep-topology/node=$IP
diff --git a/csit/variables/tcpmd5user/chlorine/update_delegated/location.uri b/csit/variables/tcpmd5user/chlorine/update_delegated/location.uri
new file mode 100644 (file)
index 0000000..51b2c69
--- /dev/null
@@ -0,0 +1 @@
+rests/operations/network-topology-pcep:update-lsp
diff --git a/csit/variables/tcpmd5user/chlorine/update_delegated/post_data.xml b/csit/variables/tcpmd5user/chlorine/update_delegated/post_data.xml
new file mode 100644 (file)
index 0000000..ab64fca
--- /dev/null
@@ -0,0 +1,27 @@
+<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+    <node>pcc://$IP</node>
+    <name>$NAME</name>
+    <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">
+    /topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]
+    </network-topology-ref>
+    <arguments>
+        <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">
+            <delegate>true</delegate>
+            <administrative>true</administrative>
+        </lsp>
+        <ero>
+            <subobject>
+                <loose>false</loose>
+                <ip-prefix>
+                    <ip-prefix>2.2.2.2/32</ip-prefix>
+                </ip-prefix>
+            </subobject>
+            <subobject>
+                <loose>false</loose>
+                <ip-prefix>
+                    <ip-prefix>1.1.1.1/32</ip-prefix>
+                </ip-prefix>
+            </subobject>
+        </ero>
+    </arguments>
+</input>
diff --git a/csit/variables/tcpmd5user/chlorine/variables.py b/csit/variables/tcpmd5user/chlorine/variables.py
new file mode 100644 (file)
index 0000000..9750e7a
--- /dev/null
@@ -0,0 +1,237 @@
+"""
+Variables file for tcpmd5user suite.
+
+Expected JSON templates are fairly long,
+therefore there are moved out of testcase file.
+Also, it is needed to generate base64 encoded tunnel name
+from Mininet IP (which is not known beforehand),
+so it is easier to employ Python here,
+than do manipulation in Robot file.
+"""
+# Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0 which accompanies this distribution,
+# and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import base64
+from string import Template
+
+
+__author__ = "Vratko Polak"
+__copyright__ = "Copyright(c) 2015, Cisco Systems, Inc."
+__license__ = "Eclipse Public License v1.0"
+__email__ = "vrpolak@cisco.com"
+
+
+# FIXME: Migrate values shared by other suites to separate Python module.
+
+
+def get_variables(mininet_ip):
+    """Return dict of variables for the given IPv4 address of Mininet VM."""
+    # TODO: Document in 'V' fashion, as in pcepuser/variables.py using more systematic local variable names.
+    # Dict of variables to return, starts empty and grows as function proceeds.
+    variables = {}
+    # Given mininet_ip, this will be the sympolic name uf tunnel under test.
+    tunnelname = "pcc_" + mininet_ip + "_tunnel_1"
+    # Base64 code for the symbolic name, as that is present in datastore.
+    tunnelname_bytes = tunnelname.encode("ascii")
+    pathcode_encoded = base64.b64encode(tunnelname_bytes)
+    pathcode = pathcode_encoded.decode("ascii")
+    variables["pcc_name"] = tunnelname
+    variables["pcc_name_code"] = pathcode
+    # JSON response when pcep-topology is ready but no PCC is connected.
+    variables[
+        "offjson"
+    ] = """{
+ "topology": [
+  {
+   "topology-id": "pcep-topology",
+   "topology-types": {
+    "network-topology-pcep:topology-pcep": {}
+   }
+  }
+ ]
+}"""
+    # Template of JSON response with pcep-topology seeing 1 PCC 1 LSP.
+    onjsontempl = Template(
+        """{
+ "topology": [
+  {
+   "node": [
+    {
+     "network-topology-pcep:path-computation-client": {
+      "ip-address": "$IP",
+      "reported-lsp": [
+       {
+        "name": "$NAME",
+        "path": [
+         {
+          "ero": {
+           "ignore": false,
+           "processing-rule": false,
+           "subobject": [
+            {
+             "ip-prefix": {
+              "ip-prefix": "1.1.1.1/32"
+             },
+             "loose": false
+            }
+           ]
+          },
+          "lsp-id": 1,
+          "odl-pcep-ietf-stateful:lsp": {
+           "administrative": true,
+           "delegate": true,
+           "ignore": false,
+           "odl-pcep-ietf-initiated:create": false,
+           "operational": "up",
+           "plsp-id": 1,
+           "processing-rule": false,
+           "remove": false,
+           "sync": true,
+           "tlvs": {
+            "lsp-identifiers": {
+             "ipv4": {
+              "ipv4-extended-tunnel-id": "$IP",
+              "ipv4-tunnel-endpoint-address": "1.1.1.1",
+              "ipv4-tunnel-sender-address": "$IP"
+             },
+             "lsp-id": 1,
+             "tunnel-id": 1
+            },
+            "symbolic-path-name": {
+             "path-name": "$CODE"
+            }
+           }
+          }
+         }
+        ]
+       }
+      ],
+      "state-sync": "synchronized",
+      "stateful-tlv": {
+       "odl-pcep-ietf-stateful:stateful": {
+        "lsp-update-capability": true,
+        "odl-pcep-ietf-initiated:initiation": true
+       }
+      }
+     },
+     "node-id": "pcc://$IP"
+    }
+   ],
+   "topology-id": "pcep-topology",
+   "topology-types": {
+    "network-topology-pcep:topology-pcep": {}
+   }
+  }
+ ]
+}"""
+    )
+    # Dictionly which tells values for placeholders.
+    repl_dict = {"IP": mininet_ip, "NAME": tunnelname, "CODE": pathcode}
+    # The finalized JSON.
+    variables["onjson"] = onjsontempl.substitute(repl_dict)
+    # The following strings are XML data.
+    # See https://wiki.opendaylight.org/view/BGP_LS_PCEP:TCP_MD5_Guide#RESTCONF_Configuration
+    # For curl, string is suitable to became -d argument only after
+    # replacing ' -> '"'"' and enclosing in single quotes.
+    variables[
+        "key_access_module"
+    ] = """<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:jni:cfg">x:native-key-access-factory</type>
+ <name>global-key-access-factory</name>
+</module>"""
+    variables[
+        "key_access_service"
+    ] = """<service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:cfg">x:key-access-factory</type>
+ <instance>
+  <name>global-key-access-factory</name>
+  <provider>/modules/module[type='native-key-access-factory'][name='global-key-access-factory']</provider>
+ </instance>
+</service>"""
+    variables[
+        "client_channel_module"
+    ] = """<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">x:md5-client-channel-factory</type>
+ <name>md5-client-channel-factory</name>
+ <key-access-factory xmlns="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">
+  <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:cfg">x:key-access-factory</type>
+  <name>global-key-access-factory</name>
+ </key-access-factory>
+</module>"""
+    variables[
+        "client_channel_service"
+    ] = """<service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">x:md5-channel-factory</type>
+ <instance>
+  <name>md5-client-channel-factory</name>
+  <provider>/modules/module[type='md5-client-channel-factory'][name='md5-client-channel-factory']</provider>
+ </instance>
+</service>"""
+    variables[
+        "server_channel_module"
+    ] = """<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">"""
+    # What is your favourite way to concatenate strings without resembling tuple?
+    variables[
+        "server_channel_module"
+    ] += """prefix:md5-server-channel-factory-impl</type>
+ <name>md5-server-channel-factory</name>
+ <server-key-access-factory xmlns="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">
+  <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:cfg">x:key-access-factory</type>
+  <name>global-key-access-factory</name>
+ </server-key-access-factory>
+</module>"""
+    variables[
+        "server_channel_service"
+    ] = """<service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">"""
+    variables[
+        "server_channel_service"
+    ] += """prefix:md5-server-channel-factory</type>
+ <instance>
+  <name>md5-server-channel-factory</name>
+  <provider>/modules/module[type='md5-server-channel-factory-impl'][name='md5-server-channel-factory']</provider>
+ </instance>
+</service>"""
+    variables[
+        "pcep_dispatcher_module"
+    ] = """<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:pcep:impl">x:pcep-dispatcher-impl</type>
+ <name>global-pcep-dispatcher</name>
+ <md5-channel-factory xmlns="urn:opendaylight:params:xml:ns:yang:controller:pcep:impl">
+  <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">x:md5-channel-factory</type>
+  <name>md5-client-channel-factory</name>
+ </md5-channel-factory>
+ <md5-server-channel-factory xmlns="urn:opendaylight:params:xml:ns:yang:controller:pcep:impl">
+  <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:tcpmd5:netty:cfg">x:md5-server-channel-factory</type>
+  <name>md5-server-channel-factory</name>
+ </md5-server-channel-factory>
+</module>"""
+    # Template to set password.
+    passwd_templ = Template(
+        """<module xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <type xmlns:x="urn:opendaylight:params:xml:ns:yang:controller:pcep:topology:provider">x:pcep-topology-provider</type>
+ <name>pcep-topology</name>
+ <client xmlns="urn:opendaylight:params:xml:ns:yang:controller:pcep:topology:provider">
+  <address xmlns="urn:opendaylight:params:xml:ns:yang:controller:pcep:topology:provider">$IP</address>
+$PASSWD </client>
+</module>"""
+    )
+    # We use three template instantiations. No password:
+    repl_dict = {"IP": mininet_ip, "PASSWD": ""}
+    variables["no_passwd_module"] = passwd_templ.substitute(repl_dict)
+    changeme = """  <password>changeme</password>
+"""
+    # wrong password
+    repl_dict = {"IP": mininet_ip, "PASSWD": changeme}
+    variables["passwd_changeme_module"] = passwd_templ.substitute(repl_dict)
+    # and correct password.
+    topsecret = """  <password>topsecret</password>
+"""
+    repl_dict = {"IP": mininet_ip, "PASSWD": topsecret}
+    variables["passwd_topsecret_module"] = passwd_templ.substitute(repl_dict)
+    # All variables set, return dict to Robot.
+    return variables