From 82ec0fbda9ab2090fea542403221be853332e003 Mon Sep 17 00:00:00 2001 From: Rajamohan Raj Date: Wed, 3 Jun 2020 20:57:11 +0000 Subject: Implement Priority Based Controller list As part of this patch, have implemented a priorityQueue based contoller list which shall contain placement contollers and action contollers listed based on their priority. Issue-ID: MULTICLOUD-1064 Signed-off-by: Rajamohan Raj Change-Id: Id1beac6e3b6ec5156f64a169042d171ff28e38d6 --- src/orchestrator/pkg/appcontext/appcontext.go | 3 +- src/orchestrator/pkg/module/add_intents.go | 1 - src/orchestrator/pkg/module/instantiation.go | 20 ++- .../pkg/module/instantiation_scheduler_helper.go | 169 +++++++++++++++++++++ 4 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 src/orchestrator/pkg/module/instantiation_scheduler_helper.go (limited to 'src') diff --git a/src/orchestrator/pkg/appcontext/appcontext.go b/src/orchestrator/pkg/appcontext/appcontext.go index 98baa0f6..a847ae32 100644 --- a/src/orchestrator/pkg/appcontext/appcontext.go +++ b/src/orchestrator/pkg/appcontext/appcontext.go @@ -172,7 +172,6 @@ func (ac *AppContext) DeleteClusterMetaGrpHandle(ch interface{}) error { return nil } - /* GetClusterMetaHandle takes in appName and ClusterName as string arguments and return the ClusterMetaHandle as string */ @@ -188,7 +187,7 @@ func (ac *AppContext) GetClusterMetaHandle(app string, cluster string) (string, if err != nil { return "", err } - cmh := fmt.Sprintf("%v", ch) + metaGrpPREFIX + "/" + cmh := fmt.Sprintf("%v", ch) + metaGrpPREFIX + "/" return cmh, nil } diff --git a/src/orchestrator/pkg/module/add_intents.go b/src/orchestrator/pkg/module/add_intents.go index 89bf255f..9c47863a 100644 --- a/src/orchestrator/pkg/module/add_intents.go +++ b/src/orchestrator/pkg/module/add_intents.go @@ -224,7 +224,6 @@ func (c IntentClient) GetAllIntents(p string, ca string, v string, di string) (L if err != nil { return ListOfIntents{}, pkgerrors.Wrap(err, "Unmarshalling Intent") } - //mapOfIntents := ListOfIntents{a.Spec.Intent.ListOfIntents} listOfMapOfIntents = append(listOfMapOfIntents, a.Spec.Intent) } return ListOfIntents{listOfMapOfIntents}, nil diff --git a/src/orchestrator/pkg/module/instantiation.go b/src/orchestrator/pkg/module/instantiation.go index d7ec663d..27990cee 100644 --- a/src/orchestrator/pkg/module/instantiation.go +++ b/src/orchestrator/pkg/module/instantiation.go @@ -30,7 +30,7 @@ import ( const ManifestFileName = "manifest.yaml" // GenericPlacementIntentName denotes the generic placement intent name -const GenericPlacementIntentName = "generic-placement-intent" +const GenericPlacementIntentName = "genericPlacementIntent" // SEPARATOR used while creating clusternames to store in etcd const SEPARATOR = "+" @@ -100,22 +100,18 @@ and returns the name of the genericPlacementIntentName. Returns empty value if s */ func findGenericPlacementIntent(p, ca, v, di string) (string, error) { var gi string - var found bool iList, err := NewIntentClient().GetAllIntents(p, ca, v, di) if err != nil { return gi, err } for _, eachMap := range iList.ListOfIntents { if gi, found := eachMap[GenericPlacementIntentName]; found { - log.Info(":: Name of the generic-placement-intent ::", log.Fields{"GenPlmtIntent": gi}) - return gi, err + log.Info(":: Name of the generic-placement-intent found ::", log.Fields{"GenPlmtIntent": gi}) + return gi, nil } } - if found == false { - fmt.Println("generic-placement-intent not found !") - } + log.Info(":: generic-placement-intent not found ! ::", log.Fields{"Searched for GenPlmtIntent": GenericPlacementIntentName}) return gi, pkgerrors.New("Generic-placement-intent not found") - } // GetSortedTemplateForApp returns the sorted templates. @@ -277,6 +273,14 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin } // END:: save the context in the orchestrator db record + // BEGIN: scheduler code + + pl, mapOfControllers, err := getPrioritizedControllerList(p, ca, v, di) + log.Info("Priority Based List ", log.Fields{"PlacementControllers::": pl.pPlaCont, + "ActionControllers::": pl.pActCont, "mapOfControllers::": mapOfControllers}) + + // END: Scheduler code + log.Info(":: Done with instantiation... ::", log.Fields{"CompositeAppName": ca}) return err } diff --git a/src/orchestrator/pkg/module/instantiation_scheduler_helper.go b/src/orchestrator/pkg/module/instantiation_scheduler_helper.go new file mode 100644 index 00000000..cbc1b31d --- /dev/null +++ b/src/orchestrator/pkg/module/instantiation_scheduler_helper.go @@ -0,0 +1,169 @@ +/* + * Copyright 2020 Intel Corporation, Inc + * + * 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. + */ + +package module + +import ( + "container/heap" + log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/controller" + mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types" +) + +// ControllerTypePlacement denotes "placement" Controller Type +const ControllerTypePlacement string = "placement" + +// ControllerTypeAction denotes "action" Controller Type +const ControllerTypeAction string = "action" + +// ControllerElement consists of controller and an internal field - index +type ControllerElement struct { + controller controller.Controller + index int // used for indexing the HeapArray +} + +// PrioritizedControlList contains PrioritizedList of PlacementControllers and ActionControllers +type PrioritizedControlList struct { + pPlaCont []controller.Controller + pActCont []controller.Controller +} + +// PriorityQueue is the heapArray to store the Controllers +type PriorityQueue []*ControllerElement + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us highest Priority controller + // The lower the number, higher the priority + return pq[i].controller.Spec.Priority < pq[j].controller.Spec.Priority +} + +// Pop method returns the controller with the highest priority +func (pq *PriorityQueue) Pop() interface{} { + old := *pq + n := len(old) + c := old[n-1] + c.index = -1 + *pq = old[0 : n-1] + return c +} + +// Push method add a controller into the heapArray +func (pq *PriorityQueue) Push(c interface{}) { + n := len(*pq) + controllerElement := c.(*ControllerElement) + controllerElement.index = n + *pq = append(*pq, controllerElement) +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func getPrioritizedControllerList(p, ca, v, di string) (PrioritizedControlList, map[string]string, error) { + listOfControllers := make([]string, 0) // shall contain the real controllerNames to be passed to controllerAPI + mapOfControllers := make(map[string]string) + + iList, err := NewIntentClient().GetAllIntents(p, ca, v, di) + if err != nil { + return PrioritizedControlList{}, map[string]string{}, err + } + for _, eachmap := range iList.ListOfIntents { + for controller, controllerIntent := range eachmap { + if controller != GenericPlacementIntentName { + listOfControllers = append(listOfControllers, controller) + mapOfControllers[controller] = controllerIntent + } + } + } + + listPC := make([]*ControllerElement, 0) + listAC := make([]*ControllerElement, 0) + + for _, cn := range listOfControllers { + c, err := NewClient().Controller.GetController(cn) + + if err != nil { + return PrioritizedControlList{}, map[string]string{}, err + } + if c.Spec.Type == ControllerTypePlacement { + // Collect in listPC + listPC = append(listPC, &ControllerElement{controller: controller.Controller{ + Metadata: mtypes.Metadata{ + Name: c.Metadata.Name, + Description: c.Metadata.Description, + UserData1: c.Metadata.UserData1, + UserData2: c.Metadata.UserData2, + }, + Spec: controller.ControllerSpec{ + Host: c.Spec.Host, + Port: c.Spec.Port, + Type: c.Spec.Type, + Priority: c.Spec.Priority, + }, + }}) + } else if c.Spec.Type == ControllerTypeAction { + // Collect in listAC + listAC = append(listAC, &ControllerElement{controller: controller.Controller{ + Metadata: mtypes.Metadata{ + Name: c.Metadata.Name, + Description: c.Metadata.Description, + UserData1: c.Metadata.UserData1, + UserData2: c.Metadata.UserData2, + }, + Spec: controller.ControllerSpec{ + Host: c.Spec.Host, + Port: c.Spec.Port, + Type: c.Spec.Type, + Priority: c.Spec.Priority, + }, + }}) + } else { + log.Info("Controller type undefined", log.Fields{"Controller type": c.Spec.Type, "ControllerName": c.Metadata.Name}) + } + } + + pqPlacementCont := make(PriorityQueue, len(listPC)) + for i, eachPC := range listPC { + pqPlacementCont[i] = &ControllerElement{controller: eachPC.controller, index: i} + } + prioritizedPlaControllerList := make([]controller.Controller, 0) + heap.Init(&pqPlacementCont) + for pqPlacementCont.Len() > 0 { + ce := heap.Pop(&pqPlacementCont).(*ControllerElement) + + prioritizedPlaControllerList = append(prioritizedPlaControllerList, ce.controller) + } + + pqActionCont := make(PriorityQueue, len(listAC)) + for i, eachAC := range listAC { + pqActionCont[i] = &ControllerElement{controller: eachAC.controller, index: i} + } + prioritizedActControllerList := make([]controller.Controller, 0) + heap.Init(&pqActionCont) + for pqActionCont.Len() > 0 { + ce := heap.Pop(&pqActionCont).(*ControllerElement) + prioritizedActControllerList = append(prioritizedActControllerList, ce.controller) + } + + prioritizedControlList := PrioritizedControlList{pPlaCont: prioritizedPlaControllerList, pActCont: prioritizedActControllerList} + + return prioritizedControlList, mapOfControllers, nil + +} -- cgit 1.2.3-korg