760d50b51221bec211cdac27b97f114337aa1d68
[integration/test.git] / csit / variables / pcepuser / aluminium / variables.py
1 """Variables file for pcepuser suite.
2
3 Expected JSON templates are fairly long,
4 therefore there are moved out of testcase file.
5 Also, it is needed to generate base64 encoded tunnel name
6 from Mininet IP (which is not known beforehand),
7 so it is easier to employ Python here,
8 than do manipulation in Robot file."""
9 # Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
10 #
11 # This program and the accompanying materials are made available under the
12 # terms of the Eclipse Public License v1.0 which accompanies this distribution,
13 # and is available at http://www.eclipse.org/legal/epl-v10.html
14
15 import base64
16 from string import Template
17
18
19 __author__ = "Vratko Polak"
20 __copyright__ = "Copyright(c) 2015, Cisco Systems, Inc."
21 __license__ = "Eclipse Public License v1.0"
22 __email__ = "vrpolak@cisco.com"
23
24
25 def get_variables(mininet_ip):
26     """Return dict of variables for the given IP address of Mininet VM."""
27     variables = {}
28     # 'V' style of explanation.
29     # Comments a nalyze from high level, to low level, then code builds from low level back to high level.
30     # ### Pcep-topology JSON responses.
31     # Some testcases see only the tunnel created by pcc-mock start: "delegated tunnel" (ID 1).
32     # Other testcases see also tunnel created on ODL demand: "instatntiated tunnel" (ID 2).
33     # Both tunnels can have two states. "Default" upon creation with single hop "1.1.1.1",
34     # and "updated" after update-lsp, which prepends another hop "2.2.2.2".
35     # Variable naming always specifies delegated state first, and ends with _json to distinguish from operation data.
36     # The whole list: default_json, updated_json, updated_default_json, updated_updated_json.
37     # Oh, and the state without mock-pcc connected is off_json.
38     # off_json has '{}' substring and no variable data, so here it is as a special case:
39     variables[
40         "off_json"
41     ] = """{
42  "topology": [
43   {
44    "topology-id": "pcep-topology",
45    "topology-types": {
46     "network-topology-pcep:topology-pcep": {}
47    }
48   }
49  ]
50 }"""
51     # Ok, other _json strings will have more regular structure and some variable data,
52     # so we will be using templates heavily.
53     # First off, there is segment describing PCC which conatins IP address but is otherwise constant.
54     # So the top-level template will look like this:
55     json_templ = Template(
56         """{
57  "network-topology-pcep:path-computation-client": {
58   "ip-address": "$IP",
59   "reported-lsp": [$LSPS
60   ],
61   "state-sync": "synchronized",
62   "stateful-tlv": {
63    "odl-pcep-ietf-stateful:stateful": {
64     "lsp-update-capability": true,
65     "odl-pcep-ietf-initiated:initiation": true
66    }
67   }
68  }
69 }"""
70     )
71     # The _json variables will differ only in $LSPS, but $IP will be present inside.
72     # Thus, the $IP substitution will come last, and any auxiliary substitutions before this final one
73     # will have to use safe_substitute().
74     # As you see, $LSPS is in json_templ without preceding newline.
75     # As a rule, a segment will always start with endline and end without endline,
76     # so that we can add comma where needed.
77     # Discussion amout delegated and instantiated implies that $LSPS is either a single delegated LSP
78     # or a pair of delegated and instantiated (separated by comma) LSPS, in appropriate state.
79     # Of course, one LSP always follow a structure, for which here is the template:
80     lsp_templ = Template(
81         """
82    {
83     "name": "$NAME",
84     "path": [
85      {
86       "ero": {
87        "ignore": false,
88        "processing-rule": false,
89        "subobject": [$HOPS
90        ]
91       },
92       "lsp-id": $ID,
93       "odl-pcep-ietf-stateful:lsp": {
94        "administrative": true,
95        "delegate": true,
96        "ignore": false,
97        "odl-pcep-ietf-initiated:create": $CREATED,
98        "operational": "up",
99        "plsp-id": $ID,
100        "processing-rule": false,
101        "remove": false,
102        "sync": true,
103        "tlvs": {
104         "lsp-identifiers": {
105          "ipv4": {
106           "ipv4-extended-tunnel-id": "$IP",
107           "ipv4-tunnel-endpoint-address": "1.1.1.1",
108           "ipv4-tunnel-sender-address": "$IP"
109          },
110          "lsp-id": $ID,
111          "tunnel-id": $ID
112         },
113         "symbolic-path-name": {
114          "path-name": "$CODE"
115         }
116        }
117       }
118      }
119     ]
120    }"""
121     )
122     # IDs were already talked about, IP will be set last. Now, $NAME.
123     # Pcc-mock uses a fixed naming scheme for delegated tunnels, so one more template can be written,
124     # but it is so simple we can write just the one-line code instead:
125     delegated_name = "pcc_" + mininet_ip + "_tunnel_1"  # 1 == ID
126     # For the instantiated tunnel, user is free to specify anything, even charachers such as \u0000 work.
127     # But as we need to plug the name to XML, let us try something more friendly:
128     instantiated_name = "Instantiated tunnel"
129     # What is CODE? The NAME in base64 encoding (without endline):
130     delegated_name_bytes = delegated_name.encode("ascii")
131     delegated_code_encoded = base64.b64encode(delegated_name_bytes)
132     delegated_code = delegated_code_encoded.decode("ascii")
133     instantiated_name_bytes = instantiated_name.encode("ascii")
134     instantiated_code_encoded = base64.b64encode(instantiated_name_bytes)
135     instantiated_code = instantiated_code_encoded.decode("ascii")
136
137     # The remaining segment is HOPS, and that is the place where default and updated states differ.
138     # Once again, there is a template for a single hop:
139     hop_templ = Template(
140         """
141        {
142          "ip-prefix": {
143           "ip-prefix": "$HOPIP/32"
144          },
145          "loose": false
146        }"""
147     )
148     # The low-to-high part of V comes now, it is just substituting and concatenating.
149     # Hops:
150     final_hop = hop_templ.substitute({"HOPIP": "1.1.1.1"})
151     update_hop = hop_templ.substitute({"HOPIP": "2.2.2.2"})
152     both_hops = update_hop + "," + final_hop
153     # Lsps:
154     default_lsp_templ = Template(lsp_templ.safe_substitute({"HOPS": final_hop}))
155     updated_lsp_templ = Template(lsp_templ.safe_substitute({"HOPS": both_hops}))
156     repl_dict = {
157         "NAME": delegated_name,
158         "ID": "1",
159         "CODE": delegated_code,
160         "CREATED": "false",
161     }
162     delegated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
163     delegated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
164     repl_dict = {
165         "NAME": instantiated_name,
166         "ID": "2",
167         "CODE": instantiated_code,
168         "CREATED": "true",
169     }
170     instantiated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
171     instantiated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
172     # Json templates (without IP set).
173     repl_dict = {"LSPS": delegated_default_lsp}
174     default_json_templ = Template(json_templ.safe_substitute(repl_dict))
175     repl_dict = {"LSPS": delegated_updated_lsp}
176     updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
177     repl_dict = {"LSPS": delegated_updated_lsp + "," + instantiated_default_lsp}
178     updated_default_json_templ = Template(json_templ.safe_substitute(repl_dict))
179     repl_dict = {"LSPS": delegated_updated_lsp + "," + instantiated_updated_lsp}
180     updated_updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
181     # Final json variables.
182     repl_dict = {"IP": mininet_ip}
183     variables["default_json"] = default_json_templ.substitute(repl_dict)
184     variables["updated_json"] = updated_json_templ.substitute(repl_dict)
185     variables["updated_default_json"] = updated_default_json_templ.substitute(repl_dict)
186     variables["updated_updated_json"] = updated_updated_json_templ.substitute(repl_dict)
187     # ### Pcep operations XML data.
188     # There are three operations, so let us just write templates from information at
189     # 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
190     # _xml describes content type and also distinguishes from similarly named _json strings.
191     add_xml_templ = Template(
192         '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
193         " <node>pcc://$IP</node>\n"
194         " <name>$NAME</name>\n"
195         ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
196         '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
197         "</network-topology-ref>\n"
198         " <arguments>\n"
199         '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
200         "   <delegate>true</delegate>\n"
201         "   <administrative>true</administrative>\n"
202         "  </lsp>\n"
203         "  <endpoints-obj>\n"
204         "   <ipv4>\n"
205         "    <source-ipv4-address>$IP</source-ipv4-address>\n"
206         "    <destination-ipv4-address>1.1.1.1</destination-ipv4-address>\n"
207         "   </ipv4>\n"
208         "  </endpoints-obj>\n"
209         "  <ero>\n"
210         "   <subobject>\n"
211         "    <loose>false</loose>\n"
212         "    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n"
213         "   </subobject>\n"
214         "  </ero>\n"
215         " </arguments>\n"
216         "</input>\n"
217     )
218     update_xml_templ = Template(
219         '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
220         " <node>pcc://$IP</node>\n"
221         " <name>$NAME</name>\n"
222         ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
223         '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
224         "</network-topology-ref>\n"
225         " <arguments>\n"
226         '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
227         "   <delegate>true</delegate>\n"
228         "   <administrative>true</administrative>\n"
229         "  </lsp>\n"
230         "  <ero>\n"
231         "   <subobject>\n"
232         "    <loose>false</loose>\n"
233         "    <ip-prefix><ip-prefix>2.2.2.2/32</ip-prefix></ip-prefix>\n"
234         "   </subobject>\n"
235         "   <subobject>\n"
236         "    <loose>false</loose>\n"
237         "    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n"
238         "   </subobject>\n"
239         "  </ero>\n"
240         " </arguments>\n"
241         "</input>\n"
242     )
243     remove_xml_templ = Template(
244         '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
245         " <node>pcc://$IP</node>\n"
246         " <name>$NAME</name>\n"
247         ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
248         '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
249         "</network-topology-ref>\n"
250         "</input>\n"
251     )
252     # The operations can be applied to either delegated or instantiated tunnel, NAME is the only distinguishing value.
253     # Also, the final IP substitution can be done here.
254     repl_dict = {"IP": mininet_ip}
255     repl_dict["NAME"] = delegated_name
256     variables["update_delegated_xml"] = update_xml_templ.substitute(repl_dict)
257     variables["remove_delegated_xml"] = remove_xml_templ.substitute(repl_dict)
258     repl_dict["NAME"] = instantiated_name
259     variables["add_instantiated_xml"] = add_xml_templ.substitute(repl_dict)
260     variables["update_instantiated_xml"] = update_xml_templ.substitute(repl_dict)
261     variables["remove_instantiated_xml"] = remove_xml_templ.substitute(repl_dict)
262     # All variables ready.
263     return variables