2021/8/17

mender : state script

都沒有文件...

mender 把更新分成幾個 state (9個?)。
然後給個 state 一個 run script 的機會 (兩個?. enter , leave)
但是說明很少。

transient error: update commit failed: statescript: The statescript version file is missing. 
This file needs to be present and contain a single number representing which version of the statescript support 
the client is using in order to successfully run statescripts on the client
只好去找 source..
    versionFilePath := filepath.Join(l.RootfsScriptsPath, "version")
    f, err := os.Open(versionFilePath)
    if err != nil && os.IsNotExist(err) {
        errmsg := "statescript: The statescript version file is missing. This file needs to be " +
            "present and contain a single number representing which version of the statescript " +
            "support the client is using in order to successfully run statescripts on the client"
        return errors.New(errmsg)
    } else if err != nil {
        return errors.Wrap(err, "statescript")
    }
    ver, err := readVersion(f)
    if _, ok := err.(readVersionParseError); ok {
        errmsg := "statescript: Failed to parse the version file in the statescript directory (%s). " +
            "The file needs to contain a single integer signifying which version of the statescript " +
            "support which this client is using"
        return fmt.Errorf(errmsg, err)
    }
所以是需要一個叫 version 的 file,裡面是數字。

然後這個 RootfsScriptsPath 就是
conf/paths.go:	DefaultRootfsScriptsPath = path.Join(GetConfDirPath(), "scripts")
應該就是 /etc/mender/scripts

version 裡面只有一個 0,然後 Error 變成
transient error: update commit failed: statescript: unsupported scripts version: 0
找到:
func NewStateScriptExecutor(config *conf.MenderConfig) statescript.Launcher {
    ret := statescript.Launcher{
        ArtScriptsPath:          config.ArtifactScriptsPath,
        RootfsScriptsPath:       config.RootfsScriptsPath,
        SupportedScriptVersions: []int{2, 3},
..
把version內容由 0 改為 3 之後,果然就 ota OK 了,沒有 Error,但是 state script 以=也沒有執行....

execute.go 有 l.get( )
func (l Launcher) get(state, action string) ([]os.FileInfo, string, error) {

    sDir := l.ArtScriptsPath
    if state == "Idle" || state == "Sync" || state == "Download" {
        sDir = l.RootfsScriptsPath
    }
...
先看script 位置,依照 state 而有不同。
path.go
    DefaultArtScriptsPath    = path.Join(GetStateDirPath(), "scripts")
    DefaultRootfsScriptsPath = path.Join(GetConfDirPath(), "scripts")

DefaultDataStore   = "/var/lib/mender"

func GetStateDirPath() string {
    return DefaultDataStore
}
func GetConfDirPath() string {
    return "/etc/mender"
}
所以 Idle, Sync, Download 是在 /etc/mender。
其他state 是 /var/lib/mender

查實際的機器, 把 state script 放到 update OS (ext4) 的 /etc/mender/scripts/ 下後。包進 ota file (mender),然後 更新到機器上。
script folder 好像會被 copy 到 /data/mender/script (就是 /var/lib/mender 的 symbolic link)。(不是全部 copy)。
而 /etc/mender/script 跟 /var/lib/mender 剛好就是上面的 RootfsScriptsPath 跟 ArtScriptsPath。

但是... RootfsScriptPath 是在ota file 的 ext4 裡, /var/lib/mender 是working 的 os..不一樣。

把一些 example 的 script copy 到 update image 的 /etc/mender/scripts 下
# ls /etc/mender/scripts/
ArtifactCommit_Enter_00   Download_Enter_00         Sync_Enter_00
ArtifactInstall_Enter_00  Download_Leave_01         version
ArtifactReboot_Enter_00   Download_Leave_02
每一個 script 都是在 /data/ 下 touch 自己的 filename.
用 mender ota 成功,到 /data 下只有看到 Sync_Enter_00
符合上面的code,, idle,sync,download 都看 /etc/mender/script
所以把 一樣的 script 都 copy 到 /var/lib/mender/scripts ...


測試,每個 script 都是
date > /data/$(basename "$0")
然後從 /data 就可以知道有哪些 script 有正確執行。
mender 的 yocto recipes 也是用一樣的 script。
-- 裡面 script 都 copy 到一樣的地方喔。


最後:

state scripts 分成兩種,一種是預先要再系統的。一種是放在 artifacr (*.mender) 。
因為 Artifact(mender) 要 download 完會有,所以download 之後的 state ,script 都可以放在 artifacr (*.mender) 中。
其他沒有 download,或是還沒download 的 state,script 就要在系統力。

系統的位置是 /etc/mender/scripts
裡面要有一個 "version" 檔,內容是一個數字,例如 3。代表 script 的版本。
放在 artifact (*.mender) 的,就要在 create mender file 時給定。
用 -s 選項就可以。
這格選項家的 state script,一定要用 Artifact 開頭,例如 ArtifactCommit_Enter_00,ArtifactInstall_Enter_00
把 scripts 都放到 state_script foldler,用 shell scipt 找出來就是...
#!/bin/bash
LIST=""
for f in state_scripts/Artifact*
do
	LIST="${LIST} -s ${f}"
done
echo ${LIST}

沒有留言:

張貼留言