Skip to content

Commit

Permalink
fix a possible race condition by iso disk download
Browse files Browse the repository at this point in the history
  • Loading branch information
MalloZup committed Nov 17, 2018
1 parent b1eec54 commit a354053
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 10 deletions.
34 changes: 32 additions & 2 deletions libvirt/cloudinit_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,10 @@ func (ci *defCloudInit) createFiles() (string, error) {

// Creates a new defCloudInit object starting from a ISO volume handled by
// libvirt
func newCloudInitDefFromRemoteISO(virConn *libvirt.Connect, id string) (defCloudInit, error) {
func newCloudInitDefFromRemoteISO(virConn *libvirt.Connect, id string, client *Client) (defCloudInit, error) {
ci := defCloudInit{}

// get cloudinit volume from ID
key, err := getCloudInitVolumeKeyFromTerraformID(id)
if err != nil {
return ci, err
Expand All @@ -205,6 +206,33 @@ func newCloudInitDefFromRemoteISO(virConn *libvirt.Connect, id string) (defCloud
}
defer volume.Free()

// get poolname so we can lock pool after
volPool, err := volume.LookupPoolByVolume()
if err != nil {
return ci, fmt.Errorf("error retrieving pool for volume: %s", err)
}
defer volPool.Free()

volPoolName, err := volPool.GetName()
if err != nil {
return ci, fmt.Errorf("error retrieving pool name: %s", err)
}

pool, err := client.libvirt.LookupStoragePoolByName(volPoolName)
if err != nil {
return ci, fmt.Errorf("can't find storage pool '%s'", volPoolName)
}
defer pool.Free()

client.poolMutexKV.Lock(volPoolName)
defer client.poolMutexKV.Unlock(volPoolName)

// Refresh the pool of the volume so that libvirt knows it is
// not longer in use.
waitForSuccess("Error refreshing pool for volume", func() error {
return pool.Refresh(0)
})

err = ci.setCloudInitDiskNameFromExistingVol(volume)
if err != nil {
return ci, err
Expand All @@ -214,7 +242,9 @@ func newCloudInitDefFromRemoteISO(virConn *libvirt.Connect, id string) (defCloud
if err != nil {
return ci, err
}

// this function has stream.recv and volume/streams which are subject to race conditions.
// namely stream.recv can wait forever (IO.block) if for any reason it doesn't get right data to read
// https://libvirt.org/html/libvirt-libvirt-stream.html#virStreamRecv
isoFile, err := downloadISO(virConn, *volume)
if isoFile != nil {
defer os.Remove(isoFile.Name())
Expand Down
3 changes: 2 additions & 1 deletion libvirt/resource_libvirt_cloud_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ func resourceCloudInitDiskCreate(d *schema.ResourceData, meta interface{}) error

func resourceCloudInitDiskRead(d *schema.ResourceData, meta interface{}) error {
virConn := meta.(*Client).libvirt
client := meta.(*Client)
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
}

ci, err := newCloudInitDefFromRemoteISO(virConn, d.Id())
ci, err := newCloudInitDefFromRemoteISO(virConn, d.Id(), client)
if err != nil {
return fmt.Errorf("error while retrieving remote ISO: %s", err)
}
Expand Down
4 changes: 2 additions & 2 deletions libvirt/resource_libvirt_cloud_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ type Expected struct {
func (expected *Expected) testAccCheckCloudInitDiskFilesContent(volumeName string, volume *libvirt.StorageVol) resource.TestCheckFunc {
return func(state *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt

client := testAccProvider.Meta().(*Client)
rs, err := getResourceFromTerraformState(volumeName, state)
if err != nil {
return err
}

cloudInitDiskDef, err := newCloudInitDefFromRemoteISO(virConn, rs.Primary.ID)
cloudInitDiskDef, err := newCloudInitDefFromRemoteISO(virConn, rs.Primary.ID, client)

if cloudInitDiskDef.MetaData != expected.MetaData {
return fmt.Errorf("metadata '%s' content differs from expected Metadata %s", cloudInitDiskDef.MetaData, expected.MetaData)
Expand Down
5 changes: 0 additions & 5 deletions libvirt/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,3 @@ func (sio *StreamIO) Read(p []byte) (int, error) {
func (sio *StreamIO) Write(p []byte) (int, error) {
return sio.Stream.Send(p)
}

// Close closes the stream
func (sio *StreamIO) Close() error {
return sio.Stream.Finish()
}

0 comments on commit a354053

Please sign in to comment.