-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #157 from imjoey/new_r_snapshot
New Resource: ovirt_snapshot
- Loading branch information
Showing
5 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package ovirt | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
ovirtsdk4 "github.com/ovirt/go-ovirt" | ||
) | ||
|
||
func resourceOvirtSnapshot() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceOvirtSnapshotCreate, | ||
Read: resourceOvirtSnapshotRead, | ||
Delete: resourceOvirtSnapshotDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(10 * time.Minute), | ||
Update: schema.DefaultTimeout(10 * time.Minute), | ||
Delete: schema.DefaultTimeout(10 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"vm_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"save_memory": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: true, | ||
ForceNew: true, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
// Computed | ||
"status": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"date": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceOvirtSnapshotCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*ovirtsdk4.Connection) | ||
builder := ovirtsdk4.NewSnapshotBuilder() | ||
|
||
builder.Description(d.Get("description").(string)). | ||
PersistMemorystate(d.Get("save_memory").(bool)) | ||
|
||
vmID := d.Get("vm_id").(string) | ||
snapshotsService := conn.SystemService().VmsService().VmService(vmID).SnapshotsService() | ||
|
||
resp, err := snapshotsService. | ||
Add(). | ||
Snapshot(builder.MustBuild()). | ||
Send() | ||
if err != nil { | ||
log.Printf("[DEBUG] Error creating Snapshot for VM (%s): %s", vmID, err) | ||
return nil | ||
} | ||
|
||
snapshotID := resp.MustSnapshot().MustId() | ||
d.SetId(vmID + ":" + snapshotID) | ||
|
||
// Wait for snapshot is OK | ||
log.Printf("[DEBUG] Snapshot (%s) is created and wait for ready (status is OK)", d.Id()) | ||
okStateConf := &resource.StateChangeConf{ | ||
Pending: []string{string(ovirtsdk4.SNAPSHOTSTATUS_LOCKED)}, | ||
Target: []string{string(ovirtsdk4.SNAPSHOTSTATUS_OK)}, | ||
Refresh: SnapshotStateRefreshFunc(conn, vmID, snapshotID), | ||
Timeout: d.Timeout(schema.TimeoutCreate), | ||
Delay: 10 * time.Second, | ||
MinTimeout: 3 * time.Second, | ||
} | ||
_, err = okStateConf.WaitForState() | ||
if err != nil { | ||
log.Printf("[DEBUG] Failed to wait for Snapshot (%s) to become OK: %s", d.Id(), err) | ||
return err | ||
} | ||
|
||
return resourceOvirtSnapshotRead(d, meta) | ||
} | ||
|
||
func resourceOvirtSnapshotRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*ovirtsdk4.Connection) | ||
vmID, snapshotID, err := getVMIDAndSnapshotID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.Set("vm_id", vmID) | ||
|
||
snapshotService := conn.SystemService(). | ||
VmsService(). | ||
VmService(vmID). | ||
SnapshotsService(). | ||
SnapshotService(snapshotID) | ||
|
||
snapshotResp, err := snapshotService.Get().Send() | ||
if err != nil { | ||
if _, ok := err.(*ovirtsdk4.NotFoundError); ok { | ||
d.SetId("") | ||
return nil | ||
} | ||
log.Printf("[DEBUG] Failed to get Snapshot (%s): %s", d.Id(), err) | ||
return err | ||
} | ||
snapshot := snapshotResp.MustSnapshot() | ||
|
||
d.Set("description", snapshot.MustDescription()) | ||
d.Set("save_memory", snapshot.MustPersistMemorystate()) | ||
d.Set("status", string(snapshot.MustSnapshotStatus())) | ||
d.Set("type", string(snapshot.MustSnapshotType())) | ||
d.Set("date", snapshot.MustDate().Format(time.RFC3339)) | ||
|
||
return nil | ||
} | ||
|
||
func resourceOvirtSnapshotDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*ovirtsdk4.Connection) | ||
vmID, snapshotID, err := getVMIDAndSnapshotID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
snapshotService := conn.SystemService(). | ||
VmsService(). | ||
VmService(vmID). | ||
SnapshotsService(). | ||
SnapshotService(snapshotID) | ||
|
||
return resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { | ||
log.Printf("[DEBUG] Now to remove Snapshot (%s)", d.Id()) | ||
_, err := snapshotService.Remove().Send() | ||
if err != nil { | ||
if _, ok := err.(*ovirtsdk4.NotFoundError); ok { | ||
// Wait until NotFoundError raises | ||
log.Printf("[DEBUG] Snapshot (%s) has been removed", d.Id()) | ||
return nil | ||
} | ||
return resource.RetryableError(fmt.Errorf("Error removing Snapshot (%s): %s", d.Id(), err)) | ||
} | ||
return resource.RetryableError(fmt.Errorf("Snapshot (%s) is still being removed", d.Id())) | ||
}) | ||
} | ||
|
||
// SnapshotStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch | ||
// an oVirt Snapshot. | ||
func SnapshotStateRefreshFunc(conn *ovirtsdk4.Connection, vmID, snapshotID string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
r, err := conn.SystemService(). | ||
VmsService(). | ||
VmService(vmID). | ||
SnapshotsService(). | ||
SnapshotService(snapshotID). | ||
Get(). | ||
Send() | ||
|
||
if err != nil { | ||
if _, ok := err.(*ovirtsdk4.NotFoundError); ok { | ||
return nil, "", nil | ||
} | ||
return nil, "", err | ||
} | ||
|
||
return r.MustSnapshot, string(r.MustSnapshot().MustSnapshotStatus()), nil | ||
} | ||
} | ||
|
||
func getVMIDAndSnapshotID(rsID string) (string, string, error) { | ||
parts := strings.Split(rsID, ":") | ||
if len(parts) != 2 { | ||
return "", "", fmt.Errorf("Invalid Snapshot ID: %s", rsID) | ||
} | ||
return parts[0], parts[1], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package ovirt | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
ovirtsdk4 "github.com/ovirt/go-ovirt" | ||
) | ||
|
||
func TestAccOvirtSnapshot_basic(t *testing.T) { | ||
description := "description for snapshot" | ||
vmID := "53000b15-82ad-4ed4-9f86-bffb95e3c28b" | ||
saveMemory := true | ||
|
||
var snapshot ovirtsdk4.Snapshot | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
IDRefreshName: "ovirt_snapshot.snapshot", | ||
CheckDestroy: testAccCheckSnapshotDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccSnapshotBasic(description, vmID, saveMemory), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckOvirtSnapshotExists("ovirt_snapshot.snapshot", &snapshot), | ||
resource.TestCheckResourceAttr("ovirt_snapshot.snapshot", "description", description), | ||
resource.TestCheckResourceAttr("ovirt_snapshot.snapshot", "vm_id", vmID), | ||
resource.TestCheckResourceAttr("ovirt_snapshot.snapshot", "save_memory", fmt.Sprintf("%t", saveMemory)), | ||
resource.TestCheckResourceAttr("ovirt_snapshot.snapshot", "status", string(ovirtsdk4.SNAPSHOTSTATUS_OK)), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckSnapshotDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*ovirtsdk4.Connection) | ||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "ovirt_snapshot" { | ||
continue | ||
} | ||
|
||
vmID, snapshotID, err := getVMIDAndSnapshotID(rs.Primary.ID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
getResp, err := conn.SystemService(). | ||
VmsService(). | ||
VmService(vmID). | ||
SnapshotsService(). | ||
SnapshotService(snapshotID). | ||
Get(). | ||
Send() | ||
|
||
if err != nil { | ||
if _, ok := err.(*ovirtsdk4.NotFoundError); ok { | ||
continue | ||
} | ||
return err | ||
} | ||
if _, ok := getResp.Snapshot(); ok { | ||
return fmt.Errorf("Snapshot %s still exist", rs.Primary.ID) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func testAccCheckOvirtSnapshotExists(n string, v *ovirtsdk4.Snapshot) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No Snapshot ID is set") | ||
} | ||
|
||
vmID, snapshotID, err := getVMIDAndSnapshotID(rs.Primary.ID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
conn := testAccProvider.Meta().(*ovirtsdk4.Connection) | ||
getResp, err := conn.SystemService(). | ||
VmsService(). | ||
VmService(vmID). | ||
SnapshotsService(). | ||
SnapshotService(snapshotID). | ||
Get(). | ||
Send() | ||
if err != nil { | ||
return err | ||
} | ||
snapshot, ok := getResp.Snapshot() | ||
if ok { | ||
*v = *snapshot | ||
return nil | ||
} | ||
return fmt.Errorf("Snapshot %s not exist", rs.Primary.ID) | ||
} | ||
} | ||
|
||
func testAccSnapshotBasic(description, vmID string, saveMemory bool) string { | ||
return fmt.Sprintf(` | ||
resource "ovirt_snapshot" "snapshot" { | ||
description = "%s" | ||
vm_id = "%s" | ||
save_memory = %t | ||
} | ||
`, description, vmID, saveMemory) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
--- | ||
layout: "ovirt" | ||
page_title: "oVirt: ovirt_snapshot" | ||
sidebar_current: "docs-ovirt-resource-snapshot" | ||
description: |- | ||
Manages a Snapshot of vm resource within oVirt. | ||
--- | ||
|
||
# ovirt\_snapshot | ||
|
||
Manages a Snapshot of VM resource within oVirt. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "ovirt_snapshot" "snapshot" { | ||
description = "description-of-snasphot" | ||
vm_id = "53000b15-82ad-4ed4-9f86-bffb95e3c28b" | ||
save_memory = true | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `description` - (Required) A description of the snapshot. Changing this creates a new snapshot. | ||
* `vm_id` - (Required) The ID of vm the snapshot taken from. Changing this creates a new snapshot. | ||
* `save_memory` - (Optional) The flag to indicate whether the content of the memory of the vm is included in the snapshot. Default is `true`. Changing this creates a new snapshot. | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `id` - The composite ID of the snapshot which is constituted by the ID of the vm the snapshot taken from and the ID of the snapshot within oVirt. | ||
* `status` - The status of the snapshot. Can be "in_preview", "locked" or "ok". | ||
* `type` - The type of the snapshot. Can be "active", "preview", "regular" or "stateless". | ||
* `date` - The string representation of the creation time of the snapshot in RFC3339 format. | ||
|
||
## Import | ||
|
||
Snapshots can be imported using the composite `id`, e.g. | ||
|
||
``` | ||
$ terraform import ovirt_snapshot.snapshot 53000b15-82ad-4ed4-9f86-bffb95e3c28b:df736600-b8be-4029-be98-4b0611be6be4 | ||
``` |