Updated code to match new rules
[integration/test.git] / csit / variables / pcepuser / 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 binascii
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 analyze 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['off_json'] = '''{
40  "topology": [
41   {
42    "topology-id": "pcep-topology",
43    "topology-types": {
44     "network-topology-pcep:topology-pcep": {}
45    }
46   }
47  ]
48 }'''
49     # Ok, other _json strings will have more regular structure and some variable data,
50     # so we will be using templates heavily.
51     # First off, there is segment describing PCC which conatins IP address but is otherwise constant.
52     # So the top-level template will look like this:
53     json_templ = Template('''{
54  "topology": [
55   {
56    "node": [
57     {
58      "network-topology-pcep:path-computation-client": {
59       "ip-address": "$IP",
60       "reported-lsp": [$LSPS
61       ],
62       "state-sync": "synchronized",
63       "stateful-tlv": {
64        "odl-pcep-ietf-stateful07:stateful": {
65         "lsp-update-capability": true,
66         "odl-pcep-ietf-initiated00:initiation": true
67        }
68       }
69      },
70      "node-id": "pcc://$IP"
71     }
72    ],
73    "topology-id": "pcep-topology",
74    "topology-types": {
75     "network-topology-pcep:topology-pcep": {}
76    }
77   }
78  ]
79 }''')
80     # The _json variables will differ only in $LSPS, but $IP will be present inside.
81     # Thus, the $IP substitution will come last, and any auxiliary substitutions before this final one
82     # will have to use safe_substitute().
83     # As you see, $LSPS is in json_templ without preceding newline.
84     # As a rule, a segment will always start with endline and end without endline,
85     # so that we can add comma where needed.
86     # Discussion amout delegated and instantiated implies that $LSPS is either a single delegated LSP
87     # or a pair of delegated and instantiated (separated by comma) LSPS, in appropriate state.
88     # Of course, one LSP always follow a structure, for which here is the template:
89     lsp_templ = Template('''
90        {
91         "name": "$NAME",
92         "path": [
93          {
94           "ero": {
95            "ignore": false,
96            "processing-rule": false,
97            "subobject": [$HOPS
98            ]
99           },
100           "lsp-id": $ID,
101           "odl-pcep-ietf-stateful07:lsp": {
102            "administrative": true,
103            "delegate": true,
104            "ignore": false,
105            "odl-pcep-ietf-initiated00:create": $CREATED,
106            "operational": "up",
107            "plsp-id": $ID,
108            "processing-rule": false,
109            "remove": false,
110            "sync": true,
111            "tlvs": {
112             "lsp-identifiers": {
113              "ipv4": {
114               "ipv4-extended-tunnel-id": "$IP",
115               "ipv4-tunnel-endpoint-address": "1.1.1.1",
116               "ipv4-tunnel-sender-address": "$IP"
117              },
118              "lsp-id": $ID,
119              "tunnel-id": $ID
120             },
121             "symbolic-path-name": {
122              "path-name": "$CODE"
123             }
124            }
125           }
126          }
127         ]
128        }''')
129     # IDs were already talked about, IP will be set last. Now, $NAME.
130     # Pcc-mock uses a fixed naming scheme for delegated tunnels, so one more template can be written,
131     # but it is so simple we can write just the one-line code instead:
132     delegated_name = 'pcc_' + mininet_ip + '_tunnel_1'  # 1 == ID
133     # For the instantiated tunnel, user is free to specify anything, even charachers such as \u0000 work.
134     # But as we need to plug the name to XML, let us try something more friendly:
135     instantiated_name = 'Instantiated tunnel'  # the space is only somewhat evil character :)
136     # What is CODE? The NAME in base64 encoding (without endline):
137     delegated_code = binascii.b2a_base64(delegated_name)[:-1]  # remove endline added by the library function
138     instantiated_code = binascii.b2a_base64(instantiated_name)[:-1]
139     # The remaining segment is HOPS, and that is the place where default and updated states differ.
140     # Once gain, there is a template for a single hop:
141     hop_templ = Template('''
142             {
143              "ip-prefix": {
144               "ip-prefix": "$HOPIP/32"
145              },
146              "loose": false
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 = {'NAME': delegated_name, 'ID': '1', 'CODE': delegated_code, 'CREATED': 'false'}
157     delegated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
158     delegated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
159     repl_dict = {'NAME': instantiated_name, 'ID': '2', 'CODE': instantiated_code, 'CREATED': 'true'}
160     instantiated_default_lsp = default_lsp_templ.safe_substitute(repl_dict)
161     instantiated_updated_lsp = updated_lsp_templ.safe_substitute(repl_dict)
162     # Json templates (without IP set).
163     repl_dict = {'LSPS': delegated_default_lsp}
164     default_json_templ = Template(json_templ.safe_substitute(repl_dict))
165     repl_dict = {'LSPS': delegated_updated_lsp}
166     updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
167     repl_dict = {'LSPS': delegated_updated_lsp + ',' + instantiated_default_lsp}
168     updated_default_json_templ = Template(json_templ.safe_substitute(repl_dict))
169     repl_dict = {'LSPS': delegated_updated_lsp + ',' + instantiated_updated_lsp}
170     updated_updated_json_templ = Template(json_templ.safe_substitute(repl_dict))
171     # Final json variables.
172     repl_dict = {'IP': mininet_ip}
173     variables['default_json'] = default_json_templ.substitute(repl_dict)
174     variables['updated_json'] = updated_json_templ.substitute(repl_dict)
175     variables['updated_default_json'] = updated_default_json_templ.substitute(repl_dict)
176     variables['updated_updated_json'] = updated_updated_json_templ.substitute(repl_dict)
177     # ### Pcep operations XML data.
178     # There are three operations, so let us just write templates from information at
179     # 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
180     # _xml describes content type and also distinguishes from similarly named _json strings.
181     add_xml_templ = Template(
182        '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
183        ' <node>pcc://$IP</node>\n'
184        ' <name>$NAME</name>\n'
185        ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
186        '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
187        '</network-topology-ref>\n'
188        ' <arguments>\n'
189        '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
190        '   <delegate>true</delegate>\n'
191        '   <administrative>true</administrative>\n'
192        '  </lsp>\n'
193        '  <endpoints-obj>\n'
194        '   <ipv4>\n'
195        '    <source-ipv4-address>$IP</source-ipv4-address>\n'
196        '    <destination-ipv4-address>1.1.1.1</destination-ipv4-address>\n'
197        '   </ipv4>\n'
198        '  </endpoints-obj>\n'
199        '  <ero>\n'
200        '   <subobject>\n'
201        '    <loose>false</loose>\n'
202        '    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n'
203        '   </subobject>\n'
204        '  </ero>\n'
205        ' </arguments>\n'
206        '</input>\n'
207     )
208     update_xml_templ = Template(
209         '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
210         ' <node>pcc://$IP</node>\n'
211         ' <name>$NAME</name>\n'
212         ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
213         '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
214         '</network-topology-ref>\n'
215         ' <arguments>\n'
216         '  <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">\n'
217         '   <delegate>true</delegate>\n'
218         '   <administrative>true</administrative>\n'
219         '  </lsp>\n'
220         '  <ero>\n'
221         '   <subobject>\n'
222         '    <loose>false</loose>\n'
223         '    <ip-prefix><ip-prefix>2.2.2.2/32</ip-prefix></ip-prefix>\n'
224         '   </subobject>\n'
225         '   <subobject>\n'
226         '    <loose>false</loose>\n'
227         '    <ip-prefix><ip-prefix>1.1.1.1/32</ip-prefix></ip-prefix>\n'
228         '   </subobject>\n'
229         '  </ero>\n'
230         ' </arguments>\n'
231         '</input>\n'
232     )
233     remove_xml_templ = Template(
234         '<input xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">\n'
235         ' <node>pcc://$IP</node>\n'
236         ' <name>$NAME</name>\n'
237         ' <network-topology-ref xmlns:topo="urn:TBD:params:xml:ns:yang:network-topology">'
238         '/topo:network-topology/topo:topology[topo:topology-id="pcep-topology"]'
239         '</network-topology-ref>\n'
240         '</input>\n'
241     )
242     # The operations can be applied to either delegated or instantiated tunnel, NAME is the only distinguishing value.
243     # Also, the final IP substitution can be done here.
244     repl_dict = {'IP': mininet_ip}
245     repl_dict['NAME'] = delegated_name
246     variables['update_delegated_xml'] = update_xml_templ.substitute(repl_dict)
247     variables['remove_delegated_xml'] = remove_xml_templ.substitute(repl_dict)
248     repl_dict['NAME'] = instantiated_name
249     variables['add_instantiated_xml'] = add_xml_templ.substitute(repl_dict)
250     variables['update_instantiated_xml'] = update_xml_templ.substitute(repl_dict)
251     variables['remove_instantiated_xml'] = remove_xml_templ.substitute(repl_dict)
252     # All variables ready.
253     return variables