2ad6859ac792557bb9f1b07a01750834938b8caa
[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         stClientID := f.SyncThingID
76         // Add new Device if needed
77         var devID protocol.DeviceID
78         if err := devID.UnmarshalText([]byte(stClientID)); err != nil {
79                 s.log.Errorf("not a valid device id (err %v)", err)
80                 return "", err
81         }
82
83         newDevice := stconfig.DeviceConfiguration{
84                 DeviceID:  devID,
85                 Name:      stClientID,
86                 Addresses: []string{"dynamic"},
87         }
88
89         var found = false
90         for _, device := range stCfg.Devices {
91                 if device.DeviceID == devID {
92                         found = true
93                         break
94                 }
95         }
96         if !found {
97                 stCfg.Devices = append(stCfg.Devices, newDevice)
98         }
99
100         // Add or update Folder settings
101         var label, id string
102         if label = f.Label; label == "" {
103                 label = strings.Split(id, "/")[0]
104         }
105         if id = f.ID; id == "" {
106                 id = stClientID[0:15] + "_" + label
107         }
108
109         // Resolve local path
110         pathCli, err := common.ResolveEnvVar(f.RelativePath)
111         if err != nil {
112                 pathCli = f.RelativePath
113         }
114         // SEB still need ShareRootDir ? a sup
115         // pathCli := filepath.Join(f.ShareRootDir, f.RelativePath)
116
117         folder := stconfig.FolderConfiguration{
118                 ID:            id,
119                 Label:         label,
120                 Path:          pathCli,
121                 AutoNormalize: true,
122         }
123
124         /* TODO - add it ?
125         if s.conf.FileConf.SThgConf.RescanIntervalS > 0 {
126                 folder.RescanIntervalS = s.conf.FileConf.SThgConf.RescanIntervalS
127         }
128         */
129
130         folder.Devices = append(folder.Devices, stconfig.FolderDeviceConfiguration{
131                 DeviceID: newDevice.DeviceID,
132         })
133
134         found = false
135         var fld stconfig.FolderConfiguration
136         for _, fld = range stCfg.Folders {
137                 if folder.ID == fld.ID {
138                         fld = folder
139                         found = true
140                         break
141                 }
142         }
143         if !found {
144                 stCfg.Folders = append(stCfg.Folders, folder)
145                 fld = stCfg.Folders[0]
146         }
147
148         err = s.ConfigSet(stCfg)
149         if err != nil {
150                 s.log.Errorln(err)
151         }
152
153         return id, nil
154 }
155
156 // FolderDelete is called to delete a folder config
157 func (s *SyncThing) FolderDelete(id string) error {
158         // Get current config
159         stCfg, err := s.ConfigGet()
160         if err != nil {
161                 s.log.Errorln(err)
162                 return err
163         }
164
165         for i, fld := range stCfg.Folders {
166                 if id == fld.ID {
167                         stCfg.Folders = append(stCfg.Folders[:i], stCfg.Folders[i+1:]...)
168                         err = s.ConfigSet(stCfg)
169                         if err != nil {
170                                 s.log.Errorln(err)
171                                 return err
172                         }
173                 }
174         }
175
176         return nil
177 }
178
179 // FolderConfigGet Returns the configuration of a specific folder
180 func (s *SyncThing) FolderConfigGet(folderID string) (stconfig.FolderConfiguration, error) {
181         fc := stconfig.FolderConfiguration{}
182         if folderID == "" {
183                 return fc, fmt.Errorf("folderID not set")
184         }
185         cfg, err := s.ConfigGet()
186         if err != nil {
187                 return fc, err
188         }
189         for _, f := range cfg.Folders {
190                 if f.ID == folderID {
191                         fc = f
192                         return fc, nil
193                 }
194         }
195         return fc, fmt.Errorf("id not found")
196 }
197
198 // FolderStatus Returns all information about the current
199 func (s *SyncThing) FolderStatus(folderID string) (*FolderStatus, error) {
200         var data []byte
201         var res FolderStatus
202         if folderID == "" {
203                 return nil, fmt.Errorf("folderID not set")
204         }
205         if err := s.client.HTTPGet("db/status?folder="+folderID, &data); err != nil {
206                 return nil, err
207         }
208         if err := json.Unmarshal(data, &res); err != nil {
209                 return nil, err
210         }
211         return &res, nil
212 }
213
214 // IsFolderInSync Returns true when folder is in sync
215 func (s *SyncThing) IsFolderInSync(folderID string) (bool, error) {
216         sts, err := s.FolderStatus(folderID)
217         if err != nil {
218                 return false, err
219         }
220         return sts.NeedBytes == 0 && sts.State == "idle", nil
221 }
222
223 // FolderScan Request immediate folder scan.
224 // Scan all folders if folderID param is empty
225 func (s *SyncThing) FolderScan(folderID string, subpath string) error {
226         url := "db/scan"
227         if folderID != "" {
228                 url += "?folder=" + folderID
229
230                 if subpath != "" {
231                         url += "&sub=" + subpath
232                 }
233         }
234         return s.client.HTTPPost(url, "")
235 }