diff --git a/examples/demo10/MEC/Get_App_Instances.go b/examples/demo10/MEC/Get_App_Instances.go new file mode 100644 index 0000000000000000000000000000000000000000..5a3f7dc79d166ce9e287082e804dc77179cc1edf --- /dev/null +++ b/examples/demo10/MEC/Get_App_Instances.go @@ -0,0 +1,35 @@ +package mec + +import ( + "fmt" + "net/http" + model "estimed_demo/Model" + utils "estimed_demo/utils" + "io" + "encoding/json" +) + +// Get MEC APP instances +func GetAppInstances(url string) ([]model.AppInstanceID, error) { + resp, err := utils.SendMECRequest("GET", url, nil) + if err != nil { + return nil, fmt.Errorf("failed to get MEC app instances: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to get MEC App Instance ID: received status code %d", resp.StatusCode) + } + + // From the response body, extract all App Instance IDs + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %v", err) + } + //log.Println("Response body:", string(body)) + + var allAppInstances []model.AppInstanceID + if err := json.Unmarshal(body, &allAppInstances); err != nil { + return nil, fmt.Errorf("failed to unmarshal response body: %v", err) + } + return allAppInstances, nil +} \ No newline at end of file diff --git a/examples/demo10/MEC/ams.go b/examples/demo10/MEC/ams.go new file mode 100644 index 0000000000000000000000000000000000000000..d12de37a36d8af0b0298c57e500b10cdc0552145 --- /dev/null +++ b/examples/demo10/MEC/ams.go @@ -0,0 +1,337 @@ +package mec + +import ( + "encoding/json" + model "estimed_demo/Model" + utils "estimed_demo/utils" + "fmt" + "log" + "net/http" + "regexp" +) + +// Create MEC AMS service registration +func CreateAMSRegistration(url string, app_instance_id string, device_info *model.RegistrationInfoDeviceInformation) (*model.RegistrationInfo, error) { + payload := &model.RegistrationInfo{} + if device_info != nil { + payload = &model.RegistrationInfo{ + ServiceConsumerId: &model.RegistrationInfoServiceConsumerId{ + AppInstanceId: app_instance_id, + }, + DeviceInformation: []model.RegistrationInfoDeviceInformation{*device_info}, + } + } else { + payload = &model.RegistrationInfo{ + ServiceConsumerId: &model.RegistrationInfoServiceConsumerId{ + AppInstanceId: app_instance_id, + }, + } + } + resp, err := utils.SendMECRequest("POST", url, payload) + if err != nil { + return nil, fmt.Errorf("failed to create AMS registration: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusCreated { + return nil, fmt.Errorf("failed to create AMS registration: received status code %d", resp.StatusCode) + } + + var registrationInfo model.RegistrationInfo + if err := json.NewDecoder(resp.Body).Decode(®istrationInfo); err != nil { + return nil, fmt.Errorf("failed to decode AMS registration response: %v", err) + } + + return ®istrationInfo, nil +} + +// Create MEC AMS subscription + +func CreateAMSSubscription(url string, app_instance_id string, callbackURL string, associateId *model.AssociateId) (*model.InlineSubscription, error) { + payload := &model.InlineSubscription{} + if associateId != nil { + payload = &model.InlineSubscription{ + SubscriptionType: "MobilityProcedureSubscription", + FilterCriteria: &model.MobilityProcedureSubscriptionFilterCriteria{ + AppInstanceId: app_instance_id, + AssociateId: []model.AssociateId{*associateId}, + }, + CallbackReference: callbackURL, + } + } else { + payload = &model.InlineSubscription{ + SubscriptionType: "MobilityProcedureSubscription", + FilterCriteria: &model.MobilityProcedureSubscriptionFilterCriteria{ + AppInstanceId: app_instance_id, + }, + // TODO: Update callback reference URL as needed + CallbackReference: callbackURL, + } + } + + resp, err := utils.SendMECRequest("POST", url, payload) + if err != nil { + return nil, fmt.Errorf("failed to create AMS subscription: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusCreated { + return nil, fmt.Errorf("failed to create AMS subscription: received status code %d", resp.StatusCode) + } + + var subscriptionInfo model.InlineSubscription + if err := json.NewDecoder(resp.Body).Decode(&subscriptionInfo); err != nil { + return nil, fmt.Errorf("failed to decode AMS subscription response: %v", err) + } + + return &subscriptionInfo, nil +} + +// AMSNotificationHandler handles incoming AMS notifications +func AMSNotificationHandler(w http.ResponseWriter, r *http.Request) (string, error) { + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + return "", fmt.Errorf("invalid request method") + } + + var notification map[string]interface{} + err := json.NewDecoder(r.Body).Decode(¬ification) + if err != nil { + http.Error(w, "Failed to decode request body", http.StatusBadRequest) + return "", fmt.Errorf("failed to decode request body: %w", err) + } + log.Printf("Received AMS notification: %+v", notification) + w.WriteHeader(http.StatusNoContent) + // Extract target app instance ID from the notification + var targetAppInstanceID string + if targetAppInfo, ok := notification["targetAppInfo"].(map[string]interface{}); ok { + if appInstanceID, ok := targetAppInfo["appInstanceId"].(string); ok { + targetAppInstanceID = appInstanceID + log.Printf("Target App Instance ID: %s", targetAppInstanceID) + } + } + if targetAppInstanceID == "" { + log.Println("Target App Instance ID not found in notification") + } + return targetAppInstanceID, nil +} + +func RegistrationAndSubscriptionHandler(matchingAppInstances []model.AppInstanceID, platformURL string, + sandbox_name string, callbackURL string, currentAppInstanceId *string, + deviceInfo *model.RegistrationInfoDeviceInformation, associateId *model.AssociateId) ([]map[string]model.PlatformInfo, error) { + var platformDetails []map[string]model.PlatformInfo + + for i, appInstance := range matchingAppInstances { + log.Printf("Creating AMS registration for App Instance ID: %s, Name: %s", appInstance.ID, appInstance.Name) + amsURL := fmt.Sprintf("%s/%s/mep1/amsi/v1/app_mobility_services", platformURL, sandbox_name) + var resp *model.RegistrationInfo + var err error + if i == 0 { + *currentAppInstanceId = appInstance.ID + resp, err = CreateAMSRegistration(amsURL, appInstance.ID, deviceInfo) + if err != nil { + return nil, fmt.Errorf("failed to create AMS registration: %v", err) + } else { + log.Printf("AMS registration created successfully: %v", resp) + } + } else { + resp, err = CreateAMSRegistration(amsURL, appInstance.ID, nil) + if err != nil { + return nil, fmt.Errorf("failed to create AMS registration: %v", err) + } else { + log.Printf("AMS registration created successfully: %v", resp) + } + } + amsSubURL := fmt.Sprintf("%s/%s/mep1/amsi/v1/subscriptions", platformURL, sandbox_name) + sub_resp := &model.InlineSubscription{} + if i == 0 { + sub_resp, err = CreateAMSSubscription(amsSubURL, appInstance.ID, callbackURL, associateId) + if err != nil { + return nil, fmt.Errorf("failed to create AMS subscription: %v", err) + } else { + log.Printf("AMS subscription created successfully: %v", sub_resp) + } + } else { + sub_resp, err = CreateAMSSubscription(amsSubURL, appInstance.ID, callbackURL, nil) + if err != nil { + return nil, fmt.Errorf("failed to create AMS subscription: %v", err) + } else { + log.Printf("AMS subscription created successfully: %v", sub_resp) + } + } + // Extract subscription ID from href using regex + subID := "" + if sub_resp.Links.Self.Href != "" { + re := regexp.MustCompile(`subscriptions/(.*)`) + matches := re.FindStringSubmatch(sub_resp.Links.Self.Href) + if len(matches) > 1 { + subID = matches[1] + } + } + platformInfo := model.PlatformInfo{ + AmsServiceID: resp.AppMobilityServiceId, + AppInstanceID: appInstance.ID, + AmsSubscriptionID: subID, + NodeName: appInstance.NodeName, + } + platformDetails = append(platformDetails, map[string]model.PlatformInfo{ + appInstance.ID: platformInfo, + }) + } + + return platformDetails, nil +} + +// TODO: Complete the function to update AMS registration info +func PutAMSRegistrationInfo(url string, targetappinstance string, platformDetails []map[string]model.PlatformInfo, + current_app_instance *string, associateID *model.AssociateId) error { + if len(platformDetails) == 0 { + return fmt.Errorf("platformDetails is empty") + } + if targetappinstance == "" { + log.Println("Initializing AMS registration info...") + } + + // Find the PlatformInfo for the current app instance by iterating through the slice + var currentPlatformInfo *model.PlatformInfo + for _, detail := range platformDetails { + if info, exists := detail[*current_app_instance]; exists { + currentPlatformInfo = &info + break // Found it, no need to continue + } + } + payload := model.RegistrationInfo{ + AppMobilityServiceId: currentPlatformInfo.AmsServiceID, + DeviceInformation: []model.RegistrationInfoDeviceInformation{ + { + AssociateId: associateID, + AppMobilityServiceLevel: &[]model.AppMobilityServiceLevel{"APP_MOBILITY_WITHOUT_CONFIRMATION"}[0], + ContextTransferState: &[]model.ContextTransferState{"USER_CONTEXT_TRANSFER_COMPLETED"}[0], + }, + }, + ServiceConsumerId: &model.RegistrationInfoServiceConsumerId{ + AppInstanceId: *current_app_instance, + }, + } + req_url := fmt.Sprintf("%s/%s", url, currentPlatformInfo.AmsServiceID) + resp, err := utils.SendMECRequest("PUT", req_url, payload) + if err != nil { + return fmt.Errorf("failed to update AMS registration info: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to update AMS registration info: received status code %d", resp.StatusCode) + } + log.Println("AMS registration info updated successfully") + + // find the PlatformInfo for the target app instance + var targetPlatformInfo *model.PlatformInfo + for _, detail := range platformDetails { + if info, exists := detail[targetappinstance]; exists { + targetPlatformInfo = &info + break // Found it, no need to continue + } + } + payload = model.RegistrationInfo{ + AppMobilityServiceId: targetPlatformInfo.AmsServiceID, + DeviceInformation: []model.RegistrationInfoDeviceInformation{ + { + AssociateId: associateID, + AppMobilityServiceLevel: &[]model.AppMobilityServiceLevel{"APP_MOBILITY_WITHOUT_CONFIRMATION"}[0], + ContextTransferState: &[]model.ContextTransferState{"NOT_TRANSFERRED"}[0], + }, + }, + ServiceConsumerId: &model.RegistrationInfoServiceConsumerId{ + AppInstanceId: targetappinstance, + }, + } + req_url = fmt.Sprintf("%s/%s", url, targetPlatformInfo.AmsServiceID) + resp, err = utils.SendMECRequest("PUT", req_url, payload) + if err != nil { + return fmt.Errorf("failed to update AMS registration info for target app instance: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to update AMS registration info for target app instance: received status code %d", resp.StatusCode) + } + + log.Println("AMS registration info for target app instance updated successfully") + + return nil +} + +func PUTAMSSubscriptionInfo(url string, targetappinstance string, platformDetails []map[string]model.PlatformInfo, + current_app_instance *string, call_back_url string, associateid *model.AssociateId) error { + if len(platformDetails) == 0 { + return fmt.Errorf("platformDetails is empty") + } + if targetappinstance == "" { + log.Println("Initializing AMS subscription info...") + } + + // Find the PlatformInfo for the current app instance by iterating through the slice + var currentPlatformInfo *model.PlatformInfo + for _, detail := range platformDetails { + if info, exists := detail[*current_app_instance]; exists { + currentPlatformInfo = &info + break // Found it, no need to continue + } + } + + payload := model.InlineSubscription{ + SubscriptionType: "MobilityProcedureSubscription", + Links: &model.MobilityProcedureSubscriptionLinks{ + Self: &model.LinkType{ + Href: fmt.Sprintf("%s/%s", url, currentPlatformInfo.AmsSubscriptionID), + }, + }, + CallbackReference: call_back_url, + FilterCriteria: &model.MobilityProcedureSubscriptionFilterCriteria{ + AppInstanceId: *current_app_instance, + AssociateId: []model.AssociateId{*associateid}, + MobilityStatus: []model.MobilityStatus{"INTERHOST_MOVEOUT_COMPLETED"}, + }, + } + resp, err := utils.SendMECRequest("PUT", fmt.Sprintf("%s/%s", url, currentPlatformInfo.AmsSubscriptionID), payload) + if err != nil { + return fmt.Errorf("failed to update AMS subscription info: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to update AMS subscription info: received status code %d", resp.StatusCode) + } + log.Println("AMS subscription info updated successfully") + + // find the PlatformInfo for the target app instance + var targetPlatformInfo *model.PlatformInfo + for _, detail := range platformDetails { + if info, exists := detail[targetappinstance]; exists { + targetPlatformInfo = &info + break // Found it, no need to continue + } + } + + payload = model.InlineSubscription{ + SubscriptionType: "MobilityProcedureSubscription", + Links: &model.MobilityProcedureSubscriptionLinks{ + Self: &model.LinkType{ + Href: fmt.Sprintf("%s/%s", url, targetPlatformInfo.AmsSubscriptionID), + }, + }, + CallbackReference: call_back_url, + FilterCriteria: &model.MobilityProcedureSubscriptionFilterCriteria{ + AppInstanceId: targetappinstance, + AssociateId: []model.AssociateId{*associateid}, + MobilityStatus: []model.MobilityStatus{"INTERHOST_MOVEOUT_TRIGGERED"}, + }, + } + resp, err = utils.SendMECRequest("PUT", fmt.Sprintf("%s/%s", url, targetPlatformInfo.AmsSubscriptionID), payload) + if err != nil { + return fmt.Errorf("failed to update AMS subscription info for target app instance: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to update AMS subscription info for target app instance: received status code %d", resp.StatusCode) + } + + log.Println("AMS subscription info for target app instance updated successfully") + return nil +} diff --git a/examples/demo10/MEC/iot_api.go b/examples/demo10/MEC/iot_api.go new file mode 100644 index 0000000000000000000000000000000000000000..f643a703b3ec16b8b8a5b46cb24cff1446eb80e7 --- /dev/null +++ b/examples/demo10/MEC/iot_api.go @@ -0,0 +1,26 @@ +package mec + +import ( + "encoding/json" + utils "estimed_demo/utils" + "fmt" + "net/http" +) + +// Fetch for platform info +func GETIotPlatformInfo(url string) ([]map[string]interface{}, error) { + resp, err := utils.SendMECRequest("GET", url, nil) + if err != nil { + return nil, fmt.Errorf("failed to get IoT platform info: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to get IoT platform info: received status code %d", resp.StatusCode) + } + + var platformInfo []map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&platformInfo); err != nil { + return nil, fmt.Errorf("failed to decode IoT platform info: %v", err) + } + return platformInfo, nil +} \ No newline at end of file diff --git a/examples/demo10/MEC/match_for_target_app_instance.go b/examples/demo10/MEC/match_for_target_app_instance.go new file mode 100644 index 0000000000000000000000000000000000000000..76576432f721d817064aed876a63a3ace446db14 --- /dev/null +++ b/examples/demo10/MEC/match_for_target_app_instance.go @@ -0,0 +1,33 @@ +package mec + +import ( + model "estimed_demo/Model" + "fmt" + "regexp" +) + +// Match for target App Instance ID +func MatchForTargetAppInstance(allAppInstances []model.AppInstanceID, cse_name string) ([]model.AppInstanceID, error) { + // Compile regex for cse_name once + reCSE, err := regexp.Compile(cse_name) + if err != nil { + return nil, fmt.Errorf("invalid regex for cse_name: %v", err) + } + var matchingAppInstances []model.AppInstanceID + for _, appInstance := range allAppInstances { + // If name matches cse_name using compiled regex, store it in our array + if reCSE.MatchString(appInstance.Name) { + matchingAppInstance := model.AppInstanceID{ + ID: appInstance.ID, + Name: appInstance.Name, + NodeName: appInstance.NodeName, + } + matchingAppInstances = append(matchingAppInstances, matchingAppInstance) + } + } + + if len(matchingAppInstances) == 0 { + return nil, fmt.Errorf("MEC App Instance with name %s not found", cse_name) + } + return matchingAppInstances, nil +} diff --git a/examples/demo10/Model/app_instance_id.go b/examples/demo10/Model/app_instance_id.go new file mode 100644 index 0000000000000000000000000000000000000000..713464f213f0ce9b3f686ad73bc3190b585d0c2b --- /dev/null +++ b/examples/demo10/Model/app_instance_id.go @@ -0,0 +1,7 @@ +package model + +type AppInstanceID struct { + ID string `json:"id"` + Name string `json:"name"` + NodeName string `json:"nodeName"` +} \ No newline at end of file diff --git a/examples/demo10/Model/model_adjacent_app_info_notification.go b/examples/demo10/Model/model_adjacent_app_info_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..2e50f57819883f614dba527285d6a1e1500517ad --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_info_notification.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AdjacentAppInfoNotification struct { + // Shall be set to \"AdjacentAppInfoNotification\". + NotificationType string `json:"notificationType"` + TimeStamp *TimeStamp `json:"timeStamp,omitempty"` + // 1 to N identifiers to associate the information for specific + AssociateId []AssociateId `json:"associateId,omitempty"` + AdjacentAppInfo []AdjacentAppInfoNotificationAdjacentAppInfo `json:"adjacentAppInfo,omitempty"` + Links *Link `json:"_links"` +} diff --git a/examples/demo10/Model/model_adjacent_app_info_notification_adjacent_app_info.go b/examples/demo10/Model/model_adjacent_app_info_notification_adjacent_app_info.go new file mode 100644 index 0000000000000000000000000000000000000000..c3e710bdddf2644cc78baebbcc26626066af6810 --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_info_notification_adjacent_app_info.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AdjacentAppInfoNotificationAdjacentAppInfo struct { + // Identifier of the adjacent application instance. + AppInstanceId string `json:"appInstanceId"` + // If present, it represents the communication interface(s) information of the application instance. + CommInterface []CommunicationInterface `json:"commInterface"` +} diff --git a/examples/demo10/Model/model_adjacent_app_info_subscription.go b/examples/demo10/Model/model_adjacent_app_info_subscription.go new file mode 100644 index 0000000000000000000000000000000000000000..9c502c972ae637a825cdab3d11a7758d5cea0c09 --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_info_subscription.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AdjacentAppInfoSubscription struct { + Links *AdjacentAppInfoSubscriptionLinks `json:"_links,omitempty"` + // URI selected by the service consumer to receive notifications on the subscribed Application Mobility Service. This shall be included both in the request and in response. + CallbackReference string `json:"callbackReference"` + // Shall be set to TRUE by the service consumer to request a test notification via HTTP on the callbackReference URI, specified in ETSI GS MEC 009, as described in clause 6.12a. + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + WebsockNotifConfig *WebsockNotifConfig `json:"websockNotifConfig,omitempty"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline,omitempty"` + FilterCriteria *AdjacentAppInfoSubscriptionFilterCriteria `json:"filterCriteria"` + SubscriptionType *SubscriptionType `json:"subscriptionType"` +} diff --git a/examples/demo10/Model/model_adjacent_app_info_subscription_filter_criteria.go b/examples/demo10/Model/model_adjacent_app_info_subscription_filter_criteria.go new file mode 100644 index 0000000000000000000000000000000000000000..63c6ff0906969180f9722fab38899c600c183e96 --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_info_subscription_filter_criteria.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// List of filtering criteria for the subscription. Any filtering criteria from below, which is included in the request, shall also be included in the response. +type AdjacentAppInfoSubscriptionFilterCriteria struct { + AppInstanceId string `json:"appInstanceId,omitempty"` +} diff --git a/examples/demo10/Model/model_adjacent_app_info_subscription_links.go b/examples/demo10/Model/model_adjacent_app_info_subscription_links.go new file mode 100644 index 0000000000000000000000000000000000000000..6c0a382969c2a83cb09b8f1d8dd645e1dff96b19 --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_info_subscription_links.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// Hyperlink related to the resource. This shall be only included in the HTTP responses and in HTTP PUT requests. +type AdjacentAppInfoSubscriptionLinks struct { + Self *LinkType `json:"self"` +} diff --git a/examples/demo10/Model/model_adjacent_app_instance_info.go b/examples/demo10/Model/model_adjacent_app_instance_info.go new file mode 100644 index 0000000000000000000000000000000000000000..13366bad1f5d0d0280a2b7a763a3528ab888e3dc --- /dev/null +++ b/examples/demo10/Model/model_adjacent_app_instance_info.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AdjacentAppInstanceInfo struct { + // Identifier of the application descriptor. + AppDId string `json:"appDId"` + // It specifies the communication interface of application instance. + AppInstanceCommLink []CommunicationInterface `json:"appInstanceCommLink"` + // Identifier of the application instance. + AppInstanceId string `json:"appInstanceId"` + MecHostInformation *MecHostInformation `json:"mecHostInformation,omitempty"` + // dentifier of the application instance that registers to the AMS, which is instantiated from the application descriptor identified by the attribute \"appDId\". + RegisteredInstanceId string `json:"registeredInstanceId,omitempty"` +} diff --git a/examples/demo10/Model/model_app_mobility_service_level.go b/examples/demo10/Model/model_app_mobility_service_level.go new file mode 100644 index 0000000000000000000000000000000000000000..12e07a763acd017bb506886c44828854c8b2f352 --- /dev/null +++ b/examples/demo10/Model/model_app_mobility_service_level.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// AppMobilityServiceLevel : This attribute provides an option for the application instance (server) to communicate with the application client before relocating this application instance to another MEC host. +type AppMobilityServiceLevel string + +// List of AppMobilityServiceLevel +const ( + NOT_ALLOWED_AppMobilityServiceLevel AppMobilityServiceLevel = "APP_MOBILITY_NOT_ALLOWED" + WITH_CONFIRMATION_AppMobilityServiceLevel AppMobilityServiceLevel = "APP_MOBILITY_WITH_CONFIRMATION" + WITHOUT_CONFIRMATION_AppMobilityServiceLevel AppMobilityServiceLevel = "APP_MOBILITY_WITHOUT_CONFIRMATION" +) diff --git a/examples/demo10/Model/model_app_termination_notification.go b/examples/demo10/Model/model_app_termination_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..c6e436e10646bec60e6ee07000a2303071f020df --- /dev/null +++ b/examples/demo10/Model/model_app_termination_notification.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// This type represents the information that the MEC platform notifies the subscribed application instance about the corresponding application instance termination/stop. +type AppTerminationNotification struct { + // Shall be set to AppTerminationNotification. + NotificationType string `json:"notificationType"` + OperationAction *OperationActionType `json:"operationAction"` + // Maximum timeout value in seconds for graceful termination or graceful stop of an application instance. + MaxGracefulTimeout int32 `json:"maxGracefulTimeout"` + Links *AppTerminationNotificationLinks `json:"_links"` +} diff --git a/examples/demo10/Model/model_app_termination_notification__links.go b/examples/demo10/Model/model_app_termination_notification__links.go new file mode 100644 index 0000000000000000000000000000000000000000..74d1af76fdc39bf9ab6d9ca6fd570c342e160122 --- /dev/null +++ b/examples/demo10/Model/model_app_termination_notification__links.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AppTerminationNotificationLinks struct { + Subscription *LinkType `json:"subscription"` + ConfirmTermination *LinkType `json:"confirmTermination,omitempty"` +} diff --git a/examples/demo10/Model/model_associate_id.go b/examples/demo10/Model/model_associate_id.go new file mode 100644 index 0000000000000000000000000000000000000000..cfa501c9477e85514e0449ade4cce762a8b2e2bc --- /dev/null +++ b/examples/demo10/Model/model_associate_id.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type AssociateId struct { + Type_ *AssociateIdType `json:"type,omitempty"` + // Value for the identifier. + Value string `json:"value,omitempty"` +} diff --git a/examples/demo10/Model/model_associate_id_type.go b/examples/demo10/Model/model_associate_id_type.go new file mode 100644 index 0000000000000000000000000000000000000000..82d58b758444bce89b9a0ba121cc5e1de480a500 --- /dev/null +++ b/examples/demo10/Model/model_associate_id_type.go @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// AssociateIdType : Numeric value (0-255) corresponding to specified type of identifier +type AssociateIdType string + +// List of AssociateIdType +const ( + UE_I_PV4_ADDRESS_AssociateIdType AssociateIdType = "UE_IPv4_ADDRESS" + UE_IPV6_ADDRESS_AssociateIdType AssociateIdType = "UE_IPV6_ADDRESS" + NATED_IP_ADDRESS_AssociateIdType AssociateIdType = "NATED_IP_ADDRESS" + GTP_TEID_AssociateIdType AssociateIdType = "GTP_TEID" +) diff --git a/examples/demo10/Model/model_communication_interface.go b/examples/demo10/Model/model_communication_interface.go new file mode 100644 index 0000000000000000000000000000000000000000..524da89f6cc8001fc98df34acd12aba7e95326b5 --- /dev/null +++ b/examples/demo10/Model/model_communication_interface.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type CommunicationInterface struct { + IpAddresses []CommunicationInterfaceIpAddresses `json:"ipAddresses,omitempty"` +} diff --git a/examples/demo10/Model/model_communication_interface_ip_addresses.go b/examples/demo10/Model/model_communication_interface_ip_addresses.go new file mode 100644 index 0000000000000000000000000000000000000000..cdde1a17999152cfc741dc8e374b9f29fc6a04d3 --- /dev/null +++ b/examples/demo10/Model/model_communication_interface_ip_addresses.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type CommunicationInterfaceIpAddresses struct { + Host string `json:"host"` + Port int32 `json:"port"` +} diff --git a/examples/demo10/Model/model_context_transfer_state.go b/examples/demo10/Model/model_context_transfer_state.go new file mode 100644 index 0000000000000000000000000000000000000000..8f0b7ccad373ce8a816865bff2206f4cdc15e889 --- /dev/null +++ b/examples/demo10/Model/model_context_transfer_state.go @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// ContextTransferState : If present, it represents the state of transferring the user context to another application instance. +type ContextTransferState string + +// List of ContextTransferState +const ( + NOT_TRANSFERRED_ContextTransferState ContextTransferState = "NOT_TRANSFERRED" + USER_CONTEXT_TRANSFER_COMPLETED_ContextTransferState ContextTransferState = "USER_CONTEXT_TRANSFER_COMPLETED" +) diff --git a/examples/demo10/Model/model_expiry_notification.go b/examples/demo10/Model/model_expiry_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..99d86842e6aa15131f86e58b1eb0604b603fd701 --- /dev/null +++ b/examples/demo10/Model/model_expiry_notification.go @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type ExpiryNotification struct { + // Shall be set to \"ExpiryNotification\". + NotificationType string `json:"notificationType"` + TimeStamp *TimeStamp `json:"timeStamp,omitempty"` + Links *Link `json:"_links"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline"` +} diff --git a/examples/demo10/Model/model_inline_notification.go b/examples/demo10/Model/model_inline_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..8c5b31de0c90a7daee11c80ebf73ab486972064c --- /dev/null +++ b/examples/demo10/Model/model_inline_notification.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type InlineNotification struct { + // Not used in client +} diff --git a/examples/demo10/Model/model_inline_subscription.go b/examples/demo10/Model/model_inline_subscription.go new file mode 100644 index 0000000000000000000000000000000000000000..12296a6f08d61287935026afe4399ee08fc4d5fa --- /dev/null +++ b/examples/demo10/Model/model_inline_subscription.go @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type InlineSubscription struct { + /* Discriminator */ + SubscriptionType string `json:"subscriptionType"` + + /* Common */ + Links *MobilityProcedureSubscriptionLinks `json:"_links,omitempty"` + CallbackReference string `json:"callbackReference"` + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + WebsockNotifConfig *WebsockNotifConfig `json:"websockNotifConfig,omitempty"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline,omitempty"` + + /* MobilityProcedureSubscription */ + FilterCriteria *MobilityProcedureSubscriptionFilterCriteria `json:"filterCriteria"` + + /* AdjacentAppInfoSubscription */ + // NOTE: to avoid json parameter conflict, use superset filterCriteria from MobilityProcedure + // FilterCriteria *AdjacentAppInfoSubscriptionFilterCriteria `json:"filterCriteria"` +} diff --git a/examples/demo10/Model/model_link.go b/examples/demo10/Model/model_link.go new file mode 100644 index 0000000000000000000000000000000000000000..656146a5cd8284bd94d530ee711d774898d6b73f --- /dev/null +++ b/examples/demo10/Model/model_link.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// Object containing hyperlinks related to the resource. +type Link struct { + Subscription *LinkType `json:"subscription"` +} diff --git a/examples/demo10/Model/model_link_type.go b/examples/demo10/Model/model_link_type.go new file mode 100644 index 0000000000000000000000000000000000000000..d9471e2272e71c82d57a4e2b64a9c4fc91141209 --- /dev/null +++ b/examples/demo10/Model/model_link_type.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// 'This data type represents a type of link' +type LinkType struct { + // The URI referring to the subscription. + Href string `json:"href"` +} diff --git a/examples/demo10/Model/model_mec_host_information.go b/examples/demo10/Model/model_mec_host_information.go new file mode 100644 index 0000000000000000000000000000000000000000..b36a4c43589c7c436ca6d576cf31b408c4686c58 --- /dev/null +++ b/examples/demo10/Model/model_mec_host_information.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type MecHostInformation struct { + // Human-readable name of MEC host. + HostName string `json:"hostName,omitempty"` + HostId *map[string]interface{} `json:"hostId"` +} diff --git a/examples/demo10/Model/model_mobility_procedure_notification.go b/examples/demo10/Model/model_mobility_procedure_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..c2c4a247120b825c1b3b2b0260638c262202b3dd --- /dev/null +++ b/examples/demo10/Model/model_mobility_procedure_notification.go @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type MobilityProcedureNotification struct { + // Shall be set to \"MobilityProcedureNotification\". + NotificationType string `json:"notificationType"` + TimeStamp *TimeStamp `json:"timeStamp,omitempty"` + // 1 to N identifiers to associate the information for specific + AssociateId []AssociateId `json:"associateId"` + MobilityStatus *MobilityStatus `json:"mobilityStatus"` + TargetAppInfo *MobilityProcedureNotificationTargetAppInfo `json:"targetAppInfo,omitempty"` + Links *Link `json:"_links"` +} diff --git a/examples/demo10/Model/model_mobility_procedure_notification_target_app_info.go b/examples/demo10/Model/model_mobility_procedure_notification_target_app_info.go new file mode 100644 index 0000000000000000000000000000000000000000..6630bfe1ccb02dad443769e6e09469678c968347 --- /dev/null +++ b/examples/demo10/Model/model_mobility_procedure_notification_target_app_info.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type MobilityProcedureNotificationTargetAppInfo struct { + // Identifiers of the target application instance. + AppInstanceId string `json:"appInstanceId"` + CommInterface *CommunicationInterface `json:"commInterface,omitempty"` +} diff --git a/examples/demo10/Model/model_mobility_procedure_subscription.go b/examples/demo10/Model/model_mobility_procedure_subscription.go new file mode 100644 index 0000000000000000000000000000000000000000..c36b0b3a6505555000b5a2c99a63d158b92892cb --- /dev/null +++ b/examples/demo10/Model/model_mobility_procedure_subscription.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type MobilityProcedureSubscription struct { + Links *MobilityProcedureSubscriptionLinks `json:"_links,omitempty"` + // URI selected by the service consumer to receive notifications on the subscribed Application Mobility Service. This shall be included both in the request and in response. + CallbackReference string `json:"callbackReference,omitempty"` + // Shall be set to TRUE by the service consumer to request a test notification via HTTP on the callbackReference URI, specified in ETSI GS MEC 009, as described in clause 6.12a. + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + WebsockNotifConfig *WebsockNotifConfig `json:"websockNotifConfig,omitempty"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline,omitempty"` + FilterCriteria *MobilityProcedureSubscriptionFilterCriteria `json:"filterCriteria"` + SubscriptionType *SubscriptionType `json:"subscriptionType"` +} diff --git a/examples/demo10/Model/model_mobility_procedure_subscription_filter_criteria.go b/examples/demo10/Model/model_mobility_procedure_subscription_filter_criteria.go new file mode 100644 index 0000000000000000000000000000000000000000..16e7ce163ff401ab9f9f77aee0451358af5dc0a8 --- /dev/null +++ b/examples/demo10/Model/model_mobility_procedure_subscription_filter_criteria.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// List of filtering criteria for the subscription. Any filtering criteria from below, which is included in the request, shall also be included in the response. +type MobilityProcedureSubscriptionFilterCriteria struct { + // Identifier of the application instance that registers the Application Mobility Service. + AppInstanceId string `json:"appInstanceId,omitempty"` + // 0 to N identifiers to associate the information for specific UE(s) and flow(s). + AssociateId []AssociateId `json:"associateId,omitempty"` + // In case mobilityStatus is not included in the subscription request, the default value 1 = INTER_HOST_MOBILITY_TRIGGERED shall be used and included in the response. + MobilityStatus []MobilityStatus `json:"mobilityStatus,omitempty"` +} diff --git a/examples/demo10/Model/model_mobility_procedure_subscription_links.go b/examples/demo10/Model/model_mobility_procedure_subscription_links.go new file mode 100644 index 0000000000000000000000000000000000000000..937f5450c3d67eff2f6a3d410cec7a6c9ac2296b --- /dev/null +++ b/examples/demo10/Model/model_mobility_procedure_subscription_links.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type MobilityProcedureSubscriptionLinks struct { + Self *LinkType `json:"self"` +} diff --git a/examples/demo10/Model/model_mobility_status.go b/examples/demo10/Model/model_mobility_status.go new file mode 100644 index 0000000000000000000000000000000000000000..a8b628691f1148df9fc71d4ecd76ec3d9a65fc60 --- /dev/null +++ b/examples/demo10/Model/model_mobility_status.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// MobilityStatus : Indicate the status of the UE mobility +type MobilityStatus string + +// List of MobilityStatus +const ( + TRIGGERED_MobilityStatus MobilityStatus = "INTERHOST_MOVEOUT_TRIGGERED" + COMPLETED_MobilityStatus MobilityStatus = "INTERHOST_MOVEOUT_COMPLETED" + FAILED_MobilityStatus MobilityStatus = "INTERHOST_MOVEOUT_FAILED" +) diff --git a/examples/demo10/Model/model_one_of_inline_notification.go b/examples/demo10/Model/model_one_of_inline_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..49ae7e4f9cc210a647dcc4647863e803ee85ead8 --- /dev/null +++ b/examples/demo10/Model/model_one_of_inline_notification.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type OneOfInlineNotification struct { + /* Discriminator */ + NotificationType string `json:"notificationType"` +} diff --git a/examples/demo10/Model/model_one_of_inline_subscription.go b/examples/demo10/Model/model_one_of_inline_subscription.go new file mode 100644 index 0000000000000000000000000000000000000000..2c68e86a9a7eb55c275cab2d5e9e92e9d56c2dda --- /dev/null +++ b/examples/demo10/Model/model_one_of_inline_subscription.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type OneOfInlineSubscription struct { + /* Discriminator */ + SubscriptionType string `json:"subscriptionType"` +} diff --git a/examples/demo10/Model/model_operation_action_type.go b/examples/demo10/Model/model_operation_action_type.go new file mode 100644 index 0000000000000000000000000000000000000000..d934d5fc4cabb4f53114d5274398d7aabceca97f --- /dev/null +++ b/examples/demo10/Model/model_operation_action_type.go @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// OperationActionType : Operation that is being performed on the MEC application instance. +type OperationActionType string + +// List of OperationActionType +const ( + STOPPING_OperationActionType OperationActionType = "STOPPING" + TERMINATING_OperationActionType OperationActionType = "TERMINATING" +) diff --git a/examples/demo10/Model/model_problem_details.go b/examples/demo10/Model/model_problem_details.go new file mode 100644 index 0000000000000000000000000000000000000000..7d55968705472d6f956e0ff53f83569550632356 --- /dev/null +++ b/examples/demo10/Model/model_problem_details.go @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type ProblemDetails struct { + // A human-readable explanation specific to this occurrence of the problem + Detail string `json:"detail,omitempty"` + // A URI reference that identifies the specific occurrence of the problem + Instance string `json:"instance,omitempty"` + // The HTTP status code for this occurrence of the problem + Status int32 `json:"status,omitempty"` + // A short, human-readable summary of the problem type + Title string `json:"title,omitempty"` + // A URI reference according to IETF RFC 3986 that identifies the problem type + Type_ string `json:"type,omitempty"` +} diff --git a/examples/demo10/Model/model_registration_info.go b/examples/demo10/Model/model_registration_info.go new file mode 100644 index 0000000000000000000000000000000000000000..ad45f4a52778dcd8c1f7343c055b3643fb6519cd --- /dev/null +++ b/examples/demo10/Model/model_registration_info.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type RegistrationInfo struct { + // The identifier of registered application mobility service. Shall be absent in POST requests, and present otherwise. + AppMobilityServiceId string `json:"appMobilityServiceId,omitempty"` + // If present, it specifies the device served by the application instance which is registering is registering the Application Mobility Service. + DeviceInformation []RegistrationInfoDeviceInformation `json:"deviceInformation,omitempty"` + // If present, it indicates the time of Application Mobility Service expiration from the time of registration accepted.The value \"0\" means infinite time, i.e. no expiration.The unit of expiry time is one second. + ExpiryTime int32 `json:"expiryTime,omitempty"` + ServiceConsumerId *RegistrationInfoServiceConsumerId `json:"serviceConsumerId"` +} diff --git a/examples/demo10/Model/model_registration_info_device_information.go b/examples/demo10/Model/model_registration_info_device_information.go new file mode 100644 index 0000000000000000000000000000000000000000..9e3885bce482b21abd626ca6e6463e8a81b7b3cb --- /dev/null +++ b/examples/demo10/Model/model_registration_info_device_information.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type RegistrationInfoDeviceInformation struct { + AssociateId *AssociateId `json:"associateId"` + AppMobilityServiceLevel *AppMobilityServiceLevel `json:"appMobilityServiceLevel,omitempty"` + ContextTransferState *ContextTransferState `json:"contextTransferState,omitempty"` +} diff --git a/examples/demo10/Model/model_registration_info_service_consumer_id.go b/examples/demo10/Model/model_registration_info_service_consumer_id.go new file mode 100644 index 0000000000000000000000000000000000000000..41437ba61968885cf06413758c31290a5f6795b1 --- /dev/null +++ b/examples/demo10/Model/model_registration_info_service_consumer_id.go @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// The identifier of service consumer requesting the application mobility service, i.e. either the application instance ID or the MEC platform ID. +type RegistrationInfoServiceConsumerId struct { + // If present, it represents the identifier of the application instance registering the Application Mobility Service. + AppInstanceId string `json:"appInstanceId,omitempty"` + // If present, it represents the identifier of the MEC platform registering the Application Mobility Service. + MepId string `json:"mepId,omitempty"` +} diff --git a/examples/demo10/Model/model_subscription_link_list.go b/examples/demo10/Model/model_subscription_link_list.go new file mode 100644 index 0000000000000000000000000000000000000000..ae7493d3729867786ecc29e3433eebf379cfe2c0 --- /dev/null +++ b/examples/demo10/Model/model_subscription_link_list.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type SubscriptionLinkList struct { + Links *SubscriptionLinkListLinks `json:"_links"` +} diff --git a/examples/demo10/Model/model_subscription_link_list_links.go b/examples/demo10/Model/model_subscription_link_list_links.go new file mode 100644 index 0000000000000000000000000000000000000000..76b7813e259a2faf95a6cfdbc7544006ed223980 --- /dev/null +++ b/examples/demo10/Model/model_subscription_link_list_links.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// List of hyperlinks related to the resource. +type SubscriptionLinkListLinks struct { + Self *LinkType `json:"self"` + // The service consumer’s subscriptions. + Subscription []SubscriptionLinkListSubscription `json:"subscription,omitempty"` +} diff --git a/examples/demo10/Model/model_subscription_link_list_subscription.go b/examples/demo10/Model/model_subscription_link_list_subscription.go new file mode 100644 index 0000000000000000000000000000000000000000..e23d56e8e37e81c47b4a0a93a79a1f28bf90f421 --- /dev/null +++ b/examples/demo10/Model/model_subscription_link_list_subscription.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type SubscriptionLinkListSubscription struct { + // The URI referring to the subscription. + Href string `json:"href"` + SubscriptionType *SubscriptionType `json:"subscriptionType"` +} diff --git a/examples/demo10/Model/model_subscription_type.go b/examples/demo10/Model/model_subscription_type.go new file mode 100644 index 0000000000000000000000000000000000000000..ca4da6f8c0902604ba517b31be7b4f27ae7f697f --- /dev/null +++ b/examples/demo10/Model/model_subscription_type.go @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type SubscriptionType string + +// List of SubscriptionType +const ( + MOBILITY_PROCEDURE_SUBSCRIPTION_SubscriptionType SubscriptionType = "MobilityProcedureSubscription" + ADJACENT_APP_INFO_SUBSCRIPTION_SubscriptionType SubscriptionType = "AdjacentAppInfoSubscription" +) diff --git a/examples/demo10/Model/model_test_notification.go b/examples/demo10/Model/model_test_notification.go new file mode 100644 index 0000000000000000000000000000000000000000..c2cafc46dd63ba1f8788f6831a20c3b93b24d364 --- /dev/null +++ b/examples/demo10/Model/model_test_notification.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type TestNotification struct { + // Shall be set to \"TestNotification\". + NotificationType string `json:"notificationType"` + Links *TestNotificationLinks `json:"_links"` +} diff --git a/examples/demo10/Model/model_test_notification__links.go b/examples/demo10/Model/model_test_notification__links.go new file mode 100644 index 0000000000000000000000000000000000000000..e77f868bb9b534495ab29e0bcaf7d456945263b0 --- /dev/null +++ b/examples/demo10/Model/model_test_notification__links.go @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// Hyperlink related to the resource. +type TestNotificationLinks struct { + Subscription *LinkType `json:"subscription"` +} diff --git a/examples/demo10/Model/model_time_stamp.go b/examples/demo10/Model/model_time_stamp.go new file mode 100644 index 0000000000000000000000000000000000000000..84e953c5c761f20245aac0e2fb12ddf9f1930cf8 --- /dev/null +++ b/examples/demo10/Model/model_time_stamp.go @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +// 'This data type represents the time stamp as Unix-time since January 1, 1970, 00:00:00 UTC' +type TimeStamp struct { + // 'The seconds part of the Time. Time is defined as Unix-time since January 1, 1970, 00:00:00 UTC.' + Seconds int32 `json:"seconds"` + // 'The nanoseconds part of the Time. Time is defined as Unix-time since January 1, 1970, 00:00:00 UTC.' + NanoSeconds int32 `json:"nanoSeconds"` +} diff --git a/examples/demo10/Model/model_websock_notif_config.go b/examples/demo10/Model/model_websock_notif_config.go new file mode 100644 index 0000000000000000000000000000000000000000..8776daae6834738994da9460a08db1711a3812cf --- /dev/null +++ b/examples/demo10/Model/model_websock_notif_config.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * 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. + * + * AdvantEDGE Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-ams](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-ams)

