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

Side by Side Diff: testservices/novaservice/service.go

Issue 6877054: First part of the nova service double. (Closed)
Patch Set: First part of the nova service double. Created 12 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
« no previous file with comments | « testservices/novaservice/novaservice.go ('k') | testservices/novaservice/service_http.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Nova double testing service - internal direct API implementation
2
3 package novaservice
4
5 import (
6 "fmt"
7 "launchpad.net/goose/nova"
8 "strings"
9 )
10
11 // Nova contains the service double's internal state.
12 type Nova struct {
13 flavors map[string]nova.FlavorDetail
14 servers map[string]nova.ServerDetail
15 groups map[int]nova.SecurityGroup
16 rules map[int]nova.SecurityGroupRule
17 floatingIPs map[int]nova.FloatingIP
18 serverGroups map[string][]int
19 serverIPs map[string][]int
20 hostname string
21 baseURL string
22 token string
23 }
24
25 // New creates an instance of the Nova object, given the parameters.
26 func New(hostname, baseURL, token string) *Nova {
27 nova := &Nova{
28 flavors: make(map[string]nova.FlavorDetail),
29 servers: make(map[string]nova.ServerDetail),
30 groups: make(map[int]nova.SecurityGroup),
31 rules: make(map[int]nova.SecurityGroupRule),
32 floatingIPs: make(map[int]nova.FloatingIP),
33 serverGroups: make(map[string][]int),
34 serverIPs: make(map[string][]int),
35 hostname: hostname,
36 baseURL: baseURL,
37 token: token,
38 }
39 return nova
40 }
41
42 // buildFlavorLinks populates the Links field of the passed
43 // FlavorDetail as needed by OpenStack HTTP API. Call this
44 // before addFlavor().
45 func (n *Nova) buildFlavorLinks(flavor *nova.FlavorDetail) {
46 ep := n.hostname
47 ver := strings.TrimLeft(n.baseURL, "/")
48 url := n.token + "/flavors/" + flavor.Id
49 flavor.Links = []nova.Link{
50 nova.Link{Href: ep + ver + url, Rel: "self"},
51 nova.Link{Href: ep + url, Rel: "bookmark"},
52 }
53 }
54
55 // addFlavor creates a new flavor.
56 func (n *Nova) addFlavor(flavor nova.FlavorDetail) error {
57 if _, err := n.getFlavor(flavor.Id); err == nil {
58 return fmt.Errorf("a flavor with id %q already exists", flavor.I d)
59 }
60 n.flavors[flavor.Id] = flavor
61 return nil
62 }
63
64 // getFlavor retrieves an existing flavor by ID.
65 func (n *Nova) getFlavor(flavorId string) (*nova.FlavorDetail, error) {
66 flavor, ok := n.flavors[flavorId]
67 if !ok {
68 return nil, fmt.Errorf("no such flavor %q", flavorId)
69 }
70 return &flavor, nil
71 }
72
73 // getFlavorAsEntity returns the stored FlavorDetail as Entity.
74 func (n *Nova) getFlavorAsEntity(flavorId string) (*nova.Entity, error) {
75 flavor, err := n.getFlavor(flavorId)
76 if err != nil {
77 return nil, err
78 }
79 return &nova.Entity{
80 Id: flavor.Id,
81 Name: flavor.Name,
82 Links: flavor.Links,
83 }, nil
84 }
85
86 // allFlavors returns a list of all existing flavors.
87 func (n *Nova) allFlavors() []nova.FlavorDetail {
88 var flavors []nova.FlavorDetail
89 for _, flavor := range n.flavors {
90 flavors = append(flavors, flavor)
91 }
92 return flavors
93 }
94
95 // allFlavorsAsEntities returns all flavors as Entity structs.
96 func (n *Nova) allFlavorsAsEntities() []nova.Entity {
97 var entities []nova.Entity
98 for _, flavor := range n.flavors {
99 entities = append(entities, nova.Entity{
100 Id: flavor.Id,
101 Name: flavor.Name,
102 Links: flavor.Links,
103 })
104 }
105 return entities
106 }
107
108 // removeFlavor deletes an existing flavor.
109 func (n *Nova) removeFlavor(flavorId string) error {
110 if _, err := n.getFlavor(flavorId); err != nil {
111 return err
112 }
113 delete(n.flavors, flavorId)
114 return nil
115 }
116
117 // buildServerLinks populates the Links field of the passed
118 // ServerDetail as needed by OpenStack HTTP API. Call this
119 // before addServer().
120 func (n *Nova) buildServerLinks(server *nova.ServerDetail) {
121 ep := n.hostname
122 ver := strings.TrimLeft(n.baseURL, "/")
123 url := n.token + "/servers/" + server.Id
124 server.Links = []nova.Link{
125 nova.Link{Href: ep + ver + url, Rel: "self"},
126 nova.Link{Href: ep + url, Rel: "bookmark"},
127 }
128 }
129
130 // addServer creates a new server.
131 func (n *Nova) addServer(server nova.ServerDetail) error {
132 if _, err := n.getServer(server.Id); err == nil {
133 return fmt.Errorf("a server with id %q already exists", server.I d)
134 }
135 n.servers[server.Id] = server
136 return nil
137 }
138
139 // getServer retrieves an existing server by ID.
140 func (n *Nova) getServer(serverId string) (*nova.ServerDetail, error) {
141 server, ok := n.servers[serverId]
142 if !ok {
143 return nil, fmt.Errorf("no such server %q", serverId)
144 }
145 return &server, nil
146 }
147
148 // getServerAsEntity returns the stored ServerDetail as Entity.
149 func (n *Nova) getServerAsEntity(serverId string) (*nova.Entity, error) {
150 server, err := n.getServer(serverId)
151 if err != nil {
152 return nil, err
153 }
154 return &nova.Entity{
155 Id: server.Id,
156 Name: server.Name,
157 Links: server.Links,
158 }, nil
159 }
160
161 // allServers returns a list of all existing servers.
162 func (n *Nova) allServers() []nova.ServerDetail {
163 var servers []nova.ServerDetail
164 for _, server := range n.servers {
165 servers = append(servers, server)
166 }
167 return servers
168 }
169
170 // allServersAsEntities returns all servers as Entity structs.
171 func (n *Nova) allServersAsEntities() []nova.Entity {
172 var entities []nova.Entity
173 for _, server := range n.servers {
174 entities = append(entities, nova.Entity{
175 Id: server.Id,
176 Name: server.Name,
177 Links: server.Links,
178 })
179 }
180 return entities
181 }
182
183 // removeServer deletes an existing server.
184 func (n *Nova) removeServer(serverId string) error {
185 if _, err := n.getServer(serverId); err != nil {
186 return err
187 }
188 delete(n.servers, serverId)
189 return nil
190 }
191
192 // addSecurityGroup creates a new security group.
193 func (n *Nova) addSecurityGroup(group nova.SecurityGroup) error {
194 if _, err := n.getSecurityGroup(group.Id); err == nil {
195 return fmt.Errorf("a security group with id %d already exists", group.Id)
196 }
197 n.groups[group.Id] = group
198 return nil
199 }
200
201 // getSecurityGroup retrieves an existing group by ID.
202 func (n *Nova) getSecurityGroup(groupId int) (*nova.SecurityGroup, error) {
203 group, ok := n.groups[groupId]
204 if !ok {
205 return nil, fmt.Errorf("no such security group %d", groupId)
206 }
207 return &group, nil
208 }
209
210 // allSecurityGroups returns a list of all existing groups.
211 func (n *Nova) allSecurityGroups() []nova.SecurityGroup {
212 var groups []nova.SecurityGroup
213 for _, group := range n.groups {
214 groups = append(groups, group)
215 }
216 return groups
217 }
218
219 // removeSecurityGroup deletes an existing group.
220 func (n *Nova) removeSecurityGroup(groupId int) error {
221 if _, err := n.getSecurityGroup(groupId); err != nil {
222 return err
223 }
224 delete(n.groups, groupId)
225 return nil
226 }
227
228 // addSecurityGroupRule creates a new rule in an existing group.
229 // This can be either an ingress or a group rule (see the notes
230 // about nova.RuleInfo).
231 func (n *Nova) addSecurityGroupRule(ruleId int, rule nova.RuleInfo) error {
232 if _, err := n.getSecurityGroupRule(ruleId); err == nil {
233 return fmt.Errorf("a security group rule with id %d already exis ts", ruleId)
234 }
235 group, err := n.getSecurityGroup(rule.ParentGroupId)
236 if err != nil {
237 return err
238 }
239 for _, ru := range group.Rules {
240 if ru.Id == ruleId {
241 return fmt.Errorf("cannot add twice rule %d to security group %d", ru.Id, group.Id)
242 }
243 }
244 newrule := nova.SecurityGroupRule{
245 ParentGroupId: rule.ParentGroupId,
246 Id: ruleId,
247 }
248 if rule.GroupId != nil {
249 sourceGroup, err := n.getSecurityGroup(*rule.GroupId)
250 if err != nil {
251 return fmt.Errorf("unknown source security group %d", *r ule.GroupId)
252 }
253 newrule.Group = &nova.SecurityGroupRef{
254 TenantId: sourceGroup.TenantId,
255 Name: sourceGroup.Name,
256 }
257 }
258 if rule.FromPort > 0 {
259 newrule.FromPort = &rule.FromPort
260 }
261 if rule.ToPort > 0 {
262 newrule.ToPort = &rule.ToPort
263 }
264 if rule.IPProtocol != "" {
265 newrule.IPProtocol = &rule.IPProtocol
266 }
267 if rule.Cidr != "" {
268 newrule.IPRange = make(map[string]string)
269 newrule.IPRange["cidr"] = rule.Cidr
270 }
271
272 group.Rules = append(group.Rules, newrule)
273 n.groups[group.Id] = *group
274 n.rules[newrule.Id] = newrule
275 return nil
276 }
277
278 // hasSecurityGroupRule returns whether the given group contains the given rule,
279 // or (when groupId=-1) whether the given rule exists.
280 func (n *Nova) hasSecurityGroupRule(groupId, ruleId int) bool {
281 rule, ok := n.rules[ruleId]
282 _, err := n.getSecurityGroup(groupId)
283 return ok && (groupId == -1 || (err == nil && rule.ParentGroupId == grou pId))
284 }
285
286 // getSecurityGroupRule retrieves an existing rule by ID.
287 func (n *Nova) getSecurityGroupRule(ruleId int) (*nova.SecurityGroupRule, error) {
288 rule, ok := n.rules[ruleId]
289 if !ok {
290 return nil, fmt.Errorf("no such security group rule %d", ruleId)
291 }
292 return &rule, nil
293 }
294
295 // removeSecurityGroupRule deletes an existing rule from its group.
296 func (n *Nova) removeSecurityGroupRule(ruleId int) error {
297 rule, err := n.getSecurityGroupRule(ruleId)
298 if err != nil {
299 return err
300 }
301 if group, err := n.getSecurityGroup(rule.ParentGroupId); err == nil {
302 idx := -1
303 for ri, ru := range group.Rules {
304 if ru.Id == ruleId {
305 idx = ri
306 break
307 }
308 }
309 if idx != -1 {
310 group.Rules = append(group.Rules[:idx], group.Rules[idx+ 1:]...)
311 n.groups[group.Id] = *group
312 }
313 // Silently ignore missing rules...
314 }
315 // ...or groups
316 delete(n.rules, ruleId)
317 return nil
318 }
319
320 // addServerSecurityGroup attaches an existing server to a group.
321 func (n *Nova) addServerSecurityGroup(serverId string, groupId int) error {
322 if _, err := n.getServer(serverId); err != nil {
323 return err
324 }
325 if _, err := n.getSecurityGroup(groupId); err != nil {
326 return err
327 }
328 groups, ok := n.serverGroups[serverId]
329 if ok {
330 for _, gid := range groups {
331 if gid == groupId {
332 return fmt.Errorf("server %q already belongs to group %d", serverId, groupId)
333 }
334 }
335 }
336 groups = append(groups, groupId)
337 n.serverGroups[serverId] = groups
338 return nil
339 }
340
341 // hasServerSecurityGroup returns whether the given server belongs to the group.
342 func (n *Nova) hasServerSecurityGroup(serverId string, groupId int) bool {
343 if _, err := n.getServer(serverId); err != nil {
344 return false
345 }
346 if _, err := n.getSecurityGroup(groupId); err != nil {
347 return false
348 }
349 groups, ok := n.serverGroups[serverId]
350 if !ok {
351 return false
352 }
353 for _, gid := range groups {
354 if gid == groupId {
355 return true
356 }
357 }
358 return false
359 }
360
361 // removeServerSecurityGroup detaches an existing server from a group.
362 func (n *Nova) removeServerSecurityGroup(serverId string, groupId int) error {
363 if _, err := n.getServer(serverId); err != nil {
364 return err
365 }
366 if _, err := n.getSecurityGroup(groupId); err != nil {
367 return err
368 }
369 groups, ok := n.serverGroups[serverId]
370 if !ok {
371 return fmt.Errorf("server %q does not belong to any groups", ser verId)
372 }
373 idx := -1
374 for gi, gid := range groups {
375 if gid == groupId {
376 idx = gi
377 break
378 }
379 }
380 if idx == -1 {
381 return fmt.Errorf("server %q does not belong to group %d", serve rId, groupId)
382 }
383 groups = append(groups[:idx], groups[idx+1:]...)
384 n.serverGroups[serverId] = groups
385 return nil
386 }
387
388 // addFloatingIP creates a new floating IP address in the pool.
389 func (n *Nova) addFloatingIP(ip nova.FloatingIP) error {
390 if _, err := n.getFloatingIP(ip.Id); err == nil {
391 return fmt.Errorf("a floating IP with id %d already exists", ip. Id)
392 }
393 n.floatingIPs[ip.Id] = ip
394 return nil
395 }
396
397 // hasFloatingIP returns whether the given floating IP address exists.
398 func (n *Nova) hasFloatingIP(address string) bool {
399 if len(n.floatingIPs) == 0 {
400 return false
401 }
402 for _, fip := range n.floatingIPs {
403 if fip.IP == address {
404 return true
405 }
406 }
407 return false
408 }
409
410 // getFloatingIP retrieves the floating IP by ID.
411 func (n *Nova) getFloatingIP(ipId int) (*nova.FloatingIP, error) {
412 ip, ok := n.floatingIPs[ipId]
413 if !ok {
414 return nil, fmt.Errorf("no such floating IP %d", ipId)
415 }
416 return &ip, nil
417 }
418
419 // allFloatingIPs returns a list of all created floating IPs.
420 func (n *Nova) allFloatingIPs() []nova.FloatingIP {
421 var fips []nova.FloatingIP
422 for _, fip := range n.floatingIPs {
423 fips = append(fips, fip)
424 }
425 return fips
426 }
427
428 // removeFloatingIP deletes an existing floating IP by ID.
429 func (n *Nova) removeFloatingIP(ipId int) error {
430 if _, err := n.getFloatingIP(ipId); err != nil {
431 return err
432 }
433 delete(n.floatingIPs, ipId)
434 return nil
435 }
436
437 // addServerFloatingIP attaches an existing floating IP to a server.
438 func (n *Nova) addServerFloatingIP(serverId string, ipId int) error {
439 if _, err := n.getServer(serverId); err != nil {
440 return err
441 }
442 if _, err := n.getFloatingIP(ipId); err != nil {
443 return err
444 }
445 fips, ok := n.serverIPs[serverId]
446 if ok {
447 for _, fipId := range fips {
448 if fipId == ipId {
449 return fmt.Errorf("server %q already has floatin g IP %d", serverId, ipId)
450 }
451 }
452 }
453 fips = append(fips, ipId)
454 n.serverIPs[serverId] = fips
455 return nil
456 }
457
458 // hasServerFloatingIP verifies the given floating IP belongs to a server.
459 func (n *Nova) hasServerFloatingIP(serverId, address string) bool {
460 if _, err := n.getServer(serverId); err != nil || !n.hasFloatingIP(addre ss) {
461 return false
462 }
463 fips, ok := n.serverIPs[serverId]
464 if !ok {
465 return false
466 }
467 for _, fipId := range fips {
468 fip := n.floatingIPs[fipId]
469 if fip.IP == address {
470 return true
471 }
472 }
473 return false
474 }
475
476 // removeServerFloatingIP deletes an attached floating IP from a server.
477 func (n *Nova) removeServerFloatingIP(serverId string, ipId int) error {
478 if _, err := n.getServer(serverId); err != nil {
479 return err
480 }
481 if _, err := n.getFloatingIP(ipId); err != nil {
482 return err
483 }
484 fips, ok := n.serverIPs[serverId]
485 if !ok {
486 return fmt.Errorf("server %q does not have any floating IPs to r emove", serverId)
487 }
488 idx := -1
489 for fi, fipId := range fips {
490 if fipId == ipId {
491 idx = fi
492 break
493 }
494 }
495 if idx == -1 {
496 return fmt.Errorf("server %q does not have floating IP %d", serv erId, ipId)
497 }
498 fips = append(fips[:idx], fips[idx+1:]...)
499 n.serverIPs[serverId] = fips
500 return nil
501 }
OLDNEW
« no previous file with comments | « testservices/novaservice/novaservice.go ('k') | testservices/novaservice/service_http.go » ('j') | no next file with comments »

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