Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add storage pool resource #571

Merged
merged 2 commits into from
May 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion examples/ubuntu/ubuntu-example.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ provider "libvirt" {
uri = "qemu:///system"
}

resource "libvirt_pool" "ubuntu" {
name = "ubuntu"
type = "dir"
path = "/tmp/terraform-provider-libvirt-pool-ubuntu"
}

# We fetch the latest ubuntu release image from their mirrors
resource "libvirt_volume" "ubuntu-qcow2" {
name = "ubuntu-qcow2"
pool = "default"
pool = "${libvirt_pool.ubuntu.name}"
source = "https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img"
format = "qcow2"
}
Expand All @@ -27,6 +33,7 @@ resource "libvirt_cloudinit_disk" "commoninit" {
name = "commoninit.iso"
user_data = "${data.template_file.user_data.rendered}"
network_config = "${data.template_file.network_config.rendered}"
pool = "${libvirt_pool.ubuntu.name}"
}

# Create the machine
Expand Down
15 changes: 15 additions & 0 deletions libvirt/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ func getResourceFromTerraformState(resourceName string, state *terraform.State)

// ** resource specifics helpers **

// getPoolFromTerraformState lookup pool by name and return the libvirt pool from a terraform state
func getPoolFromTerraformState(name string, state *terraform.State, virConn libvirt.Connect) (*libvirt.StoragePool, error) {
rs, err := getResourceFromTerraformState(name, state)
if err != nil {
return nil, err
}

pool, err := virConn.LookupStoragePoolByUUIDString(rs.Primary.ID)
if err != nil {
return nil, err
}
log.Printf("[DEBUG]:The ID is %s", rs.Primary.ID)
return pool, nil
}

// getVolumeFromTerraformState lookup volume by name and return the libvirt volume from a terraform state
func getVolumeFromTerraformState(name string, state *terraform.State, virConn libvirt.Connect) (*libvirt.StorageVol, error) {
rs, err := getResourceFromTerraformState(name, state)
Expand Down
115 changes: 115 additions & 0 deletions libvirt/pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package libvirt

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
libvirt "github.com/libvirt/libvirt-go"
)

const (
poolExistsID = "EXISTS"
poolNotExistsID = "NOT-EXISTS"
)

// poolExists returns "EXISTS" or "NOT-EXISTS" depending on the current pool existence
MalloZup marked this conversation as resolved.
Show resolved Hide resolved
func poolExists(virConn *libvirt.Connect, uuid string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
pool, err := virConn.LookupStoragePoolByUUIDString(uuid)
if err != nil {
if err.(libvirt.Error).Code == libvirt.ERR_NO_STORAGE_POOL {
log.Printf("Pool %s does not exist", uuid)
return virConn, "NOT-EXISTS", nil
}
log.Printf("Pool %s: error: %s", uuid, err.(libvirt.Error).Message)
}
if pool != nil {
defer pool.Free()
}
return virConn, poolExistsID, err
}
}

// poolWaitForExists waits for a storage pool to be up and timeout after 5 minutes.
func poolWaitForExists(virConn *libvirt.Connect, uuid string) error {
log.Printf("Waiting for pool %s to be active...", uuid)
stateConf := &resource.StateChangeConf{
Pending: []string{poolNotExistsID},
Target: []string{poolExistsID},
Refresh: poolExists(virConn, uuid),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

if _, err := stateConf.WaitForState(); err != nil {
log.Printf("%s", err)
return fmt.Errorf("unexpected error during pool creation operation. The operation did not complete successfully")
}
return nil
}

// poolWaitDeleted waits for a storage pool to be removed
func poolWaitDeleted(virConn *libvirt.Connect, uuid string) error {
log.Printf("Waiting for pool %s to be deleted...", uuid)
stateConf := &resource.StateChangeConf{
Pending: []string{poolExistsID},
Target: []string{poolNotExistsID},
Refresh: poolExists(virConn, uuid),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

if _, err := stateConf.WaitForState(); err != nil {
log.Printf("%s", err)
return fmt.Errorf("unexpected error during pool destroy operation. The pool was not deleted")
}
return nil
}

// deletePool deletes the pool identified by `uuid` from libvirt
func deletePool(client *Client, uuid string) error {
virConn := client.libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
}

pool, err := virConn.LookupStoragePoolByUUIDString(uuid)
if err != nil {
return fmt.Errorf("error retrieving storage pool info: %s", err)
}

poolName, err := pool.GetName()
if err != nil {
return fmt.Errorf("error retrieving storage pool name: %s", err)
}
client.poolMutexKV.Lock(poolName)
defer client.poolMutexKV.Unlock(poolName)

info, err := pool.GetInfo()
if err != nil {
return fmt.Errorf("error retrieving storage pool info: %s", err)
}

if info.State != libvirt.STORAGE_POOL_INACTIVE {
err := pool.Destroy()
if err != nil {
return fmt.Errorf("error deleting storage pool: %s", err)
}
}

err = pool.Delete(0)
if err != nil {
return fmt.Errorf("error deleting storage pool: %s", err)
}

err = pool.Undefine()
if err != nil {
return fmt.Errorf("error deleting storage pool: %s", err)
}

return poolWaitDeleted(client.libvirt, uuid)
}
1 change: 1 addition & 0 deletions libvirt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func Provider() terraform.ResourceProvider {
"libvirt_domain": resourceLibvirtDomain(),
"libvirt_volume": resourceLibvirtVolume(),
"libvirt_network": resourceLibvirtNetwork(),
"libvirt_pool": resourceLibvirtPool(),
"libvirt_cloudinit_disk": resourceCloudInitDisk(),
"libvirt_ignition": resourceIgnition(),
},
Expand Down