~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/state/resources_persistence.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
        "github.com/juju/juju/resource"
16
16
)
17
17
 
 
18
const (
 
19
        // CleanupKindResourceBlob identifies the cleanup kind
 
20
        // for resource blobs.
 
21
        CleanupKindResourceBlob = "resourceBlob"
 
22
)
 
23
 
18
24
// ResourcePersistenceBase exposes the core persistence functionality
19
25
// needed for resources.
20
26
type ResourcePersistenceBase interface {
30
36
        // function. It may be retried several times.
31
37
        Run(transactions jujutxn.TransactionSource) error
32
38
 
 
39
        // ServiceExistsOps returns the operations that verify that the
 
40
        // identified service exists.
 
41
        ServiceExistsOps(serviceID string) []txn.Op
 
42
 
33
43
        // IncCharmModifiedVersionOps returns the operations necessary to increment
34
44
        // the CharmModifiedVersion field for the given service.
35
45
        IncCharmModifiedVersionOps(serviceID string) []txn.Op
 
46
 
 
47
        // NewCleanupOp creates a mgo transaction operation that queues up
 
48
        // some cleanup action in state.
 
49
        NewCleanupOp(kind, prefix string) txn.Op
36
50
}
37
51
 
38
52
// ResourcePersistence provides the persistence functionality for the
53
67
func (p ResourcePersistence) ListResources(serviceID string) (resource.ServiceResources, error) {
54
68
        logger.Tracef("listing all resources for service %q", serviceID)
55
69
 
56
 
        // TODO(ericsnow) Ensure that the service is still there?
57
 
 
58
70
        docs, err := p.resources(serviceID)
59
71
        if err != nil {
60
72
                return resource.ServiceResources{}, errors.Trace(err)
62
74
 
63
75
        store := map[string]charmresource.Resource{}
64
76
        units := map[names.UnitTag][]resource.Resource{}
 
77
        downloadProgress := make(map[names.UnitTag]map[string]int64)
65
78
 
66
79
        var results resource.ServiceResources
67
80
        for _, doc := range docs {
82
95
                        continue
83
96
                }
84
97
                tag := names.NewUnitTag(doc.UnitID)
85
 
                units[tag] = append(units[tag], res)
 
98
                if doc.PendingID == "" {
 
99
                        units[tag] = append(units[tag], res)
 
100
                }
 
101
                if doc.DownloadProgress != nil {
 
102
                        if downloadProgress[tag] == nil {
 
103
                                downloadProgress[tag] = make(map[string]int64)
 
104
                        }
 
105
                        downloadProgress[tag][doc.Name] = *doc.DownloadProgress
 
106
                }
86
107
        }
87
108
        for _, res := range results.Resources {
88
109
                storeRes := store[res.Name]
90
111
        }
91
112
        for tag, res := range units {
92
113
                results.UnitResources = append(results.UnitResources, resource.UnitResources{
93
 
                        Tag:       tag,
94
 
                        Resources: res,
 
114
                        Tag:              tag,
 
115
                        Resources:        res,
 
116
                        DownloadProgress: downloadProgress[tag],
95
117
                })
96
118
        }
97
119
        return results, nil
178
200
        // so then the following line is unnecessary.
179
201
        stored.Resource = res
180
202
 
181
 
        // TODO(ericsnow) Ensure that the service is still there?
182
 
 
183
203
        if err := res.Validate(); err != nil {
184
204
                return errors.Annotate(err, "bad resource")
185
205
        }
196
216
                        // Either insert or update will work so we should not get here.
197
217
                        return nil, errors.New("setting the resource failed")
198
218
                }
 
219
                if stored.PendingID == "" {
 
220
                        // Only non-pending resources must have an existing service.
 
221
                        ops = append(ops, p.base.ServiceExistsOps(res.ServiceID)...)
 
222
                }
199
223
                return ops, nil
200
224
        }
201
225
        if err := p.base.Run(buildTxn); err != nil {
230
254
                        // Either insert or update will work so we should not get here.
231
255
                        return nil, errors.New("setting the resource failed")
232
256
                }
 
