Ver Fonte

Issue #173 inject custom prices into custom provider if the setting to enable custom pricing is true

Niko Kovacevic há 6 anos atrás
pai
commit
3cc345d753
4 ficheiros alterados com 98 adições e 76 exclusões
  1. 26 3
      cloud/customprovider.go
  2. 13 0
      cloud/provider.go
  3. 0 1
      costmodel/aggregations.go
  4. 59 72
      costmodel/costmodel.go

+ 26 - 3
cloud/customprovider.go

@@ -128,10 +128,33 @@ func (cp *CustomProvider) NodePricing(key Key) (*Node, error) {
 		k += ",gpu"    // TODO: support multiple custom gpu types.
 		gpuCount = "1" // TODO: support more than one gpu.
 	}
+
+	cpu := cp.Pricing[k].CPU
+	ram := cp.Pricing[k].RAM
+	gpu := cp.Pricing[k].GPU
+
+	// If custom pricing is enabled and can be retrieved, replace
+	// default cost values with custom values
+	customPricing, err := cp.GetConfig()
+	if CustomPricesEnabled(cp) && err == nil {
+		// TODO nikovacevic-caching how to determine if it is spot?
+		isSpot := false
+
+		if isSpot {
+			cpu = customPricing.SpotCPU
+			ram = customPricing.SpotRAM
+			gpu = customPricing.SpotGPU
+		} else {
+			cpu = customPricing.CPU
+			ram = customPricing.RAM
+			gpu = customPricing.GPU
+		}
+	}
+
 	return &Node{
-		VCPUCost: cp.Pricing[k].CPU,
-		RAMCost:  cp.Pricing[k].RAM,
-		GPUCost:  cp.Pricing[k].GPU,
+		VCPUCost: cpu,
+		RAMCost:  ram,
+		GPUCost:  gpu,
 		GPU:      gpuCount,
 	}, nil
 }

+ 13 - 0
cloud/provider.go

@@ -169,6 +169,17 @@ func ClusterName(p Provider) string {
 	return name
 }
 
+// CustomPricesEnabled returns the boolean equivalent of the cloup provider's custom prices flag,
+// indicating whether or not the cluster is using custom pricing.
+func CustomPricesEnabled(p Provider) bool {
+	config, err := p.GetConfig()
+	if err != nil {
+		return false
+	}
+
+	return config.CustomPricesEnabled == "true"
+}
+
 // GetDefaultPricingData will search for a json file representing pricing data in /models/ and use it for base pricing info.
 func GetDefaultPricingData(fname string) (*CustomPricing, error) {
 	path := os.Getenv("CONFIG_PATH")
@@ -256,10 +267,12 @@ func NewProvider(clientset *kubernetes.Clientset, apiKey string) (Provider, erro
 			APIKey:    apiKey,
 		}, nil
 	}
+
 	nodes, err := clientset.CoreV1().Nodes().List(metav1.ListOptions{})
 	if err != nil {
 		return nil, err
 	}
+
 	provider := strings.ToLower(nodes.Items[0].Spec.ProviderID)
 	if strings.HasPrefix(provider, "aws") {
 		klog.V(2).Info("Found ProviderID starting with \"aws\", using AWS Provider")

+ 0 - 1
costmodel/aggregations.go

@@ -186,7 +186,6 @@ func mergeVectors(costDatum *CostData, aggregation *Aggregation, discount float6
 	}
 }
 
