blob: e3c006f0198c4658fb65d6e9aaf88997773e16eb [file] [log] [blame]
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -08001package servers
2
3import (
Jon Perritt9a0980e2015-01-14 21:29:44 -07004 "reflect"
5
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -08006 "github.com/mitchellh/mapstructure"
Ash Wilsond27e0ff2014-09-25 11:50:31 -04007 "github.com/rackspace/gophercloud"
Ash Wilson01626a32014-09-17 10:38:07 -04008 "github.com/rackspace/gophercloud/pagination"
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -08009)
10
Ash Wilson397c78b2014-09-25 15:19:14 -040011type serverResult struct {
Ash Wilsonf548aad2014-10-20 08:35:34 -040012 gophercloud.Result
Ash Wilson397c78b2014-09-25 15:19:14 -040013}
14
15// Extract interprets any serverResult as a Server, if possible.
16func (r serverResult) Extract() (*Server, error) {
17 if r.Err != nil {
18 return nil, r.Err
19 }
20
21 var response struct {
22 Server Server `mapstructure:"server"`
23 }
24
Jon Perritt9a0980e2015-01-14 21:29:44 -070025 config := &mapstructure.DecoderConfig{
26 DecodeHook: func(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) {
27 if (from == reflect.String) && (to == reflect.Map) {
28 return map[string]interface{}{}, nil
29 }
30 return data, nil
31 },
32 Result: &response,
33 }
34 decoder, err := mapstructure.NewDecoder(config)
35 if err != nil {
36 return nil, err
37 }
38
39 err = decoder.Decode(r.Body)
40 if err != nil {
41 return nil, err
42 }
43
44 return &response.Server, nil
Ash Wilson397c78b2014-09-25 15:19:14 -040045}
46
47// CreateResult temporarily contains the response from a Create call.
48type CreateResult struct {
49 serverResult
50}
51
52// GetResult temporarily contains the response from a Get call.
53type GetResult struct {
54 serverResult
55}
56
57// UpdateResult temporarily contains the response from an Update call.
58type UpdateResult struct {
59 serverResult
60}
61
Jon Perrittcc77da62014-11-16 13:14:21 -070062// DeleteResult temporarily contains the response from a Delete call.
Jamie Hannaford34732fe2014-10-27 11:29:36 +010063type DeleteResult struct {
Jon Perrittba2395e2014-10-27 15:23:21 -050064 gophercloud.ErrResult
Jamie Hannaford34732fe2014-10-27 11:29:36 +010065}
66
Ash Wilson397c78b2014-09-25 15:19:14 -040067// RebuildResult temporarily contains the response from a Rebuild call.
Jamie Hannaford01c1efe2014-10-16 15:08:59 +020068type RebuildResult struct {
Ash Wilson397c78b2014-09-25 15:19:14 -040069 serverResult
70}
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080071
Jamie Hannaford01c1efe2014-10-16 15:08:59 +020072// ActionResult represents the result of server action operations, like reboot
73type ActionResult struct {
Jon Perrittba2395e2014-10-27 15:23:21 -050074 gophercloud.ErrResult
Jamie Hannaford01c1efe2014-10-16 15:08:59 +020075}
76
Alex Gaynor587e3e32014-11-13 10:39:09 -080077// RescueResult represents the result of a server rescue operation
Alex Gaynorfbe61bb2014-11-12 13:35:03 -080078type RescueResult struct {
79 ActionResult
Alex Gaynor7f3b06e2014-11-13 09:54:03 -080080}
81
Jon Perrittcc77da62014-11-16 13:14:21 -070082// Extract interprets any RescueResult as an AdminPass, if possible.
Alex Gaynor7f3b06e2014-11-13 09:54:03 -080083func (r RescueResult) Extract() (string, error) {
84 if r.Err != nil {
Alex Gaynor94a28aa2014-11-13 10:09:56 -080085 return "", r.Err
Alex Gaynor7f3b06e2014-11-13 09:54:03 -080086 }
87
88 var response struct {
89 AdminPass string `mapstructure:"adminPass"`
90 }
91
92 err := mapstructure.Decode(r.Body, &response)
Alex Gaynor94a28aa2014-11-13 10:09:56 -080093 return response.AdminPass, err
Alex Gaynorfbe61bb2014-11-12 13:35:03 -080094}
95
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080096// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080097type Server struct {
Ash Wilson01626a32014-09-17 10:38:07 -040098 // ID uniquely identifies this server amongst all other servers, including those not accessible to the current tenant.
99 ID string
100
101 // TenantID identifies the tenant owning this server resource.
102 TenantID string `mapstructure:"tenant_id"`
103
104 // UserID uniquely identifies the user account owning the tenant.
105 UserID string `mapstructure:"user_id"`
106
107 // Name contains the human-readable name for the server.
108 Name string
109
110 // Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created.
111 Updated string
112 Created string
113
114 HostID string
115
116 // Status contains the current operational status of the server, such as IN_PROGRESS or ACTIVE.
117 Status string
118
119 // Progress ranges from 0..100.
120 // A request made against the server completes only once Progress reaches 100.
121 Progress int
122
123 // AccessIPv4 and AccessIPv6 contain the IP addresses of the server, suitable for remote access for administration.
Jamie Hannaford908e1e92014-10-27 14:41:17 +0100124 AccessIPv4, AccessIPv6 string
Ash Wilson01626a32014-09-17 10:38:07 -0400125
126 // Image refers to a JSON object, which itself indicates the OS image used to deploy the server.
127 Image map[string]interface{}
128
129 // Flavor refers to a JSON object, which itself indicates the hardware configuration of the deployed server.
130 Flavor map[string]interface{}
131
132 // Addresses includes a list of all IP addresses assigned to the server, keyed by pool.
Ash Wilson01626a32014-09-17 10:38:07 -0400133 Addresses map[string]interface{}
134
135 // Metadata includes a list of all user-specified key-value pairs attached to the server.
136 Metadata map[string]interface{}
137
138 // Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
139 Links []interface{}
140
Ash Wilsonad21c712014-09-25 10:15:22 -0400141 // KeyName indicates which public key was injected into the server on launch.
Ash Wilson69b144f2014-10-21 14:03:52 -0400142 KeyName string `json:"key_name" mapstructure:"key_name"`
Ash Wilsonad21c712014-09-25 10:15:22 -0400143
Ash Wilson01626a32014-09-17 10:38:07 -0400144 // AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place.
145 // Note that this is the ONLY time this field will be valid.
Ash Wilson69b144f2014-10-21 14:03:52 -0400146 AdminPass string `json:"adminPass" mapstructure:"adminPass"`
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -0800147}
148
Ash Wilson397c78b2014-09-25 15:19:14 -0400149// ServerPage abstracts the raw results of making a List() request against the API.
150// As OpenStack extensions may freely alter the response bodies of structures returned to the client, you may only safely access the
151// data provided through the ExtractServers call.
152type ServerPage struct {
153 pagination.LinkedPageBase
Ash Wilsonf57381e2014-09-25 13:21:34 -0400154}
155
Ash Wilson397c78b2014-09-25 15:19:14 -0400156// IsEmpty returns true if a page contains no Server results.
157func (page ServerPage) IsEmpty() (bool, error) {
158 servers, err := ExtractServers(page)
159 if err != nil {
160 return true, err
161 }
162 return len(servers) == 0, nil
163}
164
165// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
166func (page ServerPage) NextPageURL() (string, error) {
Ash Wilson397c78b2014-09-25 15:19:14 -0400167 type resp struct {
Jamie Hannaforda581acd2014-10-08 17:14:13 +0200168 Links []gophercloud.Link `mapstructure:"servers_links"`
Ash Wilsond27e0ff2014-09-25 11:50:31 -0400169 }
170
Ash Wilson397c78b2014-09-25 15:19:14 -0400171 var r resp
172 err := mapstructure.Decode(page.Body, &r)
173 if err != nil {
174 return "", err
Ash Wilsond27e0ff2014-09-25 11:50:31 -0400175 }
176
Jamie Hannaforda581acd2014-10-08 17:14:13 +0200177 return gophercloud.ExtractNextURL(r.Links)
Ash Wilsond27e0ff2014-09-25 11:50:31 -0400178}
179
Ash Wilson01626a32014-09-17 10:38:07 -0400180// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
181func ExtractServers(page pagination.Page) ([]Server, error) {
Ash Wilson397c78b2014-09-25 15:19:14 -0400182 casted := page.(ServerPage).Body
Ash Wilson12259392014-09-17 10:50:02 -0400183
184 var response struct {
185 Servers []Server `mapstructure:"servers"`
186 }
Jon Perritt9a0980e2015-01-14 21:29:44 -0700187
188 config := &mapstructure.DecoderConfig{
189 DecodeHook: func(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) {
190 if (from == reflect.String) && (to == reflect.Map) {
191 return map[string]interface{}{}, nil
192 }
193 return data, nil
194 },
195 Result: &response,
196 }
197 decoder, err := mapstructure.NewDecoder(config)
198 if err != nil {
199 return nil, err
200 }
201
202 err = decoder.Decode(casted)
203
204 //err := mapstructure.Decode(casted, &response)
Ash Wilson12259392014-09-17 10:50:02 -0400205 return response.Servers, err
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -0800206}
Jon Perrittcc77da62014-11-16 13:14:21 -0700207
Jon Perritt78c57ce2014-11-20 11:07:18 -0700208// MetadataResult contains the result of a call for (potentially) multiple key-value pairs.
Jon Perrittcc77da62014-11-16 13:14:21 -0700209type MetadataResult struct {
210 gophercloud.Result
211}
212
213// GetMetadataResult temporarily contains the response from a metadata Get call.
214type GetMetadataResult struct {
215 MetadataResult
216}
217
Jon Perritt789f8322014-11-21 08:20:04 -0700218// ResetMetadataResult temporarily contains the response from a metadata Reset call.
219type ResetMetadataResult struct {
Jon Perrittcc77da62014-11-16 13:14:21 -0700220 MetadataResult
221}
222
Jon Perritt78c57ce2014-11-20 11:07:18 -0700223// UpdateMetadataResult temporarily contains the response from a metadata Update call.
224type UpdateMetadataResult struct {
225 MetadataResult
Jon Perrittcc77da62014-11-16 13:14:21 -0700226}
227
Jon Perritt78c57ce2014-11-20 11:07:18 -0700228// MetadatumResult contains the result of a call for individual a single key-value pair.
229type MetadatumResult struct {
230 gophercloud.Result
231}
Jon Perrittcc77da62014-11-16 13:14:21 -0700232
Jon Perritt78c57ce2014-11-20 11:07:18 -0700233// GetMetadatumResult temporarily contains the response from a metadatum Get call.
234type GetMetadatumResult struct {
235 MetadatumResult
236}
Jon Perrittcc77da62014-11-16 13:14:21 -0700237
Jon Perritt78c57ce2014-11-20 11:07:18 -0700238// CreateMetadatumResult temporarily contains the response from a metadatum Create call.
239type CreateMetadatumResult struct {
240 MetadatumResult
241}
242
243// DeleteMetadatumResult temporarily contains the response from a metadatum Delete call.
244type DeleteMetadatumResult struct {
245 gophercloud.ErrResult
Jon Perrittcc77da62014-11-16 13:14:21 -0700246}
247
248// Extract interprets any MetadataResult as a Metadata, if possible.
249func (r MetadataResult) Extract() (map[string]string, error) {
250 if r.Err != nil {
251 return nil, r.Err
252 }
253
254 var response struct {
Jon Perritt78c57ce2014-11-20 11:07:18 -0700255 Metadata map[string]string `mapstructure:"metadata"`
Jon Perrittcc77da62014-11-16 13:14:21 -0700256 }
257
258 err := mapstructure.Decode(r.Body, &response)
259 return response.Metadata, err
260}
Jon Perritt78c57ce2014-11-20 11:07:18 -0700261
262// Extract interprets any MetadatumResult as a Metadatum, if possible.
263func (r MetadatumResult) Extract() (map[string]string, error) {
264 if r.Err != nil {
265 return nil, r.Err
266 }
267
268 var response struct {
269 Metadatum map[string]string `mapstructure:"meta"`
270 }
271
272 err := mapstructure.Decode(r.Body, &response)
273 return response.Metadatum, err
274}