github.com/rigado/snapd@v2.42.5-go-mod+incompatible/overlord/configstate/configcore/watchdog.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package configcore 21 22 import ( 23 "fmt" 24 "sort" 25 "strings" 26 "time" 27 28 "github.com/snapcore/snapd/dirs" 29 "github.com/snapcore/snapd/osutil" 30 "github.com/snapcore/snapd/overlord/configstate/config" 31 ) 32 33 func init() { 34 // add supported configuration of this module 35 supportedConfigurations["core.watchdog.runtime-timeout"] = true 36 supportedConfigurations["core.watchdog.shutdown-timeout"] = true 37 } 38 39 func updateWatchdogConfig(config map[string]uint) error { 40 dir := dirs.SnapSystemdConfDir 41 name := "10-snapd-watchdog.conf" 42 dirContent := make(map[string]*osutil.FileState, 1) 43 44 configStr := []string{} 45 for k, v := range config { 46 if v > 0 { 47 configStr = append(configStr, fmt.Sprintf("%s=%d\n", k, v)) 48 } 49 } 50 if len(configStr) > 0 { 51 // We order the variables to have predictable output 52 sort.Strings(configStr) 53 content := "[Manager]\n" + strings.Join(configStr, "") 54 dirContent[name] = &osutil.FileState{ 55 Content: []byte(content), 56 Mode: 0644, 57 } 58 } 59 60 glob := name 61 _, _, err := osutil.EnsureDirState(dir, glob, dirContent) 62 return err 63 } 64 65 func handleWatchdogConfiguration(tr config.Conf) error { 66 config := map[string]uint{} 67 68 for _, key := range []string{"runtime-timeout", "shutdown-timeout"} { 69 output, err := coreCfg(tr, "watchdog."+key) 70 if err != nil { 71 return err 72 } 73 secs, err := getSystemdConfSeconds(output) 74 if err != nil { 75 return fmt.Errorf("cannot set timer to %q: %v", output, err) 76 } 77 switch key { 78 case "runtime-timeout": 79 config["RuntimeWatchdogSec"] = secs 80 case "shutdown-timeout": 81 config["ShutdownWatchdogSec"] = secs 82 } 83 } 84 85 if err := updateWatchdogConfig(config); err != nil { 86 return err 87 } 88 89 return nil 90 } 91 92 func getSystemdConfSeconds(timeStr string) (uint, error) { 93 if timeStr == "" { 94 return 0, nil 95 } 96 97 dur, err := time.ParseDuration(timeStr) 98 if err != nil { 99 return 0, fmt.Errorf("cannot parse %q: %v", timeStr, err) 100 } 101 if dur < 0 { 102 return 0, fmt.Errorf("cannot use negative duration %q: %v", timeStr, err) 103 } 104 105 return uint(dur.Seconds()), nil 106 } 107 108 func validateWatchdogOptions(tr config.Conf) error { 109 for _, key := range []string{"runtime-timeout", "shutdown-timeout"} { 110 option, err := coreCfg(tr, "watchdog."+key) 111 if err != nil { 112 return err 113 } 114 if _, err = getSystemdConfSeconds(option); err != nil { 115 return err 116 } 117 } 118 119 return nil 120 }