e5048b93dd654cd101819b40fc95ff5abe1a7c05
[integration/test.git] / csit / libraries / Sxp.py
1 import json
2 from ipaddr import IPAddress
3 from string import Template
4
5
6 def mod(num, base):
7     """Gets modulo of number
8
9     :param num: Number to be used
10     :type num: string
11     :param base: Base used
12     :type base: string
13     :returns: Int representing modulo of specified numbers.
14
15     """
16     return int(num) % int(base)
17
18
19 def get_ip_from_number(n):
20     """Generate string representing Ipv4 from specified number that is added number 2130706432
21
22     :param n: Number to be converted
23     :type n: int
24     :returns: String containing Ipv4.
25
26     """
27     ip = IPAddress(2130706432 + n)
28     return str(ip)
29
30
31 def lower_version(ver1, ver2):
32     """Generate xml containing SGT mach data
33
34     :param ver1: Version of SXP protocol for compare
35     :type ver1: string
36     :param ver2: Version of SXP protocol for compare
37     :type ver2: string
38     :returns: String containing lower from those two specified versions.
39
40     """
41     v1 = int(ver1[-1:])
42     v2 = int(ver2[-1:])
43     if v1 <= v2:
44         return ver1
45     else:
46         return ver2
47
48
49 def get_filter_entry(seq, entry_type, sgt="", esgt="", acl="", eacl="", pl="", epl=""):
50     """Generate xml containing FilterEntry data
51
52     :param seq: Sequence of entry
53     :type seq: string
54     :param entry_type: Type of entry (permit/deny)
55     :type entry_type: string
56     :param sgt: SGT matches to be added to entry
57     :type sgt: string
58     :param esgt: SGT ranges match to be added to entry
59     :type esgt: string
60     :param acl: ACL matches to be added to entry
61     :type acl: string
62     :param eacl: EACL matches to be added to entry
63     :type eacl: string
64     :param pl: PrefixList matches to be added to entry
65     :type pl: string
66     :param epl: ExtendedPrefixList matches to be added to entry
67     :type epl: string
68     :returns: String containing xml data for request
69
70     """
71     entries = ""
72     # Generate XML request containing combination of Matches of different types
73     if sgt:
74         args = sgt.split(',')
75         entries += add_sgt_matches_xml(args)
76     elif esgt:
77         args = esgt.split(',')
78         entries += add_sgt_range_xml(args[0], args[1])
79     if pl:
80         entries += add_pl_entry_xml(pl)
81     elif epl:
82         args = epl.split(',')
83         entries += add_epl_entry_xml(args[0], args[1], args[2])
84     if acl:
85         args = acl.split(',')
86         entries += add_acl_entry_xml(args[0], args[1])
87     elif eacl:
88         args = eacl.split(',')
89         entries += add_eacl_entry_xml(args[0], args[1], args[2], args[3])
90     # Wrap entries in ACL/PrefixList according to specified values
91     if pl or epl:
92         return add_pl_entry_default_xml(seq, entry_type, entries)
93     return add_acl_entry_default_xml(seq, entry_type, entries)
94
95
96 def add_peers(*args):
97     """Generate xml containing Peer mach data
98
99     :param args: Peers data
100     :type args: dict
101     :returns: String containing xml data for request
102
103     """
104     templ = Template('''
105         <sxp-peer>
106             <peer-address>$ip</peer-address>
107         </sxp-peer>''')
108     peers = ""
109     for count, value in enumerate(args):
110         peers += templ.substitute({'ip': value})
111     return peers
112
113
114 def add_sgt_matches_xml(sgt_entries):
115     """Generate xml containing SGT mach data
116
117     :param sgt_entries: SGT matches
118     :type sgt_entries: string
119     :returns: String containing xml data for request
120
121     """
122     templ = Template('''
123         <matches>$sgt</matches>''')
124     matches = ""
125     for sgt in sgt_entries:
126         matches += templ.substitute({'sgt': sgt})
127     return matches
128
129
130 def add_sgt_range_xml(start, end):
131     """Generate xml containing SGT RangeMach data
132
133     :param start: Start range of SGT
134     :type start: string
135     :param end: End range of SGT
136     :type end: string
137     :returns: String containing xml data for request
138
139     """
140     templ = Template('''
141         <sgt-start>$start</sgt-start>
142         <sgt-end>$end</sgt-end>''')
143     match = templ.substitute({'start': start, 'end': end})
144     return match
145
146
147 def add_acl_entry_default_xml(seq, entry_type, acl_entries):
148     """Generate xml containing AccessList data
149
150     :param seq: Sequence of PrefixList entry
151     :type seq: string
152     :param entry_type: Entry type (permit/deny)
153     :type entry_type: string
154     :param acl_entries: XML data containing AccessList entries
155     :type acl_entries: string
156     :returns: String containing xml data for request
157
158     """
159     templ = Template('''
160         <acl-entry>
161             <entry-type>$entry_type</entry-type>
162             <entry-seq>$seq</entry-seq>$acl_entries
163         </acl-entry>''')
164     matches = templ.substitute(
165         {'seq': seq, 'entry_type': entry_type, 'acl_entries': acl_entries})
166     return matches
167
168
169 def add_acl_entry_xml(ip, mask):
170     """Generate xml containing AccessList data
171
172     :param ip: Ipv4/6 address
173     :type ip: string
174     :param mask: Ipv4/6 wildcard mask
175     :type mask: string
176     :returns: String containing xml data for request
177
178     """
179     templ = Template('''
180         <acl-match>
181             <ip-address>$ip</ip-address>
182             <wildcard-mask>$mask</wildcard-mask>
183         </acl-match>''')
184     return templ.substitute({'ip': ip, 'mask': mask})
185
186
187 def add_eacl_entry_xml(ip, mask, amask, wmask):
188     """Generate xml containing ExtendedAccessList data
189
190     :param ip: Ipv4/6 address
191     :type ip: string
192     :param mask: Ipv4/6 wildcard mask
193     :type mask: string
194     :param amask: Ipv4/6 address mask
195     :type amask: string
196     :param wmask: Ipv4/6 address wildcard mask
197     :type wmask: string
198     :returns: String containing xml data for request
199
200     """
201     templ = Template('''
202         <acl-match>
203             <ip-address>$ip</ip-address>
204             <wildcard-mask>$mask</wildcard-mask>
205             <mask>
206               <address-mask>$amask</address-mask>
207               <wildcard-mask>$wmask</wildcard-mask>
208             </mask>
209         </acl-match>''')
210     return templ.substitute({'ip': ip, 'mask': mask, 'amask': amask, 'wmask': wmask})
211
212
213 def add_pl_entry_default_xml(seq, entry_type, pl_entries):
214     """Generate xml containing PrefixList data
215
216     :param seq: Sequence of PrefixList entry
217     :type seq: string
218     :param entry_type: Entry type (permit/deny)
219     :type entry_type: string
220     :param pl_entries: XML data containing PrefixList entries
221     :type pl_entries: string
222     :returns: String containing xml data for request
223
224     """
225     templ = Template('''
226     <prefix-list-entry xmlns="urn:opendaylight:sxp:controller">
227           <entry-type>$entry_type</entry-type>
228           <entry-seq>$seq</entry-seq>$pl_entries
229     </prefix-list-entry>''')
230     return templ.substitute({'seq': seq, 'entry_type': entry_type, 'pl_entries': pl_entries})
231
232
233 def add_pl_entry_xml(prefix):
234     """Generate xml containing PrefixList data
235
236     :param prefix: Ipv4/6 prefix
237     :type prefix: string
238     :returns: String containing xml data for request
239
240     """
241     templ = Template('''
242         <prefix-list-match>
243             <ip-prefix>$prefix</ip-prefix>
244         </prefix-list-match>''')
245     return templ.substitute({'prefix': prefix})
246
247
248 def add_epl_entry_xml(prefix, op, mask):
249     """Generate xml containing Extended PrefixList data
250
251     :param prefix: Ipv4/6 prefix
252     :type prefix: string
253     :param op: PrefixList option (ge/le/eq)
254     :type op: string
255     :param mask: Ipv4/6 Mask
256     :type mask: string
257     :returns: String containing xml data for request
258
259     """
260     templ = Template('''
261         <prefix-list-match>
262             <ip-prefix>$prefix</ip-prefix>
263             <mask>
264                 <mask-range>$op</mask-range>
265                 <mask-value>$mask</mask-value>
266             </mask>
267         </prefix-list-match>''')
268     return templ.substitute({'prefix': prefix, 'mask': mask, 'op': op})
269
270
271 def parse_peer_groups(groups_json):
272     """Parse JSON string into Array of PeerGroups
273
274     :param groups_json: JSON containing PeerGroups
275     :type groups_json: string
276     :returns: Array containing PeerGroups.
277
278     """
279     data = json.loads(groups_json)
280     groups = data['output']
281     output = []
282     for group in groups.values():
283         output += group
284     return output
285
286
287 def parse_connections(connections_json):
288     """Parse JSON string into Array of Connections
289
290     :param connections_json: JSON containing Connections
291     :type connections_json: string
292     :returns: Array containing Connections.
293
294     """
295     data = json.loads(connections_json)
296     connections = data['output']['connections']
297     output = []
298     for connection in connections.values():
299         output += connection
300     return output
301
302
303 def find_connection(connections_json, version, mode, ip, port, state):
304     """Test if Connection with specified values is contained in JSON
305
306     :param connections_json: JSON containing Connections
307     :type connections_json: string
308     :param version: Version of SXP protocol (version1/2/3/4)
309     :type version: string
310     :param mode: Mode of SXP peer (speaker/listener/both)
311     :type mode: string
312     :param ip: Ipv4/6 address of remote peer
313     :type ip: string
314     :param port: Port on with remote peer listens
315     :type port: string
316     :param state: State of connection (on/off/pendingOn/deleteHoldDown)
317     :type state: string
318     :returns: True if Connection with specified params was found, otherwise False.
319
320     """
321     for connection in parse_connections(connections_json):
322         if (connection['peer-address'] == ip and connection['tcp-port'] == int(port) and connection['mode'] == mode and
323                 connection['version'] == version):
324             if state == 'none':
325                 return True
326             elif connection['state'] == state:
327                 return True
328     return False
329
330
331 def parse_bindings(bindings_json):
332     """Parse JSON string into Array of Bindings
333
334     :param bindings_json: JSON containing Bindings
335     :type bindings_json: string
336     :returns: Array containing Bindings.
337
338     """
339     data = json.loads(bindings_json)
340     output = []
341     for bindings_json in data['output'].values():
342         for binding in bindings_json:
343             output.append(binding)
344     return output
345
346
347 def find_binding(bindings, sgt, prefix):
348     """Test if Binding with specified values is contained in JSON
349
350     :param bindings: JSON containing Bindings
351     :type bindings: string
352     :param sgt: Source Group Tag
353     :type sgt: string
354     :param prefix: Ipv4/6 prefix
355     :type prefix: string
356     :returns: True if Binding with specified params was found, otherwise False.
357
358     """
359     for binding in parse_bindings(bindings):
360         if binding['sgt'] == int(sgt):
361             for ip_prefix in binding['ip-prefix']:
362                 if ip_prefix == prefix:
363                     return True
364     return False
365
366
367 def parse_prefix_groups(prefix_groups_json, source_):
368     """Parse JSON string into Array of PrefixGroups
369
370     :param prefix_groups_json: JSON containing PrefixGroups
371     :type prefix_groups_json: string
372     :param source_: Source of PrefixGroups (sxp/local)
373     :type source_: string
374     :returns: Array containing PrefixGroups.
375
376     """
377     data = json.loads(prefix_groups_json)
378     bindings = data['sxp-node:master-database']
379     output = []
380     for binding in bindings.values():
381         for binding_source in binding:
382             if source_ == "any" or binding_source['binding-source'] == source_:
383                 for prefix_group in binding_source['prefix-group']:
384                     output.append(prefix_group)
385     return output
386
387
388 def find_binding_legacy(prefix_groups_json, sgt, prefix, source_, action):
389     """Test if Binding with specified values is contained in JSON
390
391     :param prefix_groups_json: JSON containing Bindings and PrefixGroups
392     :type prefix_groups_json: string
393     :param sgt: Source Group Tag
394     :type sgt: string
395     :param prefix: Ipv4/6 prefix
396     :type prefix: string
397     :param source_: Source of binding (local/sxp)
398     :type source_: string
399     :param action: Action for binding (add/delete)
400     :type action: string
401     :returns: True if Binding with specified params was found, otherwise False.
402
403     """
404     found = False
405     for prefixgroup in parse_prefix_groups(prefix_groups_json, source_):
406         if prefixgroup['sgt'] == int(sgt):
407             for binding in prefixgroup['binding']:
408                 if binding['ip-prefix'] == prefix and binding['action'] == action:
409                     found = True
410     return found
411
412
413 def add_entry_xml(sgt, prefix, ip):
414     """Generate xml for Add Bindings request
415
416     :param sgt: Source Group Tag
417     :type sgt: string
418     :param prefix: Ipv4/6 prefix
419     :type prefix: string
420     :param ip: Ipv4 address of node
421     :type ip: string
422     :returns: String containing xml data for request
423
424     """
425     templ = Template('''<input>
426   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
427   <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
428   <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
429 </input>''')
430     data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip})
431     return data
432
433
434 def add_connection_xml(version, mode, ip, port, node, password_):
435     """Generate xml for Add Connection request
436
437     :param version: Version of SXP protocol (version1/2/3/4)
438     :type version: string
439     :param mode: Mode of SXP peer (speaker/listener/both)
440     :type mode: string
441     :param ip: Ipv4/6 address of remote peer
442     :type ip: string
443     :param port: Port on with remote peer listens
444     :type port: string
445     :param node: Ipv4 address of node
446     :type node: string
447     :param password_: Password type (none/default)
448     :type password_: string
449     :returns: String containing xml data for request
450
451     """
452     templ = Template('''<input>
453    <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
454    <connections xmlns="urn:opendaylight:sxp:controller">
455       <connection>
456          <peer-address>$ip</peer-address>
457          <tcp-port>$port</tcp-port>
458          <password>$password_</password>
459          <mode>$mode</mode>
460          <version>$version</version>
461          <description>Connection to ISR-G2</description>
462          <connection-timers>
463             <hold-time-min-acceptable>45</hold-time-min-acceptable>
464             <keep-alive-time>30</keep-alive-time>
465             <reconciliation-time>120</reconciliation-time>
466          </connection-timers>
467       </connection>
468    </connections>
469 </input>
470 ''')
471     data = templ.substitute(
472         {'ip': ip, 'port': port, 'mode': mode, 'version': version, 'node': node, 'password_': password_})
473     return data
474
475
476 def delete_connections_xml(address, port, node):
477     """Generate xml for Delete Connection request
478
479     :param address: Ipv4/6 address of remote peer
480     :type address: string
481     :param port: Port on with remote peer listens
482     :type port: string
483     :param node: Ipv4 address of node
484     :type node: string
485     :returns: String containing xml data for request
486
487     """
488     templ = Template('''<input>
489    <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
490    <peer-address xmlns="urn:opendaylight:sxp:controller">$address</peer-address>
491    <tcp-port xmlns="urn:opendaylight:sxp:controller">$port</tcp-port>
492 </input>''')
493     data = templ.substitute({'address': address, 'port': port, 'node': node})
494     return data
495
496
497 def update_binding_xml(sgt0, prefix0, sgt1, prefix1, ip):
498     """Generate xml for Update Binding request
499
500     :param sgt0: Original Source Group Tag
501     :type sgt0: string
502     :param prefix0: Original Ipv4/6 prefix
503     :type prefix0: string
504     :param sgt1: New Source Group Tag
505     :type sgt1: string
506     :param prefix1: New Ipv4/6 prefix
507     :type prefix1: string
508     :param ip: Ipv4 address of node
509     :type ip: string
510     :returns: String containing xml data for request
511
512     """
513     templ = Template('''<input>
514   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
515   <original-binding xmlns="urn:opendaylight:sxp:controller">
516     <sgt>$sgt0</sgt>
517     <ip-prefix>$prefix0</ip-prefix>
518   </original-binding>
519   <new-binding xmlns="urn:opendaylight:sxp:controller">
520     <sgt>$sgt1</sgt>
521     <ip-prefix>$prefix1</ip-prefix>
522   </new-binding>
523 </input>''')
524     data = templ.substitute(
525         {'sgt0': sgt0, 'sgt1': sgt1, 'prefix0': prefix0, 'prefix1': prefix1, 'ip': ip})
526     return data
527
528
529 def delete_binding_xml(sgt, prefix, ip):
530     """Generate xml for Delete Binding request
531
532     :param sgt: Source Group Tag
533     :type sgt: string
534     :param prefix: Ipv4/6 prefix
535     :type prefix: string
536     :param ip: Ipv4 address of node
537     :type ip: string
538     :returns: String containing xml data for request
539
540     """
541     templ = Template('''<input>
542   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
543   <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
544   <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
545 </input>''')
546     data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip})
547     return data
548
549
550 def add_peer_group_xml(name, peers, ip):
551     """Generate xml for Add PeerGroups request
552
553     :param name: Name of PeerGroup
554     :type name: string
555     :param peers: XML formatted peers that will be added to group
556     :type peers: string
557     :param ip: Ipv4 address of node
558     :type ip: string
559     :returns: String containing xml data for request
560
561     """
562     templ = Template('''<input>
563   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
564   <sxp-peer-group xmlns="urn:opendaylight:sxp:controller">
565     <name xmlns="urn:opendaylight:sxp:controller">$name</name>
566     <sxp-peers xmlns="urn:opendaylight:sxp:controller">$peers</sxp-peers>
567     </sxp-peer-group>
568 </input>''')
569     data = templ.substitute({'name': name, 'peers': peers, 'ip': ip})
570     return data
571
572
573 def delete_peer_group_xml(name, ip):
574     """Generate xml for Delete PeerGroup request
575
576     :param name: Name of PeerGroup
577     :type name: string
578     :param ip: Ipv4 address of node
579     :type ip: string
580     :returns: String containing xml data for request
581
582     """
583     templ = Template('''<input>
584   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
585   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$name</peer-group-name>
586 </input>''')
587     data = templ.substitute({'name': name, 'ip': ip})
588     return data
589
590
591 def get_peer_groups_from_node_xml(ip):
592     """Generate xml for Get PeerGroups request
593
594     :param ip: Ipv4 address of node
595     :type ip: string
596     :returns: String containing xml data for request
597
598     """
599     templ = Template('''<input>
600    <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
601 </input>''')
602     data = templ.substitute({'ip': ip})
603     return data
604
605
606 def add_filter_xml(group, filter_type, entries, ip):
607     """Generate xml for Add Filter request
608
609     :param group: Name of group containing filter
610     :type group: string
611     :param filter_type: Type of filter
612     :type filter_type: string
613     :param entries: XML formatted entries that will be added in filter
614     :type entries: string
615     :param ip: Ipv4 address of node
616     :type ip: string
617     :returns: String containing xml data for request
618
619
620     """
621     templ = Template('''<input>
622   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
623   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
624   <sxp-filter xmlns="urn:opendaylight:sxp:controller">
625     <filter-type>$filter_type</filter-type>$entries
626   </sxp-filter>
627 </input>''')
628     data = templ.substitute(
629         {'group': group, 'filter_type': filter_type, 'ip': ip, 'entries': entries})
630     return data
631
632
633 def delete_filter_xml(group, filter_type, ip):
634     """Generate xml for Delete Filter request
635
636     :param group: Name of group containing filter
637     :type group: string
638     :param filter_type: Type of filter
639     :type filter_type: string
640     :param ip: Ipv4 address of node
641     :type ip: string
642     :returns: String containing xml data for request
643
644     """
645     templ = Template('''<input>
646   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
647   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
648   <filter-type xmlns="urn:opendaylight:sxp:controller">$filter_type</filter-type>
649 </input>''')
650     data = templ.substitute(
651         {'group': group, 'filter_type': filter_type, 'ip': ip})
652     return data
653
654
655 def get_connections_from_node_xml(ip):
656     """Generate xml for Get Connections request
657
658     :param ip: Ipv4 address of node
659     :type ip: string
660     :returns: String containing xml data for request
661
662     """
663     templ = Template('''<input>
664    <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
665 </input>''')
666     data = templ.substitute({'ip': ip})
667     return data
668
669
670 def get_bindings_from_node_xml(ip, range):
671     """Generate xml for Get Bindings request
672
673     :param range: All or only Local bindings
674     :type ip: string
675     :param ip: Ipv4 address of node
676     :type ip: string
677     :returns: String containing xml data for request
678
679     """
680     templ = Template('''<input>
681   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
682   <bindings-range xmlns="urn:opendaylight:sxp:controller">$range</bindings-range>
683 </input>''')
684     data = templ.substitute({'ip': ip, 'range': range})
685     return data