SXP Domain Filtering
[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="", ps=""):
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     :param ps: PeerSequence matches to be added to entry
69     :type ps: string
70     :returns: String containing xml data for request
71
72     """
73     entries = ""
74     # Generate XML request containing combination of Matches of different types
75     if sgt:
76         args = sgt.split(',')
77         entries += add_sgt_matches_xml(args)
78     elif esgt:
79         args = esgt.split(',')
80         entries += add_sgt_range_xml(args[0], args[1])
81     if pl:
82         entries += add_pl_entry_xml(pl)
83     elif epl:
84         args = epl.split(',')
85         entries += add_epl_entry_xml(args[0], args[1], args[2])
86     if acl:
87         args = acl.split(',')
88         entries += add_acl_entry_xml(args[0], args[1])
89     elif eacl:
90         args = eacl.split(',')
91         entries += add_eacl_entry_xml(args[0], args[1], args[2], args[3])
92     if ps:
93         args = ps.split(',')
94         entries += add_ps_entry_xml(args[0], args[1])
95     # Wrap entries in ACL/PrefixList according to specified values
96     if pl or epl:
97         return add_pl_entry_default_xml(seq, entry_type, entries)
98     elif ps:
99         return add_ps_entry_default_xml(seq, entry_type, entries)
100     return add_acl_entry_default_xml(seq, entry_type, entries)
101
102
103 def add_peers(*args):
104     """Generate xml containing Peer mach data
105
106     :param args: Peers data
107     :type args: dict
108     :returns: String containing xml data for request
109
110     """
111     templ = Template('''
112         <sxp-peer>
113             <peer-address>$ip</peer-address>
114         </sxp-peer>''')
115     peers = ""
116     for count, value in enumerate(args):
117         peers += templ.substitute({'ip': value})
118     return peers
119
120
121 def add_domains(*args):
122     """Generate xml containing Domain mach data
123
124     :param args: Domain data
125     :type args: dict
126     :returns: String containing xml data for request
127
128     """
129     templ = Template('''
130         <domain>
131             <name>$name</name>
132         </domain>''')
133     peers = ""
134     for count, value in enumerate(args):
135         peers += templ.substitute({'name': value})
136     return peers
137
138
139 def add_sgt_matches_xml(sgt_entries):
140     """Generate xml containing SGT mach data
141
142     :param sgt_entries: SGT matches
143     :type sgt_entries: string
144     :returns: String containing xml data for request
145
146     """
147     templ = Template('''
148         <matches>$sgt</matches>''')
149     matches = ""
150     for sgt in sgt_entries:
151         matches += templ.substitute({'sgt': sgt})
152     return matches
153
154
155 def add_sgt_range_xml(start, end):
156     """Generate xml containing SGT RangeMach data
157
158     :param start: Start range of SGT
159     :type start: string
160     :param end: End range of SGT
161     :type end: string
162     :returns: String containing xml data for request
163
164     """
165     templ = Template('''
166         <sgt-start>$start</sgt-start>
167         <sgt-end>$end</sgt-end>''')
168     match = templ.substitute({'start': start, 'end': end})
169     return match
170
171
172 def add_acl_entry_default_xml(seq, entry_type, acl_entries):
173     """Generate xml containing AccessList data
174
175     :param seq: Sequence of PrefixList entry
176     :type seq: string
177     :param entry_type: Entry type (permit/deny)
178     :type entry_type: string
179     :param acl_entries: XML data containing AccessList entries
180     :type acl_entries: string
181     :returns: String containing xml data for request
182
183     """
184     templ = Template('''
185         <acl-entry>
186             <entry-type>$entry_type</entry-type>
187             <entry-seq>$seq</entry-seq>$acl_entries
188         </acl-entry>''')
189     matches = templ.substitute(
190         {'seq': seq, 'entry_type': entry_type, 'acl_entries': acl_entries})
191     return matches
192
193
194 def add_acl_entry_xml(ip, mask):
195     """Generate xml containing AccessList data
196
197     :param ip: Ipv4/6 address
198     :type ip: string
199     :param mask: Ipv4/6 wildcard mask
200     :type mask: string
201     :returns: String containing xml data for request
202
203     """
204     templ = Template('''
205         <acl-match>
206             <ip-address>$ip</ip-address>
207             <wildcard-mask>$mask</wildcard-mask>
208         </acl-match>''')
209     return templ.substitute({'ip': ip, 'mask': mask})
210
211
212 def add_eacl_entry_xml(ip, mask, amask, wmask):
213     """Generate xml containing ExtendedAccessList data
214
215     :param ip: Ipv4/6 address
216     :type ip: string
217     :param mask: Ipv4/6 wildcard mask
218     :type mask: string
219     :param amask: Ipv4/6 address mask
220     :type amask: string
221     :param wmask: Ipv4/6 address wildcard mask
222     :type wmask: string
223     :returns: String containing xml data for request
224
225     """
226     templ = Template('''
227         <acl-match>
228             <ip-address>$ip</ip-address>
229             <wildcard-mask>$mask</wildcard-mask>
230             <mask>
231               <address-mask>$amask</address-mask>
232               <wildcard-mask>$wmask</wildcard-mask>
233             </mask>
234         </acl-match>''')
235     return templ.substitute({'ip': ip, 'mask': mask, 'amask': amask, 'wmask': wmask})
236
237
238 def add_ps_entry_default_xml(seq, entry_type, ps_entries):
239     """Generate xml containing PeerSequence data
240
241     :param seq: Sequence of PrefixList entry
242     :type seq: string
243     :param entry_type: Entry type (permit/deny)
244     :type entry_type: string
245     :param ps_entries: XML data containing PeerSequence entries
246     :type ps_entries: string
247     :returns: String containing xml data for request
248
249     """
250     templ = Template('''
251     <peer-sequence-entry xmlns="urn:opendaylight:sxp:controller">
252           <entry-type>$entry_type</entry-type>
253           <entry-seq>$seq</entry-seq>$ps_entries
254     </peer-sequence-entry>''')
255     return templ.substitute({'seq': seq, 'entry_type': entry_type, 'ps_entries': ps_entries})
256
257
258 def add_pl_entry_default_xml(seq, entry_type, pl_entries):
259     """Generate xml containing PrefixList data
260
261     :param seq: Sequence of PrefixList entry
262     :type seq: string
263     :param entry_type: Entry type (permit/deny)
264     :type entry_type: string
265     :param pl_entries: XML data containing PrefixList entries
266     :type pl_entries: string
267     :returns: String containing xml data for request
268
269     """
270     templ = Template('''
271     <prefix-list-entry xmlns="urn:opendaylight:sxp:controller">
272           <entry-type>$entry_type</entry-type>
273           <entry-seq>$seq</entry-seq>$pl_entries
274     </prefix-list-entry>''')
275     return templ.substitute({'seq': seq, 'entry_type': entry_type, 'pl_entries': pl_entries})
276
277
278 def add_pl_entry_xml(prefix):
279     """Generate xml containing PrefixList data
280
281     :param prefix: Ipv4/6 prefix
282     :type prefix: string
283     :returns: String containing xml data for request
284
285     """
286     templ = Template('''
287         <prefix-list-match>
288             <ip-prefix>$prefix</ip-prefix>
289         </prefix-list-match>''')
290     return templ.substitute({'prefix': prefix})
291
292
293 def add_epl_entry_xml(prefix, op, mask):
294     """Generate xml containing Extended PrefixList data
295
296     :param prefix: Ipv4/6 prefix
297     :type prefix: string
298     :param op: PrefixList option (ge/le/eq)
299     :type op: string
300     :param mask: Ipv4/6 Mask
301     :type mask: string
302     :returns: String containing xml data for request
303
304     """
305     templ = Template('''
306         <prefix-list-match>
307             <ip-prefix>$prefix</ip-prefix>
308             <mask>
309                 <mask-range>$op</mask-range>
310                 <mask-value>$mask</mask-value>
311             </mask>
312         </prefix-list-match>''')
313     return templ.substitute({'prefix': prefix, 'mask': mask, 'op': op})
314
315
316 def add_ps_entry_xml(op, length):
317     """Generate xml containing Extended PrefixList data
318
319     :param op: PrefixList option (ge/le/eq)
320     :type op: string
321     :param length: PeerSequence length
322     :type length: string
323     :returns: String containing xml data for request
324
325     """
326     templ = Template('''
327         <peer-sequence-length>$length</peer-sequence-length>
328         <peer-sequence-range>$op</peer-sequence-range>
329         ''')
330     return templ.substitute({'length': length, 'op': op})
331
332
333 def parse_peer_groups(groups_json):
334     """Parse JSON string into Array of PeerGroups
335
336     :param groups_json: JSON containing PeerGroups
337     :type groups_json: string
338     :returns: Array containing PeerGroups.
339
340     """
341     data = json.loads(groups_json)
342     groups = data['output']
343     output = []
344     for group in groups.values():
345         output += group
346     return output
347
348
349 def parse_connections(connections_json):
350     """Parse JSON string into Array of Connections
351
352     :param connections_json: JSON containing Connections
353     :type connections_json: string
354     :returns: Array containing Connections.
355
356     """
357     data = json.loads(connections_json)
358     connections = data['output']['connections']
359     output = []
360     for connection in connections.values():
361         output += connection
362     return output
363
364
365 def find_connection(connections_json, version, mode, ip, port, state):
366     """Test if Connection with specified values is contained in JSON
367
368     :param connections_json: JSON containing Connections
369     :type connections_json: string
370     :param version: Version of SXP protocol (version1/2/3/4)
371     :type version: string
372     :param mode: Mode of SXP peer (speaker/listener/both)
373     :type mode: string
374     :param ip: Ipv4/6 address of remote peer
375     :type ip: string
376     :param port: Port on with remote peer listens
377     :type port: string
378     :param state: State of connection (on/off/pendingOn/deleteHoldDown)
379     :type state: string
380     :returns: True if Connection with specified params was found, otherwise False.
381
382     """
383     for connection in parse_connections(connections_json):
384         if (connection['peer-address'] == ip and connection['tcp-port'] == int(port) and connection['mode'] == mode and
385                 connection['version'] == version):
386             if state == 'none':
387                 return True
388             elif connection['state'] == state:
389                 return True
390     return False
391
392
393 def parse_bindings(bindings_json):
394     """Parse JSON string into Array of Bindings
395
396     :param bindings_json: JSON containing Bindings
397     :type bindings_json: string
398     :returns: Array containing Bindings.
399
400     """
401     data = json.loads(bindings_json)
402     output = []
403     for bindings_json in data['output'].values():
404         for binding in bindings_json:
405             output.append(binding)
406     return output
407
408
409 def find_binding(bindings, sgt, prefix):
410     """Test if Binding with specified values is contained in JSON
411
412     :param bindings: JSON containing Bindings
413     :type bindings: string
414     :param sgt: Source Group Tag
415     :type sgt: string
416     :param prefix: Ipv4/6 prefix
417     :type prefix: string
418     :returns: True if Binding with specified params was found, otherwise False.
419
420     """
421     for binding in parse_bindings(bindings):
422         if binding['sgt'] == int(sgt):
423             for ip_prefix in binding['ip-prefix']:
424                 if ip_prefix == prefix:
425                     return True
426     return False
427
428
429 def parse_prefix_groups(prefix_groups_json, source_):
430     """Parse JSON string into Array of PrefixGroups
431
432     :param prefix_groups_json: JSON containing PrefixGroups
433     :type prefix_groups_json: string
434     :param source_: Source of PrefixGroups (sxp/local)
435     :type source_: string
436     :returns: Array containing PrefixGroups.
437
438     """
439     data = json.loads(prefix_groups_json)
440     bindings = data['sxp-node:master-database']
441     output = []
442     for binding in bindings.values():
443         for binding_source in binding:
444             if source_ == "any" or binding_source['binding-source'] == source_:
445                 for prefix_group in binding_source['prefix-group']:
446                     output.append(prefix_group)
447     return output
448
449
450 def find_binding_legacy(prefix_groups_json, sgt, prefix, source_, action):
451     """Test if Binding with specified values is contained in JSON
452
453     :param prefix_groups_json: JSON containing Bindings and PrefixGroups
454     :type prefix_groups_json: string
455     :param sgt: Source Group Tag
456     :type sgt: string
457     :param prefix: Ipv4/6 prefix
458     :type prefix: string
459     :param source_: Source of binding (local/sxp)
460     :type source_: string
461     :param action: Action for binding (add/delete)
462     :type action: string
463     :returns: True if Binding with specified params was found, otherwise False.
464
465     """
466     found = False
467     for prefixgroup in parse_prefix_groups(prefix_groups_json, source_):
468         if prefixgroup['sgt'] == int(sgt):
469             for binding in prefixgroup['binding']:
470                 if binding['ip-prefix'] == prefix and binding['action'] == action:
471                     found = True
472     return found
473
474
475 def add_entry_xml(sgt, prefix, ip, domain_name):
476     """Generate xml for Add Bindings request
477
478     :param sgt: Source Group Tag
479     :type sgt: string
480     :param prefix: Ipv4/6 prefix
481     :type prefix: string
482     :param ip: Ipv4 address of node
483     :type ip: string
484     :param domain_name: Name of Domain
485     :type domain_name: string
486     :returns: String containing xml data for request
487
488     """
489     templ = Template('''<input>
490   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
491   $domain
492   <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
493   <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
494 </input>''')
495     data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip, 'domain': get_domain_name(domain_name)})
496     return data
497
498
499 def add_connection_xml(version, mode, ip, port, node, password_, domain_name):
500     """Generate xml for Add Connection request
501
502     :param version: Version of SXP protocol (version1/2/3/4)
503     :type version: string
504     :param mode: Mode of SXP peer (speaker/listener/both)
505     :type mode: string
506     :param ip: Ipv4/6 address of remote peer
507     :type ip: string
508     :param port: Port on with remote peer listens
509     :type port: string
510     :param node: Ipv4 address of node
511     :type node: string
512     :param password_: Password type (none/default)
513     :type password_: string
514     :param domain_name: Name of Domain
515     :type domain_name: string
516     :returns: String containing xml data for request
517
518     """
519     templ = Template('''<input>
520    <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
521    $domain
522    <connections xmlns="urn:opendaylight:sxp:controller">
523       <connection>
524          <peer-address>$ip</peer-address>
525          <tcp-port>$port</tcp-port>
526          <password>$password_</password>
527          <mode>$mode</mode>
528          <version>$version</version>
529          <description>Connection to ISR-G2</description>
530          <connection-timers>
531             <hold-time-min-acceptable>45</hold-time-min-acceptable>
532             <keep-alive-time>30</keep-alive-time>
533             <reconciliation-time>120</reconciliation-time>
534          </connection-timers>
535       </connection>
536    </connections>
537 </input>
538 ''')
539     data = templ.substitute(
540         {'ip': ip, 'port': port, 'mode': mode, 'version': version, 'node': node,
541          'password_': password_, 'domain': get_domain_name(domain_name)})
542     return data
543
544
545 def delete_connections_xml(address, port, node, domain_name):
546     """Generate xml for Delete Connection request
547
548     :param address: Ipv4/6 address of remote peer
549     :type address: string
550     :param port: Port on with remote peer listens
551     :type port: string
552     :param node: Ipv4 address of node
553     :type node: string
554     :param domain_name: Name of Domain
555     :type domain_name: string
556     :returns: String containing xml data for request
557
558     """
559     templ = Template('''<input>
560    <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
561    $domain
562    <peer-address xmlns="urn:opendaylight:sxp:controller">$address</peer-address>
563    <tcp-port xmlns="urn:opendaylight:sxp:controller">$port</tcp-port>
564 </input>''')
565     data = templ.substitute({'address': address, 'port': port, 'node': node, 'domain': get_domain_name(domain_name)})
566     return data
567
568
569 def update_binding_xml(sgt0, prefix0, sgt1, prefix1, ip, domain_name):
570     """Generate xml for Update Binding request
571
572     :param sgt0: Original Source Group Tag
573     :type sgt0: string
574     :param prefix0: Original Ipv4/6 prefix
575     :type prefix0: string
576     :param sgt1: New Source Group Tag
577     :type sgt1: string
578     :param prefix1: New Ipv4/6 prefix
579     :type prefix1: string
580     :param ip: Ipv4 address of node
581     :type ip: string
582     :param domain_name: Name of Domain
583     :type domain_name: string
584     :returns: String containing xml data for request
585
586     """
587     templ = Template('''<input>
588   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
589   $domain
590   <original-binding xmlns="urn:opendaylight:sxp:controller">
591     <sgt>$sgt0</sgt>
592     <ip-prefix>$prefix0</ip-prefix>
593   </original-binding>
594   <new-binding xmlns="urn:opendaylight:sxp:controller">
595     <sgt>$sgt1</sgt>
596     <ip-prefix>$prefix1</ip-prefix>
597   </new-binding>
598 </input>''')
599     data = templ.substitute(
600         {'sgt0': sgt0, 'sgt1': sgt1, 'prefix0': prefix0, 'prefix1': prefix1, 'ip': ip,
601          'domain': get_domain_name(domain_name)})
602     return data
603
604
605 def delete_binding_xml(sgt, prefix, ip, domain_name):
606     """Generate xml for Delete Binding request
607
608     :param sgt: Source Group Tag
609     :type sgt: string
610     :param prefix: Ipv4/6 prefix
611     :type prefix: string
612     :param ip: Ipv4 address of node
613     :type ip: string
614     :param domain_name: Name of Domain
615     :type domain_name: string
616     :returns: String containing xml data for request
617
618     """
619     templ = Template('''<input>
620   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
621   <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
622   <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
623   $domain
624 </input>''')
625     data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip, 'domain': get_domain_name(domain_name)})
626     return data
627
628
629 def add_peer_group_xml(name, peers, ip):
630     """Generate xml for Add PeerGroups request
631
632     :param name: Name of PeerGroup
633     :type name: string
634     :param peers: XML formatted peers that will be added to group
635     :type peers: string
636     :param ip: Ipv4 address of node
637     :type ip: string
638     :returns: String containing xml data for request
639
640     """
641     templ = Template('''<input>
642   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
643   <sxp-peer-group xmlns="urn:opendaylight:sxp:controller">
644     <name xmlns="urn:opendaylight:sxp:controller">$name</name>
645     <sxp-peers xmlns="urn:opendaylight:sxp:controller">$peers</sxp-peers>
646     </sxp-peer-group>
647 </input>''')
648     data = templ.substitute({'name': name, 'peers': peers, 'ip': ip})
649     return data
650
651
652 def delete_peer_group_xml(name, ip):
653     """Generate xml for Delete PeerGroup request
654
655     :param name: Name of PeerGroup
656     :type name: string
657     :param ip: Ipv4 address of node
658     :type ip: string
659     :returns: String containing xml data for request
660
661     """
662     templ = Template('''<input>
663   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
664   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$name</peer-group-name>
665 </input>''')
666     data = templ.substitute({'name': name, 'ip': ip})
667     return data
668
669
670 def get_peer_groups_from_node_xml(ip):
671     """Generate xml for Get PeerGroups request
672
673     :param ip: Ipv4 address of node
674     :type ip: string
675     :returns: String containing xml data for request
676
677     """
678     templ = Template('''<input>
679    <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
680 </input>''')
681     data = templ.substitute({'ip': ip})
682     return data
683
684
685 def add_filter_xml(group, filter_type, entries, ip):
686     """Generate xml for Add Filter request
687
688     :param group: Name of group containing filter
689     :type group: string
690     :param filter_type: Type of filter
691     :type filter_type: string
692     :param entries: XML formatted entries that will be added in filter
693     :type entries: string
694     :param ip: Ipv4 address of node
695     :type ip: string
696     :returns: String containing xml data for request
697
698     """
699     templ = Template('''<input>
700   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
701   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
702   <sxp-filter xmlns="urn:opendaylight:sxp:controller">
703     <filter-type>$filter_type</filter-type>$entries
704   </sxp-filter>
705 </input>''')
706     data = templ.substitute(
707         {'group': group, 'filter_type': filter_type, 'ip': ip, 'entries': entries})
708     return data
709
710
711 def add_domain_filter_xml(domain, domains, entries, ip, filter_name=None):
712     """Generate xml for Add Domain Filter request
713
714     :param domain: Name of Domain containing filter
715     :type domain: string
716     :param domains: Domains on which filter will be applied
717     :type domains: string
718     :param entries: XML formatted entries that will be added in filter
719     :type entries: string
720     :param ip: Ipv4 address of node
721     :type ip: string
722     :param filter_name: Name of filter
723     :type filter_name: string
724     :returns: String containing xml data for request
725
726     """
727     if filter_name:
728         filter_name = "<filter-name>" + filter_name + "</filter-name>"
729     templ = Template('''<input>
730   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
731   <domain-name xmlns="urn:opendaylight:sxp:controller">$domain</domain-name>
732   <sxp-domain-filter xmlns="urn:opendaylight:sxp:controller">
733     $filter_name
734     <domains>$domains</domains>
735     $entries
736   </sxp-domain-filter>
737 </input>''')
738     data = templ.substitute(
739         {'domain': domain, 'domains': domains, 'ip': ip, 'entries': entries, 'filter_name': filter_name})
740     return data
741
742
743 def delete_filter_xml(group, filter_type, ip):
744     """Generate xml for Delete Filter request
745
746     :param group: Name of group containing filter
747     :type group: string
748     :param filter_type: Type of filter
749     :type filter_type: string
750     :param ip: Ipv4 address of node
751     :type ip: string
752     :returns: String containing xml data for request
753
754     """
755     templ = Template('''<input>
756   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
757   <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
758   <filter-type xmlns="urn:opendaylight:sxp:controller">$filter_type</filter-type>
759 </input>''')
760     data = templ.substitute(
761         {'group': group, 'filter_type': filter_type, 'ip': ip})
762     return data
763
764
765 def delete_domain_filter_xml(domain, ip, filter_name=None):
766     """Generate xml for Delete Filter request
767
768     :param domain: Name of Domain containing filter
769     :type domain: string
770     :param ip: Ipv4 address of node
771     :type ip: string
772     :param filter_name: Name of filter
773     :type filter_name: string
774     :returns: String containing xml data for request
775
776     """
777     if filter_name:
778         filter_name = '<filter-name xmlns="urn:opendaylight:sxp:controller">' + filter_name + "</filter-name>"
779     templ = Template('''<input>
780   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
781   <domain-name xmlns="urn:opendaylight:sxp:controller">$domain</domain-name>
782   $filter_name
783 </input>''')
784     data = templ.substitute(
785         {'domain': domain, 'ip': ip, 'filter_name': filter_name})
786     return data
787
788
789 def get_connections_from_node_xml(ip, domain_name):
790     """Generate xml for Get Connections request
791
792     :param ip: Ipv4 address of node
793     :type ip: string
794     :param domain_name: Name of Domain
795     :type domain_name: string
796     :returns: String containing xml data for request
797
798     """
799     templ = Template('''<input>
800    <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
801    $domain
802 </input>''')
803     data = templ.substitute({'ip': ip, 'domain': get_domain_name(domain_name)})
804     return data
805
806
807 def get_bindings_from_node_xml(ip, binding_range, domain_name):
808     """Generate xml for Get Bindings request
809
810     :param binding_range: All or only Local bindings
811     :type binding_range: string
812     :param ip: Ipv4 address of node
813     :type ip: string
814     :param domain_name: Name of Domain
815     :type domain_name: string
816     :returns: String containing xml data for request
817
818     """
819     templ = Template('''<input>
820   <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
821   <bindings-range xmlns="urn:opendaylight:sxp:controller">$range</bindings-range>
822   $domain
823 </input>''')
824     data = templ.substitute({'ip': ip, 'range': binding_range, 'domain': get_domain_name(domain_name)})
825     return data
826
827
828 def add_node_xml(node_id, port, password, version, node_ip=None, expansion=0):
829     """Generate xml for Add Node request
830
831     :param node_id: Ipv4 address formatted node id
832     :type node_id: string
833     :param node_ip: Ipv4 address of node
834     :type node_ip: string
835     :param port: Node port number
836     :type port: int
837     :param expansion: Bindings expansion
838     :type expansion: int
839     :returns: String containing xml data for request
840
841     """
842     if node_ip is None:
843         node_ip = node_id
844     templ = Template('''<input xmlns="urn:opendaylight:sxp:controller">
845     <node-id>$id</node-id>
846     <timers>
847         <retry-open-time>1</retry-open-time>
848         <hold-time-min-acceptable>120</hold-time-min-acceptable>
849         <delete-hold-down-time>120</delete-hold-down-time>
850         <hold-time-min>90</hold-time-min>
851         <reconciliation-time>120</reconciliation-time>
852         <hold-time>90</hold-time>
853         <hold-time-max>180</hold-time-max>
854         <keep-alive-time>30</keep-alive-time>
855     </timers>
856     <mapping-expanded>$expansion</mapping-expanded>
857     <security>
858         <password>$password</password>
859     </security>
860     <tcp-port>$port</tcp-port>
861     <version>$version</version>
862     <description>ODL SXP Controller</description>
863     <source-ip>$ip</source-ip>
864     <master-database></master-database>
865 </input>''')
866     data = templ.substitute(
867         {'ip': node_ip, 'id': node_id, 'port': port, 'password': password, 'version': version, 'expansion': expansion})
868     return data
869
870
871 def delete_node_xml(node_id):
872     """Generate xml for Delete node request
873
874     :param node_id: Ipv4 address formatted node id
875     :type node_id: string
876     :returns: String containing xml data for request
877
878     """
879     templ = Template('''<input xmlns="urn:opendaylight:sxp:controller">
880   <node-id>$id</node-id>
881 </input>''')
882     data = templ.substitute({'id': node_id})
883     return data
884
885
886 def add_domain_xml(node_id, name):
887     """Generate xml for Add Domain request
888
889     :param node_id: Id of node
890     :type node_id: string
891     :param name: Name of Domain
892     :type name: string
893     :returns: String containing xml data for request
894
895     """
896     templ = Template('''<input>
897   <node-id xmlns="urn:opendaylight:sxp:controller">$id</node-id>
898   <domain-name xmlns="urn:opendaylight:sxp:controller">$name</domain-name>
899 </input>''')
900     data = templ.substitute({'name': name, 'id': node_id})
901     return data
902
903
904 def delete_domain_xml(node_id, name):
905     """Generate xml for Remove Domain request
906
907     :param node_id: Id of node
908     :type node_id: string
909     :param name: Name of Domain
910     :type name: string
911     :returns: String containing xml data for request
912
913     """
914     return add_domain_xml(name, node_id)
915
916
917 def get_domain_name(domain_name):
918     """Generate xml for Get Bindings request
919
920     :param domain_name: Name of Domain
921     :type domain_name: string
922     :returns: String containing xml data for request
923
924     """
925     if domain_name == 'global':
926         return ''
927     else:
928         return '<domain-name xmlns="urn:opendaylight:sxp:controller">' + domain_name + '</domain-name>'
929
930
931 def add_bindings_xml(node_id, domain, sgt, prefixes):
932     """Generate xml for Add Bindings request
933
934     :param node_id: Id of node
935     :type node_id: string
936     :param domain: Name of Domain
937     :type domain: string
938     :param sgt: Security group
939     :type sgt: int
940     :param prefixes: List of ip-prefixes
941     :type prefixes: string
942     :returns: String containing xml data for request
943
944     """
945     bindings = ''
946     for prefix in prefixes.split(','):
947         bindings += '\n' + '<ip-prefix>' + prefix + '</ip-prefix>'
948     templ = Template('''<input>
949   <node-id xmlns="urn:opendaylight:sxp:controller">$id</node-id>
950   <domain-name xmlns="urn:opendaylight:sxp:controller">$name</domain-name>
951   <binding xmlns="urn:opendaylight:sxp:controller">
952       <sgt>$sgt</sgt>
953       $bindings
954   </binding>
955 </input>''')
956     data = templ.substitute({'name': domain, 'id': node_id, 'sgt': sgt, 'bindings': bindings})
957     return data
958
959
960 def delete_bindings_xml(node_id, domain, sgt, prefixes):
961     """Generate xml for Remove Bindings request
962
963     :param node_id: Id of node
964     :type node_id: string
965     :param domain: Name of Domain
966     :type domain: string
967     :param sgt: Security group
968     :type sgt: int
969     :param prefixes: List of ip-prefixes
970     :type prefixes: string
971     :returns: String containing xml data for request
972
973     """
974     return add_bindings_xml(node_id, domain, sgt, prefixes)
975
976
977 def prefix_range(start, end):
978     """Generate and concatenate ip-prefixes
979
980     :param start: Start index
981     :type start: string
982     :param end: End index
983     :type end: string
984     :returns: String containing concatenated ip-prefixes
985
986     """
987     start = int(start)
988     end = int(end)
989     index = 0
990     prefixes = ''
991     while index < end:
992         prefixes += get_ip_from_number(start + index) + '/32'
993         index += 1
994         if index < end:
995             prefixes += ','
996     return prefixes