mirror of
https://github.com/agent-substrate/substrate.git
synced 2026-11-12 10:35:06 +08:00
This is the companion to #496 In order to grant access to `/dev/kvm` we have to either: - use a device plugin - use a DRA driver - use an NRI plugin An NRI plugin is highly privileged in it's own right for all pods on the host and is difficult to ship portably at the moment. DRA is promising, but not enough functionality is GA yet at our current 1.35+ target. Device plugin fits reasonably well. We do wind up publishing an ~arbitrarily high limit, which has some cost in kubelet memory, but otherwise is relatively clean. This approach is what kata uses currently. Their device plugin is not available unbundled, and we anyhow have a per-node daemonset. atlet is taught to sniff if /dev/kvm appears on the host at all, so we can also stop using the manually labeled nodes for microVM class and instead schedule to the KVM + TUN devices on nodes that advertise them. Later we can migrate to device plugin by using I implemented that already, but I don't think it's worth merging at the moment. We would want consumable capacity to be on by default. We can migrate later without changing the pod spec by using `extendedResourceName`. https://github.com/agent-substrate/substrate/compare/main...BenTheElder:substrate:ateom-microvm-dra NOTE: I confirmed with upstream that device plugin is not going anywhere despite being "v1beta1", it's GA in all but name. It won't receive new features but we don't really need anyhow. We'll move to DRA down the line. --- By doing this, we can drop `privileged: true` from the uVM ateom pods. We can also drop the `ate.dev/sandboxClass` node label hacks, reducing friction to deploy.
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
// Copyright 2013 The Prometheus Authors
|
|
// 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 model
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
)
|
|
|
|
// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
|
|
// non-existing sample pair. It is a SamplePair with timestamp Earliest and
|
|
// value 0.0. Note that the natural zero value of SamplePair has a timestamp
|
|
// of 0, which is possible to appear in a real SamplePair and thus not
|
|
// suitable to signal a non-existing SamplePair.
|
|
var ZeroSamplePair = SamplePair{Timestamp: Earliest}
|
|
|
|
// A SampleValue is a representation of a value for a given sample at a given
|
|
// time.
|
|
type SampleValue float64
|
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
func (v SampleValue) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(v.String())
|
|
}
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
|
func (v *SampleValue) UnmarshalJSON(b []byte) error {
|
|
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
|
|
return errors.New("sample value must be a quoted string")
|
|
}
|
|
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*v = SampleValue(f)
|
|
return nil
|
|
}
|
|
|
|
// Equal returns true if the value of v and o is equal or if both are NaN. Note
|
|
// that v==o is false if both are NaN. If you want the conventional float
|
|
// behavior, use == to compare two SampleValues.
|
|
func (v SampleValue) Equal(o SampleValue) bool {
|
|
if v == o {
|
|
return true
|
|
}
|
|
return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
|
|
}
|
|
|
|
func (v SampleValue) String() string {
|
|
return strconv.FormatFloat(float64(v), 'f', -1, 64)
|
|
}
|
|
|
|
// SamplePair pairs a SampleValue with a Timestamp.
|
|
type SamplePair struct {
|
|
Timestamp Time
|
|
Value SampleValue
|
|
}
|
|
|
|
func (s SamplePair) MarshalJSON() ([]byte, error) {
|
|
t, err := json.Marshal(s.Timestamp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v, err := json.Marshal(s.Value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return fmt.Appendf(nil, "[%s,%s]", t, v), nil
|
|
}
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler.
|
|
func (s *SamplePair) UnmarshalJSON(b []byte) error {
|
|
v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
|
|
return json.Unmarshal(b, &v)
|
|
}
|
|
|
|
// Equal returns true if this SamplePair and o have equal Values and equal
|
|
// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
|
|
func (s *SamplePair) Equal(o *SamplePair) bool {
|
|
return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
|
|
}
|
|
|
|
func (s SamplePair) String() string {
|
|
return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
|
|
}
|