blob: 42a2c10ffe0d6a58e443e551b7f90a813ac12c48 [file] [log] [blame]
Joe Topjian1c15e3f2016-08-08 10:48:38 -06001// Package v2 contains common functions for creating compute-based resources
2// for use in acceptance tests. See the `*_test.go` files for example usages.
3package v2
4
5import (
6 "crypto/rand"
7 "crypto/rsa"
8 "fmt"
9 "testing"
10
11 "github.com/gophercloud/gophercloud"
12 "github.com/gophercloud/gophercloud/acceptance/clients"
13 "github.com/gophercloud/gophercloud/acceptance/tools"
14 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
15 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
16 dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules"
17 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
18 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
19 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks"
20 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/quotasets"
21 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
22 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
23 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
24 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
25 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
26 "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
27 "github.com/gophercloud/gophercloud/openstack/compute/v2/images"
28 "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
29
30 "golang.org/x/crypto/ssh"
31)
32
33// AssociateFloatingIP will associate a floating IP with an instance. An error
34// will be returned if the floating IP was unable to be associated.
35func AssociateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server) error {
36 associateOpts := floatingips.AssociateOpts{
37 FloatingIP: floatingIP.IP,
38 }
39
40 t.Logf("Attempting to associate floating IP %s to instance %s", floatingIP.IP, server.ID)
41 err := floatingips.AssociateInstance(client, server.ID, associateOpts).ExtractErr()
42 if err != nil {
43 return err
44 }
45
46 return nil
47}
48
49// AssociateFloatingIPWithFixedIP will associate a floating IP with an
50// instance's specific fixed IP. An error will be returend if the floating IP
51// was unable to be associated.
52func AssociateFloatingIPWithFixedIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server, fixedIP string) error {
53 associateOpts := floatingips.AssociateOpts{
54 FloatingIP: floatingIP.IP,
55 FixedIP: fixedIP,
56 }
57
58 t.Logf("Attempting to associate floating IP %s to fixed IP %s on instance %s", floatingIP.IP, fixedIP, server.ID)
59 err := floatingips.AssociateInstance(client, server.ID, associateOpts).ExtractErr()
60 if err != nil {
61 return err
62 }
63
64 return nil
65}
66
67// CreateBootableVolumeServer works like CreateServer but is configured with
68// one or more block devices defined by passing in []bootfromvolume.BlockDevice.
69// An error will be returned if a server was unable to be created.
70func CreateBootableVolumeServer(t *testing.T, client *gophercloud.ServiceClient, blockDevices []bootfromvolume.BlockDevice, choices *clients.AcceptanceTestChoices) (*servers.Server, error) {
71 if testing.Short() {
72 t.Skip("Skipping test that requires server creation in short mode.")
73 }
74
75 var server *servers.Server
76
77 networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
78 if err != nil {
79 return server, err
80 }
81
82 name := tools.RandomString("ACPTTEST", 16)
83 t.Logf("Attempting to create bootable volume server: %s", name)
84
85 serverCreateOpts := servers.CreateOpts{
86 Name: name,
87 FlavorRef: choices.FlavorID,
88 ImageRef: choices.ImageID,
89 Networks: []servers.Network{
90 servers.Network{UUID: networkID},
91 },
92 }
93
94 server, err = bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
95 serverCreateOpts,
96 blockDevices,
97 }).Extract()
98
99 if err != nil {
100 return server, err
101 }
102
103 return server, nil
104}
105
106// CreateDefaultRule will create a default security group rule with a
107// random port range between 80 and 90. An error will be returned if
108// a default rule was unable to be created.
109func CreateDefaultRule(t *testing.T, client *gophercloud.ServiceClient) (dsr.DefaultRule, error) {
110 createOpts := dsr.CreateOpts{
111 FromPort: tools.RandomInt(80, 89),
112 ToPort: tools.RandomInt(90, 99),
113 IPProtocol: "TCP",
114 CIDR: "0.0.0.0/0",
115 }
116
117 defaultRule, err := dsr.Create(client, createOpts).Extract()
118 if err != nil {
119 return *defaultRule, err
120 }
121
122 t.Logf("Created default rule: %s", defaultRule.ID)
123
124 return *defaultRule, nil
125}
126
127// CreateFloatingIP will allocate a floating IP.
128// An error will be returend if one was unable to be allocated.
129func CreateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices) (*floatingips.FloatingIP, error) {
130 createOpts := floatingips.CreateOpts{
131 Pool: choices.FloatingIPPoolName,
132 }
133 floatingIP, err := floatingips.Create(client, createOpts).Extract()
134 if err != nil {
135 return floatingIP, err
136 }
137
138 t.Logf("Created floating IP: %s", floatingIP.ID)
139 return floatingIP, nil
140}
141
142func createKey() (string, error) {
143 privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
144 if err != nil {
145 return "", err
146 }
147
148 publicKey := privateKey.PublicKey
149 pub, err := ssh.NewPublicKey(&publicKey)
150 if err != nil {
151 return "", err
152 }
153
154 pubBytes := ssh.MarshalAuthorizedKey(pub)
155 pk := string(pubBytes)
156 return pk, nil
157}
158
159// CreateKeyPair will create a KeyPair with a random name. An error will occur
160// if the keypair failed to be created. An error will be returned if the
161// keypair was unable to be created.
162func CreateKeyPair(t *testing.T, client *gophercloud.ServiceClient) (*keypairs.KeyPair, error) {
163 keyPairName := tools.RandomString("keypair_", 5)
164
165 t.Logf("Attempting to create keypair: %s", keyPairName)
166 createOpts := keypairs.CreateOpts{
167 Name: keyPairName,
168 }
169 keyPair, err := keypairs.Create(client, createOpts).Extract()
170 if err != nil {
171 return keyPair, err
172 }
173
174 t.Logf("Created keypair: %s", keyPairName)
175 return keyPair, nil
176}
177
178// CreateSecurityGroup will create a security group with a random name.
179// An error will be returned if one was failed to be created.
180func CreateSecurityGroup(t *testing.T, client *gophercloud.ServiceClient) (secgroups.SecurityGroup, error) {
181 createOpts := secgroups.CreateOpts{
182 Name: tools.RandomString("secgroup_", 5),
183 Description: "something",
184 }
185
186 securityGroup, err := secgroups.Create(client, createOpts).Extract()
187 if err != nil {
188 return *securityGroup, err
189 }
190
191 t.Logf("Created security group: %s", securityGroup.ID)
192 return *securityGroup, nil
193}
194
195// CreateSecurityGroupRule will create a security group rule with a random name
196// and a random TCP port range between port 80 and 99. An error will be
197// returned if the rule failed to be created.
198func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, securityGroupID string) (secgroups.Rule, error) {
199 createOpts := secgroups.CreateRuleOpts{
200 ParentGroupID: securityGroupID,
201 FromPort: tools.RandomInt(80, 89),
202 ToPort: tools.RandomInt(90, 99),
203 IPProtocol: "TCP",
204 CIDR: "0.0.0.0/0",
205 }
206
207 rule, err := secgroups.CreateRule(client, createOpts).Extract()
208 if err != nil {
209 return *rule, err
210 }
211
212 t.Logf("Created security group rule: %s", rule.ID)
213 return *rule, nil
214}
215
216// CreateServer creates a basic instance with a randomly generated name.
217// The flavor of the instance will be the value of the OS_FLAVOR_ID environment variable.
218// The image will be the value of the OS_IMAGE_ID environment variable.
219// The instance will be launched on the network specified in OS_NETWORK_NAME.
220// An error will be returned if the instance was unable to be created.
221func CreateServer(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices) (*servers.Server, error) {
222 if testing.Short() {
223 t.Skip("Skipping test that requires server creation in short mode.")
224 }
225
226 var server *servers.Server
227
228 networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
229 if err != nil {
230 return server, err
231 }
232
233 name := tools.RandomString("ACPTTEST", 16)
234 t.Logf("Attempting to create server: %s", name)
235
236 pwd := tools.MakeNewPassword("")
237
238 server, err = servers.Create(client, servers.CreateOpts{
239 Name: name,
240 FlavorRef: choices.FlavorID,
241 ImageRef: choices.ImageID,
242 AdminPass: pwd,
243 Networks: []servers.Network{
244 servers.Network{UUID: networkID},
245 },
Joe Topjianf464c962016-09-12 08:02:43 -0600246 Metadata: map[string]string{
247 "abc": "def",
248 },
Joe Topjian1c15e3f2016-08-08 10:48:38 -0600249 Personality: servers.Personality{
250 &servers.File{
251 Path: "/etc/test",
252 Contents: []byte("hello world"),
253 },
254 },
255 }).Extract()
256 if err != nil {
257 return server, err
258 }
259
260 if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
261 return server, err
262 }
263
264 return server, nil
265}
266
267// CreateServerGroup will create a server with a random name. An error will be
268// returned if the server group failed to be created.
269func CreateServerGroup(t *testing.T, client *gophercloud.ServiceClient, policy string) (*servergroups.ServerGroup, error) {
270 sg, err := servergroups.Create(client, &servergroups.CreateOpts{
271 Name: "test",
272 Policies: []string{policy},
273 }).Extract()
274
275 if err != nil {
276 return sg, err
277 }
278
279 return sg, nil
280}
281
282// CreateServerInServerGroup works like CreateServer but places the instance in
283// a specified Server Group.
284func CreateServerInServerGroup(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices, serverGroup *servergroups.ServerGroup) (*servers.Server, error) {
285 if testing.Short() {
286 t.Skip("Skipping test that requires server creation in short mode.")
287 }
288
289 var server *servers.Server
290
291 networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
292 if err != nil {
293 return server, err
294 }
295
296 name := tools.RandomString("ACPTTEST", 16)
297 t.Logf("Attempting to create server: %s", name)
298
299 pwd := tools.MakeNewPassword("")
300
301 serverCreateOpts := servers.CreateOpts{
302 Name: name,
303 FlavorRef: choices.FlavorID,
304 ImageRef: choices.ImageID,
305 AdminPass: pwd,
306 Networks: []servers.Network{
307 servers.Network{UUID: networkID},
308 },
309 }
310
311 schedulerHintsOpts := schedulerhints.CreateOptsExt{
312 serverCreateOpts,
313 schedulerhints.SchedulerHints{
314 Group: serverGroup.ID,
315 },
316 }
317 server, err = servers.Create(client, schedulerHintsOpts).Extract()
318 if err != nil {
319 return server, err
320 }
321
322 return server, nil
323}
324
325// CreateServerWithPublicKey works the same as CreateServer, but additionally
326// configures the server with a specified Key Pair name.
327func CreateServerWithPublicKey(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices, keyPairName string) (*servers.Server, error) {
328 if testing.Short() {
329 t.Skip("Skipping test that requires server creation in short mode.")
330 }
331
332 var server *servers.Server
333
334 networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
335 if err != nil {
336 return server, err
337 }
338
339 name := tools.RandomString("ACPTTEST", 16)
340 t.Logf("Attempting to create server: %s", name)
341
342 serverCreateOpts := servers.CreateOpts{
343 Name: name,
344 FlavorRef: choices.FlavorID,
345 ImageRef: choices.ImageID,
346 Networks: []servers.Network{
347 servers.Network{UUID: networkID},
348 },
349 }
350
351 server, err = servers.Create(client, keypairs.CreateOptsExt{
352 serverCreateOpts,
353 keyPairName,
354 }).Extract()
355 if err != nil {
356 return server, err
357 }
358
359 if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
360 return server, err
361 }
362
363 return server, nil
364}
365
Gleb37b56e82016-09-06 19:07:58 +0300366// CreateVolumeAttachment will attach a volume to a server. An error will be
Joe Topjian1c15e3f2016-08-08 10:48:38 -0600367// returned if the volume failed to attach.
368func CreateVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, server *servers.Server, volume *volumes.Volume) (*volumeattach.VolumeAttachment, error) {
369 volumeAttachOptions := volumeattach.CreateOpts{
370 VolumeID: volume.ID,
371 }
372
373 t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID)
374 volumeAttachment, err := volumeattach.Create(client, server.ID, volumeAttachOptions).Extract()
375 if err != nil {
376 return volumeAttachment, err
377 }
378
379 if err = volumes.WaitForStatus(blockClient, volume.ID, "in-use", 60); err != nil {
380 return volumeAttachment, err
381 }
382
383 return volumeAttachment, nil
384}
385
386// DeleteDefaultRule deletes a default security group rule.
387// A fatal error will occur if the rule failed to delete. This works best when
388// using it as a deferred function.
389func DeleteDefaultRule(t *testing.T, client *gophercloud.ServiceClient, defaultRule dsr.DefaultRule) {
390 err := dsr.Delete(client, defaultRule.ID).ExtractErr()
391 if err != nil {
392 t.Fatalf("Unable to delete default rule %s: %v", defaultRule.ID, err)
393 }
394
395 t.Logf("Deleted default rule: %s", defaultRule.ID)
396}
397
398// DeleteFloatingIP will de-allocate a floating IP. A fatal error will occur if
399// the floating IP failed to de-allocate. This works best when using it as a
400// deferred function.
401func DeleteFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP) {
402 err := floatingips.Delete(client, floatingIP.ID).ExtractErr()
403 if err != nil {
404 t.Fatalf("Unable to delete floating IP %s: %v", floatingIP.ID, err)
405 }
406
407 t.Logf("Deleted floating IP: %s", floatingIP.ID)
408}
409
410// DeleteKeyPair will delete a specified keypair. A fatal error will occur if
411// the keypair failed to be deleted. This works best when used as a deferred
412// function.
413func DeleteKeyPair(t *testing.T, client *gophercloud.ServiceClient, keyPair *keypairs.KeyPair) {
414 err := keypairs.Delete(client, keyPair.Name).ExtractErr()
415 if err != nil {
416 t.Fatalf("Unable to delete keypair %s: %v", keyPair.Name, err)
417 }
418
419 t.Logf("Deleted keypair: %s", keyPair.Name)
420}
421
422// DeleteSecurityGroup will delete a security group. A fatal error will occur
423// if the group failed to be deleted. This works best as a deferred function.
424func DeleteSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, securityGroup secgroups.SecurityGroup) {
425 err := secgroups.Delete(client, securityGroup.ID).ExtractErr()
426 if err != nil {
427 t.Fatalf("Unable to delete security group %s: %s", securityGroup.ID, err)
428 }
429
430 t.Logf("Deleted security group: %s", securityGroup.ID)
431}
432
433// DeleteSecurityGroupRule will delete a security group rule. A fatal error
434// will occur if the rule failed to be deleted. This works best when used
435// as a deferred function.
436func DeleteSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, rule secgroups.Rule) {
437 err := secgroups.DeleteRule(client, rule.ID).ExtractErr()
438 if err != nil {
439 t.Fatalf("Unable to delete rule: %v", err)
440 }
441
442 t.Logf("Deleted security group rule: %s", rule.ID)
443}
444
445// DeleteServer deletes an instance via its UUID.
446// A fatal error will occur if the instance failed to be destroyed. This works
447// best when using it as a deferred function.
448func DeleteServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server) {
449 err := servers.Delete(client, server.ID).ExtractErr()
450 if err != nil {
451 t.Fatalf("Unable to delete server %s: %s", server.ID, err)
452 }
453
454 t.Logf("Deleted server: %s", server.ID)
455}
456
457// DeleteServerGroup will delete a server group. A fatal error will occur if
458// the server group failed to be deleted. This works best when used as a
459// deferred function.
460func DeleteServerGroup(t *testing.T, client *gophercloud.ServiceClient, serverGroup *servergroups.ServerGroup) {
461 err := servergroups.Delete(client, serverGroup.ID).ExtractErr()
462 if err != nil {
463 t.Fatalf("Unable to delete server group %s: %v", serverGroup.ID, err)
464 }
465
466 t.Logf("Deleted server group %s", serverGroup.ID)
467}
468
469// DeleteVolumeAttachment will disconnect a volume from an instance. A fatal
470// error will occur if the volume failed to detach. This works best when used
Gleb37b56e82016-09-06 19:07:58 +0300471// as a deferred function.
Joe Topjian1c15e3f2016-08-08 10:48:38 -0600472func DeleteVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, server *servers.Server, volumeAttachment *volumeattach.VolumeAttachment) {
473
474 err := volumeattach.Delete(client, server.ID, volumeAttachment.VolumeID).ExtractErr()
475 if err != nil {
476 t.Fatalf("Unable to detach volume: %v", err)
477 }
478
479 if err = volumes.WaitForStatus(blockClient, volumeAttachment.ID, "available", 60); err != nil {
480 t.Fatalf("Unable to wait for volume: %v", err)
481 }
482 t.Logf("Deleted volume: %s", volumeAttachment.VolumeID)
483}
484
485// DisassociateFloatingIP will disassociate a floating IP from an instance. A
486// fatal error will occur if the floating IP failed to disassociate. This works
487// best when using it as a deferred function.
488func DisassociateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server) {
489 disassociateOpts := floatingips.DisassociateOpts{
490 FloatingIP: floatingIP.IP,
491 }
492
493 err := floatingips.DisassociateInstance(client, server.ID, disassociateOpts).ExtractErr()
494 if err != nil {
495 t.Fatalf("Unable to disassociate floating IP %s from server %s: %v", floatingIP.IP, server.ID, err)
496 }
497
498 t.Logf("Disassociated floating IP %s from server %s", floatingIP.IP, server.ID)
499}
500
501// GetNetworkIDFromNetworks will return the network ID from a specified network
502// UUID using the os-networks API extension. An error will be returned if the
503// network could not be retrieved.
504func GetNetworkIDFromNetworks(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
505 allPages, err := networks.List(client).AllPages()
506 if err != nil {
507 t.Fatalf("Unable to list networks: %v", err)
508 }
509
510 networkList, err := networks.ExtractNetworks(allPages)
511 if err != nil {
512 t.Fatalf("Unable to list networks: %v", err)
513 }
514
515 networkID := ""
516 for _, network := range networkList {
517 t.Logf("Network: %v", network)
518 if network.Label == networkName {
519 networkID = network.ID
520 }
521 }
522
523 t.Logf("Found network ID for %s: %s", networkName, networkID)
524
525 return networkID, nil
526}
527
528// GetNetworkIDFromTenantNetworks will return the network UUID for a given
529// network name using the os-tenant-networks API extension. An error will be
530// returned if the network could not be retrieved.
531func GetNetworkIDFromTenantNetworks(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
532 allPages, err := tenantnetworks.List(client).AllPages()
533 if err != nil {
534 return "", err
535 }
536
537 allTenantNetworks, err := tenantnetworks.ExtractNetworks(allPages)
538 if err != nil {
539 return "", err
540 }
541
542 for _, network := range allTenantNetworks {
543 if network.Name == networkName {
544 return network.ID, nil
545 }
546 }
547
548 return "", fmt.Errorf("Failed to obtain network ID for network %s", networkName)
549}
550
551// ImportPublicKey will create a KeyPair with a random name and a specified
552// public key. An error will be returned if the keypair failed to be created.
553func ImportPublicKey(t *testing.T, client *gophercloud.ServiceClient, publicKey string) (*keypairs.KeyPair, error) {
554 keyPairName := tools.RandomString("keypair_", 5)
555
556 t.Logf("Attempting to create keypair: %s", keyPairName)
557 createOpts := keypairs.CreateOpts{
558 Name: keyPairName,
559 PublicKey: publicKey,
560 }
561 keyPair, err := keypairs.Create(client, createOpts).Extract()
562 if err != nil {
563 return keyPair, err
564 }
565
566 t.Logf("Created keypair: %s", keyPairName)
567 return keyPair, nil
568}
569
570// ResizeServer performs a resize action on an instance. An error will be
571// returned if the instance failed to resize.
572// The new flavor that the instance will be resized to is specified in OS_FLAVOR_ID_RESIZE.
573func ResizeServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server, choices *clients.AcceptanceTestChoices) error {
574 opts := &servers.ResizeOpts{
575 FlavorRef: choices.FlavorIDResize,
576 }
577 if res := servers.Resize(client, server.ID, opts); res.Err != nil {
578 return res.Err
579 }
580
581 if err := WaitForComputeStatus(client, server, "VERIFY_RESIZE"); err != nil {
582 return err
583 }
584
585 return nil
586}
587
588// WaitForComputeStatus will poll an instance's status until it either matches
589// the specified status or the status becomes ERROR.
590func WaitForComputeStatus(client *gophercloud.ServiceClient, server *servers.Server, status string) error {
591 return tools.WaitFor(func() (bool, error) {
592 latest, err := servers.Get(client, server.ID).Extract()
593 if err != nil {
594 return false, err
595 }
596
597 if latest.Status == status {
598 // Success!
599 return true, nil
600 }
601
602 if latest.Status == "ERROR" {
603 return false, fmt.Errorf("Instance in ERROR state")
604 }
605
606 return false, nil
607 })
608}
609
610// PrintServer will print an instance and all of its attributes.
611func PrintServer(t *testing.T, server *servers.Server) {
612 t.Logf("ID: %s", server.ID)
613 t.Logf("TenantID: %s", server.TenantID)
614 t.Logf("UserID: %s", server.UserID)
615 t.Logf("Name: %s", server.Name)
616 t.Logf("Updated: %s", server.Updated)
617 t.Logf("Created: %s", server.Created)
618 t.Logf("HostID: %s", server.HostID)
619 t.Logf("Status: %s", server.Status)
620 t.Logf("Progress: %d", server.Progress)
621 t.Logf("AccessIPv4: %s", server.AccessIPv4)
622 t.Logf("AccessIPv6: %s", server.AccessIPv6)
623 t.Logf("Image: %s", server.Image)
624 t.Logf("Flavor: %s", server.Flavor)
625 t.Logf("Addresses: %#v", server.Addresses)
626 t.Logf("Metadata: %#v", server.Metadata)
627 t.Logf("Links: %#v", server.Links)
628 t.Logf("KeyName: %s", server.KeyName)
629 t.Logf("AdminPass: %s", server.AdminPass)
630 t.Logf("SecurityGroups: %#v", server.SecurityGroups)
631}
632
633// PrintDefaultRule will print a default security group rule and all of its attributes.
634func PrintDefaultRule(t *testing.T, defaultRule *dsr.DefaultRule) {
635 t.Logf("\tID: %s", defaultRule.ID)
636 t.Logf("\tFrom Port: %d", defaultRule.FromPort)
637 t.Logf("\tTo Port: %d", defaultRule.ToPort)
638 t.Logf("\tIP Protocol: %s", defaultRule.IPProtocol)
639 t.Logf("\tIP Range: %s", defaultRule.IPRange.CIDR)
640 t.Logf("\tParent Group ID: %s", defaultRule.ParentGroupID)
641 t.Logf("\tGroup Tenant ID: %s", defaultRule.Group.TenantID)
642 t.Logf("\tGroup Name: %s", defaultRule.Group.Name)
643}
644
645// PrintFlavor will print a flavor and all of its attributes.
646func PrintFlavor(t *testing.T, flavor *flavors.Flavor) {
647 t.Logf("ID: %s", flavor.ID)
648 t.Logf("Name: %s", flavor.Name)
649 t.Logf("RAM: %d", flavor.RAM)
650 t.Logf("Disk: %d", flavor.Disk)
651 t.Logf("Swap: %d", flavor.Swap)
652 t.Logf("RxTxFactor: %f", flavor.RxTxFactor)
653}
654
655// PrintFloatingIP will print a floating IP and all of its attributes.
656func PrintFloatingIP(t *testing.T, floatingIP *floatingips.FloatingIP) {
657 t.Logf("ID: %s", floatingIP.ID)
658 t.Logf("Fixed IP: %s", floatingIP.FixedIP)
659 t.Logf("Instance ID: %s", floatingIP.InstanceID)
660 t.Logf("IP: %s", floatingIP.IP)
661 t.Logf("Pool: %s", floatingIP.Pool)
662}
663
664// PrintImage will print an image and all of its attributes.
665func PrintImage(t *testing.T, image images.Image) {
666 t.Logf("ID: %s", image.ID)
667 t.Logf("Name: %s", image.Name)
668 t.Logf("MinDisk: %d", image.MinDisk)
669 t.Logf("MinRAM: %d", image.MinRAM)
670 t.Logf("Status: %s", image.Status)
671 t.Logf("Progress: %d", image.Progress)
672 t.Logf("Metadata: %#v", image.Metadata)
673 t.Logf("Created: %s", image.Created)
674 t.Logf("Updated: %s", image.Updated)
675}
676
677// PrintKeyPair will print keypair and all of its attributes.
678func PrintKeyPair(t *testing.T, keypair *keypairs.KeyPair) {
679 t.Logf("Name: %s", keypair.Name)
680 t.Logf("Fingerprint: %s", keypair.Fingerprint)
681 t.Logf("Public Key: %s", keypair.PublicKey)
682 t.Logf("Private Key: %s", keypair.PrivateKey)
683 t.Logf("UserID: %s", keypair.UserID)
684}
685
686// PrintNetwork will print an os-networks based network and all of its attributes.
687func PrintNetwork(t *testing.T, network *networks.Network) {
688 t.Logf("Bridge: %s", network.Bridge)
689 t.Logf("BridgeInterface: %s", network.BridgeInterface)
690 t.Logf("Broadcast: %s", network.Broadcast)
691 t.Logf("CIDR: %s", network.CIDR)
692 t.Logf("CIDRv6: %s", network.CIDRv6)
693 t.Logf("CreatedAt: %v", network.CreatedAt)
694 t.Logf("Deleted: %t", network.Deleted)
695 t.Logf("DeletedAt: %v", network.DeletedAt)
696 t.Logf("DHCPStart: %s", network.DHCPStart)
697 t.Logf("DNS1: %s", network.DNS1)
698 t.Logf("DNS2: %s", network.DNS2)
699 t.Logf("Gateway: %s", network.Gateway)
700 t.Logf("Gatewayv6: %s", network.Gatewayv6)
701 t.Logf("Host: %s", network.Host)
702 t.Logf("ID: %s", network.ID)
703 t.Logf("Injected: %t", network.Injected)
704 t.Logf("Label: %s", network.Label)
705 t.Logf("MultiHost: %t", network.MultiHost)
706 t.Logf("Netmask: %s", network.Netmask)
707 t.Logf("Netmaskv6: %s", network.Netmaskv6)
708 t.Logf("Priority: %d", network.Priority)
709 t.Logf("ProjectID: %s", network.ProjectID)
710 t.Logf("RXTXBase: %d", network.RXTXBase)
711 t.Logf("UpdatedAt: %v", network.UpdatedAt)
712 t.Logf("VLAN: %d", network.VLAN)
713 t.Logf("VPNPrivateAddress: %s", network.VPNPrivateAddress)
714 t.Logf("VPNPublicAddress: %s", network.VPNPublicAddress)
715 t.Logf("VPNPublicPort: %d", network.VPNPublicPort)
716}
717
718// PrintQuotaSet will print a quota set and all of its attributes.
719func PrintQuotaSet(t *testing.T, quotaSet *quotasets.QuotaSet) {
720 t.Logf("instances: %d\n", quotaSet.Instances)
721 t.Logf("cores: %d\n", quotaSet.Cores)
722 t.Logf("ram: %d\n", quotaSet.Ram)
723 t.Logf("key_pairs: %d\n", quotaSet.KeyPairs)
724 t.Logf("metadata_items: %d\n", quotaSet.MetadataItems)
725 t.Logf("security_groups: %d\n", quotaSet.SecurityGroups)
726 t.Logf("security_group_rules: %d\n", quotaSet.SecurityGroupRules)
727 t.Logf("fixed_ips: %d\n", quotaSet.FixedIps)
728 t.Logf("floating_ips: %d\n", quotaSet.FloatingIps)
729 t.Logf("injected_file_content_bytes: %d\n", quotaSet.InjectedFileContentBytes)
730 t.Logf("injected_file_path_bytes: %d\n", quotaSet.InjectedFilePathBytes)
731 t.Logf("injected_files: %d\n", quotaSet.InjectedFiles)
732}
733
734// PrintSecurityGroup will print a security group and all of its attributes and rules.
735func PrintSecurityGroup(t *testing.T, securityGroup *secgroups.SecurityGroup) {
736 t.Logf("ID: %s", securityGroup.ID)
737 t.Logf("Name: %s", securityGroup.Name)
738 t.Logf("Description: %s", securityGroup.Description)
739 t.Logf("Tenant ID: %s", securityGroup.TenantID)
740 t.Logf("Rules:")
741
742 for _, rule := range securityGroup.Rules {
743 t.Logf("\tID: %s", rule.ID)
744 t.Logf("\tFrom Port: %d", rule.FromPort)
745 t.Logf("\tTo Port: %d", rule.ToPort)
746 t.Logf("\tIP Protocol: %s", rule.IPProtocol)
747 t.Logf("\tIP Range: %s", rule.IPRange.CIDR)
748 t.Logf("\tParent Group ID: %s", rule.ParentGroupID)
749 t.Logf("\tGroup Tenant ID: %s", rule.Group.TenantID)
750 t.Logf("\tGroup Name: %s", rule.Group.Name)
751 }
752}
753
754// PrintServerGroup will print a server group and all of its attributes.
755func PrintServerGroup(t *testing.T, serverGroup *servergroups.ServerGroup) {
756 t.Logf("ID: %s", serverGroup.ID)
757 t.Logf("Name: %s", serverGroup.Name)
758 t.Logf("Policies: %#v", serverGroup.Policies)
759 t.Logf("Members: %#v", serverGroup.Members)
760 t.Logf("Metadata: %#v", serverGroup.Metadata)
761}
762
763// PrintTenantNetwork will print an os-tenant-networks based network and all of its attributes.
764func PrintTenantNetwork(t *testing.T, network *tenantnetworks.Network) {
765 t.Logf("ID: %s", network.ID)
766 t.Logf("Name: %s", network.Name)
767 t.Logf("CIDR: %s", network.CIDR)
768}
769
770// PrintVolumeAttachment will print a volume attachment and all of its attributes.
771func PrintVolumeAttachment(t *testing.T, volumeAttachment *volumeattach.VolumeAttachment) {
772 t.Logf("ID: %s", volumeAttachment.ID)
773 t.Logf("Device: %s", volumeAttachment.Device)
774 t.Logf("VolumeID: %s", volumeAttachment.VolumeID)
775 t.Logf("ServerID: %s", volumeAttachment.ServerID)
776}