@@ -89,6 +89,88 @@ func testAccCheckLibvirtVolumeIsBackingStore(name string) resource.TestCheckFunc
89
89
}
90
90
}
91
91
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: %w" , 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: %w" , 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: %w" , 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: %w" , 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: %w" , 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
+
92
174
func TestAccLibvirtVolume_Basic (t * testing.T ) {
93
175
var volume libvirt.StorageVol
94
176
randomVolumeResource := acctest .RandStringFromCharSet (10 , acctest .CharSetAlpha )
@@ -201,6 +283,103 @@ func TestAccLibvirtVolume_BackingStoreTestByName(t *testing.T) {
201
283
})
202
284
}
203
285
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
+
204
383
// The destroy function should always handle the case where the resource might already be destroyed
205
384
// (manually, for example). If the resource is already destroyed, this should not return an error.
206
385
// This allows Terraform users to manually delete resources without breaking Terraform.
0 commit comments