-// TODO nikovacevic-caching
 func getPriceVectors(costDatum *CostData, discount float64, idleCoefficient float64) ([]*Vector, []*Vector, []*Vector, [][]*Vector) {
 	cpuv := make([]*Vector, 0, len(costDatum.CPUAllocation))
 	for _, val := range costDatum.CPUAllocation {

+ 59 - 72
costmodel/costmodel.go

@@ -931,18 +931,20 @@ func GetPVCost(pv *costAnalyzerCloud.PV, kpv *v1.PersistentVolume, cloud costAna
 	return nil
 }
 
-func getNodeCost(cache ClusterCache, cloud costAnalyzerCloud.Provider) (map[string]*costAnalyzerCloud.Node, error) {
-	cfg, err := cloud.GetConfig()
+func getNodeCost(cache ClusterCache, cp costAnalyzerCloud.Provider) (map[string]*costAnalyzerCloud.Node, error) {
+	cfg, err := cp.GetConfig()
 	if err != nil {
 		return nil, err
 	}
+
 	nodeList := cache.GetAllNodes()
 	nodes := make(map[string]*costAnalyzerCloud.Node)
 	for _, n := range nodeList {
 		name := n.GetObjectMeta().GetName()
 		nodeLabels := n.GetObjectMeta().GetLabels()
 		nodeLabels["providerID"] = n.Spec.ProviderID
-		cnode, err := cloud.NodePricing(cloud.GetKey(nodeLabels))
+
+		cnode, err := cp.NodePricing(cp.GetKey(nodeLabels))
 		if err != nil {
 			klog.V(1).Infof("Error getting node. Error: " + err.Error())
 			nodes[name] = cnode
@@ -957,6 +959,7 @@ func getNodeCost(cache ClusterCache, cloud costAnalyzerCloud.Provider) (map[stri
 		} else {
 			cpu, _ = strconv.ParseFloat(newCnode.VCPU, 64)
 		}
+
 		var ram float64
 		if newCnode.RAM == "" {
 			newCnode.RAM = n.Status.Capacity.Memory().String()
@@ -964,97 +967,75 @@ func getNodeCost(cache ClusterCache, cloud costAnalyzerCloud.Provider) (map[stri
 		ram = float64(n.Status.Capacity.Memory().Value())
 		newCnode.RAMBytes = fmt.Sprintf("%f", ram)
 
-		if newCnode.GPU != "" && newCnode.GPUCost == "" { // We couldn't find a gpu cost, so fix cpu and ram, then accordingly
-			klog.V(4).Infof("GPU without cost found for %s, calculating...", cloud.GetKey(nodeLabels).Features())
-			defaultCPU, err := strconv.ParseFloat(cfg.CPU, 64)
-			if err != nil {
-				klog.V(3).Infof("Could not parse default cpu price")
-				return nil, err
-			}
-			defaultRAM, err := strconv.ParseFloat(cfg.RAM, 64)
+		defaultCPU, err := strconv.ParseFloat(cfg.CPU, 64)
+		if err != nil {
+			klog.V(3).Infof("Could not parse default cpu price")
+			return nil, err
+		}
+
+		defaultRAM, err := strconv.ParseFloat(cfg.RAM, 64)
+		if err != nil {
+			klog.V(3).Infof("Could not parse default ram price")
+			return nil, err
+		}
+
+		defaultGPU, err := strconv.ParseFloat(cfg.RAM, 64)
+		if err != nil {
+			klog.V(3).Infof("Could not parse default gpu price")
+			return nil, err
+		}
+
+		var nodePrice float64
+		if newCnode.Cost != "" {
+			nodePrice, err = strconv.ParseFloat(newCnode.Cost, 64)
 			if err != nil {
-				klog.V(3).Infof("Could not parse default ram price")
+				klog.V(3).Infof("Could not parse total node price")
 				return nil, err
 			}
-			defaultGPU, err := strconv.ParseFloat(cfg.RAM, 64)
+		} else {
+			nodePrice, err = strconv.ParseFloat(newCnode.VCPUCost, 64) // all the price was allocated the the CPU
 			if err != nil {
-				klog.V(3).Infof("Could not parse default gpu price")
+				klog.V(3).Infof("Could not parse node vcpu price")
 				return nil, err
 			}
-			cpuToRAMRatio := defaultCPU / defaultRAM
-			gpuToRAMRatio := defaultGPU / defaultRAM
+		}
 
-			ramGB := ram / 1024 / 1024 / 1024
-			ramMultiple := gpuToRAMRatio + cpu*cpuToRAMRatio + ramGB
-			var nodePrice float64
-			if newCnode.Cost != "" {
-				nodePrice, err = strconv.ParseFloat(newCnode.Cost, 64)
-				if err != nil {
-					klog.V(3).Infof("Could not parse total node price")
-					return nil, err
-				}
-			} else {
-				nodePrice, err = strconv.ParseFloat(newCnode.VCPUCost, 64) // all the price was allocated the the CPU
-				if err != nil {
-					klog.V(3).Infof("Could not parse node vcpu price")
-					return nil, err
-				}
-			}
+		cpuToRAMRatio := defaultCPU / defaultRAM
 
+		ramGB := ram / 1024 / 1024 / 1024
+
+		if newCnode.GPU != "" && newCnode.GPUCost == "" {
+			// We couldn't find a gpu cost, so fix cpu and ram, then accordingly
+			klog.V(4).Infof("GPU without cost found for %s, calculating...", cp.GetKey(nodeLabels).Features())
+
+			gpuToRAMRatio := defaultGPU / defaultRAM
+			ramMultiple := gpuToRAMRatio + cpu*cpuToRAMRatio + ramGB
 			ramPrice := (nodePrice / ramMultiple)
 			cpuPrice := ramPrice * cpuToRAMRatio
 			gpuPrice := ramPrice * gpuToRAMRatio
+
 			newCnode.VCPUCost = fmt.Sprintf("%f", cpuPrice)
 			newCnode.RAMCost = fmt.Sprintf("%f", ramPrice)
 			newCnode.RAMBytes = fmt.Sprintf("%f", ram)
 			newCnode.GPUCost = fmt.Sprintf("%f", gpuPrice)
+		} else if newCnode.RAMCost == "" {
+			// We couldn't find a ramcost, so fix cpu and allocate ram accordingly
+			klog.V(4).Infof("No RAM cost found for %s, calculating...", cp.GetKey(nodeLabels).Features())
 
-		} else {
-			if newCnode.RAMCost == "" { // We couldn't find a ramcost, so fix cpu and allocate ram accordingly
-				klog.V(4).Infof("No RAM cost found for %s, calculating...", cloud.GetKey(nodeLabels).Features())
-				defaultCPU, err := strconv.ParseFloat(cfg.CPU, 64)
-				if err != nil {
-					klog.V(3).Infof("Could not parse default cpu price")
-					return nil, err
-				}
-				defaultRAM, err := strconv.ParseFloat(cfg.RAM, 64)
-				if err != nil {
-					klog.V(3).Infof("Could not parse default ram price")
-					return nil, err
-				}
-				cpuToRAMRatio := defaultCPU / defaultRAM
-
-				ramGB := ram / 1024 / 1024 / 1024
-
-				ramMultiple := cpu*cpuToRAMRatio + ramGB
-
-				var nodePrice float64
-				if newCnode.Cost != "" {
-					nodePrice, err = strconv.ParseFloat(newCnode.Cost, 64)
-					if err != nil {
-						klog.V(3).Infof("Could not parse total node price")
-						return nil, err
-					}
-				} else {
-					nodePrice, err = strconv.ParseFloat(newCnode.VCPUCost, 64) // all the price was allocated the the CPU
-					if err != nil {
-						klog.V(3).Infof("Could not parse node vcpu price")
-						return nil, err
-					}
-				}
+			ramMultiple := cpu*cpuToRAMRatio + ramGB
+			ramPrice := (nodePrice / ramMultiple)
+			cpuPrice := ramPrice * cpuToRAMRatio
 
-				ramPrice := (nodePrice / ramMultiple)
-				cpuPrice := ramPrice * cpuToRAMRatio
+			newCnode.VCPUCost = fmt.Sprintf("%f", cpuPrice)
+			newCnode.RAMCost = fmt.Sprintf("%f", ramPrice)
+			newCnode.RAMBytes = fmt.Sprintf("%f", ram)
 
-				newCnode.VCPUCost = fmt.Sprintf("%f", cpuPrice)
-				newCnode.RAMCost = fmt.Sprintf("%f", ramPrice)
-				newCnode.RAMBytes = fmt.Sprintf("%f", ram)
-				klog.V(4).Infof("Computed \"%s\" RAM Cost := %v", name, newCnode.RAMCost)
-			}
+			klog.V(4).Infof("Computed \"%s\" RAM Cost := %v", name, newCnode.RAMCost)
 		}
 
 		nodes[name] = &newCnode
 	}
+
 	return nodes, nil
 }
 
@@ -1450,11 +1431,14 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
 				}
 				costs.CPUAllocation = getContainerAllocation(costs.CPUReq, costs.CPUUsed)
 				costs.RAMAllocation = getContainerAllocation(costs.RAMReq, costs.RAMUsed)
+
 				if filterNamespace == "" {
 					containerNameCost[newKey] = costs
 				} else if costs.Namespace == filterNamespace {
 					containerNameCost[newKey] = costs
 				}
+
+				// TODO nikovacevic-caching filter cluster ID
 			}
 
 		} else {
@@ -1517,6 +1501,7 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
 			}
 			costs.CPUAllocation = getContainerAllocation(costs.CPUReq, costs.CPUUsed)
 			costs.RAMAllocation = getContainerAllocation(costs.RAMReq, costs.RAMUsed)
+
 			if filterNamespace == "" {
 				containerNameCost[key] = costs
 				missingContainers[key] = costs
@@ -1524,6 +1509,8 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
 				containerNameCost[key] = costs
 				missingContainers[key] = costs
 			}
+
+			// TODO nikovacevic-caching filter cluster ID
 		}
 	}