X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/00f65f60e69326839447f431146312481db05f01..dcf8de623d744458d7e39a1efe3814349de76649:/lib/config/load.go diff --git a/lib/config/load.go b/lib/config/load.go index 6099215edc..dba7997870 100644 --- a/lib/config/load.go +++ b/lib/config/load.go @@ -6,6 +6,7 @@ package config import ( "bytes" + "crypto/sha256" _ "embed" "encoding/json" "errors" @@ -17,10 +18,12 @@ import ( "regexp" "strconv" "strings" + "time" "git.arvados.org/arvados.git/sdk/go/arvados" "github.com/ghodss/yaml" "github.com/imdario/mergo" + "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" ) @@ -46,6 +49,12 @@ type Loader struct { KeepBalancePath string configdata []byte + // UTC time for configdata: either the modtime of the file we + // read configdata from, or the time when we read configdata + // from a pipe. + sourceTimestamp time.Time + // UTC time when configdata was read. + loadTimestamp time.Time } // NewLoader returns a new Loader with Stdin and Logger set to the @@ -166,25 +175,36 @@ func (ldr *Loader) MungeLegacyConfigArgs(lgr logrus.FieldLogger, args []string, return munged } -func (ldr *Loader) loadBytes(path string) ([]byte, error) { +func (ldr *Loader) loadBytes(path string) (buf []byte, sourceTime, loadTime time.Time, err error) { + loadTime = time.Now().UTC() if path == "-" { - return ioutil.ReadAll(ldr.Stdin) + buf, err = ioutil.ReadAll(ldr.Stdin) + sourceTime = loadTime + return } f, err := os.Open(path) if err != nil { - return nil, err + return } defer f.Close() - return ioutil.ReadAll(f) + fi, err := f.Stat() + if err != nil { + return + } + sourceTime = fi.ModTime().UTC() + buf, err = ioutil.ReadAll(f) + return } func (ldr *Loader) Load() (*arvados.Config, error) { if ldr.configdata == nil { - buf, err := ldr.loadBytes(ldr.Path) + buf, sourceTime, loadTime, err := ldr.loadBytes(ldr.Path) if err != nil { return nil, err } ldr.configdata = buf + ldr.sourceTimestamp = sourceTime + ldr.loadTimestamp = loadTime } // FIXME: We should reject YAML if the same key is used twice @@ -320,6 +340,7 @@ func (ldr *Loader) Load() (*arvados.Config, error) { ldr.checkEnum("Containers.LocalKeepLogsToContainerLog", cc.Containers.LocalKeepLogsToContainerLog, "none", "all", "errors"), ldr.checkEmptyKeepstores(cc), ldr.checkUnlistedKeepstores(cc), + ldr.checkLocalKeepBlobBuffers(cc), ldr.checkStorageClasses(cc), ldr.checkCUDAVersions(cc), // TODO: check non-empty Rendezvous on @@ -330,6 +351,8 @@ func (ldr *Loader) Load() (*arvados.Config, error) { } } } + cfg.SourceTimestamp = ldr.sourceTimestamp + cfg.SourceSHA256 = fmt.Sprintf("%x", sha256.Sum256(ldr.configdata)) return &cfg, nil } @@ -415,6 +438,24 @@ cluster: return nil } +func (ldr *Loader) checkLocalKeepBlobBuffers(cc arvados.Cluster) error { + kbb := cc.Containers.LocalKeepBlobBuffersPerVCPU + if kbb == 0 { + return nil + } + for uuid, vol := range cc.Volumes { + if len(vol.AccessViaHosts) > 0 { + ldr.Logger.Warnf("LocalKeepBlobBuffersPerVCPU is %d but will not be used because at least one volume (%s) uses AccessViaHosts -- suggest changing to 0", kbb, uuid) + return nil + } + if !vol.ReadOnly && vol.Replication < cc.Collections.DefaultReplication { + ldr.Logger.Warnf("LocalKeepBlobBuffersPerVCPU is %d but will not be used because at least one volume (%s) has lower replication than DefaultReplication (%d < %d) -- suggest changing to 0", kbb, uuid, vol.Replication, cc.Collections.DefaultReplication) + return nil + } + } + return nil +} + func (ldr *Loader) checkStorageClasses(cc arvados.Cluster) error { classOnVolume := map[string]bool{} for volid, vol := range cc.Volumes { @@ -555,3 +596,30 @@ func (ldr *Loader) autofillPreemptible(label string, cc *arvados.Cluster) { } } + +// RegisterMetrics registers metrics showing the timestamp and content +// hash of the currently loaded config. +// +// Must not be called more than once for a given registry. Must not be +// called before Load(). Metrics are not updated by subsequent calls +// to Load(). +func (ldr *Loader) RegisterMetrics(reg *prometheus.Registry) { + hash := fmt.Sprintf("%x", sha256.Sum256(ldr.configdata)) + vec := prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "arvados", + Subsystem: "config", + Name: "source_timestamp_seconds", + Help: "Timestamp of config file when it was loaded.", + }, []string{"sha256"}) + vec.WithLabelValues(hash).Set(float64(ldr.sourceTimestamp.UnixNano()) / 1e9) + reg.MustRegister(vec) + + vec = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "arvados", + Subsystem: "config", + Name: "load_timestamp_seconds", + Help: "Time when config file was loaded.", + }, []string{"sha256"}) + vec.WithLabelValues(hash).Set(float64(ldr.loadTimestamp.UnixNano()) / 1e9) + reg.MustRegister(vec) +}