Skip to content
Snippets Groups Projects
Commit 77c6a4ee authored by Pablo Armingol's avatar Pablo Armingol
Browse files

Merge branch 'develop' of https://labs.etsi.org/rep/tfs/controller into...

Merge branch 'develop' of https://labs.etsi.org/rep/tfs/controller into feat/tid-add-interface-information-to-network-instance
parents 2e5046cb 5f07ac38
No related branches found
No related tags found
2 merge requests!294Release TeraFlowSDN 4.0,!220Resolve "(TID) Add interface information to network instance"
......@@ -20,7 +20,7 @@ from .Tools import add_value_from_tag
LOGGER = logging.getLogger(__name__)
XPATH_ACL_SET = "//ocacl:acl/ocacl:acl-sets/ocacl:acl-set"
XPATH_A_ACL_ENTRY = ".//ocacl:acl-entries/ocacl:ecl-entry"
XPATH_A_ACL_ENTRY = ".//ocacl:acl-entries/ocacl:acl-entry"
XPATH_A_IPv4 = ".//ocacl:ipv4/ocacl:config"
XPATH_A_TRANSPORT = ".//ocacl:transport/ocacl:config"
XPATH_A_ACTIONS = ".//ocacl:actions/ocacl:config"
......@@ -34,29 +34,31 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
response = []
acl = {}
name = {}
for xml_acl in xml_data.xpath(XPATH_ACL_SET, namespaces=NAMESPACES):
#LOGGER.info('xml_acl = {:s}'.format(str(ET.tostring(xml_acl))))
acl_name = xml_acl.find('ocacl:name', namespaces=NAMESPACES)
if acl_name is None or acl_name.text is None: continue
add_value_from_tag(acl, 'name', acl_name)
add_value_from_tag(name, 'name', acl_name)
acl_type = xml_acl.find('ocacl:type', namespaces=NAMESPACES)
add_value_from_tag(acl, 'type', acl_type)
for xml_acl_entries in xml_acl.xpath(XPATH_A_ACL_ENTRY, namespaces=NAMESPACES):
acl_id = xml_acl_entries.find('ocacl:sequence_id', namespaces=NAMESPACES)
add_value_from_tag(acl, 'sequence_id', acl_id)
acl_id = xml_acl_entries.find('ocacl:sequence-id', namespaces=NAMESPACES)
add_value_from_tag(acl, 'sequence-id', acl_id)
LOGGER.info('xml_acl_id = {:s}'.format(str(ET.tostring(acl_id))))
for xml_ipv4 in xml_acl_entries.xpath(XPATH_A_IPv4, namespaces=NAMESPACES):
ipv4_source = xml_ipv4.find('ocacl:source_address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source_address' , ipv4_source)
ipv4_source = xml_ipv4.find('ocacl:source-address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source-address' , ipv4_source)
ipv4_destination = xml_ipv4.find('ocacl:destination_address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination_address' , ipv4_destination)
ipv4_destination = xml_ipv4.find('ocacl:destination-address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination-address' , ipv4_destination)
ipv4_protocol = xml_ipv4.find('ocacl:protocol', namespaces=NAMESPACES)
add_value_from_tag(acl, 'protocol' , ipv4_protocol)
......@@ -64,30 +66,30 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
ipv4_dscp = xml_ipv4.find('ocacl:dscp', namespaces=NAMESPACES)
add_value_from_tag(acl, 'dscp' , ipv4_dscp)
ipv4_hop_limit = xml_ipv4.find('ocacl:hop_limit', namespaces=NAMESPACES)
add_value_from_tag(acl, 'hop_limit' , ipv4_hop_limit)
ipv4_hop_limit = xml_ipv4.find('ocacl:hop-limit', namespaces=NAMESPACES)
add_value_from_tag(acl, 'hop-limit' , ipv4_hop_limit)
for xml_transport in xml_acl_entries.xpath(XPATH_A_TRANSPORT, namespaces=NAMESPACES):
transport_source = xml_transport.find('ocacl:source_port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source_port' ,transport_source)
transport_source = xml_transport.find('ocacl:source-port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source-port' ,transport_source)
transport_destination = xml_transport.find('ocacl:destination_port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination_port' ,transport_destination)
transport_destination = xml_transport.find('ocacl:destination-port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination-port' ,transport_destination)
transport_tcp_flags = xml_transport.find('ocacl:tcp_flags', namespaces=NAMESPACES)
add_value_from_tag(acl, 'tcp_flags' ,transport_tcp_flags)
transport_tcp_flags = xml_transport.find('ocacl:tcp-flags', namespaces=NAMESPACES)
add_value_from_tag(acl, 'tcp-flags' ,transport_tcp_flags)
for xml_action in xml_acl_entries.xpath(XPATH_A_ACTIONS, namespaces=NAMESPACES):
action = xml_action.find('ocacl:forwarding_action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'forwarding_action' ,action)
action = xml_action.find('ocacl:forwarding-action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'forwarding-action' ,action)
log_action = xml_action.find('ocacl:log_action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'log_action' ,log_action)
log_action = xml_action.find('ocacl:log-action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'log-action' ,log_action)
resource_key = '/acl/acl-set[{:s}][{:s}]/acl-entry[{:s}]'.format(
acl['name'], acl['type'], acl['sequence-id'])
name['name'], acl['type'], acl['sequence-id'])
response.append((resource_key,acl))
for xml_interface in xml_data.xpath(XPATH_INTERFACE, namespaces=NAMESPACES):
......@@ -99,25 +101,25 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
for xml_ingress in xml_interface.xpath(XPATH_I_INGRESS, namespaces=NAMESPACES):
i_name = xml_ingress.find('ocacl:set_name_ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress_set_name' , i_name)
i_name = xml_ingress.find('ocacl:set-name-ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress-set-name' , i_name)
i_type = xml_ingress.find('ocacl:type_ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress_type' , i_type)
i_type = xml_ingress.find('ocacl:type-ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress-type' , i_type)
resource_key = '/acl/interfaces/ingress[{:s}][{:s}]'.format(
acl['name'], acl['type'])
name['name'], acl['type'])
response.append((resource_key,interface))
for xml_egress in xml_interface.xpath(XPATH_I_EGRESS, namespaces=NAMESPACES):
e_name = xml_egress.find('ocacl:set_name_egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress_set_name' , e_name)
e_name = xml_egress.find('ocacl:set-name-egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress-set-name' , e_name)
e_type = xml_egress.find('ocacl:type_egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress_type' , e_type)
e_type = xml_egress.find('ocacl:type-egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress-type' , e_type)
resource_key = '/acl/interfaces/egress[{:s}][{:s}]'.format(
acl['name'], acl['type'])
name['name'], acl['type'])
response.append((resource_key,interface))
return response
......@@ -165,6 +165,16 @@ def inventory(device_uuid: str):
context_client.close()
return render_template('device/inventory.html', device=device_obj)
@device.route('logical/<path:device_uuid>', methods=['GET', 'POST'])
def logical(device_uuid: str):
context_client.connect()
device_obj = get_device(context_client, device_uuid, rw_copy=False)
if device_obj is None:
flash('Device({:s}) not found'.format(str(device_uuid)), 'danger')
device_obj = Device()
context_client.close()
return render_template('device/logical.html', device=device_obj)
@device.get('<path:device_uuid>/delete')
def delete(device_uuid):
try:
......
......@@ -51,6 +51,7 @@
<th scope="col">Config Rules</th>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
......@@ -83,6 +84,14 @@
</svg>
</a>
</td>
<td>
<a href="{{ url_for('device.logical', device_uuid=device.device_id.device_uuid.uuid) }}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
</svg>
</a>
</td>
</tr>
{% endfor %}
{% else %}
......
<!--
Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
{% extends 'base.html' %}
{% block content %}
<style>
ul,
#myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
.caret {
cursor: pointer;
-webkit-user-select: none;
/* Safari 3.1+ */
-moz-user-select: none;
/* Firefox 2+ */
-ms-user-select: none;
/* IE 10+ */
user-select: none;
}
.caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
.caret-down::before {
-ms-transform: rotate(90deg);
/* IE 9 */
-webkit-transform: rotate(90deg);
/* Safari */
transform: rotate(90deg);
}
.nested {
display: none;
}
.active {
display: block;
}
</style>
<h1>Device {{ device.name }} ({{ device.device_id.device_uuid.uuid }})</h1>
<div class="row mb-3">
<div class="col-sm-3">
<button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('device.home') }}'">
<i class="bi bi-box-arrow-in-left"></i>
Back to device list
</button>
</div>
</div>
<br>
<div class="row mb-3">
<div>
<ul id="myUL">
<li><span class="caret">ACL</span>
<ul class="nested">
{% set acl_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/acl/' in config.custom.resource_key %}
{% if 'acl-set' in config.custom.resource_key %}
{% set acl_name = config.custom.resource_key.split('acl-set[')[1].split('][')[0] %}
{% else %}
{% set acl_name = config.custom.resource_key.split('ress[')[1].split('][')[0] %}
{% endif %}
{% if acl_name|length == 0 %}
{% set acl_name = 'Undefined' %}
{% endif %}
{% if acl_name not in acl_names %}
{% set _ = acl_names.append(acl_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for acl_name in acl_names %}
<li><span class="caret">{{ acl_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/acl/' in config.custom.resource_key and acl_name in config.custom.resource_key.split('][')[0] %}
{% if 'acl-entry' in config.custom.resource_key %}
{% set rule_number = config.custom.resource_key.split('acl-entry[')[1].split(']')[0] %}
<li><span><b>Rule {{ rule_number }}:</b> {{ config.custom.resource_value }}</span></li>
{% else %}
<li><span><b>Interface:</b> {{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
</ul>
<ul id="myUL">
<li><span class="caret">Routing Policy</span>
<ul class="nested">
{% set pol_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/routing_policy/' in config.custom.resource_key %}
{% if 'policy_definition' in config.custom.resource_key %}
{% set pol_name = config.custom.resource_key.split('policy_definition[')[1].split(']')[0] %}
{% endif %}
{% if pol_name|length == 0 %}
{% set pol_name = 'Undefined' %}
{% endif %}
{% if pol_name not in pol_names %}
{% set _ = pol_names.append(pol_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for pol_name in pol_names %}
<li><span class="caret">{{ pol_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/routing_policy/' in config.custom.resource_key and pol_name in config.custom.resource_key.split('[')[1].split(']')[0] %}
{% if 'policy_definition' not in config.custom.resource_key %}
<li><span>{{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
</ul>
<ul id="myUL">
<li><span class="caret">VRFs</span>
<ul class="nested">
<li><span class="caret">VRF default</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in 'default' %}
{% if ']/' in config.custom.resource_key%}
{% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %}
<li><span><b> {{ aux.replace('_', ' ').title() }}:</b> {{ config.custom.resource_value }}</span></li>
{% else %}
<li><span><b> Network Instance:</b> {{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
<li><span class="caret">L3VPN</span>
<ul class="nested">
{% set vpn_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/network_instance' in config.custom.resource_key %}
{% if 'L3VRF' in config.custom.resource_value %}
{% set vpn_name = config.custom.resource_key.split('network_instance[')[1].split(']')[0] %}
{% if vpn_name not in vpn_names %}
{% set _ = vpn_names.append(vpn_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for vpn_name in vpn_names %}
<li><span class="caret">{{ vpn_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in vpn_name %}
{% if ']/' in config.custom.resource_key%}
{% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %}
<li><span><b> {{ aux.replace('_', ' ').title() }}:</b> {{ config.custom.resource_value }}</span></li>
{% else %}
<li><span><b> Network Instance:</b> {{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
<li><span class="caret">L2VPN</span>
<ul class="nested">
{% set vpn_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/network_instance' in config.custom.resource_key %}
{% if 'L2VSI' in config.custom.resource_value %}
{% set vpn_name = config.custom.resource_key.split('network_instance[')[1].split(']')[0] %}
{% if vpn_name not in vpn_names %}
{% set _ = vpn_names.append(vpn_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for vpn_name in vpn_names %}
<li><span class="caret">{{ vpn_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in vpn_name %}
{% if ']/' in config.custom.resource_key%}
{% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %}
<li><span><b> {{ aux.replace('_', ' ').title() }}:</b> {{ config.custom.resource_value }}</span></li>
{% else %}
<li><span><b> Network Instance:</b> {{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
</ul>
</li>
</ul>
<ul id="myUL">
<li><span class="caret">Interfaces</span>
<ul class="nested">
<li><span class="caret">Logical Interfaces</span>
<ul class="nested">
{% set interface_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface[' in config.custom.resource_key %}
{% if 'ethernetCsmacd' in config.custom.resource_value %}
{% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %}
<li><span>{{ interface_name}}:</span> {{config.custom.resource_value}}</li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
<li><span class="caret">Loopback</span>
<ul class="nested">
{% set interface_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface[' in config.custom.resource_key %}
{% if 'softwareLoopback' in config.custom.resource_value %}
{% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %}
{% if interface_name not in interface_names %}
{% set _ = interface_names.append(interface_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for interface_name in interface_names %}
<li><span class="caret">{{ interface_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %}
{% if 'subinterface' in config.custom.resource_key %}
{% set subinterface_name = config.custom.resource_key.split('subinterface[')[1].split(']')[0] %}
<li><span><b>Subinterface {{subinterface_name}}: </b>{{ config.custom.resource_value }}</span></li>
{% else %}
<li><span>{{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
<li><span class="caret">Interfaces L3</span>
<ul class="nested">
{% set interface_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface[' in config.custom.resource_key %}
{% if 'l3ipvlan' in config.custom.resource_value %}
{% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %}
{% if interface_name not in interface_names %}
{% set _ = interface_names.append(interface_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for interface_name in interface_names %}
<li><span class="caret">{{ interface_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface' in config.custom.resource_key and '/subinterface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %}
<li><span>{{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
<li><span class="caret">Interfaces L2</span>
<ul class="nested">
{% set interface_names = [] %}
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if '/interface[' in config.custom.resource_key %}
{% if 'l2vlan' in config.custom.resource_value or 'mplsTunnel' in config.custom.resource_value %}
{% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %}
{% if interface_name not in interface_names %}
{% set _ = interface_names.append(interface_name) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% for interface_name in interface_names %}
<li><span class="caret">{{ interface_name }}</span>
<ul class="nested">
{% for config in device.device_config.config_rules %}
{% if config.WhichOneof('config_rule') == 'custom' %}
{% if 'subinterface' in config.custom.resource_key %}
{% if '/interface' in config.custom.resource_key and '/subinterface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %}
<li><span>{{ config.custom.resource_value }}</span></li>
{% endif %}
{% else %}
{% if '/interface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %}
<li><span>{{ config.custom.resource_value }}</span></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
</ul>
</li>
</ul>
<script>
var toggler = document.getElementsByClassName("caret");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
</script>
</div>
</div>
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment