Commit d2fbc336 authored by Michel Roy's avatar Michel Roy Committed by Kevin Di Lallo
Browse files

remove unused code & protect active endpoint

parent 333bb286
Loading
Loading
Loading
Loading
+184 −179
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import (
	"time"

	"github.com/flimzy/kivik"
	_ "github.com/go-kivik/couchdb"
	"github.com/gorilla/mux"

	ceModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-ctrl-engine-model"
@@ -42,12 +41,6 @@ const activeScenarioName = "active"
const moduleName string = "meep-ctrl-engine"
const moduleMonEngine string = "mon-engine"

const ALLUP = "0"
const ATLEASTONENOTUP = "1"
const NOUP = "2"

const NB_CORE_PODS = 10 //although virt-engine is not a pod yet... it is considered as one as is appended to the list of pods

var db *kivik.DB
var virtWatchdog *watchdog.Watchdog
var rc *redis.Connector
@@ -113,7 +106,8 @@ func CtrlEngineInit() (err error) {
	return nil
}

// Create a new scenario in store
// Create a new scenario in the scenario store
// POST /scenario/{name}
func ceCreateScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceCreateScenario")

@@ -150,7 +144,8 @@ func ceCreateScenario(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Delete scenario from store
// Delete scenario from scenario store
// DELETE /scenarios/{name}
func ceDeleteScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceDeleteScenario")

@@ -172,7 +167,8 @@ func ceDeleteScenario(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Remove all scenarios from DB
// Remove all scenarios from sceanrio store
// DELETE /scenarios
func ceDeleteScenarioList(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceDeleteScenarioList")

@@ -188,7 +184,8 @@ func ceDeleteScenarioList(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Retrieve the requested scenario
// Retrieve scenario from scenario store
// GET /scenarios/{name}
func ceGetScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceGetScenario")

@@ -226,6 +223,8 @@ func ceGetScenario(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, s)
}

// Retrieve all scenarios from scenario store
// GET /scenarios
func ceGetScenarioList(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceGetScenarioList")

@@ -249,7 +248,8 @@ func ceGetScenarioList(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, sl)
}

// Update stored scenario
// Update scenario in scenario store
// PUT /scenarios/{name}
func ceSetScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceSetScenario")

@@ -286,7 +286,8 @@ func ceSetScenario(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Activate/Deploy scenario
// Activate a scenario
// POST /active/{name}
func ceActivateScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceActivateScenario")

@@ -330,7 +331,8 @@ func ceActivateScenario(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// ceGetActiveScenario retrieves the deployed scenario status
// Retrieves the active scenario
// GET /active
func ceGetActiveScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("CEGetActiveScenario")

@@ -352,11 +354,17 @@ func ceGetActiveScenario(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, string(scenario))
}

// ceGetActiveNodeServiceMaps retrieves the deployed scenario external node service mappings
// Retrieves service maps of the active scenario
// GET /active/serviceMaps
// NOTE: query parameters 'node', 'type' and 'service' may be specified to filter results
func ceGetActiveNodeServiceMaps(w http.ResponseWriter, r *http.Request) {
	var filteredList *[]ceModel.NodeServiceMaps

	if !activeModel.Active {
		http.Error(w, "No scenario is active", http.StatusNotFound)
		return
	}

	// Retrieve node ID & service name from query parameters
	query := r.URL.Query()
	node := query.Get("node")
@@ -431,12 +439,13 @@ func ceGetActiveNodeServiceMaps(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, string(jsonResponse))
}

// Terminate the active/deployed scenario
// Terminate the active scenario
// DELETE /active
func ceTerminateScenario(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceTerminateScenario")

	if !activeModel.Active {
		http.Error(w, "No active model", http.StatusNotFound)
		http.Error(w, "No scenario is active", http.StatusNotFound)
		return
	}

@@ -451,11 +460,158 @@ func ceTerminateScenario(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

func ceGetEventList(w http.ResponseWriter, r *http.Request) {
// Send an event to the active scenario
// POST /events/{type}
func ceSendEvent(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceSendEvent")

	if !activeModel.Active {
		http.Error(w, "No scenario is active", http.StatusNotFound)
		return
	}

	// Get event type from request parameters
	vars := mux.Vars(r)
	eventType := vars["type"]
	log.Debug("Event Type: ", eventType)

	// Retrieve event from request body
	if r.Body == nil {
		err := errors.New("Request body is missing")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var event ceModel.Event
	decoder := json.NewDecoder(r.Body)
	err := decoder.Decode(&event)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Process Event
	var httpStatus int
	var error string
	switch eventType {
	case "MOBILITY":
		error, httpStatus = sendEventMobility(event)
	case "NETWORK-CHARACTERISTICS-UPDATE":
		error, httpStatus = sendEventNetworkCharacteristics(event)
	case "POAS-IN-RANGE":
		error, httpStatus = sendEventPoasInRange(event)
	default:
		error = "Unsupported event type"
		httpStatus = http.StatusBadRequest
	}

	if error != "" {
		log.Error(error)
		http.Error(w, error, httpStatus)
		return
	}

	// Send response
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
}

// Retrieve POD states
// GET /states
func ceGetStates(w http.ResponseWriter, r *http.Request) {

	subKey := ""
	var podsStatus ceModel.PodsStatus
	// Retrieve client ID & service name from query parameters
	query := r.URL.Query()
	longParam := query.Get("long")
	typeParam := query.Get("type")

	detailed := false
	if longParam == "true" {
		detailed = true
	}

	if typeParam == "" {
		subKey = "MO-scenario:"
	} else {
		subKey = "MO-" + typeParam + ":"
	}

	//values for pod name
	keyName := moduleMonEngine + "*" + subKey + "*"

	//get will be unique... but reusing the generic function
	var err error
	if detailed {
		// err = RedisDBForEachEntry(keyName, getPodDetails, &podsStatus)
		err = rc.ForEachEntry(keyName, getPodDetails, &podsStatus)
	} else {
		// err = RedisDBForEachEntry(keyName, getPodStatesOnly, &podsStatus)
		err = rc.ForEachEntry(keyName, getPodStatesOnly, &podsStatus)
	}

	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if typeParam == "core" {
		// ***** virt-engine is not a pod yet, but we need to make sure it is started to have a functional system
		var podStatus ceModel.PodStatus
		podStatus.Name = "virt-engine"
		if virtWatchdog.IsAlive() {
			podStatus.LogicalState = "Running"
		} else {
			podStatus.LogicalState = "NotRunning"
		}
		podsStatus.PodStatus = append(podsStatus.PodStatus, podStatus)
		// ***** virt-engine running or not code END

		//if some are missing... its because its coming up and as such... we cannot return a success yet... adding one entry that will be false

		corePods := getCorePodsList()

		//loop through each of them by name
		for _, statusPod := range podsStatus.PodStatus {
			for corePod := range corePods {
				if strings.Contains(statusPod.Name, corePod) {
					corePods[corePod] = true
					break
				}
			}
		}

		//loop through the list of pods to see which one might be missing
		for corePod := range corePods {
			if !corePods[corePod] {
				var podStatus ceModel.PodStatus
				podStatus.Name = corePod
				podStatus.LogicalState = "NotAvailable"
				podsStatus.PodStatus = append(podsStatus.PodStatus, podStatus)
			}
		}
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	// Format response
	jsonResponse, err := json.Marshal(podsStatus)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Send response
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsonResponse))
}

// ------------------

func sendEventNetworkCharacteristics(event ceModel.Event) (string, int) {
	if event.EventNetworkCharacteristicsUpdate == nil {
		return "Malformed request: missing EventNetworkCharacteristicsUpdate", http.StatusBadRequest
@@ -526,7 +682,7 @@ func sendEventPoasInRange(event ceModel.Event) (string, int) {
		log.Debug("UE Found. Checking for update to visible POAs")

		// Compare new list of poas with current UE list and update if necessary
		if !Equal(poasInRange, ue.NetworkLocationsInRange) {
		if !equal(poasInRange, ue.NetworkLocationsInRange) {
			log.Debug("Updating POAs in range for UE: " + ue.Name)
			ue.NetworkLocationsInRange = poasInRange

@@ -547,80 +703,6 @@ func sendEventPoasInRange(event ceModel.Event) (string, int) {
	return "", -1
}

// Equal tells whether a and b contain the same elements.
// A nil argument is equivalent to an empty slice.
func Equal(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}

func ceSendEvent(w http.ResponseWriter, r *http.Request) {
	log.Debug("ceSendEvent")

	// Get event type from request parameters
	vars := mux.Vars(r)
	eventType := vars["type"]
	log.Debug("Event Type: ", eventType)

	// Retrieve event from request body
	if r.Body == nil {
		err := errors.New("Request body is missing")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var event ceModel.Event
	decoder := json.NewDecoder(r.Body)
	err := decoder.Decode(&event)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Process Event
	var httpStatus int
	var error string
	switch eventType {
	case "MOBILITY":
		error, httpStatus = sendEventMobility(event)
	case "NETWORK-CHARACTERISTICS-UPDATE":
		error, httpStatus = sendEventNetworkCharacteristics(event)
	case "POAS-IN-RANGE":
		error, httpStatus = sendEventPoasInRange(event)
	default:
		error = "Unsupported event type"
		httpStatus = http.StatusBadRequest
	}

	if error != "" {
		log.Error(error)
		http.Error(w, error, httpStatus)
		return
	}

	// Send response
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
}

func ceGetMeepSettings(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
}

func ceSetMeepSettings(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
}

func getPodDetails(key string, fields map[string]string, userData interface{}) error {

	podsStatus := userData.(*ceModel.PodsStatus)
@@ -666,93 +748,16 @@ func getPodStatesOnly(key string, fields map[string]string, userData interface{}
	return nil
}

func ceGetStates(w http.ResponseWriter, r *http.Request) {

	subKey := ""
	var podsStatus ceModel.PodsStatus
	// Retrieve client ID & service name from query parameters
	query := r.URL.Query()
	longParam := query.Get("long")
	typeParam := query.Get("type")

	detailed := false
	if longParam == "true" {
		detailed = true
	}

	if typeParam == "" {
		subKey = "MO-scenario:"
	} else {
		subKey = "MO-" + typeParam + ":"
	}

	//values for pod name
	keyName := moduleMonEngine + "*" + subKey + "*"

	//get will be unique... but reusing the generic function
	var err error
	if detailed {
		// err = RedisDBForEachEntry(keyName, getPodDetails, &podsStatus)
		err = rc.ForEachEntry(keyName, getPodDetails, &podsStatus)
	} else {
		// err = RedisDBForEachEntry(keyName, getPodStatesOnly, &podsStatus)
		err = rc.ForEachEntry(keyName, getPodStatesOnly, &podsStatus)
	}

	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if typeParam == "core" {
		// ***** virt-engine is not a pod yet, but we need to make sure it is started to have a functional system
		var podStatus ceModel.PodStatus
		podStatus.Name = "virt-engine"
		if virtWatchdog.IsAlive() {
			podStatus.LogicalState = "Running"
		} else {
			podStatus.LogicalState = "NotRunning"
		}
		podsStatus.PodStatus = append(podsStatus.PodStatus, podStatus)
		// ***** virt-engine running or not code END

		//if some are missing... its because its coming up and as such... we cannot return a success yet... adding one entry that will be false

		corePods := getCorePodsList()

		//loop through each of them by name
		for _, statusPod := range podsStatus.PodStatus {
			for corePod := range corePods {
				if strings.Contains(statusPod.Name, corePod) {
					corePods[corePod] = true
					break
				}
			}
		}

		//loop through the list of pods to see which one might be missing
		for corePod := range corePods {
			if !corePods[corePod] {
				var podStatus ceModel.PodStatus
				podStatus.Name = corePod
				podStatus.LogicalState = "NotAvailable"
				podsStatus.PodStatus = append(podsStatus.PodStatus, podStatus)
			}
// Equal tells whether a and b contain the same elements.
// A nil argument is equivalent to an empty slice.
func equal(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	// Format response
	jsonResponse, err := json.Marshal(podsStatus)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Send response
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsonResponse))
	return true
}