LEFT | RIGHT |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package maas | 4 package maas |
5 | 5 |
6 import ( | 6 import ( |
7 "bytes" | 7 "bytes" |
8 "encoding/base64" | 8 "encoding/base64" |
9 "fmt" | 9 "fmt" |
10 "io" | 10 "io" |
11 "io/ioutil" | 11 "io/ioutil" |
12 "net/url" | 12 "net/url" |
13 "sort" | 13 "sort" |
14 "sync" | 14 "sync" |
15 | 15 |
16 "launchpad.net/gomaasapi" | 16 "launchpad.net/gomaasapi" |
17 | 17 |
18 » "launchpad.net/juju-core/environs" | 18 » "launchpad.net/juju-core/environs/storage" |
19 "launchpad.net/juju-core/errors" | 19 "launchpad.net/juju-core/errors" |
20 "launchpad.net/juju-core/utils" | 20 "launchpad.net/juju-core/utils" |
21 ) | 21 ) |
22 | 22 |
23 type maasStorage struct { | 23 type maasStorage struct { |
24 // Mutex protects the "*Unlocked" fields. | 24 // Mutex protects the "*Unlocked" fields. |
25 sync.Mutex | 25 sync.Mutex |
26 | 26 |
27 // The Environ that this Storage is for. | 27 // The Environ that this Storage is for. |
28 environUnlocked *maasEnviron | 28 environUnlocked *maasEnviron |
29 | 29 |
30 // Reference to the URL on the API where files are stored. | 30 // Reference to the URL on the API where files are stored. |
31 maasClientUnlocked gomaasapi.MAASObject | 31 maasClientUnlocked gomaasapi.MAASObject |
32 } | 32 } |
33 | 33 |
34 var _ environs.Storage = (*maasStorage)(nil) | 34 var _ storage.Storage = (*maasStorage)(nil) |
35 | 35 |
36 func NewStorage(env *maasEnviron) environs.Storage { | 36 func NewStorage(env *maasEnviron) storage.Storage { |
37 storage := new(maasStorage) | 37 storage := new(maasStorage) |
38 storage.environUnlocked = env | 38 storage.environUnlocked = env |
39 storage.maasClientUnlocked = env.getMAASClient().GetSubObject("files") | 39 storage.maasClientUnlocked = env.getMAASClient().GetSubObject("files") |
40 return storage | 40 return storage |
41 } | 41 } |
42 | 42 |
43 // getSnapshot returns a consistent copy of a maasStorage. Use this if you | 43 // getSnapshot returns a consistent copy of a maasStorage. Use this if you |
44 // need a consistent view of the object's entire state, without having to | 44 // need a consistent view of the object's entire state, without having to |
45 // lock the object the whole time. | 45 // lock the object the whole time. |
46 // | 46 // |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 func (stor *maasStorage) Remove(name string) error { | 189 func (stor *maasStorage) Remove(name string) error { |
190 // The only thing that can go wrong here, really, is that the file | 190 // The only thing that can go wrong here, really, is that the file |
191 // does not exist. But deletion is idempotent: deleting a file that | 191 // does not exist. But deletion is idempotent: deleting a file that |
192 // is no longer there anyway is success, not failure. | 192 // is no longer there anyway is success, not failure. |
193 stor.getSnapshot().maasClientUnlocked.GetSubObject(name).Delete() | 193 stor.getSnapshot().maasClientUnlocked.GetSubObject(name).Delete() |
194 return nil | 194 return nil |
195 } | 195 } |
196 | 196 |
197 // RemoveAll is specified in the StorageWriter interface. | 197 // RemoveAll is specified in the StorageWriter interface. |
198 func (stor *maasStorage) RemoveAll() error { | 198 func (stor *maasStorage) RemoveAll() error { |
199 » names, err := environs.DefaultList(stor, "") | 199 » names, err := storage.ListWithDefaultRetry(stor, "") |
200 if err != nil { | 200 if err != nil { |
201 return err | 201 return err |
202 } | 202 } |
203 // Remove all the objects in parallel so that we incur less round-trips. | 203 // Remove all the objects in parallel so that we incur less round-trips. |
204 // If we're in danger of having hundreds of objects, | 204 // If we're in danger of having hundreds of objects, |
205 // we'll want to change this to limit the number | 205 // we'll want to change this to limit the number |
206 // of concurrent operations. | 206 // of concurrent operations. |
207 var wg sync.WaitGroup | 207 var wg sync.WaitGroup |
208 wg.Add(len(names)) | 208 wg.Add(len(names)) |
209 errc := make(chan error, len(names)) | 209 errc := make(chan error, len(names)) |
210 for _, name := range names { | 210 for _, name := range names { |
211 name := name | 211 name := name |
212 go func() { | 212 go func() { |
213 defer wg.Done() | 213 defer wg.Done() |
214 if err := stor.Remove(name); err != nil { | 214 if err := stor.Remove(name); err != nil { |
215 errc <- err | 215 errc <- err |
216 } | 216 } |
217 }() | 217 }() |
218 } | 218 } |
219 wg.Wait() | 219 wg.Wait() |
220 select { | 220 select { |
221 case err := <-errc: | 221 case err := <-errc: |
222 return fmt.Errorf("cannot delete all provider state: %v", err) | 222 return fmt.Errorf("cannot delete all provider state: %v", err) |
223 default: | 223 default: |
224 } | 224 } |
225 return nil | 225 return nil |
226 } | 226 } |
LEFT | RIGHT |