+ <bindings-range xmlns="urn:opendaylight:sxp:controller">$range</bindings-range>
+ $domain
+</input>"""
+ )
+ data = templ.substitute(
+ {"ip": ip, "range": binding_range, "domain": get_domain_name(domain_name)}
+ )
+ return data
+
+
+def add_node_xml(
+ node_id,
+ port,
+ password,
+ version,
+ node_ip=None,
+ expansion=0,
+ bindings_timeout=0,
+ keystores=None,
+ retry_open_timer=1,
+):
+ """Generate xml for Add Node request
+
+ :param node_id: Ipv4 address formatted node id
+ :type node_id: str
+ :param node_ip: Ipv4 address of node
+ :type node_ip: strl
+ :param port: Node port number
+ :type port: int
+ :param password: TCP-MD5 password
+ :type password: str
+ :param version: Sxp device version
+ :type version: str
+ :param expansion: Bindings expansion
+ :type expansion: int
+ :param bindings_timeout: Specifies DHD and Reconciliation timers
+ :type bindings_timeout: int
+ :param keystores: SSL keystore and truststore specification
+ :type keystores: dict
+ :returns: String containing xml data for request
+
+ """
+ tls = ""
+ if keystores:
+ tls = Template(
+ """
+ <tls>
+ <keystore>
+ <location>$keystore</location>
+ <type>JKS</type>
+ <path-type>PATH</path-type>
+ <password>$passwd</password>
+ </keystore>
+ <truststore>
+ <location>$truststore</location>
+ <type>JKS</type>
+ <path-type>PATH</path-type>
+ <password>$passwd</password>
+ </truststore>
+ <certificate-password>$passwd</certificate-password>
+ </tls>
+ """
+ ).substitute(
+ {
+ "keystore": keystores["keystore"],
+ "truststore": keystores["truststore"],
+ "passwd": keystores["password"],
+ }
+ )
+
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <timers>
+ <retry-open-time>$retry_open_timer</retry-open-time>
+ <hold-time-min-acceptable>120</hold-time-min-acceptable>
+ <delete-hold-down-time>$timeout</delete-hold-down-time>
+ <hold-time-min>90</hold-time-min>
+ <reconciliation-time>$timeout</reconciliation-time>
+ <hold-time>90</hold-time>
+ <hold-time-max>180</hold-time-max>
+ <keep-alive-time>30</keep-alive-time>
+ </timers>
+ <mapping-expanded>$expansion</mapping-expanded>
+ <security>
+ $tls
+ <password>$password</password>
+ </security>
+ <tcp-port>$port</tcp-port>
+ <version>$version</version>
+ <description>ODL SXP Controller</description>
+ <source-ip>$ip</source-ip>
+</input>"""
+ )
+ data = templ.substitute(
+ {
+ "ip": node_ip or node_id,
+ "id": node_id,
+ "port": port,
+ "password": password,
+ "version": version,
+ "expansion": expansion,
+ "timeout": bindings_timeout,
+ "tls": tls,
+ "retry_open_timer": retry_open_timer,
+ }
+ )
+ return data
+
+
+def delete_node_xml(node_id):
+ """Generate xml for Delete node request
+
+ :param node_id: Ipv4 address formatted node id
+ :type node_id: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+</input>"""
+ )
+ data = templ.substitute({"id": node_id})
+ return data
+
+
+def add_domain_xml_fluorine(node_id, name, sgt, prefixes, origin):
+ """Generate xml for Add Domain request (Fluorine version: bindings with origin)
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param name: Name of Domain
+ :type name: str
+ :param sgt: Security group
+ :type sgt: int
+ :param prefixes: List of ip-prefixes
+ :type prefixes: str
+ :param origin: Origin of added bindings
+ :type origin: str
+ :returns: String containing xml data for request
+
+ """
+ master_database = ""
+ if prefixes != "None":
+ xml_prefixes = ""
+ for prefix in prefixes.split(","):
+ xml_prefixes += "\n" + "<ip-prefix>" + prefix + "</ip-prefix>"
+ if xml_prefixes:
+ master_database += """<master-database>
+ <binding>
+ <sgt>$sgt</sgt>
+ $xml_prefixes
+ </binding>
+ </master-database>"""
+ master_database = Template(master_database).substitute(
+ ({"sgt": sgt, "xml_prefixes": xml_prefixes})
+ )
+
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <domain-name>$name</domain-name>
+ <origin>$origin</origin>
+ $master_database
+</input>"""
+ )
+
+ data = templ.substitute(
+ {
+ "name": name,
+ "id": node_id,
+ "origin": origin,
+ "master_database": master_database,
+ }
+ )
+ return data
+
+
+def add_domain_xml_oxygen(node_id, name, sgt, prefixes):
+ """Generate xml for Add Domain request (Oxygen version: bindings without origin)
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param name: Name of Domain
+ :type name: str
+ :param sgt: Security group
+ :type sgt: int
+ :param prefixes: List of ip-prefixes
+ :type prefixes: str
+ :returns: String containing xml data for request
+
+ """
+ master_database = ""
+ if prefixes != "None":
+ xml_prefixes = ""
+ for prefix in prefixes.split(","):
+ xml_prefixes += "\n" + "<ip-prefix>" + prefix + "</ip-prefix>"
+ if xml_prefixes:
+ master_database += """<master-database>
+ <binding>
+ <sgt>$sgt</sgt>
+ $xml_prefixes
+ </binding>
+ </master-database>"""
+ master_database = Template(master_database).substitute(
+ ({"sgt": sgt, "xml_prefixes": xml_prefixes})
+ )
+
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <domain-name>$name</domain-name>
+ $master_database
+</input>"""
+ )
+
+ data = templ.substitute(
+ {"name": name, "id": node_id, "master_database": master_database}
+ )
+ return data
+
+
+def delete_domain_xml(node_id, name):
+ """Generate xml for Remove Domain request
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param name: Name of Domain
+ :type name: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$node_id</node-id>
+ <domain-name>$name</domain-name>
+</input>"""
+ )
+
+ data = templ.substitute({"node_id": node_id, "name": name})
+ return data
+
+
+def get_domain_name(domain_name):
+ """Generate xml for Get Bindings request
+
+ :param domain_name: Name of Domain
+ :type domain_name: str
+ :returns: String containing xml data for request
+
+ """
+ if domain_name == "global":
+ return ""
+ else:
+ return (
+ '<domain-name xmlns="urn:opendaylight:sxp:controller">'
+ + domain_name
+ + "</domain-name>"
+ )
+
+
+def add_bindings_xml_fluorine(node_id, domain, sgt, prefixes, origin):
+ """Generate xml for Add Bindings request (Fluorine version with origin type)
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param domain: Name of Domain
+ :type domain: str
+ :param sgt: Security group
+ :type sgt: int
+ :param prefixes: List of ip-prefixes
+ :type prefixes: str
+ :param origin: Origin of added bindings
+ :type origin: str
+ :returns: String containing xml data for request
+
+ """
+ xml_prefixes = ""
+ for prefix in prefixes.split(","):
+ xml_prefixes += "\n" + "<ip-prefix>" + prefix + "</ip-prefix>"
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <domain-name>$name</domain-name>
+ <origin>$origin</origin>
+ <master-database>
+ <binding>
+ <sgt>$sgt</sgt>
+ $xml_prefixes
+ </binding>
+ </master-database>
+</input>"""
+ )
+ data = templ.substitute(
+ {
+ "name": domain,
+ "id": node_id,
+ "sgt": sgt,
+ "xml_prefixes": xml_prefixes,
+ "origin": origin,
+ }
+ )
+ return data
+
+
+def add_bindings_xml_oxygen(node_id, domain, sgt, prefixes):
+ """Generate xml for Add Bindings request (Oxygen version without origin type)
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param domain: Name of Domain
+ :type domain: str
+ :param sgt: Security group
+ :type sgt: int
+ :param prefixes: List of ip-prefixes
+ :type prefixes: str
+ :returns: String containing xml data for request
+
+ """
+ xml_prefixes = ""
+ for prefix in prefixes.split(","):
+ xml_prefixes += "\n" + "<ip-prefix>" + prefix + "</ip-prefix>"
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <domain-name>$name</domain-name>
+ <binding>
+ <sgt>$sgt</sgt>
+ $xml_prefixes
+ </binding>
+</input>"""
+ )
+ data = templ.substitute(
+ {"name": domain, "id": node_id, "sgt": sgt, "xml_prefixes": xml_prefixes}
+ )
+ return data
+
+
+def delete_bindings_xml(node_id, domain, sgt, prefixes):
+ """Generate xml for Remove Bindings request
+
+ :param node_id: Id of node
+ :type node_id: str
+ :param domain: Name of Domain
+ :type domain: str
+ :param sgt: Security group
+ :type sgt: int
+ :param prefixes: Comma separated list of ip-prefixes
+ :type prefixes: str
+ :returns: String containing xml data for request
+
+ """
+ xml_prefixes = ""
+ for prefix in prefixes.split(","):
+ xml_prefixes += "\n" + "<ip-prefix>" + prefix + "</ip-prefix>"
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:controller">
+ <node-id>$id</node-id>
+ <domain-name>$name</domain-name>
+ <binding>
+ <sgt>$sgt</sgt>
+ $xml_prefixes
+ </binding>
+</input>"""
+ )
+ data = templ.substitute(
+ {"name": domain, "id": node_id, "sgt": sgt, "xml_prefixes": xml_prefixes}
+ )
+ return data
+
+
+def prefix_range(start, end):
+ """Generate and concatenate ip-prefixes
+
+ :param start: Start index
+ :type start: str
+ :param end: End index
+ :type end: str
+ :returns: String containing concatenated ip-prefixes
+
+ """
+ start = int(start)
+ end = int(end)
+ index = 0
+ prefixes = ""
+ while index < end:
+ prefixes += get_ip_from_number(index + start) + "/32"
+ index += 1
+ if index < end:
+ prefixes += ","
+ return prefixes
+
+
+def route_definition_xml(virtual_ip, net_mask, interface):
+ """Generate xml for Add Bindings request
+
+ :param interface: Network interface name
+ :type interface: str
+ :param net_mask: NetMask of virtual ip
+ :type net_mask: str
+ :param virtual_ip: Virtual ip
+ :type virtual_ip: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """
+ <routing-definition>
+ <ip-address>$vip</ip-address>
+ <interface>$interface</interface>
+ <netmask>$mask</netmask>
+ </routing-definition>
+ """
+ )
+ data = templ.substitute(
+ {"mask": net_mask, "vip": virtual_ip, "interface": interface}
+ )
+ return data
+
+
+def route_definitions_xml(routes, old_routes=None):
+ """Generate xml for Add Bindings request
+
+ :param routes: XML formatted data containing RouteDefinitions
+ :type routes: str
+ :param old_routes: Routes add to request that needs to persist
+ :type old_routes: str
+ :returns: String containing xml data for request
+
+ """
+ if old_routes and "</sxp-cluster-route>" in old_routes:
+ templ = Template(
+ old_routes.replace("</sxp-cluster-route>", "$routes</sxp-cluster-route>")
+ )
+ else:
+ templ = Template(
+ """<sxp-cluster-route xmlns="urn:opendaylight:sxp:cluster:route">
+ $routes
+</sxp-cluster-route>
+ """
+ )
+ data = templ.substitute({"routes": routes})
+ return data
+
+
+def add_binding_origin_xml(origin, priority):
+ """Generate xml for Add Binding Origin request
+
+ :param origin: Origin type
+ :type origin: str
+ :param priority: Origin priority
+ :type priority: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:config:controller">
+ <origin>$origin</origin>
+ <priority>$priority</priority>
+</input>"""
+ )
+ data = templ.substitute({"origin": origin, "priority": priority})
+ return data
+
+
+def update_binding_origin_xml(origin, priority):
+ """Generate xml for Update Binding Origin request
+
+ :param origin: Origin type
+ :type origin: str
+ :param priority: Origin priority
+ :type priority: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:config:controller">
+ <origin>$origin</origin>
+ <priority>$priority</priority>
+</input>"""
+ )
+ data = templ.substitute({"origin": origin, "priority": priority})
+ return data
+
+
+def delete_binding_origin_xml(origin):
+ """Generate xml for Delete Binding Origin request
+
+ :param origin: Origin type
+ :type origin: str
+ :returns: String containing xml data for request
+
+ """
+ templ = Template(
+ """<input xmlns="urn:opendaylight:sxp:config:controller">
+ <origin>$origin</origin>
+</input>"""
+ )
+ data = templ.substitute({"origin": origin})