**Type & Usage**
Edge Service used by edge applications that want to get information about application mobility in the network

**Note**
AdvantEDGE supports a selected subset of Application Mobility API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package model + +type WebsockNotifConfig struct { + // Set by AMS to indicate to the service consumer the Websocket URI to be used for delivering notifications. + WebsocketUri string `json:"websocketUri,omitempty"` + // Set to true by the service consumer to indicate that Websocket delivery is requested. + RequestWebsocketUri bool `json:"requestWebsocketUri,omitempty"` +} diff --git a/examples/demo10/Model/platform_info.go b/examples/demo10/Model/platform_info.go new file mode 100644 index 0000000000000000000000000000000000000000..e35d52a2b458b5a696ff8898cdfeb195e7eb3bbf --- /dev/null +++ b/examples/demo10/Model/platform_info.go @@ -0,0 +1,8 @@ +package model + +type PlatformInfo struct { + AmsServiceID string `json:"ams_service_id,omitempty"` + AppInstanceID string `json:"app_instance_id,omitempty"` + AmsSubscriptionID string `json:"ams_subscription_id,omitempty"` + NodeName string `json:"node_name,omitempty"` +} diff --git a/examples/demo10/go.mod b/examples/demo10/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..9196c4824139ea443d6443f966ab884f9308bae7 --- /dev/null +++ b/examples/demo10/go.mod @@ -0,0 +1,7 @@ +module estimed_demo + +go 1.17 + +require ( + github.com/google/uuid v1.6.0 // indirect +) diff --git a/examples/demo10/go.sum b/examples/demo10/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..40e65d629b6dea1b3ca51f5778cd7ca9d29cff27 --- /dev/null +++ b/examples/demo10/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= \ No newline at end of file diff --git a/examples/demo10/main.go b/examples/demo10/main.go new file mode 100644 index 0000000000000000000000000000000000000000..8e4a870a361684be6091ecc4e618fbb73f2e0d37 --- /dev/null +++ b/examples/demo10/main.go @@ -0,0 +1,268 @@ +package main + +import ( + mec "estimed_demo/MEC" + model "estimed_demo/Model" + onem2m "estimed_demo/oneM2M" + "fmt" + "log" + "math/rand" + "net/http" + "os" + "os/signal" + "syscall" + "time" +) + +// MN-CSE platform details +var platformURL = "" +var sandboxURL = "mec-platform2.etsi.org" // Site that hosts MEC Sandbox + + +var cse_id = "" // CSE Structured ID +var cse_name = "mep-cse-mn" // CSE Name (for some API calls) +var AE_ID = "CSmartCar" // Application Entity ID +var App_Name = "SmartCar" // Application Resource Name +var App_Id = "N-Smart_Car_Application" +var appVersion = "1.0.0" +var containerName = "SmartCarContainer" +var remote_cse_id = "/laboai-id-in" + +// MEC platform details +var sandbox_name = "sbxt8mvfg1" // Namespace allocated to the user upon login +var DeviceId = "10.100.0.1" // This is the IP of UE moving on map in Sandbox +var ams_pltf = "mep1" + +// Endpoints for recieving notifications from MEC platform +var server_port = "{Server_Port}" // Port to listen on for notifications +var ams_notification_endpoint = "/ams/notify" +var server_ip = "{Server_IP}" // IP address to listen on for notifications + +var notificationChan = make(chan string, 10) +var currentAppInstanceId = "" +var platformDetails = []map[string]model.PlatformInfo{} +var associateId = &model.AssociateId{ + Type_: &[]model.AssociateIdType{"UE_IPv4_ADDRESS"}[0], + Value: DeviceId, +} +var deviceInfo = &model.RegistrationInfoDeviceInformation{ + AssociateId: associateId, + AppMobilityServiceLevel: &[]model.AppMobilityServiceLevel{"APP_MOBILITY_WITHOUT_CONFIRMATION"}[0], + ContextTransferState: &[]model.ContextTransferState{"NOT_TRANSFERRED"}[0], +} + +// initApp initializes the application and connects to the oneM2M platform +func initApp() error { + // Start HTTP server to listen for sensor connections + log.Println("Starting HTTP server on port 9876 to listen for sensor connections...") + server := &http.Server{Addr: fmt.Sprintf("%s:%s", server_ip, server_port)} + // Set up HTTP routes + http.HandleFunc(ams_notification_endpoint, func(w http.ResponseWriter, r *http.Request) { + id, err := mec.AMSNotificationHandler(w, r) + if err != nil { + log.Printf("Error handling AMS notification: %v", err) + } else if id != "" { + notificationChan <- id + } + }) + + // Start server in a goroutine so it doesn't block + go func() { + log.Println("Server goroutine starting...") + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Printf("Server error: %v", err) + log.Printf("ERROR: Could not start server: %v", err) + } + }() + + // Give the server a moment to start and check if it's running + time.Sleep(1 * time.Second) + + // log.Println("✓ HTTP server started and listening on 0.0.0.0:9876") + + log.Printf("Initializing %s (version %s)", App_Id, appVersion) + log.Println("Obtaining MEC App Instance ID of mn-cse") + + // Fetch MEC App Instance ID to find the correct App Instance for mn-cse + // Construct MEC App Instance URL + url := fmt.Sprintf("%s/%s/sandbox-ctrl/v1/applications", sandboxURL, sandbox_name) + + // Get all MEC App Instance ID + allAppInstances, err := mec.GetAppInstances(url) + if err != nil { + return fmt.Errorf("failed to get MEC App Instance IDs: %v", err) + } + log.Printf("Total MEC App Instances retrieved: %d", len(allAppInstances)) + log.Printf("MEC App Instances: %+v", allAppInstances) + + // Array to store matching app instances + matchingAppInstances, err := mec.MatchForTargetAppInstance(allAppInstances, cse_name) + if err != nil { + return fmt.Errorf("failed to match MEC App Instances: %v", err) + } + + // Create AMS registration and subscription for each matching App Instance + callbackURL := fmt.Sprintf("http://%s:%s%s", server_ip, server_port, ams_notification_endpoint) + platformDetails, err = mec.RegistrationAndSubscriptionHandler(matchingAppInstances, sandboxURL, + sandbox_name, callbackURL, ¤tAppInstanceId, deviceInfo, associateId) + if err != nil { + return fmt.Errorf("failed to create AMS registration and subscription: %v", err) + } + + // Request IoT API for IoT platform urls + log.Println("Fetching IoT platform information from MEC...") + + // Current App Instance ID must be set from previous step + var current_pltf_details model.PlatformInfo + for _, pltf := range platformDetails { + if platformInfo, exists := pltf[currentAppInstanceId]; exists { + current_pltf_details = platformInfo + break + } + } + log.Printf("Current platform details: %v", current_pltf_details) + + iot_url := fmt.Sprintf("%s/%s/%s/iots/v1/registered_iot_platforms", sandboxURL, sandbox_name, current_pltf_details.NodeName) + iot_platforms, err := mec.GETIotPlatformInfo(iot_url) + if err != nil { + return fmt.Errorf("failed to get IoT platform info: %v", err) + } + + platformURL = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["endpoint"].(map[string]interface{})["uris"].([]interface{})[0].(string) + log.Printf("IoT platform URL: %s", platformURL) + cse_id = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["id"].(string) + log.Printf("CSE ID: %s", cse_id) + cse_name = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["name"].(string) + log.Printf("CSE Name: %s", cse_name) + + // Initialize oneM2M application + err = onem2m.InitOneM2MApp(platformURL, cse_name, cse_id, App_Name, App_Id, AE_ID, containerName, remote_cse_id) + if err != nil { + return fmt.Errorf("failed to initialize oneM2M application: %v", err) + } + // Create subscription for notification server + // err = onem2m.CreateSubscription(platformURL, cse_name, App_Name, containerName) + // if err != nil { + // return fmt.Errorf("failed to create oneM2M subscription: %v", err) + // } + return nil +} + +func main() { + log.SetFlags(log.LstdFlags | log.Lshortfile) + // Handle graceful shutdown on system kill signals + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + go func() { + <-sigs + latestData, err := onem2m.RetrieveLatestData(platformURL, cse_name, App_Name, AE_ID, containerName) + if err != nil { + log.Printf("Failed to retrieve latest data: %v", err) + } else { + log.Printf("Latest data: %s", latestData) + } + if err := onem2m.DeregisterAE(platformURL, cse_name, cse_id, App_Name, AE_ID); err != nil { + log.Printf("Failed to deregister AE: %v", err) + } + log.Println("\nReceived shutdown signal, exiting...") + os.Exit(0) + }() + + // Initialize the application + if err := initApp(); err != nil { + log.Fatalf("Failed to initialize application: %v", err) + os.Exit(1) + } + + // Start goroutine to handle received target app instance IDs + go func() { + for targetAppInstanceID := range notificationChan { + // Get platform details for the received ID + var targetPltfDetails model.PlatformInfo + for _, pltf := range platformDetails { + if platformInfo, exists := pltf[targetAppInstanceID]; exists { + targetPltfDetails = platformInfo + break + } + } + log.Printf("Target platform details: %v", targetPltfDetails) + + // Connect to new IoT platform + iot_url := fmt.Sprintf("%s/%s/%s/iots/v1/registered_iot_platforms", sandboxURL, sandbox_name, targetPltfDetails.NodeName) + iot_platforms, err := mec.GETIotPlatformInfo(iot_url) + if err != nil { + log.Printf("Failed to get IoT platform info for target app instance %s: %v", targetAppInstanceID, err) + continue + } + // Temporarily store old platform URL + old_platformURL := platformURL + old_cse_id := cse_id + old_cse_name := cse_name + + platformURL = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["endpoint"].(map[string]interface{})["uris"].([]interface{})[0].(string) + log.Printf("New IoT platform URL after mobility: %s", platformURL) + + cse_name = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["name"].(string) + cse_id = iot_platforms[0]["customServicesTransportInfo"].([]interface{})[0].(map[string]interface{})["id"].(string) + + // Re-initialize oneM2M application on the new platform + err = onem2m.InitOneM2MApp(platformURL, cse_name, cse_id, App_Name, App_Id, AE_ID, containerName, remote_cse_id) + if err != nil { + log.Printf("Failed to re-initialize oneM2M application after mobility: %v", err) + continue + } else { + log.Printf("Successfully re-initialized oneM2M application on new platform after mobility") + } + + // Disconnect from previous platform + log.Printf("Disconnecting from previous platform: %s", old_platformURL) + if err := onem2m.DeregisterAE(old_platformURL, old_cse_name, old_cse_id, App_Name, AE_ID); err != nil { + log.Printf("Failed to deregister AE from old platform: %v", err) + } else { + log.Printf("Successfully deregistered AE from old platform") + } + + // Update AMS registration to reflect new platform connection + log.Printf("Updating AMS registration to reflect new platform connection...") + + // PUT request to AMS for currentAppInstanceId to switch + ams_url := fmt.Sprintf("%s/%s/%s/amsi/v1/app_mobility_services", sandboxURL, sandbox_name, ams_pltf) + err = mec.PutAMSRegistrationInfo(ams_url, targetAppInstanceID, platformDetails, ¤tAppInstanceId, associateId) + if err != nil { + log.Printf("Failed to update AMS registration info for target app instance %s: %v", targetAppInstanceID, err) + continue + } else { + log.Printf("Successfully updated AMS registration info for target app instance %s", targetAppInstanceID) + } + + // Update AMS subscription to reflect new platform connection + log.Printf("Updating AMS subscription to reflect new platform connection...") + ams_url = fmt.Sprintf("%s/%s/%s/amsi/v1/subscriptions", sandboxURL, sandbox_name, ams_pltf) + err = mec.PUTAMSSubscriptionInfo(ams_url, targetAppInstanceID, platformDetails, ¤tAppInstanceId, + fmt.Sprintf("http://%s:%s%s", server_ip, server_port, ams_notification_endpoint), associateId) + if err != nil { + log.Printf("Failed to update AMS subscription info for target app instance %s: %v", targetAppInstanceID, err) + continue + } else { + log.Printf("Successfully updated AMS subscription info for target app instance %s", targetAppInstanceID) + } + currentAppInstanceId = targetAppInstanceID + } + }() + + // Example: Send telemetry data + speed := []int{60, 62, 58, 65, 68} + temperature := []float64{25.5, 26.0, 24.8, 25.2, 25.9} + fuel := []int{75, 74, 73, 72, 71} + // For only terminates on system kill signal + for { + telemetryData := fmt.Sprintf(`{"temperature": %f, "speed": %d, "fuel": %d}`, + temperature[rand.Intn(len(temperature))], + speed[rand.Intn(len(speed))], + fuel[rand.Intn(len(fuel))]) + if err := onem2m.CreateContentInstance(platformURL, cse_name, App_Name, AE_ID, containerName, remote_cse_id, telemetryData); err != nil { + log.Printf("Failed to send telemetry: %v", err) + } + time.Sleep(5 * time.Second) + } +} diff --git a/examples/demo10/oneM2M/createAE.go b/examples/demo10/oneM2M/createAE.go new file mode 100644 index 0000000000000000000000000000000000000000..01904b9f82ebb17c47cecde083555f6bb2e16b85 --- /dev/null +++ b/examples/demo10/oneM2M/createAE.go @@ -0,0 +1,44 @@ +package onem2m +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" +) + +// CreateAE creates an Application Entity on the oneM2M platform +func CreateAE(platformURL, cse_name, cse_id, App_Name, App_Id, AE_ID, remote_cse_id string) error { + log.Println("Creating Application Entity (AE)...") + + reqBody := fmt.Sprintf(`{ + "m2m:ae": { + "rn": "%s", + "api": "%s", + "rr": true, + "lbl": ["Type/SmartCar", "Category/Vehicle"], + "srv": ["5"], + "at": ["%s"] + } + }`, App_Name, App_Id, remote_cse_id) + + url := fmt.Sprintf("%s/~%s/%s", platformURL, cse_id, cse_name) + log.Println("url (Create AE):", url) + resp, err := utils.MakeOneM2MRequest("POST", url, reqBody, 2, AE_ID) + if err != nil { + return err + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + if resp.StatusCode == http.StatusCreated { + log.Println("✓ Application Entity (AE) created successfully") + return nil + } else if resp.StatusCode == http.StatusConflict || resp.StatusCode == http.StatusForbidden { + log.Println("⚠ AE already exists") + return nil + } + + return fmt.Errorf("failed to create AE: status %d, body: %s", resp.StatusCode, string(body)) +} \ No newline at end of file diff --git a/examples/demo10/oneM2M/createContentInstance.go b/examples/demo10/oneM2M/createContentInstance.go new file mode 100644 index 0000000000000000000000000000000000000000..b072ad222089883fbb113ebe419c6432cd15d340 --- /dev/null +++ b/examples/demo10/oneM2M/createContentInstance.go @@ -0,0 +1,43 @@ +package onem2m +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" + "strings" +) + +// CreateContentInstance creates a ContentInstance (data) in the container +func CreateContentInstance(platformURL, cse_name, App_Name, AE_ID, containerName, remote_cse_id, data string) error { + log.Printf("Creating ContentInstance with data: %s", data) + + // Escape JSON quotes in the content field + escapedData := strings.ReplaceAll(data, `"`, `\"`) + + reqBody := fmt.Sprintf(`{ + "m2m:cin": { + "con": "%s", + "lbl": ["telemetry"], + "at": ["%s"], + "aa": ["lbl", "con"] + } + }`, escapedData, remote_cse_id) + + url := fmt.Sprintf("%s/%s/%s/%s", platformURL, cse_name, App_Name, containerName) + + resp, err := utils.MakeOneM2MRequest("POST", url, reqBody, 4, AE_ID) + if err != nil { + return fmt.Errorf("request error: %v", err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + if resp.StatusCode == http.StatusCreated { + log.Println("✓ ContentInstance created successfully") + return nil + } + + return fmt.Errorf("failed to create content instance: status %d, body: %s", resp.StatusCode, string(body)) +} \ No newline at end of file diff --git a/examples/demo10/oneM2M/createSubscription.go b/examples/demo10/oneM2M/createSubscription.go new file mode 100644 index 0000000000000000000000000000000000000000..51141de9bc66145c7de6433e7c6e5953b27a9385 --- /dev/null +++ b/examples/demo10/oneM2M/createSubscription.go @@ -0,0 +1,64 @@ +package onem2m + +import ( + "bytes" + "crypto/tls" + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +// CreateSubscription creates a subscription on the specified container for the notification server endpoint +func CreateSubscription(platformURL, cseName, appName, containerName string) error { + subscriptionURL := fmt.Sprintf("%s/%s/%s/%s", platformURL, cseName, appName, containerName) + + target := subscriptionURL + // Subscription resource body + body := map[string]interface{}{ + "m2m:sub": map[string]interface{}{ + "rn": "DataSyncSub", + "nu": []string{"https://192.168.20.163:9999/notifications"}, + "nct": 1, + "enc": map[string]interface{}{ + "net": []int{3}, + }, + }, + } + jsonBody, err := json.Marshal(body) + if err != nil { + return fmt.Errorf("failed to marshal subscription body: %v", err) + } + + adminUser := "CAdmin" + adminSecret := "ikram123" + authString := fmt.Sprintf("%s:%s", adminUser, adminSecret) + authHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(authString)) + + req, err := http.NewRequest("POST", target, bytes.NewBuffer(jsonBody)) + if err != nil { + return fmt.Errorf("failed to create subscription request: %v", err) + } + req.Header.Set("X-M2M-Origin", adminUser) + req.Header.Set("X-M2M-RI", "req-admin") + req.Header.Set("Authorization", authHeader) + req.Header.Set("X-M2M-RVI", "5") + req.Header.Set("Content-Type", "application/json;ty=23") + + // Skip TLS verification for development/testing + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to send subscription request: %v", err) + } + defer resp.Body.Close() + respBody, _ := ioutil.ReadAll(resp.Body) + if resp.StatusCode != 201 && resp.StatusCode != 409 { // 409: Already exists + return fmt.Errorf("subscription creation failed: %s", string(respBody)) + } + return nil +} diff --git a/examples/demo10/oneM2M/createcontainer.go b/examples/demo10/oneM2M/createcontainer.go new file mode 100644 index 0000000000000000000000000000000000000000..a3745f5222f21802795dc6c8126713dbe741e386 --- /dev/null +++ b/examples/demo10/oneM2M/createcontainer.go @@ -0,0 +1,44 @@ +package onem2m + +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" +) + +// CreateContainer creates a container under the AE +func CreateContainer(platformURL, cse_name, cse_id, App_Name, AE_ID, containerName, remote_cse_id string) error { + log.Println("Creating Container...") + + reqBody := fmt.Sprintf(`{ + "m2m:cnt": { + "rn": "%s", + "mni": 10, + "at": ["%s"], + "lbl": ["Data/Telemetry"], + "aa": ["lbl"] + } + }`, containerName, remote_cse_id) + + url := fmt.Sprintf("%s/~/%s/%s/%s", platformURL, cse_id, cse_name, App_Name) + log.Println("url (Create Container):", url) + resp, err := utils.MakeOneM2MRequest("POST", url, reqBody, 3, AE_ID) + if err != nil { + return fmt.Errorf("request error: %v", err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + if resp.StatusCode == http.StatusCreated { + log.Println("✓ Container created successfully") + return nil + } else if resp.StatusCode == http.StatusConflict { + log.Println("⚠ Container already exists") + return nil + } + + return fmt.Errorf("failed to create container: status %d, body: %s", resp.StatusCode, string(body)) +} \ No newline at end of file diff --git a/examples/demo10/oneM2M/deregister.go b/examples/demo10/oneM2M/deregister.go new file mode 100644 index 0000000000000000000000000000000000000000..ac04d09171dfdd4e08a6dfcf298adb2f34987c66 --- /dev/null +++ b/examples/demo10/oneM2M/deregister.go @@ -0,0 +1,27 @@ +package onem2m + +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" +) + +// DeregisterAE deregisters the AE from the oneM2M platform +func DeregisterAE(platformURL, cseName, cse_id, appName, aeID string) error { + aeResource := fmt.Sprintf("%s/~%s/%s/%s", platformURL, cse_id, cseName, appName) + resp, err := utils.MakeOneM2MRequest("DELETE", aeResource, "", 2, aeID) + if err != nil { + return fmt.Errorf("failed to deregister AE: %v", err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent { + return fmt.Errorf("failed to deregister AE, status: %s, response: %s", resp.Status, string(body)) + } + + log.Printf("✓ AE deregistered successfully, response: %s", string(body)) + return nil +} diff --git a/examples/demo10/oneM2M/oneM2m_init.go b/examples/demo10/oneM2M/oneM2m_init.go new file mode 100644 index 0000000000000000000000000000000000000000..3f9b92204e03622240b77da92075d7dabe443f4a --- /dev/null +++ b/examples/demo10/oneM2M/oneM2m_init.go @@ -0,0 +1,31 @@ +package onem2m + +import ( + "log" + "time" +) + +// Initialize oneM2M application +func InitOneM2MApp(platformURL, cse_name, cse_id, App_Name, + App_Id, AE_ID, containerName, remote_cse_id string) error { + log.Printf("Connecting to MN-CSE: %s", platformURL) + // Create AE + if err := CreateAE(platformURL, cse_name, cse_id, App_Name, App_Id, AE_ID, remote_cse_id); err != nil { + return err + } + // Wait briefly to ensure AE is registered + time.Sleep(2 * time.Second) + + // Create Container + if err := CreateContainer(platformURL, cse_name, cse_id, App_Name, AE_ID, containerName, remote_cse_id); err != nil { + return err + } + + // Verify container + if err := RetrieveContainer(platformURL, cse_name, cse_id, App_Name, AE_ID, containerName); err != nil { + log.Printf("Warning: Could not verify container: %v", err) + } + + log.Println("✓ Application initialized successfully") + return nil +} diff --git a/examples/demo10/oneM2M/retrieveContainer.go b/examples/demo10/oneM2M/retrieveContainer.go new file mode 100644 index 0000000000000000000000000000000000000000..a6d4dc211f531ae2dc1a172a5c276fe5d89aa362 --- /dev/null +++ b/examples/demo10/oneM2M/retrieveContainer.go @@ -0,0 +1,28 @@ +package onem2m +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" +) + +// RetrieveContainer retrieves container details +func RetrieveContainer(platformURL, cse_name, cse_id, App_Name, AE_ID, containerName string) error { + url := fmt.Sprintf("%s/~%s/%s/%s/%s", platformURL, cse_id, cse_name, App_Name, containerName) + + resp, err := utils.MakeOneM2MRequest("GET", url, "", 0, AE_ID) + if err != nil { + return fmt.Errorf("error retrieving container: %v", err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + if resp.StatusCode == http.StatusOK { + log.Println("✓ Container exists and is accessible") + return nil + } + + return fmt.Errorf("container not found: status %d, body: %s", resp.StatusCode, string(body)) +} \ No newline at end of file diff --git a/examples/demo10/oneM2M/retrieveLatestData.go b/examples/demo10/oneM2M/retrieveLatestData.go new file mode 100644 index 0000000000000000000000000000000000000000..9208f581272644956e6e9c077a68a103fb5f1656 --- /dev/null +++ b/examples/demo10/oneM2M/retrieveLatestData.go @@ -0,0 +1,30 @@ +package onem2m +import ( + "estimed_demo/utils" + "fmt" + "io" + "log" + "net/http" +) + +// RetrieveLatestData retrieves the latest ContentInstance from the container +func RetrieveLatestData(platformURL, cse_name, App_Name, AE_ID, containerName string) (string, error) { + // Use 'la' (latest) to get the most recent ContentInstance + // ToDo: Fix variable name cse_id to cse_name // check this file + url := fmt.Sprintf("%s/%s/%s/%s/la", platformURL, cse_name, App_Name, containerName) + + resp, err := utils.MakeOneM2MRequest("GET", url, "", 0, AE_ID) + if err != nil { + return "", fmt.Errorf("error retrieving data: %v", err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + if resp.StatusCode == http.StatusOK { + log.Println("✓ Latest data retrieved successfully") + return string(body), nil + } + + return "", fmt.Errorf("failed to retrieve data: status %d", resp.StatusCode) +} \ No newline at end of file diff --git a/examples/demo10/utils/mec_req.go b/examples/demo10/utils/mec_req.go new file mode 100644 index 0000000000000000000000000000000000000000..f4f32e155c24910333d6899e0f9d3743ceeeba94 --- /dev/null +++ b/examples/demo10/utils/mec_req.go @@ -0,0 +1,50 @@ +package utils + +import ( + "bytes" + "context" + "crypto/tls" + "encoding/json" + "fmt" + "log" + "net/http" + "time" +) + +func SendMECRequest(method, url string, payload interface{}) (*http.Response, error) { + client := &http.Client{ + Timeout: 10 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + } + + var req *http.Request + var err error + + // Handle GET requests with no payload + if method == "GET" && payload == nil { + req, err = http.NewRequestWithContext(context.Background(), method, url, nil) + if err != nil { + return nil, fmt.Errorf("failed to create request: %v", err) + } + } else { + // Handle requests with payload + reqBody, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal payload: %v", err) + } + log.Println("Request body:", string(reqBody)) + + req, err = http.NewRequestWithContext(context.Background(), method, url, bytes.NewBuffer(reqBody)) + if err != nil { + return nil, fmt.Errorf("failed to create request: %v", err) + } + req.Header.Set("Content-Type", "application/json") + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("User-Agent", "Go-http-client/1.1") + + return client.Do(req) +} diff --git a/examples/demo10/utils/onem2m_req.go b/examples/demo10/utils/onem2m_req.go new file mode 100644 index 0000000000000000000000000000000000000000..7295ebcd0fa9c8d3152f01d1c6f450972d3f6472 --- /dev/null +++ b/examples/demo10/utils/onem2m_req.go @@ -0,0 +1,53 @@ +package utils + +import ( + "crypto/tls" + "encoding/base64" + "fmt" + "net/http" + "strings" + "time" + + "github.com/google/uuid" +) + +// MakeOneM2MRequest creates and sends a oneM2M HTTP request +func MakeOneM2MRequest(method, url, body string, ty int, originator string) (*http.Response, error) { + client := &http.Client{Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + Timeout: 10 * time.Second} + reqID := uuid.New().String() + + // if originator == "" { + // originator = AE_ID + // } + + headers := map[string]string{ + "X-M2M-Origin": originator, + "X-M2M-RI": reqID, + "X-M2M-RVI": "5", + "Accept": "application/json", + "Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("CAdmin:ikram123")), + } + + if method == "POST" { + headers["Content-Type"] = fmt.Sprintf("application/json;ty=%d", ty) + } + + req, err := http.NewRequest(method, url, strings.NewReader(body)) + if err != nil { + return nil, fmt.Errorf("failed to create request: %v", err) + } + + for key, value := range headers { + req.Header.Set(key, value) + } + + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %v", err) + } + + return resp, nil +} diff --git a/go-apps/meep-iot-pltf/meep-acme-in-cse/Dockerfile b/go-apps/meep-iot-pltf/meep-acme-in-cse/Dockerfile index 608b06b800c50b79f9201e653ace6fa65b787512..1eab6208e3b4d24ce74ea80a388a305479161f8b 100644 --- a/go-apps/meep-iot-pltf/meep-acme-in-cse/Dockerfile +++ b/go-apps/meep-iot-pltf/meep-acme-in-cse/Dockerfile @@ -1,4 +1,5 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 + ENV MQTT_ENABLE="" ENV MQTT_HOST="" ENV MQTT_PORT="" @@ -16,38 +17,17 @@ ENV MEC_SANDBOX_SERVER="" RUN echo "meep-acme-in-cse" > /etc/hostname \ && DEBIAN_FRONTEND=noninteractive apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y \ - autoconf \ - bison \ - build-essential \ - cmake \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ curl \ - dos2unix \ - doxygen \ - emacs \ - expect \ - flex \ - g++ \ - gcc \ gettext \ git \ gnutls-bin \ iputils-ping \ jq \ libedit2 \ - libedit-dev \ libffi-dev \ libglib2.0-dev \ - libgcrypt-dev \ - libjsoncpp-dev \ - libncurses5-dev \ - libpcap-dev \ libssl-dev \ - libtool-bin \ - libtool \ - libxml2-dev \ - libxml2-utils \ - libyaml-dev \ lsof \ ntp \ pkg-config \ @@ -55,24 +35,21 @@ RUN echo "meep-acme-in-cse" > /etc/hostname \ python3-pip \ python3-setuptools \ sudo \ - sshpass \ - tcpdump \ tzdata \ && DEBIAN_FRONTEND=noninteractive apt-get autoremove --purge -y \ && DEBIAN_FRONTEND=noninteractive apt-get autoclean \ && DEBIAN_FRONTEND=noninteractive apt-get clean \ - && pip3 install --no-cache-dir --upgrade pip + && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/app -#RUN git clone --branch development https://github.com/ankraft/ACME-oneM2M-CSE.git ACME-oneM2M-CSE -RUN git clone https://github.com/ankraft/ACME-oneM2M-CSE.git ACME-oneM2M-CSE +RUN git clone --branch development https://github.com/ankraft/ACME-oneM2M-CSE.git ACME-oneM2M-CSE WORKDIR /usr/src/app/ACME-oneM2M-CSE COPY ./data /usr/src/app/ACME-oneM2M-CSE RUN chmod +x entrypoint.sh \ - && pip3 install --no-cache-dir -r requirements.txt + && pip3 install --no-cache-dir -r requirements.txt --break-system-packages -ENTRYPOINT ["./entrypoint.sh"] +ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/go-apps/meep-iot-pltf/meep-acme-in-cse/acme.ini.in b/go-apps/meep-iot-pltf/meep-acme-in-cse/acme.ini.in index a2dbd1964b9b25f8151724de71331798b8306097..c434ab0ce34cba19317fb734e968d9554849a5bd 100644 --- a/go-apps/meep-iot-pltf/meep-acme-in-cse/acme.ini.in +++ b/go-apps/meep-iot-pltf/meep-acme-in-cse/acme.ini.in @@ -29,6 +29,9 @@ databaseType=memory logLevel=debug consoleTheme=dark +[cse] +poa=https://$SERVER_IP:443/$SVC_PATH + [mqtt] enable=$MQTT_ENABLE address=$MQTT_HOST @@ -37,12 +40,17 @@ keepalive=45 [mqtt.websocket] enable=$MQTT_ENABLE port=$MQTT_PORT -transport=websockets +;transport=websockets path=$WEBSOCK_ETPATH +[mqtt.security] +useTLS=true + [cse.registration] ; Edit this to add more allowed originators. -allowedCSROriginators=/$CSE_BASE_RI,/acme-mep-id-mn-cse,/id-in,/id-mn,/id-asn +;allowedCSROriginators=/$CSE_BASE_RI,/acme-mep-id-mn-cse,/id-in,/id-mn,/id-asn,/mep-id-mn-cse +allowedCSROriginators=/* +;address=https://${basic.config:registrarCseHost}:${basic.config:registrarCsePort} [textui] startWithTUI=false @@ -53,11 +61,17 @@ enable=true [http] enableUpperTesterEndpoint=true enableStructureEndpoint=true +root=/ +address=https://${basic.config:cseHost}:${basic.config:httpPort}${http:externalRoot} +externalRoot=/$SVC_PATH/ + +[webui] +root=/webui [coap] enable=$ENABLE_COAP port=5683 [websocket] -enable=$ENABLE_WS +enable=false port=8180 diff --git a/go-apps/meep-iot-pltf/meep-acme-in-cse/entrypoint.sh b/go-apps/meep-iot-pltf/meep-acme-in-cse/entrypoint.sh index 8bdd260bfaf01bbd9d9629bd6a00abfc803bceef..b6a40717113b0a5105fc31a1346c30c33e38fc94 100755 --- a/go-apps/meep-iot-pltf/meep-acme-in-cse/entrypoint.sh +++ b/go-apps/meep-iot-pltf/meep-acme-in-cse/entrypoint.sh @@ -2,7 +2,9 @@ set -e echo "MEEP_HOST_URL: ${MEEP_HOST_URL}" -SERVER_IP="${MEEP_HOST_URL#http://}"; MEEP_HOST_URL="${MEEP_HOST_URL#https://}" +# SERVER_IP="${MEEP_HOST_URL#http://}"; MEEP_HOST_URL="${MEEP_HOST_URL#https://}" +SERVER_IP="${MEEP_HOST_URL#http://}" +SERVER_IP="${SERVER_IP#https://}" echo "MEC_PLATFORM=$MEC_PLATFORM" echo "MEEP_SANDBOX_NAME=$MEEP_SANDBOX_NAME" @@ -21,21 +23,21 @@ echo "MQTT_USERNAME: ${MQTT_USERNAME}" echo "MQTT_PASSWORD: ${MQTT_PASSWORD}" # Retrieve the internal meep-mosquitto IP address -SERVICE_NAME="meep-cloud-mosquitto" +SERVICE_NAME="monaco-telecom-meep-cloud-mosquitto" NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) -MOSQUITTO_NODE_IP_ADDRESS=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.clusterIP') -echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_IP_ADDRESS" - -# Retrieve the internal meep-mosquitto port id -MOSQUITTO_NODE_PORT=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.ports[0].targetPort') -echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_PORT" +# MOSQUITTO_NODE_IP_ADDRESS=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.clusterIP') +# echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_IP_ADDRESS" + +# # Retrieve the internal meep-mosquitto port id +# MOSQUITTO_NODE_PORT=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.ports[0].targetPort') +# echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_PORT" if [[ ! -z "${MEEP_MEP_NAME}" ]]; then svcPath="${MEEP_SANDBOX_NAME}/${MEEP_MEP_NAME}" @@ -51,6 +53,8 @@ fi sleep 5 # Wait for ETSI MEC Platform up and stable +SVC_PATH="${svcPath}/meep-acme-in-cse" + SERVER_IP=`echo $SERVER_IP | sed -e "s/https:\/\///g"` # Remove https:// SERVER_PORT=${SERVER_PORT:-3003} MEC_SANDBOX_ID=${MEEP_SANDBOX_NAME:-"meep-sandbox"} @@ -62,12 +66,12 @@ ENABLE_WS=${ENABLE_WS:-false} # MQTT Configuration MQTT_ENABLE=${MQTT_ENABLE:-true} -MQTT_HOST=${MOSQUITTO_NODE_IP_ADDRESS:-"meep-cloud-mosquito"} +MQTT_HOST=${SERVER_IP:-"monaco-telecom-meep-cloud-mosquitto"} MQTT_PORT=${MOSQUITTO_NODE_PORT:-443} MQTT_USERNAME=${MQTT_USERNAME:-"acme-mn-cse"} MQTT_PASSWORD=${MQTT_PASSWORD:-"mqtt"} -WEBSOCK_ETPATH="/$MEC_SANDBOX_ID"${WEBSOCK_ETPATH:-"/monaco-telecom/meep-cloud-mosquitto"} +WEBSOCK_ETPATH="/$MEC_SANDBOX_ID"${WEBSOCK_ETPATH:-"/monaco-telecom/meep-mosquitto"} echo "Environment variables set:" echo "SERVER_TYPE: ${SERVER_TYPE}" @@ -83,6 +87,7 @@ echo "MQTT_PORT: ${MQTT_PORT}" echo "MQTT_USERNAME: ${MQTT_USERNAME}" echo "MQTT_PASSWORD: ${MQTT_PASSWORD}" echo "WEBSOCK_ETPATH: ${WEBSOCK_ETPATH}" +echo "SVC_PATH: ${SVC_PATH}" export SERVER_TYPE export SERVER_IP @@ -100,6 +105,8 @@ export MQTT_USERNAME export MQTT_PASSWORD export WEBSOCK_ETPATH +export SVC_PATH + workdir="/usr/src/app/ACME-oneM2M-CSE" cd "$workdir" || { echo "Directory $workdir not found"; exit 1; } envsubst < acme.ini.in > acme.ini diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/Dockerfile b/go-apps/meep-iot-pltf/meep-acme-mn-cse/Dockerfile index f7ad8e980425a754efde91a37ced8adfa6af1ab1..7ef8c3035259cd6c5ce584ccf0ec79b740b8be06 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/Dockerfile +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 ENV SERVER_TYPE="" ENV SERVER_IP="" @@ -24,40 +24,17 @@ ENV ACME_IN_SERVICE_NAME="" RUN echo "meep-acme-mn-cse" > /etc/hostname \ && DEBIAN_FRONTEND=noninteractive apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y \ - && DEBIAN_FRONTEND=noninteractive apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y \ - autoconf \ - bison \ - build-essential \ - cmake \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ curl \ - dos2unix \ - doxygen \ - emacs \ - expect \ - flex \ - g++ \ - gcc \ gettext \ git \ gnutls-bin \ iputils-ping \ jq \ libedit2 \ - libedit-dev \ libffi-dev \ libglib2.0-dev \ - libgcrypt-dev \ - libjsoncpp-dev \ - libncurses5-dev \ - libpcap-dev \ libssl-dev \ - libtool-bin \ - libtool \ - libxml2-dev \ - libxml2-utils \ - libyaml-dev \ lsof \ ntp \ pkg-config \ @@ -65,13 +42,11 @@ RUN echo "meep-acme-mn-cse" > /etc/hostname \ python3-pip \ python3-setuptools \ sudo \ - sshpass \ - tcpdump \ tzdata \ && DEBIAN_FRONTEND=noninteractive apt-get autoremove --purge -y \ && DEBIAN_FRONTEND=noninteractive apt-get autoclean \ && DEBIAN_FRONTEND=noninteractive apt-get clean \ - && pip3 install --no-cache-dir --upgrade pip + && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/app @@ -82,7 +57,7 @@ WORKDIR /usr/src/app/ACME-oneM2M-CSE COPY ./data /usr/src/app/ACME-oneM2M-CSE RUN chmod +x entrypoint.sh \ - && pip3 install --no-cache-dir -r requirements.txt + && pip3 install --no-cache-dir -r requirements.txt --break-system-packages ENTRYPOINT ["./entrypoint.sh"] diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme.ini.in b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme.ini.in index 5ef1483a8b4e864fc0d7239215ba50e37507c344..5115ca606092868df3160696a892e44ebb3669b2 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme.ini.in +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme.ini.in @@ -34,12 +34,18 @@ databaseType=memory logLevel=debug consoleTheme=dark +[cse] +poa=https://$SERVER_IP:443/$SVC_PATH + [cse.registration] ; Edit this to add more allowed originators. -allowedCSROriginators=/id-in,/id-mn,/id-asn +;allowedCSROriginators=/$REMOTE_CSE_ID,/laboai-id-in,/laboai-cse-in,/acme-mep-id-mn-cse,/id-in,/id-mn,/id-asn,/mep-id-mn-cse +allowedCSROriginators=/* [cse.registrar] INCSEcseID=/$REMOTE_CSE_ID +address=https://${basic.config:registrarCseHost}:${basic.config:registrarCsePort}/ +root=$REMOTE_SVC_PATH [textui] startWithTUI=false @@ -48,8 +54,14 @@ startWithTUI=false enable=true [http] -enableUpperTesterEndpoint=true -enableStructureEndpoint=true +enableUpperTesterEndpoint = true +enableStructureEndpoint = true +root=/ +address=https://${basic.config:cseHost}:${basic.config:httpPort}${http:externalRoot} +externalRoot=/$SVC_PATH/ + +[webui] +root=/webui [mqtt] enable=$MQTT_ENABLE @@ -59,17 +71,23 @@ keepalive=45 [mqtt.websocket] enable=$MQTT_ENABLE port=$MQTT_PORT -transport=websockets +;transport=websockets path=$WEBSOCK_ETPATH +[mqtt.security] +useTLS=true + [coap] enable=$ENABLE_COAP port=5683 [websocket] -enable=$ENABLE_WS +enable=false port=8180 +[logging] +enableBindingsLogging = false + [etsi_mec] mec_enable=$MEC_ENABLE mec_host=$MEC_HOST_URL @@ -79,3 +97,5 @@ mec_platform=$MEC_PLATFORM mec_sandbox_id=$MEC_SANDBOX_ID cse_external_ip=$CSE_EXTERNAL_IP cse_external_port=$CSE_EXTERNAL_PORT +fullAddress=$MN_CSE_FULL_ADDRESS +mec_app_instance_id=$MEC_APP_INSTANCE_ID \ No newline at end of file diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/protocols/MECClient.py b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/protocols/MECClient.py index 1eb8126344de7d50030dc798dfd4909c930350ab..08008b05350a1525738147c9644b086f4c16118c 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/protocols/MECClient.py +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/protocols/MECClient.py @@ -48,7 +48,9 @@ class MECClient(object): 'mqtt_port', 'wss_path', 'cse_resourceID', + 'fullAddress', 'isStopped', + 'mec_app_instance_id', 'mecConnection', 'mecConnections', 'isInfo', @@ -59,7 +61,9 @@ class MECClient(object): # TODO move config handling to event handler - def __init__(self, p_http_address: str, p_http_port: str, p_cse_resourceID: str, p_cse_external_ip: str, p_cse_external_port: str, p_use_wss: bool, p_mqtt_address: str, p_mqtt_port: str, p_wss_path: str = "") -> None: + def __init__(self, p_http_address: str, p_http_port: str, p_cse_resourceID: str, + p_cse_external_ip: str, p_cse_external_port: str, p_use_wss: bool, p_mqtt_address: str, + p_mqtt_port: str, p_fullAddress: str, p_mec_app_instance_id: str , p_wss_path: str = "") -> None: """ Initialize the MEC client. """ self.http_address = p_http_address @@ -73,6 +77,8 @@ class MECClient(object): self.mqtt_address = p_mqtt_address self.mqtt_port = p_mqtt_port self.wss_path = p_wss_path + self.fullAddress = p_fullAddress + self.mec_app_instance_id = p_mec_app_instance_id self.isStopped = False """ Flag to indicate whether the MEC client is stopped. """ @@ -213,7 +219,7 @@ class MECClient(object): userTransportInfoList = [] userTransportInfo = {} userTransportInfo['id'] = str(uuid.uuid4()) - userTransportInfo['name'] = self.cse_resourceID + userTransportInfo['name'] = Configuration.cse_cseID userTransportInfo['type'] = 'MB_TOPIC_BASED' if self.use_wss: userTransportInfo['description'] = 'MQTT over WS-Secured' @@ -223,37 +229,42 @@ class MECClient(object): userTransportInfo['protocol'] = 'MQTT' userTransportInfo['version'] = '2' userTransportInfo['endpoint'] = {} + # userTransportInfo['endpoint']['addresses'] = [] + # The MEC API expects an array of URIs for the endpoint 'uris' field. + # Previously this was set to a single string which caused the server + # to return: "cannot unmarshal string into Go struct field ... uris of type []string". if self.use_wss: userTransportInfo['endpoint']['uris'] = [] userTransportInfo['endpoint']['uris'].append('wss://' + self.mqtt_address + ':' + str(self.mqtt_port) + self.wss_path) - address = {} - address['host'] = self.mqtt_address - address['port'] = self.mqtt_port - userTransportInfo['endpoint']['addresses'].append(address) else: userTransportInfo['endpoint']['addresses'] = [] address = {} address['host'] = self.mqtt_address address['port'] = self.mqtt_port userTransportInfo['endpoint']['addresses'].append(address) + # userTransportInfo['endpoint']['uris'] = [ self.fullAddress ] + # address = {} + # address['host'] = self.mqtt_address + # address['port'] = self.mqtt_port + # userTransportInfo['endpoint']['addresses'].append(address) userTransportInfo['security'] = {} userTransportInfo['implSpecificInfo'] = {} userTransportInfoList.append(userTransportInfo) body_json['userTransportInfo'] = userTransportInfoList customServicesTransportInfoList = [] customServicesTransportInfo = {} - customServicesTransportInfo['id'] = str(uuid.uuid4()) - customServicesTransportInfo['name'] = self.cse_resourceID - customServicesTransportInfo['description'] = 'ACME oneM2M CSE' + # customServicesTransportInfo['id'] = str(uuid.uuid4()) + customServicesTransportInfo['id'] = Configuration.cse_cseID + customServicesTransportInfo['name'] = Configuration.cse_resourceName + customServicesTransportInfo['description'] = 'ACME oneM2M CSE ID' customServicesTransportInfo['type'] = 'REST_HTTP' customServicesTransportInfo['protocol'] = 'REST_HTTP' customServicesTransportInfo['version'] = '4' customServicesTransportInfo['endpoint'] = {} - customServicesTransportInfo['endpoint']['addresses'] = [] - address = {} - address['host'] = self.cse_external_ip - address['port'] = int(self.http_port) #int(self.cse_external_port) - customServicesTransportInfo['endpoint']['addresses'].append(address) + if self.fullAddress == '': + customServicesTransportInfo['endpoint']['uris'] = [ 'https://' + self.cse_external_ip + ':' + str(self.http_port) ] + else: + customServicesTransportInfo['endpoint']['uris'] = [ self.fullAddress ] customServicesTransportInfo['security'] = {} customServicesTransportInfoList.append(customServicesTransportInfo) body_json['customServicesTransportInfo'] = customServicesTransportInfoList @@ -262,7 +273,7 @@ class MECClient(object): tries = 0 while tries < 5: - response = requests.post(url, headers=self.headers, json=body_json) + response = requests.post(url, headers=self.headers, json=body_json, verify=False) L.isInfo and L.log(f'MECClient.registerToMec: response.content: ' + str(response.content)) if response.status_code == 201: self.register = Result() @@ -292,7 +303,7 @@ class MECClient(object): '/' + Configuration.mec_sandbox_id + \ '/' + Configuration.mec_platform + \ '/iots/v1/registered_iot_platforms/' + json_dict['iotPlatformId'] - response = requests.delete(url, headers=self.headers) + response = requests.delete(url, headers=self.headers, verify=False) self.register = None return Result(rsc = response.status_code) except Exception as e: @@ -300,3 +311,78 @@ class MECClient(object): self.register = None return Result(rsc = ResponseStatusCode.INTERNAL_SERVER_ERROR, dbg = 'MEC Deregistration failure') + + def confirm_readyToMec(self) -> Result: + """ Confirm readiness to MEC platform. + """ + if self.isStopped: + return Result(rsc = ResponseStatusCode.INTERNAL_SERVER_ERROR, dbg = 'MEC client is not running') + + try: + req_body = { + "indication": "READY" + } + url = \ + Configuration.mec_protocol + '://' +Configuration.mec_host + ':' + str(Configuration.mec_port) + \ + '/' + Configuration.mec_sandbox_id + \ + '/' + Configuration.mec_platform + \ + '/mec_app_support/v2/applications/' + self.mec_app_instance_id + '/confirm_ready' + L.log('MECClient.confirm_readyToMec: ' + str(req_body)) + L.log('MECClient.confirm_readyToMec: ' + str(url)) + response = requests.post(url, headers=self.headers, json=req_body, verify=False) + return Result(rsc = response.status_code) + except Exception as e: + L.logErr(f'MECClient.confirm_readyToMec: ' + str(e)) + return Result(rsc = ResponseStatusCode.INTERNAL_SERVER_ERROR, dbg = 'MEC Confirm readiness failure') + + def post_mec_service(self) -> Result: + """ + Declare MEC service to MEC platform. + This function declares MN-CSE as MEC service to the MEC platform. + """ + if self.isStopped: + return Result(rsc = ResponseStatusCode.INTERNAL_SERVER_ERROR, dbg = 'MEC client is not running') + + try: + req_body = { + "serName": Configuration.cse_resourceName, + "serCategory": { + "href": "catalogueHref", + "id": Configuration.cse_cseID, + "name": Configuration.cse_resourceName, + "version": "v1" + }, + "version": "v1.0.0", + "state": "ACTIVE", + "transportInfo": { + "id": "acme-mn-cse-transport", + "name": "REST", + "type": "REST_HTTP", + "protocol": "HTTPS", + "version": "4.0", + "endpoint": { + "uris": [ + self.fullAddress + ], + "fqdn": None, + "addresses": None, + "alternative": None + }, + "security": None + }, + "serializer": "JSON", + "scopeOfLocality": "MEC_SYSTEM", + "consumedLocalOnly": True + } + url = \ + Configuration.mec_protocol + '://' + Configuration.mec_host + ':' + str(Configuration.mec_port) + \ + '/' + Configuration.mec_sandbox_id + \ + '/' + Configuration.mec_platform + \ + '/mec_service_mgmt/v1/applications/' + self.mec_app_instance_id + '/services' + L.log('MECClient.POST_mec_service: ' + str(req_body)) + L.log('MECClient.POST_mec_service: ' + str(url)) + response = requests.post(url, headers=self.headers, json=req_body, verify=False) + return Result(rsc = response.status_code) + except Exception as e: + L.logErr(f'MECClient.POST_mec_service: ' + str(e)) + return Result(rsc = ResponseStatusCode.INTERNAL_SERVER_ERROR, dbg = 'MEC Declare MEC service failure') \ No newline at end of file diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/CSE.py b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/CSE.py index d4311f7a7334e1cfb2c3d33daca71bdd90af6ff3..b1b0ad0185f048ab9933e64f0b3f2fe75842746a 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/CSE.py +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/CSE.py @@ -37,6 +37,7 @@ from ..services.GroupManager import GroupManager from ..runtime.Importer import Importer from ..services.LocationManager import LocationManager from ..services.NotificationManager import NotificationManager +from ..runtime.PluginManager import PluginManager from ..services.RegistrationManager import RegistrationManager from ..services.RemoteCSEManager import RemoteCSEManager from ..runtime.ScriptManager import ScriptManager @@ -97,6 +98,9 @@ mqttClient:MQTTClient = None notification:NotificationManager = None """ Runtime instance of the `NotificationManager`. """ +pluginManager:PluginManager = None +""" Runtime instance of the `PluginManager`. """ + registration:RegistrationManager = None """ Runtime instance of the `RegistrationManager`. """ @@ -159,7 +163,7 @@ def startup(args:argparse.Namespace, **kwargs:Dict[str, Any]) -> bool: False if the CSE couldn't initialized and started. """ global action, announce, coapServer, console, dispatcher, event, groupResource, httpServer, importer, location, mqttClient, mecClient - global notification, registration, remote, request, script, security, semantic, statistics, storage, textUI, time + global notification, pluginManager, registration, remote, request, script, security, semantic, statistics, storage, textUI, time global timeSeries, validator, webSocketServer # Set status @@ -228,14 +232,12 @@ def startup(args:argparse.Namespace, **kwargs:Dict[str, Any]) -> bool: if Configuration.mec_enable: L.log('Initializing MEC client') - - # Initialize the MEC client if Configuration.mqtt_websocket_enable: - mecClient = MECClient(Configuration.http_address, Configuration.http_port, Configuration.cse_resourceID, Configuration.cse_external_ip, Configuration.cse_external_port, Configuration.mqtt_websocket_enable, Configuration.mqtt_address, Configuration.mqtt_websocket_port, Configuration.mec_platform+"/"+Configuration.mec_sandbox_id+"/"+) + mecClient = MECClient(Configuration.http_address, Configuration.http_port, Configuration.cse_resourceID, Configuration.cse_external_ip, Configuration.cse_external_port, Configuration.mqtt_websocket_enable, Configuration.mqtt_address, Configuration.mqtt_websocket_port, Configuration.fullAddress, Configuration.mec_app_instance_id, Configuration.mqtt_websocket_path) else: - mecClient = MECClient(Configuration.http_address, Configuration.http_port, Configuration.cse_resourceID, Configuration.cse_external_ip, Configuration.cse_external_port, Configuration.mqtt_websocket_enable, Configuration.mqtt_address, Configuration.mqtt_port) + mecClient = MECClient(Configuration.http_address, Configuration.http_port, Configuration.cse_resourceID, Configuration.cse_external_ip, Configuration.cse_external_port, Configuration.mqtt_websocket_enable, Configuration.mqtt_address, Configuration.mqtt_port, Configuration.fullAddress, Configuration.mec_app_instance_id) if mecClient is None: - Configuration.mec_enable = False + Configuration.mec_enable = False # → Experimental late loading # @@ -256,6 +258,11 @@ def startup(args:argparse.Namespace, **kwargs:Dict[str, Any]) -> bool: RC.cseStatus = CSEStatus.STOPPED return False + # Initialize the plugin manager + # This loads, configures and runs the plugins as well + pluginManager = PluginManager() + + # Start the HTTP server if not httpServer.run(): # This does return (!) L.logErr('Terminating', showStackTrace = False) @@ -284,8 +291,13 @@ def startup(args:argparse.Namespace, **kwargs:Dict[str, Any]) -> bool: L.logErr(f'Error during startup: {e.dbg}') RC.cseStatus = CSEStatus.STOPPED return False + except KeyError as e: + L.logErr(f'Error during startup: {e}') + RC.cseStatus = CSEStatus.STOPPED + return False + except Exception as e: - L.logErr(f'Error during startup: {e}', exc = e) + L.logErr(f'Error during startup: {e}', exc=e) RC.cseStatus = CSEStatus.STOPPED return False @@ -311,7 +323,7 @@ def startup(args:argparse.Namespace, **kwargs:Dict[str, Any]) -> bool: def shutdown() -> None: - """ Gracefully shutdown the CSE programmatically. This will end the mail console loop + """ Gracefully shutdown the CSE programmatically. This will end the main console loop to terminate. The actual shutdown happens in the _shutdown() method. @@ -351,6 +363,7 @@ def _shutdown() -> None: event.cseShutdown() # type: ignore # shutdown the services + pluginManager and pluginManager.shutdown() textUI and textUI.shutdown() console and console.shutdown() time and time.shutdown() @@ -453,7 +466,7 @@ def resetCSE() -> None: # Enable log queuing again L.queueOn() - # Send restart event + # Send restarted event event.cseRestarted() # type: ignore [attr-defined] RC.cseStatus = CSEStatus.RUNNING @@ -481,9 +494,11 @@ def run() -> None: L.logDebug(f'MEC enable: {Configuration.mec_enable}') if Configuration.mec_enable: + mecClient.confirm_readyToMec() + mecClient.post_mec_service() mecClient.registerToMec() - if waitFor(C.cseStartupDelay * 3, lambda: RC.cseStatus == CSEStatus.RUNNING): + if waitFor(C.cseStartupDelay * 3, lambda: RC.cseStatus==CSEStatus.RUNNING): console.run() else: raise TimeoutError(L.logErr(f'CSE did not start within {C.cseStartupDelay * 3} seconds')) diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/Configuration.py b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/Configuration.py index a44cf2b7b3e42d39b0ba28fa8d8bd77b96fbedfb..36b6132148e3959261f0d716247ebe3791280397 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/Configuration.py +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/Configuration.py @@ -16,6 +16,7 @@ from typing import Any, Dict, Tuple, Optional, cast, Set import configparser, argparse, os, os.path, pathlib from copy import deepcopy from inspect import getmembers +from dotenv import load_dotenv, find_dotenv from rich.console import Console @@ -53,6 +54,9 @@ class Configuration(object): """ + configParser:ACMEConfiguration = None + """ The ACMEConfiguration instance holding the configuration values. """ + coap_enable:bool """ Enable or disable the CoAP server. """ @@ -200,6 +204,14 @@ class Configuration(object): """ The size of the operation requests. """ + cse_operation_plugins_disabledPlugins:list[str] + """ A list of disabled plugins. """ + + cse_operation_plugins_replace:bool + """ Replace existing plugins with the same name. """ + + + cse_registrars:dict[str, CSERegistrar] = {} """ A dictionary of CSE or service provider CSEs registrars. The keys are the CSE IDs, the values are dictionaries with the registrar information. """ @@ -265,6 +277,8 @@ class Configuration(object): database_postgresql_schema:str """ The schema of the PostgreSQL database. """ + fullAddress:str + """ The full address of the MN-CSE. """ http_address:str """ The address to listen on for HTTP the http server. """ @@ -290,6 +304,9 @@ class Configuration(object): http_root:str """ The root of the HTTP path. """ + http_externalRoot:str + """ The non-local root path of the HTTP path. This is used when the CSE is accessed from non-local addresses, e.g. in a Kubernetes cluster. """ + http_timeout:float """ The timeout for HTTP requests. """ @@ -375,6 +392,8 @@ class Configuration(object): logging_enableUTCTimezone:bool """ Enable or disable UTC timezone. """ + mec_app_instance_id:str + """ MEC application instance id. """ mqtt_address:str """ The address to listen on for the MQTT server. """ @@ -856,7 +875,7 @@ class Configuration(object): zk.disconnect() # Read and parse the configuration file - config = ACMEConfiguration() + Configuration.configParser = ACMEConfiguration() # Construct the default values that are used for interpolation _defaults = { 'basic.config': { @@ -877,35 +896,45 @@ class Configuration(object): 'secret' : os.getenv('ACME_SECURITY_SECRET', 'acme'), # The main secret key for the CSE. } } + # Load environment variables from .env file from the base directory, if it exists + load_dotenv(dotenv_path=f'{Configuration.baseDirectory}{os.path.sep}.env') + # Add environment variables to the defaults _defaults.update({ 'DEFAULT': {k: v.replace('$', '$$') for k,v in os.environ.items()} }) # Add (empty) default for supported environment variables to the defaults dictionary for the interpolation during reading the configuration file _envVariables = { e: os.getenv(e, '') if e not in _defaults else _defaults[e] for e in ( - 'ACME_MQTT_SECURITY_PASSWORD', 'ACME_MQTT_SECURITY_USERNAME', + 'ACME_MQTT_SECURITY_PASSWORD', + 'ACME_MQTT_SECURITY_USERNAME', 'ACME_DATABASE_POSTGRESQL_PASSWORD', - 'ACME_CSE_REGISTRAR_SECURITY_HTTPUSERNAME', 'ACME_CSE_REGISTRAR_SECURITY_HTTPPASSWORD', 'ACME_CSE_REGISTRAR_SECURITY_HTTPBEARERTOKEN', - 'ACME_CSE_REGISTRAR_SECURITY_WSUSERNAME', 'ACME_CSE_REGISTRAR_SECURITY_WSPASSWORD', 'ACME_CSE_REGISTRAR_SECURITY_WSBEARERTOKEN', - 'ACME_CSE_REGISTRAR_SECURITY_SELFHTTPUSERNAME', 'ACME_CSE_REGISTRAR_SECURITY_SELFHTTPPASSWORD', - 'ACME_CSE_REGISTRAR_SECURITY_SELFWSUSERNAME', 'ACME_CSE_REGISTRAR_SECURITY_SELFWSPASSWORD', + 'ACME_CSE_REGISTRAR_SECURITY_HTTPUSERNAME', + 'ACME_CSE_REGISTRAR_SECURITY_HTTPPASSWORD', + 'ACME_CSE_REGISTRAR_SECURITY_HTTPBEARERTOKEN', + 'ACME_CSE_REGISTRAR_SECURITY_WSUSERNAME', + 'ACME_CSE_REGISTRAR_SECURITY_WSPASSWORD', + 'ACME_CSE_REGISTRAR_SECURITY_WSBEARERTOKEN', + 'ACME_CSE_REGISTRAR_SECURITY_SELFHTTPUSERNAME', + 'ACME_CSE_REGISTRAR_SECURITY_SELFHTTPPASSWORD', + 'ACME_CSE_REGISTRAR_SECURITY_SELFWSUSERNAME', + 'ACME_CSE_REGISTRAR_SECURITY_SELFWSPASSWORD', ) } _defaults['DEFAULT'].update(_envVariables) # Set the defaults - config.read_dict(_defaults) + Configuration.configParser.read_dict(_defaults) try: # Read the configuration files # if len(config.read( [Configuration._defaultConfigFile, Configuration.configfile])) == 0 and Configuration._args_configfile != C.defaultUserConfigFile: # Allow - if len(config.read(configurationFiles)) == 0 and Configuration._args_configfile != C.defaultUserConfigFile: # Allow + if len(Configuration.configParser.read(configurationFiles)) == 0 and Configuration._args_configfile != C.defaultUserConfigFile: # Allow Configuration._print(f'[red]Configuration file missing or not readable: {Configuration._args_configfile}') return False # Read the extra configuration strings (e.g. from Zookeeper) for cs in configurationStrings: - config.read_string(cs) + Configuration.configParser.read_string(cs) except configparser.Error as e: Configuration._print('[red]Error in configuration file') @@ -916,7 +945,7 @@ class Configuration(object): # Look for deprecated and renamed sections and print an error message if _deprecatedSections: for o, n in _deprecatedSections: - if config.has_section(o): + if Configuration.configParser.has_section(o): Configuration._print(fr'[red]Found old section name in configuration file. Please rename "\[{o}]" to "\[{n}]".') return False @@ -928,7 +957,7 @@ class Configuration(object): # and to set the respective attributes in the Configuration class. # Validations are done later below. for m in _moduleConfigs: - m.readConfiguration(config, Configuration) # type:ignore [arg-type] + m.readConfiguration(Configuration.configParser, Configuration) # type:ignore [arg-type] except configparser.InterpolationMissingOptionError as e: Configuration._print(f'[red]Error in configuration file: {Configuration.configfile}\n{str(e)}') @@ -979,8 +1008,8 @@ class Configuration(object): attr = getattr(Configuration, k) match attr: case pathlib.Path(): - # Convert pathlib.Path to string - attr = str(attr) + # Don't change the original dict, so make a copy + attr = deepcopy(attr) case dict(): # Convert dict elements to instances dict, if necessary for k2,v2 in attr.items(): @@ -990,8 +1019,7 @@ class Configuration(object): # Replace underscores with dots in the key names result[k.replace('_', '.')] = attr - result = deepcopy(result) # make sure that the result is a deep copy of the configuration - return result + return deepcopy(result) # make sure that the result is a deep copy of the configuration @staticmethod diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/configurations/MECClientConfiguration.py b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/configurations/MECClientConfiguration.py index be6bf4a1ed8adc9ca5424fd017b9e0f73d0c4233..c94fb6bbeaef92e8503f2000ffbea467b20baafe 100644 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/configurations/MECClientConfiguration.py +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/acme/runtime/configurations/MECClientConfiguration.py @@ -35,6 +35,8 @@ class MECClientConfiguration(ModuleConfiguration): config.mec_protocol = parser.get('etsi_mec', 'mec_protocol', fallback = 'https') config.mec_platform = parser.get('etsi_mec', 'mec_platform', fallback = 'mep1') config.mec_sandbox_id = parser.get('etsi_mec', 'mec_sandbox_id', fallback = 'mec_sandbox_id') + config.fullAddress = parser.get('etsi_mec', 'fullAddress', fallback = None) + config.mec_app_instance_id = parser.get('etsi_mec', 'mec_app_instance_id', fallback = None) def validateConfiguration(self, config:Configuration, initial:Optional[bool] = False) -> None: """ Validate the configuration. @@ -61,5 +63,9 @@ class MECClientConfiguration(ModuleConfiguration): Configuration.cse_external_ip = Configuration._cse_external_ip if Configuration._cse_external_port is not None: Configuration.cse_external_port = Configuration._cse_external_port + if Configuration.fullAddress is not None: + Configuration.fullAddress = Configuration.fullAddress + if Configuration.mec_app_instance_id is not None: + Configuration.mec_app_instance_id = Configuration.mec_app_instance_id config.mec_host = normalizeURL(config.mec_host) diff --git a/go-apps/meep-iot-pltf/meep-acme-mn-cse/entrypoint.sh b/go-apps/meep-iot-pltf/meep-acme-mn-cse/entrypoint.sh index c1fce9fb1bddc1fb79fc633375fcb5e848109cef..feba66c5143b1c5c8c6597146b4de8309b77f325 100755 --- a/go-apps/meep-iot-pltf/meep-acme-mn-cse/entrypoint.sh +++ b/go-apps/meep-iot-pltf/meep-acme-mn-cse/entrypoint.sh @@ -2,9 +2,12 @@ set -e echo "MEEP_HOST_URL: ${MEEP_HOST_URL}" -SERVER_IP="${MEEP_HOST_URL#http://}"; MEEP_HOST_URL="${MEEP_HOST_URL#https://}" +# SERVER_IP="${MEEP_HOST_URL#http://}"; MEEP_HOST_URL="${MEEP_HOST_URL#https://}" +SERVER_IP="${MEEP_HOST_URL#http://}" +SERVER_IP="${SERVER_IP#https://}" -echo "MEC_PLATFORM=$MEC_PLATFORM" +echo "MEEP_HOST_URL: ${MEEP_HOST_URL}" +echo "MEC_PLATFORM=$MEEP_MEP_NAME" echo "MEEP_SANDBOX_NAME=$MEEP_SANDBOX_NAME" # Other environment variables @@ -19,6 +22,7 @@ echo "MQTT_HOST: ${MQTT_HOST}" echo "MQTT_PORT: ${MQTT_PORT}" echo "MQTT_USERNAME: ${MQTT_USERNAME}" echo "MQTT_PASSWORD: ${MQTT_PASSWORD}" +echo "APP_INSTANCE_ID: ${MEEP_INSTANCE_ID}" sleep 10 # Wait for the MEC platform to stablize and acme in cse to be ready @@ -26,62 +30,62 @@ sleep 10 # Wait for the MEC platform to stablize and acme in cse to be ready SERVICE_NAME="meep-mosquitto" NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) -MOSQUITTO_NODE_IP_ADDRESS=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.clusterIP') -echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_IP_ADDRESS" - -# Retrieve the internal meep-mosquitto port id -MOSQUITTO_NODE_PORT=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.ports[0].targetPort') -echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_PORT" - -# Retrieve the internal meep-acme-in-cse IP address -SERVICE_NAME="meep-acme-in-cse" -REMOTE_CSE_IP_ADDRESS=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.clusterIP') -echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $REMOTE_CSE_IP_ADDRESS" - -# Retrieve the internal meep-acme-in-cse port id -SERVICE_NAME="meep-acme-in-cse" -NODE_PORT_IN_CSE=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.ports[0].targetPort') -echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_PORT_IN_CSE" - -SERVICE_NAME="meep-acme-mn-cse" -NODE_IP=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.clusterIP') -echo "External NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_IP" -NODE_PORT=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ - | jq -r '.spec.ports[0].nodePort') -echo "External NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_PORT" +# MOSQUITTO_NODE_IP_ADDRESS=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.clusterIP') +# echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_IP_ADDRESS" + +# # Retrieve the internal meep-mosquitto port id +# MOSQUITTO_NODE_PORT=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.ports[0].targetPort') +# echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $MOSQUITTO_NODE_PORT" + +# # Retrieve the internal meep-acme-in-cse IP address +# SERVICE_NAME="meep-acme-in-cse" +# REMOTE_CSE_IP_ADDRESS=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.clusterIP') +# echo "Internal IP exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $REMOTE_CSE_IP_ADDRESS" + +# # Retrieve the internal meep-acme-in-cse port id +# SERVICE_NAME="meep-acme-in-cse" +# NODE_PORT_IN_CSE=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.ports[0].targetPort') +# echo "Internal NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_PORT_IN_CSE" + +# SERVICE_NAME="meep-acme-mn-cse" +# NODE_IP=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.clusterIP') +# echo "External NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_IP" +# NODE_PORT=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/services/$SERVICE_NAME \ +# | jq -r '.spec.ports[0].nodePort') +# echo "External NodePort exposed for service [$SERVICE_NAME] in namespace [$NAMESPACE] is: $NODE_PORT" # The following name is the one name used to represent its block in scenario at endpoint /alt -ACME_IN_SERVICE_NAME=${ACME_IN_SERVICE_NAME:-"om2m-acme-in-cse"} -# Fetch pod name acme in cse -POD_NAME=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods \ - | jq -r --arg svc "$ACME_IN_SERVICE_NAME" '.items[] | select(.metadata.labels.app == $svc) | .metadata.name' | head -n 1) -echo "Pod name for service [$ACME_IN_SERVICE_NAME] in namespace [$NAMESPACE] is: $POD_NAME" - -# Step 2: Get the MEEP_MEP_NAME of ACME IN CSE environment variable from the pod -ACME_MEEP_MEP_NAME=$(curl -sSk \ - -H "Authorization: Bearer $TOKEN" \ - https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/$POD_NAME \ - | jq -r '.spec.containers[0].env[] | select(.name=="MEEP_MEP_NAME") | .value') -echo "MEEP_MEP_NAME for service [$ACME_IN_SERVICE_NAME] in namespace [$NAMESPACE] is: $ACME_MEEP_MEP_NAME" +# ACME_IN_SERVICE_NAME=${ACME_IN_SERVICE_NAME:-"monaco-telecom-meep-acme-in-cse"} +# # Fetch pod name acme in cse +# POD_NAME=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods \ +# | jq -r --arg svc "$ACME_IN_SERVICE_NAME" '.items[] | select(.metadata.labels.app == $svc) | .metadata.name' | head -n 1) +# echo "Pod name for service [$ACME_IN_SERVICE_NAME] in namespace [$NAMESPACE] is: $POD_NAME" + +# # Step 2: Get the MEEP_MEP_NAME of ACME IN CSE environment variable from the pod +# ACME_MEEP_MEP_NAME=$(curl -sSk \ +# -H "Authorization: Bearer $TOKEN" \ +# https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/$POD_NAME \ +# | jq -r '.spec.containers[0].env[] | select(.name=="MEEP_MEP_NAME") | .value') +# echo "MEEP_MEP_NAME for service [$ACME_IN_SERVICE_NAME] in namespace [$NAMESPACE] is: $ACME_MEEP_MEP_NAME" if [[ ! -z "${MEEP_MEP_NAME}" ]]; then svcPath="${MEEP_SANDBOX_NAME}/${MEEP_MEP_NAME}" @@ -99,34 +103,42 @@ SERVER_IP=`echo $SERVER_IP | sed -e "s/https:\/\///g"` # Remove https:// SERVER_TYPE=${SERVER_TYPE:-"MN"} SERVER_PORT=${SERVER_PORT:-3004} +# MN-CSE Address + CSE_BASE_NAME=${CSE_BASE_NAME:-"mep-cse-mn"} CSE_BASE_RI=${CSE_BASE_RI:-"acme-mep-id-mn-cse"} +MN_CSE_FULL_ADDRESS="https://${SERVER_IP}/${svcPath}/meep-acme-mn-cse" # REMOTE_CSE_HOST="${REMOTE_CSE_IP_ADDRESS:-"meep-acme-in-cse"}" # REMOTE_CSE_PORT=${NODE_PORT_IN_CSE:-3003} REMOTE_CSE_HOST=${SERVER_IP:-"meep-acme-in-cse"} -REMOTE_CSE_PORT=80/${MEEP_SANDBOX_NAME}/${ACME_MEEP_MEP_NAME:-"mep1"}/meep-acme-in-cse +# REMOTE_CSE_PORT=443/${MEEP_SANDBOX_NAME}/${ACME_MEEP_MEP_NAME:-"monaco-telecom"}/meep-acme-in-cse +REMOTE_CSE_PORT=443 +REMOTE_SVC_PATH=${MEEP_SANDBOX_NAME}/${ACME_MEEP_MEP_NAME:-"monaco-telecom"}/meep-acme-in-cse REMOTE_CSE_ID=${REMOTE_CSE_ID:-"laboai-id-in"} REMOTE_CSE_NAME=${REMOTE_CSE_NAME:-"laboai-cse-in"} ENABLE_COAP=${ENABLE_COAP:-false} ENABLE_WS=${ENABLE_WS:-false} -CSE_EXTERNAL_IP=${NODE_IP} -CSE_EXTERNAL_PORT=${NODE_PORT} +CSE_EXTERNAL_IP=${SERVER_IP} +CSE_EXTERNAL_PORT=${NODE_PORT:-443} # MEC Configuration MEC_ENABLE=${MEC_ENABLE:-true} MEC_HOST_URL=${SERVER_IP} -MEC_PLATFORM=${MEC_PLATFORM:-"mep1"} +MEC_PLATFORM=${MEEP_MEP_NAME:-"mep1"} MEC_SANDBOX_ID=${MEEP_SANDBOX_NAME:-"meep-sandbox"} +MEC_APP_INSTANCE_ID=${MEEP_INSTANCE_ID:-"meep-acme-mn-cse-instance"} # MQTT Configuration MQTT_ENABLE=${MQTT_ENABLE:-true} -MQTT_HOST=${MOSQUITTO_NODE_IP_ADDRESS:-"meep-mosquito"} -MQTT_PORT=${MOSQUITTO_NODE_PORT:-443} +MQTT_HOST=${SERVER_IP:-"meep-mosquito"} +MQTT_PORT=443 MQTT_USERNAME=${MQTT_USERNAME:-"acme-mn-cse"} MQTT_PASSWORD=${MQTT_PASSWORD:-"mqtt"} -WEBSOCK_ETPATH="/$MEC_SANDBOX_ID"${WEBSOCK_ETPATH:-"/monaco-telecom/meep-cloud-mosquitto"} +WEBSOCK_ETPATH="/$MEC_SANDBOX_ID"${WEBSOCK_ETPATH:-"/monaco-telecom/meep-mosquitto"} + +SVC_PATH="${svcPath}/meep-acme-mn-cse" echo "Environment variables set:" echo "SERVER_TYPE: ${SERVER_TYPE}" @@ -147,15 +159,21 @@ echo "MQTT_USERNAME: ${MQTT_USERNAME}" echo "MQTT_PASSWORD: ${MQTT_PASSWORD}" echo "MEC_ENABLE: ${MEC_ENABLE}" echo "MEC_HOST_URL: ${MEC_HOST_URL}" -echo "MEC_PLATFORM: ${MEC_PLATFORM}" +echo "MEC_PLATFORM: ${MEEP_MEP_NAME}" echo "MEC_SANDBOX_ID: ${MEC_SANDBOX_ID}" echo "ENABLE_COAP: ${ENABLE_COAP}" echo "ENABLE_WS: ${ENABLE_WS}" echo "WEBSOCK_ETPATH: ${WEBSOCK_ETPATH}" +echo "MN_CSE_FULL_ADDRESS: ${MN_CSE_FULL_ADDRESS}" +echo "MEC_APP_INSTANCE_ID: ${MEC_APP_INSTANCE_ID}" +echo "SVC_PATH: ${SVC_PATH}" +echo "REMOTE_SVC_PATH: ${REMOTE_SVC_PATH}" export SERVER_TYPE export SERVER_IP export SERVER_PORT +export MN_CSE_FULL_ADDRESS +export MEC_APP_INSTANCE_ID export CSE_BASE_NAME export CSE_BASE_RI @@ -163,6 +181,7 @@ export REMOTE_CSE_ID export REMOTE_CSE_NAME export REMOTE_CSE_HOST export REMOTE_CSE_PORT +export REMOTE_SVC_PATH export CSE_EXTERNAL_IP export CSE_EXTERNAL_PORT export ENABLE_COAP @@ -180,6 +199,8 @@ export MEC_HOST_URL export MEC_PLATFORM export MEC_SANDBOX_ID +export SVC_PATH + workdir="/usr/src/app/ACME-oneM2M-CSE" cd "$workdir" || { echo "Directory $workdir not found"; exit 1; } envsubst < acme.ini.in > acme.ini diff --git a/go-apps/meep-iot/server/meep-iot.go b/go-apps/meep-iot/server/meep-iot.go index cb1c1f27c7473a3cec915a6b3bd258558a4c6903..9ebf3a1ee412ddf25ccbb88acc06b9b336d2db4e 100644 --- a/go-apps/meep-iot/server/meep-iot.go +++ b/go-apps/meep-iot/server/meep-iot.go @@ -755,9 +755,9 @@ func registerediotplatformsPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Mandatory attribute Type_ shall be set to MB_TOPIC_BASED in the request body.", http.StatusBadRequest) return } - if v.Protocol != "MQTT" && v.Protocol != "AMQP" { - log.Error("Mandatory Protocol parameter shall be set to MQTT or AMQP") - errHandlerProblemDetails(w, "Mandatory attribute Protocol shall be set to MQTT or AMQP in the request body.", http.StatusBadRequest) + if v.Protocol != "MQTT" && v.Protocol != "MQTT+WSS" && v.Protocol != "AMQP" { + log.Error("Mandatory Protocol parameter shall be set to MQTT, MQTT+WSS or AMQP") + errHandlerProblemDetails(w, "Mandatory attribute Protocol shall be set to MQTT, MQTT+WSS or AMQP in the request body.", http.StatusBadRequest) return } if v.Version == "" { diff --git a/go-apps/meep-sandbox-ctrl/server/app-ctrl.go b/go-apps/meep-sandbox-ctrl/server/app-ctrl.go index a798cd5133979a01a1885a83206bb5a789ca7a41..0e9cdc8944351221def4f8d0dc08e8fa56bdd266 100644 --- a/go-apps/meep-sandbox-ctrl/server/app-ctrl.go +++ b/go-apps/meep-sandbox-ctrl/server/app-ctrl.go @@ -250,18 +250,23 @@ func getScenarioAppInstanceList(activeModel *mod.Model) ([]*apps.Application, er var appList []*apps.Application if activeModel != nil { - // Get active scenario node names - appNames := activeModel.GetNodeNames(mod.NodeTypeEdgeApp) - for _, appName := range appNames { - // Get scenario Process & context - proc, ctx, err := getScenarioProcess(appName, activeModel) - if err != nil { - log.Error(err.Error()) + // Get all processes + processes := activeModel.GetProcesses(nil) + for _, proc := range processes.Processes { + // Only handle EDGE-APP for duplicates + if proc.Type_ != mod.NodeTypeEdgeApp { + continue + } + + // Get context by ID + ctx := activeModel.GetNodeContextById(proc.Id) + if ctx == nil { + log.Error("Failed to get context for process ID: " + proc.Id) continue } // Create app instance - app, err := createAppInstance(proc, ctx) + app, err := createAppInstance(&proc, ctx) if err != nil { log.Error(err.Error()) continue diff --git a/go-apps/meep-virt-engine/go.mod b/go-apps/meep-virt-engine/go.mod index e80bab8085c2f5bf1bc07a30ecdb4de07a40452b..88c118c8771a07900990da8ddd83f8633488554c 100644 --- a/go-apps/meep-virt-engine/go.mod +++ b/go-apps/meep-virt-engine/go.mod @@ -8,6 +8,7 @@ require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog v0.0.0 + github.com/google/uuid v1.2.0 // indirect ) replace ( diff --git a/go-apps/meep-virt-engine/server/chart-template.go b/go-apps/meep-virt-engine/server/chart-template.go index 7681a997098647f13d48f945809733cbc0f0ba81..a8763b5db9af6fcc29bd5887969e07f470f8a617 100644 --- a/go-apps/meep-virt-engine/server/chart-template.go +++ b/go-apps/meep-virt-engine/server/chart-template.go @@ -182,29 +182,22 @@ func getAppEnablement(mepName string, model *mod.Model) string { func generateScenarioCharts(sandboxName string, procName string, model *mod.Model) (charts []helm.Chart, err error) { serviceMap := map[string]string{} - procNames := model.GetNodeNames("CLOUD-APP") - procNames = append(procNames, model.GetNodeNames("EDGE-APP")...) - procNames = append(procNames, model.GetNodeNames("UE-APP")...) - for _, name := range procNames { + processes := model.GetProcesses(nil) + for _, proc := range processes.Processes { // Check if single process is being added - if procName != "" && name != procName { + if procName != "" && proc.Name != procName { continue } // Retrieve node process information from model - node := model.GetNode(name) + node := model.GetNodeById(proc.Id) if node == nil { - err = errors.New("Error finding process: " + name) - return nil, err - } - proc, ok := node.(*dataModel.Process) - if !ok { - err = errors.New("Error casting process: " + name) + err = errors.New("Error finding process: " + proc.Name + " with ID: " + proc.Id) return nil, err } - ctx := model.GetNodeContext(name) + ctx := model.GetNodeContextById(proc.Id) if ctx == nil { - err = errors.New("Error finding context for process: " + name) + err = errors.New("Error finding context for process: " + proc.Name + " with ID: " + proc.Id) return nil, err } @@ -256,12 +249,13 @@ func generateScenarioCharts(sandboxName string, procName string, model *mod.Mode } } } - } else if mepService := getMepService(proc); mepService != "" { + } else if mepService := getMepService(&proc); mepService != "" { log.Debug("Processing MEP Service chart for element[", proc.Name, "]") // Get MEP Name mepName := ctx.Parents[mod.PhyLoc] + // Important part of code. // Create Sandbox template var sandboxTemplate SandboxTemplate sandboxTemplate.InstanceId = proc.Id @@ -291,7 +285,10 @@ func generateScenarioCharts(sandboxName string, procName string, model *mod.Mode } // Create chart - chartName := proc.Name + chartName := mepName + "-" + proc.Name + if len(chartName) > 53 { + chartName = chartName[:53] + } chartLocation, _, err := createChart(chartName, sandboxName, scenarioName, mepService, sandboxTemplate) if err != nil { log.Debug("yaml creation file process: ", err) @@ -572,6 +569,11 @@ func newChart(chartName string, sandboxName string, scenarioName string, chartLo chart.ReleaseName = "meep-" + scenarioName + "-" + chartName } + // Truncate release name to 53 characters to comply with Helm requirements + if len(chart.ReleaseName) > 53 { + chart.ReleaseName = chart.ReleaseName[:53] + } + chart.Name = chartName chart.Namespace = sandboxName chart.Location = chartLocation diff --git a/go-packages/meep-model/model.go b/go-packages/meep-model/model.go index 97c1030be84c2507fb1e7dd3b0971a8bd86de5be..b22a9cd8a98e66a664c46309973befbbb17435a7 100644 --- a/go-packages/meep-model/model.go +++ b/go-packages/meep-model/model.go @@ -240,6 +240,7 @@ func (m *Model) SetScenario(j []byte) (err error) { m.scenario = scenario err = m.parseNodes() + // No Prob in Parsing Nodes if err != nil { log.Error(err.Error()) return err @@ -368,7 +369,7 @@ func (m *Model) GetServiceMaps() *[]dataModel.NodeServiceMaps { return &m.svcMap } -//UpdateNetChar - Update network characteristics for a node +// UpdateNetChar - Update network characteristics for a node func (m *Model) UpdateNetChar(nc *dataModel.EventNetworkCharacteristicsUpdate, userData interface{}) (err error) { m.lock.Lock() defer m.lock.Unlock() @@ -550,12 +551,6 @@ func (m *Model) addPhyLoc(node *dataModel.ScenarioNode, parentNode *Node) (err e return err } - // Make sure node Name is unique - n := m.nodeMap.FindByName(pl.Name) - if n != nil { - return errors.New("Element " + pl.Name + " already exists in scenario " + m.name) - } - // Ignore any configured processes pl.Processes = make([]dataModel.Process, 0) @@ -581,12 +576,6 @@ func (m *Model) addProcess(node *dataModel.ScenarioNode, parentNode *Node) (err return err } - // Make sure node Name is unique - n := m.nodeMap.FindByName(proc.Name) - if n != nil { - return errors.New("Element " + proc.Name + " already exists in scenario " + m.name) - } - // Add Proc to parent PhyLoc pl.Processes = append(pl.Processes, *proc) @@ -838,7 +827,7 @@ func (m *Model) removeProcess(node *dataModel.ScenarioNode) (err error) { return nil } -//GetScenarioName - Get the scenario name +// GetScenarioName - Get the scenario name func (m *Model) GetScenarioName() string { m.lock.RLock() defer m.lock.RUnlock() @@ -850,7 +839,7 @@ func (m *Model) GetScenarioName() string { return "" } -//GetNodeNames - Get the list of nodes of a certain type; "" or "ANY" returns all +// GetNodeNames - Get the list of nodes of a certain type; "" or "ANY" returns all func (m *Model) GetNodeNames(typ ...string) []string { m.lock.RLock() defer m.lock.RUnlock() @@ -858,11 +847,15 @@ func (m *Model) GetNodeNames(typ ...string) []string { nm := make(map[string]*Node) for _, t := range typ { if t == "" || t == "ANY" { - nm = m.nodeMap.nameMap + for name, nodes := range m.nodeMap.nameMap { + if len(nodes) > 0 { + nm[name] = nodes[0] + } + } break } - for k, v := range m.nodeMap.typeMap[t] { - nm[k] = v + for name, node := range m.nodeMap.FindAllByType(t) { + nm[name] = node } } @@ -873,41 +866,46 @@ func (m *Model) GetNodeNames(typ ...string) []string { return list } -//GetEdges - Get a map of node edges for the current scenario +// GetEdges - Get a map of node edges for the current scenario func (m *Model) GetEdges() (edgeMap map[string]string) { m.lock.RLock() defer m.lock.RUnlock() edgeMap = make(map[string]string) - for k, node := range m.nodeMap.nameMap { - p := reflect.ValueOf(node.parent) - pName := reflect.Indirect(p).FieldByName("Name") - if pName.IsValid() { - edgeMap[k] = pName.String() - // fmt.Printf("%s (%T) \t\t %s(%T)\n", k, node.object, pName, node.parent) + for k, nodes := range m.nodeMap.nameMap { + if len(nodes) > 0 { + node := nodes[0] + p := reflect.ValueOf(node.parent) + pName := reflect.Indirect(p).FieldByName("Name") + if pName.IsValid() { + edgeMap[k] = pName.String() + // fmt.Printf("%s (%T) \t\t %s(%T)\n", k, node.object, pName, node.parent) + } } } return edgeMap } // GetNode - Get a node by its name -// Returned value is of type interface{} -// Good practice: returned node should be type asserted with val,ok := node.(someType) to prevent panic +// +// Returned value is of type interface{} +// Good practice: returned node should be type asserted with val,ok := node.(someType) to prevent panic func (m *Model) GetNode(name string) (node interface{}) { m.lock.RLock() defer m.lock.RUnlock() node = nil n := m.nodeMap.nameMap[name] - if n != nil { - node = n.object + if len(n) > 0 { + node = n[0].object } return node } // GetNodeById - Get a node by its id -// Returned value is of type interface{} -// Returned node may be nil +// +// Returned value is of type interface{} +// Returned node may be nil func (m *Model) GetNodeById(id string) (node interface{}) { m.lock.RLock() defer m.lock.RUnlock() @@ -927,8 +925,8 @@ func (m *Model) GetNodeId(name string) (id string) { id = "" n := m.nodeMap.nameMap[name] - if n != nil { - id = n.id + if len(n) > 0 { + id = n[0].id } return id } @@ -940,8 +938,8 @@ func (m *Model) GetNodeType(name string) (typ string) { typ = "" n := m.nodeMap.nameMap[name] - if n != nil { - typ = n.nodeType + if len(n) > 0 { + typ = n[0].nodeType } return typ } @@ -953,8 +951,8 @@ func (m *Model) GetNodeParent(name string) (parent interface{}) { parent = nil n := m.nodeMap.nameMap[name] - if n != nil { - parent = n.parent + if len(n) > 0 { + parent = n[0].parent } return parent } @@ -966,8 +964,8 @@ func (m *Model) GetNodeChild(name string) (child interface{}) { child = nil n := m.nodeMap.nameMap[name] - if n != nil { - child = n.child + if len(n) > 0 { + child = n[0].child } return child } @@ -979,11 +977,29 @@ func (m *Model) GetNodeContext(name string) (ctx *NodeContext) { ctx = nil n := m.nodeMap.nameMap[name] + if len(n) > 0 { + nodeCtx := n[0].context + var ok bool + if ctx, ok = nodeCtx.(*NodeContext); !ok { + log.Error("Error casting node context for node: " + name) + return nil + } + } + return ctx +} + +// GetNodeContextById - Get a node context by ID +func (m *Model) GetNodeContextById(id string) (ctx *NodeContext) { + m.lock.RLock() + defer m.lock.RUnlock() + + ctx = nil + n := m.nodeMap.idMap[id] if n != nil { nodeCtx := n.context var ok bool if ctx, ok = nodeCtx.(*NodeContext); !ok { - log.Error("Error casting node context for node: " + name) + log.Error("Error casting node context for node ID: " + id) return nil } } @@ -1221,21 +1237,20 @@ func (m *Model) GetProcesses(filter *NodeFilter) dataModel.Processes { m.lock.RLock() defer m.lock.RUnlock() - // Get process nodes - nMap := make(map[string]*Node) - m.mergeNodeMap(nMap, m.nodeMap.FindAllByType(NodeTypeUEApp)) - m.mergeNodeMap(nMap, m.nodeMap.FindAllByType(NodeTypeEdgeApp)) - m.mergeNodeMap(nMap, m.nodeMap.FindAllByType(NodeTypeCloudApp)) - // Find nodes that match filter criteria var processes dataModel.Processes processes.Processes = []dataModel.Process{} - for _, node := range nMap { - if m.filterNode(node, Proc, filter) { - process := *(node.object.(*dataModel.Process)) - - // Append process to list - processes.Processes = append(processes.Processes, process) + types := []string{NodeTypeUEApp, NodeTypeEdgeApp, NodeTypeCloudApp} + for _, typ := range types { + for _, nodes := range m.nodeMap.typeMap[typ] { + for _, node := range nodes { + if m.filterNode(node, Proc, filter) { + process := *(node.object.(*dataModel.Process)) + + // Append process to list + processes.Processes = append(processes.Processes, process) + } + } } } return processes @@ -1316,7 +1331,6 @@ func (m *Model) parseNodes() (err error) { procCtx := NewNodeContext(m.scenario.Name, domain.Name, zone.Name, nl.Name, pl.Name) m.nodeMap.AddNode(NewNode(proc.Id, proc.Name, proc.Type_, proc, nil, pl, procCtx)) m.networkGraph.AddNode(proc.Name, pl.Name, false) - // Update service map for external processes if proc.IsExternal { var nodeServiceMaps dataModel.NodeServiceMaps diff --git a/go-packages/meep-model/nodeMap.go b/go-packages/meep-model/nodeMap.go index 298fbb302cddb2dc12997a84c6f53cd76b98196e..f8c897400a59095e2e35b1a25425d24e24de4497 100644 --- a/go-packages/meep-model/nodeMap.go +++ b/go-packages/meep-model/nodeMap.go @@ -30,16 +30,16 @@ type Node struct { // NodeMap - Model node map type NodeMap struct { idMap map[string]*Node - nameMap map[string]*Node - typeMap map[string]map[string]*Node + nameMap map[string][]*Node + typeMap map[string]map[string][]*Node } // NewNodeMap - allocate a blank NodeMap func NewNodeMap() (nm *NodeMap) { nm = new(NodeMap) nm.idMap = make(map[string]*Node) - nm.nameMap = make(map[string]*Node) - nm.typeMap = make(map[string]map[string]*Node) + nm.nameMap = make(map[string][]*Node) + nm.typeMap = make(map[string]map[string][]*Node) return nm } @@ -59,11 +59,14 @@ func NewNode(id string, name string, nodeType string, object interface{}, child // AddNode - Add a node to the NodeMap func (nm *NodeMap) AddNode(n *Node) { nm.idMap[n.id] = n - nm.nameMap[n.name] = n + nm.nameMap[n.name] = []*Node{n} if nm.typeMap[n.nodeType] == nil { - nm.typeMap[n.nodeType] = make(map[string]*Node) + nm.typeMap[n.nodeType] = make(map[string][]*Node) } - nm.typeMap[n.nodeType][n.name] = n + if nm.typeMap[n.nodeType][n.name] == nil { + nm.typeMap[n.nodeType][n.name] = []*Node{} + } + nm.typeMap[n.nodeType][n.name] = append(nm.typeMap[n.nodeType][n.name], n) } // FindById - find a node using its name @@ -73,15 +76,25 @@ func (nm *NodeMap) FindById(id string) (n *Node) { // FindByName - find a node using its name func (nm *NodeMap) FindByName(name string) (n *Node) { - return nm.nameMap[name] + nodes := nm.nameMap[name] + if len(nodes) > 0 { + return nodes[0] + } + return nil } // FindByType - find a node using its type - NOT SURE WE NEED THIS -func (nm *NodeMap) FindByType(name string, nodeType string) (n *Node) { +func (nm *NodeMap) FindByType(name string, nodeType string) []*Node { return nm.typeMap[nodeType][name] } // FindAllByType - find a list of nodes using a type func (nm *NodeMap) FindAllByType(nodeType string) map[string]*Node { - return nm.typeMap[nodeType] + result := make(map[string]*Node) + for name, nodes := range nm.typeMap[nodeType] { + if len(nodes) > 0 { + result[name] = nodes[0] + } + } + return result } diff --git a/go-packages/meep-model/validator.go b/go-packages/meep-model/validator.go index a102fd46565a6af11d835fc827048101c308378e..67fdfeee47abf97862bc9764bc4097843d076fa0 100644 --- a/go-packages/meep-model/validator.go +++ b/go-packages/meep-model/validator.go @@ -502,6 +502,9 @@ func validateScenario(scenario *dataModel.Scenario) error { return err } + // Name map for elements within this domain + domainNameMap := make(map[string]bool) + // Validate zones for zoneIndex := range domain.Zones { zone := &domain.Zones[zoneIndex] @@ -509,7 +512,7 @@ func validateScenario(scenario *dataModel.Scenario) error { if err := validateUniqueId(zone.Id, idMap); err != nil { return err } - if err := validateUniqueName(zone.Name, nameMap); err != nil { + if err := validateUniqueName(zone.Name, domainNameMap); err != nil { return err } @@ -520,7 +523,7 @@ func validateScenario(scenario *dataModel.Scenario) error { if err := validateUniqueId(nl.Id, idMap); err != nil { return err } - if err := validateUniqueName(nl.Name, nameMap); err != nil { + if err := validateUniqueName(nl.Name, domainNameMap); err != nil { return err } @@ -533,7 +536,7 @@ func validateScenario(scenario *dataModel.Scenario) error { if err := validateUniqueId(pl.Id, idMap); err != nil { return err } - if err := validateUniqueName(pl.Name, nameMap); err != nil { + if err := validateUniqueName(pl.Name, domainNameMap); err != nil { return err } @@ -546,9 +549,6 @@ func validateScenario(scenario *dataModel.Scenario) error { if err := validateUniqueId(proc.Id, idMap); err != nil { return err } - if err := validateUniqueName(proc.Name, nameMap); err != nil { - return err - } } } } diff --git a/js-apps/meep-frontend/src/js/containers/cfg/cfg-network-element-container.js b/js-apps/meep-frontend/src/js/containers/cfg/cfg-network-element-container.js index 5ae54fdc25199f6d2d0a4cde50619731efad067f..4ed7e1f3d5058b8ae62292af66132d8a8d5b2b65 100644 --- a/js-apps/meep-frontend/src/js/containers/cfg/cfg-network-element-container.js +++ b/js-apps/meep-frontend/src/js/containers/cfg/cfg-network-element-container.js @@ -1363,33 +1363,41 @@ const TypeRelatedFormFields = ({ onUpdate, onEditLocation, onEditPath, element } const cfgElementTypes = [ { label: 'Logical Domain', - options: [ELEMENT_TYPE_OPERATOR_GENERIC, ELEMENT_TYPE_OPERATOR_CELL] + options: [ + { label: 'Generic', value: ELEMENT_TYPE_OPERATOR_GENERIC }, + { label: 'Cellular', value: ELEMENT_TYPE_OPERATOR_CELL } + ] }, { label: 'Logical Zone', - options: [ELEMENT_TYPE_ZONE] + options: [{ label: 'Zone', value: ELEMENT_TYPE_ZONE }] }, { label: 'Network Location', - options: [ELEMENT_TYPE_POA_GENERIC, ELEMENT_TYPE_POA_4G, ELEMENT_TYPE_POA_5G, ELEMENT_TYPE_POA_WIFI] + options: [ + { label: 'Generic', value: ELEMENT_TYPE_POA_GENERIC }, + { label: '4G', value: ELEMENT_TYPE_POA_4G }, + { label: '5G', value: ELEMENT_TYPE_POA_5G }, + { label: 'WiFi', value: ELEMENT_TYPE_POA_WIFI } + ] }, { label: 'Physical Location', options: [ - ELEMENT_TYPE_UE, - ELEMENT_TYPE_FOG, - ELEMENT_TYPE_EDGE, - ELEMENT_TYPE_DC - // ELEMENT_TYPE_CN + { label: 'Terminal', value: ELEMENT_TYPE_UE }, + { label: 'Fog', value: ELEMENT_TYPE_FOG }, + { label: 'Edge', value: ELEMENT_TYPE_EDGE }, + { label: 'Distant Cloud', value: ELEMENT_TYPE_DC } + // { label: 'Core Network', value: ELEMENT_TYPE_CN } ] }, { label: 'Process', options: [ - ELEMENT_TYPE_UE_APP, - // ELEMENT_TYPE_MECSVC, - ELEMENT_TYPE_EDGE_APP, - ELEMENT_TYPE_CLOUD_APP + { label: 'Terminal Application', value: ELEMENT_TYPE_UE_APP }, + // { label: 'MEC Service', value: ELEMENT_TYPE_MECSVC }, + { label: 'Edge Application', value: ELEMENT_TYPE_EDGE_APP }, + { label: 'Cloud Application', value: ELEMENT_TYPE_CLOUD_APP } ] } ]; @@ -1398,9 +1406,9 @@ const execElementTypes = [ { label: 'Process', options: [ - ELEMENT_TYPE_UE_APP, - ELEMENT_TYPE_EDGE_APP, - ELEMENT_TYPE_CLOUD_APP + { label: 'Terminal Application', value: ELEMENT_TYPE_UE_APP }, + { label: 'Edge Application', value: ELEMENT_TYPE_EDGE_APP }, + { label: 'Cloud Application', value: ELEMENT_TYPE_CLOUD_APP } ] } ]; diff --git a/js-apps/meep-frontend/src/js/containers/cfg/cfg-page-container.js b/js-apps/meep-frontend/src/js/containers/cfg/cfg-page-container.js index 30a19d518d49443025f8f3067855849d7a7bab45..7e4e1b9bca3cbc6ffd50b604482945cb198c0851 100644 --- a/js-apps/meep-frontend/src/js/containers/cfg/cfg-page-container.js +++ b/js-apps/meep-frontend/src/js/containers/cfg/cfg-page-container.js @@ -68,7 +68,19 @@ import { IDC_DIALOG_EXPORT_SCENARIO, ELEMENT_TYPE_POA_4G, ELEMENT_TYPE_POA_5G, - ELEMENT_TYPE_POA_WIFI + ELEMENT_TYPE_POA_WIFI, + ELEMENT_TYPE_UE, + ELEMENT_TYPE_FOG, + ELEMENT_TYPE_EDGE, + ELEMENT_TYPE_DC, + ELEMENT_TYPE_CN, + ELEMENT_TYPE_UE_APP, + ELEMENT_TYPE_EDGE_APP, + ELEMENT_TYPE_CLOUD_APP, + ELEMENT_TYPE_OPERATOR, + ELEMENT_TYPE_OPERATOR_CELL, + ELEMENT_TYPE_ZONE, + ELEMENT_TYPE_POA } from '../../meep-constants'; import { @@ -89,6 +101,7 @@ import { FIELD_MEMORY_MIN, FIELD_MEMORY_MAX } from '../../util/elem-utils'; +import { getElementFromScenario, updateElementInScenario } from '../../util/scenario-utils'; import { pipe, filter } from '../../util/functional'; @@ -137,6 +150,30 @@ export const validateNetworkElement = (element, entries, elemSetErrMsg) => { return false; } + // Check if type is valid + const validTypes = [ + ELEMENT_TYPE_SCENARIO, + ELEMENT_TYPE_OPERATOR, + ELEMENT_TYPE_OPERATOR_CELL, + ELEMENT_TYPE_ZONE, + ELEMENT_TYPE_POA, + ELEMENT_TYPE_POA_4G, + ELEMENT_TYPE_POA_5G, + ELEMENT_TYPE_POA_WIFI, + ELEMENT_TYPE_UE, + ELEMENT_TYPE_FOG, + ELEMENT_TYPE_EDGE, + ELEMENT_TYPE_DC, + ELEMENT_TYPE_CN, + ELEMENT_TYPE_UE_APP, + ELEMENT_TYPE_EDGE_APP, + ELEMENT_TYPE_CLOUD_APP + ]; + if (!validTypes.includes(type)) { + elemSetErrMsg('Invalid element type: ' + type); + return false; + } + // Check for valid & unique network element name (except if editing) var name = getElemFieldVal(element, FIELD_NAME); if (name === null || name === '') { @@ -144,10 +181,10 @@ export const validateNetworkElement = (element, entries, elemSetErrMsg) => { return false; } - if (data[name] && data[name].id !== element.id) { - elemSetErrMsg('Element name already exists'); - return false; - } + // if (data[name] && data[name].id !== element.id) { + // elemSetErrMsg('Element name already exists'); + // return false; + // } // Nothing else to validate for Scenario element if (type === ELEMENT_TYPE_SCENARIO) { @@ -155,9 +192,16 @@ export const validateNetworkElement = (element, entries, elemSetErrMsg) => { } // Make sure parent exists - if (!data[getElemFieldVal(element, FIELD_PARENT)]) { - elemSetErrMsg('Parent does not exist'); - return false; + var parentName = getElemFieldVal(element, FIELD_PARENT); + if (parentName) { + parentName = parentName.trim(); + if (!Object.values(data).some(e => { + const eName = getElemFieldVal(e, FIELD_NAME); + return eName && eName.trim() === parentName; + })) { + elemSetErrMsg('Parent does not exist'); + return false; + } } // If GPU requested, make sure type is set @@ -245,16 +289,16 @@ class CfgPageContainer extends Component { } // EDIT - onEditElement(element) { - if (element !== null) { - if (!this.props.configuredElement || (element.id !== this.props.configuredElement.id)) { - resetElem(element); + onEditElement(element) { + if (element !== null) { + // Always fetch the full element from the scenario by ID + // let element = getElementFromScenario(this.props.cfg.scenario, element.id); + //resetElem(element); this.props.cfgElemEdit(element); + } else { + this.props.cfgElemClear(); } - } else { - this.props.cfgElemClear(); } - } // SAVE onSaveElement(element) { @@ -270,6 +314,11 @@ class CfgPageContainer extends Component { this.props.updateScenarioElem(element); } + // Update scenario for canvas reflection + // let updatedScenario = JSON.parse(JSON.stringify(this.props.cfg.scenario)); + // updateElementInScenario(updatedScenario, element); + // this.props.changeScenario(updatedScenario); + // Reset Element configuration pane this.props.cfgElemClear(); } @@ -288,8 +337,10 @@ class CfgPageContainer extends Component { this.props.cloneScenarioElem(element); - //force update on the visual aspect of the scenario - //this.props.updateScenario(); + // Update scenario for canvas reflection + const updatedScenario = JSON.parse(JSON.stringify(this.props.cfg.scenario)); + updateElementInScenario(updatedScenario, element); + this.props.changeScenario(updatedScenario); this.props.cfgElemClear(); } @@ -467,6 +518,11 @@ class CfgPageContainer extends Component { const scenarioCopy = JSON.parse(JSON.stringify(cfg.scenario)); scenarioCopy.name = scenarioName; + // Update scenario with configured elements + Object.values(cfg.table.entries).forEach(element => { + updateElementInScenario(scenarioCopy, element); + }); + // Create new scenario if scenario is new if (cfg.state === CFG_STATE_NEW || scenarioName !== cfg.scenario.name) { this.props.api.createScenario( @@ -737,7 +793,7 @@ class CfgPageContainer extends Component { type={TYPE_CFG} onNewElement={() => this.onNewElement()} onEditElement={elem => this.onEditElement(elem)} - onDeleteElement={() => this.onDeleteElement()} + onDeleteElement={elem => this.onDeleteElement(elem)} onApplyCloneElement={elem => this.onApplyCloneElement(elem)} /> diff --git a/js-apps/meep-frontend/src/js/containers/cfg/cfg-table.js b/js-apps/meep-frontend/src/js/containers/cfg/cfg-table.js index 6ebb5f1ac96c5eb3a42c14879a402f83391caf28..f000768bf643f65aa6f0973c0d48542faf29d40d 100644 --- a/js-apps/meep-frontend/src/js/containers/cfg/cfg-table.js +++ b/js-apps/meep-frontend/src/js/containers/cfg/cfg-table.js @@ -95,10 +95,15 @@ class CfgTable extends Component { this.props.changeTable(table); } - onClick(/*event, name*/) { - // var table = updateObject({}, this.props.table); - // handleClick(table, event, name); - // this.props.changeTable(table); + onClick(event, elem) { + // Select by unique id + var table = updateObject({}, this.props.table); + table.selected = [elem.id]; + this.props.changeTable(table); + // Call parent handler to open config panel for this element + if (this.props.onEditElement) { + this.props.onEditElement(elem); + } } onChangePage(event, page) { @@ -198,15 +203,16 @@ class CfgTable extends Component { const name = getElemFieldVal(elem, FIELD_NAME); const type = getElemFieldVal(elem, FIELD_TYPE); const parent = getElemFieldVal(elem, FIELD_PARENT); - const isSelected = isRowSelected(table, name); + const id = elem.id; + const isSelected = table.selected && table.selected[0] === id; return ( this.onClick(event, name)} + onClick={event => this.onClick(event, elem)} role='checkbox' aria-checked={isSelected} tabIndex={-1} - key={name} + key={id} selected={isSelected} > diff --git a/js-apps/meep-frontend/src/js/containers/idc-map.js b/js-apps/meep-frontend/src/js/containers/idc-map.js index 07aa0a222c3057b01f2211abea308a6110fcb0db..95d8ff787bcb03d8fd3b0bdcce6f62b062e088e1 100644 --- a/js-apps/meep-frontend/src/js/containers/idc-map.js +++ b/js-apps/meep-frontend/src/js/containers/idc-map.js @@ -167,18 +167,32 @@ class IDCMap extends Component { if (this.props.type === TYPE_CFG) { // Target element update if (nextProps.configuredElement !== this.props.configuredElement) { + console.log('[IDCMap] shouldComponentUpdate: configuredElement changed', nextProps.configuredElement); return true; } // Scenario change if (nextProps.cfgScenarioName !== this.props.cfgScenarioName) { + console.log('[IDCMap] shouldComponentUpdate: cfgScenarioName changed', nextProps.cfgScenarioName); + return true; + } + // Scenario content change + if (!deepEqual(nextProps.cfgScenario, this.props.cfgScenario)) { + console.log('[IDCMap] shouldComponentUpdate: cfgScenario content changed'); + return true; + } + // Table change (needed for zone color lookups) + if (!deepEqual(nextProps.cfgTable, this.props.cfgTable)) { + console.log('[IDCMap] shouldComponentUpdate: cfgTable changed'); return true; } // Sandbox update if (nextProps.cfgView !== this.props.cfgView) { + console.log('[IDCMap] shouldComponentUpdate: cfgView changed', nextProps.cfgView); return true; } // Map asset change if (!deepEqual(this.getMap(nextProps), this.getMap(this.props))) { + console.log('[IDCMap] shouldComponentUpdate: map data changed'); return true; } return false; @@ -200,6 +214,61 @@ class IDCMap extends Component { return (this.props.type === TYPE_CFG) ? this.props.cfgTable : this.props.execTable; } + buildMapFromScenario(scenario) { + var map = { + ueList: [], + poaList: [], + computeList: [] + }; + + if (!scenario || !scenario.deployment || !scenario.deployment.domains) { + return map; + } + + scenario.deployment.domains.forEach(domain => { + if (domain.zones) { + domain.zones.forEach(zone => { + if (zone.networkLocations) { + zone.networkLocations.forEach(nl => { + if (nl.physicalLocations) { + nl.physicalLocations.forEach(pl => { + if (pl.type === 'UE' && pl.geoData && pl.geoData.location) { + map.ueList.push({ + assetName: pl.name, + id: pl.id || pl.name, + radius: pl.geoData.radius || 0, + location: pl.geoData.location, + path: pl.geoData.path || null, + eopMode: pl.geoData.eopMode || null, + velocity: pl.geoData.velocity || null + }); + } else if ((pl.type === 'FOG' || pl.type === 'EDGE' || pl.type === 'DC') && pl.geoData && pl.geoData.location) { + map.computeList.push({ + assetName: pl.name, + id: pl.id || pl.name, + location: pl.geoData.location + }); + } + }); + } + // For POA + if ((nl.type === 'POA' || nl.type === 'POA-4G' || nl.type === 'POA-5G' || nl.type === 'POA-WIFI') && nl.geoData && nl.geoData.location) { + map.poaList.push({ + assetName: nl.name, + id: nl.id || nl.name, + location: nl.geoData.location, + radius: nl.geoData.radius || 0 + }); + } + }); + } + }); + } + }); + + return map; + } + updateCfg(cfg) { switch (this.props.type) { case TYPE_CFG: @@ -230,10 +299,10 @@ class IDCMap extends Component { } } - editElement(name) { + editElement(id) { // Update selected nodes in table const table = updateObject({}, this.getTable()); - const elem = this.getElementByName(table.entries, name); + const elem = this.getElementById(table.entries, id); table.selected = elem ? [elem.id] : []; this.changeTable(table); @@ -241,8 +310,8 @@ class IDCMap extends Component { if (this.props.type === TYPE_CFG) { this.props.onEditElement(elem ? elem : this.props.configuredElement); - // Update target element name & reset controls on target change - if (name !== this.targetElemName) { + // Update target element & reset controls on target change + if (id !== this.targetElemId) { this.map.pm.disableDraw('Marker'); this.map.pm.disableDraw('Line'); if (this.map.pm.globalEditEnabled()) { @@ -255,12 +324,12 @@ class IDCMap extends Component { this.map.pm.toggleGlobalRemovalMode(); } } - this.targetElemName = name; + this.targetElemId = id; } } - getElementByName(entries, name) { - var element = entries[name]; + getElementById(entries, id) { + var element = entries[id]; return element ? element : null; } @@ -401,7 +470,7 @@ class IDCMap extends Component { var radius = 0; var table = this.getTable(); if (table && table.entries) { - radius = getElemFieldVal(table.entries[scenarioName], FIELD_D2D_RADIUS); + radius = getElemFieldVal(table.entries[scenarioName], FIELD_D2D_RADIUS); // scenarioName should be scenario ID if available } return radius; } @@ -416,7 +485,7 @@ class IDCMap extends Component { var poa = null; var table = this.getTable(); if (table && table.entries) { - poa = getElemFieldVal(table.entries[ue], FIELD_PARENT); + poa = getElemFieldVal(table.entries[ue], FIELD_PARENT); // ue should be ue ID } return poa; } @@ -744,12 +813,12 @@ class IDCMap extends Component { setUeMarker(ue) { var latlng = L.latLng(L.GeoJSON.coordsToLatLng(ue.location.coordinates)); - var pathLatLngs = ue.path ? L.GeoJSON.coordsToLatLngs(ue.path.coordinates) : null; + var pathLatLngs = (ue.path && ue.path.coordinates) ? L.GeoJSON.coordsToLatLngs(ue.path.coordinates) : null; // Find existing UE marker var existingMarker; this.ueOverlay.eachLayer((marker) => { - if (marker.options.meep.ue.id === ue.assetName){ + if (marker.options.meep.ue.id === (ue.id || ue.assetName)){ existingMarker = marker; return; } @@ -788,23 +857,24 @@ class IDCMap extends Component { pmIgnore: true }); - var m = L.marker(latlng, { - meep: { - ue: { - id: ue.assetName, - path: p, - eopMode: ue.eopMode, - velocity: ue.velocity, - connected: true, - d2dInRange: ue.d2dInRange, - range: c - } - }, - icon: markerIcon, - opacity: UE_OPACITY, - draggable: (this.props.type === TYPE_CFG) ? true : false, - pmIgnore: (this.props.type === TYPE_CFG) ? false : true - }); + var m = L.marker(latlng, { + meep: { + ue: { + id: ue.id || ue.assetName, + name: ue.assetName, + path: p, + eopMode: ue.eopMode, + velocity: ue.velocity, + connected: true, + d2dInRange: ue.d2dInRange, + range: c + } + }, + icon: markerIcon, + opacity: UE_OPACITY, + draggable: (this.props.type === TYPE_CFG && this.map.pm.globalDragModeEnabled()) ? true : false, + pmIgnore: (this.props.type === TYPE_CFG) ? false : true + }); m.bindTooltip(ue.assetName).openTooltip(); // Handlers @@ -884,7 +954,7 @@ class IDCMap extends Component { // Find existing POA marker var existingMarker; this.poaOverlay.eachLayer((marker) => { - if (marker.options.meep.poa.id === poa.assetName){ + if (marker.options.meep.poa.id === (poa.id || poa.assetName)){ existingMarker = marker; return; } @@ -915,7 +985,8 @@ class IDCMap extends Component { var m = L.marker(latlng, { meep: { poa: { - id: poa.assetName, + id: poa.id || poa.assetName, + name: poa.assetName, range: c } }, @@ -965,7 +1036,7 @@ class IDCMap extends Component { // Find existing COMPUTE marker var existingMarker; this.computeOverlay.eachLayer((marker) => { - if (marker.options.meep.compute.id === compute.assetName){ + if (marker.options.meep.compute.id === (compute.id || compute.assetName)){ existingMarker = marker; return; } @@ -985,7 +1056,8 @@ class IDCMap extends Component { var m = L.marker(latlng, { meep: { compute: { - id: compute.assetName, + id: compute.id || compute.assetName, + name: compute.assetName, connected: true } }, @@ -1109,7 +1181,13 @@ class IDCMap extends Component { } // Get copy of map data - var map = deepCopy(this.getMap(this.props)); + var map; + if (this.props.type === TYPE_CFG) { + map = this.buildMapFromScenario(this.props.cfgScenario); + console.log('[IDCMap] updateMarkers (CFG): ues=', map.ueList.length, 'poas=', map.poaList.length, 'computes=', map.computeList.length); + } else { + map = deepCopy(this.getMap(this.props)); + } if (!map) { return; } @@ -1125,7 +1203,7 @@ class IDCMap extends Component { for (let i = 0; i < map.computeList.length; i++) { let compute = map.computeList[i]; this.setComputeMarker(compute); - computeMap[compute.assetName] = true; + computeMap[compute.id || compute.assetName] = true; } } @@ -1142,7 +1220,7 @@ class IDCMap extends Component { for (let i = 0; i < map.poaList.length; i++) { let poa = map.poaList[i]; this.setPoaMarker(poa); - poaMap[poa.assetName] = true; + poaMap[poa.id || poa.assetName] = true; } } @@ -1160,7 +1238,7 @@ class IDCMap extends Component { for (let i = 0; i < map.ueList.length; i++) { let ue = map.ueList[i]; this.setUeMarker(ue); - ueMap[ue.assetName] = true; + ueMap[ue.id || ue.assetName] = true; } } @@ -1177,20 +1255,20 @@ class IDCMap extends Component { } onEditModeToggle(e) { - var targetElemName = getElemFieldVal(this.props.configuredElement, FIELD_NAME); + var targetElemId = this.props.configuredElement ? this.props.configuredElement.id : null; if (e.enabled) { - this.setTarget(targetElemName); + this.setTarget(targetElemId); } else { - this.updateTargetGeoData(targetElemName, '', ''); + this.updateTargetGeoData(targetElemId, '', ''); } } onDragModeToggle(e) { - var targetElemName = getElemFieldVal(this.props.configuredElement, FIELD_NAME); + var targetElemId = this.props.configuredElement ? this.props.configuredElement.id : null; if (e.enabled) { - this.setTarget(targetElemName); + this.setTarget(targetElemId); } else { - this.updateTargetGeoData(targetElemName, '', ''); + this.updateTargetGeoData(targetElemId, '', ''); } } @@ -1210,8 +1288,8 @@ class IDCMap extends Component { } // Update configured element & refresh map to create the new marker or path - var targetElemName = getElemFieldVal(this.props.configuredElement, FIELD_NAME); - this.updateTargetGeoData(targetElemName, location, path); + var targetElemId = this.props.configuredElement ? this.props.configuredElement.id : null; + this.updateTargetGeoData(targetElemId, location, path); } onPoaMoved(e) { @@ -1225,14 +1303,14 @@ class IDCMap extends Component { this.props.cfgElemUpdate(updatedElem); } - updateTargetGeoData(targetElemName, location, path) { - if (!targetElemName) { + updateTargetGeoData(targetElemId, location, path) { + if (!targetElemId) { return; } // Get latest geoData from map, if any if (!location) { - var markerInfo = this.getMarkerInfo(targetElemName); + var markerInfo = this.getMarkerInfo(targetElemId); if (markerInfo && markerInfo.marker) { location = JSON.stringify(L.GeoJSON.latLngToCoords(markerInfo.marker.getLatLng())); if (!path && markerInfo.type === TYPE_UE && markerInfo.marker.options.meep.ue.path) { @@ -1268,6 +1346,9 @@ class IDCMap extends Component { setTarget(target) { // Disable changes on all markers except target + console.log('[IDCMap] setTarget:', target); + var isDragModeEnabled = this.map.pm.globalDragModeEnabled(); + this.ueOverlay.eachLayer((marker) => { var path = marker.options.meep.ue.path; if (marker.pm && (!target || marker.options.meep.ue.id !== target)) { @@ -1279,8 +1360,14 @@ class IDCMap extends Component { } } else { marker.setOpacity(OPACITY_TARGET); + if (marker.pm && isDragModeEnabled) { + marker.pm.enable(); + } if (path) { path.setStyle({opacity: OPACITY_TARGET}); + if (path.pm && this.map.pm.globalEditEnabled()) { + path.pm.enable(); + } } } }); @@ -1291,6 +1378,9 @@ class IDCMap extends Component { marker.options.meep.poa.range.setStyle({opacity: target ? POA_RANGE_OPACITY_BACKGROUND : POA_RANGE_OPACITY}); } else { marker.setOpacity(OPACITY_TARGET); + if (marker.pm && isDragModeEnabled) { + marker.pm.enable(); + } marker.options.meep.poa.range.setStyle({opacity: OPACITY_TARGET}); } }); @@ -1300,6 +1390,9 @@ class IDCMap extends Component { marker.setOpacity(target ? COMPUTE_OPACITY_BACKGROUND : COMPUTE_OPACITY); } else { marker.setOpacity(OPACITY_TARGET); + if (marker.pm && isDragModeEnabled) { + marker.pm.enable(); + } } }); } @@ -1316,11 +1409,16 @@ class IDCMap extends Component { var removalModeEnabled = false; // Update target element name & reset controls on target change - var targetElemName = getElemFieldVal(this.props.configuredElement, FIELD_NAME); + var targetElemId = this.props.configuredElement ? this.props.configuredElement.id : null; + console.log('[IDCMap] updateEditControls: targetElemId =', targetElemId); // Determine which controls to enable - if (targetElemName) { - var markerInfo = this.getMarkerInfo(targetElemName); + // Only look up a marker if we have a target id; treat a stale/unmatched id the + // same as "no target" so all markers remain interactive instead of being dimmed. + var markerInfo = targetElemId ? this.getMarkerInfo(targetElemId) : null; + var markerTarget = (markerInfo && markerInfo.marker) ? targetElemId : null; + + if (targetElemId) { if (markerInfo && markerInfo.marker) { // Enable path create/edit for UE only if (markerInfo.type === TYPE_UE) { @@ -1330,10 +1428,12 @@ class IDCMap extends Component { editModeEnabled = true; } dragModeEnabled = true; + console.log('[IDCMap] updateEditControls: found marker for target, dragMode =', dragModeEnabled); // removalModeEnabled = true; } else { - // Enable marker creation + // Element is configured but has no map marker yet — enable placement drawMarkerEnabled = true; + console.log('[IDCMap] updateEditControls: no marker for target (unplaced/stale elem), drawMarker enabled'); } } @@ -1364,8 +1464,11 @@ class IDCMap extends Component { } } - // Set target element & disable edit on all other markers - this.setTarget(targetElemName); + // Only focus (dim others) when the configured element actually has a marker on + // the map. If it doesn't (element not yet placed, or stale id from a previous + // scenario), pass null so all markers remain fully interactive. + console.log('[IDCMap] updateEditControls: setTarget with', markerTarget); + this.setTarget(markerTarget); } render() { @@ -1393,6 +1496,7 @@ const mapStateToProps = state => { configuredElement: state.cfg.elementConfiguration.configuredElement, cfgView: state.ui.cfgView, cfgScenarioName: state.cfg.scenario.name, + cfgScenario: state.cfg.scenario, appInstanceTable: state.exec.appInstanceTable.data }; }; diff --git a/js-apps/meep-frontend/src/js/meep-constants.js b/js-apps/meep-frontend/src/js/meep-constants.js index 974cd7e3c7af76e229e31704cd832a6bf2707267..a8d086e6c3ff1ca91c291e4d8a6512d3b3995cd8 100644 --- a/js-apps/meep-frontend/src/js/meep-constants.js +++ b/js-apps/meep-frontend/src/js/meep-constants.js @@ -262,23 +262,23 @@ export const CLOUD_APP_TYPE_STR = 'CLOUD-APP'; export const ELEMENT_TYPE_SCENARIO = 'SCENARIO'; export const ELEMENT_TYPE_OPERATOR = 'OPERATOR'; -export const ELEMENT_TYPE_OPERATOR_GENERIC = 'OPERATOR GENERIC'; -export const ELEMENT_TYPE_OPERATOR_CELL = 'OPERATOR CELLULAR'; +export const ELEMENT_TYPE_OPERATOR_GENERIC = 'OPERATOR'; +export const ELEMENT_TYPE_OPERATOR_CELL = 'OPERATOR-CELLULAR'; export const ELEMENT_TYPE_ZONE = 'ZONE'; export const ELEMENT_TYPE_POA = 'POA'; -export const ELEMENT_TYPE_POA_GENERIC = 'POA GENERIC'; -export const ELEMENT_TYPE_POA_4G = 'POA CELLULAR 4G'; -export const ELEMENT_TYPE_POA_5G = 'POA CELLULAR 5G'; -export const ELEMENT_TYPE_POA_WIFI = 'POA WIFI'; -export const ELEMENT_TYPE_DC = 'DISTANT CLOUD'; -export const ELEMENT_TYPE_CN = 'CORE NETWORK'; +export const ELEMENT_TYPE_POA_GENERIC = 'POA'; +export const ELEMENT_TYPE_POA_4G = 'POA-4G'; +export const ELEMENT_TYPE_POA_5G = 'POA-5G'; +export const ELEMENT_TYPE_POA_WIFI = 'POA-WIFI'; +export const ELEMENT_TYPE_DC = 'DC'; +export const ELEMENT_TYPE_CN = 'CN'; export const ELEMENT_TYPE_EDGE = 'EDGE'; export const ELEMENT_TYPE_FOG = 'FOG'; -export const ELEMENT_TYPE_UE = 'TERMINAL'; -export const ELEMENT_TYPE_MECSVC = 'MEC SERVICE'; -export const ELEMENT_TYPE_UE_APP = 'TERMINAL APPLICATION'; -export const ELEMENT_TYPE_EDGE_APP = 'EDGE APPLICATION'; -export const ELEMENT_TYPE_CLOUD_APP = 'CLOUD APPLICATION'; +export const ELEMENT_TYPE_UE = 'UE'; +export const ELEMENT_TYPE_MECSVC = 'MEC-SVC'; +export const ELEMENT_TYPE_UE_APP = 'UE-APP'; +export const ELEMENT_TYPE_EDGE_APP = 'EDGE-APP'; +export const ELEMENT_TYPE_CLOUD_APP = 'CLOUD-APP'; // Default latencies per physical location type export const DEFAULT_LATENCY_INTER_DOMAIN = 50; diff --git a/js-apps/meep-frontend/src/js/state/cfg/table-reducer.js b/js-apps/meep-frontend/src/js/state/cfg/table-reducer.js index 3856315b6435130f3519281329e51e70de47fd11..61ae03a88b8040aef34b43852577a47f5dd82a9e 100644 --- a/js-apps/meep-frontend/src/js/state/cfg/table-reducer.js +++ b/js-apps/meep-frontend/src/js/state/cfg/table-reducer.js @@ -38,7 +38,7 @@ export function cfgChangeTable(table) { export function cfgTableReducer(state = initialState, action) { switch (action.type) { case CFG_CHANGE_TABLE: - var ret = updateObject({}, action.payload); + var ret = updateObject(state, action.payload); return ret; default: return state; diff --git a/js-apps/meep-frontend/src/js/util/scenario-utils.js b/js-apps/meep-frontend/src/js/util/scenario-utils.js index 896921fd7e031b83074047a6ca37c9c018d652ad..8bbd72f8eec68ee239d43066a9e9d510c65d2bbe 100644 --- a/js-apps/meep-frontend/src/js/util/scenario-utils.js +++ b/js-apps/meep-frontend/src/js/util/scenario-utils.js @@ -298,7 +298,7 @@ export function parseScenario(scenario, pduSessions) { var table = {}; table.data = { edges: edges, nodes: nodes }; table.entries = _.reduce(table.data.nodes, (nodeMap, node) => { - nodeMap[node.name] = updateObject(node, getElementFromScenario(scenario, node.id)); + nodeMap[node.id] = updateObject(node, getElementFromScenario(scenario, node.id)); return nodeMap; }, {}); @@ -306,7 +306,7 @@ export function parseScenario(scenario, pduSessions) { var visData = {}; visData.nodes = new visdata.DataSet(nodes); visData.edges = new visdata.DataSet(edges); - + // Update map data var mapData = {}; mapData.ueList = _.sortBy(ueList, ['assetName']); @@ -569,6 +569,8 @@ export function updateElementInScenario(scenario, element) { } domain.label = name; domain.name = name; + domain.type = getElemFieldVal(element, FIELD_TYPE); + domain.parent = getElemFieldVal(element, FIELD_PARENT); return; } @@ -601,6 +603,8 @@ export function updateElementInScenario(scenario, element) { zone.label = name; zone.name = name; + zone.type = getElemFieldVal(element, FIELD_TYPE); + zone.parent = getElemFieldVal(element, FIELD_PARENT); return; } @@ -649,6 +653,8 @@ export function updateElementInScenario(scenario, element) { nl.label = name; nl.name = name; + nl.type = getElemFieldVal(element, FIELD_TYPE); + nl.parent = getElemFieldVal(element, FIELD_PARENT); return; } @@ -698,6 +704,8 @@ export function updateElementInScenario(scenario, element) { pl.label = name; pl.name = name; + pl.type = getElemFieldVal(element, FIELD_TYPE); + pl.parent = getElemFieldVal(element, FIELD_PARENT); return; } diff --git a/playbooks/README.md b/playbooks/README.md index 0080bd98617e3cd5b74cdcb908124b9ef169ed85..91a9b22cd0429a5db7cbbe61361f37289ce3e80d 100644 --- a/playbooks/README.md +++ b/playbooks/README.md @@ -133,7 +133,7 @@ ansible-playbook -i inventories/dev/hosts.ini site.yml -K You can run just parts of the setup with `--tags` or skip parts with `--skip-tags`. (The roles here are intentionally simple and do not define custom tags; feel free to add them if you want finer control.) -## 📖 Notes +## Notes * Ensure worker nodes have SSH access configured before running. * Use `--tags` if you want to run specific roles (e.g. `--tags kubernetes,helm`).