Commit 3da43d34 authored by Christos Tranoris's avatar Christos Tranoris
Browse files

updated readme and added spme tests

parent e841ec7a
Loading
Loading
Loading
Loading
+4 −12
Original line number Diff line number Diff line
@@ -2,10 +2,8 @@

## Overview

The **IETF NS Controller** is a Spring Boot microservice implementing the customer part of the **IETF RFC 9543 Network Slice Service** for Teraflow SDN. This microservice acts as an **OSL Resource Controller** that bridges 
OpenSlice microservices (like TMF API, Service Orchestrator (OSOM)) and Network Slice Service Providers (e.g., TerflowSDN) through a **message-driven architecture** using Apache Camel and ActiveMQ.

**WARNING: This artifact is still under testing and not fully functional**
The **IETF NS Controller** is a Spring Boot microservice implementing the customer part of the **IETF RFC 9543 Network Slice Service** for controllers who support the IETF RFC 9543 like Teraflow SDN. This microservice acts as an **OSL Resource Controller** that bridges 
OpenSlice microservices (like TMF API, Service Orchestrator (OSOM)) and Network Slice Service Providers (e.g., TeraflowSDN) through a **message-driven architecture** using Apache Camel and ActiveMQ.

### Architectural approach

@@ -30,7 +28,7 @@ OpenSlice microservices (like TMF API, Service Orchestrator (OSOM)) and Network


