-
Notifications
You must be signed in to change notification settings - Fork 456
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add directory-based storage pool resource
This patch adds a resource type for directory-based libvirt storage pool. Known issue: The test `TestAccLibvirtPool_ManuallyDestroyed` and currently fail. I failed to find out why yet. Fixes #435.
- Loading branch information
Showing
6 changed files
with
526 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,232 @@ | ||
package libvirt | ||
|
||
import ( | ||
"encoding/xml" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/libvirt/libvirt-go-xml" | ||
) | ||
|
||
func resourceLibvirtDirPool() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceLibvirtDirPoolCreate, | ||
Read: resourceLibvirtDirPoolRead, | ||
Delete: resourceLibvirtDirPoolDelete, | ||
Exists: resourceLibvirtDirPoolExists, | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"path": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"capacity": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"allocation": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"available": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Optional: true, | ||
ForceNew: true, | ||
}, | ||
"xml": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
MaxItems: 1, | ||
ForceNew: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"xslt": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
} | ||
} | ||
|
||
func resourceLibvirtDirPoolCreate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
if client.libvirt == nil { | ||
return fmt.Errorf(LibVirtConIsNil) | ||
} | ||
|
||
poolName := d.Get("name").(string) | ||
|
||
client.poolMutexKV.Lock(poolName) | ||
defer client.poolMutexKV.Unlock(poolName) | ||
|
||
// Check whether the storage pool already exists. Its name needs to be | ||
// unique. | ||
if _, err := client.libvirt.LookupStoragePoolByName(poolName); err == nil { | ||
return fmt.Errorf("storage pool '%s' already exists", poolName) | ||
} | ||
log.Printf("[DEBUG] Pool with name '%s' does not exist yet", poolName) | ||
|
||
poolPath := d.Get("path").(string) | ||
poolDef := libvirtxml.StoragePool{ | ||
// We only support "dir" type at the moment | ||
Type: "dir", | ||
Name: poolName, | ||
Target: &libvirtxml.StoragePoolTarget{ | ||
Path: poolPath, | ||
}, | ||
} | ||
data, err := xmlMarshallIndented(poolDef) | ||
if err != nil { | ||
return fmt.Errorf("Error serializing libvirt storage pool: %s", err) | ||
} | ||
log.Printf("[DEBUG] Generated XML for libvirt storage pool:\n%s", data) | ||
|
||
data, err = transformResourceXML(data, d) | ||
if err != nil { | ||
return fmt.Errorf("Error applying XSLT stylesheet: %s", err) | ||
} | ||
|
||
// create the pool | ||
pool, err := client.libvirt.StoragePoolDefineXML(data, 0) | ||
if err != nil { | ||
return fmt.Errorf("Error creating libvirt storage pool: %s", err) | ||
} | ||
defer pool.Free() | ||
|
||
err = pool.Build(0) | ||
if err != nil { | ||
return fmt.Errorf("Error building libvirt storage pool: %s", err) | ||
} | ||
|
||
err = pool.SetAutostart(true) | ||
if err != nil { | ||
return fmt.Errorf("Error setting up libvirt storage pool: %s", err) | ||
} | ||
|
||
err = pool.Create(0) | ||
if err != nil { | ||
return fmt.Errorf("Error starting libvirt storage pool: %s", err) | ||
} | ||
|
||
err = pool.Refresh(0) | ||
if err != nil { | ||
return fmt.Errorf("Error refreshing libvirt storage pool: %s", err) | ||
} | ||
|
||
id, err := pool.GetUUIDString() | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving libvirt pool id: %s", err) | ||
} | ||
d.SetId(id) | ||
|
||
// make sure we record the id even if the rest of this gets interrupted | ||
d.Partial(true) | ||
d.Set("id", id) | ||
d.SetPartial("id") | ||
d.Partial(false) | ||
|
||
log.Printf("[INFO] Pool ID: %s", d.Id()) | ||
|
||
return resourceLibvirtDirPoolRead(d, meta) | ||
} | ||
|
||
func resourceLibvirtDirPoolRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
virConn := client.libvirt | ||
if virConn == nil { | ||
return fmt.Errorf(LibVirtConIsNil) | ||
} | ||
|
||
pool, err := virConn.LookupStoragePoolByUUIDString(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving libvirt storage pool: %s", err) | ||
} | ||
defer pool.Free() | ||
|
||
poolName, err := pool.GetName() | ||
if err != nil { | ||
return fmt.Errorf("error retrieving pool name: %s", err) | ||
} | ||
d.Set("name", poolName) | ||
|
||
info, err := pool.GetInfo() | ||
if err != nil { | ||
return fmt.Errorf("error retrieving pool info: %s", err) | ||
} | ||
d.Set("capacity", info.Capacity) | ||
d.Set("allocation", info.Allocation) | ||
d.Set("available", info.Available) | ||
|
||
poolDefXML, err := pool.GetXMLDesc(0) | ||
if err != nil { | ||
return fmt.Errorf("could not get XML description for pool %s: %s", poolName, err) | ||
} | ||
|
||
var poolDef libvirtxml.StoragePool | ||
err = xml.Unmarshal([]byte(poolDefXML), &poolDef) | ||
if err != nil { | ||
return fmt.Errorf("could not get a pool definition from XML for %s: %s", poolDef.Name, err) | ||
} | ||
|
||
var poolPath string | ||
if poolDef.Target != nil && poolDef.Target.Path != "" { | ||
poolPath = poolDef.Target.Path | ||
} | ||
|
||
if poolPath == "" { | ||
log.Printf("Pool %s has no path specified", poolName) | ||
} else { | ||
log.Printf("[DEBUG] Pool %s path: %s", poolName, poolPath) | ||
d.Set("path", poolPath) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceLibvirtDirPoolDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
if client.libvirt == nil { | ||
return fmt.Errorf(LibVirtConIsNil) | ||
} | ||
|
||
return removePool(client, d.Id()) | ||
} | ||
|
||
func resourceLibvirtDirPoolExists(d *schema.ResourceData, meta interface{}) (bool, error) { | ||
log.Printf("[DEBUG] Check if resource libvirt_dir_pool exists") | ||
client := meta.(*Client) | ||
virConn := client.libvirt | ||
if virConn == nil { | ||
return false, fmt.Errorf(LibVirtConIsNil) | ||
} | ||
|
||
pool, err := virConn.LookupStoragePoolByUUIDString(d.Id()) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if pool == nil { | ||
return false, fmt.Errorf("Failed to retrieve pool with ID %s", d.Id()) | ||
} | ||
defer pool.Free() | ||
|
||
return true, nil | ||
} |
Oops, something went wrong.