diff options
-rwxr-xr-x | kud/tests/plugin_collection_v2.sh | 131 | ||||
-rw-r--r-- | src/orchestrator/pkg/appcontext/appcontext.go | 3 | ||||
-rw-r--r-- | src/orchestrator/pkg/module/add_intents.go | 1 | ||||
-rw-r--r-- | src/orchestrator/pkg/module/instantiation.go | 20 | ||||
-rw-r--r-- | src/orchestrator/pkg/module/instantiation_scheduler_helper.go | 169 |
5 files changed, 310 insertions, 14 deletions
diff --git a/kud/tests/plugin_collection_v2.sh b/kud/tests/plugin_collection_v2.sh index 5ebed6ad..05ff4265 100755 --- a/kud/tests/plugin_collection_v2.sh +++ b/kud/tests/plugin_collection_v2.sh @@ -82,6 +82,8 @@ deploymentIntentGroupNameDesc="test_deployment_intent_group_desc" releaseName="test" intentToBeAddedinDeploymentIntentGroup="name_of_intent_to_be_added_in_deployment_group" intentToBeAddedinDeploymentIntentGroupDesc="desc_of_intent_to_be_added_in_deployment_group" +hpaIntentName="hpaIntentName" +trafficIntentName="trafficIntentName" chart_name="edgex" profile_name="test_profile" @@ -90,6 +92,28 @@ namespace="plugin-tests-namespace" cloud_region_id="kud" cloud_region_owner="localhost" + +# Controllers +genericPlacementIntent="genericPlacementIntent" +OVNintent="OVNintent" +OVNintentName="OVNintentName" +OVNHostName="OVNHostName" +OVNPort="9027" +CostBasedIntent="costBasedIntent" +CostBasedIntentName="CostBasedIntentName" +CostBasedHostName="OVNHostName" +CostBasedPort="9028" +hpaIntent="hpaIntent" +trafficIntent="trafficIntent" +gpcHostName="gpcHostName" +gpcPort="9029" +hpaControllerIntentName="hpaControllerIntentName" +hpaHostName="hpaHostName" +hpaPort="9030" +trafficControllerIntentName="trafficControllerIntentName" +trafficHostName="trafficHostName" +trafficPort="9031" + # Setup install_deps populate_CSAR_composite_app_helm "$csar_id" @@ -97,7 +121,20 @@ populate_CSAR_composite_app_helm "$csar_id" # BEGIN :: Delete statements are issued so that we clean up the 'orchestrator' collection # and freshly populate the documents, also it serves as a direct test # for all our DELETE APIs and an indirect test for all GET APIs +print_msg "Deleting controller ${genericPlacementIntent}" +delete_resource "${base_url}/controllers/${genericPlacementIntent}" + +print_msg "Deleting controller ${hpaIntent}" +delete_resource "${base_url}/controllers/${hpaIntent}" + +print_msg "Deleting controller ${trafficIntent}" +delete_resource "${base_url}/controllers/${trafficIntent}" +print_msg "Deleting controller ${CostBasedIntent}" +delete_resource "${base_url}/controllers/${CostBasedIntent}" + +print_msg "Deleting controller ${OVNintent}" +delete_resource "${base_url}/controllers/${OVNintent}" print_msg "Deleting intentToBeAddedinDeploymentIntentGroup" delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}/intents/${intentToBeAddedinDeploymentIntentGroup}" @@ -135,6 +172,9 @@ delete_resource "${base_url}/projects/${project_name}/composite-apps/${composite print_msg "Deleting ${project_name}" delete_resource "${base_url}/projects/${project_name}" + + + # END :: Delete statements were issued so that we clean up the db # and freshly populate the documents, also it serves as a direct test # for all our DELETE APIs and an indirect test for all GET APIs @@ -415,7 +455,7 @@ call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${ # END: Registering DeploymentIntentGroup in the database # BEGIN: Adding intents to an intent group -print_msg "Adding the genericPlacement intent to the deploymentIntent group" +print_msg "Adding all the intents to the deploymentIntent group" payload="$(cat <<EOF { "metadata":{ @@ -426,7 +466,11 @@ payload="$(cat <<EOF }, "spec":{ "intent":{ - "generic-placement-intent":"${genericPlacementIntentName}" + "${genericPlacementIntent}":"${genericPlacementIntentName}", + "${hpaIntent}" : "${hpaControllerIntentName}", + "${trafficIntent}" : "${trafficControllerIntentName}", + "${CostBasedIntent}" : "${CostBasedIntentName}", + "${OVNintent}" : "${OVNintentName}" } } } @@ -435,8 +479,89 @@ EOF call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}/intents" # END: Adding intents to an intent group +# BEGIN: Adding controllers +print_msg "Adding CostBased placement contoller" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${CostBasedIntent}", + "description":"${CostBasedIntentName}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "host": "${CostBasedHostName}", + "port": ${CostBasedPort}, + "type": "placement", + "priority": 3 + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/controllers" + +print_msg "Adding HPA contoller" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${hpaIntent}", + "description":"${hpaControllerIntentName}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "host": "${hpaHostName}", + "port": ${hpaPort}, + "type": "placement", + "priority": 2 + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/controllers" + +print_msg "Adding traffic contoller" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${trafficIntent}", + "description":"${trafficControllerIntentName}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "host": "${trafficHostName}", + "port": ${trafficPort}, + "type": "action", + "priority": 3 + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/controllers" + +print_msg "Adding OVN action contoller" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${OVNintent}", + "description":"${OVNintentName}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "host": "${OVNHostName}", + "port": ${OVNPort}, + "type": "action", + "priority": 2 + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/controllers" +# END: Adding controllers + #BEGIN: Instantiation print_msg "Getting the sorted templates for each of the apps.." call_api -d "" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}/instantiate" # END: Instantiation - 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 + +} |