pkg/scheduler/plugins/resourcequota/resourcequota.go (72 lines of code) (raw):
package resourcequota
import (
"fmt"
v1 "k8s.io/api/core/v1"
quotav1 "k8s.io/apiserver/pkg/quota/v1"
"k8s.io/klog"
"volcano.sh/apis/pkg/apis/scheduling"
"volcano.sh/volcano/pkg/scheduler/api"
"volcano.sh/volcano/pkg/scheduler/framework"
"volcano.sh/volcano/pkg/scheduler/plugins/util"
)
// PluginName indicates name of volcano scheduler plugin.
const PluginName = "resourcequota"
// resourceQuota scope not supported
type resourceQuotaPlugin struct {
// Arguments given for the plugin
pluginArguments framework.Arguments
}
// New return resourcequota plugin
func New(arguments framework.Arguments) framework.Plugin {
return &resourceQuotaPlugin{
pluginArguments: arguments,
}
}
func (rq *resourceQuotaPlugin) Name() string {
return PluginName
}
func (rq *resourceQuotaPlugin) OnSessionOpen(ssn *framework.Session) {
ssn.AddJobEnqueueableFn(rq.Name(), func(obj interface{}) int {
job := obj.(*api.JobInfo)
resourcesRequests := job.PodGroup.Spec.MinResources
if resourcesRequests == nil {
return util.Permit
}
quotas := ssn.NamespaceInfo[api.NamespaceName(job.Namespace)].QuotaStatus
for _, resourceQuota := range quotas {
hardResources := quotav1.ResourceNames(resourceQuota.Hard)
used := v1.ResourceList{}
for _, j := range ssn.Jobs {
rr := j.PodGroup.Spec.MinResources
if j.Namespace != job.Namespace || rr == nil {
continue
}
switch j.PodGroup.Status.Phase {
case scheduling.PodGroupRunning, scheduling.PodGroupInqueue:
ru := quotav1.Mask(*rr, hardResources)
used = quotav1.Add(used, ru)
}
}
requestedUsage := quotav1.Mask(*resourcesRequests, hardResources)
newUsage := quotav1.Add(used, requestedUsage)
maskedNewUsage := quotav1.Mask(newUsage, quotav1.ResourceNames(requestedUsage))
if allowed, exceeded := quotav1.LessThanOrEqual(maskedNewUsage, resourceQuota.Hard); !allowed {
failedRequestedUsage := quotav1.Mask(requestedUsage, exceeded)
failedUsed := quotav1.Mask(resourceQuota.Used, exceeded)
failedHard := quotav1.Mask(resourceQuota.Hard, exceeded)
msg := fmt.Sprintf("resource quota insufficient, requested: %v, used: %v, limited: %v",
failedRequestedUsage,
failedUsed,
failedHard,
)
klog.V(4).Infof("enqueueable false for job: %s/%s, because :%s", job.Namespace, job.Name, msg)
ssn.RecordPodGroupEvent(
job.PodGroup,
v1.EventTypeWarning,
string(scheduling.PodGroupUnschedulableType),
msg,
)
return util.Reject
}
}
return util.Permit
})
}
func (rq *resourceQuotaPlugin) OnSessionClose(session *framework.Session) {
}