d5c74ef00b0facacc2d502f8a577d32569e59fe1
[src/xds/xds-agent.git] / lib / syncthing / stfolder.go
1 package st
2
3 import (
4         "encoding/json"
5         "fmt"
6         "strings"
7
8         common "github.com/iotbzh/xds-common/golib"
9         "github.com/iotbzh/xds-server/lib/folder"
10         stconfig "github.com/syncthing/syncthing/lib/config"
11         "github.com/syncthing/syncthing/lib/protocol"
12 )
13
14 // FIXME remove and use an interface on xdsconfig.FolderConfig
15 type FolderChangeArg struct {
16         ID           string
17         Label        string
18         RelativePath string
19         SyncThingID  string
20         ShareRootDir string
21 }
22
23 // FolderLoadFromStConfig Load/Retrieve folder config from syncthing database
24 func (s *SyncThing) FolderLoadFromStConfig(f *[]folder.FolderConfig) error {
25
26         defaultSdk := "" // cannot know which was the default sdk
27
28         stCfg, err := s.ConfigGet()
29         if err != nil {
30                 return err
31         }
32         if len(stCfg.Devices) < 1 {
33                 return fmt.Errorf("Cannot load syncthing config: no device defined")
34         }
35         devID := stCfg.Devices[0].DeviceID.String()
36         if devID == s.MyID {
37                 if len(stCfg.Devices) < 2 {
38                         return fmt.Errorf("Cannot load syncthing config: no valid device found")
39                 }
40                 devID = stCfg.Devices[1].DeviceID.String()
41         }
42
43         for _, stFld := range stCfg.Folders {
44                 /*
45                         cliPath := strings.TrimPrefix(stFld.Path, s.conf.FileConf.ShareRootDir)
46                         if cliPath == "" {
47                                 cliPath = stFld.Path
48                         }*/
49                 cliPath := stFld.Path
50                 *f = append(*f, folder.FolderConfig{
51                         ID:            stFld.ID,
52                         Label:         stFld.Label,
53                         ClientPath:    strings.TrimRight(cliPath, "/"),
54                         Type:          folder.TypeCloudSync,
55                         Status:        folder.StatusDisable,
56                         DefaultSdk:    defaultSdk,
57                         RootPath:      "", //s.conf.FileConf.ShareRootDir,
58                         DataCloudSync: folder.CloudSyncConfig{SyncThingID: devID},
59                 })
60         }
61
62         return nil
63 }
64
65 // FolderChange is called when configuration has changed
66 func (s *SyncThing) FolderChange(f FolderChangeArg) (string, error) {
67
68         // Get current config
69         stCfg, err := s.ConfigGet()
70         if err != nil {
71                 s.log.Errorln(err)
72                 return "", err
73         }
74
75         // Add new Device if needed
76         var devID protocol.DeviceID
77         if err := devID.UnmarshalText([]byte(f.SyncThingID)); err != nil {
78                 s.log.Errorf("not a valid device id (err %v)", err)
79                 return "", err
80         }
81
82         newDevice := stconfig.DeviceConfiguration{
83                 DeviceID:  devID,
84                 Name:      f.SyncThingID,
85                 Addresses: []string{"dynamic"},
86         }
87
88         var found = false
89         for _, device := range stCfg.Devices {
90                 if device.DeviceID == devID {
91                         found = true
92                         break
93                 }
94         }
95         if !found {
96                 stCfg.Devices = append(stCfg.Devices, newDevice)
97         }
98
99         // Add or update Folder settings
100         var label, id string
101         if label = f.Label; label == "" {
102                 label = strings.Split(id, "/")[0]
103         }
104         if id = f.ID; id == "" {
105                 id = f.SyncThingID[0:15] + "_" + label
106         }
107
108         // Resolve local path
109         pathCli, err := common.ResolveEnvVar(f.RelativePath)
110         if err != nil {
111                 pathCli = f.RelativePath
112         }
113         // SEB still need ShareRootDir ? a sup
114         // pathCli := filepath.Join(f.ShareRootDir, f.RelativePath)
115
116         folder := stconfig.FolderConfiguration{
117                 ID:            id,
118                 Label:         label,
119                 Path:          pathCli,
120                 AutoNormalize: true,
121         }
122
123         /* TODO - add it ?
124         if s.conf.FileConf.SThgConf.RescanIntervalS > 0 {
125                 folder.RescanIntervalS = s.conf.FileConf.SThgConf.RescanIntervalS
126         }
127         */
128
129         folder.Devices = append(folder.Devices, stconfig.FolderDeviceConfiguration{
130                 DeviceID: newDevice.DeviceID,
131         })
132
133         found = false
134         var fld stconfig.FolderConfiguration
135         for _, fld = range stCfg.Folders {
136                 if folder.ID == fld.ID {
137                         fld = folder
138                         found = true
139                         break
140                 }
141         }
142         if !found {
143                 stCfg.Folders = append(stCfg.Folders, folder)
144                 fld = stCfg.Folders[0]
145         }
146
147         err = s.ConfigSet(stCfg)
148         if err != nil {
149                 s.log.Errorln(err)
150         }
151
152         return id, nil
153 }
154
155 // FolderDelete is called to delete a folder config
156 func (s *SyncThing) FolderDelete(id string) error {
157         // Get current config
158         stCfg, err := s.ConfigGet()
159         if err != nil {
160                 s.log.Errorln(err)
161                 return err
162         }
163
164         for i, fld := range stCfg.Folders {
165                 if id == fld.ID {
166                         stCfg.Folders = append(stCfg.Folders[:i], stCfg.Folders[i+1:]...)
167                         err = s.ConfigSet(stCfg)
168                         if err != nil {
169                                 s.log.Errorln(err)
170                                 return err
171                         }
172                 }
173         }
174
175         return nil
176 }
177
178 // FolderConfigGet Returns the configuration of a specific folder
179 func (s *SyncThing) FolderConfigGet(folderID string) (stconfig.FolderConfiguration, error) {
180         fc := stconfig.FolderConfiguration{}
181         if folderID == "" {
182                 return fc, fmt.Errorf("folderID not set")
183         }
184         cfg, err := s.ConfigGet()
185         if err != nil {
186                 return fc, err
187         }
188         for _, f := range cfg.Folders {
189                 if f.ID == folderID {
190                         fc = f
191                         return fc, nil
192                 }
193         }
194         return fc, fmt.Errorf("id not found")
195 }
196
197 // FolderStatus Returns all information about the current
198 func (s *SyncThing) FolderStatus(folderID string) (*FolderStatus, error) {
199         var data []byte
200         var res FolderStatus
201         if folderID == "" {
202                 return nil, fmt.Errorf("folderID not set")
203         }
204         if err := s.client.HTTPGet("db/status?folder="+folderID, &data); err != nil {
205                 return nil, err
206         }
207         if err := json.Unmarshal(data, &res); err != nil {
208                 return nil, err
209         }
210         return &res, nil
211 }
212
213 // IsFolderInSync Returns true when folder is in sync
214 func (s *SyncThing) IsFolderInSync(folderID string) (bool, error) {
215         sts, err := s.FolderStatus(folderID)
216         if err != nil {
217                 return false, err
218         }
219         return sts.NeedBytes == 0 && sts.State == "idle", nil
220 }
221
222 // FolderScan Request immediate folder scan.
223 // Scan all folders if folderID param is empty
224 func (s *SyncThing) FolderScan(folderID string, subpath string) error {
225         url := "db/scan"
226         if folderID != "" {
227                 url += "?folder=" + folderID
228
229                 if subpath != "" {
230                         url += "&sub=" + subpath
231                 }
232         }
233         return s.client.HTTPPost(url, "")
234 }