update xds-server package in docker
[src/xds/xds-server.git] / lib / xdsserver / xds-server-update.go
1 /*
2  * Copyright (C) 2017-2018 "IoT.bzh"
3  * Author Sebastien Douheret <sebastien@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/golib"
29         "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
30 )
31
32 const (
33         scriptXdsSrvUpdate    = "updateXdsServerPackage"
34         scriptGetXdsSrvUpdate = "getXdsServerPackage"
35         scriptXdsSrvRestart   = "restartXdsServer"
36 )
37
38 //Lock allows to lock xds-server avoiding restart
39 type Lock struct {
40         sc.Mutex
41         LockCpt int
42 }
43
44 // MonitorUpdates try to update xds-server package at first
45 // then monitor updates
46 func MonitorUpdates(ctx *Context) {
47         UpdateXdsServer(ctx) //try to update at startup
48
49         updateTime, err := time.ParseDuration(ctx.Config.FileConf.XdsSrvUpdateTime)
50         if err != nil {
51                 ctx.Log.Errorf("Wrong format type of XdsSrvUpdateTime\n"+
52                         "err=%v \n"+
53                         "Valid time units are ns, us, ms, s, m, h\n"+
54                         "Here an example: 1h10m10s", err)
55         } else {
56                 ctx.Log.Infof("Update time for package xds-server is %v", updateTime)
57                 go func(ctx *Context) {
58                         for {
59                                 currentUpdateTime := updateTime
60                                 for currentUpdateTime > 0*time.Minute {
61                                         time.Sleep(currentUpdateTime)
62                                         currentUpdateTime = UpdateXdsServer(ctx)
63                                 }
64                         }
65                 }(ctx)
66         }
67 }
68
69 func getScriptsDir(ctx *Context) string {
70         scriptsDir := ctx.Config.FileConf.XdsSrvUpdateScriptsDir
71         if !common.Exists(scriptsDir) {
72                 // allow to use scripts/sdk in debug mode
73                 scriptsDir = filepath.Join(filepath.Dir(ctx.Config.FileConf.XdsSrvUpdateScriptsDir), "scripts", "package-update")
74                 if !common.Exists(scriptsDir) {
75                         ctx.Log.Errorf("scripts directory doesn't exist (%v)", scriptsDir)
76                 }
77         }
78         return scriptsDir
79 }
80
81 // UpdateXdsServer launches update package xds-server script
82 func UpdateXdsServer(ctx *Context) time.Duration {
83         timeToRestartIfBusy := 0 * time.Minute
84         scriptsDir := getScriptsDir(ctx)
85
86         ctx.Log.Infof("Trying to update xds-server package, "+
87                 "package-update scripts dir: %s", scriptsDir)
88
89         cmd := exec.Command(path.Join(scriptsDir, scriptXdsSrvUpdate))
90         _, err := cmd.CombinedOutput()
91         if err != nil {
92                 ctx.Log.Errorf("Cannot update xds-server package err=%v", err)
93                 return 0
94         }
95
96         cmd = exec.Command(path.Join(scriptsDir, scriptXdsSrvRestart))
97         ctx.lock.Lock()
98         if ctx.lock.LockCpt == 0 { //no action in progress
99                 _, err = cmd.CombinedOutput()
100                 if err != nil {
101                         ctx.Log.Errorf("Cannot restart xds-server service err=%v", err)
102                         return 0
103                 }
104         } else {
105                 timeToRestartIfBusy = 1 * time.Minute
106                 ctx.Log.Infof("Cannot restart xds-server service because "+
107                         "xds-server has an action in progress, trying to restart in a %v", timeToRestartIfBusy)
108         }
109         ctx.lock.Unlock()
110
111         return timeToRestartIfBusy
112 }
113
114 // GetXdsSrvUpdate gets information about package
115 func GetXdsSrvUpdate(ctx *Context) xsapiv1.XdsSrvUpdate {
116         var xdsSrvUpdate xsapiv1.XdsSrvUpdate
117         scriptsDir := getScriptsDir(ctx)
118
119         //exec getXdsSrvUpdate script
120         cmd := exec.Command(path.Join(scriptsDir, scriptGetXdsSrvUpdate))
121         stdout, err := cmd.CombinedOutput()
122         if err != nil {
123                 ctx.Log.Errorf("Cannot get xds-server package information err=%v", err)
124                 return xdsSrvUpdate
125         }
126
127         //stdout is formatting with 'version: xxxxx'
128         outputs := strings.Split(string(stdout[:]), "\n")
129         installedVersion := strings.Split(outputs[0], ": ")[1]
130         candidateVersion := strings.Split(outputs[1], ": ")[1]
131         ctx.Log.Infof("XdsSrvUpdate: candidateVersion:%v installedVersion:%v", candidateVersion, installedVersion)
132         xdsSrvUpdate = xsapiv1.XdsSrvUpdate{
133                 CurrentVersion: installedVersion,
134                 NewerVersion:   candidateVersion,
135                 UpdateTime:     ctx.Config.FileConf.XdsSrvUpdateTime,
136         }
137         return xdsSrvUpdate
138 }