From 662515729c413eaa01793560541d22d6adac06f4 Mon Sep 17 00:00:00 2001 From: srstack Date: Tue, 7 Dec 2021 17:44:29 +0800 Subject: [PATCH 01/13] add check port func --- pkg/cluster/spec/util.go | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/pkg/cluster/spec/util.go b/pkg/cluster/spec/util.go index 0e1a523ccb..fecb81d8e9 100644 --- a/pkg/cluster/spec/util.go +++ b/pkg/cluster/spec/util.go @@ -17,7 +17,9 @@ import ( "bytes" "context" "crypto/tls" + "encoding/binary" "fmt" + "net" "path/filepath" "reflect" "strings" @@ -210,3 +212,109 @@ func PackagePath(comp string, version string, os string, arch string) string { fileName := fmt.Sprintf("%s-%s-%s-%s.tar.gz", comp, version, os, arch) return ProfilePath(TiUPPackageCacheDir, fileName) } + +// IsValidIP Determine whether the IP is legal +func IsValidIP(str string) (bool, net.IP) { + address := net.ParseIP(str) // Parse the IP if it is legal, it will return the legal IP format + if address == nil { + return false, nil + } + return true, address +} + +// IsPortOpen 判断端口是否开 +func IsPortOpen(ip string, port int) bool { + isValid, _ := IsValidIP(ip) + + if isValid { + if ping, _ := IsPing(ip); !ping { + return ping + } + + netIP := net.ParseIP(ip) + tcpAddr := net.TCPAddr{ + IP: netIP, + Port: port, + } + // initiate a TCP conn to test whether the corresponding port exists + conn, err := net.DialTCP("tcp", nil, &tcpAddr) + if err != nil { + return false + } + // 否则则存在该端口,关闭连接句柄 + _ = conn.Close() + return true + } + return false +} + +// ICMP icmp package info +type ICMP struct { + Type uint8 + Code uint8 + Checksum uint16 + Identifier uint16 + SequenceNum uint16 +} + +// IsPing Check IP connectivity +func IsPing(ip string) (bool, error) { + var icmp ICMP + //开始填充数据包 + icmp.Type = 8 //8->echo message 0->reply message + icmp.Code = 0 + icmp.Checksum = 0 + icmp.Identifier = 0 + icmp.SequenceNum = 0 + + recvBuf := make([]byte, 32) + var buffer bytes.Buffer + + // First write the icmp datagram in the buffer for checksum + binary.Write(&buffer, binary.BigEndian, icmp) + icmp.Checksum = checkSum(buffer.Bytes()) + buffer.Reset() + binary.Write(&buffer, binary.BigEndian, icmp) + + conn, err := net.DialTimeout("ip4:icmp", ip, time.Second*2) + if err != nil { + return false, err + } + _, err = conn.Write(buffer.Bytes()) + if err != nil { + return false, err + } + conn.SetReadDeadline(time.Now().Add(time.Second * 2)) + num, err := conn.Read(recvBuf) + if err != nil { + return false, err + } + + conn.SetReadDeadline(time.Time{}) + + if string(recvBuf[0:num]) != "" { + return true, nil + } + return false, fmt.Errorf("ping %v failed", ip) + +} + +// checkSum +func checkSum(data []byte) uint16 { + var ( + sum uint32 + length int = len(data) + index int + ) + for length > 1 { + sum += uint32(data[index])<<8 + uint32(data[index+1]) + index += 2 + length -= 2 + } + if length > 0 { + sum += uint32(data[index]) + } + sum += (sum >> 16) + + return uint16(^sum) +} From eb6e81535cca0568312fa6212671cc225a212fc2 Mon Sep 17 00:00:00 2001 From: srstack Date: Tue, 7 Dec 2021 18:03:39 +0800 Subject: [PATCH 02/13] add exist task --- pkg/cluster/task/exist.go | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 pkg/cluster/task/exist.go diff --git a/pkg/cluster/task/exist.go b/pkg/cluster/task/exist.go new file mode 100644 index 0000000000..45fdc45969 --- /dev/null +++ b/pkg/cluster/task/exist.go @@ -0,0 +1,67 @@ +// Copyright 2020 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package task + +import ( + "context" + "fmt" + + "github.com/pingcap/errors" + "github.com/pingcap/tiup/pkg/cluster/ctxt" +) + +// Rmdir is used to delete directory on the target host +type Exist struct { + host string + path string + isFile bool + isDirectory bool +} + +// Execute implements the Task interface +func (e *Exist) Execute(ctx context.Context) error { + exec, found := ctxt.GetInner(ctx).GetExecutor(e.host) + if !found { + return ErrNoExecutor + } + + cmd := fmt.Sprintf(`[ -e %s ] && echo 1`, e.path) + + switch { + case e.isFile: + cmd = fmt.Sprintf(`[ -f %s ] && echo 1`, e.path) + case e.isDirectory: + cmd = fmt.Sprintf(`[ -d %s ] && echo 1`, e.path) + } + + req, _, err := exec.Execute(ctx, cmd, false) + if err != nil { + return errors.Trace(err) + } + if string(req) != "1" { + return fmt.Errorf("`%s` does not exist on the target host `%s`", e.path, e.host) + } + + return nil +} + +// Rollback implements the Task interface +func (e *Exist) Rollback(ctx context.Context) error { + return nil +} + +// String implements the fmt.Stringer interface +func (e *Exist) String() string { + return fmt.Sprintf("Exist: host=%s, path='%s'", e.host, e.path) +} From d073d677a53482eb394c29b59f33ebc08d262b5b Mon Sep 17 00:00:00 2001 From: srstack Date: Tue, 7 Dec 2021 18:07:39 +0800 Subject: [PATCH 03/13] add notexist task --- pkg/cluster/task/exist.go | 2 +- pkg/cluster/task/notexist.go | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 pkg/cluster/task/notexist.go diff --git a/pkg/cluster/task/exist.go b/pkg/cluster/task/exist.go index 45fdc45969..3d76571906 100644 --- a/pkg/cluster/task/exist.go +++ b/pkg/cluster/task/exist.go @@ -21,7 +21,7 @@ import ( "github.com/pingcap/tiup/pkg/cluster/ctxt" ) -// Rmdir is used to delete directory on the target host +// Exist is used to determine path if it exists on the target host type Exist struct { host string path string diff --git a/pkg/cluster/task/notexist.go b/pkg/cluster/task/notexist.go new file mode 100644 index 0000000000..037bd7a0e7 --- /dev/null +++ b/pkg/cluster/task/notexist.go @@ -0,0 +1,67 @@ +// Copyright 2020 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package task + +import ( + "context" + "fmt" + + "github.com/pingcap/errors" + "github.com/pingcap/tiup/pkg/cluster/ctxt" +) + +// NotExist is used to determine path if it exists on the target host +type NotExist struct { + host string + path string + isFile bool + isDirectory bool +} + +// Execute implements the Task interface +func (e *NotExist) Execute(ctx context.Context) error { + exec, found := ctxt.GetInner(ctx).GetExecutor(e.host) + if !found { + return ErrNoExecutor + } + + cmd := fmt.Sprintf(`[ ! -e %s ] && echo 1`, e.path) + + switch { + case e.isFile: + cmd = fmt.Sprintf(`[ ! -f %s ] && echo 1`, e.path) + case e.isDirectory: + cmd = fmt.Sprintf(`[ ! -d %s ] && echo 1`, e.path) + } + + req, _, err := exec.Execute(ctx, cmd, false) + if err != nil { + return errors.Trace(err) + } + if string(req) != "1" { + return fmt.Errorf("`%s` is exist on the target host `%s`", e.path, e.host) + } + + return nil +} + +// Rollback implements the Task interface +func (e *NotExist) Rollback(ctx context.Context) error { + return nil +} + +// String implements the fmt.Stringer interface +func (e *NotExist) String() string { + return fmt.Sprintf("NotExist: host=%s, path='%s'", e.host, e.path) +} From 6601480cafe69049295152cda92c751d09863397 Mon Sep 17 00:00:00 2001 From: srstack Date: Wed, 8 Dec 2021 19:39:13 +0800 Subject: [PATCH 04/13] add scale-out check --- components/cluster/command/check.go | 20 ++++-- pkg/cluster/manager/check.go | 86 ++++++++++++++++++---- pkg/cluster/operation/check.go | 27 +++++++ pkg/cluster/spec/util.go | 108 ---------------------------- pkg/cluster/task/check.go | 8 +++ pkg/cluster/task/exist.go | 67 ----------------- pkg/cluster/task/notexist.go | 67 ----------------- 7 files changed, 124 insertions(+), 259 deletions(-) delete mode 100644 pkg/cluster/task/exist.go delete mode 100644 pkg/cluster/task/notexist.go diff --git a/components/cluster/command/check.go b/components/cluster/command/check.go index 37b1b4dde9..63a9615bba 100644 --- a/components/cluster/command/check.go +++ b/components/cluster/command/check.go @@ -28,22 +28,34 @@ func newCheckCmd() *cobra.Command { IdentityFile: path.Join(utils.UserHome(), ".ssh", "id_rsa"), } cmd := &cobra.Command{ - Use: "check ", + Use: "check [scale-out.yml]", Short: "Perform preflight checks for the cluster.", Long: `Perform preflight checks for the cluster. By default, it checks deploy servers before a cluster is deployed, the input is the topology.yaml for the cluster. If '--cluster' is set, it will perform checks for an existing cluster, the input is the cluster name. Some checks are ignore in this mode, such as port and dir -conflict checks with other clusters`, +conflict checks with other clusters +If you want to check the scale-out topology, please use execute the following command +' check --cluster ' +it will the new instances `, RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 { + if len(args) != 1 && len(args) != 2 { return cmd.Help() } + scaleOutTopo := "" if opt.ExistCluster { clusterReport.ID = scrubClusterName(args[0]) } - return cm.CheckCluster(args[0], opt, gOpt) + + if len(args) == 2 { + if !opt.ExistCluster { + return cmd.Help() + } + scaleOutTopo = args[1] + } + + return cm.CheckCluster(args[0], scaleOutTopo, opt, gOpt) }, } diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 47ba547b28..77875a24eb 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -45,7 +45,7 @@ type CheckOptions struct { } // CheckCluster check cluster before deploying or upgrading -func (m *Manager) CheckCluster(clusterOrTopoName string, opt CheckOptions, gOpt operator.Options) error { +func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt CheckOptions, gOpt operator.Options) error { var topo spec.Specification ctx := ctxt.New( context.Background(), @@ -69,10 +69,36 @@ func (m *Manager) CheckCluster(clusterOrTopoName string, opt CheckOptions, gOpt if err != nil { return err } - opt.User = metadata.User - opt.IdentityFile = m.specManager.Path(clusterName, "ssh", "id_rsa") - topo = *metadata.Topology + if scaleoutTopo != "" { + currTopo := *metadata.Topology + if err := spec.ParseTopologyYaml(scaleoutTopo, &topo); err != nil { + return err + } + spec.ExpandRelativeDir(&topo) + + mergedTopo := currTopo.MergeTopo(&topo) + if err := mergedTopo.Validate(); err != nil { + return err + } + if err := checkConflict(m, clusterName, mergedTopo); err != nil { + return err + } + + // complete global configuration + topo.GlobalOptions = currTopo.GlobalOptions + topo.MonitoredOptions = currTopo.MonitoredOptions + topo.ServerConfigs = currTopo.ServerConfigs + + // scaleOutTopo also is not exists instacne + opt.ExistCluster = false + } else { + opt.User = metadata.User + opt.IdentityFile = m.specManager.Path(clusterName, "ssh", "id_rsa") + + topo = *metadata.Topology + } + topo.AdjustByVersion(metadata.Version) } else { // check before cluster is deployed topoFileName := clusterOrTopoName @@ -82,15 +108,7 @@ func (m *Manager) CheckCluster(clusterOrTopoName string, opt CheckOptions, gOpt } spec.ExpandRelativeDir(&topo) - clusterList, err := m.specManager.GetAllClusters() - if err != nil { - return err - } - // use a dummy cluster name, the real cluster name is set during deploy - if err := spec.CheckClusterPortConflict(clusterList, "nonexist-dummy-tidb-cluster", &topo); err != nil { - return err - } - if err := spec.CheckClusterDirConflict(clusterList, "nonexist-dummy-tidb-cluster", &topo); err != nil { + if err := checkConflict(m, "nonexist-dummy-tidb-cluster", &topo); err != nil { return err } } @@ -198,6 +216,34 @@ func checkSystemInfo( task.CheckTypeFIO, topo, opt.Opr, + ). + CheckSys( + inst.GetHost(), + inst.DeployDir(), + task.ChecktypeIsExist, + topo, + opt.Opr, + ). + CheckSys( + inst.GetHost(), + inst.DataDir(), + task.ChecktypeIsExist, + topo, + opt.Opr, + ). + CheckSys( + inst.GetHost(), + inst.LogDir(), + task.ChecktypeIsExist, + topo, + opt.Opr, + ). + CheckSys( + inst.GetHost(), + fmt.Sprintf("/etc/systemd/system/%s-%d.service", inst.ComponentName(), inst.GetPort()), + task.ChecktypeIsExist, + topo, + opt.Opr, ) if opt.ExistCluster { t1 = t1.CheckSys( @@ -596,3 +642,17 @@ func (m *Manager) checkRegionsInfo(clusterName string, topo *spec.Specification, } return nil } + +// checkConflict checks cluster conflict +func checkConflict(m *Manager, clusterName string, topo spec.Topology) error { + clusterList, err := m.specManager.GetAllClusters() + if err != nil { + return err + } + // use a dummy cluster name, the real cluster name is set during deploy + if err := spec.CheckClusterPortConflict(clusterList, clusterName, topo); err != nil { + return err + } + err = spec.CheckClusterDirConflict(clusterList, clusterName, topo) + return err +} diff --git a/pkg/cluster/operation/check.go b/pkg/cluster/operation/check.go index 032f5b20e4..9c5f3ce2c4 100644 --- a/pkg/cluster/operation/check.go +++ b/pkg/cluster/operation/check.go @@ -62,6 +62,7 @@ var ( CheckNameFio = "fio" CheckNameTHP = "thp" CheckNameDirPermission = "permission" + CheckNameDirExist = "exist" ) // CheckResult is the result of a check @@ -853,3 +854,29 @@ func CheckDirPermission(ctx context.Context, e ctxt.Executor, user, path string) return results } + +// CheckDirIsExist check if the directory exists +func CheckDirIsExist(ctx context.Context, e ctxt.Executor, path string) []*CheckResult { + var results []*CheckResult + + if path == "" { + return results + } + + req, _, _ := e.Execute(ctx, + fmt.Sprintf( + "[ -e %s ] && echo 1", + path, + ), + false) + + if strings.ReplaceAll(string(req), "\n", "") == "1" { + results = append(results, &CheckResult{ + Name: CheckNameDirExist, + Err: fmt.Errorf("%s already exists", path), + Msg: fmt.Sprintf("%s already exists", path), + }) + } + + return results +} diff --git a/pkg/cluster/spec/util.go b/pkg/cluster/spec/util.go index fecb81d8e9..0e1a523ccb 100644 --- a/pkg/cluster/spec/util.go +++ b/pkg/cluster/spec/util.go @@ -17,9 +17,7 @@ import ( "bytes" "context" "crypto/tls" - "encoding/binary" "fmt" - "net" "path/filepath" "reflect" "strings" @@ -212,109 +210,3 @@ func PackagePath(comp string, version string, os string, arch string) string { fileName := fmt.Sprintf("%s-%s-%s-%s.tar.gz", comp, version, os, arch) return ProfilePath(TiUPPackageCacheDir, fileName) } - -// IsValidIP Determine whether the IP is legal -func IsValidIP(str string) (bool, net.IP) { - address := net.ParseIP(str) // Parse the IP if it is legal, it will return the legal IP format - if address == nil { - return false, nil - } - return true, address -} - -// IsPortOpen 判断端口是否开 -func IsPortOpen(ip string, port int) bool { - isValid, _ := IsValidIP(ip) - - if isValid { - if ping, _ := IsPing(ip); !ping { - return ping - } - - netIP := net.ParseIP(ip) - tcpAddr := net.TCPAddr{ - IP: netIP, - Port: port, - } - // initiate a TCP conn to test whether the corresponding port exists - conn, err := net.DialTCP("tcp", nil, &tcpAddr) - if err != nil { - return false - } - // 否则则存在该端口,关闭连接句柄 - _ = conn.Close() - return true - } - return false -} - -// ICMP icmp package info -type ICMP struct { - Type uint8 - Code uint8 - Checksum uint16 - Identifier uint16 - SequenceNum uint16 -} - -// IsPing Check IP connectivity -func IsPing(ip string) (bool, error) { - var icmp ICMP - //开始填充数据包 - icmp.Type = 8 //8->echo message 0->reply message - icmp.Code = 0 - icmp.Checksum = 0 - icmp.Identifier = 0 - icmp.SequenceNum = 0 - - recvBuf := make([]byte, 32) - var buffer bytes.Buffer - - // First write the icmp datagram in the buffer for checksum - binary.Write(&buffer, binary.BigEndian, icmp) - icmp.Checksum = checkSum(buffer.Bytes()) - buffer.Reset() - binary.Write(&buffer, binary.BigEndian, icmp) - - conn, err := net.DialTimeout("ip4:icmp", ip, time.Second*2) - if err != nil { - return false, err - } - _, err = conn.Write(buffer.Bytes()) - if err != nil { - return false, err - } - conn.SetReadDeadline(time.Now().Add(time.Second * 2)) - num, err := conn.Read(recvBuf) - if err != nil { - return false, err - } - - conn.SetReadDeadline(time.Time{}) - - if string(recvBuf[0:num]) != "" { - return true, nil - } - return false, fmt.Errorf("ping %v failed", ip) - -} - -// checkSum -func checkSum(data []byte) uint16 { - var ( - sum uint32 - length int = len(data) - index int - ) - for length > 1 { - sum += uint32(data[index])<<8 + uint32(data[index+1]) - index += 2 - length -= 2 - } - if length > 0 { - sum += uint32(data[index]) - } - sum += (sum >> 16) - - return uint16(^sum) -} diff --git a/pkg/cluster/task/check.go b/pkg/cluster/task/check.go index 4a835346f2..5d26aae9b1 100644 --- a/pkg/cluster/task/check.go +++ b/pkg/cluster/task/check.go @@ -36,6 +36,7 @@ var ( CheckTypePartitions = "partitions" CheckTypeFIO = "fio" CheckTypePermission = "permission" + ChecktypeIsExist = "exist" ) // place the check utilities are stored @@ -147,6 +148,13 @@ func (c *CheckSys) Execute(ctx context.Context) error { return ErrNoExecutor } storeResults(ctx, c.host, operator.CheckDirPermission(ctx, e, c.topo.GlobalOptions.User, c.checkDir)) + case ChecktypeIsExist: + e, ok := ctxt.GetInner(ctx).GetExecutor(c.host) + if !ok { + return ErrNoExecutor + } + // check partition mount options for data_dir + storeResults(ctx, c.host, operator.CheckDirIsExist(ctx, e, c.checkDir)) } return nil diff --git a/pkg/cluster/task/exist.go b/pkg/cluster/task/exist.go deleted file mode 100644 index 3d76571906..0000000000 --- a/pkg/cluster/task/exist.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020 PingCAP, Inc. -// -// 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, -// See the License for the specific language governing permissions and -// limitations under the License. - -package task - -import ( - "context" - "fmt" - - "github.com/pingcap/errors" - "github.com/pingcap/tiup/pkg/cluster/ctxt" -) - -// Exist is used to determine path if it exists on the target host -type Exist struct { - host string - path string - isFile bool - isDirectory bool -} - -// Execute implements the Task interface -func (e *Exist) Execute(ctx context.Context) error { - exec, found := ctxt.GetInner(ctx).GetExecutor(e.host) - if !found { - return ErrNoExecutor - } - - cmd := fmt.Sprintf(`[ -e %s ] && echo 1`, e.path) - - switch { - case e.isFile: - cmd = fmt.Sprintf(`[ -f %s ] && echo 1`, e.path) - case e.isDirectory: - cmd = fmt.Sprintf(`[ -d %s ] && echo 1`, e.path) - } - - req, _, err := exec.Execute(ctx, cmd, false) - if err != nil { - return errors.Trace(err) - } - if string(req) != "1" { - return fmt.Errorf("`%s` does not exist on the target host `%s`", e.path, e.host) - } - - return nil -} - -// Rollback implements the Task interface -func (e *Exist) Rollback(ctx context.Context) error { - return nil -} - -// String implements the fmt.Stringer interface -func (e *Exist) String() string { - return fmt.Sprintf("Exist: host=%s, path='%s'", e.host, e.path) -} diff --git a/pkg/cluster/task/notexist.go b/pkg/cluster/task/notexist.go deleted file mode 100644 index 037bd7a0e7..0000000000 --- a/pkg/cluster/task/notexist.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020 PingCAP, Inc. -// -// 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, -// See the License for the specific language governing permissions and -// limitations under the License. - -package task - -import ( - "context" - "fmt" - - "github.com/pingcap/errors" - "github.com/pingcap/tiup/pkg/cluster/ctxt" -) - -// NotExist is used to determine path if it exists on the target host -type NotExist struct { - host string - path string - isFile bool - isDirectory bool -} - -// Execute implements the Task interface -func (e *NotExist) Execute(ctx context.Context) error { - exec, found := ctxt.GetInner(ctx).GetExecutor(e.host) - if !found { - return ErrNoExecutor - } - - cmd := fmt.Sprintf(`[ ! -e %s ] && echo 1`, e.path) - - switch { - case e.isFile: - cmd = fmt.Sprintf(`[ ! -f %s ] && echo 1`, e.path) - case e.isDirectory: - cmd = fmt.Sprintf(`[ ! -d %s ] && echo 1`, e.path) - } - - req, _, err := exec.Execute(ctx, cmd, false) - if err != nil { - return errors.Trace(err) - } - if string(req) != "1" { - return fmt.Errorf("`%s` is exist on the target host `%s`", e.path, e.host) - } - - return nil -} - -// Rollback implements the Task interface -func (e *NotExist) Rollback(ctx context.Context) error { - return nil -} - -// String implements the fmt.Stringer interface -func (e *NotExist) String() string { - return fmt.Sprintf("NotExist: host=%s, path='%s'", e.host, e.path) -} From 6b4447c9bd49353f43342d0d1ad1ef4c2abd1ddc Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 02:50:27 +0800 Subject: [PATCH 05/13] add scale-out tips --- pkg/cluster/manager/scale_out.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/cluster/manager/scale_out.go b/pkg/cluster/manager/scale_out.go index 7058a04de6..c3bf487551 100644 --- a/pkg/cluster/manager/scale_out.go +++ b/pkg/cluster/manager/scale_out.go @@ -65,6 +65,9 @@ func (m *Manager) ScaleOut( return err } + m.logger.Infof(`It is recommended to check the scale-out topology before executing scale-out operations + '%s'`, color.YellowString("tiup cluster check %s %s --cluster", name, topoFile)) + topo := metadata.GetTopology() base := metadata.GetBaseMeta() // Inherit existing global configuration. We must assign the inherited values before unmarshalling From ed661e99b65d3b3a49607590c3f1045e6102cb21 Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 12:15:44 +0800 Subject: [PATCH 06/13] fix deploy path --- pkg/cluster/manager/check.go | 14 +++++++------- pkg/cluster/manager/scale_out.go | 9 +-------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 77875a24eb..389ddc6bf9 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -72,24 +72,24 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check if scaleoutTopo != "" { currTopo := *metadata.Topology + // complete global configuration + topo.GlobalOptions = currTopo.GlobalOptions + topo.MonitoredOptions = currTopo.MonitoredOptions + topo.ServerConfigs = currTopo.ServerConfigs + if err := spec.ParseTopologyYaml(scaleoutTopo, &topo); err != nil { return err } - spec.ExpandRelativeDir(&topo) - mergedTopo := currTopo.MergeTopo(&topo) if err := mergedTopo.Validate(); err != nil { return err } + + spec.ExpandRelativeDir(&topo) if err := checkConflict(m, clusterName, mergedTopo); err != nil { return err } - // complete global configuration - topo.GlobalOptions = currTopo.GlobalOptions - topo.MonitoredOptions = currTopo.MonitoredOptions - topo.ServerConfigs = currTopo.ServerConfigs - // scaleOutTopo also is not exists instacne opt.ExistCluster = false } else { diff --git a/pkg/cluster/manager/scale_out.go b/pkg/cluster/manager/scale_out.go index c3bf487551..44a3f5d4c4 100644 --- a/pkg/cluster/manager/scale_out.go +++ b/pkg/cluster/manager/scale_out.go @@ -169,14 +169,7 @@ func (m *Manager) ScaleOut( } } - clusterList, err := m.specManager.GetAllClusters() - if err != nil { - return err - } - if err := spec.CheckClusterPortConflict(clusterList, name, mergedTopo); err != nil { - return err - } - if err := spec.CheckClusterDirConflict(clusterList, name, mergedTopo); err != nil { + if err := checkConflict(m, name, mergedTopo); err != nil { return err } } From 73466183f2079d4235b06fae2c6b144ba17f2ef3 Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 13:00:58 +0800 Subject: [PATCH 07/13] add scale-out check --- pkg/cluster/manager/scale_out.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/cluster/manager/scale_out.go b/pkg/cluster/manager/scale_out.go index 44a3f5d4c4..e27cbdfdf6 100644 --- a/pkg/cluster/manager/scale_out.go +++ b/pkg/cluster/manager/scale_out.go @@ -51,6 +51,11 @@ func (m *Manager) ScaleOut( return err } + if !opt.Stage2 { + m.logger.Infof(`It is recommended to check the scale-out topology before executing scale-out operations + '%s'`, color.YellowString("tiup cluster check %s %s --cluster", name, topoFile)) + } + // check the scale out file lock is exist err := checkScaleOutLock(m, name, opt, skipConfirm) if err != nil { @@ -65,9 +70,6 @@ func (m *Manager) ScaleOut( return err } - m.logger.Infof(`It is recommended to check the scale-out topology before executing scale-out operations - '%s'`, color.YellowString("tiup cluster check %s %s --cluster", name, topoFile)) - topo := metadata.GetTopology() base := metadata.GetBaseMeta() // Inherit existing global configuration. We must assign the inherited values before unmarshalling From 9c1d9a13f067f3f0a583774bcccb2a883c4fa382 Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 13:15:07 +0800 Subject: [PATCH 08/13] fix opt.User --- pkg/cluster/manager/check.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 389ddc6bf9..9ad00db134 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -93,12 +93,11 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check // scaleOutTopo also is not exists instacne opt.ExistCluster = false } else { - opt.User = metadata.User opt.IdentityFile = m.specManager.Path(clusterName, "ssh", "id_rsa") - topo = *metadata.Topology } + opt.User = metadata.User topo.AdjustByVersion(metadata.Version) } else { // check before cluster is deployed topoFileName := clusterOrTopoName From 48c000a47b0c0c457e4a98e4732f146712ed9933 Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 13:49:57 +0800 Subject: [PATCH 09/13] fix Topo.Validate --- pkg/cluster/manager/check.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 9ad00db134..b827d7347f 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -52,6 +52,7 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check gOpt.Concurrency, m.logger, ) + var currTopo *spec.Specification if opt.ExistCluster { // check for existing cluster clusterName := clusterOrTopoName @@ -71,7 +72,7 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check } if scaleoutTopo != "" { - currTopo := *metadata.Topology + currTopo = metadata.Topology // complete global configuration topo.GlobalOptions = currTopo.GlobalOptions topo.MonitoredOptions = currTopo.MonitoredOptions @@ -80,23 +81,15 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check if err := spec.ParseTopologyYaml(scaleoutTopo, &topo); err != nil { return err } - mergedTopo := currTopo.MergeTopo(&topo) - if err := mergedTopo.Validate(); err != nil { - return err - } - spec.ExpandRelativeDir(&topo) - if err := checkConflict(m, clusterName, mergedTopo); err != nil { - return err - } // scaleOutTopo also is not exists instacne opt.ExistCluster = false } else { opt.IdentityFile = m.specManager.Path(clusterName, "ssh", "id_rsa") + topo = *metadata.Topology } - opt.User = metadata.User topo.AdjustByVersion(metadata.Version) } else { // check before cluster is deployed @@ -132,6 +125,19 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check return err } + // Abort scale out operation if the merged topology is invalid + if opt.ExistCluster && scaleoutTopo != "" { + if currTopo != nil { + mergedTopo := currTopo.MergeTopo(&topo) + if err := mergedTopo.Validate(); err != nil { + return err + } + if err := checkConflict(m, clusterOrTopoName, mergedTopo); err != nil { + return err + } + } + } + if err := checkSystemInfo(ctx, sshConnProps, sshProxyProps, &topo, &gOpt, &opt); err != nil { return err } From 5ca80e074706cf6797e3dffa521cff709ae126a9 Mon Sep 17 00:00:00 2001 From: srstack Date: Thu, 9 Dec 2021 14:10:38 +0800 Subject: [PATCH 10/13] fix Topo.Validate --- pkg/cluster/manager/check.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index b827d7347f..1dda3c6372 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -126,15 +126,13 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check } // Abort scale out operation if the merged topology is invalid - if opt.ExistCluster && scaleoutTopo != "" { - if currTopo != nil { - mergedTopo := currTopo.MergeTopo(&topo) - if err := mergedTopo.Validate(); err != nil { - return err - } - if err := checkConflict(m, clusterOrTopoName, mergedTopo); err != nil { - return err - } + if currTopo != nil { + mergedTopo := currTopo.MergeTopo(&topo) + if err := mergedTopo.Validate(); err != nil { + return err + } + if err := checkConflict(m, clusterOrTopoName, mergedTopo); err != nil { + return err } } From d65d0528750989dcdb8ad8879edebe8d9737f702 Mon Sep 17 00:00:00 2001 From: srstack Date: Fri, 10 Dec 2021 13:29:50 +0800 Subject: [PATCH 11/13] fix Topo.Validate --- pkg/cluster/manager/check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 1dda3c6372..91a4ae40fa 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -126,7 +126,7 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check } // Abort scale out operation if the merged topology is invalid - if currTopo != nil { + if currTopo != nil && scaleoutTopo != "" { mergedTopo := currTopo.MergeTopo(&topo) if err := mergedTopo.Validate(); err != nil { return err From 5de7ff4387d39d7915abcf10f07c8bf866ee406d Mon Sep 17 00:00:00 2001 From: srstack Date: Fri, 24 Dec 2021 18:01:41 +0800 Subject: [PATCH 12/13] fix rootssh with scale-out check --- pkg/cluster/manager/check.go | 66 +++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/pkg/cluster/manager/check.go b/pkg/cluster/manager/check.go index 91a4ae40fa..896c746d4d 100644 --- a/pkg/cluster/manager/check.go +++ b/pkg/cluster/manager/check.go @@ -83,14 +83,15 @@ func (m *Manager) CheckCluster(clusterOrTopoName, scaleoutTopo string, opt Check } spec.ExpandRelativeDir(&topo) + // checkConflict after fillHostArch // scaleOutTopo also is not exists instacne opt.ExistCluster = false } else { opt.IdentityFile = m.specManager.Path(clusterName, "ssh", "id_rsa") - topo = *metadata.Topology + opt.User = metadata.User } - opt.User = metadata.User + topo.AdjustByVersion(metadata.Version) } else { // check before cluster is deployed topoFileName := clusterOrTopoName @@ -207,19 +208,9 @@ func checkSystemInfo( opt.Opr, ) } - // if the data dir set in topology is relative, and the home dir of deploy user - // and the user run the check command is on different partitions, the disk detection - // may be using incorrect partition for validations. - for _, dataDir := range spec.MultiDirAbs(opt.User, inst.DataDir()) { - // build checking tasks + + if !opt.ExistCluster { t1 = t1. - CheckSys( - inst.GetHost(), - dataDir, - task.CheckTypeFIO, - topo, - opt.Opr, - ). CheckSys( inst.GetHost(), inst.DeployDir(), @@ -248,6 +239,21 @@ func checkSystemInfo( topo, opt.Opr, ) + } + // if the data dir set in topology is relative, and the home dir of deploy user + // and the user run the check command is on different partitions, the disk detection + // may be using incorrect partition for validations. + for _, dataDir := range spec.MultiDirAbs(opt.User, inst.DataDir()) { + // build checking tasks + t1 = t1. + CheckSys( + inst.GetHost(), + dataDir, + task.CheckTypeFIO, + topo, + opt.Opr, + ) + if opt.ExistCluster { t1 = t1.CheckSys( inst.GetHost(), @@ -319,20 +325,6 @@ func checkSystemInfo( topo, opt.Opr, ). - // check for listening port - Shell( - inst.GetHost(), - "ss -lnt", - "", - false, - ). - CheckSys( - inst.GetHost(), - "", - task.CheckTypePort, - topo, - opt.Opr, - ). // check for system limits Shell( inst.GetHost(), @@ -377,6 +369,24 @@ func checkSystemInfo( topo, opt.Opr, ) + + if !opt.ExistCluster { + t1 = t1. + // check for listening port + Shell( + inst.GetHost(), + "ss -lnt", + "", + false, + ). + CheckSys( + inst.GetHost(), + "", + task.CheckTypePort, + topo, + opt.Opr, + ) + } } checkSysTasks = append( From d361ed7f375283a687851e1f6651838709e67c0b Mon Sep 17 00:00:00 2001 From: srstack Date: Wed, 29 Dec 2021 12:05:25 +0800 Subject: [PATCH 13/13] remove the suggestion to execute check --- pkg/cluster/manager/scale_out.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/cluster/manager/scale_out.go b/pkg/cluster/manager/scale_out.go index e27cbdfdf6..f1f132a998 100644 --- a/pkg/cluster/manager/scale_out.go +++ b/pkg/cluster/manager/scale_out.go @@ -51,11 +51,6 @@ func (m *Manager) ScaleOut( return err } - if !opt.Stage2 { - m.logger.Infof(`It is recommended to check the scale-out topology before executing scale-out operations - '%s'`, color.YellowString("tiup cluster check %s %s --cluster", name, topoFile)) - } - // check the scale out file lock is exist err := checkScaleOutLock(m, name, opt, skipConfirm) if err != nil {