From 33fbfebd380879470a342da4061e3e8f6820addb Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Fri, 8 Nov 2024 11:26:56 +0000 Subject: [PATCH 01/17] Service component - L3NM gNMI OpenConfig: - StaticRouteGenerator: Fixed link endpoints compuotation - ConfigRuleComposer: Reverted to default network instance as cEOS does not work properly with VRFs - ConfigRuleComposer: Added interface deactivation - Improved logging - Updated unitary tests --- .../ConfigRuleComposer.py | 32 +++++++++++++---- .../L3NMGnmiOpenConfigServiceHandler.py | 9 ++--- .../StaticRouteGenerator.py | 12 +++++-- .../MockServiceHandler.py | 36 +++++++++++++++++-- .../test_unitary_sns4sns.py | 20 +++++------ 5 files changed, 83 insertions(+), 26 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py index c8227975f..54101d041 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py @@ -21,7 +21,8 @@ from service.service.service_handler_api.AnyTreeTools import TreeNode LOGGER = logging.getLogger(__name__) -NETWORK_INSTANCE = 'teraflowsdn' +#NETWORK_INSTANCE = 'teraflowsdn' +NETWORK_INSTANCE = 'default' RE_IF = re.compile(r'^\/interface\[([^\]]+)\]$') RE_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') @@ -109,11 +110,18 @@ class EndpointComposer: if self.ipv4_prefix_len is None: return [] json_config_rule = json_config_rule_delete if delete else json_config_rule_set config_rules = [ - json_config_rule(*_network_instance_interface( - network_instance_name, self.objekt.name, self.sub_interface_index - )), + #json_config_rule(*_network_instance_interface( + # network_instance_name, self.objekt.name, self.sub_interface_index + #)), ] - if not delete: + if delete: + config_rules.extend([ + json_config_rule(*_interface( + self.objekt.name, index=self.sub_interface_index, address_ip=None, + address_prefix=None, enabled=False + )), + ]) + else: config_rules.extend([ json_config_rule(*_interface( self.objekt.name, index=self.sub_interface_index, address_ip=self.ipv4_address, @@ -128,6 +136,12 @@ class EndpointComposer: 'address_ip' : self.ipv4_address, 'address_prefix': self.ipv4_prefix_len, } + + def __str__(self): + data = {'uuid': self.uuid} + if self.objekt is not None: data['name'] = self.objekt.name + data.update(self.dump()) + return json.dumps(data) class DeviceComposer: def __init__(self, device_uuid : str) -> None: @@ -212,7 +226,7 @@ class DeviceComposer: json_config_rule = json_config_rule_delete if delete else json_config_rule_set config_rules = [ - json_config_rule(*_network_instance(network_instance_name, 'L3VRF')) + #json_config_rule(*_network_instance(network_instance_name, 'L3VRF')) ] for endpoint in self.endpoints.values(): config_rules.extend(endpoint.get_config_rules(network_instance_name, delete=delete)) @@ -240,6 +254,12 @@ class DeviceComposer: 'static_routes' : self.static_routes, } + def __str__(self): + data = {'uuid': self.uuid} + if self.objekt is not None: data['name'] = self.objekt.name + data.update(self.dump()) + return json.dumps(data) + class ConfigRuleComposer: def __init__(self) -> None: self.objekt : Optional[Service] = None diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/L3NMGnmiOpenConfigServiceHandler.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/L3NMGnmiOpenConfigServiceHandler.py index 8aa3781a4..4099675fa 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/L3NMGnmiOpenConfigServiceHandler.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/L3NMGnmiOpenConfigServiceHandler.py @@ -65,8 +65,9 @@ class L3NMGnmiOpenConfigServiceHandler(_ServiceHandler): self.__endpoint_map[(device_uuid, endpoint_uuid)] = (device_obj.name, endpoint_obj.name) + LOGGER.debug('[pre] config_rule_composer = {:s}'.format(json.dumps(self.__config_rule_composer.dump()))) self.__static_route_generator.compose(endpoints) - LOGGER.debug('config_rule_composer = {:s}'.format(json.dumps(self.__config_rule_composer.dump()))) + LOGGER.debug('[post] config_rule_composer = {:s}'.format(json.dumps(self.__config_rule_composer.dump()))) def _do_configurations( self, config_rules_per_device : Dict[str, List[Dict]], endpoints : List[Tuple[str, str, Optional[str]]], @@ -110,8 +111,8 @@ class L3NMGnmiOpenConfigServiceHandler(_ServiceHandler): #network_instance_name = service_uuid.split('-')[0] #config_rules_per_device = self.__config_rule_composer.get_config_rules(network_instance_name, delete=False) config_rules_per_device = self.__config_rule_composer.get_config_rules(delete=False) - LOGGER.debug('config_rules_per_device={:s}'.format(str(config_rules_per_device))) - results = self._do_configurations(config_rules_per_device, endpoints) + LOGGER.debug('config_rules_per_device={:s}'.format(json.dumps(config_rules_per_device))) + results = self._do_configurations(config_rules_per_device, endpoints, delete=False) LOGGER.debug('results={:s}'.format(str(results))) return results @@ -128,7 +129,7 @@ class L3NMGnmiOpenConfigServiceHandler(_ServiceHandler): #network_instance_name = service_uuid.split('-')[0] #config_rules_per_device = self.__config_rule_composer.get_config_rules(network_instance_name, delete=True) config_rules_per_device = self.__config_rule_composer.get_config_rules(delete=True) - LOGGER.debug('config_rules_per_device={:s}'.format(str(config_rules_per_device))) + LOGGER.debug('config_rules_per_device={:s}'.format(json.dumps(config_rules_per_device))) results = self._do_configurations(config_rules_per_device, endpoints, delete=True) LOGGER.debug('results={:s}'.format(str(results))) return results diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py index 201f22e63..c52321473 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py @@ -63,12 +63,20 @@ class StaticRouteGenerator: def _compute_link_endpoints( self, connection_hop_list : List[Tuple[str, str, Optional[str]]] ) -> List[Tuple[Tuple[str, str, Optional[str]], Tuple[str, str, Optional[str]]]]: + # In some cases connection_hop_list might contain repeated endpoints, remove them here. + added_connection_hops = set() + filtered_connection_hop_list = list() + for connection_hop in connection_hop_list: + if connection_hop in added_connection_hops: continue + filtered_connection_hop_list.append(connection_hop) + added_connection_hops.add(connection_hop) + connection_hop_list = filtered_connection_hop_list + num_connection_hops = len(connection_hop_list) if num_connection_hops % 2 != 0: raise Exception('Number of connection hops must be even') if num_connection_hops < 4: raise Exception('Number of connection hops must be >= 4') - # Skip service endpoints (first and last) - it_connection_hops = iter(connection_hop_list[1:-1]) + it_connection_hops = iter(connection_hop_list) return list(zip(it_connection_hops, it_connection_hops)) def _compute_link_addresses( diff --git a/src/service/tests/test_l3nm_gnmi_static_rule_gen/MockServiceHandler.py b/src/service/tests/test_l3nm_gnmi_static_rule_gen/MockServiceHandler.py index 22da218ab..a480f6b31 100644 --- a/src/service/tests/test_l3nm_gnmi_static_rule_gen/MockServiceHandler.py +++ b/src/service/tests/test_l3nm_gnmi_static_rule_gen/MockServiceHandler.py @@ -19,6 +19,7 @@ from common.tools.object_factory.Connection import json_connection_id from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_type from service.service.service_handler_api._ServiceHandler import _ServiceHandler +#from service.service.service_handler_api.AnyTreeTools import TreeNode from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.service_handler_api.Tools import get_device_endpoint_uuids, get_endpoint_matching from .MockTaskExecutor import MockTaskExecutor @@ -45,6 +46,10 @@ class MockServiceHandler(_ServiceHandler): service_settings = self.__settings_handler.get_service_settings() self.__config_rule_composer.configure(self.__service, service_settings) + #prev_endpoint_obj = None + #prev_endpoint = None + #settings_for_next = None + #for i,endpoint in enumerate(endpoints): for endpoint in endpoints: device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint) @@ -60,8 +65,35 @@ class MockServiceHandler(_ServiceHandler): _endpoint = _device.get_endpoint(endpoint_obj.name) _endpoint.configure(endpoint_obj, endpoint_settings) + #if settings_for_next is not None: + # _endpoint.configure(endpoint_obj, settings_for_next) + # settings_for_next = None + + #if endpoint_settings is not None and 'neighbor_address' in endpoint_settings.value: + # _neighbor_settings = {'address_ip': endpoint_settings.value['neighbor_address']} + # + # if 'address_prefix' in endpoint_settings.value: + # _neighbor_settings['address_prefix'] = endpoint_settings.value['address_prefix'] + # elif 'prefix_length' in endpoint_settings.value: + # _neighbor_settings['address_prefix'] = endpoint_settings.value['prefix_length'] + # else: + # MSG = 'IP Address Prefix not found. Tried: address_prefix and prefix_length. endpoint_settings.value={:s}' + # raise Exception(MSG.format(str(endpoint_settings.value))) + # + # neighbor_settings = TreeNode('.') + # neighbor_settings.value = _neighbor_settings + # if i % 2 == 0: + # # configure in next endpoint + # settings_for_next = neighbor_settings + # else: + # # configure in previous endpoint + # prev_endpoint.configure(prev_endpoint_obj, neighbor_settings) + self.__endpoint_map[(device_uuid, endpoint_uuid)] = (device_obj.name, endpoint_obj.name) + #prev_endpoint = _endpoint + #prev_endpoint_obj = endpoint_obj + self.__static_route_generator.compose(endpoints) LOGGER.debug('config_rule_composer = {:s}'.format(json.dumps(self.__config_rule_composer.dump()))) @@ -106,7 +138,7 @@ class MockServiceHandler(_ServiceHandler): #network_instance_name = service_uuid.split('-')[0] #config_rules_per_device = self.__config_rule_composer.get_config_rules(network_instance_name, delete=False) config_rules_per_device = self.__config_rule_composer.get_config_rules(delete=False) - LOGGER.debug('config_rules_per_device={:s}'.format(str(config_rules_per_device))) + LOGGER.debug('config_rules_per_device={:s}'.format(json.dumps(config_rules_per_device))) results = self._do_configurations(config_rules_per_device, endpoints) LOGGER.debug('results={:s}'.format(str(results))) return results @@ -123,7 +155,7 @@ class MockServiceHandler(_ServiceHandler): #network_instance_name = service_uuid.split('-')[0] #config_rules_per_device = self.__config_rule_composer.get_config_rules(network_instance_name, delete=True) config_rules_per_device = self.__config_rule_composer.get_config_rules(delete=True) - LOGGER.debug('config_rules_per_device={:s}'.format(str(config_rules_per_device))) + LOGGER.debug('config_rules_per_device={:s}'.format(json.dumps(config_rules_per_device))) results = self._do_configurations(config_rules_per_device, endpoints, delete=True) LOGGER.debug('results={:s}'.format(str(results))) return results diff --git a/src/service/tests/test_l3nm_gnmi_static_rule_gen/test_unitary_sns4sns.py b/src/service/tests/test_l3nm_gnmi_static_rule_gen/test_unitary_sns4sns.py index 0177500e2..64035f1bb 100644 --- a/src/service/tests/test_l3nm_gnmi_static_rule_gen/test_unitary_sns4sns.py +++ b/src/service/tests/test_l3nm_gnmi_static_rule_gen/test_unitary_sns4sns.py @@ -37,27 +37,23 @@ SERVICE = Service(**json_service_l3nm_planned( json_endpoint_id(json_device_id('edge-net'), 'eth1'), ], config_rules=[ + json_config_rule_set('/settings', {'address_families': ['IPV4'], 'mtu': 1500}), + json_config_rule_set('/static_routing', {}), + json_config_rule_set('/device[core-net]/endpoint[eth1]/settings', { - 'address_ip': '10.10.10.0', 'address_prefix': 24, 'index': 0 - }), - json_config_rule_set('/device[r1]/endpoint[eth10]/settings', { - 'address_ip': '10.10.10.229', 'address_prefix': 24, 'index': 0 - }), - json_config_rule_set('/device[r2]/endpoint[eth10]/settings', { - 'address_ip': '10.158.72.229', 'address_prefix': 24, 'index': 0 + 'address_ip': '10.10.10.0', 'neighbor_address': '10.10.10.229', 'address_prefix': 24, 'index': 0 }), json_config_rule_set('/device[edge-net]/endpoint[eth1]/settings', { - 'address_ip': '10.158.72.0', 'address_prefix': 24, 'index': 0 + 'address_ip': '10.158.72.0', 'neighbor_address': '10.158.72.229', 'address_prefix': 24, 'index': 0 }), ] )) CONNECTION_ENDPOINTS : List[Tuple[str, str, Optional[str]]] = [ #('core-net', 'int', None), - ('core-net', 'eth1', None), - ('r1', 'eth10', None), ('r1', 'eth2', None), - ('r2', 'eth1', None), ('r2', 'eth10', None), - ('edge-net', 'eth1', None), + ('core-net', 'eth1', None), ('r1', 'eth10', None), + ('r1', 'eth2', None), ('r2', 'eth1', None), + ('r2', 'eth10', None), ('edge-net', 'eth1', None), #('edge-net', 'int', None), ] -- GitLab From 85cd754435f83449488c7b0d798b5303b73b4d46 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Fri, 8 Nov 2024 11:27:15 +0000 Subject: [PATCH 02/17] Updated sns4sns test IETF L3VPN request --- src/tests/sns4sns24/02-ietf-l3vpn-nbi.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json b/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json index 31d7e0a6d..0d34cfe9a 100644 --- a/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json +++ b/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json @@ -11,7 +11,7 @@ "site-network-accesses": { "site-network-access": [ { - "site-network-access-id": "int", + "site-network-access-id": "eth1", "site-network-access-type": "ietf-l3vpn-svc:multipoint", "device-reference": "core-net", "vpn-attachment": {"vpn-id": "ietf-l3vpn-edge-core", "site-role": "ietf-l3vpn-svc:spoke-role"}, @@ -48,7 +48,7 @@ "site-network-accesses": { "site-network-access": [ { - "site-network-access-id": "int", + "site-network-access-id": "eth1", "site-network-access-type": "ietf-l3vpn-svc:multipoint", "device-reference": "edge-net", "vpn-attachment": {"vpn-id": "ietf-l3vpn-edge-core", "site-role": "ietf-l3vpn-svc:hub-role"}, -- GitLab From 06a6a510ba288e581e0d520b8140c0cc3842c793 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Fri, 8 Nov 2024 11:27:58 +0000 Subject: [PATCH 03/17] Device - gNMI OpenConfig driver: - Disabled MTUs, some devices crash when setting it --- .../service/drivers/gnmi_openconfig/handlers/Interface.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py index fda3ab71b..36a024bd1 100644 --- a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py +++ b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py @@ -41,14 +41,14 @@ class InterfaceHandler(_Handler): vlan_id = get_int (resource_value, 'vlan_id', ) # 127 address_ip = get_str (resource_value, 'address_ip' ) # 172.16.0.1 address_prefix = get_int (resource_value, 'address_prefix') # 24 - mtu = get_int (resource_value, 'mtu' ) # 1500 + #mtu = get_int (resource_value, 'mtu', 1450) # 1500 yang_ifs : libyang.DContainer = yang_handler.get_data_path('/openconfig-interfaces:interfaces') yang_if_path = 'interface[name="{:s}"]'.format(if_name) yang_if : libyang.DContainer = yang_ifs.create_path(yang_if_path) yang_if.create_path('config/name', if_name ) if enabled is not None: yang_if.create_path('config/enabled', enabled) - if mtu is not None: yang_if.create_path('config/mtu', mtu) + #if mtu is not None: yang_if.create_path('config/mtu', mtu) yang_sifs : libyang.DContainer = yang_if.create_path('subinterfaces') yang_sif_path = 'subinterface[index="{:d}"]'.format(sif_index) @@ -69,7 +69,7 @@ class InterfaceHandler(_Handler): yang_ipv4_addr : libyang.DContainer = yang_ipv4_addrs.create_path(yang_ipv4_addr_path) yang_ipv4_addr.create_path('config/ip', address_ip) yang_ipv4_addr.create_path('config/prefix-length', address_prefix) - if mtu is not None: yang_ipv4_addr.create_path('config/mtu', mtu) + #if mtu is not None: yang_ipv4_addr.create_path('config/mtu', mtu) str_path = '/interfaces/interface[name={:s}]'.format(if_name) str_data = yang_if.print_mem('json') -- GitLab From f0c8f6f99156370e745721a7ee6129969305c03c Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Fri, 8 Nov 2024 11:54:34 +0000 Subject: [PATCH 04/17] Added Hackfest 5 material --- hackfest5/.gitignore | 4 + hackfest5/README.md | 109 +++++++++++++ hackfest5/clab-cli-dc1.sh | 16 ++ hackfest5/clab-cli-dc2.sh | 16 ++ hackfest5/clab-cli-r1.sh | 16 ++ hackfest5/clab-cli-r2.sh | 16 ++ hackfest5/clab-deploy.sh | 17 ++ hackfest5/clab-destroy.sh | 18 +++ hackfest5/clab-graph.sh | 17 ++ hackfest5/clab-inspect.sh | 17 ++ hackfest5/clab/hackfest5.clab.yml | 65 ++++++++ hackfest5/data/ietf-l3vpn-service.json | 83 ++++++++++ hackfest5/data/tfs-service.json | 26 ++++ hackfest5/data/tfs-topology.json | 100 ++++++++++++ hackfest5/deploy_specs.sh | 208 +++++++++++++++++++++++++ hackfest5/images/arista/.gitignore | 3 + hackfest5/images/arista/.gitkeep | 0 hackfest5/redeploy-tfs.sh | 17 ++ 18 files changed, 748 insertions(+) create mode 100644 hackfest5/.gitignore create mode 100644 hackfest5/README.md create mode 100755 hackfest5/clab-cli-dc1.sh create mode 100755 hackfest5/clab-cli-dc2.sh create mode 100755 hackfest5/clab-cli-r1.sh create mode 100755 hackfest5/clab-cli-r2.sh create mode 100755 hackfest5/clab-deploy.sh create mode 100755 hackfest5/clab-destroy.sh create mode 100755 hackfest5/clab-graph.sh create mode 100755 hackfest5/clab-inspect.sh create mode 100644 hackfest5/clab/hackfest5.clab.yml create mode 100644 hackfest5/data/ietf-l3vpn-service.json create mode 100644 hackfest5/data/tfs-service.json create mode 100644 hackfest5/data/tfs-topology.json create mode 100755 hackfest5/deploy_specs.sh create mode 100644 hackfest5/images/arista/.gitignore create mode 100644 hackfest5/images/arista/.gitkeep create mode 100755 hackfest5/redeploy-tfs.sh diff --git a/hackfest5/.gitignore b/hackfest5/.gitignore new file mode 100644 index 000000000..0ba4756f1 --- /dev/null +++ b/hackfest5/.gitignore @@ -0,0 +1,4 @@ +clab-*/ +*.clab.yml.bak +*.tar +*.tar.gz diff --git a/hackfest5/README.md b/hackfest5/README.md new file mode 100644 index 000000000..03f5b9629 --- /dev/null +++ b/hackfest5/README.md @@ -0,0 +1,109 @@ +# Hackfest 5 - Control an Emulated DataPlane through TeraFlowSDN + +## TeraFlowSDN Deployment +```bash +cd ~/tfs-ctrl +source hackfest5/deploy_specs.sh +./deploy/all.sh +``` + +# ContainerLab - hackfest5 cEOS - Commands + +## Download and install ContainerLab +```bash +sudo bash -c "$(curl -sL https://get.containerlab.dev)" -- -v 0.59.0 +``` + +## Download hackfest5 cEOS image and create Docker image +- Note: Image to be downloaded for free from [Arista](https://www.arista.com/en/login) website. +```bash +cd ~/tfs-ctrl/hackfest5/images/arista +docker import cEOS64-lab-4.32.2F.tar ceos:4.32.2F +``` + +## Deploy scenario +```bash +~/tfs-ctrl/hackfest5/clab-deploy.sh +``` + +## Inspect scenario +```bash +~/tfs-ctrl/hackfest5/clab-inspect.sh +``` + +## Show scenario's topology +```bash +~/tfs-ctrl/hackfest5/clab-graph.sh +``` + +## Destroy scenario +```bash +~/tfs-ctrl/hackfest5/clab-destroy.sh +``` + +## Access cEOS Bash +```bash +docker exec -it clab-hackfest5-r1 bash +``` + +## Access cEOS CLI +```bash +docker exec -it clab-hackfest5-r1 Cli +docker exec -it clab-hackfest5-r2 Cli +``` + +## Configure ContainerLab clients +```bash +docker exec -it clab-hackfest5-client1 bash + ip address add 192.168.1.10/24 dev eth1 + ip route add 192.168.2.0/24 via 192.168.1.1 + ping 192.168.2.10 + +docker exec -it clab-hackfest5-client2 bash + ip address add 192.168.2.10/24 dev eth1 + ip route add 192.168.1.0/24 via 192.168.2.1 + ping 192.168.1.10 +``` + +## Install gNMIc +```bash +sudo bash -c "$(curl -sL https://get-gnmic.kmrd.dev)" +``` + +## gNMI Capabilities request +```bash +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure capabilities +``` + +## gNMI Get request +```bash +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path / > r1.json +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /interfaces/interface > r1-ifaces.json +``` + +## gNMI Set request +```bash +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --update-path /system/config/hostname --update-value "my-r1" +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /system/config/hostname +``` + +## Subscribe request +```bash +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf subscribe --path /interfaces/interface[name=Management0]/state/ + +# In another terminal, you can generate traffic opening SSH connection +ssh admin@clab-hackfest5-r1 +``` + +# Check configurations done: +```bash +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/network-instances' > r1-nis.json +gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/interfaces' > r1-ifs.json +``` + +# Delete elements: +```bash +--address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' +--address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' +--address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' +``` diff --git a/hackfest5/clab-cli-dc1.sh b/hackfest5/clab-cli-dc1.sh new file mode 100755 index 000000000..44631fa22 --- /dev/null +++ b/hackfest5/clab-cli-dc1.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +docker exec -it clab-hackfest5-dc1 bash diff --git a/hackfest5/clab-cli-dc2.sh b/hackfest5/clab-cli-dc2.sh new file mode 100755 index 000000000..56e152014 --- /dev/null +++ b/hackfest5/clab-cli-dc2.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +docker exec -it clab-hackfest5-dc2 bash diff --git a/hackfest5/clab-cli-r1.sh b/hackfest5/clab-cli-r1.sh new file mode 100755 index 000000000..f921809bf --- /dev/null +++ b/hackfest5/clab-cli-r1.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +docker exec -it clab-hackfest5-r1 Cli diff --git a/hackfest5/clab-cli-r2.sh b/hackfest5/clab-cli-r2.sh new file mode 100755 index 000000000..154179a63 --- /dev/null +++ b/hackfest5/clab-cli-r2.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +docker exec -it clab-hackfest5-r2 Cli diff --git a/hackfest5/clab-deploy.sh b/hackfest5/clab-deploy.sh new file mode 100755 index 000000000..84b4d2c22 --- /dev/null +++ b/hackfest5/clab-deploy.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +cd ~/tfs-ctrl/hackfest5 +sudo containerlab deploy --topo hackfest5.clab.yml diff --git a/hackfest5/clab-destroy.sh b/hackfest5/clab-destroy.sh new file mode 100755 index 000000000..dc65a82e7 --- /dev/null +++ b/hackfest5/clab-destroy.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +cd ~/tfs-ctrl/hackfest5 +sudo containerlab destroy --topo hackfest5.clab.yml +sudo rm -rf clab-hackfest5/ .hackfest5.clab.yml.bak diff --git a/hackfest5/clab-graph.sh b/hackfest5/clab-graph.sh new file mode 100755 index 000000000..f0ad96932 --- /dev/null +++ b/hackfest5/clab-graph.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +cd ~/tfs-ctrl/hackfest5 +sudo containerlab graph --topo hackfest5.clab.yml diff --git a/hackfest5/clab-inspect.sh b/hackfest5/clab-inspect.sh new file mode 100755 index 000000000..5e1fc7a62 --- /dev/null +++ b/hackfest5/clab-inspect.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +cd ~/tfs-ctrl/hackfest5 +sudo containerlab inspect --topo hackfest5.clab.yml diff --git a/hackfest5/clab/hackfest5.clab.yml b/hackfest5/clab/hackfest5.clab.yml new file mode 100644 index 000000000..f3887d869 --- /dev/null +++ b/hackfest5/clab/hackfest5.clab.yml @@ -0,0 +1,65 @@ +# Copyright 2022-2024 ETSI 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. + +# TFS - Arista devices + Linux clients + +name: hackfest5 + +mgmt: + network: mgmt-net + ipv4-subnet: 172.20.20.0/24 + +topology: + kinds: + arista_ceos: + kind: arista_ceos + #image: ceos:4.30.4M + #image: ceos:4.31.2F + #image: ceos:4.31.5M + #image: ceos:4.32.0F + image: ceos:4.32.2F + #image: ceos:4.32.2.1F + linux: + kind: linux + image: ghcr.io/hellt/network-multitool:latest + + nodes: + r1: + kind: arista_ceos + mgmt-ipv4: 172.20.20.101 + + r2: + kind: arista_ceos + mgmt-ipv4: 172.20.20.102 + + dc1: + kind: linux + mgmt-ipv4: 172.20.20.211 + exec: + - ip link set address 00:c1:ab:00:01:01 dev eth1 + - ip address add 192.168.1.10/24 dev eth1 + - ip route add 192.168.2.0/24 via 192.168.1.1 + + dc2: + kind: linux + mgmt-ipv4: 172.20.20.221 + exec: + - ip link set address 00:c1:ab:00:02:01 dev eth1 + - ip address add 192.168.2.10/24 dev eth1 + - ip route add 192.168.1.0/24 via 192.168.2.1 + + links: + - endpoints: ["r1:eth2", "r2:eth1"] + - endpoints: ["r1:eth10", "dc1:eth1"] + - endpoints: ["r2:eth10", "dc2:eth1"] diff --git a/hackfest5/data/ietf-l3vpn-service.json b/hackfest5/data/ietf-l3vpn-service.json new file mode 100644 index 000000000..9eb70db54 --- /dev/null +++ b/hackfest5/data/ietf-l3vpn-service.json @@ -0,0 +1,83 @@ +{ + "ietf-l3vpn-svc:l3vpn-svc": { + "vpn-services": {"vpn-service": [{"vpn-id": "ietf-l3vpn-svc"}]}, + "sites": { + "site": [ + { + "site-id": "site_DC1", + "management": {"type": "ietf-l3vpn-svc:provider-managed"}, + "locations": {"location": [{"location-id": "DC1"}]}, + "devices": {"device": [{"device-id": "dc1", "location": "DC1"}]}, + "site-network-accesses": { + "site-network-access": [ + { + "site-network-access-id": "eth1", + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "device-reference": "dc1", + "vpn-attachment": {"vpn-id": "ietf-l3vpn-svc", "site-role": "ietf-l3vpn-svc:spoke-role"}, + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "provider-address": "192.168.1.1", + "customer-address": "192.168.1.10", + "prefix-length": 24 + } + } + }, + "service": { + "svc-mtu": 1500, + "svc-input-bandwidth": 1000000000, + "svc-output-bandwidth": 1000000000, + "qos": {"qos-profile": {"classes": {"class": [{ + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": {"latency-boundary": 10}, + "bandwidth": {"guaranteed-bw-percent": 100} + }]}}} + } + } + ] + } + }, + { + "site-id": "site_DC2", + "management": {"type": "ietf-l3vpn-svc:provider-managed"}, + "locations": {"location": [{"location-id": "DC2"}]}, + "devices": {"device": [{"device-id": "dc2", "location": "DC2"}]}, + "site-network-accesses": { + "site-network-access": [ + { + "site-network-access-id": "eth1", + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "device-reference": "dc2", + "vpn-attachment": {"vpn-id": "ietf-l3vpn-svc", "site-role": "ietf-l3vpn-svc:hub-role"}, + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "provider-address": "192.168.2.1", + "customer-address": "192.168.2.10", + "prefix-length": 24 + } + } + }, + "service": { + "svc-mtu": 1500, + "svc-input-bandwidth": 1000000000, + "svc-output-bandwidth": 1000000000, + "qos": {"qos-profile": {"classes": {"class": [{ + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": {"latency-boundary": 10}, + "bandwidth": {"guaranteed-bw-percent": 100} + }]}}} + } + } + ] + } + } + ] + } + } +} diff --git a/hackfest5/data/tfs-service.json b/hackfest5/data/tfs-service.json new file mode 100644 index 000000000..397fc8478 --- /dev/null +++ b/hackfest5/data/tfs-service.json @@ -0,0 +1,26 @@ +{ + "services": [ + { + "service_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "tfs-l3vpn-svc"} + }, + "service_type": "SERVICETYPE_L3NM", + "service_status": {"service_status": "SERVICESTATUS_PLANNED"}, + "service_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "dc1"}}, "endpoint_uuid": {"uuid": "int"}}, + {"device_id": {"device_uuid": {"uuid": "dc2"}}, "endpoint_uuid": {"uuid": "int"}} + ], + "service_constraints": [], + "service_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[dc1]/endpoint[eth1]/settings", + "resource_value": {"address_ip": "192.168.1.10", "address_prefix": 24, "index": 0} + }}, + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[dc2]/endpoint[eth1]/settings", + "resource_value": {"address_ip": "192.168.2.10", "address_prefix": 24, "index": 0} + }} + ]} + } + ] +} diff --git a/hackfest5/data/tfs-topology.json b/hackfest5/data/tfs-topology.json new file mode 100644 index 000000000..49df9de42 --- /dev/null +++ b/hackfest5/data/tfs-topology.json @@ -0,0 +1,100 @@ +{ + "contexts": [ + {"context_id": {"context_uuid": {"uuid": "admin"}}} + ], + "topologies": [ + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}}} + ], + "devices": [ + { + "device_id": {"device_uuid": {"uuid": "dc1"}}, "device_type": "emu-datacenter", + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ + {"uuid": "eth1", "type": "copper"}, {"uuid": "int", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "dc2"}}, "device_type": "emu-datacenter", + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ + {"uuid": "eth1", "type": "copper"}, {"uuid": "int", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "r1"}}, "device_type": "packet-router", + "device_drivers": ["DEVICEDRIVER_GNMI_OPENCONFIG"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "172.20.20.101"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "6030"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "use_tls": false + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "r2"}}, "device_type": "packet-router", + "device_drivers": ["DEVICEDRIVER_GNMI_OPENCONFIG"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "172.20.20.102"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "6030"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "use_tls": false + }}} + ]} + } + ], + "links": [ + { + "link_id": {"link_uuid": {"uuid": "r1/Ethernet2==r2/Ethernet1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet2"}}, + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "r2/Ethernet1==r1/Ethernet2"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet1"}}, + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet2"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "r1/Ethernet10==dc1/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet10"}}, + {"device_id": {"device_uuid": {"uuid": "dc1"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "dc1/eth1==r1/Ethernet10"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "dc1"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet10"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "r2/Ethernet10==dc2/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet10"}}, + {"device_id": {"device_uuid": {"uuid": "dc2"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "dc2/eth1==r2/Ethernet10"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "dc2"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet10"}} + ] + } + ] +} diff --git a/hackfest5/deploy_specs.sh b/hackfest5/deploy_specs.sh new file mode 100755 index 000000000..2b59fa62b --- /dev/null +++ b/hackfest5/deploy_specs.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + + +# ----- TeraFlowSDN ------------------------------------------------------------ + +# Set the URL of the internal MicroK8s Docker registry where the images will be uploaded to. +export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" + +# Set the list of components, separated by spaces, you want to build images for, and deploy. +#export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" +export TFS_COMPONENTS="context device pathcomp service nbi webui" + +# Uncomment to activate Monitoring (old) +#export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" + +# Uncomment to activate Monitoring Framework (new) +#export TFS_COMPONENTS="${TFS_COMPONENTS} kpi_manager kpi_value_writer kpi_value_api telemetry analytics automation" + +# Uncomment to activate QoS Profiles +#export TFS_COMPONENTS="${TFS_COMPONENTS} qos_profile" + +# Uncomment to activate BGP-LS Speaker +#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker" + +# Uncomment to activate Optical Controller +# To manage optical connections, "service" requires "opticalcontroller" to be deployed +# before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the +# "opticalcontroller" only if "service" is already in TFS_COMPONENTS, and re-export it. +#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then +# BEFORE="${TFS_COMPONENTS% service*}" +# AFTER="${TFS_COMPONENTS#* service}" +# export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" +#fi + +# Uncomment to activate ZTP +#export TFS_COMPONENTS="${TFS_COMPONENTS} ztp" + +# Uncomment to activate Policy Manager +#export TFS_COMPONENTS="${TFS_COMPONENTS} policy" + +# Uncomment to activate Optical CyberSecurity +#export TFS_COMPONENTS="${TFS_COMPONENTS} dbscanserving opticalattackmitigator opticalattackdetector opticalattackmanager" + +# Uncomment to activate L3 CyberSecurity +#export TFS_COMPONENTS="${TFS_COMPONENTS} l3_attackmitigator l3_centralizedattackdetector" + +# Uncomment to activate TE +#export TFS_COMPONENTS="${TFS_COMPONENTS} te" + +# Uncomment to activate Forecaster +#export TFS_COMPONENTS="${TFS_COMPONENTS} forecaster" + +# Uncomment to activate E2E Orchestrator +#export TFS_COMPONENTS="${TFS_COMPONENTS} e2e_orchestrator" + +# Uncomment to activate DLT and Interdomain +#export TFS_COMPONENTS="${TFS_COMPONENTS} interdomain dlt" +#if [[ "$TFS_COMPONENTS" == *"dlt"* ]]; then +# export KEY_DIRECTORY_PATH="src/dlt/gateway/keys/priv_sk" +# export CERT_DIRECTORY_PATH="src/dlt/gateway/keys/cert.pem" +# export TLS_CERT_PATH="src/dlt/gateway/keys/ca.crt" +#fi + +# Uncomment to activate QKD App +# To manage QKD Apps, "service" requires "qkd_app" to be deployed +# before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the +# "qkd_app" only if "service" is already in TFS_COMPONENTS, and re-export it. +#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then +# BEFORE="${TFS_COMPONENTS% service*}" +# AFTER="${TFS_COMPONENTS#* service}" +# export TFS_COMPONENTS="${BEFORE} qkd_app service ${AFTER}" +#fi + + +# Set the tag you want to use for your images. +export TFS_IMAGE_TAG="dev" + +# Set the name of the Kubernetes namespace to deploy TFS to. +export TFS_K8S_NAMESPACE="tfs" + +# Set additional manifest files to be applied after the deployment +export TFS_EXTRA_MANIFESTS="manifests/nginx_ingress_http.yaml" + +# Uncomment to monitor performance of components +#export TFS_EXTRA_MANIFESTS="${TFS_EXTRA_MANIFESTS} manifests/servicemonitors.yaml" + +# Uncomment when deploying Optical CyberSecurity +#export TFS_EXTRA_MANIFESTS="${TFS_EXTRA_MANIFESTS} manifests/cachingservice.yaml" + +# Set the new Grafana admin password +export TFS_GRAFANA_PASSWORD="admin123+" + +# Disable skip-build flag to rebuild the Docker images. +export TFS_SKIP_BUILD="" + + +# ----- CockroachDB ------------------------------------------------------------ + +# Set the namespace where CockroackDB will be deployed. +export CRDB_NAMESPACE="crdb" + +# Set the external port CockroackDB Postgre SQL interface will be exposed to. +export CRDB_EXT_PORT_SQL="26257" + +# Set the external port CockroackDB HTTP Mgmt GUI interface will be exposed to. +export CRDB_EXT_PORT_HTTP="8081" + +# Set the database username to be used by Context. +export CRDB_USERNAME="tfs" + +# Set the database user's password to be used by Context. +export CRDB_PASSWORD="tfs123" + +# Set CockroachDB installation mode to 'single'. This option is convenient for development and testing. +# See ./deploy/all.sh or ./deploy/crdb.sh for additional details +export CRDB_DEPLOY_MODE="single" + +# Disable flag for dropping database, if it exists. +export CRDB_DROP_DATABASE_IF_EXISTS="YES" + +# Disable flag for re-deploying CockroachDB from scratch. +export CRDB_REDEPLOY="" + + +# ----- NATS ------------------------------------------------------------------- + +# Set the namespace where NATS will be deployed. +export NATS_NAMESPACE="nats" + +# Set the external port NATS Client interface will be exposed to. +export NATS_EXT_PORT_CLIENT="4222" + +# Set the external port NATS HTTP Mgmt GUI interface will be exposed to. +export NATS_EXT_PORT_HTTP="8222" + +# Set NATS installation mode to 'single'. This option is convenient for development and testing. +# See ./deploy/all.sh or ./deploy/nats.sh for additional details +export NATS_DEPLOY_MODE="single" + +# Disable flag for re-deploying NATS from scratch. +export NATS_REDEPLOY="" + + +# ----- QuestDB ---------------------------------------------------------------- + +# Set the namespace where QuestDB will be deployed. +export QDB_NAMESPACE="qdb" + +# Set the external port QuestDB Postgre SQL interface will be exposed to. +export QDB_EXT_PORT_SQL="8812" + +# Set the external port QuestDB Influx Line Protocol interface will be exposed to. +export QDB_EXT_PORT_ILP="9009" + +# Set the external port QuestDB HTTP Mgmt GUI interface will be exposed to. +export QDB_EXT_PORT_HTTP="9000" + +# Set the database username to be used for QuestDB. +export QDB_USERNAME="admin" + +# Set the database user's password to be used for QuestDB. +export QDB_PASSWORD="quest" + +# Set the table name to be used by Monitoring for KPIs. +export QDB_TABLE_MONITORING_KPIS="tfs_monitoring_kpis" + +# Set the table name to be used by Slice for plotting groups. +export QDB_TABLE_SLICE_GROUPS="tfs_slice_groups" + +# Disable flag for dropping tables if they exist. +export QDB_DROP_TABLES_IF_EXIST="YES" + +# Disable flag for re-deploying QuestDB from scratch. +export QDB_REDEPLOY="" + + +# ----- K8s Observability ------------------------------------------------------ + +# Set the external port Prometheus Mgmt HTTP GUI interface will be exposed to. +export PROM_EXT_PORT_HTTP="9090" + +# Set the external port Grafana HTTP Dashboards will be exposed to. +export GRAF_EXT_PORT_HTTP="3000" + + +# ----- Apache Kafka ----------------------------------------------------------- + +# Set the namespace where Apache Kafka will be deployed. +export KFK_NAMESPACE="kafka" + +# Set the port Apache Kafka server will be exposed to. +export KFK_SERVER_PORT="9092" + +# Set the flag to YES for redeploying of Apache Kafka +export KFK_REDEPLOY="" diff --git a/hackfest5/images/arista/.gitignore b/hackfest5/images/arista/.gitignore new file mode 100644 index 000000000..284b64ce5 --- /dev/null +++ b/hackfest5/images/arista/.gitignore @@ -0,0 +1,3 @@ +!.gitkeep +*.tar +*.tar.gz diff --git a/hackfest5/images/arista/.gitkeep b/hackfest5/images/arista/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/hackfest5/redeploy-tfs.sh b/hackfest5/redeploy-tfs.sh new file mode 100755 index 000000000..13f97cc77 --- /dev/null +++ b/hackfest5/redeploy-tfs.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI 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. + +source ~/tfs-ctrl/hackfest5/deploy_specs.sh +./deploy/all.sh -- GitLab From 33d61617bdfa48b7270fdeed95760ece637861df Mon Sep 17 00:00:00 2001 From: Lluis Gifre Renom Date: Fri, 8 Nov 2024 12:12:11 +0000 Subject: [PATCH 05/17] Update hackfest5.clab.yml --- hackfest5/clab/hackfest5.clab.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hackfest5/clab/hackfest5.clab.yml b/hackfest5/clab/hackfest5.clab.yml index f3887d869..2d1fe763c 100644 --- a/hackfest5/clab/hackfest5.clab.yml +++ b/hackfest5/clab/hackfest5.clab.yml @@ -45,7 +45,7 @@ topology: dc1: kind: linux - mgmt-ipv4: 172.20.20.211 + mgmt-ipv4: 172.20.20.201 exec: - ip link set address 00:c1:ab:00:01:01 dev eth1 - ip address add 192.168.1.10/24 dev eth1 @@ -53,7 +53,7 @@ topology: dc2: kind: linux - mgmt-ipv4: 172.20.20.221 + mgmt-ipv4: 172.20.20.202 exec: - ip link set address 00:c1:ab:00:02:01 dev eth1 - ip address add 192.168.2.10/24 dev eth1 -- GitLab From 4a3be7f8ae00786fc4d280d0e5c286a759f86adc Mon Sep 17 00:00:00 2001 From: Lluis Gifre Renom Date: Fri, 8 Nov 2024 12:26:01 +0000 Subject: [PATCH 06/17] Update clab-deploy.sh --- hackfest5/clab-deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hackfest5/clab-deploy.sh b/hackfest5/clab-deploy.sh index 84b4d2c22..56626a90a 100755 --- a/hackfest5/clab-deploy.sh +++ b/hackfest5/clab-deploy.sh @@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -cd ~/tfs-ctrl/hackfest5 +cd ~/tfs-ctrl/hackfest5/clab sudo containerlab deploy --topo hackfest5.clab.yml -- GitLab From d8d09fefc46565722ed5b5c659f1717baf65b157 Mon Sep 17 00:00:00 2001 From: Lluis Gifre Renom Date: Fri, 8 Nov 2024 12:26:52 +0000 Subject: [PATCH 07/17] Update hackfest5.clab.yml --- hackfest5/{clab => }/hackfest5.clab.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename hackfest5/{clab => }/hackfest5.clab.yml (100%) diff --git a/hackfest5/clab/hackfest5.clab.yml b/hackfest5/hackfest5.clab.yml similarity index 100% rename from hackfest5/clab/hackfest5.clab.yml rename to hackfest5/hackfest5.clab.yml -- GitLab From 35230182e76e462f832cfeafc26164c34d638af5 Mon Sep 17 00:00:00 2001 From: Lluis Gifre Renom Date: Fri, 8 Nov 2024 12:27:10 +0000 Subject: [PATCH 08/17] Update clab-deploy.sh --- hackfest5/clab-deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hackfest5/clab-deploy.sh b/hackfest5/clab-deploy.sh index 56626a90a..84b4d2c22 100755 --- a/hackfest5/clab-deploy.sh +++ b/hackfest5/clab-deploy.sh @@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -cd ~/tfs-ctrl/hackfest5/clab +cd ~/tfs-ctrl/hackfest5 sudo containerlab deploy --topo hackfest5.clab.yml -- GitLab From dd1164aac579cd9fc058c53fb4b7256c127b03e9 Mon Sep 17 00:00:00 2001 From: Lluis Gifre Renom Date: Fri, 8 Nov 2024 16:39:14 +0000 Subject: [PATCH 09/17] Update deploy_specs.sh --- hackfest5/deploy_specs.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hackfest5/deploy_specs.sh b/hackfest5/deploy_specs.sh index 2b59fa62b..e9565218a 100755 --- a/hackfest5/deploy_specs.sh +++ b/hackfest5/deploy_specs.sh @@ -24,7 +24,7 @@ export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" export TFS_COMPONENTS="context device pathcomp service nbi webui" # Uncomment to activate Monitoring (old) -#export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" +export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" # Uncomment to activate Monitoring Framework (new) #export TFS_COMPONENTS="${TFS_COMPONENTS} kpi_manager kpi_value_writer kpi_value_api telemetry analytics automation" @@ -199,10 +199,10 @@ export GRAF_EXT_PORT_HTTP="3000" # ----- Apache Kafka ----------------------------------------------------------- # Set the namespace where Apache Kafka will be deployed. -export KFK_NAMESPACE="kafka" +#export KFK_NAMESPACE="kafka" # Set the port Apache Kafka server will be exposed to. -export KFK_SERVER_PORT="9092" +#export KFK_SERVER_PORT="9092" # Set the flag to YES for redeploying of Apache Kafka -export KFK_REDEPLOY="" +#export KFK_REDEPLOY="" -- GitLab From 7fae0639b8f7eb6f56b63b0208ff0243d8f61aa6 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 11 Nov 2024 09:18:10 +0000 Subject: [PATCH 10/17] Updated Hackfest 5 scripts --- deploy/all.sh | 4 ++-- deploy/nats.sh | 3 +-- deploy/tfs.sh | 32 ++++++++++++++++---------------- hackfest5/redeploy-tfs.sh | 5 +++++ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/deploy/all.sh b/deploy/all.sh index 97f4db37d..96d9e30ca 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -212,8 +212,8 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} # Deploy QuestDB ./deploy/qdb.sh -# Deploy Apache Kafka -./deploy/kafka.sh +## Deploy Apache Kafka +#./deploy/kafka.sh # Expose Dashboard ./deploy/expose_dashboard.sh diff --git a/deploy/nats.sh b/deploy/nats.sh index cb3dd2318..b6df8066b 100755 --- a/deploy/nats.sh +++ b/deploy/nats.sh @@ -69,8 +69,7 @@ function nats_deploy_single() { echo ">>> NATS is present; skipping step." else echo ">>> Deploy NATS" - helm3 install ${NATS_NAMESPACE} nats/nats --namespace ${NATS_NAMESPACE} --set nats.image=nats:2.9-alpine --set config.cluster.enabled=true --set config.cluster.tls.enabled=true - + helm3 install ${NATS_NAMESPACE} nats/nats --namespace ${NATS_NAMESPACE} --set nats.image=nats:2.9-alpine echo ">>> Waiting NATS statefulset to be created..." while ! kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; do diff --git a/deploy/tfs.sh b/deploy/tfs.sh index f39609408..76e0a7383 100755 --- a/deploy/tfs.sh +++ b/deploy/tfs.sh @@ -112,16 +112,16 @@ export PROM_EXT_PORT_HTTP=${PROM_EXT_PORT_HTTP:-"9090"} export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} -# ----- Apache Kafka ------------------------------------------------------ - -# If not already set, set the namespace where Apache Kafka will be deployed. -export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} - -# If not already set, set the port Apache Kafka server will be exposed to. -export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} - -# If not already set, if flag is YES, Apache Kafka will be redeployed and topic will be lost. -export KFK_REDEPLOY=${KFK_REDEPLOY:-""} +## ----- Apache Kafka ------------------------------------------------------ +# +## If not already set, set the namespace where Apache Kafka will be deployed. +#export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} +# +## If not already set, set the port Apache Kafka server will be exposed to. +#export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} +# +## If not already set, if flag is YES, Apache Kafka will be redeployed and topic will be lost. +#export KFK_REDEPLOY=${KFK_REDEPLOY:-""} ######################################################################################################################## # Automated steps start here @@ -153,12 +153,12 @@ kubectl create secret generic crdb-data --namespace ${TFS_K8S_NAMESPACE} --type= --from-literal=CRDB_SSLMODE=require printf "\n" -echo ">>> Create Secret with Apache Kakfa..." -KFK_SERVER_PORT=$(kubectl --namespace ${KFK_NAMESPACE} get service kafka-service -o 'jsonpath={.spec.ports[0].port}') -kubectl create secret generic kfk-kpi-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ - --from-literal=KFK_NAMESPACE=${KFK_NAMESPACE} \ - --from-literal=KFK_SERVER_PORT=${KFK_SERVER_PORT} -printf "\n" +#echo ">>> Create Secret with Apache Kafka..." +#KFK_SERVER_PORT=$(kubectl --namespace ${KFK_NAMESPACE} get service kafka-service -o 'jsonpath={.spec.ports[0].port}') +#kubectl create secret generic kfk-kpi-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ +# --from-literal=KFK_NAMESPACE=${KFK_NAMESPACE} \ +# --from-literal=KFK_SERVER_PORT=${KFK_SERVER_PORT} +#printf "\n" echo "Create secret with NATS data" NATS_CLIENT_PORT=$(kubectl --namespace ${NATS_NAMESPACE} get service ${NATS_NAMESPACE} -o 'jsonpath={.spec.ports[?(@.name=="client")].port}') diff --git a/hackfest5/redeploy-tfs.sh b/hackfest5/redeploy-tfs.sh index 13f97cc77..8ea927241 100755 --- a/hackfest5/redeploy-tfs.sh +++ b/hackfest5/redeploy-tfs.sh @@ -14,4 +14,9 @@ # limitations under the License. source ~/tfs-ctrl/hackfest5/deploy_specs.sh + +helm3 uninstall --namespace ${NATS_NAMESPACE} ${NATS_NAMESPACE} +kubectl delete namespace ${NATS_NAMESPACE} --ignore-not-found +kubectl delete namespace ${KFK_NAMESPACE} --ignore-not-found + ./deploy/all.sh -- GitLab From 43ab63884a8c2f88255395f87a42f0eefc62328d Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 11 Nov 2024 10:09:37 +0000 Subject: [PATCH 11/17] Hackfest 5: - Updated redeploy-tfs script - Updated CLab descriptor - Updated README --- hackfest5/README.md | 122 ++++++++++++++++++++++++++--------- hackfest5/hackfest5.clab.yml | 4 +- hackfest5/redeploy-tfs.sh | 12 ++++ 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/hackfest5/README.md b/hackfest5/README.md index 03f5b9629..c64105389 100644 --- a/hackfest5/README.md +++ b/hackfest5/README.md @@ -1,93 +1,151 @@ # Hackfest 5 - Control an Emulated DataPlane through TeraFlowSDN -## TeraFlowSDN Deployment + +## Prepare your VM ```bash cd ~/tfs-ctrl -source hackfest5/deploy_specs.sh -./deploy/all.sh +git checkout feat/hackfest5 +git pull ``` -# ContainerLab - hackfest5 cEOS - Commands -## Download and install ContainerLab + +## ContainerLab Commands + +### Download and install ContainerLab ```bash sudo bash -c "$(curl -sL https://get.containerlab.dev)" -- -v 0.59.0 ``` -## Download hackfest5 cEOS image and create Docker image +### Check available images in Docker +```bash +docker images | grep -E "ceos|multitool" +``` + +### Download hackfest5 cEOS image and create Docker image [already done] - Note: Image to be downloaded for free from [Arista](https://www.arista.com/en/login) website. ```bash -cd ~/tfs-ctrl/hackfest5/images/arista -docker import cEOS64-lab-4.32.2F.tar ceos:4.32.2F +docker import ~/tfs-ctrl/hackfest5/images/arista/cEOS64-lab-4.31.5M.tar ceos:4.31.5M +docker import ~/tfs-ctrl/hackfest5/images/arista/cEOS64-lab-4.32.2F.tar ceos:4.32.2F ``` -## Deploy scenario +### Deploy scenario ```bash ~/tfs-ctrl/hackfest5/clab-deploy.sh ``` -## Inspect scenario +### Inspect scenario ```bash ~/tfs-ctrl/hackfest5/clab-inspect.sh ``` -## Show scenario's topology +### Show scenario's topology ```bash ~/tfs-ctrl/hackfest5/clab-graph.sh ``` -## Destroy scenario +### Destroy scenario ```bash ~/tfs-ctrl/hackfest5/clab-destroy.sh ``` -## Access cEOS Bash +### Access cEOS CLI ```bash -docker exec -it clab-hackfest5-r1 bash +~/tfs-ctrl/hackfest5/clab-cli-r1.sh ``` -## Access cEOS CLI +### Access DC CLI ```bash -docker exec -it clab-hackfest5-r1 Cli -docker exec -it clab-hackfest5-r2 Cli +~/tfs-ctrl/hackfest5/clab-cli-dc1.sh ``` -## Configure ContainerLab clients +### Start pinging remote DC ```bash -docker exec -it clab-hackfest5-client1 bash - ip address add 192.168.1.10/24 dev eth1 - ip route add 192.168.2.0/24 via 192.168.1.1 +~/tfs-ctrl/hackfest5/clab-cli-dc1.sh ping 192.168.2.10 +``` + + + +## TeraFlowSDN Commands -docker exec -it clab-hackfest5-client2 bash - ip address add 192.168.2.10/24 dev eth1 - ip route add 192.168.1.0/24 via 192.168.2.1 - ping 192.168.1.10 +### Re-Deploy TeraFlowSDN +```bash +~/tfs-ctrl/hackfest5/redeploy-tfs.sh ``` -## Install gNMIc +### Show TeraFlowSDN Deployment status +```bash +source ~/tfs-ctrl/hackfest5/deploy_specs.sh +./deploy/show.sh +``` + +### Show log of a TeraFlowSDN component +```bash +source ~/tfs-ctrl/hackfest5/deploy_specs.sh +~/tfs-ctrl/scripts/show_logs_device.sh +``` + + + +## L3VPN Commands + +### Create a new IETF L3VPN through TeraFlowSDN NBI +```bash +cd ~/tfs-ctrl/hackfest5/data +curl -X POST \ + --header "Content-Type: application/json" \ + --data @ietf-l3vpn-service.json \ + --user "admin:admin" \ + http://127.0.0.1/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services +``` + +### Get UUID of a IETF L3VPN through TeraFlowSDN NBI +```bash +curl --user "admin:admin" \ + http://127.0.0.1/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=ietf-l3vpn-svc/ +``` + +### Delete a IETF L3VPN through TeraFlowSDN NBI +```bash +curl -X DELETE --user "admin:admin" \ + http://127.0.0.1/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=ietf-l3vpn-svc/ +``` + +### Start pinging remote DC +```bash +~/tfs-ctrl/hackfest5/clab-cli-dc1.sh + ping 192.168.2.10 +``` + + + + +## gNMIc Commands + +### Install gNMIc ```bash sudo bash -c "$(curl -sL https://get-gnmic.kmrd.dev)" ``` -## gNMI Capabilities request +### gNMI Capabilities request ```bash gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure capabilities ``` -## gNMI Get request +### gNMI Get request ```bash gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path / > r1.json gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /interfaces/interface > r1-ifaces.json ``` -## gNMI Set request +### gNMI Set request ```bash gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --update-path /system/config/hostname --update-value "my-r1" gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /system/config/hostname ``` -## Subscribe request +### Subscribe request ```bash gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf subscribe --path /interfaces/interface[name=Management0]/state/ @@ -95,13 +153,13 @@ gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin ssh admin@clab-hackfest5-r1 ``` -# Check configurations done: +### Check configurations done: ```bash gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/network-instances' > r1-nis.json gnmic --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/interfaces' > r1-ifs.json ``` -# Delete elements: +### Delete elements: ```bash --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' --address clab-hackfest5-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' diff --git a/hackfest5/hackfest5.clab.yml b/hackfest5/hackfest5.clab.yml index 2d1fe763c..2fb703df0 100644 --- a/hackfest5/hackfest5.clab.yml +++ b/hackfest5/hackfest5.clab.yml @@ -26,9 +26,9 @@ topology: kind: arista_ceos #image: ceos:4.30.4M #image: ceos:4.31.2F - #image: ceos:4.31.5M + image: ceos:4.31.5M #image: ceos:4.32.0F - image: ceos:4.32.2F + #image: ceos:4.32.2F #image: ceos:4.32.2.1F linux: kind: linux diff --git a/hackfest5/redeploy-tfs.sh b/hackfest5/redeploy-tfs.sh index 8ea927241..8369b2b61 100755 --- a/hackfest5/redeploy-tfs.sh +++ b/hackfest5/redeploy-tfs.sh @@ -15,8 +15,20 @@ source ~/tfs-ctrl/hackfest5/deploy_specs.sh +echo "Cleaning-up old NATS and Kafka deployments..." helm3 uninstall --namespace ${NATS_NAMESPACE} ${NATS_NAMESPACE} kubectl delete namespace ${NATS_NAMESPACE} --ignore-not-found kubectl delete namespace ${KFK_NAMESPACE} --ignore-not-found +printf "\n" +echo "Deployting TeraFlowSDN..." ./deploy/all.sh +printf "\n" + +echo "Waiting for Context to be subscribed to NATS..." +while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do + printf "%c" "." + sleep 1 +done +kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server +printf "\n" -- GitLab From e10bd36794f149b29859ff2401c7c576f6146689 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 11 Nov 2024 10:10:15 +0000 Subject: [PATCH 12/17] Service component - L3NM gNMI OpenConfig: - Ignore default networks 0.0.0.0/* --- .../l3nm_gnmi_openconfig/ConfigRuleComposer.py | 3 ++- .../l3nm_gnmi_openconfig/StaticRouteGenerator.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py index 54101d041..ec03f1b7a 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py @@ -201,7 +201,8 @@ class DeviceComposer: endpoint.ipv4_prefix_len = ipv4_prefix_len endpoint.sub_interface_index = int(subif_index) endpoint_ip_network = netaddr.IPNetwork('{:s}/{:d}'.format(ipv4_network, ipv4_prefix_len)) - self.connected.add(str(endpoint_ip_network.cidr)) + if '0.0.0.0/' not in str(endpoint_ip_network.cidr): + self.connected.add(str(endpoint_ip_network.cidr)) match = RE_SR.match(config_rule_custom.resource_key) if match is not None: diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py index c52321473..b315c7f4d 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py @@ -138,6 +138,7 @@ class StaticRouteGenerator: if endpoint.ipv4_address is None: continue ip_network = _compose_ipv4_network(endpoint.ipv4_address, endpoint.ipv4_prefix_len) + if '0.0.0.0/' in str(ip_network.cidr): continue device.connected.add(str(ip_network.cidr)) def _compute_static_routes( -- GitLab From c4ae09781466bd279a8c59278ddef3ff1e5b5831 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 11 Nov 2024 14:09:33 +0000 Subject: [PATCH 13/17] Hackfest 5: - Updated redeploy-tfs script - Updated CLab descriptor - Updated commands in README --- hackfest5/README.md | 20 ++++++++++++++++++ hackfest5/hackfest5.clab.yml | 2 ++ hackfest5/r1-startup.cfg | 39 ++++++++++++++++++++++++++++++++++++ hackfest5/r2-startup.cfg | 39 ++++++++++++++++++++++++++++++++++++ hackfest5/redeploy-tfs.sh | 2 +- 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 hackfest5/r1-startup.cfg create mode 100644 hackfest5/r2-startup.cfg diff --git a/hackfest5/README.md b/hackfest5/README.md index c64105389..1906a5005 100644 --- a/hackfest5/README.md +++ b/hackfest5/README.md @@ -69,6 +69,26 @@ docker import ~/tfs-ctrl/hackfest5/images/arista/cEOS64-lab-4.32.2F.tar ceos:4.3 ## TeraFlowSDN Commands +### Check status of MicroK8s +```bash +microk8s.status --wait-ready +``` + +### Start MicroK8s +```bash +microk8s.start +``` + +### Periodically report status of MicroK8s every second +```bash +watch -n 1 microk8s.status --wait-ready +``` + +### Periodically report status of workload in MicroK8s every second +```bash +watch -n 1 kubectl get all --all-namespaces +``` + ### Re-Deploy TeraFlowSDN ```bash ~/tfs-ctrl/hackfest5/redeploy-tfs.sh diff --git a/hackfest5/hackfest5.clab.yml b/hackfest5/hackfest5.clab.yml index 2fb703df0..acc58e9d0 100644 --- a/hackfest5/hackfest5.clab.yml +++ b/hackfest5/hackfest5.clab.yml @@ -38,10 +38,12 @@ topology: r1: kind: arista_ceos mgmt-ipv4: 172.20.20.101 + startup-config: r1-startup.cfg r2: kind: arista_ceos mgmt-ipv4: 172.20.20.102 + startup-config: r2-startup.cfg dc1: kind: linux diff --git a/hackfest5/r1-startup.cfg b/hackfest5/r1-startup.cfg new file mode 100644 index 000000000..2d1964f5f --- /dev/null +++ b/hackfest5/r1-startup.cfg @@ -0,0 +1,39 @@ +! device: r1 (cEOSLab, EOS-4.31.2F-35442176.4312F (engineering build)) +! +no aaa root +! +username admin privilege 15 role network-admin secret sha512 $6$tUMBMqI5iPca5XcJ$5QU/R83S.zjpHQyeB3H63BGWOgxewjqZ1NsxdaWPo3gLwRXVTrgYvMmwwZlzjYoqrD7yp7e9YD073/.FKLYEY1 +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model multi-agent +! +hostname r1 +! +spanning-tree mode mstp +! +system l1 + unsupported speed action error + unsupported error-correction action error +! +management api http-commands + no shutdown +! +management api gnmi + transport grpc default +! +management api netconf + transport ssh default +! +interface Ethernet2 +! +interface Ethernet10 +! +interface Management0 + ip address 172.20.20.101/24 +! +ip routing +! +ip route 0.0.0.0/0 172.20.20.1 +! +end diff --git a/hackfest5/r2-startup.cfg b/hackfest5/r2-startup.cfg new file mode 100644 index 000000000..7acd56bf6 --- /dev/null +++ b/hackfest5/r2-startup.cfg @@ -0,0 +1,39 @@ +! device: r2 (cEOSLab, EOS-4.31.2F-35442176.4312F (engineering build)) +! +no aaa root +! +username admin privilege 15 role network-admin secret sha512 $6$Z/om4jI3S5BmwxfB$igaSOaJnh3m36TbSMHKCusA77m07CU8JJxalupXIUFuy7HaGt6k.C1kfSJsPqjn1AhLaL.LvLkt/hcqTFgpjG. +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model multi-agent +! +hostname r2 +! +spanning-tree mode mstp +! +system l1 + unsupported speed action error + unsupported error-correction action error +! +management api http-commands + no shutdown +! +management api gnmi + transport grpc default +! +management api netconf + transport ssh default +! +interface Ethernet1 +! +interface Ethernet10 +! +interface Management0 + ip address 172.20.20.102/24 +! +ip routing +! +ip route 0.0.0.0/0 172.20.20.1 +! +end diff --git a/hackfest5/redeploy-tfs.sh b/hackfest5/redeploy-tfs.sh index 8369b2b61..688d8ef39 100755 --- a/hackfest5/redeploy-tfs.sh +++ b/hackfest5/redeploy-tfs.sh @@ -18,7 +18,7 @@ source ~/tfs-ctrl/hackfest5/deploy_specs.sh echo "Cleaning-up old NATS and Kafka deployments..." helm3 uninstall --namespace ${NATS_NAMESPACE} ${NATS_NAMESPACE} kubectl delete namespace ${NATS_NAMESPACE} --ignore-not-found -kubectl delete namespace ${KFK_NAMESPACE} --ignore-not-found +kubectl delete namespace kafka --ignore-not-found printf "\n" echo "Deployting TeraFlowSDN..." -- GitLab From eba2fe40954a9da9a3f83c50ebac2ef1e7aebc42 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 19 Nov 2024 10:33:13 +0000 Subject: [PATCH 14/17] Updated deployment scripts --- deploy/all.sh | 4 ++-- deploy/tfs.sh | 32 ++++++++++++++++---------------- hackfest5/redeploy-tfs.sh | 20 +++++++++++++++++++- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/deploy/all.sh b/deploy/all.sh index 96d9e30ca..97f4db37d 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -212,8 +212,8 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} # Deploy QuestDB ./deploy/qdb.sh -## Deploy Apache Kafka -#./deploy/kafka.sh +# Deploy Apache Kafka +./deploy/kafka.sh # Expose Dashboard ./deploy/expose_dashboard.sh diff --git a/deploy/tfs.sh b/deploy/tfs.sh index 76e0a7383..a1429e443 100755 --- a/deploy/tfs.sh +++ b/deploy/tfs.sh @@ -112,16 +112,16 @@ export PROM_EXT_PORT_HTTP=${PROM_EXT_PORT_HTTP:-"9090"} export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} -## ----- Apache Kafka ------------------------------------------------------ -# -## If not already set, set the namespace where Apache Kafka will be deployed. -#export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} -# -## If not already set, set the port Apache Kafka server will be exposed to. -#export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} -# -## If not already set, if flag is YES, Apache Kafka will be redeployed and topic will be lost. -#export KFK_REDEPLOY=${KFK_REDEPLOY:-""} +# ----- Apache Kafka ------------------------------------------------------ + +# If not already set, set the namespace where Apache Kafka will be deployed. +export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} + +# If not already set, set the port Apache Kafka server will be exposed to. +export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} + +# If not already set, if flag is YES, Apache Kafka will be redeployed and topic will be lost. +export KFK_REDEPLOY=${KFK_REDEPLOY:-""} ######################################################################################################################## # Automated steps start here @@ -153,12 +153,12 @@ kubectl create secret generic crdb-data --namespace ${TFS_K8S_NAMESPACE} --type= --from-literal=CRDB_SSLMODE=require printf "\n" -#echo ">>> Create Secret with Apache Kafka..." -#KFK_SERVER_PORT=$(kubectl --namespace ${KFK_NAMESPACE} get service kafka-service -o 'jsonpath={.spec.ports[0].port}') -#kubectl create secret generic kfk-kpi-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ -# --from-literal=KFK_NAMESPACE=${KFK_NAMESPACE} \ -# --from-literal=KFK_SERVER_PORT=${KFK_SERVER_PORT} -#printf "\n" +echo ">>> Create Secret with Apache Kafka..." +KFK_SERVER_PORT=$(kubectl --namespace ${KFK_NAMESPACE} get service kafka-service -o 'jsonpath={.spec.ports[0].port}') +kubectl create secret generic kfk-kpi-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ + --from-literal=KFK_NAMESPACE=${KFK_NAMESPACE} \ + --from-literal=KFK_SERVER_PORT=${KFK_SERVER_PORT} +printf "\n" echo "Create secret with NATS data" NATS_CLIENT_PORT=$(kubectl --namespace ${NATS_NAMESPACE} get service ${NATS_NAMESPACE} -o 'jsonpath={.spec.ports[?(@.name=="client")].port}') diff --git a/hackfest5/redeploy-tfs.sh b/hackfest5/redeploy-tfs.sh index 688d8ef39..ff55bed3f 100755 --- a/hackfest5/redeploy-tfs.sh +++ b/hackfest5/redeploy-tfs.sh @@ -22,7 +22,25 @@ kubectl delete namespace kafka --ignore-not-found printf "\n" echo "Deployting TeraFlowSDN..." -./deploy/all.sh + +# Deploy CockroachDB +./deploy/crdb.sh + +# Deploy NATS +./deploy/nats.sh + +# Deploy QuestDB +./deploy/qdb.sh + +# Expose Dashboard +./deploy/expose_dashboard.sh + +# Deploy TeraFlowSDN +./deploy/tfs.sh + +# Show deploy summary +./deploy/show.sh + printf "\n" echo "Waiting for Context to be subscribed to NATS..." -- GitLab From 664432b7685fd0144c5c57f2855353c9815363d9 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 19 Nov 2024 10:33:29 +0000 Subject: [PATCH 15/17] Device - gNMI OpenConfig Driver: - Corrected MTU logic --- .../service/drivers/gnmi_openconfig/handlers/Interface.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py index 36a024bd1..1fb418542 100644 --- a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py +++ b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py @@ -41,14 +41,14 @@ class InterfaceHandler(_Handler): vlan_id = get_int (resource_value, 'vlan_id', ) # 127 address_ip = get_str (resource_value, 'address_ip' ) # 172.16.0.1 address_prefix = get_int (resource_value, 'address_prefix') # 24 - #mtu = get_int (resource_value, 'mtu', 1450) # 1500 + mtu = get_int (resource_value, 'mtu', ) # 1500 yang_ifs : libyang.DContainer = yang_handler.get_data_path('/openconfig-interfaces:interfaces') yang_if_path = 'interface[name="{:s}"]'.format(if_name) yang_if : libyang.DContainer = yang_ifs.create_path(yang_if_path) yang_if.create_path('config/name', if_name ) if enabled is not None: yang_if.create_path('config/enabled', enabled) - #if mtu is not None: yang_if.create_path('config/mtu', mtu) + if mtu is not None: yang_if.create_path('config/mtu', mtu) yang_sifs : libyang.DContainer = yang_if.create_path('subinterfaces') yang_sif_path = 'subinterface[index="{:d}"]'.format(sif_index) @@ -69,7 +69,6 @@ class InterfaceHandler(_Handler): yang_ipv4_addr : libyang.DContainer = yang_ipv4_addrs.create_path(yang_ipv4_addr_path) yang_ipv4_addr.create_path('config/ip', address_ip) yang_ipv4_addr.create_path('config/prefix-length', address_prefix) - #if mtu is not None: yang_ipv4_addr.create_path('config/mtu', mtu) str_path = '/interfaces/interface[name={:s}]'.format(if_name) str_data = yang_if.print_mem('json') -- GitLab From 8c0ed513cf8d97e3ff52d8d54a2e26c1425c4e2f Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 19 Nov 2024 10:34:25 +0000 Subject: [PATCH 16/17] Device - gNMI OpenConfig Driver: - Corrected MTU logic --- .../service/drivers/gnmi_openconfig/handlers/Interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py index 1fb418542..a52c84691 100644 --- a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py +++ b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py @@ -41,7 +41,7 @@ class InterfaceHandler(_Handler): vlan_id = get_int (resource_value, 'vlan_id', ) # 127 address_ip = get_str (resource_value, 'address_ip' ) # 172.16.0.1 address_prefix = get_int (resource_value, 'address_prefix') # 24 - mtu = get_int (resource_value, 'mtu', ) # 1500 + mtu = get_int (resource_value, 'mtu' ) # 1500 yang_ifs : libyang.DContainer = yang_handler.get_data_path('/openconfig-interfaces:interfaces') yang_if_path = 'interface[name="{:s}"]'.format(if_name) -- GitLab From 8655f81568ac500cbf9f87e7bfa85373f63b01f5 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 19 Nov 2024 10:39:10 +0000 Subject: [PATCH 17/17] Service - gNMI OpenConfig Service Handler: - Generalized configuration of network instances --- .../ConfigRuleComposer.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py index ec03f1b7a..277d6d7e1 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py @@ -21,8 +21,9 @@ from service.service.service_handler_api.AnyTreeTools import TreeNode LOGGER = logging.getLogger(__name__) -#NETWORK_INSTANCE = 'teraflowsdn' +#NETWORK_INSTANCE = 'teraflowsdn' # TODO: investigate; sometimes it does not create/delete static rules properly NETWORK_INSTANCE = 'default' +DEFAULT_NETWORK_INSTANCE = 'default' RE_IF = re.compile(r'^\/interface\[([^\]]+)\]$') RE_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') @@ -109,11 +110,13 @@ class EndpointComposer: if self.ipv4_address is None: return [] if self.ipv4_prefix_len is None: return [] json_config_rule = json_config_rule_delete if delete else json_config_rule_set - config_rules = [ - #json_config_rule(*_network_instance_interface( - # network_instance_name, self.objekt.name, self.sub_interface_index - #)), - ] + + config_rules : List[Dict] = list() + if network_instance_name != DEFAULT_NETWORK_INSTANCE: + config_rules.append(json_config_rule(*_network_instance_interface( + network_instance_name, self.objekt.name, self.sub_interface_index + ))) + if delete: config_rules.extend([ json_config_rule(*_interface( @@ -226,9 +229,9 @@ class DeviceComposer: if self.objekt.device_type not in SELECTED_DEVICES: return [] json_config_rule = json_config_rule_delete if delete else json_config_rule_set - config_rules = [ - #json_config_rule(*_network_instance(network_instance_name, 'L3VRF')) - ] + config_rules : List[Dict] = list() + if network_instance_name != DEFAULT_NETWORK_INSTANCE: + json_config_rule(*_network_instance(network_instance_name, 'L3VRF')) for endpoint in self.endpoints.values(): config_rules.extend(endpoint.get_config_rules(network_instance_name, delete=delete)) if len(self.static_routes) > 0: -- GitLab