+/*
+ * Copyright (C) 2017-2018 "IoT.bzh"
+ * Author Sebastien Douheret <sebastien@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/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
+}