From 54d0a0304a0f76a0e619a8adac370eb3866f52b1 Mon Sep 17 00:00:00 2001
From: liyuanr <liyuanrong1@huawei.com>
Date: Wed, 31 Aug 2022 18:06:28 +0800
Subject: [PATCH] KubeOS:add the clearing of space before the upgrade and
 rectifying the rollback failure.

The pre-upgrade space clearance function is added to resolve the problem that the upgrade
fails due to residual resources when the upgrade is performed again after a power failure.
Fix the rollback failure when the upgrade fails due to the upgrade using different architectures.

Signed-off-by: liyuanr <liyuanrong1@huawei.com>
---
 cmd/agent/server/docker_image.go | 91 ++++++++++++++++++++++++++++----
 scripts/grub.cfg                 | 10 ----
 2 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/cmd/agent/server/docker_image.go b/cmd/agent/server/docker_image.go
index 11b21aa..4f9edc1 100644
--- a/cmd/agent/server/docker_image.go
+++ b/cmd/agent/server/docker_image.go
@@ -15,6 +15,7 @@ package server
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -47,9 +48,18 @@ func pullOSImage(req *pb.UpdateRequest) (string, error) {
 		return "", err
 	}
 
+	containerName := "kubeos-temp"
+	containers, err := cli.ContainerList(ctx, types.ContainerListOptions{All: true})
+	for _, container := range containers {
+		if container.Names[0] == "/"+containerName {
+			if err = cli.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{}); err != nil {
+				return "", err
+			}
+		}
+	}
 	info, err := cli.ContainerCreate(ctx, &container.Config{
 		Image: imageName,
-	}, nil, nil, "kubeos-temp")
+	}, nil, nil, containerName)
 	if err != nil {
 		return "", err
 	}
@@ -71,22 +81,31 @@ func pullOSImage(req *pb.UpdateRequest) (string, error) {
 		return "", fmt.Errorf("space is not enough for downloaing")
 	}
 
+	tmpUpdatePath := filepath.Join(PersistDir, "/KubeOS-Update")
+	tmpMountPath := filepath.Join(tmpUpdatePath, "/kubeos-update")
+	tmpTarPath := filepath.Join(tmpUpdatePath, "/os.tar")
+	imagePath := filepath.Join(PersistDir, "/update.img")
+
+	if err = cleanSpace(tmpUpdatePath, tmpMountPath, imagePath); err != nil {
+		return "", err
+	}
+	if err = os.MkdirAll(tmpMountPath, imgPermission); err != nil {
+		return "", err
+	}
+	defer os.RemoveAll(tmpUpdatePath)
+
 	srcInfo := archive.CopyInfo{
 		Path:   "/",
 		Exists: true,
 		IsDir:  stat.Mode.IsDir(),
 	}
-	if err = archive.CopyTo(tarStream, srcInfo, PersistDir); err != nil {
+	if err = archive.CopyTo(tarStream, srcInfo, tmpUpdatePath); err != nil {
 		return "", err
 	}
-
-	tmpMountPath := filepath.Join(PersistDir, "/kubeos-update")
-	if err = os.Mkdir(tmpMountPath, imgPermission); err != nil {
+	if err = runCommand("dd", "if=/dev/zero", "of="+imagePath, "bs=2M", "count=1024"); err != nil {
 		return "", err
 	}
-	defer os.Remove(tmpMountPath)
-	imagePath := filepath.Join(PersistDir, "/update.img")
-	if err = runCommand("dd", "if=/dev/zero", "of="+imagePath, "bs=2M", "count=1024"); err != nil {
+	if err = os.Chmod(imagePath, imgPermission); err != nil {
 		return "", err
 	}
 	_, next, err := getNextPart(partA, partB)
@@ -102,10 +121,62 @@ func pullOSImage(req *pb.UpdateRequest) (string, error) {
 	}()
 
 	logrus.Infoln("downloading to file " + imagePath)
-	tmpTarPath := filepath.Join(PersistDir, "/os.tar")
 	if err = runCommand("tar", "-xvf", tmpTarPath, "-C", tmpMountPath); err != nil {
 		return "", err
 	}
-	defer os.Remove(tmpTarPath)
 	return imagePath, nil
 }
+
+func cleanSpace(updatePath, mountPath, imagePath string) error {
+	isFileExist, err := checkFileExist(mountPath)
+	if err != nil {
+		return err
+	}
+	if isFileExist {
+		var st syscall.Stat_t
+		if err := syscall.Lstat(mountPath, &st); err != nil {
+			return err
+		}
+		dev := st.Dev
+		parent := filepath.Dir(mountPath)
+		if err := syscall.Lstat(parent, &st); err != nil {
+			return err
+		}
+		if dev != st.Dev {
+			if err := syscall.Unmount(mountPath, 0); err != nil {
+				return err
+			}
+		}
+	}
+
+	if err = deleteFile(updatePath); err != nil {
+		return err
+	}
+
+	if err = deleteFile(imagePath); err != nil {
+		return err
+	}
+	return nil
+}
+
+func deleteFile(path string) error {
+	isFileExist, err := checkFileExist(path)
+	if err != nil {
+		return err
+	}
+	if isFileExist {
+		if err = os.RemoveAll(path); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+func checkFileExist(path string) (bool, error) {
+	if _, err := os.Stat(path); err == nil {
+		return true, nil
+	} else if errors.Is(err, os.ErrNotExist) {
+		return false, nil
+	} else {
+		return false, err
+	}
+}
diff --git a/scripts/grub.cfg b/scripts/grub.cfg
index d10e4cf..c1a2641 100644
--- a/scripts/grub.cfg
+++ b/scripts/grub.cfg
@@ -91,11 +91,6 @@ menuentry 'A' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
         insmod part_msdos
         insmod ext2
         set root='hd0,msdos2'
-        if [ x$feature_platform_search_hint = xy ]; then
-          search --no-floppy --file --set=root --hint-bios=hd0,msdos2 --hint-efi=hd0,msdos2 --hint-baremetal=ahci0,msdos2 /boot/vmlinuz
-        else
-          search --no-floppy --file --set=root /boot/vmlinuz
-        fi
         linux   /boot/vmlinuz root=/dev/sda2 ro rootfstype=ext4 nomodeset quiet oops=panic softlockup_panic=1 nmi_watchdog=1 rd.shell=0 selinux=0 crashkernel=256M panic=3
         initrd  /boot/initramfs.img
 }
@@ -107,11 +102,6 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
         insmod part_msdos
         insmod ext2
         set root='hd0,msdos3'
-        if [ x$feature_platform_search_hint = xy ]; then
-          search --no-floppy --file --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3 /boot/vmlinuz
-        else
-          search --no-floppy --file --set=root /boot/vmlinuz
-        fi
         linux   /boot/vmlinuz root=/dev/sda3 ro rootfstype=ext4 nomodeset quiet oops=panic softlockup_panic=1 nmi_watchdog=1 rd.shell=0 selinux=0 crashkernel=256M panic=3
         initrd  /boot/initramfs.img
 }
-- 
2.33.0.windows.2

