diff options
Diffstat (limited to 'lib/xdsserver/xds-server-update.go')
-rw-r--r-- | lib/xdsserver/xds-server-update.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/xdsserver/xds-server-update.go b/lib/xdsserver/xds-server-update.go new file mode 100644 index 0000000..cd9d6b1 --- /dev/null +++ b/lib/xdsserver/xds-server-update.go @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author Clément Bénier <clement.benier@iot.bzh> + * + * 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/xdsconfig" + "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1" +) + +const ( + scriptXdsSrvUpdate = "updateXdsServerPackage" + scriptGetXdsSrvUpdate = "getXdsServerPackage" + scriptXdsSrvRestart = "restartXdsServer" +) + +//LockXdsUpdate allows to lock xds-server avoiding restart +type LockXdsUpdate struct { + sc.Mutex + LockCpt int +} + +//LockXdsUpdateCounter Inc/decrement lock counter +func LockXdsUpdateCounter(ctx *Context, inc bool) { + if inc { + //paranoia lock count > 10 + if ctx.lockXdsSrvUpdate.LockCpt > 10 { + ctx.Log.Errorf("lock counter value is abnormally high: LockCpt=%v", ctx.lockXdsSrvUpdate.LockCpt) + } + ctx.lockXdsSrvUpdate.Lock() + ctx.lockXdsSrvUpdate.LockCpt++ + ctx.lockXdsSrvUpdate.Unlock() + } else { + //paranoia lock count < 0 + if ctx.lockXdsSrvUpdate.LockCpt <= 0 { + ctx.Log.Errorf("lock counter value is lower than 0: LockCpt=%v", ctx.lockXdsSrvUpdate.LockCpt) + return + } + ctx.lockXdsSrvUpdate.Lock() + ctx.lockXdsSrvUpdate.LockCpt-- + ctx.lockXdsSrvUpdate.Unlock() + } +} + +//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\n"+ + "So, default value is set %v", err, xdsconfig.DefaultXdsSrvUpdateTime) + updateTime, _ = time.ParseDuration(xdsconfig.DefaultXdsSrvUpdateTime) + } + ctx.Log.Infof("Update time for package xds-server is %v", updateTime) + go func(ctx *Context) { + for { + currentUpdateTime := updateTime + for currentUpdateTime > 0 { + time.Sleep(currentUpdateTime) + currentUpdateTime = UpdateXdsServer(ctx) + } + } + }(ctx) +} + +func getScriptsDir(ctx *Context) string { + scriptsDir := ctx.Config.FileConf.XdsUtilsScriptsDir + if !common.Exists(scriptsDir) { + // allow to use scripts/xds-utils when debugging with vscode(EXEPATH=WORKSPACE) + scriptsDir = filepath.Join(filepath.Dir(ctx.Config.FileConf.XdsUtilsScriptsDir), "scripts", "xds-utils") + 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, "+ + "xds-utils scripts dir: %s", scriptsDir) + + //launch xds-server update package script + 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 + } + + //launch xds-server restart script + cmd = exec.Command(path.Join(scriptsDir, scriptXdsSrvRestart)) + ctx.lockXdsSrvUpdate.Lock() + if ctx.lockXdsSrvUpdate.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.lockXdsSrvUpdate.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 +} |