Commit cd90e81e authored by Christos Tranoris's avatar Christos Tranoris
Browse files

successful creation of resource

parent 2fd14074
Loading
Loading
Loading
Loading
+2 −127
Original line number Diff line number Diff line
@@ -230,8 +230,8 @@ public class SloSleTemplateBootstrapService implements CommandLineRunner {
        addSpecCharacteristic(spec, "testOnly",    "BOOLEAN", "false",       true);

        // Operational status (RFC 9543 admin/oper states)
        addSpecCharacteristic(spec, "status.adminState", "TEXT", "admin-up",     true);
        addSpecCharacteristic(spec, "status.operState",  "TEXT", "operational",  true);
        addSpecCharacteristic(spec, "status.adminStatus", "TEXT", "admin-up",     true);
        addSpecCharacteristic(spec, "status.operStatus",  "TEXT", "operational",  true);

        // SLO/SLE template reference (stores the referenced SloSleTemplate ID)
        addSpecCharacteristic(spec, "sloSleTemplate", "TEXT", "", false);
@@ -513,130 +513,5 @@ public class SloSleTemplateBootstrapService implements CommandLineRunner {


   
    /**
     * Parse RFC 9543 formatted SliceService JSON and return SliceService domain object.
     *
     * This method handles the real-world RFC 9543 network-slice-service format with
     * SDP (Service Demarcation Points) and connection groups.
     *
     * @param sliceServiceJson RFC 9543 formatted JSON string
     * @return SliceService domain object
     * @throws Exception if JSON parsing fails
     */
    public NetworkSliceServices parseAndConvertSliceService(String sliceServiceJson) throws Exception {
        log.info("Parsing RFC 9543 SliceService JSON");

        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readTree(sliceServiceJson);

            // Navigate through RFC 9543 namespace wrapper
            JsonNode nssNode = rootNode.get("ietf-network-slice-service:network-slice-services");
            if (nssNode == null) {
                throw new IllegalArgumentException("Missing RFC 9543 namespace wrapper");
            }

            JsonNode sliceServicesNode = nssNode.get("slice-service");
            if (sliceServicesNode == null || !sliceServicesNode.isArray() || sliceServicesNode.size() == 0) {
                throw new IllegalArgumentException("No slice-service array found");
            }

            // Parse all slice services from the array
            List<SliceService> sliceServices = new ArrayList<>();

            for (int i = 0; i < sliceServicesNode.size(); i++) {
                JsonNode sliceServiceNode = sliceServicesNode.get(i);

                // Parse service identity
                String serviceId = sliceServiceNode.get("id").asText();
                String serviceDescription = sliceServiceNode.has("description") ?
                    sliceServiceNode.get("description").asText() : "Network Slice Service";

                log.info("Parsing slice service: {}", serviceId);

                // Create SliceService domain object
                SliceService service = new SliceService();
                service.setId(serviceId);
                service.setDescription(serviceDescription);
                service.setTestOnly(false);

            // Parse SLO/SLE template reference
            if (sliceServiceNode.has("slo-sle-policy")) {
                JsonNode sloSlePolicyNode = sliceServiceNode.get("slo-sle-policy");
                if (sloSlePolicyNode.has("slo-sle-template")) {
                    String templateId = sloSlePolicyNode.get("slo-sle-template").asText();
                    SloSleTemplate template = new SloSleTemplate();
                    template.setId(templateId);
                    service.setSloSleTemplate(template);
                    log.debug("Service {} references template: {}", serviceId, templateId);
                }
            }

            // Parse service tags
            if (sliceServiceNode.has("service-tags")) {
                JsonNode tagsNode = sliceServiceNode.get("service-tags");
                if (tagsNode.has("tag-type") && tagsNode.get("tag-type").isArray()) {
                    for (JsonNode tagNode : tagsNode.get("tag-type")) {
                        String tagType = tagNode.get("tag-type").asText();
                        if (tagNode.has("tag-type-value") && tagNode.get("tag-type-value").isArray()) {
                            for (JsonNode tagValueNode : tagNode.get("tag-type-value")) {
                                ServiceTag tag = new ServiceTag();
                                tag.setValue(tagType + ":" + tagValueNode.asText());
                                service.getServiceTags().add(tag);
                            }
                        }
                    }
                }
            }

            // Parse status
            ServiceStatus status = new ServiceStatus();
            status.setAdminState("admin-up");
            status.setOperState("operational");
            service.setStatus(status);

            // Parse SDPs (Service Demarcation Points)
            if (sliceServiceNode.has("sdps") && sliceServiceNode.get("sdps").has("sdp")) {
                JsonNode sdpsNode = sliceServiceNode.get("sdps").get("sdp");
                if (sdpsNode.isArray()) {
                    log.debug("Found {} SDPs in slice service", sdpsNode.size());
                }
            }

                // Parse connection groups
                if (sliceServiceNode.has("connection-groups") &&
                    sliceServiceNode.get("connection-groups").has("connection-group")) {
                    JsonNode connGroupsNode = sliceServiceNode.get("connection-groups").get("connection-group");
                    if (connGroupsNode.isArray()) {
                        log.debug("Found {} connection groups in slice service", connGroupsNode.size());
                    }
                }

                // Add this service to the list
                sliceServices.add(service);
                log.info("Successfully parsed RFC 9543 SliceService: {}", serviceId);
            }

            // Create NetworkSliceServices wrapper with all parsed services
            NetworkSliceServices networkSliceServices = new NetworkSliceServices();
            networkSliceServices.setSliceServices(sliceServices);

            // Build and store the RFC 9543 formatted JSON request (slice-service array)
            Map<String, List<SliceService>> sliceServiceWrapper = new HashMap<>();
            sliceServiceWrapper.put("slice-service", sliceServices);

            log.info("Successfully created NetworkSliceServices with {} service(s)", sliceServices.size());
            return networkSliceServices;

        } catch (IllegalArgumentException e) {
            log.error("Invalid RFC 9543 SliceService JSON format: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("Error parsing RFC 9543 SliceService JSON", e);
            throw e;
        }
    }

   

}
+13 −6
Original line number Diff line number Diff line
@@ -2,26 +2,33 @@ package org.etsi.osl.controllers.ietf.ns.api.domain.model;

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

/**
 * Represents a connectivity construct within a connection group.
 * Defines a specific connectivity pattern (P2P, P2MP, A2A) and includes
 * the SDP members that are part of this construct.
 * Supports P2P (p2p-sender-sdp / p2p-receiver-sdp), P2MP, and A2A patterns.
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ConnectivityConstruct {
    private String id;

    /** P2P sender SDP reference (RFC 9543: p2p-sender-sdp). */
    @JsonProperty("p2p-sender-sdp")
    private String p2pSenderSdp;

    /** P2P receiver SDP reference (RFC 9543: p2p-receiver-sdp). */
    @JsonProperty("p2p-receiver-sdp")
    private String p2pReceiverSdp;

    private ConnectivityType type;
    private ConstructStatus status;

    // 0-to-1 relationship: optional SLO/SLE policy override
    private PolicyRef policyOverride;

    // Many-to-many relationship: members by reference
    private List<SdpMember> members = new ArrayList<>();
}
+24 −4
Original line number Diff line number Diff line
package org.etsi.osl.controllers.ietf.ns.api.domain.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
 * Enumeration for connectivity types as per IETF Network Slice Service specification.
 * P2P: Point-to-Point
 * P2MP: Point-to-Multipoint
 * A2A: Any-to-Any
 * Accepts RFC 9543 kebab-case strings (e.g., "point-to-point") and UPPER_SNAKE_CASE.
 */
