Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apis/nodecore/v1alpha1/k8slice_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package v1alpha1

import "k8s.io/apimachinery/pkg/api/resource"
import (
"k8s.io/apimachinery/pkg/api/resource"
)

// K8SliceConfiguration is the partition of the flavor K8Slice.
type K8SliceConfiguration struct {
Expand Down
33 changes: 32 additions & 1 deletion apis/nodecore/v1alpha1/k8slice_flavor.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type K8SliceCharacteristics struct {
Memory resource.Quantity `json:"memory"`
// Pods is the maximum number of pods schedulable on this K8Slice Flavor.
Pods resource.Quantity `json:"pods"`
// GPU is the number of GPU cores of the K8Slice Flavor.
// GPU contains the GPU traits of the K8Slice Flavor.
Gpu *GPU `json:"gpu,omitempty"`
// Storage is the amount of storage offered by this K8Slice Flavor.
Storage *resource.Quantity `json:"storage,omitempty"`
Expand All @@ -60,6 +60,37 @@ type GPU struct {
Cores resource.Quantity `json:"cores"`
// Memory of the GPU
Memory resource.Quantity `json:"memory"`
//
// FLARE properties
//
Vendor string `json:"vendor"`
Tier string `json:"tier,omitempty"`
Count int64 `json:"count,omitempty"`
MultiInstance bool `json:"multi_instance,omitempty"`
Shared bool `json:"shared,omitempty"`
SharingStrategy string `json:"sharing_strategy,omitempty"`
Dedicated bool `json:"dedicated,omitempty"`
Interruptible bool `json:"interruptible,omitempty"`
NetworkBandwidth resource.Quantity `json:"network_bandwidth,omitempty"`
NetworkLatencyMs int64 `json:"network_latency_ms,omitempty"`
NetworkTier string `json:"network_tier,omitempty"`
TrainingScore float64 `json:"training_score,omitempty"`
InferenceScore float64 `json:"inference_score,omitempty"`
HPCScore float64 `json:"hpc_score,omitempty"`
GraphicsScore float64 `json:"graphics_score,omitempty"`
Architecture string `json:"architecture,omitempty"`
Interconnect string `json:"interconnect,omitempty"`
InterconnectBandwidth resource.Quantity `json:"interconnect_bandwidth,omitempty"`
ComputeCapability string `json:"compute_capability,omitempty"`
ClockSpeed resource.Quantity `json:"clock_speed,omitempty"`
FP32TFlops float64 `json:"fp32_tflops,omitempty"`
Topology string `json:"topology,omitempty"`
MultiGPUEfficiency string `json:"multi_gpu_efficiency,omitempty"`
Region string `json:"region,omitempty"`
Zone string `json:"zone,omitempty"`
HourlyRate float64 `json:"hourly_rate,omitempty"`
Provider string `json:"provider,omitempty"`
PreEmptible bool `json:"pre_emptible,omitempty"`
}

// Policies represents the policies of a K8Slice Flavor, such as the partitionability of the K8Slice Flavor.
Expand Down
7 changes: 6 additions & 1 deletion apis/nodecore/v1alpha1/k8slice_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package v1alpha1

import "k8s.io/klog/v2"
import (
"k8s.io/klog/v2"
)

// K8SliceSelector is the selector for a K8Slice.
type K8SliceSelector struct {
Expand All @@ -32,6 +34,9 @@ type K8SliceSelector struct {

// StorageFilter is the Storage filter of the K8SliceSelector.
StorageFilter *ResourceQuantityFilter `json:"storageFilter,omitempty"`

//GPUFilters is the advanced GPU filter of the K8SliceSelector
GPUFilters []GPUFieldSelector `json:"gpuFilters,omitempty"`
}

// GetFlavorTypeSelector returns the type of the Flavor.
Expand Down
46 changes: 46 additions & 0 deletions apis/nodecore/v1alpha1/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ const (
// FilterType is the type of filter that can be applied to a resource quantity.
type FilterType string

// BooleanFilter is a filter that can be applied to a boolean value.
type BooleanFilter struct {
Data runtime.RawExtension `json:"data"`
}

type NumberFilter struct {
// Name indicates the type of the filter
Name FilterType `json:"name"`
// Filter data
Data runtime.RawExtension `json:"data"`
}

type NumberMatchSelector struct {
// Value is the value to match
Value float64 `json:"value"`
}

type NumberRangeSelector struct {
// Min is the minimum value of the range
Min *float64 `json:"min,omitempty"`
// Max is the maximum value of the range
Max *float64 `json:"max,omitempty"`
}

// StringFilter is a filter that can be applied to a string.
type StringFilter struct {
// Name indicates the type of the filter
Expand Down Expand Up @@ -76,6 +100,28 @@ type ResourceRangeSelector struct {
Max *resource.Quantity `json:"max,omitempty"`
}

type SelectorName string

var (
ResourceRangeSelectorName = SelectorName("ResourceRangeSelector")
ResourceMatchSelectorName = SelectorName("ResourceMatchSelector")
StringRangeSelectorName = SelectorName("StringRangeSelector")
StringFilterSelectorName = SelectorName("StringFilter")
BooleanFilterSelectorName = SelectorName("BooleanFilter")
NumberRangeSelectorName = SelectorName("NumberRangeFilter")
NumberMatchSelectorName = SelectorName("NumberMatchFilter")
)

type GPUFieldSelector struct {
// Field is the GPU field the filter should evaluate.
Field string `json:"field"`
// Selector is the name of the concrete Selector to enforce for the given data.
//+kubebuilder:validation:Enum=ResourceRangeSelector;ResourceMatchSelector;StringRangeSelector;StringFilter;BooleanFilter;NumberRangeFilter;NumberFilter
Selector SelectorName `json:"filter"`
// Data contains the raw data for the given filter.
Data runtime.RawExtension `json:"data"`
}

// ParseResourceQuantityFilter parses a ResourceQuantityFilter into a FilterType and the corresponding filter data.
// It also provides a set of validation rules for the filter data.
// Particularly for the ResourceRangeSelector, it checks that at least one of min or max is set and that min is less than max if both are set.
Expand Down
98 changes: 98 additions & 0 deletions apis/nodecore/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 18 additions & 13 deletions cmd/local-resource-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ import (
"k8s.io/klog/v2"
metricsv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"

nodecorev1alpha1 "github.com/fluidos-project/node/apis/nodecore/v1alpha1"
"github.com/fluidos-project/node/pkg/indexer"
localresourcemanager "github.com/fluidos-project/node/pkg/local-resource-manager"
"github.com/fluidos-project/node/pkg/utils/flags"
)
Expand Down Expand Up @@ -82,13 +82,6 @@ func main() {

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

cfg := ctrl.GetConfigOrDie()
cl, err := client.New(cfg, client.Options{Scheme: scheme})
if err != nil {
setupLog.Error(err, "Unable to create client")
os.Exit(1)
}

var webhookServer webhook.Server

if *enableWH {
Expand All @@ -115,20 +108,23 @@ func main() {
// Print something about the mgr
setupLog.Info("Manager started", "manager", mgr)

flavorIndexer := indexer.FlavorByNodeName{}

// Register the controller
if err = (&localresourcemanager.NodeReconciler{
Client: cl,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
EnableAutoDiscovery: *enableAutoDiscovery,
WebhookServer: webhookServer,
FlavorIndexer: flavorIndexer,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Node")
os.Exit(1)
}

// Register the controller
if err = (&localresourcemanager.ServiceBlueprintReconciler{
Client: cl,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
EnableAutoDiscovery: *enableAutoDiscovery,
WebhookServer: webhookServer,
Expand Down Expand Up @@ -161,13 +157,22 @@ func main() {
setupLog.Error(err, "unable to set up ready check")
os.Exit(1)
}
if err := mgr.AddHealthzCheck("webhook", webhookServer.StartedChecker()); err != nil {
setupLog.Error(err, "unable to set up webhook health check")
if *enableWH {
if err := mgr.AddHealthzCheck("webhook", webhookServer.StartedChecker()); err != nil {
setupLog.Error(err, "unable to set up webhook health check")
os.Exit(1)
}
}

ctx := ctrl.SetupSignalHandler()

if err := mgr.GetFieldIndexer().IndexField(ctx, flavorIndexer.Object(), flavorIndexer.Field(), flavorIndexer.IndexerFunc()); err != nil {
setupLog.Error(err, "problem setting up flavorIndexer")
os.Exit(1)
}

setupLog.Info("Starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
if err := mgr.Start(ctx); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
Expand Down
Loading