github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/runtime/k0s/utils.go (about)

     1  // Copyright © 2022 Alibaba Group Holding Ltd.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package k0s
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/pkg/errors"
    25  	"github.com/sealerio/sealer/pkg/client/k8s"
    26  	"golang.org/x/sync/errgroup"
    27  	corev1 "k8s.io/api/core/v1"
    28  	"k8s.io/apimachinery/pkg/util/wait"
    29  	"k8s.io/client-go/tools/clientcmd"
    30  	runtimeClient "sigs.k8s.io/controller-runtime/pkg/client"
    31  
    32  	"github.com/sirupsen/logrus"
    33  )
    34  
    35  const WaitingFork0sServiceStartTimes = 5
    36  
    37  func (k *Runtime) WaitK0sReady(host net.IP) error {
    38  	times := WaitingFork0sServiceStartTimes
    39  	for {
    40  		times--
    41  		if times == 0 {
    42  			break
    43  		}
    44  		logrus.Infof("waiting for k0s service ready")
    45  		time.Sleep(time.Second * 5)
    46  		bytes, err := k.infra.Cmd(host, nil, "k0s status")
    47  		if err != nil {
    48  			return err
    49  		}
    50  		// k0s status return: `Process ID: xxx` when it started successfully, or return: `connect failed`,
    51  		// so we use field `Process` whether contains in string(bytes) to verify if k0s service started successfully.
    52  		if strings.Contains(string(bytes), "Process") {
    53  			return nil
    54  		}
    55  	}
    56  	return errors.New("failed to start k0s: failed to get k0s status after 10 seconds")
    57  }
    58  
    59  func GetClientFromConfig(adminConfPath string) (runtimeClient.Client, error) {
    60  	adminConfig, err := clientcmd.BuildConfigFromFlags("", adminConfPath)
    61  	if nil != err {
    62  		return nil, err
    63  	}
    64  
    65  	var ret runtimeClient.Client
    66  
    67  	timeout := time.Second * 30
    68  	err = wait.PollImmediate(time.Second*10, timeout, func() (done bool, err error) {
    69  		cli, err := runtimeClient.New(adminConfig, runtimeClient.Options{})
    70  		if nil != err {
    71  			return false, err
    72  		}
    73  
    74  		ns := corev1.Namespace{}
    75  		if err := cli.Get(context.Background(), runtimeClient.ObjectKey{Name: "default"}, &ns); nil != err {
    76  			return false, err
    77  		}
    78  
    79  		ret = cli
    80  
    81  		return true, nil
    82  	})
    83  	return ret, err
    84  }
    85  
    86  func (k *Runtime) WaitSSHReady(tryTimes int, hosts ...net.IP) error {
    87  	eg, _ := errgroup.WithContext(context.Background())
    88  	for _, h := range hosts {
    89  		host := h
    90  		eg.Go(func() error {
    91  			// TODO: use Time.Ticker to replace this loop.
    92  			for i := 0; i < tryTimes; i++ {
    93  				if err := k.infra.Ping(host); err == nil {
    94  					return nil
    95  				}
    96  				time.Sleep(time.Duration(i) * time.Second)
    97  			}
    98  			return fmt.Errorf("wait for [%s] ssh ready timeout, ensure that the IP address or password is correct", host)
    99  		})
   100  	}
   101  	return eg.Wait()
   102  }
   103  
   104  func (k *Runtime) getNodeName(host net.IP) (string, error) {
   105  	client, err := k8s.NewK8sClient()
   106  	if err != nil {
   107  		return "", err
   108  	}
   109  	nodeList, err := client.ListNodes()
   110  	if err != nil {
   111  		return "", err
   112  	}
   113  	var hosts []string
   114  	for _, node := range nodeList.Items {
   115  		hosts = append(hosts, node.GetName())
   116  	}
   117  
   118  	hostName, err := k.infra.CmdToString(host, nil, "hostname", "")
   119  	if err != nil {
   120  		return "", err
   121  	}
   122  
   123  	var name string
   124  	for _, h := range hosts {
   125  		if strings.TrimSpace(h) == "" {
   126  			continue
   127  		}
   128  		hh := strings.ToLower(h)
   129  		fromH := strings.ToLower(hostName)
   130  		if hh == fromH {
   131  			name = h
   132  			break
   133  		}
   134  	}
   135  	return name, nil
   136  }