public enum ConnectivityType {
    P2P,
    P2MP,
    A2A
    A2A;

    @JsonCreator
    public static ConnectivityType fromValue(String value) {
        if (value == null || value.isBlank()) return null;
        String lower = value.toLowerCase();
        if (lower.contains("point-to-point") || lower.equals("p2p")) return P2P;
        if (lower.contains("point-to-multipoint") || lower.equals("p2mp")) return P2MP;
        if (lower.contains("any-to-any") || lower.equals("a2a")) return A2A;
        try { return valueOf(value.toUpperCase()); } catch (IllegalArgumentException e) { return null; }
    }

    @JsonValue
    public String toValue() {
        return switch (this) {
            case P2P  -> "point-to-point";
            case P2MP -> "point-to-multipoint";
            case A2A  -> "any-to-any";
        };
    }
}
+8 −14
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package org.etsi.osl.controllers.ietf.ns.api.domain.model;

import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -37,6 +38,7 @@ public class NetworkSliceServices implements LogicalResourceMappable {
     * Get the unique identifier - uses the first slice service ID if available.
     */
    @Override
    @JsonIgnore
    public String getEntityId() {
        if (sliceServices != null && !sliceServices.isEmpty()) {
            return sliceServices.get(0).getId();
@@ -44,10 +46,8 @@ public class NetworkSliceServices implements LogicalResourceMappable {
        return "unknown";
    }

    /**
     * Get the display name - uses the first slice service ID if available.
     */
    @Override
    @JsonIgnore
    public String getEntityName() {
        if (sliceServices != null && !sliceServices.isEmpty()) {
            return sliceServices.get(0).getId();
@@ -55,10 +55,8 @@ public class NetworkSliceServices implements LogicalResourceMappable {
        return "Network Slice Services";
    }

    /**
     * Get the description - uses the first slice service description if available.
     */
    @Override
    @JsonIgnore
    public String getEntityDescription() {
        if (sliceServices != null && !sliceServices.isEmpty() && sliceServices.get(0).getDescription() != null) {
            return sliceServices.get(0).getDescription();
@@ -66,18 +64,14 @@ public class NetworkSliceServices implements LogicalResourceMappable {
        return "IETF RFC 9543 Network Slice Services";
    }

    /**
     * Check if this entity has status mapping.
     */
    @Override
    @JsonIgnore
    public boolean hasStatusMapping() {
        return sliceServices != null && !sliceServices.isEmpty() && sliceServices.get(0).getStatus() != null;
    }

    /**
     * Map service status to TMF639 resource states - uses the first slice service status.
     */
    @Override
    @JsonIgnore
    public void mapStatusToResourceStates(LogicalResource resource) {
        if (sliceServices != null && !sliceServices.isEmpty()) {
            SliceService firstService = sliceServices.get(0);
@@ -85,7 +79,7 @@ public class NetworkSliceServices implements LogicalResourceMappable {
                ServiceStatus status = firstService.getStatus();

                // Map administrative state
                String adminState = status.getAdminState();
                String adminState = status.getAdminStatus();
                if (adminState != null && adminState.equals("admin-up")) {
                    resource.setAdministrativeState(ResourceAdministrativeStateType.UNLOCKED);
                } else if (adminState != null && adminState.equals("admin-down")) {
@@ -93,7 +87,7 @@ public class NetworkSliceServices implements LogicalResourceMappable {
                }

                // Map operational state
                String operState = status.getOperState();
                String operState = status.getOperStatus();
                if (operState != null && operState.equals("operational")) {
                    resource.setOperationalState(ResourceOperationalStateType.ENABLE);
                } else if (operState != null && operState.equals("non-operational")) {
+139 −248

File changed.

Preview size limit exceeded, changes collapsed.

Loading