From 710071a871bbaa9f1f514acf0710966e7ae5b53d Mon Sep 17 00:00:00 2001
From: anatasluo <luolongjuna@gmail.com>
Date: Fri, 6 Aug 2021 11:39:15 +0800
Subject: [PATCH] restore pid file after restore from systemd

When I use systemd to restore nginx service,
I find that systemd will check pid file and it will
timeout since no value can be found in pid file.

To slove this problem, I add a ExecStartPost action to
write back necessary pid file.

Signed-off-by: anatasluo <luolongjuna@gmail.com>
---
 src/server.go | 50 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/src/server.go b/src/server.go
index 6b5d2c2..38a0bdb 100644
--- a/src/server.go
+++ b/src/server.go
@@ -50,6 +50,25 @@ func overrideConf(path string, content string) error {
 	return nil
 }
 
+func getSystemdOptions(service string, option string) (error, string) {
+	return runCmd("systemctl", []string{"show", "--property",
+		option, "--value", service}, nil, nil, nil)
+}
+
+func getPIDFile(service string) (error, string) {
+	err, ret := getSystemdOptions(service, "PIDFile")
+	if err != nil {
+		log.Errorf("Unable to get pid file for service %s\n", service)
+		log.Errorf("Error is %s \n", err)
+		return err, ""
+	}
+
+	log.Debugf("Get pid file for %s - %s \n", service, ret)
+
+	i := strings.Index(ret, "=")
+	return nil, ret[i+1:]
+}
+
 func overrideSystemctl(service string, pid int) error {
 	systemdEtc := nvwaSeverConfig.GetString("systemd_etc")
 
@@ -57,8 +76,9 @@ func overrideSystemctl(service string, pid int) error {
 	_ = os.Mkdir(systemdDir, 0700)
 
 	content := "[Service]\nExecStart=\nExecStart="
-	content += "nvwa restore " + service + " " + strconv.Itoa(pid) + "\n"
+	content += "nvwa restore " + service + "@" + strconv.Itoa(pid) + "\n"
 	content += "User=root\nGroup=root\n"
+
 	err := overrideConf(path.Join(systemdDir, "nvwa_override_exec.conf"), content)
 	if err != nil {
 		return err
@@ -118,8 +138,7 @@ func findPids(criuPids map[string]int) error {
 
 	services := nvwaRestoreConfig.GetStringSlice("services")
 	for _, val := range services {
-		err, tmpRet := runCmd("systemctl", []string{"show", "--property",
-			"MainPID", "--value", val}, nil, nil, nil)
+		err, tmpRet := getSystemdOptions(val, "MainPID")
 		if err != nil {
 			log.Errorf("Unable to get pid for service %s\n", val)
 			log.Errorf("Error is %s \n", err)
@@ -356,11 +375,27 @@ func loadConfig() {
 	readConfig(nvwaRestoreConfig, "nvwa-restore")
 }
 
-func RestoreService(service string) int {
+func RestoreService(cmd string) int {
+	i := strings.Index(cmd, "@")
+	service := cmd[:i]
+	pid := cmd[i+1:]
+
+	log.Debugf("nvwa restore %s %s \n", service, pid)
+
 	criuExe := nvwaSeverConfig.GetString("criu_exe")
 	criuDir := nvwaSeverConfig.GetString("criu_dir")
 
-	err, _ := runCmd(criuExe, getCriuPara("restore", path.Join(criuDir, service), ""),
+	err, pidfile := getPIDFile(service)
+	if err != nil {
+		return -1
+	}
+	pidfile = strings.TrimSpace(pidfile)
+	if pidfile != "" {
+		pidData := []byte(pid)
+		_ = ioutil.WriteFile(pidfile, pidData, 0644)
+	}
+
+	err, _ = runCmd(criuExe, getCriuPara("restore", path.Join(criuDir, service), ""),
 		os.Stdin, os.Stdout, os.Stderr)
 	if err != nil {
 		log.Errorf("Restore %s failed, error is %s \n", service, err)
@@ -435,7 +470,10 @@ func ExitServer(msg string) int {
 func may_init_socket(path string) error {
 	socketDir := filepath.Dir(path)
 	log.Debugf("Socket directory %s \n", socketDir)
-	return os.Mkdir(socketDir, 0700)
+	if _, err := os.Stat(socketDir); os.IsNotExist(err) {
+		return os.Mkdir(socketDir, 0700)
+	}
+	return nil
 }
 
 func runServer(path string) {
-- 
2.31.1

