Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1077)

Side by Side Diff: nova/nova.go

Issue 6875052: Add filtering to ListServers APIs (Closed)
Patch Set: Created 11 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // The nova package provides a way to access the OpenStack Compute APIs. 1 // The nova package provides a way to access the OpenStack Compute APIs.
2 // See http://docs.openstack.org/api/openstack-compute/2/content/. 2 // See http://docs.openstack.org/api/openstack-compute/2/content/.
3 package nova 3 package nova
4 4
5 import ( 5 import (
6 "encoding/base64" 6 "encoding/base64"
7 "fmt" 7 "fmt"
8 "launchpad.net/goose/client" 8 "launchpad.net/goose/client"
9 goosehttp "launchpad.net/goose/http" 9 goosehttp "launchpad.net/goose/http"
10 "net/http" 10 "net/http"
11 "net/url"
11 ) 12 )
12 13
13 const ( 14 const (
14 apiFlavors = "/flavors" 15 apiFlavors = "/flavors"
15 apiFlavorsDetail = "/flavors/detail" 16 apiFlavorsDetail = "/flavors/detail"
16 apiServers = "/servers" 17 apiServers = "/servers"
17 apiServersDetail = "/servers/detail" 18 apiServersDetail = "/servers/detail"
18 apiSecurityGroups = "/os-security-groups" 19 apiSecurityGroups = "/os-security-groups"
19 apiSecurityGroupRules = "/os-security-group-rules" 20 apiSecurityGroupRules = "/os-security-group-rules"
20 apiFloatingIPs = "/os-floating-ips" 21 apiFloatingIPs = "/os-floating-ips"
21 ) 22 )
22 23
24 const (
jameinel 2012/12/04 13:01:45 I wonder if these should be typed as well as group
wallyworld 2012/12/05 00:46:41 I considered it but then filter.Add(key, value) wo
25 // Server status values.
26 StatusActive = "ACTIVE" // The server is active.
27 StatusBuild = "BUILD" // The server has not finished the original build process.
28 StatusDeleted = "DELETED" // The server is deleted.
29 StatusError = "ERROR" // The server is in error.
30 StatusHardReboot = "HARD_REBOOT" // The server is hard rebooting.
31 StatusPassword = "PASSWORD" // The password is being reset on t he server.
32 StatusReboot = "REBOOT" // The server is in a soft reboot s tate.
33 StatusRebuild = "REBUILD" // The server is currently being re built from an image.
34 StatusRescue = "RESCUE" // The server is in rescue mode.
35 StatusResize = "RESIZE" // Server is performing the differe ntial copy of data that changed during its initial copy.
36 StatusShutoff = "SHUTOFF" // The virtual machine (VM) was pow ered down by the user, but not through the OpenStack Compute API.
37 StatusSuspended = "SUSPENDED" // The server is suspended, either by request or necessity.
38 StatusUnknown = "UNKNOWN" // The state of the server is unkno wn. Contact your cloud provider.
39 StatusVerifyResize = "VERIFY_RESIZE" // System is awaiting confirmation that the server is operational after a move or resize.
40 )
41
42 const (
43 // Filter keys.
44 FilterStatus = "status" // The server status. See Server St atus Values.
45 FilterImage = "image" // The image reference specified as an ID or full URL.
46 FilterFlavor = "flavor" // The flavor reference specified a s an ID or full URL.
47 FilterServer = "name" // The server name.
48 FilterMarker = "marker" // The ID of the last item in the p revious list.
49 FilterLimit = "limit" // The page size.
50 FilterChangesSince = "changes-since" // The changes-since time. The list contains servers that have been deleted since the changes-since time.
51 )
52
23 // Client provides a means to access the OpenStack Compute Service. 53 // Client provides a means to access the OpenStack Compute Service.
24 type Client struct { 54 type Client struct {
25 client client.Client 55 client client.Client
26 } 56 }
27 57
28 func New(client client.Client) *Client { 58 func New(client client.Client) *Client {
29 return &Client{client} 59 return &Client{client}
30 } 60 }
31 61
62 // ----------------------------------------------------------------------------
63 // Filtering helper.
64
65 // Filter builds filtering parameters to be used in an OpenStack query which sup ports
66 // filtering. For example:
67 //
68 // filter := NewFilter()
69 // filter.Add("name", "server_name")
70 // filter.Add("status", "ACTIVE")
71 // resp, err := nova.ListServers(filter)
jameinel 2012/12/04 13:01:45 Maybe it wouldn't help, as we don't have "filter.A
wallyworld 2012/12/05 00:46:41 Add is used for all sorts of filter keys: status,
72 //
73 type Filter struct {
74 url.Values
75 }
76
77 // NewFilter creates a new Filter.
78 func NewFilter() *Filter {
79 return &Filter{make(url.Values)}
80 }
81
32 type Link struct { 82 type Link struct {
33 Href string 83 Href string
34 Rel string 84 Rel string
35 Type string 85 Type string
36 } 86 }
37 87
38 // Entity can describe a flavor, flavor detail or server. 88 // Entity can describe a flavor, flavor detail or server.
39 // Contains a list of links. 89 // Contains a list of links.
40 type Entity struct { 90 type Entity struct {
41 Id string 91 Id string
(...skipping 14 matching lines...) Expand all
56 type FlavorDetail struct { 106 type FlavorDetail struct {
57 Name string 107 Name string
58 RAM int 108 RAM int
59 VCPUs int 109 VCPUs int
60 Disk int 110 Disk int
61 Id string 111 Id string
62 Swap interface{} // Can be an empty string (?!) 112 Swap interface{} // Can be an empty string (?!)
63 } 113 }
64 114
65 // ListFlavorsDetail lists all details for available flavors. 115 // ListFlavorsDetail lists all details for available flavors.
66 func (c *Client) ListFlavorsDetail() (*[]FlavorDetail, error) { 116 func (c *Client) ListFlavorsDetail() ([]FlavorDetail, error) {
67 var resp struct { 117 var resp struct {
68 Flavors []FlavorDetail 118 Flavors []FlavorDetail
69 } 119 }
70 requestData := goosehttp.RequestData{RespValue: &resp} 120 requestData := goosehttp.RequestData{RespValue: &resp}
71 err := c.client.SendRequest(client.GET, "compute", apiFlavorsDetail, &re questData, 121 err := c.client.SendRequest(client.GET, "compute", apiFlavorsDetail, &re questData,
72 "failed to get list of flavors details") 122 "failed to get list of flavors details")
73 if err != nil { 123 if err != nil {
74 return nil, err 124 return nil, err
75 } 125 }
76 » return &resp.Flavors, nil 126 » return resp.Flavors, nil
77 } 127 }
78 128
79 // ListServers lists IDs, names, and links for all servers. 129 // ListServers lists IDs, names, and links for all servers.
80 func (c *Client) ListServers() (*[]Entity, error) { 130 func (c *Client) ListServers(filter *Filter) ([]Entity, error) {
81 var resp struct { 131 var resp struct {
82 Servers []Entity 132 Servers []Entity
83 } 133 }
84 » requestData := goosehttp.RequestData{RespValue: &resp, ExpectedStatus: [ ]int{http.StatusOK}} 134 » requestData := goosehttp.RequestData{RespValue: &resp, Params: &filter.V alues, ExpectedStatus: []int{http.StatusOK}}
85 err := c.client.SendRequest(client.GET, "compute", apiServers, &requestD ata, 135 err := c.client.SendRequest(client.GET, "compute", apiServers, &requestD ata,
86 "failed to get list of servers") 136 "failed to get list of servers")
87 if err != nil { 137 if err != nil {
88 return nil, err 138 return nil, err
89 } 139 }
90 » return &resp.Servers, nil 140 » return resp.Servers, nil
91 } 141 }
92 142
93 type ServerDetail struct { 143 type ServerDetail struct {
94 AddressIPv4 string 144 AddressIPv4 string
95 AddressIPv6 string 145 AddressIPv6 string
96 Created string 146 Created string
97 Flavor Entity 147 Flavor Entity
98 HostId string 148 HostId string
99 Id string 149 Id string
100 Image Entity 150 Image Entity
101 Links []Link 151 Links []Link
102 Name string 152 Name string
103 Progress int 153 Progress int
104 Status string 154 Status string
105 TenantId string `json:"tenant_id"` 155 TenantId string `json:"tenant_id"`
106 Updated string 156 Updated string
107 UserId string `json:"user_id"` 157 UserId string `json:"user_id"`
108 } 158 }
109 159
110 // ListServersDetail lists all details for available servers. 160 // ListServersDetail lists all details for available servers.
111 func (c *Client) ListServersDetail() (*[]ServerDetail, error) { 161 func (c *Client) ListServersDetail(filter *Filter) ([]ServerDetail, error) {
112 var resp struct { 162 var resp struct {
113 Servers []ServerDetail 163 Servers []ServerDetail
114 } 164 }
115 » requestData := goosehttp.RequestData{RespValue: &resp} 165 » requestData := goosehttp.RequestData{RespValue: &resp, Params: &filter.V alues}
116 err := c.client.SendRequest(client.GET, "compute", apiServersDetail, &re questData, 166 err := c.client.SendRequest(client.GET, "compute", apiServersDetail, &re questData,
117 "failed to get list of servers details") 167 "failed to get list of servers details")
118 if err != nil { 168 if err != nil {
119 return nil, err 169 return nil, err
120 } 170 }
121 » return &resp.Servers, nil 171 » return resp.Servers, nil
122 } 172 }
123 173
124 // GetServer lists details for the specified server. 174 // GetServer lists details for the specified server.
125 func (c *Client) GetServer(serverId string) (*ServerDetail, error) { 175 func (c *Client) GetServer(serverId string) (*ServerDetail, error) {
126 var resp struct { 176 var resp struct {
127 Server ServerDetail 177 Server ServerDetail
128 } 178 }
129 url := fmt.Sprintf("%s/%s", apiServers, serverId) 179 url := fmt.Sprintf("%s/%s", apiServers, serverId)
130 requestData := goosehttp.RequestData{RespValue: &resp} 180 requestData := goosehttp.RequestData{RespValue: &resp}
131 err := c.client.SendRequest(client.GET, "compute", url, &requestData, 181 err := c.client.SendRequest(client.GET, "compute", url, &requestData,
(...skipping 20 matching lines...) Expand all
152 Name string `json:"name"` 202 Name string `json:"name"`
153 FlavorId string `json:"flavorRef"` 203 FlavorId string `json:"flavorRef"`
154 ImageId string `json:"imageRef"` 204 ImageId string `json:"imageRef"`
155 UserData *string `json:"user_data"` 205 UserData *string `json:"user_data"`
156 SecurityGroupNames []struct { 206 SecurityGroupNames []struct {
157 Name string `json:"name"` 207 Name string `json:"name"`
158 } `json:"security_groups"` 208 } `json:"security_groups"`
159 } 209 }
160 210
161 // RunServer creates a new server. 211 // RunServer creates a new server.
162 func (c *Client) RunServer(opts RunServerOpts) error { 212 func (c *Client) RunServer(opts RunServerOpts) (*Entity, error) {
163 var req struct { 213 var req struct {
164 Server RunServerOpts `json:"server"` 214 Server RunServerOpts `json:"server"`
165 } 215 }
166 req.Server = opts 216 req.Server = opts
167 if opts.UserData != nil { 217 if opts.UserData != nil {
168 data := []byte(*opts.UserData) 218 data := []byte(*opts.UserData)
169 encoded := base64.StdEncoding.EncodeToString(data) 219 encoded := base64.StdEncoding.EncodeToString(data)
170 req.Server.UserData = &encoded 220 req.Server.UserData = &encoded
171 } 221 }
172 » requestData := goosehttp.RequestData{ReqValue: req, ExpectedStatus: []in t{http.StatusAccepted}} 222 » var resp struct {
223 » » Server Entity `json:"server"`
224 » }
225 » requestData := goosehttp.RequestData{ReqValue: req, RespValue: &resp, Ex pectedStatus: []int{http.StatusAccepted}}
173 err := c.client.SendRequest(client.POST, "compute", apiServers, &request Data, 226 err := c.client.SendRequest(client.POST, "compute", apiServers, &request Data,
174 "failed to run a server with %#v", opts) 227 "failed to run a server with %#v", opts)
175 » return err 228 » if err != nil {
229 » » return nil, err
230 » }
231 » return &resp.Server, nil
176 } 232 }
177 233
178 type SecurityGroupRule struct { 234 type SecurityGroupRule struct {
179 FromPort *int `json:"from_port"` // Can be nil 235 FromPort *int `json:"from_port"` // Can be nil
180 IPProtocol *string `json:"ip_protocol"` // Can be nil 236 IPProtocol *string `json:"ip_protocol"` // Can be nil
181 ToPort *int `json:"to_port"` // Can be nil 237 ToPort *int `json:"to_port"` // Can be nil
182 ParentGroupId int `json:"parent_group_id"` 238 ParentGroupId int `json:"parent_group_id"`
183 IPRange map[string]string `json:"ip_range"` // Can be empty 239 IPRange map[string]string `json:"ip_range"` // Can be empty
184 Id int 240 Id int
185 Group map[string]string // Can be empty 241 Group map[string]string // Can be empty
186 } 242 }
187 243
188 type SecurityGroup struct { 244 type SecurityGroup struct {
189 Rules []SecurityGroupRule 245 Rules []SecurityGroupRule
190 TenantId string `json:"tenant_id"` 246 TenantId string `json:"tenant_id"`
191 Id int 247 Id int
192 Name string 248 Name string
193 Description string 249 Description string
194 } 250 }
195 251
196 // ListSecurityGroups lists IDs, names, and other details for all security group s. 252 // ListSecurityGroups lists IDs, names, and other details for all security group s.
197 func (c *Client) ListSecurityGroups() (*[]SecurityGroup, error) { 253 func (c *Client) ListSecurityGroups() ([]SecurityGroup, error) {
198 var resp struct { 254 var resp struct {
199 Groups []SecurityGroup `json:"security_groups"` 255 Groups []SecurityGroup `json:"security_groups"`
200 } 256 }
201 requestData := goosehttp.RequestData{RespValue: &resp} 257 requestData := goosehttp.RequestData{RespValue: &resp}
202 err := c.client.SendRequest(client.GET, "compute", apiSecurityGroups, &r equestData, 258 err := c.client.SendRequest(client.GET, "compute", apiSecurityGroups, &r equestData,
203 "failed to list security groups") 259 "failed to list security groups")
204 if err != nil { 260 if err != nil {
205 return nil, err 261 return nil, err
206 } 262 }
207 » return &resp.Groups, nil 263 » return resp.Groups, nil
208 } 264 }
209 265
210 // GetServerSecurityGroups list security groups for a specific server. 266 // GetServerSecurityGroups list security groups for a specific server.
211 func (c *Client) GetServerSecurityGroups(serverId string) (*[]SecurityGroup, err or) { 267 func (c *Client) GetServerSecurityGroups(serverId string) ([]SecurityGroup, erro r) {
212 268
213 var resp struct { 269 var resp struct {
214 Groups []SecurityGroup `json:"security_groups"` 270 Groups []SecurityGroup `json:"security_groups"`
215 } 271 }
216 url := fmt.Sprintf("%s/%s/%s", apiServers, serverId, apiSecurityGroups) 272 url := fmt.Sprintf("%s/%s/%s", apiServers, serverId, apiSecurityGroups)
217 requestData := goosehttp.RequestData{RespValue: &resp} 273 requestData := goosehttp.RequestData{RespValue: &resp}
218 err := c.client.SendRequest(client.GET, "compute", url, &requestData, 274 err := c.client.SendRequest(client.GET, "compute", url, &requestData,
219 "failed to list server (%s) security groups", serverId) 275 "failed to list server (%s) security groups", serverId)
220 if err != nil { 276 if err != nil {
221 return nil, err 277 return nil, err
222 } 278 }
223 » return &resp.Groups, nil 279 » return resp.Groups, nil
224 } 280 }
225 281
226 // CreateSecurityGroup creates a new security group. 282 // CreateSecurityGroup creates a new security group.
227 func (c *Client) CreateSecurityGroup(name, description string) (*SecurityGroup, error) { 283 func (c *Client) CreateSecurityGroup(name, description string) (*SecurityGroup, error) {
228 var req struct { 284 var req struct {
229 SecurityGroup struct { 285 SecurityGroup struct {
230 Name string `json:"name"` 286 Name string `json:"name"`
231 Description string `json:"description"` 287 Description string `json:"description"`
232 } `json:"security_group"` 288 } `json:"security_group"`
233 } 289 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 383
328 type FloatingIP struct { 384 type FloatingIP struct {
329 FixedIP interface{} `json:"fixed_ip"` // Can be a string or null 385 FixedIP interface{} `json:"fixed_ip"` // Can be a string or null
330 Id int `json:"id"` 386 Id int `json:"id"`
331 InstanceId interface{} `json:"instance_id"` // Can be a string or null 387 InstanceId interface{} `json:"instance_id"` // Can be a string or null
332 IP string `json:"ip"` 388 IP string `json:"ip"`
333 Pool string `json:"pool"` 389 Pool string `json:"pool"`
334 } 390 }
335 391
336 // ListFloatingIPs lists floating IP addresses associated with the tenant or acc ount. 392 // ListFloatingIPs lists floating IP addresses associated with the tenant or acc ount.
337 func (c *Client) ListFloatingIPs() (*[]FloatingIP, error) { 393 func (c *Client) ListFloatingIPs() ([]FloatingIP, error) {
338 var resp struct { 394 var resp struct {
339 FloatingIPs []FloatingIP `json:"floating_ips"` 395 FloatingIPs []FloatingIP `json:"floating_ips"`
340 } 396 }
341 397
342 requestData := goosehttp.RequestData{RespValue: &resp} 398 requestData := goosehttp.RequestData{RespValue: &resp}
343 err := c.client.SendRequest(client.GET, "compute", apiFloatingIPs, &requ estData, 399 err := c.client.SendRequest(client.GET, "compute", apiFloatingIPs, &requ estData,
344 "failed to list floating ips") 400 "failed to list floating ips")
345 if err != nil { 401 if err != nil {
346 return nil, err 402 return nil, err
347 } 403 }
348 » return &resp.FloatingIPs, nil 404 » return resp.FloatingIPs, nil
349 } 405 }
350 406
351 // GetFloatingIP lists details of the floating IP address associated with specif ied id. 407 // GetFloatingIP lists details of the floating IP address associated with specif ied id.
352 func (c *Client) GetFloatingIP(ipId int) (*FloatingIP, error) { 408 func (c *Client) GetFloatingIP(ipId int) (*FloatingIP, error) {
353 var resp struct { 409 var resp struct {
354 FloatingIP FloatingIP `json:"floating_ip"` 410 FloatingIP FloatingIP `json:"floating_ip"`
355 } 411 }
356 412
357 url := fmt.Sprintf("%s/%d", apiFloatingIPs, ipId) 413 url := fmt.Sprintf("%s/%d", apiFloatingIPs, ipId)
358 requestData := goosehttp.RequestData{RespValue: &resp} 414 requestData := goosehttp.RequestData{RespValue: &resp}
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } `json:"removeFloatingIp"` 468 } `json:"removeFloatingIp"`
413 } 469 }
414 req.RemoveFloatingIP.Address = address 470 req.RemoveFloatingIP.Address = address
415 471
416 url := fmt.Sprintf("%s/%s/action", apiServers, serverId) 472 url := fmt.Sprintf("%s/%s/action", apiServers, serverId)
417 requestData := goosehttp.RequestData{ReqValue: req, ExpectedStatus: []in t{http.StatusAccepted}} 473 requestData := goosehttp.RequestData{ReqValue: req, ExpectedStatus: []in t{http.StatusAccepted}}
418 err := c.client.SendRequest(client.POST, "compute", url, &requestData, 474 err := c.client.SendRequest(client.POST, "compute", url, &requestData,
419 "failed to remove floating ip %s to server %s", address, serverI d) 475 "failed to remove floating ip %s to server %s", address, serverI d)
420 return err 476 return err
421 } 477 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b