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