Commit d17cc7ee authored by Yann Garcia's avatar Yann Garcia
Browse files

Update meep-vis test scenario

parent d9090cdd
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -1122,12 +1122,13 @@ func sendReadyConfirmation(appInstanceId string) error {
	appReady.Indication = "READY"
	log.Info(appSupportClientPath)
	resp, err := appSupportClient.MecAppSupportApi.ApplicationsConfirmReadyPOST(context.TODO(), appReady, appInstanceId)
	status := strconv.Itoa(resp.StatusCode)
	if err != nil {
		log.Error("Failed to receive confirmation acknowlegement ", resp.Status)
		appActivityLogs = append(appActivityLogs, "Send confirm ready ["+status+"]")
		log.Error(err.Error())
		//log.Error("Failed to receive confirmation acknowlegement ", resp.Status)
		appActivityLogs = append(appActivityLogs, "Send confirm ready ["+err.Error()+"]")
		return err
	}
	status := strconv.Itoa(resp.StatusCode)

	appActivityLogs = append(appActivityLogs, "Send confirm ready ["+status+"]")
	return nil
+21 −9
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ const (
)

func resetAutomation() {
	log.Debug("Reset automation")
	log.Info(">>> Reset automation")

	// Stop automation if running
	_ = setAutomation(AutoTypeMovement, false)
@@ -60,6 +60,7 @@ func resetAutomation() {
}

func setAutomation(automationType string, state bool) (err error) {
	log.Info(">>> setAutomation: ", automationType)

	// Validate automation type
	if _, found := ge.automation[automationType]; !found {
@@ -101,8 +102,9 @@ func setAutomation(automationType string, state bool) (err error) {
}

func startAutomation() {
	log.Info(">>> startAutomation")
	if ge.automationTicker == nil {
		log.Debug("Starting automation loop")
		log.Info("Starting automation loop")
		ge.automationTicker = time.NewTicker(1000 * time.Millisecond)
		go func() {
			for range ge.automationTicker.C {
@@ -113,14 +115,17 @@ func startAutomation() {
}

func stopAutomation() {
	log.Info(">>> stopAutomation")
	if ge.automationTicker != nil {
		ge.automationTicker.Stop()
		ge.automationTicker = nil
		log.Debug("Stopping automation loop")
		log.Info("Stopping automation loop")
	}
}

func runAutomation() {
	log.Info(">>> runAutomation: ")

	var ueMap map[string]*am.Ue
	var poaMap map[string]*am.Poa
	var err error
@@ -146,6 +151,7 @@ func runAutomation() {
	}

	// Mobility
	log.Info("runAutomation: ge.automation[AutoTypeMobility]: ", ge.automation[AutoTypeMobility])
	if ge.automation[AutoTypeMobility] {
		runAutoMobility(ueMap)
	}
@@ -169,7 +175,7 @@ func runAutomation() {
}

func runAutoMovement() {
	log.Debug("Auto Movement: updating UE positions")
	log.Info("Auto Movement: updating UE positions")

	// Calculate number of increments (seconds) for position update
	currentTime := time.Now()
@@ -189,6 +195,8 @@ func runAutoMovement() {
}

func runAutoMobility(ueMap map[string]*am.Ue) {
	log.Info(">>> runAutoMobility: updating UE positions: ", ueMap)

	for _, ue := range ueMap {
		// Get stored UE info
		ueInfo := getUeInfo(ue.Name)
@@ -418,7 +426,7 @@ func calculateThroughput(radius float32, distance float32, maxUl int32, maxDl in
// ----------------------------  REST API  ------------------------------------

func geGetAutomationState(w http.ResponseWriter, r *http.Request) {
	log.Debug("Get all automation states")
	log.Info("Get all automation states")

	var automationList AutomationStateList
	for automation, state := range ge.automation {
@@ -443,10 +451,12 @@ func geGetAutomationState(w http.ResponseWriter, r *http.Request) {
}

func geGetAutomationStateByName(w http.ResponseWriter, r *http.Request) {
	log.Info(">>> geGetAutomationStateByName: ", r)
	// Get automation type from request path parameters
	vars := mux.Vars(r)
	log.Info(">>> geGetAutomationStateByName: vars: ", vars)
	automationType := vars["type"]
	log.Debug("Get automation state for type: ", automationType)
	log.Info("***************** Get automation state for type: ", automationType)

	// Get automation state
	var automationState AutomationState
@@ -475,17 +485,19 @@ func geGetAutomationStateByName(w http.ResponseWriter, r *http.Request) {
}

func geSetAutomationStateByName(w http.ResponseWriter, r *http.Request) {
	log.Info(">>> geSetAutomationStateByName: ", *r)
	// Get automation type from request path parameters
	vars := mux.Vars(r)
	vars := mux.Vars(r) //returns map[] https://stackoverflow.com/questions/31371111/mux-vars-not-working
	log.Info("geSetAutomationStateByName: vars: ", vars)
	automationType := vars["type"]

	// Retrieve requested state from query parameters
	query := r.URL.Query()
	automationState, _ := strconv.ParseBool(query.Get("run"))
	if automationState {
		log.Debug("Start automation for type: ", automationType)
		log.Info("Start automation for type: ", automationType)
	} else {
		log.Debug("Stop automation for type: ", automationType)
		log.Info("Stop automation for type: ", automationType)
	}

	// Set automation state
+45 −20
Original line number Diff line number Diff line
@@ -284,13 +284,13 @@ func msgHandler(msg *mq.Msg, userData interface{}) {

	switch msg.Message {
	case mq.MsgScenarioActivate:
		log.Debug("RX MSG: ", mq.PrintMsg(msg))
		log.Info("RX MSG: ", mq.PrintMsg(msg))
		processScenarioActivate()
	case mq.MsgScenarioUpdate:
		log.Debug("RX MSG: ", mq.PrintMsg(msg))
		log.Info("RX MSG: ", mq.PrintMsg(msg))
		processScenarioUpdate()
	case mq.MsgScenarioTerminate:
		log.Debug("RX MSG: ", mq.PrintMsg(msg))
		log.Info("RX MSG: ", mq.PrintMsg(msg))
		processScenarioTerminate()
	default:
		log.Trace("Ignoring unsupported message: ", mq.PrintMsg(msg))
@@ -298,16 +298,19 @@ func msgHandler(msg *mq.Msg, userData interface{}) {
}

func processScenarioActivate() {
	log.Info(">>> processScenarioActivate")
	// Sync with active scenario store
	ge.activeModel.UpdateScenario()

	// Retrieve & process POA and Compute Assets in active scenario
	assetList := ge.activeModel.GetNodeNames(mod.NodeTypePoa, mod.NodeTypePoa4G, mod.NodeTypePoa5G, mod.NodeTypePoaWifi, mod.NodeTypeEdge, mod.NodeTypeFog, mod.NodeTypeCloud)
	log.Info("processScenarioActivate: assetList (Poa): ", assetList)
	setAssets(assetList)

	// Retrieve & process UE assets in active scenario
	// NOTE: Required to make sure initial UE selection takes all POAs into account
	assetList = ge.activeModel.GetNodeNames(mod.NodeTypeUE)
	log.Info("processScenarioActivate: assetList (Ue): ", assetList)
	setAssets(assetList)

	// Update Gis cache
@@ -315,6 +318,7 @@ func processScenarioActivate() {

	// Start snapshot thread
	scenarioName := ge.activeModel.GetScenarioName()
	log.Info("processScenarioActivate: scenarioName: ", scenarioName)
	if scenarioName != "" {
		err := ge.StartSnapshotThread()

@@ -347,6 +351,7 @@ func processScenarioActivate() {
}

func processScenarioUpdate() {
	log.Info(">>> processScenarioUpdate")
	// Sync with active scenario store
	ge.activeModel.UpdateScenario()

@@ -366,6 +371,7 @@ func processScenarioUpdate() {
	}

	// Create, update & delete assets according to scenario update
	log.Info("processScenarioUpdate: assetList: ", assetList)
	setAssets(assetList)
	removeAssets(assetsToRemove)

@@ -374,6 +380,7 @@ func processScenarioUpdate() {
}

func processScenarioTerminate() {
	log.Info(">>> processScenarioTerminate")
	// Sync with active scenario store
	ge.activeModel.UpdateScenario()

@@ -389,7 +396,7 @@ func processScenarioTerminate() {
	_ = ge.assetMgr.DeleteAllCompute()

	// Clear asset list
	log.Debug("GeoData deleted for all assets")
	log.Info("GeoData deleted for all assets")
	ge.assets = make(map[string]*Asset)

	// Flush cache
@@ -397,6 +404,7 @@ func processScenarioTerminate() {
}

func setAssets(assetList []string) {
	log.Info(">>> setAssets")
	for _, assetName := range assetList {
		var geoData *AssetGeoData = nil
		var err error
@@ -461,21 +469,21 @@ func removeAssets(assetList []string) {
		delete(ge.assets, assetName)

		if isUe(nodeType) {
			log.Debug("GeoData deleted for UE: ", assetName)
			log.Info("GeoData deleted for UE: ", assetName)
			err := ge.assetMgr.DeleteUe(assetName)
			if err != nil {
				log.Error(err.Error())
				continue
			}
		} else if isPoa(nodeType) {
			log.Debug("GeoData deleted for POA: ", assetName)
			log.Info("GeoData deleted for POA: ", assetName)
			err := ge.assetMgr.DeletePoa(assetName)
			if err != nil {
				log.Error(err.Error())
				continue
			}
		} else if isCompute(nodeType) {
			log.Debug("GeoData deleted for Compute: ", assetName)
			log.Info("GeoData deleted for Compute: ", assetName)
			err := ge.assetMgr.DeleteCompute(assetName)
			if err != nil {
				log.Error(err.Error())
@@ -488,6 +496,7 @@ func removeAssets(assetList []string) {
}

func setUe(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoData) error {
	log.Info(">>> setUe")
	// UE data map
	ueData := make(map[string]interface{})

@@ -521,7 +530,7 @@ func setUe(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoData)
		if err != nil {
			return err
		}
		log.Debug("GeoData created for UE: ", asset.name)
		log.Info("GeoData created for UE: ", asset.name)
		asset.geoData = geoData

	} else {
@@ -559,7 +568,7 @@ func setUe(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoData)
			if err != nil {
				return err
			}
			log.Debug("GeoData updated for UE: ", asset.name)
			log.Info("GeoData updated for UE: ", asset.name)
		}
	}

@@ -567,6 +576,7 @@ func setUe(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoData)
}

func setPoa(asset *Asset, nl *dataModel.NetworkLocation, geoData *AssetGeoData) error {
	log.Info(">>> setUe")
	// Get POA Data
	poaData := make(map[string]interface{})

@@ -587,7 +597,7 @@ func setPoa(asset *Asset, nl *dataModel.NetworkLocation, geoData *AssetGeoData)
		if err != nil {
			return err
		}
		log.Debug("GeoData stored for POA: ", asset.name)
		log.Info("GeoData stored for POA: ", asset.name)
		asset.geoData = geoData
	} else {
		// Update Geodata
@@ -606,13 +616,14 @@ func setPoa(asset *Asset, nl *dataModel.NetworkLocation, geoData *AssetGeoData)
			if err != nil {
				return err
			}
			log.Debug("GeoData created for POA: ", asset.name)
			log.Info("GeoData created for POA: ", asset.name)
		}
	}
	return nil
}

func setCompute(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoData) error {
	log.Info(">>> setUe")
	// Get Compute Data
	computeData := make(map[string]interface{})

@@ -633,7 +644,7 @@ func setCompute(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoD
		if err != nil {
			return err
		}
		log.Debug("GeoData created for Compute: ", asset.name)
		log.Info("GeoData created for Compute: ", asset.name)
		asset.geoData = geoData
	} else {
		// Update Geodata
@@ -655,7 +666,7 @@ func setCompute(asset *Asset, pl *dataModel.PhysicalLocation, geoData *AssetGeoD
			if err != nil {
				return err
			}
			log.Debug("GeoData updated for Compute: ", asset.name)
			log.Info("GeoData updated for Compute: ", asset.name)
		}
	}
	return nil
@@ -995,7 +1006,7 @@ func updateCache() {

	if profiling {
		proFinish = time.Now()
		log.Debug("updateCache: ", proFinish.Sub(proStart))
		log.Info("updateCache: ", proFinish.Sub(proStart))
	}
}

@@ -1036,7 +1047,7 @@ func geDeleteGeoDataByName(w http.ResponseWriter, r *http.Request) {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	log.Debug("Delete GeoData for asset: ", asset.name)
	log.Info("Delete GeoData for asset: ", asset.name)

	// Remove asset from DB
	if isUe(asset.typ) {
@@ -1086,7 +1097,7 @@ func geGetAssetData(w http.ResponseWriter, r *http.Request) {
	if subType != "" {
		subTypeStr = subType
	}
	log.Debug("Get GeoData for assetType[", assetTypeStr, "] subType[", subTypeStr, "] excludePath[", excludePath, "]")
	log.Info("Get GeoData for assetType[", assetTypeStr, "] subType[", subTypeStr, "] excludePath[", excludePath, "]")

	var assetList GeoDataAssetList

@@ -1209,7 +1220,7 @@ func geGetDistanceGeoDataByName(w http.ResponseWriter, r *http.Request) {
	// Get asset name from request path parameters
	vars := mux.Vars(r)
	assetName := vars["assetName"]
	log.Debug("Get Distance GeoData for asset: ", assetName)
	log.Info("Get Distance GeoData for asset: ", assetName)

	// Make sure scenario is active
	if ge.activeModel.GetScenarioName() == "" {
@@ -1329,7 +1340,7 @@ func geGetWithinRangeGeoDataByName(w http.ResponseWriter, r *http.Request) {
	// Get asset name from request path parameters
	vars := mux.Vars(r)
	assetName := vars["assetName"]
	log.Debug("Get Within Range GeoData for asset: ", assetName)
	log.Info("Get Within Range GeoData for asset: ", assetName)

	// Make sure scenario is active
	if ge.activeModel.GetScenarioName() == "" {
@@ -1444,16 +1455,24 @@ func geGetWithinRangeGeoDataByName(w http.ResponseWriter, r *http.Request) {
}

func geGetGeoDataByName(w http.ResponseWriter, r *http.Request) {
	log.Info(">>> geGetGeoDataByName: ", *r)

	// Get asset name from request path parameters
	vars := mux.Vars(r)
	assetName := vars["assetName"]
	log.Debug("Get GeoData for asset: ", assetName)
	log.Info("Get GeoData for asset: ", assetName)

	// Retrieve query parameters
	query := r.URL.Query()
	log.Info("geGetGeoDataByName: query: ", query)
	if assetName == "" {
		assetName = query.Get("assetName")
	}
	excludePath := query.Get("excludePath")
	log.Info("geGetGeoDataByName: excludePath: ", excludePath)

	// Make sure scenario is active
	log.Info("geGetGeoDataByName: ge.activeModel.GetScenarioName: ", ge.activeModel.GetScenarioName())
	if ge.activeModel.GetScenarioName() == "" {
		err := errors.New("No active scenario")
		log.Error(err.Error())
@@ -1463,6 +1482,7 @@ func geGetGeoDataByName(w http.ResponseWriter, r *http.Request) {

	// Find asset in active scenario model
	node := ge.activeModel.GetNode(assetName)
	log.Info("geGetGeoDataByName: node: ", node)
	if node == nil {
		err := errors.New("Asset not found in active scenario")
		log.Error(err.Error())
@@ -1477,6 +1497,11 @@ func geGetGeoDataByName(w http.ResponseWriter, r *http.Request) {
	// Retrieve geodata from Asset Manager using asset name & type
	nodeType := ge.activeModel.GetNodeType(assetName)
	asset.SubType = nodeType
	log.Info("geGetGeoDataByName: nodeType: ", nodeType)
	log.Info("geGetGeoDataByName: isUe(nodeType): ", isUe(nodeType))

	ueMap, _ := ge.assetMgr.GetAllUe()
	log.Info("geGetGeoDataByName: All UEs: ", ueMap)

	if isUe(nodeType) {
		// Get UE information
@@ -1553,7 +1578,7 @@ func geUpdateGeoDataByName(w http.ResponseWriter, r *http.Request) {
	// Get asset name from request path parameters
	vars := mux.Vars(r)
	assetName := vars["assetName"]
	log.Debug("Set GeoData for asset: ", assetName)
	log.Info("Set GeoData for asset: ", assetName)

	// Retrieve Geodata to set from request body
	var geoData GeoDataAsset
+150 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package server
import (
	"os"
	//"bytes"
	//"encoding/json"
	"encoding/json"
	"errors"
	"fmt"
	"io"
@@ -516,14 +516,138 @@ func TestGetAutomationState(t *testing.T) {

	time.Sleep(1000 * time.Millisecond)

	var expectedResponse AutomationStateList
	expectedResponse.States = make([]AutomationState, 4)
	expectedResponse.States[0] = AutomationState{"MOVEMENT", false}
	expectedResponse.States[1] = AutomationState{"MOBILITY", false}
	expectedResponse.States[2] = AutomationState{"POAS-IN-RANGE", false}
	expectedResponse.States[3] = AutomationState{"NETWORK-CHARACTERISTICS-UPDATE", false}

	r, err := sendRequest(http.MethodGet, "/automation", nil, nil, nil, http.StatusOK, GetAutomationState)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
	fmt.Println("==> ", r)
	var respBody AutomationStateList
	err = json.Unmarshal([]byte(r), &respBody) // Verify Json conversion
	if err != nil {
		t.Fatalf("Failed to get expected response")
	}
	if !validateAutomationStateList(respBody, expectedResponse) {
		t.Fatalf("Failed to get expected response")
	}

	terminateScenario()

	Stop()
	err = Uninit()
	if err != nil {
		t.Fatalf("Error terminating test basic procedure")
	}
}

func TestGetGeodata(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	initializeVars()
	err := Init()
	if err != nil {
		t.Fatalf("Error initializing test basic procedure")
	}
	err = Run()
	if err != nil {
		t.Fatalf("Error running test basic procedure")
	}
	fmt.Println("Set a scenario")
	initialiseScenario(testScenario)

	time.Sleep(1000 * time.Millisecond)

	r, err := sendRequest(http.MethodGet, "/geodata?assetName=UE", nil, nil, nil, http.StatusNotFound, GetGeoDataByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
	fmt.Println("==> r: ", r)

	updateScenario("mobility1")
	time.Sleep(1000 * time.Millisecond)

	r, err = sendRequest(http.MethodGet, "/geodata?assetName=ue1", nil, nil, nil, http.StatusOK, GetGeoDataByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
	fmt.Println("==> r: ", r)

	terminateScenario()

	Stop()
	err = Uninit()
	if err != nil {
		t.Fatalf("Error terminating test basic procedure")
	}
}

/*func TestGetAutomationStateByName(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	initializeVars()
	err := Init()
	if err != nil {
		t.Fatalf("Error initializing test basic procedure")
	}
	err = Run()
	if err != nil {
		t.Fatalf("Error running test basic procedure")
	}
	fmt.Println("Set a scenario")
	initialiseScenario(testScenario)

	time.Sleep(1000 * time.Millisecond)

    // HTTP error 500 expected
	_, err = sendRequest(http.MethodGet, "/automation/MOBILITY", nil, nil, nil, http.StatusInternalServerError, GetAutomationStateByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}

	updateScenario("mobility1")
	time.Sleep(1000 * time.Millisecond)

    // Set MOBILITY
	_, err = sendRequest(http.MethodPost, "/automation/MOBILITY?run=true", nil, nil, nil, http.StatusOK, SetAutomationStateByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
    // HTTP OK expected
	r, err := sendRequest(http.MethodGet, "/automation/MOBILITY", nil, nil, nil, http.StatusOK, GetAutomationStateByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
	fmt.Println("==> r: ", r)

    updateScenario("mobility1")
	time.Sleep(1000 * time.Millisecond)

    // Unset MOBILITY
	_, err = sendRequest(http.MethodPost, "/automation/MOBILITY?run=false", nil, nil, nil, http.StatusOK, SetAutomationStateByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}
    // HTTP error 500 expected
	_, err = sendRequest(http.MethodGet, "/automation/MOBILITY", nil, nil, nil, http.StatusInternalServerError, GetAutomationStateByName)
	if err != nil {
		t.Fatal("Failed to get expected response: ", err.Error())
	}

    terminateScenario()

    Stop()
    err = Uninit()
	if err != nil {
		t.Fatalf("Error terminating test basic procedure")
	}
}*/

func terminateScenario() {
	if mqLocal != nil {
@@ -684,3 +808,27 @@ func sendRequest(method string, url string, body io.Reader, vars map[string]stri
	}
	return string(rr.Body.String()), nil
}

func validateAutomationStateList(response AutomationStateList, expectedResponse AutomationStateList) bool {
	if len(response.States) != len(expectedResponse.States) {
		fmt.Println("len(response) != len(expectedResponse)")
		return false
	}
	notFound := false
	for _, item := range response.States {
		found := false
		for _, item1 := range expectedResponse.States {
			if item == item1 {
				// Found it
				fmt.Println("validateAutomationStateList: item: ", item, "found")
				found = true
				break
			}
		}
		if !found {
			notFound = true
			break
		}
	}
	return !notFound
}
+1 −0
Original line number Diff line number Diff line
@@ -647,6 +647,7 @@ func predictedQosPost(w http.ResponseWriter, r *http.Request) {
		powerResp, _, err := gisAppClient.GeospatialDataApi.GetGeoDataPowerValues(context.TODO(), geocoordinatesList)
		if err != nil {
			log.Error("Failed to communicate with gis engine: ", err)
			errHandlerProblemDetails(w, "Failed to communicate with gis engine.", http.StatusBadRequest)
			return
		}
		routeInfoList := responseData.Routes[i].RouteInfo
Loading