Commit 560f7463 authored by Kevin Di Lallo's avatar Kevin Di Lallo
Browse files

added sandbox store

parent bd77c2d3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ require (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0
	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-redis v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog v0.0.0
	github.com/gorilla/handlers v1.4.0
	github.com/gorilla/mux v1.7.3
@@ -22,5 +22,6 @@ replace (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model => ../../go-packages/meep-model
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq => ../../go-packages/meep-mq
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis => ../../go-packages/meep-redis
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store => ../../go-packages/meep-sandbox-store
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog => ../../go-packages/meep-watchdog
)
+2 −1
Original line number Diff line number Diff line
github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-metric-store v0.0.0-20200306214341-11d08c83c4d6/go.mod h1:l+tpnSBllsNPIngH3Db1D/dhJZu8V4T9pppO1MU2yLc=
github.com/KromDaniel/jonson v0.0.0-20180630143114-d2f9c3c389db/go.mod h1:RU+6d0CNIRSp6yo1mXLIIrnFa/3LHhvcDVLVJyovptM=
github.com/KromDaniel/rejonson v0.0.0-20180822072824-00b5bcf2b351 h1:1u1XrfCBnY+GijnyU6O1k4odp5TnqZQTsp5v7+n/E4Y=
github.com/KromDaniel/rejonson v0.0.0-20180822072824-00b5bcf2b351/go.mod h1:HxwfbuElTuGf+/uKZfjJrCnv0BmmpkPJDI7gBwj1KkM=
@@ -24,6 +25,7 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237/go.mod h1:UOnLAUmVG5paym8pD3C4B9BQylUDC2vXFJJpT7JrlEA=
@@ -33,7 +35,6 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+61 −84
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import (
	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model"
	mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq"
	redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis"
	ss "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store"
	wd "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog"
)

@@ -42,8 +42,8 @@ type Scenario struct {

type PlatformCtrl struct {
	scenarioStore *couch.Connector
	sandboxStore  *ss.SandboxStore
	veWatchdog    *wd.Watchdog
	sandboxStore  *redis.Connector
	mqGlobal      *mq.MsgQueue
}

@@ -53,6 +53,10 @@ const moduleNamespace = "default"
const moduleVirtEngineName = "meep-virt-engine"
const moduleVirtEngineNamespace = "default"

// MQ payload fields
const fieldSandboxName = "sandbox-name"
const fieldScenarioName = "scenario-name"

// Declare as variables to enable overwrite in test
var couchDBAddr = "http://meep-couchdb-svc-couchdb:5984/"
var redisDBAddr = "meep-redis-master:6379"
@@ -78,13 +82,13 @@ func Init() (err error) {
	}
	log.Info("Message Queue created")

	// Make Scenario DB connection
	// Connect to Scenario Store
	pfmCtrl.scenarioStore, err = couch.NewConnector(couchDBAddr, scenarioDBName)
	if err != nil {
		log.Error("Failed connection to Scenario DB. Error: ", err)
		log.Error("Failed connection to Scenario Store. Error: ", err)
		return err
	}
	log.Info("Connected to Scenario DB")
	log.Info("Connected to Scenario Store")

	// Retrieve scenario list from DB
	_, scenarioList, err := pfmCtrl.scenarioStore.GetDocList()
@@ -114,12 +118,12 @@ func Init() (err error) {
	}

	// Connect to Sandbox Store
	pfmCtrl.sandboxStore, err = redis.NewConnector(redisDBAddr, 0)
	pfmCtrl.sandboxStore, err = ss.NewSandboxStore(redisDBAddr)
	if err != nil {
		log.Error("Failed connection to Redis: ", err)
		log.Error("Failed connection to Sandbox Store: ", err.Error())
		return err
	}
	log.Info("Connected to Sandbox Store DB")
	log.Info("Connected to Sandbox Store")

	// Setup for virt-engine monitoring
	pfmCtrl.veWatchdog, err = wd.NewWatchdog(moduleName, moduleNamespace, moduleVirtEngineName, moduleVirtEngineNamespace, "")
@@ -362,8 +366,7 @@ func pcCreateSandbox(w http.ResponseWriter, r *http.Request) {
	for i := 0; i < retryCount; i++ {
		// sandboxName = "sbox-" + xid.New().String()
		sandboxName = "sbox-" + randSeq(6)
		key := moduleName + ":sandboxes:" + sandboxName
		if !pfmCtrl.sandboxStore.EntryExists(key) {
		if sbox, _ := pfmCtrl.sandboxStore.Get(sandboxName); sbox == nil {
			uniqueNameFound = true
			break
		}
@@ -407,11 +410,8 @@ func pcCreateSandboxWithName(w http.ResponseWriter, r *http.Request) {
		return
	}

	// Create new sandbox key
	key := moduleName + ":sandboxes:" + sandboxName

	// Make sure sandbox does not already exist
	if pfmCtrl.sandboxStore.EntryExists(key) {
	if sbox, _ := pfmCtrl.sandboxStore.Get(sandboxName); sbox != nil {
		err = errors.New("Sandbox already exists")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusConflict)
@@ -440,33 +440,16 @@ func pcDeleteSandbox(w http.ResponseWriter, r *http.Request) {
	sandboxName := vars["name"]
	log.Debug("Sandbox to delete: ", sandboxName)

	// Get sandbox key
	key := moduleName + ":sandboxes:" + sandboxName

	// Make sure sandbox exists
	if !pfmCtrl.sandboxStore.EntryExists(key) {
		err := errors.New("Sandbox not found exists")
	if sbox, _ := pfmCtrl.sandboxStore.Get(sandboxName); sbox == nil {
		err := errors.New("Sandbox not found")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	// Remove sandbox from DB
	err := pfmCtrl.sandboxStore.DelEntry(key)
	if err != nil {
		log.Error("Entry could not be deleted in DB for sandbox: ", sandboxName, ": ", err)
	}

	// Inform Virt Engine to destroy sandbox
	msg := pfmCtrl.mqGlobal.CreateMsg(mq.MsgSandboxDestroy, moduleVirtEngineName, moduleVirtEngineNamespace)
	msg.Payload["sandboxName"] = sandboxName
	log.Debug("TX MSG: ", mq.PrintMsg(msg))
	err = pfmCtrl.mqGlobal.SendMsg(msg)
	if err != nil {
		log.Error("Failed to send message. Error: ", err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// Delete sandbox
	deleteSandbox(sandboxName)

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
@@ -477,38 +460,24 @@ func pcDeleteSandbox(w http.ResponseWriter, r *http.Request) {
func pcDeleteSandboxList(w http.ResponseWriter, r *http.Request) {
	log.Debug("pcDeleteSandboxList")

	// Delete all sandboxes
	keyMatchStr := moduleName + ":sandboxes:*"
	err := pfmCtrl.sandboxStore.ForEachEntry(keyMatchStr, deleteSandbox, nil)
	if err != nil {
	// Get all sandboxes
	sboxMap, err := pfmCtrl.sandboxStore.GetAll()
	if err != nil || sboxMap == nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	// Delete all sandboxes
	for _, sbox := range sboxMap {
		deleteSandbox(sbox.Name)
	}

func deleteSandbox(key string, fields map[string]string, userData interface{}) error {
	// Flush sandbox store
	pfmCtrl.sandboxStore.Flush()

	// Remove sandbox from DB
	sandboxName := fields["name"]
	err := pfmCtrl.sandboxStore.DelEntry(key)
	if err != nil {
		log.Error("Entry could not be deleted in DB for sandbox: ", sandboxName, ": ", err.Error())
	}

	// Inform Virt Engine to destroy sandbox
	msg := pfmCtrl.mqGlobal.CreateMsg(mq.MsgSandboxDestroy, moduleVirtEngineName, moduleVirtEngineNamespace)
	msg.Payload["sandboxName"] = sandboxName
	log.Debug("TX MSG: ", mq.PrintMsg(msg))
	err = pfmCtrl.mqGlobal.SendMsg(msg)
	if err != nil {
		log.Error("Failed to send message. Error: ", err.Error())
	}

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

// Retrieve Sandbox with provided name
@@ -521,11 +490,9 @@ func pcGetSandbox(w http.ResponseWriter, r *http.Request) {
	sandboxName := vars["name"]
	log.Debug("Sandbox to retrieve: ", sandboxName)

	// Get sandbox key
	key := moduleName + ":sandboxes:" + sandboxName

	// Make sure sandbox exists
	if !pfmCtrl.sandboxStore.EntryExists(key) {
	// Get sandbox
	sbox, _ := pfmCtrl.sandboxStore.Get(sandboxName)
	if sbox == nil {
		err := errors.New("Sandbox not found")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusNotFound)
@@ -534,7 +501,7 @@ func pcGetSandbox(w http.ResponseWriter, r *http.Request) {

	// Prepare response
	var sandbox dataModel.Sandbox
	sandbox.Name = sandboxName
	sandbox.Name = sbox.Name

	// Format response
	jsonResponse, err := json.Marshal(sandbox)
@@ -555,16 +522,22 @@ func pcGetSandbox(w http.ResponseWriter, r *http.Request) {
func pcGetSandboxList(w http.ResponseWriter, r *http.Request) {
	log.Debug("pcGetSandboxList")

	// Retrieve list of sandboxes
	var sandboxList dataModel.SandboxList
	keyMatchStr := moduleName + ":sandboxes:*"
	err := pfmCtrl.sandboxStore.ForEachEntry(keyMatchStr, getSandboxInfo, &sandboxList)
	// Get all sandboxes
	sboxMap, err := pfmCtrl.sandboxStore.GetAll()
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Update sandbox list
	var sandboxList dataModel.SandboxList
	for _, sbox := range sboxMap {
		var sandbox dataModel.Sandbox
		sandbox.Name = sbox.Name
		sandboxList.Sandboxes = append(sandboxList.Sandboxes, sandbox)
	}

	// Format response
	jsonResponse, err := json.Marshal(sandboxList)
	if err != nil {
@@ -582,14 +555,11 @@ func pcGetSandboxList(w http.ResponseWriter, r *http.Request) {
// Create new sandbox in store and publish updagte
func createSandbox(sandboxName string, sandboxConfig *dataModel.SandboxConfig) (err error) {

	// Create new sandbox key
	key := moduleName + ":sandboxes:" + sandboxName

	// Create sandbox in DB
	fields := make(map[string]interface{})
	fields["name"] = sandboxName
	fields["scenarioName"] = sandboxConfig.ScenarioName
	err = pfmCtrl.sandboxStore.SetEntry(key, fields)
	sbox := new(ss.Sandbox)
	sbox.Name = sandboxName
	sbox.ScenarioName = sandboxConfig.ScenarioName
	err = pfmCtrl.sandboxStore.Set(sbox)
	if err != nil {
		log.Error(err.Error())
		return err
@@ -597,8 +567,8 @@ func createSandbox(sandboxName string, sandboxConfig *dataModel.SandboxConfig) (

	// Inform Virt Engine to create sandbox
	msg := pfmCtrl.mqGlobal.CreateMsg(mq.MsgSandboxCreate, moduleVirtEngineName, moduleVirtEngineNamespace)
	msg.Payload["sandboxName"] = sandboxName
	msg.Payload["scenarioName"] = sandboxConfig.ScenarioName
	msg.Payload[fieldSandboxName] = sandboxName
	msg.Payload[fieldScenarioName] = sandboxConfig.ScenarioName
	log.Debug("TX MSG: ", mq.PrintMsg(msg))
	err = pfmCtrl.mqGlobal.SendMsg(msg)
	if err != nil {
@@ -609,12 +579,19 @@ func createSandbox(sandboxName string, sandboxConfig *dataModel.SandboxConfig) (
	return nil
}

func getSandboxInfo(key string, fields map[string]string, userData interface{}) error {
	sandboxList := userData.(*dataModel.SandboxList)
	var sandbox dataModel.Sandbox
	sandbox.Name = fields["name"]
	sandboxList.Sandboxes = append(sandboxList.Sandboxes, sandbox)
	return nil
func deleteSandbox(sandboxName string) {

	// Remove sandbox from store
	pfmCtrl.sandboxStore.Del(sandboxName)

	// Inform Virt Engine to destroy sandbox
	msg := pfmCtrl.mqGlobal.CreateMsg(mq.MsgSandboxDestroy, moduleVirtEngineName, moduleVirtEngineNamespace)
	msg.Payload[fieldSandboxName] = sandboxName
	log.Debug("TX MSG: ", mq.PrintMsg(msg))
	err := pfmCtrl.mqGlobal.SendMsg(msg)
	if err != nil {
		log.Error("Failed to send message. Error: ", err.Error())
	}
}

var charset = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
+2 −1
Original line number Diff line number Diff line
@@ -10,8 +10,8 @@ require (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-metric-store v0.0.0
	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-redis v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-replay-manager v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store v0.0.0
	github.com/gorilla/handlers v1.4.0
	github.com/gorilla/mux v1.7.3
)
@@ -27,4 +27,5 @@ replace (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis => ../../go-packages/meep-redis
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-replay-manager => ../../go-packages/meep-replay-manager
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-ctrl-client => ../../go-packages/meep-sandbox-ctrl-client
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store => ../../go-packages/meep-sandbox-store
)
+14 −16
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@ import (
	ms "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-metric-store"
	mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model"
	mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq"
	redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis"
	replay "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-replay-manager"
	ss "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sandbox-store"
)

type Scenario struct {
@@ -54,13 +54,12 @@ type SandboxCtrl struct {
	activeModel   *mod.Model
	metricStore   *ms.MetricStore
	replayMgr     *replay.ReplayMgr
	sandboxStore  *redis.Connector
	sandboxStore  *ss.SandboxStore
}

const scenarioDBName = "scenarios"
const replayDBName = "replays"
const moduleName = "meep-sandbox-ctrl"
const platformModuleName = "meep-platform-ctrl"
const eventTypeMobility = "MOBILITY"
const eventTypeNetCharUpdate = "NETWORK-CHARACTERISTICS-UPDATE"
const eventTypePoasInRange = "POAS-IN-RANGE"
@@ -145,12 +144,12 @@ func Init() (err error) {
	}

	// Connect to Sandbox Store
	sbxCtrl.sandboxStore, err = redis.NewConnector(redisDBAddr, 0)
	sbxCtrl.sandboxStore, err = ss.NewSandboxStore(redisDBAddr)
	if err != nil {
		log.Error("Failed connection to Redis: ", err)
		log.Error("Failed connection to Sandbox Store: ", err.Error())
		return err
	}
	log.Info("Connected to Sandbox Store DB")
	log.Info("Connected to Sandbox Store")

	return nil
}
@@ -159,16 +158,15 @@ func Init() (err error) {
func Run() (err error) {

	// Activate scenario on sandbox startup if required, otherwise wait for activation request
	key := platformModuleName + ":sandboxes:" + sbxCtrl.sandboxName
	fields, err := sbxCtrl.sandboxStore.GetEntry(key)
	if err == nil {
		scenarioName := fields["scenarioName"]
		err = activateScenario(scenarioName)
	if sbox, err := sbxCtrl.sandboxStore.Get(sbxCtrl.sandboxName); err == nil && sbox != nil {
		if sbox.ScenarioName != "" {
			err = activateScenario(sbox.ScenarioName)
			if err != nil {
				log.Error("Failed to activate scenario with err: ", err.Error())
			} else {
			log.Info("Successfully activated scenario: ", scenarioName)
			_ = httpLog.ReInit(moduleName, scenarioName)
				log.Info("Successfully activated scenario: ", sbox.ScenarioName)
				_ = httpLog.ReInit(moduleName, sbxCtrl.sandboxName, scenarioName)
			}
		}
	}

Loading