Files
sealos/pkg/filesystem/rootfs/rootfs_default.go
zzjin 2ef083dfc3 Feat typo (#1170)
* Update cmd typos to match unified code format.
* 1. Update Dockerfile install typo
2. run&fix `make format` on all files
2022-06-24 22:44:12 +08:00

226 lines
6.7 KiB
Go

/*
Copyright 2022 cuisongliu@qq.com.
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,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rootfs
import (
"context"
"fmt"
"io/ioutil"
"path"
"path/filepath"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/labring/sealos/pkg/env"
"github.com/labring/sealos/pkg/runtime"
v2 "github.com/labring/sealos/pkg/types/v1beta1"
"github.com/labring/sealos/pkg/utils/constants"
"github.com/labring/sealos/pkg/utils/exec"
"github.com/labring/sealos/pkg/utils/file"
"github.com/labring/sealos/pkg/utils/iputils"
"github.com/labring/sealos/pkg/utils/logger"
"github.com/labring/sealos/pkg/utils/ssh"
)
type defaultRootfs struct {
//clusterService image.ClusterService
//imgList types.ImageListOCIV1
//cluster types.ClusterManifestList
images []v2.MountImage
}
func (f *defaultRootfs) MountRootfs(cluster *v2.Cluster, hosts []string, initFlag, appFlag bool) error {
return f.mountRootfs(cluster, hosts, initFlag, appFlag)
}
func (f *defaultRootfs) UnMountRootfs(cluster *v2.Cluster, hosts []string) error {
return f.unmountRootfs(cluster, hosts)
}
func (f *defaultRootfs) getClusterName(cluster *v2.Cluster) string {
return cluster.Name
}
func (f *defaultRootfs) getSSH(cluster *v2.Cluster) ssh.Interface {
return ssh.NewSSHClient(&cluster.Spec.SSH, true)
}
func (f *defaultRootfs) mountRootfs(cluster *v2.Cluster, ipList []string, initFlag, appFlag bool) error {
target := constants.NewData(f.getClusterName(cluster)).RootFSPath()
eg, _ := errgroup.WithContext(context.Background())
envProcessor := env.NewEnvProcessor(cluster, f.images)
for _, cInfo := range f.images {
src := cInfo
eg.Go(func() error {
if !file.IsExist(src.MountPoint) {
logger.Debug("Image %s not exist,render env continue", src.ImageName)
return nil
}
err := renderENV(src.MountPoint, ipList, envProcessor)
if err != nil {
return errors.Wrap(err, "render env to rootfs failed")
}
dirs, err := file.StatDir(src.MountPoint, true)
if err != nil {
return errors.Wrap(err, "get rootfs files failed")
}
if len(dirs) != 0 {
_, err = exec.RunBashCmd(fmt.Sprintf(constants.DefaultChmodBash, src.MountPoint))
if err != nil {
return errors.Wrap(err, "run chmod to rootfs failed")
}
}
return nil
})
}
if err := eg.Wait(); err != nil {
return err
}
check := constants.NewBash(f.getClusterName(cluster), cluster.GetImageLabels())
sshClient := f.getSSH(cluster)
for _, IP := range ipList {
ip := IP
eg.Go(func() error {
fileEg, _ := errgroup.WithContext(context.Background())
for _, cInfo := range f.images {
img := cInfo
fileEg.Go(func() error {
if img.Type == v2.RootfsImage {
logger.Debug("send rootfs images ,ip: %s , init flag: %v, app flag: %v,image name: %s, image type: %s", ip, initFlag, appFlag, img.ImageName, img.Type)
err := CopyFiles(sshClient, iputils.GetHostIP(ip) == cluster.GetMaster0IP(), false, ip, img.MountPoint, target)
if err != nil {
return fmt.Errorf("copy container %s rootfs failed %v", img.Name, err)
}
}
return nil
})
}
if err := fileEg.Wait(); err != nil {
return err
}
for _, cInfo := range f.images {
if cInfo.Type == v2.AddonsImage {
logger.Debug("send addons images ,ip: %s , init flag: %v, app flag: %v,image name: %s, image type: %s", ip, initFlag, appFlag, cInfo.ImageName, cInfo.Type)
err := CopyFiles(sshClient, iputils.GetHostIP(ip) == cluster.GetMaster0IP(), false, ip, cInfo.MountPoint, target)
if err != nil {
return fmt.Errorf("copy container %s rootfs failed %v", cInfo.Name, err)
}
}
}
if initFlag {
checkBash := check.CheckBash()
if checkBash == "" {
return nil
}
if err := f.getSSH(cluster).CmdAsync(ip, envProcessor.WrapperShell(ip, check.CheckBash()), runtime.ApplyImageShimCMD(target)); err != nil {
return err
}
if err := f.getSSH(cluster).CmdAsync(ip, envProcessor.WrapperShell(ip, check.InitBash())); err != nil {
return err
}
}
return nil
})
}
err := eg.Wait()
if err != nil {
return err
}
endEg, _ := errgroup.WithContext(context.Background())
for _, cInfo := range f.images {
ip := cluster.GetMaster0IP()
img := cInfo
endEg.Go(func() error {
if appFlag && img.Type == v2.AppImage {
logger.Debug("send app images ,ip: %s , init flag: %v, app flag: %v,image name: %s, image type: %s", ip, initFlag, appFlag, img.ImageName, img.Type)
err = CopyFiles(sshClient, iputils.GetHostIP(ip) == cluster.GetMaster0IP(), true, ip, img.MountPoint, target)
if err != nil {
return fmt.Errorf("copy container %s app rootfs failed %v", img.Name, err)
}
}
return nil
})
}
return endEg.Wait()
}
func (f *defaultRootfs) unmountRootfs(cluster *v2.Cluster, ipList []string) error {
clusterRootfsDir := constants.NewData(f.getClusterName(cluster)).Homedir()
rmRootfs := fmt.Sprintf("rm -rf %s", clusterRootfsDir)
eg, _ := errgroup.WithContext(context.Background())
for _, IP := range ipList {
ip := IP
eg.Go(func() error {
SSH := f.getSSH(cluster)
return SSH.CmdAsync(ip, rmRootfs)
})
}
return eg.Wait()
}
func renderENV(mountDir string, ipList []string, p env.Interface) error {
var (
renderEtc = path.Join(mountDir, constants.EtcDirName)
renderChart = path.Join(mountDir, constants.ChartsDirName)
renderManifests = path.Join(mountDir, constants.ManifestsDirName)
)
for _, ip := range ipList {
for _, dir := range []string{renderEtc, renderChart, renderManifests} {
logger.Debug("render env dir: %s", dir)
if file.IsExist(dir) {
err := p.RenderAll(ip, dir)
if err != nil {
return err
}
}
}
}
return nil
}
func CopyFiles(sshEntry ssh.Interface, isRegistry, isApp bool, ip, src, target string) error {
files, err := ioutil.ReadDir(src)
if err != nil {
return fmt.Errorf("failed to copy files %s", err)
}
if isRegistry {
return sshEntry.Copy(ip, src, target)
}
targetIP := ip
if isApp {
targetIP = "127.0.0.1"
}
for _, f := range files {
if f.Name() == constants.RegistryDirName {
continue
}
err = sshEntry.Copy(targetIP, filepath.Join(src, f.Name()), filepath.Join(target, f.Name()))
if err != nil {
return fmt.Errorf("failed to copy sub files %v", err)
}
}
return nil
}
func NewDefaultRootfs(images []v2.MountImage) (Interface, error) {
return &defaultRootfs{images: images}, nil
}