2 from ipaddr import IPAddress
3 from string import Template
7 """Gets modulo of number
9 :param num: Number to be used
11 :param base: Base used
13 :returns: Int representing modulo of specified numbers.
16 return int(num) % int(base)
19 def get_ip_from_number(n):
20 """Generate string representing Ipv4 from specified number that is added number 2130706432
22 :param n: Number to be converted
24 :returns: String containing Ipv4.
27 ip = IPAddress(2130706432 + n)
31 def lower_version(ver1, ver2):
32 """Generate xml containing SGT mach data
34 :param ver1: Version of SXP protocol for compare
36 :param ver2: Version of SXP protocol for compare
38 :returns: String containing lower from those two specified versions.
49 def get_filter_entry(seq, entry_type, sgt="", esgt="", acl="", eacl="", pl="", epl=""):
50 """Generate xml containing FilterEntry data
52 :param seq: Sequence of entry
54 :param entry_type: Type of entry (permit/deny)
55 :type entry_type: string
56 :param sgt: SGT matches to be added to entry
58 :param esgt: SGT ranges match to be added to entry
60 :param acl: ACL matches to be added to entry
62 :param eacl: EACL matches to be added to entry
64 :param pl: PrefixList matches to be added to entry
66 :param epl: ExtendedPrefixList matches to be added to entry
68 :returns: String containing xml data for request
72 # Generate XML request containing combination of Matches of different types
75 entries += add_sgt_matches_xml(args)
77 args = esgt.split(',')
78 entries += add_sgt_range_xml(args[0], args[1])
80 entries += add_pl_entry_xml(pl)
83 entries += add_epl_entry_xml(args[0], args[1], args[2])
86 entries += add_acl_entry_xml(args[0], args[1])
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
92 return add_pl_entry_default_xml(seq, entry_type, entries)
93 return add_acl_entry_default_xml(seq, entry_type, entries)
97 """Generate xml containing Peer mach data
99 :param args: Peers data
101 :returns: String containing xml data for request
106 <peer-address>$ip</peer-address>
109 for count, value in enumerate(args):
110 peers += templ.substitute({'ip': value})
114 def add_sgt_matches_xml(sgt_entries):
115 """Generate xml containing SGT mach data
117 :param sgt_entries: SGT matches
118 :type sgt_entries: string
119 :returns: String containing xml data for request
123 <matches>$sgt</matches>''')
125 for sgt in sgt_entries:
126 matches += templ.substitute({'sgt': sgt})
130 def add_sgt_range_xml(start, end):
131 """Generate xml containing SGT RangeMach data
133 :param start: Start range of SGT
135 :param end: End range of SGT
137 :returns: String containing xml data for request
141 <sgt-start>$start</sgt-start>
142 <sgt-end>$end</sgt-end>''')
143 match = templ.substitute({'start': start, 'end': end})
147 def add_acl_entry_default_xml(seq, entry_type, acl_entries):
148 """Generate xml containing AccessList data
150 :param seq: Sequence of PrefixList entry
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
161 <entry-type>$entry_type</entry-type>
162 <entry-seq>$seq</entry-seq>$acl_entries
164 matches = templ.substitute(
165 {'seq': seq, 'entry_type': entry_type, 'acl_entries': acl_entries})
169 def add_acl_entry_xml(ip, mask):
170 """Generate xml containing AccessList data
172 :param ip: Ipv4/6 address
174 :param mask: Ipv4/6 wildcard mask
176 :returns: String containing xml data for request
181 <ip-address>$ip</ip-address>
182 <wildcard-mask>$mask</wildcard-mask>
184 return templ.substitute({'ip': ip, 'mask': mask})
187 def add_eacl_entry_xml(ip, mask, amask, wmask):
188 """Generate xml containing ExtendedAccessList data
190 :param ip: Ipv4/6 address
192 :param mask: Ipv4/6 wildcard mask
194 :param amask: Ipv4/6 address mask
196 :param wmask: Ipv4/6 address wildcard mask
198 :returns: String containing xml data for request
203 <ip-address>$ip</ip-address>
204 <wildcard-mask>$mask</wildcard-mask>
206 <address-mask>$amask</address-mask>
207 <wildcard-mask>$wmask</wildcard-mask>
210 return templ.substitute({'ip': ip, 'mask': mask, 'amask': amask, 'wmask': wmask})
213 def add_pl_entry_default_xml(seq, entry_type, pl_entries):
214 """Generate xml containing PrefixList data
216 :param seq: Sequence of PrefixList entry
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
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})
233 def add_pl_entry_xml(prefix):
234 """Generate xml containing PrefixList data
236 :param prefix: Ipv4/6 prefix
238 :returns: String containing xml data for request
243 <ip-prefix>$prefix</ip-prefix>
244 </prefix-list-match>''')
245 return templ.substitute({'prefix': prefix})
248 def add_epl_entry_xml(prefix, op, mask):
249 """Generate xml containing Extended PrefixList data
251 :param prefix: Ipv4/6 prefix
253 :param op: PrefixList option (ge/le/eq)
255 :param mask: Ipv4/6 Mask
257 :returns: String containing xml data for request
262 <ip-prefix>$prefix</ip-prefix>
264 <mask-range>$op</mask-range>
265 <mask-value>$mask</mask-value>
267 </prefix-list-match>''')
268 return templ.substitute({'prefix': prefix, 'mask': mask, 'op': op})
271 def parse_peer_groups(groups_json):
272 """Parse JSON string into Array of PeerGroups
274 :param groups_json: JSON containing PeerGroups
275 :type groups_json: string
276 :returns: Array containing PeerGroups.
279 data = json.loads(groups_json)
280 groups = data['output']
282 for group in groups.values():
287 def parse_connections(connections_json):
288 """Parse JSON string into Array of Connections
290 :param connections_json: JSON containing Connections
291 :type connections_json: string
292 :returns: Array containing Connections.
295 data = json.loads(connections_json)
296 connections = data['output']['connections']
298 for connection in connections.values():
303 def find_connection(connections_json, version, mode, ip, port, state):
304 """Test if Connection with specified values is contained in JSON
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)
312 :param ip: Ipv4/6 address of remote peer
314 :param port: Port on with remote peer listens
316 :param state: State of connection (on/off/pendingOn/deleteHoldDown)
318 :returns: True if Connection with specified params was found, otherwise False.
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):
326 elif connection['state'] == state:
331 def parse_prefix_groups(prefix_groups_json, source_):
332 """Parse JSON string into Array of PrefixGroups
334 :param prefix_groups_json: JSON containing PrefixGroups
335 :type prefix_groups_json: string
336 :param source_: Source of PrefixGroups (sxp/local)
337 :type source_: string
338 :returns: Array containing PrefixGroups.
341 data = json.loads(prefix_groups_json)
342 bindings = data['sxp-node:master-database']
344 for binding in bindings.values():
345 for binding_source in binding:
346 if binding_source['binding-source'] == source_:
347 for prefix_group in binding_source['prefix-group']:
348 output.append(prefix_group)
352 def find_binding(prefix_groups_json, sgt, prefix, source_, action):
353 """Test if Binding with specified values is contained in JSON
355 :param prefix_groups_json: JSON containing Bindings and PrefixGroups
356 :type prefix_groups_json: string
357 :param sgt: Source Group Tag
359 :param prefix: Ipv4/6 prefix
361 :param source_: Source of binding (local/sxp)
362 :type source_: string
363 :param action: Action for binding (add/delete)
365 :returns: True if Binding with specified params was found, otherwise False.
369 for prefixgroup in parse_prefix_groups(prefix_groups_json, source_):
370 if prefixgroup['sgt'] == int(sgt):
371 for binding in prefixgroup['binding']:
372 if binding['ip-prefix'] == prefix and binding['action'] == action:
377 def find_binding_with_peer_sequence(prefix_groups_json, sgt, prefix, source_, action, node_id, peer_seq):
378 """Test if Binding with specified values is contained in JSON
380 :param prefix_groups_json: JSON containing Bindings and PrefixGroups
381 :type prefix_groups_json: string
382 :param sgt: Source Group Tag
384 :param prefix: Ipv4/6 prefix
386 :param source_: Source of binding (local/sxp)
387 :type source_: string
388 :param action: Action for binding (add/delete)
390 :param node_id: NodeId of from where Binding came from
391 :type node_id: string
392 :param peer_seq: Hop of specified NodeId from where Binding came from
393 :type peer_seq: string
394 :returns: True if Binding with specified params was found, otherwise False.
397 correct_sequence = False
399 for prefixgroup in parse_prefix_groups(prefix_groups_json, source_):
400 if prefixgroup['sgt'] == int(sgt):
401 for binding in prefixgroup['binding']:
402 if binding['ip-prefix'] == prefix and binding['action'] == action:
403 for peer in binding['peer-sequence']['peer']:
404 if peer['seq'] == int(peer_seq) and peer['node-id'] == node_id:
405 correct_sequence = True
406 for peer_source in binding['sources']['source']:
407 if peer_source == node_id:
409 return found_source and correct_sequence
412 def add_entry_xml(sgt, prefix, ip):
413 """Generate xml for Add Bindings request
415 :param sgt: Source Group Tag
417 :param prefix: Ipv4/6 prefix
419 :param ip: Ipv4 address of node
421 :returns: String containing xml data for request
424 templ = Template('''<input>
425 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
426 <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
427 <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
429 data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip})
433 def add_connection_xml(version, mode, ip, port, node, password_):
434 """Generate xml for Add Connection request
436 :param version: Version of SXP protocol (version1/2/3/4)
437 :type version: string
438 :param mode: Mode of SXP peer (speaker/listener/both)
440 :param ip: Ipv4/6 address of remote peer
442 :param port: Port on with remote peer listens
444 :param node: Ipv4 address of node
446 :param password_: Password type (none/default)
447 :type password_: string
448 :returns: String containing xml data for request
451 templ = Template('''<input>
452 <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
453 <connections xmlns="urn:opendaylight:sxp:controller">
455 <peer-address>$ip</peer-address>
456 <tcp-port>$port</tcp-port>
457 <password>$password_</password>
459 <version>$version</version>
460 <description>Connection to ISR-G2</description>
462 <hold-time-min-acceptable>45</hold-time-min-acceptable>
463 <keep-alive-time>30</keep-alive-time>
464 <reconciliation-time>120</reconciliation-time>
470 data = templ.substitute(
471 {'ip': ip, 'port': port, 'mode': mode, 'version': version, 'node': node, 'password_': password_})
475 def delete_connections_xml(address, port, node):
476 """Generate xml for Delete Connection request
478 :param address: Ipv4/6 address of remote peer
479 :type address: string
480 :param port: Port on with remote peer listens
482 :param node: Ipv4 address of node
484 :returns: String containing xml data for request
487 templ = Template('''<input>
488 <requested-node xmlns="urn:opendaylight:sxp:controller">$node</requested-node>
489 <peer-address xmlns="urn:opendaylight:sxp:controller">$address</peer-address>
490 <tcp-port xmlns="urn:opendaylight:sxp:controller">$port</tcp-port>
492 data = templ.substitute({'address': address, 'port': port, 'node': node})
496 def update_binding_xml(sgt0, prefix0, sgt1, prefix1, ip):
497 """Generate xml for Update Binding request
499 :param sgt0: Original Source Group Tag
501 :param prefix0: Original Ipv4/6 prefix
502 :type prefix0: string
503 :param sgt1: New Source Group Tag
505 :param prefix1: New Ipv4/6 prefix
506 :type prefix1: string
507 :param ip: Ipv4 address of node
509 :returns: String containing xml data for request
512 templ = Template('''<input>
513 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
514 <original-binding xmlns="urn:opendaylight:sxp:controller">
516 <ip-prefix>$prefix0</ip-prefix>
518 <new-binding xmlns="urn:opendaylight:sxp:controller">
520 <ip-prefix>$prefix1</ip-prefix>
523 data = templ.substitute(
524 {'sgt0': sgt0, 'sgt1': sgt1, 'prefix0': prefix0, 'prefix1': prefix1, 'ip': ip})
528 def delete_binding_xml(sgt, prefix, ip):
529 """Generate xml for Delete Binding request
531 :param sgt: Source Group Tag
533 :param prefix: Ipv4/6 prefix
535 :param ip: Ipv4 address of node
537 :returns: String containing xml data for request
540 templ = Template('''<input>
541 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
542 <sgt xmlns="urn:opendaylight:sxp:controller">$sgt</sgt>
543 <ip-prefix xmlns="urn:opendaylight:sxp:controller">$prefix</ip-prefix>
545 data = templ.substitute({'sgt': sgt, 'prefix': prefix, 'ip': ip})
549 def add_peer_group_xml(name, peers, ip):
550 """Generate xml for Add PeerGroups request
552 :param name: Name of PeerGroup
554 :param peers: XML formatted peers that will be added to group
556 :param ip: Ipv4 address of node
558 :returns: String containing xml data for request
561 templ = Template('''<input>
562 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
563 <sxp-peer-group xmlns="urn:opendaylight:sxp:controller">
564 <name xmlns="urn:opendaylight:sxp:controller">$name</name>
565 <sxp-peers xmlns="urn:opendaylight:sxp:controller">$peers</sxp-peers>
568 data = templ.substitute({'name': name, 'peers': peers, 'ip': ip})
572 def delete_peer_group_xml(name, ip):
573 """Generate xml for Delete PeerGroup request
575 :param name: Name of PeerGroup
577 :param ip: Ipv4 address of node
579 :returns: String containing xml data for request
582 templ = Template('''<input>
583 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
584 <peer-group-name xmlns="urn:opendaylight:sxp:controller">$name</peer-group-name>
586 data = templ.substitute({'name': name, 'ip': ip})
590 def get_peer_groups_from_node_xml(ip):
591 """Generate xml for Get PeerGroups request
593 :param ip: Ipv4 address of node
595 :returns: String containing xml data for request
598 templ = Template('''<input>
599 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
601 data = templ.substitute({'ip': ip})
605 def add_filter_xml(group, filter_type, entries, ip):
606 """Generate xml for Add Filter request
608 :param group: Name of group containing filter
610 :param filter_type: Type of filter
611 :type filter_type: string
612 :param entries: XML formatted entries that will be added in filter
613 :type entries: string
614 :param ip: Ipv4 address of node
616 :returns: String containing xml data for request
620 templ = Template('''<input>
621 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
622 <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
623 <sxp-filter xmlns="urn:opendaylight:sxp:controller">
624 <filter-type>$filter_type</filter-type>$entries
627 data = templ.substitute(
628 {'group': group, 'filter_type': filter_type, 'ip': ip, 'entries': entries})
632 def delete_filter_xml(group, filter_type, ip):
633 """Generate xml for Delete Filter request
635 :param group: Name of group containing filter
637 :param filter_type: Type of filter
638 :type filter_type: string
639 :param ip: Ipv4 address of node
641 :returns: String containing xml data for request
644 templ = Template('''<input>
645 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
646 <peer-group-name xmlns="urn:opendaylight:sxp:controller">$group</peer-group-name>
647 <filter-type xmlns="urn:opendaylight:sxp:controller">$filter_type</filter-type>
649 data = templ.substitute(
650 {'group': group, 'filter_type': filter_type, 'ip': ip})
654 def get_connections_from_node_xml(ip):
655 """Generate xml for Get Connections request
657 :param ip: Ipv4 address of node
659 :returns: String containing xml data for request
662 templ = Template('''<input>
663 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
665 data = templ.substitute({'ip': ip})
669 def get_bindings_from_node_xml(ip):
670 """Generate xml for Get Bindings request
672 :param ip: Ipv4 address of node
674 :returns: String containing xml data for request
677 templ = Template('''<input>
678 <requested-node xmlns="urn:opendaylight:sxp:controller">$ip</requested-node>
680 data = templ.substitute({'ip': ip})