/* * Copyright (C) 2017-2018 "IoT.bzh" * Author Sebastien Douheret * * 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 xdsserver import ( "os/exec" "path" "path/filepath" "strings" sc "sync" "time" common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib" "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1" ) const ( scriptXdsSrvUpdate = "updateXdsServerPackage" scriptGetXdsSrvUpdate = "getXdsServerPackage" scriptXdsSrvRestart = "restartXdsServer" ) //Lock allows to lock xds-server avoiding restart type Lock struct { sc.Mutex LockCpt int } // MonitorUpdates try to update xds-server package at first // then monitor updates func MonitorUpdates(ctx *Context) { UpdateXdsServer(ctx) //try to update at startup updateTime, err := time.ParseDuration(ctx.Config.FileConf.XdsSrvUpdateTime) if err != nil { ctx.Log.Errorf("Wrong format type of XdsSrvUpdateTime\n"+ "err=%v \n"+ "Valid time units are ns, us, ms, s, m, h\n"+ "Here an example: 1h10m10s", err) } else { ctx.Log.Infof("Update time for package xds-server is %v", updateTime) go func(ctx *Context) { for { currentUpdateTime := updateTime for currentUpdateTime > 0*time.Minute { time.Sleep(currentUpdateTime) currentUpdateTime = UpdateXdsServer(ctx) } } }(ctx) } } func getScriptsDir(ctx *Context) string { scriptsDir := ctx.Config.FileConf.XdsSrvUpdateScriptsDir if !common.Exists(scriptsDir) { // allow to use scripts/sdk in debug mode scriptsDir = filepath.Join(filepath.Dir(ctx.Config.FileConf.XdsSrvUpdateScriptsDir), "scripts", "package-update") if !common.Exists(scriptsDir) { ctx.Log.Errorf("scripts directory doesn't exist (%v)", scriptsDir) } } return scriptsDir } // UpdateXdsServer launches update package xds-server script func UpdateXdsServer(ctx *Context) time.Duration { timeToRestartIfBusy := 0 * time.Minute scriptsDir := getScriptsDir(ctx) ctx.Log.Infof("Trying to update xds-server package, "+ "package-update scripts dir: %s", scriptsDir) cmd := exec.Command(path.Join(scriptsDir, scriptXdsSrvUpdate)) _, err := cmd.CombinedOutput() if err != nil { ctx.Log.Errorf("Cannot update xds-server package err=%v", err) return 0 } cmd = exec.Command(path.Join(scriptsDir, scriptXdsSrvRestart)) ctx.lock.Lock() if ctx.lock.LockCpt == 0 { //no action in progress _, err = cmd.CombinedOutput() if err != nil { ctx.Log.Errorf("Cannot restart xds-server service err=%v", err) return 0 } } else { timeToRestartIfBusy = 1 * time.Minute ctx.Log.Infof("Cannot restart xds-server service because "+ "xds-server has an action in progress, trying to restart in a %v", timeToRestartIfBusy) } ctx.lock.Unlock() return timeToRestartIfBusy } // GetXdsSrvUpdate gets information about package func GetXdsSrvUpdate(ctx *Context) xsapiv1.XdsSrvUpdate { var xdsSrvUpdate xsapiv1.XdsSrvUpdate scriptsDir := getScriptsDir(ctx) //exec getXdsSrvUpdate script cmd := exec.Command(path.Join(scriptsDir, scriptGetXdsSrvUpdate)) stdout, err := cmd.CombinedOutput() if err != nil { ctx.Log.Errorf("Cannot get xds-server package information err=%v", err) return xdsSrvUpdate } //stdout is formatting with 'version: xxxxx' outputs := strings.Split(string(stdout[:]), "\n") installedVersion := strings.Split(outputs[0], ": ")[1] candidateVersion := strings.Split(outputs[1], ": ")[1] ctx.Log.Infof("XdsSrvUpdate: candidateVersion:%v installedVersion:%v", candidateVersion, installedVersion) xdsSrvUpdate = xsapiv1.XdsSrvUpdate{ CurrentVersion: installedVersion, NewerVersion: candidateVersion, UpdateTime: ctx.Config.FileConf.XdsSrvUpdateTime, } return xdsSrvUpdate }