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

virt-engine model - compile

parent 298729f3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ go 1.12
require (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-ctrl-engine-model v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog v0.0.0
)

@@ -16,3 +16,5 @@ replace github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger => ../../g
replace github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis => ../../go-packages/meep-redis

replace github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog => ../../go-packages/meep-watchdog

replace github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model => ../../go-packages/meep-model
+5 −0
Original line number Diff line number Diff line
@@ -4,14 +4,18 @@ github.com/KromDaniel/rejonson v0.0.0-20180822072824-00b5bcf2b351 h1:1u1XrfCBnY+
github.com/KromDaniel/rejonson v0.0.0-20180822072824-00b5bcf2b351/go.mod h1:HxwfbuElTuGf+/uKZfjJrCnv0BmmpkPJDI7gBwj1KkM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flimzy/kivik v1.8.1/go.mod h1:S2aPycbG0eDFll4wgXt9uacSNkXISPufutnc9sv+mdA=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kivik/couchdb v1.8.1/go.mod h1:5XJRkAMpBlEVA4q0ktIZjUPYBjoBmRoiWvwUBzP3BOQ=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -19,6 +23,7 @@ github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
+287 −276
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package server

import (
	"errors"
	"os"
	"os/user"
	"path/filepath"
@@ -25,16 +26,17 @@ import (
	"text/template"

	"github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-virt-engine/helm"
	model "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-ctrl-engine-model"
	ceModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-ctrl-engine-model"
	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model"
)

const SERVICE_PORT_MIN = 1
const SERVICE_PORT_MAX = 65535
const SERVICE_NODE_PORT_MIN = 30000
const SERVICE_NODE_PORT_MAX = 32767
const DEFAULT_DUMMY_CONTAINER_IMAGE = "nginx"
const serviceNodePortMin = 30000
const serviceNodePortMax = 32767
const trueStr = "true"
const falseStr = "false"

// DeploymentTemplate - Deployment Template
type DeploymentTemplate struct {
	Enabled                  string
	Name                     string
@@ -56,6 +58,7 @@ type DeploymentTemplate struct {
	PlacementId              string
}

// ServiceTemplate - Service Template
type ServiceTemplate struct {
	Enabled          string
	Name             string
@@ -68,6 +71,7 @@ type ServiceTemplate struct {
	MeServiceName    string
}

// ServicePortTemplate - Service Port Template
type ServicePortTemplate struct {
	Port       string
	TargetPort string
@@ -75,6 +79,7 @@ type ServicePortTemplate struct {
	NodePort   string
}

// ExternalTemplate -  External Template
type ExternalTemplate struct {
	Enabled           string
	Selector          []string
@@ -82,6 +87,7 @@ type ExternalTemplate struct {
	EgressServiceMap  []EgressServiceTemplate
}

// IngressServiceTemplate - Ingress Service Template
type IngressServiceTemplate struct {
	Name     string
	Port     string
@@ -89,6 +95,7 @@ type IngressServiceTemplate struct {
	Protocol string
}

// EgressServiceTemplate - Egress Service Template
type EgressServiceTemplate struct {
	Name      string
	MeSvcName string
@@ -97,7 +104,7 @@ type EgressServiceTemplate struct {
	Protocol  string
}

// helm values.yaml template
// ScenarioTemplate -helm values.yaml template
type ScenarioTemplate struct {
	Deployment    DeploymentTemplate
	Service       ServiceTemplate
@@ -108,41 +115,46 @@ type ScenarioTemplate struct {
// Service map
var serviceMap map[string]string

func addTemplateLabel(deploymentTemplate *DeploymentTemplate, label string) {
	deploymentTemplate.TemplateLabels = append(deploymentTemplate.TemplateLabels, label)
}

func addMatchLabel(deploymentTemplate *DeploymentTemplate, label string) {
	deploymentTemplate.MatchLabels = append(deploymentTemplate.MatchLabels, label)
}

func addServiceLabel(serviceTemplate *ServiceTemplate, label string) {
	serviceTemplate.Labels = append(serviceTemplate.Labels, label)
// Deploy - Generate charts & deploy
func Deploy(model *mod.Model) error {
	//var charts []helm.Chart
	charts, err := generateCharts(model)
	if err != nil {
		log.Debug("Error creating scenario templates: ", err)
		return err
	}

func addSelector(serviceTemplate *ServiceTemplate, selector string) {
	serviceTemplate.Selector = append(serviceTemplate.Selector, selector)
	err = deployCharts(charts)
	if err != nil {
		log.Error("Error deploying scenario templates: ", err)
		return err
	}

func addExtSelector(externalTemplate *ExternalTemplate, selector string) {
	externalTemplate.Selector = append(externalTemplate.Selector, selector)
	return nil
}

func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {

	var charts []helm.Chart
func generateCharts(model *mod.Model) (charts []helm.Chart, err error) {
	serviceMap = map[string]string{}

	// Parse domains
	for _, domain := range scenario.Deployment.Domains {
		// Parse zones
		for _, zone := range domain.Zones {
			// Parse Network Locations
			for _, nl := range zone.NetworkLocations {
				// Parse Physical locations
				for _, pl := range nl.PhysicalLocations {
					// Parse Processes
					for _, proc := range pl.Processes {
	procNames := model.GetNodeNames("PROCESS")

	for _, name := range procNames {
		node := model.GetNode(name)
		if node == nil {
			err = errors.New("Error finding process: " + name)
			return nil, err
		}
		proc, ok := node.(*ceModel.Process)
		if !ok {
			err = errors.New("Error casting process: " + name)
			return nil, err
		}
		ctx := model.GetNodeContext(name)
		if ctx == nil {
			err = errors.New("Error getting context for process: " + name)
			return nil, err
		}
		scenarioName := model.GetScenarioName()

		// Create default scenario template
		var scenarioTemplate ScenarioTemplate
@@ -152,7 +164,7 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
		setScenarioDefaults(&scenarioTemplate)

		// Fill general scenario template information
						scenarioTemplate.NamespaceName = scenario.Name
		scenarioTemplate.NamespaceName = scenarioName
		deploymentTemplate.Name = proc.Name

		// Create charts
@@ -160,9 +172,9 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
			log.Debug("Processing user-defined chart for element[", proc.Name, "]")

			// Add user-defined chart
							newChart := createChart(scenario.Name+"-"+proc.Name, getFullPath(proc.UserChartLocation),
			nc := newChart(scenarioName+"-"+proc.Name, getFullPath(proc.UserChartLocation),
				getFullPath(proc.UserChartAlternateValues))
							charts = append(charts, newChart)
			charts = append(charts, nc)
			log.Debug("user chart added ", len(charts))

			// Parse User Chart Group to find new group services
@@ -174,12 +186,12 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
				if meSvcName != "" {
					if _, found := serviceMap[meSvcName]; !found {
						serviceMap[meSvcName] = "meepMeSvc: " + meSvcName
										serviceTemplate.MeServiceEnabled = "true"
						serviceTemplate.MeServiceEnabled = trueStr
						serviceTemplate.MeServiceName = meSvcName
						addServiceLabel(serviceTemplate, "meepMeSvc: "+meSvcName)

										serviceTemplate.Namespace = scenario.Name
										addServiceLabel(serviceTemplate, "meepScenario: "+scenario.Name)
						serviceTemplate.Namespace = scenarioName
						addServiceLabel(serviceTemplate, "meepScenario: "+scenarioName)

						// NOTE: Every service within a group must expose the same port & protocol
						var portTemplate ServicePortTemplate
@@ -188,24 +200,23 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
						serviceTemplate.Ports = append(serviceTemplate.Ports, portTemplate)

						// Create chart files
										chartLocation, err := createYamlScenarioFiles(scenarioTemplate)
						chartLocation, err := templateChart(scenarioTemplate)
						if err != nil {
							log.Debug("yaml creation file process: ", err)
							return nil, err
						}

						// Create virt-engine chart for new group service
										newChart := createChart(scenario.Name+"-"+proc.Name+"-svc", chartLocation, "")
										charts = append(charts, newChart)
						c := newChart(scenarioName+"-"+proc.Name+"-svc", chartLocation, "")
						charts = append(charts, c)
						log.Debug("chart added for user chart group service ", len(charts))
					}
				}
							}
			} else {
				log.Debug("Processing virt-engine chart for element[", proc.Name, "]")

				// Fill deployment template information
							deploymentTemplate.Enabled = "true"
				deploymentTemplate.Enabled = trueStr
				deploymentTemplate.ContainerName = proc.Name
				deploymentTemplate.ContainerImageRepository = proc.Image
				deploymentTemplate.ContainerImagePullPolicy = "Always"
@@ -220,11 +231,11 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {

					// Add app name associated to service
					svcName := proc.ServiceConfig.Name
								serviceTemplate.Enabled = "true"
					serviceTemplate.Enabled = trueStr
					serviceTemplate.Name = svcName
								serviceTemplate.Namespace = scenario.Name
					serviceTemplate.Namespace = scenarioName
					addSelector(serviceTemplate, "meepSvc: "+svcName)
								addServiceLabel(serviceTemplate, "meepScenario: "+scenario.Name)
					addServiceLabel(serviceTemplate, "meepScenario: "+scenarioName)
					addTemplateLabel(deploymentTemplate, "meepSvc: "+svcName)

					// Create and store ME Service template only with first occurrence.
@@ -233,7 +244,7 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
					if meSvcName != "" {
						if _, found := serviceMap[meSvcName]; !found {
							serviceMap[meSvcName] = "meepMeSvc: " + meSvcName
										serviceTemplate.MeServiceEnabled = "true"
							serviceTemplate.MeServiceEnabled = trueStr
							serviceTemplate.MeServiceName = meSvcName
						}
						addServiceLabel(serviceTemplate, "meepMeSvc: "+meSvcName)
@@ -247,7 +258,7 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
						portTemplate.Protocol = ports.Protocol

						// Add NodePort if service is exposed externally
									if ports.ExternalPort >= SERVICE_NODE_PORT_MIN && ports.ExternalPort <= SERVICE_NODE_PORT_MAX {
						if ports.ExternalPort >= serviceNodePortMin && ports.ExternalPort <= serviceNodePortMax {
							portTemplate.NodePort = strconv.Itoa(int(ports.ExternalPort))
							serviceTemplate.Type = "NodePort"
						} else {
@@ -260,14 +271,14 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {

				// Enable GPU template if present
				if proc.GpuConfig != nil {
								deploymentTemplate.GpuEnabled = "true"
					deploymentTemplate.GpuEnabled = trueStr
					deploymentTemplate.GpuType = proc.GpuConfig.Type_
					deploymentTemplate.GpuCount = strconv.Itoa(int(proc.GpuConfig.Count))
				}

				// Enable External template if set
				if proc.IsExternal {
								externalTemplate.Enabled = "true"
					externalTemplate.Enabled = trueStr
					addExtSelector(externalTemplate, "meepAppId: "+proc.Id)

					// Add ingress Service Maps, if any
@@ -304,27 +315,73 @@ func populateScenarioTemplate(scenario model.Scenario) ([]helm.Chart, error) {
				}

				// Create chart files
							chartLocation, err := createYamlScenarioFiles(scenarioTemplate)
				chartLocation, err := templateChart(scenarioTemplate)
				if err != nil {
					log.Debug("yaml creation file process: ", err)
					return nil, err
				}

				// Create virt-engine chart
							newChart := createChart(scenario.Name+"-"+proc.Name, chartLocation, "")
				newChart := newChart(scenarioName+"-"+proc.Name, chartLocation, "")
				charts = append(charts, newChart)
				log.Debug("chart added ", len(charts))
			}

		}

	}

	return charts, nil
}

func deployCharts(charts []helm.Chart) error {

	err := helm.InstallCharts(charts)
	if err != nil {
		return err
	}
	return nil
}

func templateChart(scenarioTemplate ScenarioTemplate) (string, error) {

	homePath := os.Getenv("HOME")

	templateFilePath := homePath + "/.meep/template/values-template.yaml"
	templateDefaultDir := homePath + "/.meep/template/defaultDir"

	t, err := template.ParseFiles(templateFilePath)
	if err != nil {
		log.Error(err)
		return "", err
	}

	outputDirPath := homePath + "/.meep/active/" + scenarioTemplate.NamespaceName + "/" + scenarioTemplate.Deployment.Name
	log.Debug("Creation of the output path ", outputDirPath)

	_ = CopyDir(templateDefaultDir, outputDirPath)

	outputFilePath := outputDirPath + "/values.yaml"

	//creation of output file
	f, err := os.Create(outputFilePath)
	if err != nil {
		log.Debug("create file: ", err)
		return "", err
	}

	//filling the template output file
	err = t.Execute(f, scenarioTemplate)
	if err != nil {
		log.Debug("execute: ", err)
		return "", err
	}

	return charts, nil
	f.Close()
	return outputDirPath, nil
}

func createChart(name string, chartLocation string, valuesFile string) helm.Chart {
func newChart(name string, chartLocation string, valuesFile string) helm.Chart {
	var chart helm.Chart
	chart.ChartName = name
	chart.ReleaseName = "meep-" + name
@@ -333,6 +390,26 @@ func createChart(name string, chartLocation string, valuesFile string) helm.Char
	return chart
}

func addTemplateLabel(deploymentTemplate *DeploymentTemplate, label string) {
	deploymentTemplate.TemplateLabels = append(deploymentTemplate.TemplateLabels, label)
}

func addMatchLabel(deploymentTemplate *DeploymentTemplate, label string) {
	deploymentTemplate.MatchLabels = append(deploymentTemplate.MatchLabels, label)
}

func addServiceLabel(serviceTemplate *ServiceTemplate, label string) {
	serviceTemplate.Labels = append(serviceTemplate.Labels, label)
}

func addSelector(serviceTemplate *ServiceTemplate, selector string) {
	serviceTemplate.Selector = append(serviceTemplate.Selector, selector)
}

func addExtSelector(externalTemplate *ExternalTemplate, selector string) {
	externalTemplate.Selector = append(externalTemplate.Selector, selector)
}

func getFullPath(path string) string {
	fullPath := path

@@ -359,26 +436,26 @@ func setScenarioDefaults(scenarioTemplate *ScenarioTemplate) {
}

func setDeploymentDefaults(deploymentTemplate *DeploymentTemplate) {
	deploymentTemplate.Enabled = "false"
	deploymentTemplate.Enabled = falseStr
	deploymentTemplate.ReplicaCount = "1"
	deploymentTemplate.ApiVersion = "v1"
	deploymentTemplate.ContainerEnvEnabled = "false"
	deploymentTemplate.ContainerCommandEnabled = "false"
	deploymentTemplate.GpuEnabled = "false"
	deploymentTemplate.ContainerEnvEnabled = falseStr
	deploymentTemplate.ContainerCommandEnabled = falseStr
	deploymentTemplate.GpuEnabled = falseStr
}

func setServiceDefaults(serviceTemplate *ServiceTemplate) {
	serviceTemplate.Enabled = "false"
	serviceTemplate.MeServiceEnabled = "false"
	serviceTemplate.Enabled = falseStr
	serviceTemplate.MeServiceEnabled = falseStr
}

func setExternalDefaults(externalTemplate *ExternalTemplate) {
	externalTemplate.Enabled = "false"
	externalTemplate.Enabled = falseStr
}

func setEnv(deployment *DeploymentTemplate, envString string) {
	if envString != "" {
		deployment.ContainerEnvEnabled = "true"
		deployment.ContainerEnvEnabled = trueStr
		allVar := strings.Split(envString, ",")

		for _, oneVar := range allVar {
@@ -392,7 +469,7 @@ func setEnv(deployment *DeploymentTemplate, envString string) {
func setCommand(deployment *DeploymentTemplate, command string, commandArgs string) {
	if command != "" {
		log.Debug("command ", command)
		deployment.ContainerCommandEnabled = "true"
		deployment.ContainerCommandEnabled = trueStr

		// Retrieve command list
		allCmd := strings.Split(command, ",")
@@ -407,69 +484,3 @@ func setCommand(deployment *DeploymentTemplate, command string, commandArgs stri
		}
	}
}

func CreateYamlScenarioFile(scenario model.Scenario) error {

	//var charts []helm.Chart
	charts, err := populateScenarioTemplate(scenario)

	if err != nil {
		log.Debug("populate template : ", err)
		return err
	}

	err = deployCharts(charts)
	if err != nil {
		log.Error("charts error : ", err)
		return err
	}

	return nil
}

func createYamlScenarioFiles(scenarioTemplate ScenarioTemplate) (string, error) {

	homePath := os.Getenv("HOME")

	templateFilePath := homePath + "/.meep/template/values-template.yaml"
	templateDefaultDir := homePath + "/.meep/template/defaultDir"

	t, err := template.ParseFiles(templateFilePath)
	if err != nil {
		log.Error(err)
		return "", err
	}

	outputDirPath := homePath + "/.meep/active/" + scenarioTemplate.NamespaceName + "/" + scenarioTemplate.Deployment.Name
	log.Debug("Creation of the output path ", outputDirPath)

	_ = CopyDir(templateDefaultDir, outputDirPath)

	outputFilePath := outputDirPath + "/values.yaml"

	//creation of output file
	f, err := os.Create(outputFilePath)
	if err != nil {
		log.Debug("create file: ", err)
		return "", err
	}

	//filling the template output file
	err = t.Execute(f, scenarioTemplate)
	if err != nil {
		log.Debug("execute: ", err)
		return "", err
	}

	f.Close()
	return outputDirPath, nil
}

func deployCharts(charts []helm.Chart) error {

	err := helm.InstallCharts(charts)
	if err != nil {
		return err
	}
	return nil
}
+31 −70
Original line number Diff line number Diff line
@@ -17,47 +17,31 @@
package server

import (
	"encoding/json"
	"os"
	"strings"

	"github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-virt-engine/helm"
	model "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-ctrl-engine-model"
	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis"
	mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model"
	watchdog "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-watchdog"
)

const moduleCtrlEngine string = "ctrl-engine"
const typeActive string = "active"
const channelCtrlActive string = moduleCtrlEngine + "-" + typeActive
// const moduleCtrlEngine string = "ctrl-engine"
// const typeActive string = "active"
// const channelCtrlActive string = moduleCtrlEngine + "-" + typeActive
// var rc *redis.Connector
// const activeScenarioEventKey string = moduleCtrlEngine + ":" + typeActive

var activeScenarioName string = ""
var watchdogClient *watchdog.Pingee
var rc *redis.Connector

const activeScenarioEventKey string = moduleCtrlEngine + ":" + typeActive
const moduleName string = "meep-virt-engine"
const redisAddr string = "localhost:30379"

var watchdogClient *watchdog.Pingee
var activeModel *mod.Model
var activeScenarioName string

// VirtEngineInit - Initialize virtualization engine
func VirtEngineInit() (err error) {
	log.Debug("Initializing MEEP Virtualization Engine")
	// Connect to Redis DB
	rc, err = redis.NewConnector(redisAddr, 0)
	if err != nil {
		log.Error("Failed connection to Redis DB. Error: ", err)
		return err
	}
	log.Info("Connected to Redis DB")

	// Subscribe to Pub-Sub events for MEEP Controller
	// NOTE: Current implementation is RedisDB Pub-Sub
	err = rc.Subscribe(channelCtrlActive)
	if err != nil {
		log.Error("Failed to subscribe to Pub/Sub events. Error: ", err)
		return err
	}
	log.Info("Subscribed to Redis Events")

	// Setup for liveness monitoring
	watchdogClient, err = watchdog.NewPingee(redisAddr, "meep-virt-engine")
@@ -71,23 +55,29 @@ func VirtEngineInit() (err error) {
		return err
	}

	// Listen for model updates
	activeModel, err = mod.NewModel(redisAddr, moduleName, "activeScenario")
	if err != nil {
		log.Error("Failed to create model: ", err.Error())
		return err
	}

	return nil
}

// ListenEvents - Redis DB event listener
// ListenEvents - Listen for model updates
func ListenEvents() {
	// Listen for subscribed events. Provide event handler method.
	_ = rc.Listen(eventHandler)

	err := activeModel.Listen(eventHandler)
	if err != nil {
		log.Error("Failed to listening for model updates: ", err.Error())
	}
}

func eventHandler(channel string, payload string) {
	// Handle Message according to Rx Channel
	switch channel {

	// MEEP Ctrl Engine active scenario update event
	case channelCtrlActive:
		log.Debug("Event received on channel: ", channel)
	case mod.ActiveScenarioEvents:
		processActiveScenarioUpdate()

	default:
@@ -96,54 +86,25 @@ func eventHandler(channel string, payload string) {
}

func processActiveScenarioUpdate() {
	// Retrieve active scenario from DB
	jsonScenario, err := rc.JSONGetEntry(activeScenarioEventKey, ".")
	log.Debug("Scenario Event:", jsonScenario)
	if err != nil {
	if !activeModel.Active {
		terminateScenario(activeScenarioName)
		activeScenarioName = ""
	} else {
		activateScenario(jsonScenario)
		// Cache name for later deletion
		activeScenarioName = activeModel.GetScenarioName()
		activateScenario()
	}
}

func unmarshallScenario(jsonScenario string) (model.Scenario, error) {

	log.Debug("unmarshallScenario")

	var scenario model.Scenario

	//readAndPrintRequest(r)
	err := json.Unmarshal([]byte(jsonScenario), &scenario)
func activateScenario() {
	err := Deploy(activeModel)
	if err != nil {
		log.Error(err.Error())
		return scenario, err
	}
	return scenario, nil
}

func activateScenario(jsonScenario string) {
	scenario, err := unmarshallScenario(jsonScenario)
	if err != nil {
		log.Error("Error unmarshalling scenario: ", jsonScenario)
		return
	}

	activeScenarioName = scenario.Name
	err = CreateYamlScenarioFile(scenario)
	if err != nil {
		log.Error("Error creating scenario charts: ", err)
		log.Error("Error creating charts: ", err)
		return
	}
}

func terminateScenario(name string) {
	// Make sure scenario name is valid
	if name == "" {
		log.Warn("Trying to terminate empty scenario")
		return
	}

	// Retrieve list of releases
	rels, _ := helm.GetReleasesName()
	var toDelete []helm.Chart