X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/9cdec66d5b0238e9d99c1e8e1d5c8571d798689d..86660414472d4ff0d8267f9845a753497bd41692:/lib/config/load.go diff --git a/lib/config/load.go b/lib/config/load.go index 8f8ab2bf27..fbd01488a0 100644 --- a/lib/config/load.go +++ b/lib/config/load.go @@ -16,6 +16,7 @@ import ( "io/ioutil" "os" "regexp" + "runtime" "strconv" "strings" "time" @@ -25,6 +26,7 @@ import ( "github.com/imdario/mergo" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) //go:embed config.default.yml @@ -297,7 +299,10 @@ func (ldr *Loader) Load() (*arvados.Config, error) { ldr.loadOldKeepBalanceConfig, ) } - loadFuncs = append(loadFuncs, ldr.setImplicitStorageClasses) + loadFuncs = append(loadFuncs, + ldr.setImplicitStorageClasses, + ldr.setLoopbackInstanceType, + ) for _, f := range loadFuncs { err = f(&cfg) if err != nil { @@ -340,6 +345,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 @@ -361,7 +367,7 @@ func (ldr *Loader) checkClusterID(label, clusterID string, emptyStringOk bool) e if emptyStringOk && clusterID == "" { return nil } else if !acceptableClusterIDRe.MatchString(clusterID) { - return fmt.Errorf("%s: cluster ID should be 5 alphanumeric characters", label) + return fmt.Errorf("%s: cluster ID should be 5 lowercase alphanumeric characters", label) } return nil } @@ -414,6 +420,67 @@ func (ldr *Loader) checkEnum(label, value string, accepted ...string) error { return fmt.Errorf("%s: unacceptable value %q: must be one of %q", label, value, accepted) } +func (ldr *Loader) setLoopbackInstanceType(cfg *arvados.Config) error { + for id, cc := range cfg.Clusters { + if !cc.Containers.CloudVMs.Enable || cc.Containers.CloudVMs.Driver != "loopback" { + continue + } + if len(cc.InstanceTypes) == 1 { + continue + } + if len(cc.InstanceTypes) > 1 { + return fmt.Errorf("Clusters.%s.InstanceTypes: cannot use multiple InstanceTypes with loopback driver", id) + } + // No InstanceTypes configured. Fill in implicit + // default. + hostram, err := getHostRAM() + if err != nil { + return err + } + scratch, err := getFilesystemSize(os.TempDir()) + if err != nil { + return err + } + cc.InstanceTypes = arvados.InstanceTypeMap{"localhost": { + Name: "localhost", + ProviderType: "localhost", + VCPUs: runtime.NumCPU(), + RAM: hostram, + Scratch: scratch, + IncludedScratch: scratch, + }} + cfg.Clusters[id] = cc + } + return nil +} + +func getFilesystemSize(path string) (arvados.ByteSize, error) { + var stat unix.Statfs_t + err := unix.Statfs(path, &stat) + if err != nil { + return 0, err + } + return arvados.ByteSize(stat.Blocks * uint64(stat.Bsize)), nil +} + +var reMemTotal = regexp.MustCompile(`(^|\n)MemTotal: *(\d+) kB\n`) + +func getHostRAM() (arvados.ByteSize, error) { + buf, err := os.ReadFile("/proc/meminfo") + if err != nil { + return 0, err + } + m := reMemTotal.FindSubmatch(buf) + if m == nil { + return 0, errors.New("error parsing /proc/meminfo: no MemTotal") + } + kb, err := strconv.ParseInt(string(m[2]), 10, 64) + if err != nil { + return 0, fmt.Errorf("error parsing /proc/meminfo: %q: %w", m[2], err) + } + return arvados.ByteSize(kb) * 1024, nil +} + func (ldr *Loader) setImplicitStorageClasses(cfg *arvados.Config) error { cluster: for id, cc := range cfg.Clusters { @@ -437,6 +504,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 {