Skip to content

Commit

Permalink
Merge pull request #571 from zeenix/pool-resource
Browse files Browse the repository at this point in the history
Add storage pool resource
  • Loading branch information
MalloZup committed May 17, 2019
2 parents 709e1db + 476095b commit c573bc1
Show file tree
Hide file tree
Showing 7 changed files with 650 additions and 1 deletion.
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
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

0 comments on commit c573bc1

Please sign in to comment.