@@ -89,6 +89,88 @@ func testAccCheckLibvirtVolumeIsBackingStore(name string) resource.TestCheckFunc
8989 }
9090}
9191
92+ func testAccCheckLibvirtVolumeDoesNotHaveBackingStore (name string ) resource.TestCheckFunc {
93+ return func (state * terraform.State ) error {
94+ virConn := testAccProvider .Meta ().(* Client ).libvirt
95+
96+ vol , err := getVolumeFromTerraformState (name , state , virConn )
97+ if err != nil {
98+ return err
99+ }
100+
101+ volXMLDesc , err := virConn .StorageVolGetXMLDesc (* vol , 0 )
102+ if err != nil {
103+ return fmt .Errorf ("Error retrieving libvirt volume XML description: %s" , err )
104+ }
105+
106+ volumeDef := newDefVolume ()
107+ err = xml .Unmarshal ([]byte (volXMLDesc ), & volumeDef )
108+ if err != nil {
109+ return fmt .Errorf ("Error reading libvirt volume XML description: %s" , err )
110+ }
111+
112+ if volumeDef .BackingStore != nil {
113+ return fmt .Errorf ("FAIL: volume has a backing store, but it shouldn't" )
114+ }
115+
116+ return nil
117+ }
118+ }
119+
120+ func testAccCheckLibvirtVolumeExpectedCapacity (name string , expectedCapacity uint64 ) resource.TestCheckFunc {
121+ return func (state * terraform.State ) error {
122+ virConn := testAccProvider .Meta ().(* Client ).libvirt
123+
124+ vol , err := getVolumeFromTerraformState (name , state , virConn )
125+ if err != nil {
126+ return err
127+ }
128+
129+ _ , capacity , _ , err := virConn .StorageVolGetInfo (* vol )
130+ if err != nil {
131+ return fmt .Errorf ("Error retrieving libvirt volume info: %s" , err )
132+ }
133+
134+ if expectedCapacity != capacity {
135+ return fmt .Errorf ("FAIL: volume capacity is supposed to be %d bytes, but it's %d bytes" , expectedCapacity , capacity )
136+ }
137+
138+ return nil
139+ }
140+ }
141+
142+ func testAccCheckLibvirtVolumeExpectedFormat (name , expectedFormat string ) resource.TestCheckFunc {
143+ return func (state * terraform.State ) error {
144+ virConn := testAccProvider .Meta ().(* Client ).libvirt
145+
146+ vol , err := getVolumeFromTerraformState (name , state , virConn )
147+ if err != nil {
148+ return err
149+ }
150+
151+ volXMLDesc , err := virConn .StorageVolGetXMLDesc (* vol , 0 )
152+ if err != nil {
153+ return fmt .Errorf ("Error retrieving libvirt volume XML description: %s" , err )
154+ }
155+
156+ volumeDef := newDefVolume ()
157+ err = xml .Unmarshal ([]byte (volXMLDesc ), & volumeDef )
158+ if err != nil {
159+ return fmt .Errorf ("Error reading libvirt volume XML description: %s" , err )
160+ }
161+
162+ if volumeDef .Target == nil {
163+ return fmt .Errorf ("FAIL: volume XML description doesn't contain target element" )
164+ } else if volumeDef .Target .Format == nil {
165+ return fmt .Errorf ("FAIL: volume XML description doesn't contain target.format element" )
166+ } else if volumeDef .Target .Format .Type != expectedFormat {
167+ return fmt .Errorf ("FAIL: volume format is supposed to be '%s', but it is '%s'" , expectedFormat , volumeDef .Target .Format .Type )
168+ }
169+
170+ return nil
171+ }
172+ }
173+
92174func TestAccLibvirtVolume_Basic (t * testing.T ) {
93175 var volume libvirt.StorageVol
94176 randomVolumeResource := acctest .RandStringFromCharSet (10 , acctest .CharSetAlpha )
@@ -201,6 +283,103 @@ func TestAccLibvirtVolume_BackingStoreTestByName(t *testing.T) {
201283 })
202284}
203285
286+ func TestAccLibvirtVolume_BackingStoreCopy (t * testing.T ) {
287+ randomStr := acctest .RandStringFromCharSet (10 , acctest .CharSetAlpha )
288+ poolPath := "/tmp/terraform-provider-libvirt-pool-" + randomStr
289+ var baseSize uint64 = 5 * 1024 * 1024
290+ var copySize uint64 = 10 * 1024 * 1024
291+ config := fmt .Sprintf (`
292+ resource "libvirt_pool" "pool_%[1]s" {
293+ name = "pool-%[1]s"
294+ type = "dir"
295+ path = "%[2]s"
296+ }
297+
298+ resource "libvirt_volume" "base_raw_%[1]s" {
299+ name = "base-raw-%[1]s"
300+ format = "raw"
301+ size = "%[3]d"
302+ pool = "${libvirt_pool.pool_%[1]s.name}"
303+ }
304+
305+ resource "libvirt_volume" "base_qcow2_%[1]s" {
306+ name = "base-qcow2-%[1]s"
307+ format = "qcow2"
308+ size = "%[3]d"
309+ pool = "${libvirt_pool.pool_%[1]s.name}"
310+ }
311+
312+ resource "libvirt_volume" "copy_raw_from_raw_%[1]s" {
313+ name = "copy-raw-from-raw-%[1]s"
314+ format = "raw"
315+ size = "%[4]d"
316+ base_volume_copy = true
317+ base_volume_id = "${libvirt_volume.base_raw_%[1]s.id}"
318+ pool = "${libvirt_pool.pool_%[1]s.name}"
319+ }
320+
321+ resource "libvirt_volume" "copy_raw_from_qcow2_%[1]s" {
322+ name = "copy-raw-from-qcow2_%[1]s"
323+ format = "raw"
324+ size = "%[4]d"
325+ base_volume_copy = true
326+ base_volume_id = "${libvirt_volume.base_qcow2_%[1]s.id}"
327+ pool = "${libvirt_pool.pool_%[1]s.name}"
328+ }
329+
330+ resource "libvirt_volume" "copy_qcow2_from_raw_%[1]s" {
331+ name = "copy-qcow2-from-raw-%[1]s"
332+ format = "qcow2"
333+ size = "%[4]d"
334+ base_volume_copy = true
335+ base_volume_id = "${libvirt_volume.base_raw_%[1]s.id}"
336+ pool = "${libvirt_pool.pool_%[1]s.name}"
337+ }
338+
339+ resource "libvirt_volume" "copy_qcow2_from_qcow2_%[1]s" {
340+ name = "copy-qcow2-from-qcow2-%[1]s"
341+ format = "qcow2"
342+ size = "%[4]d"
343+ base_volume_copy = true
344+ base_volume_id = "${libvirt_volume.base_qcow2_%[1]s.id}"
345+ pool = "${libvirt_pool.pool_%[1]s.name}"
346+ }
347+ ` , randomStr , poolPath , baseSize , copySize )
348+
349+ volumes := map [string ]string {
350+ "copy_raw_from_raw_" : "raw" ,
351+ "copy_raw_from_qcow2_" : "raw" ,
352+ "copy_qcow2_from_raw_" : "qcow2" ,
353+ "copy_qcow2_from_qcow2_" : "qcow2" ,
354+ }
355+ var volume libvirt.StorageVol
356+ testCheckFuncs := []resource.TestCheckFunc {}
357+ for baseName , format := range volumes {
358+ fullName := "libvirt_volume." + baseName + randomStr
359+ testCheckFuncs = append (testCheckFuncs ,
360+ testAccCheckLibvirtVolumeExists (fullName , & volume ),
361+ testAccCheckLibvirtVolumeDoesNotHaveBackingStore (fullName ),
362+ testAccCheckLibvirtVolumeExpectedCapacity (fullName , copySize ),
363+ testAccCheckLibvirtVolumeExpectedFormat (fullName , format ),
364+ )
365+ }
366+
367+ resource .Test (t , resource.TestCase {
368+ PreCheck : func () { testAccPreCheck (t ) },
369+ Providers : testAccProviders ,
370+ CheckDestroy : resource .ComposeAggregateTestCheckFunc (
371+ testAccCheckLibvirtVolumeDestroy ,
372+ testAccCheckLibvirtPoolDestroy ,
373+ ),
374+ Steps : []resource.TestStep {
375+ {
376+ Config : config ,
377+ Check : resource .ComposeTestCheckFunc (testCheckFuncs ... ),
378+ },
379+ },
380+ })
381+ }
382+
204383// The destroy function should always handle the case where the resource might already be destroyed
205384// (manually, for example). If the resource is already destroyed, this should not return an error.
206385// This allows Terraform users to manually delete resources without breaking Terraform.
0 commit comments