github.com/raghuse92/packer@v1.3.2/builder/qemu/step_convert_disk.go (about) 1 package qemu 2 3 import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 "strings" 8 9 "github.com/hashicorp/packer/common" 10 "github.com/hashicorp/packer/helper/multistep" 11 "github.com/hashicorp/packer/packer" 12 13 "os" 14 ) 15 16 // This step converts the virtual disk that was used as the 17 // hard drive for the virtual machine. 18 type stepConvertDisk struct{} 19 20 func (s *stepConvertDisk) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 21 config := state.Get("config").(*Config) 22 driver := state.Get("driver").(Driver) 23 diskName := state.Get("disk_filename").(string) 24 ui := state.Get("ui").(packer.Ui) 25 26 if config.SkipCompaction && !config.DiskCompression { 27 return multistep.ActionContinue 28 } 29 30 name := diskName + ".convert" 31 32 sourcePath := filepath.Join(config.OutputDir, diskName) 33 targetPath := filepath.Join(config.OutputDir, name) 34 35 command := []string{ 36 "convert", 37 } 38 39 if config.DiskCompression { 40 command = append(command, "-c") 41 } 42 43 command = append(command, []string{ 44 "-O", config.Format, 45 sourcePath, 46 targetPath, 47 }..., 48 ) 49 50 ui.Say("Converting hard drive...") 51 // Retry the conversion a few times in case it takes the qemu process a 52 // moment to release the lock 53 err := common.Retry(1, 10, 10, func(_ uint) (bool, error) { 54 if err := driver.QemuImg(command...); err != nil { 55 if strings.Contains(err.Error(), `Failed to get shared "write" lock`) { 56 ui.Say("Error getting file lock for conversion; retrying...") 57 return false, nil 58 } 59 err = fmt.Errorf("Error converting hard drive: %s", err) 60 return true, err 61 } 62 return true, nil 63 }) 64 65 if err != nil { 66 if err == common.RetryExhaustedError { 67 err = fmt.Errorf("Exhausted retries for getting file lock: %s", err) 68 state.Put("error", err) 69 ui.Error(err.Error()) 70 return multistep.ActionHalt 71 } else { 72 err := fmt.Errorf("Error converting hard drive: %s", err) 73 state.Put("error", err) 74 ui.Error(err.Error()) 75 return multistep.ActionHalt 76 } 77 } 78 79 if err := os.Rename(targetPath, sourcePath); err != nil { 80 err := fmt.Errorf("Error moving converted hard drive: %s", err) 81 state.Put("error", err) 82 ui.Error(err.Error()) 83 return multistep.ActionHalt 84 } 85 86 return multistep.ActionContinue 87 } 88 89 func (s *stepConvertDisk) Cleanup(state multistep.StateBag) {}