257
                // No pending resources so we always do this here.
 
258
                ops = append(ops, p.base.ServiceExistsOps(serviceID)...)
233
259
                return ops, nil
234
260
        }
235
261
        if err := p.base.Run(buildTxn); err != nil {
241
267
// SetUnitResource stores the resource info for a particular unit. The
242
268
// resource must already be set for the service.
243
269
func (p ResourcePersistence) SetUnitResource(unitID string, res resource.Resource) error {
 
270
        if res.PendingID != "" {
 
271
                return errors.Errorf("pending resources not allowed")
 
272
        }
 
273
        return p.setUnitResource(unitID, res, nil)
 
274
}
 
275
 
 
276
// SetUnitResource stores the resource info for a particular unit. The
 
277
// resource must already be set for the service. The provided progress
 
278
// is stored in the DB.
 
279
func (p ResourcePersistence) SetUnitResourceProgress(unitID string, res resource.Resource, progress int64) error {
 
280
        if res.PendingID == "" {
 
281
                return errors.Errorf("only pending resources may track progress")
 
282
        }
 
283
        return p.setUnitResource(unitID, res, &progress)
 
284
}
 
285
 
 
286
func (p ResourcePersistence) setUnitResource(unitID string, res resource.Resource, progress *int64) error {
244
287
        stored, err := p.getStored(res)
245
288
        if err != nil {
246
289
                return errors.Trace(err)
249
292
        // so then the following line is unnecessary.
250
293
        stored.Resource = res
251
294
 
252
 
        // TODO(ericsnow) Ensure that the service is still there?
253
 
 
254
295
        if err := res.Validate(); err != nil {
255
296
                return errors.Annotate(err, "bad resource")
256
297
        }
260
301
                var ops []txn.Op
261
302
                switch attempt {
262
303
                case 0:
263
 
                        ops = newInsertUnitResourceOps(unitID, stored)
 
304
                        ops = newInsertUnitResourceOps(unitID, stored, progress)
264
305
                case 1:
265
 
                        ops = newUpdateUnitResourceOps(unitID, stored)
 
306
                        ops = newUpdateUnitResourceOps(unitID, stored, progress)
266
307
                default:
267
308
                        // Either insert or update will work so we should not get here.
268
309
                        return nil, errors.New("setting the resource failed")
269
310
                }
 
311
                // No pending resources so we always do this here.
 
312
                ops = append(ops, p.base.ServiceExistsOps(res.ServiceID)...)
270
313
                return ops, nil
271
314
        }
272
315
        if err := p.base.Run(buildTxn); err != nil {
325
368
        ops := newResolvePendingResourceOps(pending, exists)
326
369
        return ops, nil
327
370
}
 
371
 
 
372
// NewRemoveUnitResourcesOps returns mgo transaction operations
 
373
// that remove resource information specific to the unit from state.
 
374
func (p ResourcePersistence) NewRemoveUnitResourcesOps(unitID string) ([]txn.Op, error) {
 
375
        docs, err := p.unitResources(unitID)
 
376
        if err != nil {
 
377
                return nil, errors.Trace(err)
 
378
        }
 
379
 
 
380
        ops := newRemoveResourcesOps(docs)
 
381
        // We do not remove the resource from the blob store here. That is
 
382
        // a service-level matter.
 
383
        return ops, nil
 
384
}
 
385
 
 
386
// NewRemoveResourcesOps returns mgo transaction operations that
 
387
// remove all the service's resources from state.
 
388
func (p ResourcePersistence) NewRemoveResourcesOps(serviceID string) ([]txn.Op, error) {
 
389
        docs, err := p.resources(serviceID)
 
390
        if err != nil {
 
391
                return nil, errors.Trace(err)
 
392
        }
 
393
 
 
394
        ops := newRemoveResourcesOps(docs)
 
395
        for _, doc := range docs {
 
396
                ops = append(ops, p.base.NewCleanupOp(CleanupKindResourceBlob, doc.StoragePath))
 
397
        }
 
398
        return ops, nil
 
399
}