Use go module as dependency tool instead of glide
[src/xds/xds-server.git] / lib / xdsserver / xds-server-update.go
1 /*
2  * Copyright (C) 2018 "IoT.bzh"
3  * Author Clément Bénier <clement.benier@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package xdsserver
19
20 import (
21         "os/exec"
22         "path"
23         "path/filepath"
24         "strings"
25         sc "sync"
26         "time"
27
28         common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git"
29         "gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xdsconfig"
30         "gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xsapiv1"
31 )
32
33 const (
34         scriptXdsSrvUpdate    = "updateXdsServerPackage"
35         scriptGetXdsSrvUpdate = "getXdsServerPackage"
36         scriptXdsSrvRestart   = "restartXdsServer"
37 )
38
39 //LockXdsUpdate allows to lock xds-server avoiding restart
40 type LockXdsUpdate struct {
41         sc.Mutex
42         LockCpt int
43 }
44
45 //LockXdsUpdateCounter Inc/decrement lock counter
46 func LockXdsUpdateCounter(ctx *Context, inc bool) {
47         if inc {
48                 //paranoia lock count > 10
49                 if ctx.lockXdsSrvUpdate.LockCpt > 10 {
50                         ctx.Log.Errorf("lock counter value is abnormally high: LockCpt=%v", ctx.lockXdsSrvUpdate.LockCpt)
51                 }
52                 ctx.lockXdsSrvUpdate.Lock()
53                 ctx.lockXdsSrvUpdate.LockCpt++
54                 ctx.lockXdsSrvUpdate.Unlock()
55         } else {
56                 //paranoia lock count < 0
57                 if ctx.lockXdsSrvUpdate.LockCpt <= 0 {
58                         ctx.Log.Errorf("lock counter value is lower than 0: LockCpt=%v", ctx.lockXdsSrvUpdate.LockCpt)
59                         return
60                 }
61                 ctx.lockXdsSrvUpdate.Lock()
62                 ctx.lockXdsSrvUpdate.LockCpt--
63                 ctx.lockXdsSrvUpdate.Unlock()
64         }
65 }
66
67 //MonitorUpdates try to update xds-server package at first
68 // then monitor updates
69 func MonitorUpdates(ctx *Context) {
70         UpdateXdsServer(ctx) //try to update at startup
71
72         updateTime, err := time.ParseDuration(ctx.Config.FileConf.XdsSrvUpdateTime)
73         if err != nil {
74                 ctx.Log.Errorf("Wrong format type of XdsSrvUpdateTime\n"+
75                         "err=%v \n"+
76                         "Valid time units are ns, us, ms, s, m, h\n"+
77                         "Here an example: 1h10m10s\n"+
78                         "So, default value is set %v", err, xdsconfig.DefaultXdsSrvUpdateTime)
79                 updateTime, _ = time.ParseDuration(xdsconfig.DefaultXdsSrvUpdateTime)
80         }
81         ctx.Log.Infof("Update time for package xds-server is %v", updateTime)
82         go func(ctx *Context) {
83                 for {
84                         currentUpdateTime := updateTime
85                         for currentUpdateTime > 0 {
86                                 time.Sleep(currentUpdateTime)
87                                 currentUpdateTime = UpdateXdsServer(ctx)
88                         }
89                 }
90         }(ctx)
91 }
92
93 func getScriptsDir(ctx *Context) string {
94         scriptsDir := ctx.Config.FileConf.XdsUtilsScriptsDir
95         if !common.Exists(scriptsDir) {
96                 // allow to use scripts/xds-utils when debugging with vscode(EXEPATH=WORKSPACE)
97                 scriptsDir = filepath.Join(filepath.Dir(ctx.Config.FileConf.XdsUtilsScriptsDir), "scripts", "xds-utils")
98                 if !common.Exists(scriptsDir) {
99                         ctx.Log.Errorf("scripts directory doesn't exist (%v)", scriptsDir)
100                 }
101         }
102         return scriptsDir
103 }
104
105 // UpdateXdsServer launches update package xds-server script
106 func UpdateXdsServer(ctx *Context) time.Duration {
107         timeToRestartIfBusy := 0 * time.Minute
108         scriptsDir := getScriptsDir(ctx)
109
110         ctx.Log.Infof("Trying to update xds-server package, "+
111                 "xds-utils scripts dir: %s", scriptsDir)
112
113         //launch xds-server update package script
114         cmd := exec.Command(path.Join(scriptsDir, scriptXdsSrvUpdate))
115         _, err := cmd.CombinedOutput()
116         if err != nil {
117                 ctx.Log.Errorf("Cannot update xds-server package err=%v", err)
118                 return 0
119         }
120
121         //launch xds-server restart script
122         cmd = exec.Command(path.Join(scriptsDir, scriptXdsSrvRestart))
123         ctx.lockXdsSrvUpdate.Lock()
124         if ctx.lockXdsSrvUpdate.LockCpt == 0 { //no action in progress
125                 _, err = cmd.CombinedOutput()
126                 if err != nil {
127                         ctx.Log.Errorf("Cannot restart xds-server service err=%v", err)
128                         return 0
129                 }
130         } else {
131                 timeToRestartIfBusy = 1 * time.Minute
132                 ctx.Log.Infof("Cannot restart xds-server service because "+
133                         "xds-server has an action in progress, trying to restart in a %v", timeToRestartIfBusy)
134         }
135         ctx.lockXdsSrvUpdate.Unlock()
136
137         return timeToRestartIfBusy
138 }
139
140 // GetXdsSrvUpdate gets information about package
141 func GetXdsSrvUpdate(ctx *Context) xsapiv1.XdsSrvUpdate {
142         var xdsSrvUpdate xsapiv1.XdsSrvUpdate
143         scriptsDir := getScriptsDir(ctx)
144
145         //exec getXdsSrvUpdate script
146         cmd := exec.Command(path.Join(scriptsDir, scriptGetXdsSrvUpdate))
147         stdout, err := cmd.CombinedOutput()
148         if err != nil {
149                 ctx.Log.Errorf("Cannot get xds-server package information err=%v", err)
150                 return xdsSrvUpdate
151         }
152
153         //stdout is formatting with 'version: xxxxx'
154         outputs := strings.Split(string(stdout[:]), "\n")
155         installedVersion := strings.Split(outputs[0], ": ")[1]
156         candidateVersion := strings.Split(outputs[1], ": ")[1]
157         ctx.Log.Infof("XdsSrvUpdate: candidateVersion:%v installedVersion:%v", candidateVersion, installedVersion)
158         xdsSrvUpdate = xsapiv1.XdsSrvUpdate{
159                 CurrentVersion: installedVersion,
160                 NewerVersion:   candidateVersion,
161                 UpdateTime:     ctx.Config.FileConf.XdsSrvUpdateTime,
162         }
163         return xdsSrvUpdate
164 }