┌─────────────────────────────────────────────────────────────┐
│   Network Slice Service Provider (e.g. TerflowSDN)          
│   Network Slice Service Provider (e.g. TeraflowSDN)         │
│   (RESTCONF Server implementing RFC 9543)                   │
└─────────────────────────────────────────────────────────────┘
```
@@ -330,7 +328,7 @@ When OpenSlice OSOM creates a resource using a registered resource specification
1. OSOM sends a `CREATE` message to `CREATE/ns.ietf.controllers.osl.etsi.org/v1alpha/0.1.0`
2. Controller reads the spec name from the resource's `resourceSpecification.name`
3. Handler parses the JSON characteristic payload and deserializes to domain objects
4. Controller calls `RestconfClientImpl` to provision the slice via RESTCONF to TerflowSDN
4. Controller calls `RestconfClientImpl` to provision the slice via RESTCONF to TeraflowSDN
5. Controller updates the resource status in OpenSlice:
   - **CREATE success:** Status = `AVAILABLE`, administrative state = `UNLOCKED`
   - **CREATE failure:** Status = `UNKNOWN`, health = `Unhealthy`, message describes error
@@ -439,12 +437,6 @@ All runtime settings are configured in `application.yml`:
- [`doc/bootstrap_phase.puml`](doc/bootstrap_phase.puml) — 3-step bootstrap sequence
- [`doc/resource_creation_lifecycle.puml`](doc/resource_creation_lifecycle.puml) — resource lifecycle from OSOM to RESTCONF

**Implementation Guides (doc/NSC/):**
- `RESTCONF_CONSUMER_GUIDE.md` — RFC 9543 overview and RESTCONF operations
- `RESTCONF_IMPLEMENTATION.md` — Implementation patterns with examples
- `SLO_SLE_TEMPLATE_GUIDE.md` — SLO/SLE API reference
- `SLO_SLE_REFACTORING_SUMMARY.md` — Refactoring history and class hierarchy

**Test Resources:**
- `doc/NSC/examples/` — RFC 9543 JSON test payloads
- `doc/NSC/draft-ietf-teas-ietf-network-slice-nbi-yang-25.txt` — RFC 9543 specification
+1 −2
Original line number Diff line number Diff line
@@ -12,8 +12,7 @@ import org.springframework.context.annotation.ComponentScan;


/**
 * For implementing the callback and events, it might be useful to check the DDD pattern:
 * https://www.baeldung.com/spring-data-ddd

 * 
 * 
 * @author ctranoris
+0 −43
Original line number Diff line number Diff line
package org.etsi.osl.controllers.ietf.ns.demo;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import lombok.extern.slf4j.Slf4j;

/**
 * Simple demo RESTCONF server that serves example network-slice-services.
 *
 * This server:
 * - Listens on port 11880
 * - Provides RESTCONF endpoints for network slice services
 * - Serves example SLO/SLE templates
 * - Demonstrates RFC 8040 RESTCONF protocol compliance
 *
 * Usage:
 * 1. Run this application
 * 2. Access endpoints at http://localhost:11880/restconf/data/...
 *
 * Example RESTCONF operations:
 * - GET http://localhost:11880/restconf/data/ietf-network-slice-service:network-slice-services/slo-sle-templates
 * - GET http://localhost:11880/restconf/data/ietf-network-slice:network-slice-services
 * - GET http://localhost:11880/restconf/data/ietf-network-slice:network-slice-services/slice-services
 * - POST http://localhost:11880/restconf/data/ietf-network-slice:network-slice-services/slice-services
 *
 * @author ctranoris
 */
@SpringBootApplication
@ComponentScan(basePackages = {
    "org.etsi.osl.controllers.ietf.ns.demo",
    
})
@Slf4j
public class RestconfServerDemo {

    public static void main(String[] args) {
        log.info("Starting RESTCONF Server Demo on port 11880...");
        new SpringApplicationBuilder(RestconfServerDemo.class)
            .profiles("demo")
            .run(args);
    }
}
+0 −223
Original line number Diff line number Diff line
package org.etsi.osl.controllers.ietf.ns.demo;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

/**
 * RFC 9543 compliant demo service generator.
 *
 * Generates example IETF Network Slice Service templates and services
 * according to draft-ietf-teas-ietf-network-slice-nbi-yang-25.
 *
 * This service creates demo data in the exact format specified in the RFC.
 */
@Service
@Slf4j
public class Rfc9543DemoService {

    /**
     * Create RFC 9543 compliant network slice services response.
     *
     * @return Response with proper YANG structure
     */
    public Rfc9543NetworkSliceServicesResponse createDemoServices() {
        log.info("Generating RFC 9543 compliant network slice services...");

        Rfc9543NetworkSliceServicesResponse response = new Rfc9543NetworkSliceServicesResponse();

        // Create main container
        Rfc9543NetworkSliceServicesResponse.NetworkSliceServices nss =
            new Rfc9543NetworkSliceServicesResponse.NetworkSliceServices();

        // Create templates container with proper templates
        Rfc9543NetworkSliceServicesResponse.SloSleTemplatesContainer templatesContainer =
            new Rfc9543NetworkSliceServicesResponse.SloSleTemplatesContainer();

        templatesContainer.setSloSleTemplate(createRfc9543Templates());
        nss.setSloSleTemplates(templatesContainer);

        // Create slice services
        nss.setSliceServices(createRfc9543SliceServices());

        response.setNetworkSliceServices(nss);

        log.info("Created {} templates and {} services",
                nss.getSloSleTemplates().getSloSleTemplate().size(),
                nss.getSliceServices().size());

        return response;
    }

    /**
     * Create RFC 9543 compliant SLO/SLE templates.
     * Based on Figure 6 from draft-ietf-teas-ietf-network-slice-nbi-yang-25.
     */
    private List<Rfc9543SloSleTemplate> createRfc9543Templates() {
        List<Rfc9543SloSleTemplate> templates = new ArrayList<>();

        // PLATINUM Template
        templates.add(createPlatinumTemplate());

        // GOLD Template
        templates.add(createGoldTemplate());

        // SILVER Template (additional example)
        templates.add(createSilverTemplate());

        return templates;
    }

    /**
     * PLATINUM Template: High performance, low latency
     * Two-way bandwidth: 1 Gbps, 95th percentile latency 50ms
     */
    private Rfc9543SloSleTemplate createPlatinumTemplate() {
        Rfc9543SloSleTemplate template = new Rfc9543SloSleTemplate();
        template.setId("DEMO-PLATINUM-template");
        template.setDescription("Two-way bandwidth: 1 Gbps, 95th percentile latency 50ms");

        // SLO Policy
        Rfc9543SloSleTemplate.SloPolicy sloPolicy = new Rfc9543SloSleTemplate.SloPolicy();

        // Metric 1: Two-way bandwidth
        Rfc9543SloSleTemplate.MetricBound bandwidthBound =
            new Rfc9543SloSleTemplate.MetricBound();
        bandwidthBound.setMetricType("two-way-bandwidth");
        bandwidthBound.setMetricUnit("Gbps");
        bandwidthBound.setBound("1");
        sloPolicy.getMetricBound().add(bandwidthBound);

        // Metric 2: Two-way delay percentile (95th percentile)
        Rfc9543SloSleTemplate.MetricBound delayBound =
            new Rfc9543SloSleTemplate.MetricBound();
        delayBound.setMetricType("two-way-delay-percentile");
        delayBound.setMetricUnit("milliseconds");
        delayBound.setPercentileValue("95.000");
        delayBound.setBound("50");
        sloPolicy.getMetricBound().add(delayBound);

        template.setSloPolicy(sloPolicy);

        // SLE Policy
        Rfc9543SloSleTemplate.SlePolicy slePolicy = new Rfc9543SloSleTemplate.SlePolicy();
        slePolicy.getIsolation().add("traffic-isolation");
        template.setSlePolicy(slePolicy);

        return template;
    }

    /**
     * GOLD Template: High performance with guaranteed latency
     * Two-way bandwidth: 1 Gbps, maximum latency 100ms
     */
    private Rfc9543SloSleTemplate createGoldTemplate() {
        Rfc9543SloSleTemplate template = new Rfc9543SloSleTemplate();
        template.setId("DEMO-GOLD-template");
        template.setDescription("Two-way bandwidth: 1 Gbps, maximum latency 100ms");

        // SLO Policy
        Rfc9543SloSleTemplate.SloPolicy sloPolicy = new Rfc9543SloSleTemplate.SloPolicy();

        // Metric 1: Two-way bandwidth
        Rfc9543SloSleTemplate.MetricBound bandwidthBound =
            new Rfc9543SloSleTemplate.MetricBound();
        bandwidthBound.setMetricType("two-way-bandwidth");
        bandwidthBound.setMetricUnit("Gbps");
        bandwidthBound.setBound("1");
        sloPolicy.getMetricBound().add(bandwidthBound);

        // Metric 2: Two-way delay maximum
        Rfc9543SloSleTemplate.MetricBound delayBound =
            new Rfc9543SloSleTemplate.MetricBound();
        delayBound.setMetricType("two-way-delay-maximum");
        delayBound.setMetricUnit("milliseconds");
        delayBound.setBound("100");
        sloPolicy.getMetricBound().add(delayBound);

        template.setSloPolicy(sloPolicy);

        // SLE Policy
        Rfc9543SloSleTemplate.SlePolicy slePolicy = new Rfc9543SloSleTemplate.SlePolicy();
        slePolicy.getIsolation().add("traffic-isolation");
        template.setSlePolicy(slePolicy);

        return template;
    }

    /**
     * SILVER Template: Standard performance
     * Two-way bandwidth: 500 Mbps, 99th percentile latency 100ms
     */
    private Rfc9543SloSleTemplate createSilverTemplate() {
        Rfc9543SloSleTemplate template = new Rfc9543SloSleTemplate();
        template.setId("DEMO-SILVER-template");
        template.setDescription("Two-way bandwidth: 500 Mbps, 99th percentile latency 100ms");

        // SLO Policy
        Rfc9543SloSleTemplate.SloPolicy sloPolicy = new Rfc9543SloSleTemplate.SloPolicy();

        // Metric 1: Two-way bandwidth
        Rfc9543SloSleTemplate.MetricBound bandwidthBound =
            new Rfc9543SloSleTemplate.MetricBound();
        bandwidthBound.setMetricType("two-way-bandwidth");
        bandwidthBound.setMetricUnit("Mbps");
        bandwidthBound.setBound("500");
        sloPolicy.getMetricBound().add(bandwidthBound);

        // Metric 2: Two-way delay percentile (99th percentile)
        Rfc9543SloSleTemplate.MetricBound delayBound =
            new Rfc9543SloSleTemplate.MetricBound();
        delayBound.setMetricType("two-way-delay-percentile");
        delayBound.setMetricUnit("milliseconds");
        delayBound.setPercentileValue("99.000");
        delayBound.setBound("100");
        sloPolicy.getMetricBound().add(delayBound);

        template.setSloPolicy(sloPolicy);

        // SLE Policy
        Rfc9543SloSleTemplate.SlePolicy slePolicy = new Rfc9543SloSleTemplate.SlePolicy();
        slePolicy.getIsolation().add("traffic-isolation");
        template.setSlePolicy(slePolicy);

        return template;
    }

    /**
     * Create RFC 9543 compliant slice services.
     */
    private List<Rfc9543NetworkSliceServicesResponse.SliceService> createRfc9543SliceServices() {
        List<Rfc9543NetworkSliceServicesResponse.SliceService> services = new ArrayList<>();

        // Service 1: E-Commerce
        Rfc9543NetworkSliceServicesResponse.SliceService ecommerce =
            new Rfc9543NetworkSliceServicesResponse.SliceService();
        ecommerce.setId("service-ecommerce-001");
        ecommerce.setDescription("E-Commerce Platform Network Slice Service");
        ecommerce.setTestOnly(false);
        ecommerce.setStatus("active");
        services.add(ecommerce);

        // Service 2: Video Streaming
        Rfc9543NetworkSliceServicesResponse.SliceService video =
            new Rfc9543NetworkSliceServicesResponse.SliceService();
        video.setId("service-video-001");
        video.setDescription("Video Streaming CDN Network Slice Service");
        video.setTestOnly(false);
        video.setStatus("active");
        services.add(video);

        // Service 3: Enterprise WAN
        Rfc9543NetworkSliceServicesResponse.SliceService enterprise =
            new Rfc9543NetworkSliceServicesResponse.SliceService();
        enterprise.setId("service-enterprise-wan-001");
        enterprise.setDescription("Enterprise WAN Network Slice Service");
        enterprise.setTestOnly(false);
        enterprise.setStatus("active");
        services.add(enterprise);

        return services;
    }
}
+0 −136
Original line number Diff line number Diff line
package org.etsi.osl.controllers.ietf.ns.demo;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * RFC 9543 compliant response wrapper for network-slice-services.
 *
 * This class represents the complete RESTCONF response structure as defined
 * in draft-ietf-teas-ietf-network-slice-nbi-yang-25.
 *
 * The response follows the YANG container hierarchy:
 * {
 *   "ietf-network-slice-service:network-slice-services": {
 *     "slo-sle-templates": {
 *       "slo-sle-template": [ ... ]
 *     },
 *     "slice-service": [ ... ]
 *   }
 * }
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Rfc9543NetworkSliceServicesResponse {

    /**
     * YANG container for network slice services with RFC 9543 namespace.
     * This is the root container for all network slice service data.
     */
    @JsonProperty("ietf-network-slice-service:network-slice-services")
    private NetworkSliceServices networkSliceServices;

    /**
     * Network slice services container with templates and services.
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class NetworkSliceServices {
        /**
         * Container for SLO/SLE template definitions.
         * These are reusable service level templates.
         */
        @JsonProperty("slo-sle-templates")
        private SloSleTemplatesContainer sloSleTemplates;

        /**
         * Container for slice service instances.
         * These are actual service instances that may reference templates.
         */
        @JsonProperty("slice-service")
        private List<SliceService> sliceServices = new ArrayList<>();
    }

    /**
     * Container for SLO/SLE templates.
     * Holds a list of reusable template definitions.
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class SloSleTemplatesContainer {
        /**
         * List of SLO/SLE template definitions.
         * Each template defines a set of service level requirements.
         */
        @JsonProperty("slo-sle-template")
        private List<Rfc9543SloSleTemplate> sloSleTemplate = new ArrayList<>();
    }

    /**
     * Network Slice Service instance.
     *
     * Represents a customer-requested network slice service with specific
     * connectivity and SLO/SLE requirements.
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class SliceService {
        /**
         * Unique identifier for the slice service.
         * Example: "service-ecommerce-001"
         */
        @JsonProperty("id")
        private String id;

        /**
         * Human-readable description of the slice service.
         * Example: "E-Commerce Platform Network Slice Service"
         */
        @JsonProperty("description")
        private String description;

        /**
         * Service tags for classification and management.
         * Optional list of tags.
         */
        @JsonProperty("service-tags")
        private ServiceTags serviceTags;

        /**
         * Test-only flag indicating this is a feasibility check.
         * If present and set to true, the service is not provisioned.
         * Optional field.
         */
        @JsonProperty("test-only")
        private Boolean testOnly;

        /**
         * Status of the slice service.
         * Example: "active", "pending", "terminated"
         */
        @JsonProperty("status")
        private String status;
    }

    /**
     * Service tags container for classification.
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ServiceTags {
        /**
         * List of tag values for service categorization.
         */
        @JsonProperty("tag")
        private List<String> tags = new ArrayList<>();
    }
}
Loading