blob: c509d4264b34828d3b685fc2b30c5e293abaddad [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 vlan struct {
13 // Add the controller in when we need to do things with the vlan.
14 // controller Controller
15
16 resourceURI string
17
18 id int
19 name string
20 fabric string
21
22 vid int
23 mtu int
24 dhcp bool
25
26 primaryRack string
27 secondaryRack string
28}
29
30// ID implements VLAN.
31func (v *vlan) ID() int {
32 return v.id
33}
34
35// Name implements VLAN.
36func (v *vlan) Name() string {
37 return v.name
38}
39
40// Fabric implements VLAN.
41func (v *vlan) Fabric() string {
42 return v.fabric
43}
44
45// VID implements VLAN.
46func (v *vlan) VID() int {
47 return v.vid
48}
49
50// MTU implements VLAN.
51func (v *vlan) MTU() int {
52 return v.mtu
53}
54
55// DHCP implements VLAN.
56func (v *vlan) DHCP() bool {
57 return v.dhcp
58}
59
60// PrimaryRack implements VLAN.
61func (v *vlan) PrimaryRack() string {
62 return v.primaryRack
63}
64
65// SecondaryRack implements VLAN.
66func (v *vlan) SecondaryRack() string {
67 return v.secondaryRack
68}
69
70func readVLANs(controllerVersion version.Number, source interface{}) ([]*vlan, error) {
71 checker := schema.List(schema.StringMap(schema.Any()))
72 coerced, err := checker.Coerce(source, nil)
73 if err != nil {
74 return nil, errors.Annotatef(err, "vlan base schema check failed")
75 }
76 valid := coerced.([]interface{})
77
78 var deserialisationVersion version.Number
79 for v := range vlanDeserializationFuncs {
80 if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 {
81 deserialisationVersion = v
82 }
83 }
84 if deserialisationVersion == version.Zero {
85 return nil, errors.Errorf("no vlan read func for version %s", controllerVersion)
86 }
87 readFunc := vlanDeserializationFuncs[deserialisationVersion]
88 return readVLANList(valid, readFunc)
89}
90
91func readVLANList(sourceList []interface{}, readFunc vlanDeserializationFunc) ([]*vlan, error) {
92 result := make([]*vlan, 0, len(sourceList))
93 for i, value := range sourceList {
94 source, ok := value.(map[string]interface{})
95 if !ok {
96 return nil, errors.Errorf("unexpected value for vlan %d, %T", i, value)
97 }
98 vlan, err := readFunc(source)
99 if err != nil {
100 return nil, errors.Annotatef(err, "vlan %d", i)
101 }
102 result = append(result, vlan)
103 }
104 return result, nil
105}
106
107type vlanDeserializationFunc func(map[string]interface{}) (*vlan, error)
108
109var vlanDeserializationFuncs = map[version.Number]vlanDeserializationFunc{
110 twoDotOh: vlan_2_0,
111}
112
113func vlan_2_0(source map[string]interface{}) (*vlan, error) {
114 fields := schema.Fields{
115 "id": schema.ForceInt(),
116 "resource_uri": schema.String(),
117 "name": schema.OneOf(schema.Nil(""), schema.String()),
118 "fabric": schema.String(),
119 "vid": schema.ForceInt(),
120 "mtu": schema.ForceInt(),
121 "dhcp_on": schema.Bool(),
122 // racks are not always set.
123 "primary_rack": schema.OneOf(schema.Nil(""), schema.String()),
124 "secondary_rack": schema.OneOf(schema.Nil(""), schema.String()),
125 }
126 checker := schema.FieldMap(fields, nil)
127 coerced, err := checker.Coerce(source, nil)
128 if err != nil {
129 return nil, errors.Annotatef(err, "vlan 2.0 schema check failed")
130 }
131 valid := coerced.(map[string]interface{})
132 // From here we know that the map returned from the schema coercion
133 // contains fields of the right type.
134
135 // Since the primary and secondary racks are optional, we use the two
136 // part cast assignment. If the case fails, then we get the default value
137 // we care about, which is the empty string.
138 primary_rack, _ := valid["primary_rack"].(string)
139 secondary_rack, _ := valid["secondary_rack"].(string)
140 name, _ := valid["name"].(string)
141
142 result := &vlan{
143 resourceURI: valid["resource_uri"].(string),
144 id: valid["id"].(int),
145 name: name,
146 fabric: valid["fabric"].(string),
147 vid: valid["vid"].(int),
148 mtu: valid["mtu"].(int),
149 dhcp: valid["dhcp_on"].(bool),
150 primaryRack: primary_rack,
151 secondaryRack: secondary_rack,
152 }
153 return result, nil
154}