Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
cd34616
ETSI MEC gap analysis
alebellu Oct 21, 2025
8401045
feat(mec-010-2): add comprehensive implementation plan for MEC 010-2 …
alebellu Oct 21, 2025
49eabcf
Add feasibility study and implementation plan for Nuvla as MEC Orches…
alebellu Oct 21, 2025
2363ef4
MEC-003 Implementation Phase 1
alebellu Oct 21, 2025
87bc9e8
feat(mepm): add MEC Platform Manager resource and lifecycle tests
alebellu Oct 21, 2025
e42fb40
Implement Mm5 Interface and MEPM Resource Integration
alebellu Oct 21, 2025
5d8e136
feat(mec-003): add Phase 2 completion report with MEPM resource and M…
alebellu Oct 21, 2025
ad35355
feat(mm5): add integration tests and mock MEPM server for Mm5 interface
alebellu Oct 21, 2025
d0af9d3
feat(mec): add end-to-end orchestration tests for MEC MEO functionality
alebellu Oct 21, 2025
3106dbb
Add Mm5 API Reference and Quick Start Guide for MEC MEO Implementation
alebellu Oct 21, 2025
9419b69
Implement MEC 010-2 Application Lifecycle Management API
alebellu Oct 21, 2025
266cbf9
feat(mec): implement lifecycle operation handler and tests for app in…
alebellu Oct 21, 2025
eb90233
fix(mm5): update URL paths in resource queries to include mm5 prefix
alebellu Oct 21, 2025
883f848
feat(lifecycle): implement job-based operation tracking and state syn…
alebellu Oct 21, 2025
2f256b6
Add MEC 010-2 Notification Dispatcher and related tests
alebellu Oct 21, 2025
e879668
docs: update MEC 010-2 implementation progress to reflect completion …
alebellu Oct 21, 2025
a7d329e
docs: add MEC 010-2 implementation summary detailing project status, …
alebellu Oct 21, 2025
619984b
Implement MEC 010-2 Query Filters and Pagination
alebellu Oct 21, 2025
1c448a8
feat(error-handler): implement RFC 7807 ProblemDetails error handling…
alebellu Oct 21, 2025
c6e9d92
Add MEC 010-2 Application Lifecycle Management API specification
alebellu Oct 21, 2025
fd45df0
feat(tests): add integration tests for MEC 010-2 Application Lifecycl…
alebellu Oct 21, 2025
bcfe10b
feat(docs): add MEC 010-2 Standards Compliance Matrix detailing imple…
alebellu Oct 21, 2025
b5384fd
feat(docs): update MEC 010-2 implementation summary and progress to r…
alebellu Oct 21, 2025
92e6fb6
Add presentation slides for Nuvla MEC Orchestrator: Standards Complia…
alebellu Oct 23, 2025
d49300f
Refactor documentation and code references from Mm5 to Mm3 interface
alebellu Oct 24, 2025
89e659e
Implement ETSI MEC 010-2 Mm1 Application Package Management
alebellu Oct 24, 2025
b96e083
3GPP compliance study
alebellu Oct 24, 2025
4494c74
Add ETSI MEC compliance presentation and gap analysis documentation
alebellu Nov 26, 2025
3f2d031
Enhance compliance study with detailed mapping of MEC orchestrator re…
alebellu Nov 27, 2025
e31d5f1
Clarify MEC compliance document by updating relevant specifications f…
alebellu Nov 27, 2025
53d56fe
Add assessment of compliance with 3GPP
alebellu Dec 4, 2025
0a43452
Add compliance assessment for ETSI GS MEC 037 and create presentation…
alebellu Jan 22, 2026
aac9964
Add detailed documentation for MEO's/MEAO's application package and l…
alebellu Mar 17, 2026
ff2e33c
Add new documentation and validation strategy for Nuvla's compliance …
alebellu Apr 17, 2026
52ce8f0
Remove pre-release compliance deliverables from git
alebellu Apr 17, 2026
651bb10
Refine validation strategy documentation for Nuvla's compliance with …
alebellu Apr 17, 2026
f724159
Add Nuvla MEC engineering backlog, gap closure plan, and validation t…
alebellu Apr 29, 2026
e31e5ea
Enhance Nuvla MEC engineering backlog and gap closure plan
alebellu Apr 29, 2026
db35d1a
ETSI compliance WS1: freeze MEC baseline and normalize Mm3 references
alebellu Apr 29, 2026
efca7cc
ETSI compliance WS2: back MEC app lifecycle with Nuvla deployments an…
alebellu Apr 29, 2026
203baee
ETSI compliance WS3: resolve MEPM targets and execute MEC lifecycle o…
alebellu Apr 29, 2026
888bb5a
ETSI compliance WS4: complete MEC Mm1 package content lifecycle
alebellu Apr 30, 2026
a28b910
ETSI compliance WS5: dispatch MEC notifications on job finalization
alebellu May 4, 2026
25857ed
Enhance MEC resource management and validation
alebellu May 7, 2026
d3a84ec
Implement MEC job attributes and error handling improvements
alebellu May 8, 2026
8b07115
Refactor MEC API to align with ETSI GS MEC 010-2 v4.1.1
alebellu May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ downloads/*

.clj-kondo
test-reports/
docs/5g-emerge/ETSI-MEC/submitted/5G-EMERGE_P2_TN_2.3.2\ Compliance_of_the_orchestration_software\ v06-pre-release.md
docs/5g-emerge/ETSI-MEC/submitted/5G-EMERGE_P2_TN_2.3.2\ Compliance_of_the_orchestration_software\ v06-pre-release.pdf
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ This repository contains the code and configuration for the Nuvla API
server, packaged as a Docker container. The API is inspired by the
CIMI specification from DMTF.

## MEC Orchestrator (MEO) Positioning

The Nuvla API Server functions as a **MEC Orchestrator (MEO)** as defined in
[ETSI GS MEC 003](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/003/).
It provides system-level orchestration for edge applications across distributed
Multi-access Edge Computing (MEC) infrastructure.

**Key MEC Capabilities:**
- **System Orchestration** - Multi-host application lifecycle management
- **Application Package Management** - On-boarding, validation, and distribution
- **Resource Management** - Placement decisions and infrastructure coordination
- **Standard Interfaces** - MEC-compliant APIs (Mm2, Mm3, Mm5, Mm9)

For detailed MEC architecture mapping and implementation documentation, see:
- [MEC 003 Architectural Mapping](docs/5g-emerge/MEC-003-architectural-mapping.md)
- [MEC Terminology Guide](docs/5g-emerge/MEC-terminology-guide.md)
- [MEC Implementation Plans](docs/5g-emerge/)

## Artifacts

- `nuvla/api:<version>`. A Docker container that can be obtained from
Expand Down
3 changes: 2 additions & 1 deletion code/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,10 @@
[org.clojars.konstan/kinsky-test-jar ~kinsky-version]]}

:test {:dependencies [[me.raynes/fs "1.4.6"]
[org.testcontainers/testcontainers "1.20.4"]
[org.testcontainers/testcontainers "1.21.4"]
[peridot "0.5.4"]
[clj-test-containers "0.7.4"]
[ring/ring-jetty-adapter "1.12.2"]
[org.clojure/test.check "1.1.1"]
[com.cemerick/url "0.1.1"]
[org.clojars.konstan/kinsky-test-jar ~kinsky-version]
Expand Down
4 changes: 3 additions & 1 deletion code/src/com/sixsq/nuvla/server/app/routes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[com.sixsq.nuvla.server.resources.common.crud :as crud]
[com.sixsq.nuvla.server.resources.common.dynamic-load :as dyn]
[com.sixsq.nuvla.server.resources.common.event-context :as ec]
[com.sixsq.nuvla.server.resources.mec :as mec]
[com.sixsq.nuvla.server.util.response :as r]
[compojure.core :refer [ANY DELETE GET let-routes OPTIONS PATCH POST PUT routes]]
[compojure.route :as route]
Expand Down Expand Up @@ -87,6 +88,7 @@
classpath."
[]
(apply routes (doall (concat [cors-preflight-check-route
(route/resources (str p/service-context "static"))]
(route/resources (str p/service-context "static"))
mec/routes]
(dyn/resource-routes)
final-routes))))
2 changes: 2 additions & 0 deletions code/src/com/sixsq/nuvla/server/app/server.clj
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,5 @@
(reset! server-stop-fn nil)
(println "stopped"))
(println "Server not started")))


18 changes: 15 additions & 3 deletions code/src/com/sixsq/nuvla/server/resources/common/dynamic_load.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@
(not (.contains ns-name "test"))
sym)))

(defn mec-resource-link?
"Returns the namespace symbol for nested MEC resource collections that should
be exposed in the cloud-entry-point collections list."
[sym]
(let [ns-name (name sym)]
(and
(re-matches #"^com\.sixsq\.nuvla\.server\.resources\.mec\.[\w-]+$" ns-name)
(not (.contains ns-name "test"))
sym)))


(defn resource-namespaces
"Returns sequence of the resource namespaces on the classpath."
Expand All @@ -29,8 +39,9 @@
keyword associated with the relative URL for the resource. Function returns
nil if 'resource-type' cannot be found in the resource."
[resource-ns]
(when-let [vtag (ns-util/resolve "resource-type" resource-ns)]
[(keyword (deref vtag)) {:href (deref vtag)}]))
(when (ns-util/resolve "query-impl" resource-ns)
(when-let [vtag (ns-util/resolve "resource-type" resource-ns)]
[(keyword (deref vtag)) {:href (deref vtag)}])))


(def ^:private initialize-data-fns (atom []))
Expand Down Expand Up @@ -70,7 +81,8 @@
"Returns a lazy sequence of all of the resource links for resources
discovered on the classpath."
[]
(->> (resource-namespaces)
(->> (concat (resource-namespaces)
(ns-util/load-filtered-namespaces mec-resource-link?))
(map get-resource-link)
(remove nil?)))

Expand Down
67 changes: 54 additions & 13 deletions code/src/com/sixsq/nuvla/server/resources/deployment.clj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ a container orchestration engine.
[com.sixsq.nuvla.server.resources.deployment.utils :as utils]
[com.sixsq.nuvla.server.resources.job.interface :as job-interface]
[com.sixsq.nuvla.server.resources.job.utils :as job-utils]
[com.sixsq.nuvla.server.resources.mec.job-notifications :as mec-job-notifications]
[com.sixsq.nuvla.server.resources.module.utils :as module-utils]
[com.sixsq.nuvla.server.resources.nuvlabox.status-utils :as nuvlabox-status-utils]
[com.sixsq.nuvla.server.resources.resource-metadata :as md]
Expand Down Expand Up @@ -308,6 +309,8 @@ a container orchestration engine.
user-rights? (get-in deployment [:module :content :requires-user-rights])
data? (some? (:data deployment))
execution-mode (:execution-mode deployment)
job-attrs (get-in request [:body :job-attrs])
mec-operate? (= "OPERATE" (:mec-operation-type job-attrs))
state (if (= execution-mode "pull") "PENDING" "STARTING")
new-deployment (-> deployment
(assoc :state state)
Expand All @@ -318,18 +321,25 @@ a container orchestration engine.
user-rights?)
(auth/current-authentication request))))
(edit-deployment request))]
(when stopped?
;; A stopped MEC deployment must keep its persisted southbound MM3 app instance id
;; so the subsequent OPERATE->STARTED job can act on the same instance.
(when (and stopped? (not mec-operate?))
(utils/delete-child-resources "deployment-parameter" id))
(utils/create-job new-deployment request "start_deployment" execution-mode))
(utils/create-job new-deployment request "start_deployment" execution-mode
:job-attrs job-attrs))
(catch Exception e
(or (ex-data e) (throw e)))))

(defmethod crud/do-action [resource-type "stop"]
[{{uuid :uuid} :params body :body :as request}]
(try
(let [deployment (-> (str resource-type "/" uuid)
(crud/retrieve-by-id-as-admin)
(u/throw-cannot-do-action-invalid-state utils/can-stop? "stop"))
(let [deployment-id (str resource-type "/" uuid)
job-attrs (:job-attrs body)
mec-terminate? (= "TERMINATE" (:mec-operation-type job-attrs))
deployment0 (crud/retrieve-by-id-as-admin deployment-id)
deployment (if (and mec-terminate? (= "STOPPED" (:state deployment0)))
deployment0
(u/throw-cannot-do-action-invalid-state deployment0 utils/can-stop? "stop"))
execution-mode (:execution-mode deployment)
params (cond-> {}
(:delete body) (assoc :delete true)
Expand All @@ -338,7 +348,9 @@ a container orchestration engine.
(-> deployment
(assoc :state "STOPPING")
(edit-deployment request)
(utils/create-job request "stop_deployment" execution-mode :payload params)))
(utils/create-job request "stop_deployment" execution-mode
:payload params
:job-attrs job-attrs)))
(catch Exception e
(or (ex-data e) (throw e)))))

Expand Down Expand Up @@ -441,19 +453,48 @@ a container orchestration engine.
(utils/get-context resource false))

(defmethod job-interface/on-cancel ["deployment" "start_deployment"]
[resource]
(utils/on-cancel resource))
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-cancel ["deployment" "update_deployment"]
[resource]
(utils/on-cancel resource))
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-cancel ["deployment" "stop_deployment"]
[resource]
(utils/on-cancel resource))
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-timeout ["deployment" "start_deployment"]
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-timeout ["deployment" "update_deployment"]
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-timeout ["deployment" "stop_deployment"]
[job]
(let [response (utils/on-cancel job)]
(mec-job-notifications/dispatch-mec-job-finalization! job)
response))

(defmethod job-interface/on-done ["deployment" "start_deployment"]
[job]
(mec-job-notifications/dispatch-mec-job-finalization! job))

(defmethod job-interface/on-done ["deployment" "stop_deployment"]
[{:keys [target-resource state payload] :as _job}]
[{:keys [target-resource state payload] :as job}]
(mec-job-notifications/dispatch-mec-job-finalization! job)
(when-let [deployment (and (= state job-utils/state-success)
(-> payload j/read-value (get "delete" false))
(some-> target-resource :href crud/retrieve-by-id-as-admin))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@

(defn create-job
[{:keys [id nuvlabox deployment-set] :as resource} request action execution-mode
& {:keys [payload]}]
& {:keys [payload job-attrs]}]
(a/throw-cannot-manage resource request)
(let [active-claim (auth/current-active-claim request)
low-priority (get-in request [:body :low-priority] false)
Expand All @@ -131,7 +131,8 @@
:parent-job parent-job
:priority (if low-priority 999 50)
:execution-mode execution-mode
:payload (when (seq payload) (j/write-value-as-string payload)))
:payload (when (seq payload) (j/write-value-as-string payload))
:job-attrs job-attrs)
job-msg (str action " " id " with async " job-id)]
(when (not= job-status 201)
(throw (r/ex-response
Expand Down
5 changes: 3 additions & 2 deletions code/src/com/sixsq/nuvla/server/resources/job/utils.clj
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
(defn create-job
[target-resource action acl created-by & {:keys [priority affected-resources
execution-mode payload
parent-job]}]
parent-job job-attrs]}]
(let [job-map (cond-> {:action action
:target-resource {:href target-resource}
:acl acl
Expand All @@ -135,7 +135,8 @@
parent-job (assoc :parent-job parent-job)
affected-resources (assoc :affected-resources affected-resources)
execution-mode (assoc :execution-mode execution-mode)
payload (assoc :payload payload))
payload (assoc :payload payload)
(seq job-attrs) (merge job-attrs))
create-request {:params {:resource-name "job"}
:body job-map
:nuvla/authn auth/internal-identity}]
Expand Down
Loading
Loading