-
Notifications
You must be signed in to change notification settings - Fork 13
/
resource_server_network_adapter.go
253 lines (215 loc) · 8.13 KB
/
resource_server_network_adapter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
package ddcloud
import (
"fmt"
"log"
"github.com/DimensionDataResearch/dd-cloud-compute-terraform/models"
"github.com/DimensionDataResearch/dd-cloud-compute-terraform/retry"
"github.com/DimensionDataResearch/go-dd-cloud-compute/compute"
"github.com/hashicorp/terraform/helper/schema"
)
const (
resourceKeyServerPrimaryNetworkAdapter = "primary_network_adapter"
resourceKeyServerAdditionalNetworkAdapter = "additional_network_adapter"
resourceKeyServerNetworkAdapterID = "id"
resourceKeyServerNetworkAdapterMAC = "mac"
resourceKeyServerNetworkAdapterVLANID = "vlan"
resourceKeyServerNetworkAdapterIPV4 = "ipv4"
resourceKeyServerNetworkAdapterIPV6 = "ipv6"
resourceKeyServerNetworkAdapterType = "type"
)
func schemaServerPrimaryNetworkAdapter() *schema.Schema {
return schemaServerNetworkAdapter(true)
}
func schemaServerAdditionalNetworkAdapter() *schema.Schema {
return schemaServerNetworkAdapter(false)
}
func schemaServerNetworkAdapter(isPrimary bool) *schema.Schema {
var maxItems int
if isPrimary {
maxItems = 1
} else {
maxItems = 0
}
return &schema.Schema{
Type: schema.TypeList,
Required: isPrimary,
Optional: !isPrimary,
Computed: !isPrimary,
ForceNew: !isPrimary,
MinItems: 1,
MaxItems: maxItems,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
resourceKeyServerNetworkAdapterID: &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The network adapter's identifier in CloudControl",
},
resourceKeyServerNetworkAdapterMAC: &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The network adapter's MAC address",
},
resourceKeyServerNetworkAdapterVLANID: &schema.Schema{
Type: schema.TypeString,
Computed: true,
Optional: true,
Default: nil,
ForceNew: true,
Description: "VLAN ID of the network adapter",
},
resourceKeyServerNetworkAdapterIPV4: &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Default: nil,
Description: "The IPV4 address associated with the network adapter",
},
resourceKeyServerNetworkAdapterIPV6: &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The IPV6 Address associated the network adapter",
},
resourceKeyServerNetworkAdapterType: &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Default: nil,
Description: fmt.Sprintf("The type of network adapter (%s or %s)",
compute.NetworkAdapterTypeE1000,
compute.NetworkAdapterTypeVMXNET3,
),
ValidateFunc: validateNetworkAdapterAdapterType,
},
},
},
}
}
func addServerNetworkAdapter(providerState *providerState, serverID string, networkAdapter *models.NetworkAdapter) error {
log.Printf("Add network adapter to server '%s'", serverID)
apiClient := providerState.Client()
operationDescription := fmt.Sprintf("Add network adapter to server '%s'", serverID)
err := providerState.RetryAction(operationDescription, func(context retry.Context) {
asyncLock := providerState.AcquireAsyncOperationLock(operationDescription)
defer asyncLock.Release()
var addAdapterError error
if networkAdapter.HasExplicitType() {
networkAdapter.ID, addAdapterError = apiClient.AddNicWithTypeToServer(
serverID,
networkAdapter.PrivateIPv4Address,
networkAdapter.VLANID,
networkAdapter.AdapterType,
)
} else {
networkAdapter.ID, addAdapterError = apiClient.AddNicToServer(
serverID,
networkAdapter.PrivateIPv4Address,
networkAdapter.VLANID,
)
}
if compute.IsResourceBusyError(addAdapterError) {
context.Retry()
} else if addAdapterError != nil {
context.Fail(addAdapterError)
}
})
if err != nil {
return err
}
log.Printf("Adding network adapter '%s' to server '%s'...", networkAdapter.ID, serverID)
compositeNetworkAdapterID := fmt.Sprintf("%s/%s", serverID, networkAdapter.ID)
_, err = apiClient.WaitForChange(
compute.ResourceTypeNetworkAdapter,
compositeNetworkAdapterID,
"Add network adapter",
resourceUpdateTimeoutServer,
)
if err != nil {
return err
}
log.Printf("Added network adapter '%s' to server '%s'.", networkAdapter.ID, serverID)
return nil
}
func modifyServerNetworkAdapterIP(providerState *providerState, serverID string, networkAdapter models.NetworkAdapter) error {
log.Printf("Update IP address(es) for network adapter '%s'.", networkAdapter.ID)
apiClient := providerState.Client()
operationDescription := fmt.Sprintf("Update IP address info for network adapter '%s'", networkAdapter.ID)
err := providerState.RetryAction(operationDescription, func(context retry.Context) {
asyncLock := providerState.AcquireAsyncOperationLock(operationDescription)
defer asyncLock.Release()
changeAddressError := apiClient.NotifyServerIPAddressChange(networkAdapter.ID, &networkAdapter.PrivateIPv4Address, nil)
if compute.IsResourceBusyError(changeAddressError) {
context.Retry()
} else if changeAddressError != nil {
context.Fail(changeAddressError)
}
})
if err != nil {
return err
}
log.Printf("Updating IP address(es) for network adapter '%s'...", networkAdapter.ID)
compositeNetworkAdapterID := fmt.Sprintf("%s/%s", serverID, networkAdapter.ID)
_, err = apiClient.WaitForChange(compute.ResourceTypeNetworkAdapter, compositeNetworkAdapterID, "Update adapter IP address", resourceUpdateTimeoutServer)
log.Printf("Updated IP address(es) for network adapter '%s'.", networkAdapter.ID)
return err
}
func modifyServerNetworkAdapterType(providerState *providerState, serverID string, networkAdapter models.NetworkAdapter) error {
log.Printf("Change type of network adapter '%s' to '%s'.",
networkAdapter.ID,
networkAdapter.AdapterType,
)
apiClient := providerState.Client()
operationDescription := fmt.Sprintf("Change type of network adapter '%s'", networkAdapter.ID)
err := providerState.RetryAction(operationDescription, func(context retry.Context) {
asyncLock := providerState.AcquireAsyncOperationLock(operationDescription)
defer asyncLock.Release()
changeTypeError := apiClient.ChangeNetworkAdapterType(networkAdapter.ID, networkAdapter.AdapterType)
if compute.IsResourceBusyError(changeTypeError) {
context.Retry()
} else if changeTypeError != nil {
context.Fail(changeTypeError)
}
})
if err != nil {
return err
}
log.Printf("Changing type of network adapter '%s'...", networkAdapter.ID)
compositeNetworkAdapterID := fmt.Sprintf("%s/%s", serverID, networkAdapter.ID)
_, err = apiClient.WaitForChange(compute.ResourceTypeNetworkAdapter, compositeNetworkAdapterID, "Change type", resourceUpdateTimeoutServer)
log.Printf("Changed type of network adapter '%s'.", networkAdapter.ID)
return err
}
func removeServerNetworkAdapter(providerState *providerState, serverID string, networkAdapter *models.NetworkAdapter) error {
log.Printf("Remove network adapter '%s'.", networkAdapter.ID)
apiClient := providerState.Client()
removingAdapter := true
operationDescription := fmt.Sprintf("Remove network adapter '%s'", networkAdapter.ID)
err := providerState.RetryAction(operationDescription, func(context retry.Context) {
asyncLock := providerState.AcquireAsyncOperationLock(operationDescription)
defer asyncLock.Release()
removeError := apiClient.RemoveNicFromServer(networkAdapter.ID)
if compute.IsResourceBusyError(removeError) {
context.Retry()
} else if compute.IsResourceNotFoundError(removeError) {
log.Printf("Network adapter '%s' not found (will treat as deleted).",
networkAdapter.ID,
)
removingAdapter = false
} else if removeError != nil {
context.Fail(removeError)
}
})
if err != nil {
return err
}
if removingAdapter {
log.Printf("Removing network adapter '%s'...", networkAdapter.ID)
compositeNetworkAdapterID := fmt.Sprintf("%s/%s", serverID, networkAdapter.ID)
_, err = apiClient.WaitForNestedDeleteChange(compute.ResourceTypeNetworkAdapter, compositeNetworkAdapterID, "Remove network adapter", resourceUpdateTimeoutServer)
if err != nil {
return err
}
log.Printf("Removed network adapter '%s'.", networkAdapter.ID)
}
return nil
}