blob: f6d6afa2cda1c8d424053130c83abcdecde9cbfa [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001// Copyright 2016 Canonical Ltd.
2// Licensed under the LGPLv3, see LICENCE file for details.
3
4package gomaasapi
5
6import (
7 "github.com/juju/errors"
8 "github.com/juju/schema"
9 "github.com/juju/version"
10)
11
12type partition struct {
13 resourceURI string
14
15 id int
16 path string
17 uuid string
18
19 usedFor string
20 size uint64
21
22 filesystem *filesystem
23}
24
25// ID implements Partition.
26func (p *partition) ID() int {
27 return p.id
28}
29
30// Path implements Partition.
31func (p *partition) Path() string {
32 return p.path
33}
34
35// FileSystem implements Partition.
36func (p *partition) FileSystem() FileSystem {
37 if p.filesystem == nil {
38 return nil
39 }
40 return p.filesystem
41}
42
43// UUID implements Partition.
44func (p *partition) UUID() string {
45 return p.uuid
46}
47
48// UsedFor implements Partition.
49func (p *partition) UsedFor() string {
50 return p.usedFor
51}
52
53// Size implements Partition.
54func (p *partition) Size() uint64 {
55 return p.size
56}
57
58func readPartitions(controllerVersion version.Number, source interface{}) ([]*partition, error) {
59 checker := schema.List(schema.StringMap(schema.Any()))
60 coerced, err := checker.Coerce(source, nil)
61 if err != nil {
62 return nil, WrapWithDeserializationError(err, "partition base schema check failed")
63 }
64 valid := coerced.([]interface{})
65
66 var deserialisationVersion version.Number
67 for v := range partitionDeserializationFuncs {
68 if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 {
69 deserialisationVersion = v
70 }
71 }
72 if deserialisationVersion == version.Zero {
73 return nil, NewUnsupportedVersionError("no partition read func for version %s", controllerVersion)
74 }
75 readFunc := partitionDeserializationFuncs[deserialisationVersion]
76 return readPartitionList(valid, readFunc)
77}
78
79// readPartitionList expects the values of the sourceList to be string maps.
80func readPartitionList(sourceList []interface{}, readFunc partitionDeserializationFunc) ([]*partition, error) {
81 result := make([]*partition, 0, len(sourceList))
82 for i, value := range sourceList {
83 source, ok := value.(map[string]interface{})
84 if !ok {
85 return nil, NewDeserializationError("unexpected value for partition %d, %T", i, value)
86 }
87 partition, err := readFunc(source)
88 if err != nil {
89 return nil, errors.Annotatef(err, "partition %d", i)
90 }
91 result = append(result, partition)
92 }
93 return result, nil
94}
95
96type partitionDeserializationFunc func(map[string]interface{}) (*partition, error)
97
98var partitionDeserializationFuncs = map[version.Number]partitionDeserializationFunc{
99 twoDotOh: partition_2_0,
100}
101
102func partition_2_0(source map[string]interface{}) (*partition, error) {
103 fields := schema.Fields{
104 "resource_uri": schema.String(),
105
106 "id": schema.ForceInt(),
107 "path": schema.String(),
108 "uuid": schema.OneOf(schema.Nil(""), schema.String()),
109
110 "used_for": schema.String(),
111 "size": schema.ForceUint(),
112
113 "filesystem": schema.OneOf(schema.Nil(""), schema.StringMap(schema.Any())),
114 }
115 defaults := schema.Defaults{
116 "uuid": "",
117 }
118 checker := schema.FieldMap(fields, defaults)
119 coerced, err := checker.Coerce(source, nil)
120 if err != nil {
121 return nil, WrapWithDeserializationError(err, "partition 2.0 schema check failed")
122 }
123 valid := coerced.(map[string]interface{})
124 // From here we know that the map returned from the schema coercion
125 // contains fields of the right type.
126
127 var filesystem *filesystem
128 if fsSource := valid["filesystem"]; fsSource != nil {
129 filesystem, err = filesystem2_0(fsSource.(map[string]interface{}))
130 if err != nil {
131 return nil, errors.Trace(err)
132 }
133 }
134 uuid, _ := valid["uuid"].(string)
135 result := &partition{
136 resourceURI: valid["resource_uri"].(string),
137 id: valid["id"].(int),
138 path: valid["path"].(string),
139 uuid: uuid,
140 usedFor: valid["used_for"].(string),
141 size: valid["size"].(uint64),
142 filesystem: filesystem,
143 }
144 return result, nil
145}