diff --git a/pkg/cluster/operation/check.go b/pkg/cluster/operation/check.go index bbefbb7b84..b5d24a22dc 100644 --- a/pkg/cluster/operation/check.go +++ b/pkg/cluster/operation/check.go @@ -497,6 +497,13 @@ func CheckPartitions(opt *CheckOptions, host string, topo *spec.Specification, r flt := flatPartitions(insightInfo.Partitions) parts := sortPartitions(flt) + // check if multiple instances are using the same partition as data storeage + type storePartitionInfo struct { + comp string + path string + } + uniqueStores := make(map[string][]storePartitionInfo) // host+partition -> info + topo.IterInstance(func(inst spec.Instance) { if inst.GetHost() != host { return @@ -511,6 +518,17 @@ func CheckPartitions(opt *CheckOptions, host string, topo *spec.Specification, r return } + // only check for TiKV and TiFlash, other components are not that I/O sensitive + switch inst.ComponentName() { + case spec.ComponentTiKV, + spec.ComponentTiFlash: + usKey := fmt.Sprintf("%s:%s", host, blk.Mount.MountPoint) + uniqueStores[usKey] = append(uniqueStores[usKey], storePartitionInfo{ + comp: inst.ComponentName(), + path: dataDir, + }) + } + switch blk.Mount.FSType { case "ext4": if !strings.Contains(blk.Mount.Options, "nodelalloc") { @@ -538,6 +556,25 @@ func CheckPartitions(opt *CheckOptions, host string, topo *spec.Specification, r } }) + for key, parts := range uniqueStores { + if len(parts) > 1 { + pathList := make([]string, 0) + for _, p := range parts { + pathList = append(pathList, + fmt.Sprintf("%s:%s", p.comp, p.path), + ) + } + results = append(results, &CheckResult{ + Name: CheckNameDisks, + Err: fmt.Errorf( + "multiple components %s are using the same partition %s as data dir", + strings.Join(pathList, ","), + key, + ), + }) + } + } + return results } @@ -681,3 +718,51 @@ func CheckTHP(ctx context.Context, e ctxt.Executor) *CheckResult { result.Msg = "THP is disabled" return result } + +// CheckJRE checks if java command is available for TiSpark nodes +func CheckJRE(ctx context.Context, e ctxt.Executor, host string, topo *spec.Specification) []*CheckResult { + var results []*CheckResult + + topo.IterInstance(func(inst spec.Instance) { + if inst.ComponentName() != spec.ComponentTiSpark { + return + } + + // check if java cli is available + stdout, stderr, err := e.Execute(ctx, "java -version", false) + if err != nil { + results = append(results, &CheckResult{ + Name: CheckNameCommand, + Err: fmt.Errorf("java not usable, %s", strings.Trim(string(stderr), "\n")), + Msg: "JRE is not installed properly or not set in PATH", + }) + return + } + if len(stderr) > 0 { + line := strings.Split(string(stderr), "\n")[0] + fields := strings.Split(line, " ") + ver := strings.Trim(fields[len(fields)-1], "\"") + if !strings.HasPrefix(ver, "1.8.") { + results = append(results, &CheckResult{ + Name: CheckNameCommand, + Err: fmt.Errorf("java version %s is not supported, use Java 8 (1.8)", ver), + Msg: "Installed JRE is not Java 8", + }) + } else { + results = append(results, &CheckResult{ + Name: CheckNameCommand, + Msg: "java: " + strings.Split(string(stderr), "\n")[0], + }) + } + } else { + results = append(results, &CheckResult{ + Name: CheckNameCommand, + Err: fmt.Errorf("unknown output of java %s", stdout), + Msg: "java: " + strings.Split(string(stdout), "\n")[0], + Warn: true, + }) + } + }) + + return results +} diff --git a/pkg/cluster/task/check.go b/pkg/cluster/task/check.go index d368718e5b..43f0fcecbd 100644 --- a/pkg/cluster/task/check.go +++ b/pkg/cluster/task/check.go @@ -121,6 +121,10 @@ func (c *CheckSys) Execute(ctx context.Context) error { Msg: "numactl: " + strings.Split(string(stdout), "\n")[0], }) } + + // check if JRE is available for TiSpark + results = append(results, operator.CheckJRE(ctx, e, c.host, c.topo)...) + storeResults(ctx, c.host, results) case CheckTypePartitions: // check partition mount options for data_dir